summaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/Kconfig2
-rw-r--r--drivers/input/Makefile2
-rw-r--r--drivers/input/input.c10
-rw-r--r--drivers/input/keyboard/gpio_keys.c169
-rw-r--r--drivers/input/misc/Kconfig32
-rw-r--r--drivers/input/misc/Makefile4
-rw-r--r--drivers/input/misc/hbtp_input.c1625
-rw-r--r--drivers/input/misc/hbtp_vm.c293
-rw-r--r--drivers/input/misc/ots_pat9125/Kconfig14
-rw-r--r--drivers/input/misc/ots_pat9125/Makefile7
-rw-r--r--drivers/input/misc/ots_pat9125/pat9125_linux_driver.c627
-rw-r--r--drivers/input/misc/ots_pat9125/pixart_ots.c78
-rw-r--r--drivers/input/misc/ots_pat9125/pixart_ots.h58
-rw-r--r--drivers/input/misc/ots_pat9125/pixart_platform.h17
-rw-r--r--drivers/input/misc/qpnp-power-on.c2413
-rw-r--r--drivers/input/misc/vl53L0/Makefile20
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l010_api.h1476
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l010_device.h237
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l010_strings.h134
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l010_tuning.h58
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_api.h1950
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_api_calibration.h85
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_api_core.h108
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_api_histogram.h70
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_api_ranging.h47
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_api_strings.h277
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_def.h663
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_device.h261
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_i2c_platform.h402
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_interrupt_threshold_settings.h194
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_platform.h231
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_platform_log.h128
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_tuning.h146
-rw-r--r--drivers/input/misc/vl53L0/inc/vl53l0_types.h69
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l010_api.c4175
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l010_tuning.c138
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l0_api.c3109
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l0_api_calibration.c1284
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l0_api_core.c2270
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l0_api_histogram.c750
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l0_api_ranging.c42
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l0_api_strings.c463
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l0_i2c_platform.c383
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l0_platform.c242
-rw-r--r--drivers/input/misc/vl53L0/src/vl53l0_port_i2c.c155
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0-cci.h62
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0-i2c.h35
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0.h219
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0_module-cci.c547
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0_module-i2c.c266
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0_module.c2885
-rw-r--r--drivers/input/sensors/bmi160/Kconfig121
-rw-r--r--drivers/input/sensors/bmi160/Makefile41
-rw-r--r--drivers/input/sensors/bmi160/bmi160.c18753
-rw-r--r--drivers/input/sensors/bmi160/bmi160.h11814
-rw-r--r--drivers/input/sensors/bmi160/bmi160_driver.c4022
-rw-r--r--drivers/input/sensors/bmi160/bmi160_driver.h409
-rw-r--r--drivers/input/sensors/bmi160/bmi160_i2c.c411
-rw-r--r--drivers/input/sensors/bmi160/bmi160_spi.c299
-rw-r--r--drivers/input/sensors/bmi160/bs_log.c50
-rw-r--r--drivers/input/sensors/bmi160/bs_log.h171
-rw-r--r--drivers/input/sensors/bmi160/bstclass.c238
-rw-r--r--drivers/input/sensors/bmi160/bstclass.h78
-rw-r--r--drivers/input/sensors/smi130/Kconfig121
-rw-r--r--drivers/input/sensors/smi130/Makefile47
-rw-r--r--drivers/input/sensors/smi130/boschclass.c341
-rw-r--r--drivers/input/sensors/smi130/boschclass.h181
-rw-r--r--drivers/input/sensors/smi130/bs_log.c153
-rw-r--r--drivers/input/sensors/smi130/bs_log.h274
-rw-r--r--drivers/input/sensors/smi130/modules.order0
-rw-r--r--drivers/input/sensors/smi130/readme.md49
-rw-r--r--drivers/input/sensors/smi130/smi130.c18785
-rw-r--r--drivers/input/sensors/smi130/smi130.h11851
-rw-r--r--drivers/input/sensors/smi130/smi130_acc.c7507
-rw-r--r--drivers/input/sensors/smi130/smi130_driver.c4121
-rw-r--r--drivers/input/sensors/smi130/smi130_driver.h512
-rw-r--r--drivers/input/sensors/smi130/smi130_gyro.c7422
-rw-r--r--drivers/input/sensors/smi130/smi130_gyro.h4705
-rw-r--r--drivers/input/sensors/smi130/smi130_gyro_driver.c2036
-rw-r--r--drivers/input/sensors/smi130/smi130_i2c.c472
-rw-r--r--drivers/input/sensors/smi130/smi130_spi.c402
-rw-r--r--drivers/input/touchscreen/Kconfig121
-rw-r--r--drivers/input/touchscreen/Makefile7
-rw-r--r--drivers/input/touchscreen/atmel_maxtouch_ts.c4215
-rw-r--r--drivers/input/touchscreen/ft5x06_ts.c2781
-rw-r--r--drivers/input/touchscreen/gen_vkeys.c230
-rw-r--r--drivers/input/touchscreen/it7258_ts_i2c.c2248
-rw-r--r--drivers/input/touchscreen/maxim_sti.c2842
-rw-r--r--drivers/input/touchscreen/st/Kconfig9
-rw-r--r--drivers/input/touchscreen/st/Makefile5
-rw-r--r--drivers/input/touchscreen/st/fts.c2385
-rw-r--r--drivers/input/touchscreen/st/fts.h249
-rw-r--r--drivers/input/touchscreen/st/fts_driver_test.c871
-rw-r--r--drivers/input/touchscreen/st/fts_fw.h10
-rw-r--r--drivers/input/touchscreen/st/fts_gui.c359
-rw-r--r--drivers/input/touchscreen/st/fts_lib/Makefile7
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsCompensation.c591
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsCompensation.h146
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsCrossCompile.c43
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsCrossCompile.h34
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsError.c105
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsError.h75
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsFlash.c1071
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsFlash.h79
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsFrame.c569
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsFrame.h49
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsGesture.c393
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsGesture.h74
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsHardware.h177
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsIO.c403
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsIO.h35
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsSoftware.h131
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsTest.c2324
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsTest.h158
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsTime.c84
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsTime.h29
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsTool.c706
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsTool.h64
-rw-r--r--drivers/input/touchscreen/st/fts_limits.h10
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/Kconfig64
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/Makefile10
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c4506
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h405
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c2163
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c530
-rwxr-xr-xdrivers/input/touchscreen/synaptics_dsx/synaptics_dsx_spi.c335
126 files changed, 156009 insertions, 11 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 2557dcda7621..5987a6c2261b 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -214,6 +214,8 @@ source "drivers/input/touchscreen/Kconfig"
source "drivers/input/misc/Kconfig"
+source "drivers/input/sensors/bmi160/Kconfig"
+
endif
menu "Hardware I/O ports"
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 2a6d05ab9170..45286b8e4769 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -28,4 +28,4 @@ obj-$(CONFIG_INPUT_MISC) += misc/
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
obj-$(CONFIG_INPUT_KEYRESET) += keyreset.o
obj-$(CONFIG_INPUT_KEYCOMBO) += keycombo.o
-
+obj-y += sensors/bmi160/
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 880605959aa6..baaddd168804 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1667,8 +1667,14 @@ void input_reset_device(struct input_dev *dev)
mutex_lock(&dev->mutex);
spin_lock_irqsave(&dev->event_lock, flags);
- input_dev_toggle(dev, true);
- input_dev_release_keys(dev);
+ /*
+ * Keys that have been pressed at suspend time are unlikely
+ * to be still pressed when we resume.
+ */
+ if (!test_bit(INPUT_PROP_NO_DUMMY_RELEASE, dev->propbit)) {
+ input_dev_toggle(dev, true);
+ input_dev_release_keys(dev);
+ }
spin_unlock_irqrestore(&dev->event_lock, flags);
mutex_unlock(&dev->mutex);
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index bef317ff7352..c93dd193a496 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -3,6 +3,7 @@
*
* Copyright 2005 Phil Blundell
* Copyright 2010, 2011 David Jander <david@protonic.nl>
+ * Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -31,6 +32,8 @@
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/syscore_ops.h>
struct gpio_button_data {
const struct gpio_keys_button *button;
@@ -50,11 +53,17 @@ struct gpio_button_data {
struct gpio_keys_drvdata {
const struct gpio_keys_platform_data *pdata;
+ struct pinctrl *key_pinctrl;
struct input_dev *input;
struct mutex disable_lock;
struct gpio_button_data data[0];
};
+static struct device *global_dev;
+static struct syscore_ops gpio_keys_syscore_pm_ops;
+
+static void gpio_keys_syscore_resume(void);
+
/*
* SYSFS interface for enabling/disabling keys and switches:
*
@@ -341,14 +350,14 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
const struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY;
- int state = gpio_get_value_cansleep(button->gpio);
+ int state;
+ state = (__gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
if (state < 0) {
dev_err(input->dev.parent, "failed to get gpio state\n");
return;
}
- state = (state ? 1 : 0) ^ button->active_low;
if (type == EV_ABS) {
if (state)
input_event(input, type, button->code, button->value);
@@ -564,6 +573,41 @@ static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata)
input_sync(input);
}
+static int gpio_keys_pinctrl_configure(struct gpio_keys_drvdata *ddata,
+ bool active)
+{
+ struct pinctrl_state *set_state;
+ int retval;
+
+ if (active) {
+ set_state =
+ pinctrl_lookup_state(ddata->key_pinctrl,
+ "tlmm_gpio_key_active");
+ if (IS_ERR(set_state)) {
+ dev_err(&ddata->input->dev,
+ "cannot get ts pinctrl active state\n");
+ return PTR_ERR(set_state);
+ }
+ } else {
+ set_state =
+ pinctrl_lookup_state(ddata->key_pinctrl,
+ "tlmm_gpio_key_suspend");
+ if (IS_ERR(set_state)) {
+ dev_err(&ddata->input->dev,
+ "cannot get gpiokey pinctrl sleep state\n");
+ return PTR_ERR(set_state);
+ }
+ }
+ retval = pinctrl_select_state(ddata->key_pinctrl, set_state);
+ if (retval) {
+ dev_err(&ddata->input->dev,
+ "cannot set ts pinctrl active state\n");
+ return retval;
+ }
+
+ return 0;
+}
+
static int gpio_keys_open(struct input_dev *input)
{
struct gpio_keys_drvdata *ddata = input_get_drvdata(input);
@@ -627,6 +671,8 @@ gpio_keys_get_devtree_pdata(struct device *dev)
pdata->nbuttons = nbuttons;
pdata->rep = !!of_get_property(node, "autorepeat", NULL);
+ pdata->name = of_get_property(node, "input-name", NULL);
+ pdata->use_syscore = of_property_read_bool(node, "use-syscore");
i = 0;
for_each_child_of_node(node, pp) {
@@ -673,7 +719,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL);
if (of_property_read_u32(pp, "debounce-interval",
- &button->debounce_interval))
+ &button->debounce_interval))
button->debounce_interval = 5;
}
@@ -708,6 +754,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
size_t size;
int i, error;
int wakeup = 0;
+ struct pinctrl_state *set_state;
if (!pdata) {
pdata = gpio_keys_get_devtree_pdata(dev);
@@ -729,6 +776,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ global_dev = dev;
ddata->pdata = pdata;
ddata->input = input;
mutex_init(&ddata->disable_lock);
@@ -736,7 +784,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ddata);
input_set_drvdata(input, ddata);
- input->name = pdata->name ? : pdev->name;
+ input->name = GPIO_KEYS_DEV_NAME;
input->phys = "gpio-keys/input0";
input->dev.parent = &pdev->dev;
input->open = gpio_keys_open;
@@ -751,13 +799,31 @@ static int gpio_keys_probe(struct platform_device *pdev)
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
+ /* Get pinctrl if target uses pinctrl */
+ ddata->key_pinctrl = devm_pinctrl_get(dev);
+ if (IS_ERR(ddata->key_pinctrl)) {
+ if (PTR_ERR(ddata->key_pinctrl) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ pr_debug("Target does not use pinctrl\n");
+ ddata->key_pinctrl = NULL;
+ }
+
+ if (ddata->key_pinctrl) {
+ error = gpio_keys_pinctrl_configure(ddata, true);
+ if (error) {
+ dev_err(dev, "cannot set ts pinctrl active state\n");
+ return error;
+ }
+ }
+
for (i = 0; i < pdata->nbuttons; i++) {
const struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_button_data *bdata = &ddata->data[i];
error = gpio_keys_setup_key(pdev, input, bdata, button);
if (error)
- return error;
+ goto err_setup_key;
if (button->wakeup)
wakeup = 1;
@@ -767,7 +833,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
if (error) {
dev_err(dev, "Unable to export keys/switches, error: %d\n",
error);
- return error;
+ goto err_create_sysfs;
}
error = input_register_device(input);
@@ -779,16 +845,34 @@ static int gpio_keys_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, wakeup);
+ if (pdata->use_syscore)
+ gpio_keys_syscore_pm_ops.resume = gpio_keys_syscore_resume;
+
+ register_syscore_ops(&gpio_keys_syscore_pm_ops);
+
return 0;
err_remove_group:
sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
+err_create_sysfs:
+err_setup_key:
+ if (ddata->key_pinctrl) {
+ set_state =
+ pinctrl_lookup_state(ddata->key_pinctrl,
+ "tlmm_gpio_key_suspend");
+ if (IS_ERR(set_state))
+ dev_err(dev, "cannot get gpiokey pinctrl sleep state\n");
+ else
+ pinctrl_select_state(ddata->key_pinctrl, set_state);
+ }
+
return error;
}
static int gpio_keys_remove(struct platform_device *pdev)
{
sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
+ unregister_syscore_ops(&gpio_keys_syscore_pm_ops);
device_init_wakeup(&pdev->dev, 0);
@@ -796,11 +880,54 @@ static int gpio_keys_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM_SLEEP
+static void gpio_keys_syscore_resume(void)
+{
+ struct gpio_keys_drvdata *ddata = dev_get_drvdata(global_dev);
+ struct input_dev *input = ddata->input;
+ struct gpio_button_data *bdata = NULL;
+ int error = 0;
+ int i;
+
+ if (ddata->key_pinctrl) {
+ error = gpio_keys_pinctrl_configure(ddata, true);
+ if (error) {
+ dev_err(global_dev, "failed to put the pin in resume state\n");
+ return;
+ }
+ }
+
+ if (device_may_wakeup(global_dev)) {
+ for (i = 0; i < ddata->pdata->nbuttons; i++) {
+ bdata = &ddata->data[i];
+ if (bdata->button->wakeup)
+ disable_irq_wake(bdata->irq);
+ }
+ } else {
+ mutex_lock(&input->mutex);
+ if (input->users)
+ error = gpio_keys_open(input);
+ mutex_unlock(&input->mutex);
+ }
+
+ if (error)
+ return;
+
+ gpio_keys_report_state(ddata);
+}
+
static int gpio_keys_suspend(struct device *dev)
{
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct input_dev *input = ddata->input;
- int i;
+ int i, ret;
+
+ if (ddata->key_pinctrl) {
+ ret = gpio_keys_pinctrl_configure(ddata, false);
+ if (ret) {
+ dev_err(dev, "failed to put the pin in suspend state\n");
+ return ret;
+ }
+ }
if (device_may_wakeup(dev)) {
for (i = 0; i < ddata->pdata->nbuttons; i++) {
@@ -825,6 +952,19 @@ static int gpio_keys_resume(struct device *dev)
int error = 0;
int i;
+ if (ddata->pdata->use_syscore == true) {
+ dev_dbg(global_dev, "Using syscore resume, no need of this resume.\n");
+ return 0;
+ }
+
+ if (ddata->key_pinctrl) {
+ error = gpio_keys_pinctrl_configure(ddata, true);
+ if (error) {
+ dev_err(dev, "failed to put the pin in resume state\n");
+ return error;
+ }
+ }
+
if (device_may_wakeup(dev)) {
for (i = 0; i < ddata->pdata->nbuttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
@@ -844,6 +984,21 @@ static int gpio_keys_resume(struct device *dev)
gpio_keys_report_state(ddata);
return 0;
}
+
+#else
+
+static void gpio_keys_syscore_resume(void){}
+
+static int gpio_keys_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int gpio_keys_resume(struct device *dev)
+{
+ return 0;
+}
+
#endif
static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 25ac47b9a180..dd98d8c8fd1f 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -103,6 +103,17 @@ config INPUT_E3X0_BUTTON
To compile this driver as a module, choose M here: the
module will be called e3x0_button.
+config INPUT_HBTP_INPUT
+ tristate "HBTP input driver support"
+ help
+ This option enables an input driver for the host based touch
+ processing.
+
+ Say Y to enable HBTP input driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hbtp_input.
+
config INPUT_PCSPKR
tristate "PC Speaker support"
depends on PCSPKR_PLATFORM
@@ -150,6 +161,15 @@ config INPUT_PMIC8XXX_PWRKEY
To compile this driver as a module, choose M here: the
module will be called pmic8xxx-pwrkey.
+config INPUT_QPNP_POWER_ON
+ tristate "QPNP PMIC Power-on support"
+ depends on SPMI
+ help
+ This option enables device driver support for the power-on
+ functionality of Qualcomm Technologies, Inc. PNP PMICs. It supports
+ reporting the change in status of the KPDPWR_N line (connected to the
+ power-key) as well as reset features.
+
config INPUT_SPARCSPKR
tristate "SPARC Speaker support"
depends on PCI && SPARC64
@@ -812,4 +832,16 @@ config INPUT_DRV2667_HAPTICS
To compile this driver as a module, choose M here: the
module will be called drv2667-haptics.
+source "drivers/input/misc/ots_pat9125/Kconfig"
+
+config INPUT_STMVL53L0
+ tristate "STM VL53L0 Proximity support"
+ depends on INPUT && I2C
+ help
+ Say Y here if you want to use STMicroelectronics's proximity sensor
+ through I2C interface.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stmvl53l0.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 66c3cc9f181c..44c026abcb6f 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o
obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o
obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o
obj-$(CONFIG_INPUT_GPIO) += gpio_event.o gpio_matrix.o gpio_input.o gpio_output.o gpio_axis.o
+obj-$(CONFIG_INPUT_HBTP_INPUT) += hbtp_input.o hbtp_vm.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o
obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
@@ -56,6 +57,7 @@ obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_PM8941_PWRKEY) += pm8941-pwrkey.o
obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
+obj-$(CONFIG_INPUT_QPNP_POWER_ON) += qpnp-power-on.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
@@ -77,3 +79,5 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
+obj-$(CONFIG_INPUT_PIXART_OTS_PAT9125_SWITCH) += ots_pat9125/
+obj-$(CONFIG_INPUT_STMVL53L0) += vl53L0/
diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c
new file mode 100644
index 000000000000..ca6286a36604
--- /dev/null
+++ b/drivers/input/misc/hbtp_input.c
@@ -0,0 +1,1625 @@
+
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/input/mt.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <uapi/linux/hbtp_input.h>
+#include "../input-compat.h"
+#include <linux/ktime.h>
+#include <linux/uaccess.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#endif
+
+#define HBTP_INPUT_NAME "hbtp_input"
+#define DISP_COORDS_SIZE 2
+
+#define HBTP_PINCTRL_VALID_STATE_CNT (2)
+#define HBTP_HOLD_DURATION_US (10)
+#define HBTP_PINCTRL_DDIC_SEQ_NUM (4)
+
+struct hbtp_data {
+ struct platform_device *pdev;
+ struct input_dev *input_dev;
+ s32 count;
+ struct mutex mutex;
+ struct mutex sensormutex;
+ struct hbtp_sensor_data *sensor_data;
+ bool touch_status[HBTP_MAX_FINGER];
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#endif
+ struct pinctrl *ts_pinctrl;
+ struct pinctrl_state *gpio_state_active;
+ struct pinctrl_state *gpio_state_suspend;
+ bool ddic_rst_enabled;
+ struct pinctrl_state *ddic_rst_state_active;
+ struct pinctrl_state *ddic_rst_state_suspend;
+ u32 ts_pinctrl_seq_delay;
+ u32 ddic_pinctrl_seq_delay[HBTP_PINCTRL_DDIC_SEQ_NUM];
+ u32 fb_resume_seq_delay;
+ int lcd_state;
+ bool power_suspended;
+ bool power_sync_enabled;
+ bool power_sig_enabled;
+ struct completion power_resume_sig;
+ struct completion power_suspend_sig;
+ struct regulator *vcc_ana;
+ struct regulator *vcc_dig;
+ int afe_load_ua;
+ int afe_vtg_min_uv;
+ int afe_vtg_max_uv;
+ int dig_load_ua;
+ int dig_vtg_min_uv;
+ int dig_vtg_max_uv;
+ int disp_maxx; /* Display Max X */
+ int disp_maxy; /* Display Max Y */
+ int def_maxx; /* Default Max X */
+ int def_maxy; /* Default Max Y */
+ int des_maxx; /* Desired Max X */
+ int des_maxy; /* Desired Max Y */
+ bool use_scaling;
+ bool override_disp_coords;
+ bool manage_afe_power_ana;
+ bool manage_power_dig;
+ u32 power_on_delay;
+ u32 power_off_delay;
+ bool manage_pin_ctrl;
+ bool init_completion_done_once;
+ s16 ROI[MAX_ROI_SIZE];
+ s16 accelBuffer[MAX_ACCEL_SIZE];
+};
+
+static struct hbtp_data *hbtp;
+
+static struct kobject *sensor_kobject;
+
+#if defined(CONFIG_FB)
+static int hbtp_fb_early_suspend(struct hbtp_data *ts);
+static int hbtp_fb_suspend(struct hbtp_data *ts);
+static int hbtp_fb_early_resume(struct hbtp_data *ts);
+static int hbtp_fb_revert_resume(struct hbtp_data *ts);
+#endif
+
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ int blank;
+ int lcd_state;
+ struct fb_event *evdata = data;
+ struct fb_info *fbi = NULL;
+ struct hbtp_data *hbtp_data =
+ container_of(self, struct hbtp_data, fb_notif);
+
+ if (!evdata) {
+ pr_debug("evdata is NULL");
+ return 0;
+ }
+ fbi = evdata->info;
+
+ /*
+ * Node 0 is the primary display and others are
+ * external displays such as HDMI/DP.
+ * We need to handle only fb event for the primary display.
+ */
+ if (!fbi || fbi->node != 0) {
+ pr_debug("%s: no need to handle the fb event", __func__);
+ return 0;
+ }
+
+ if (evdata->data && hbtp_data &&
+ (event == FB_EARLY_EVENT_BLANK ||
+ event == FB_R_EARLY_EVENT_BLANK)) {
+ blank = *(int *)(evdata->data);
+ lcd_state = hbtp->lcd_state;
+ if (event == FB_EARLY_EVENT_BLANK) {
+ if (blank <= FB_BLANK_NORMAL &&
+ lcd_state == FB_BLANK_POWERDOWN) {
+ pr_debug("%s: receives EARLY_BLANK:UNBLANK\n",
+ __func__);
+ hbtp_fb_early_resume(hbtp_data);
+ } else if (blank == FB_BLANK_POWERDOWN &&
+ lcd_state <= FB_BLANK_NORMAL) {
+ pr_debug("%s: receives EARLY_BLANK:POWERDOWN\n",
+ __func__);
+ hbtp_fb_early_suspend(hbtp_data);
+ } else {
+ pr_debug("%s: receives EARLY_BLANK:%d in %d state\n",
+ __func__, blank, lcd_state);
+ }
+ } else if (event == FB_R_EARLY_EVENT_BLANK) {
+ if (blank <= FB_BLANK_NORMAL) {
+ pr_debug("%s: receives R_EARLY_BALNK:UNBLANK\n",
+ __func__);
+ hbtp_fb_early_suspend(hbtp_data);
+ hbtp_fb_suspend(hbtp_data);
+ } else if (blank == FB_BLANK_POWERDOWN) {
+ pr_debug("%s: receives R_EARLY_BALNK:POWERDOWN\n",
+ __func__);
+ hbtp_fb_revert_resume(hbtp_data);
+ } else {
+ pr_debug("%s: receives R_EARLY_BALNK:%d in %d state\n",
+ __func__, blank, lcd_state);
+ }
+ }
+ }
+
+ if (evdata->data && hbtp_data &&
+ event == FB_EVENT_BLANK) {
+ blank = *(int *)(evdata->data);
+ lcd_state = hbtp->lcd_state;
+ if (blank == FB_BLANK_POWERDOWN &&
+ lcd_state <= FB_BLANK_NORMAL) {
+ pr_debug("%s: receives BLANK:POWERDOWN\n", __func__);
+ hbtp_fb_suspend(hbtp_data);
+ } else if (blank <= FB_BLANK_NORMAL &&
+ lcd_state == FB_BLANK_POWERDOWN) {
+ pr_debug("%s: receives BLANK:UNBLANK\n", __func__);
+ } else {
+ pr_debug("%s: receives BLANK:%d in %d state\n",
+ __func__, blank, lcd_state);
+ }
+ hbtp_data->lcd_state = blank;
+ }
+ return 0;
+}
+#endif
+
+static ssize_t hbtp_sensor_roi_show(struct file *dev, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t pos,
+ size_t size) {
+ mutex_lock(&hbtp->sensormutex);
+ memcpy(buf, hbtp->ROI, size);
+ mutex_unlock(&hbtp->sensormutex);
+
+ return size;
+}
+
+static ssize_t hbtp_sensor_vib_show(struct file *dev, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t pos,
+ size_t size) {
+ mutex_lock(&hbtp->sensormutex);
+ memcpy(buf, hbtp->accelBuffer, size);
+ mutex_unlock(&hbtp->sensormutex);
+
+ return size;
+}
+
+static struct bin_attribute capdata_attr = {
+ .attr = {
+ .name = "capdata",
+ .mode = S_IRUGO,
+ },
+ .size = 1024,
+ .read = hbtp_sensor_roi_show,
+ .write = NULL,
+};
+
+static struct bin_attribute vibdata_attr = {
+ .attr = {
+ .name = "vib_data",
+ .mode = S_IRUGO,
+ },
+ .size = MAX_ACCEL_SIZE*sizeof(int16_t),
+ .read = hbtp_sensor_vib_show,
+ .write = NULL,
+};
+
+static int hbtp_input_open(struct inode *inode, struct file *file)
+{
+ mutex_lock(&hbtp->mutex);
+ if (hbtp->count) {
+ pr_err("%s is busy\n", HBTP_INPUT_NAME);
+ mutex_unlock(&hbtp->mutex);
+ return -EBUSY;
+ }
+ hbtp->count++;
+ mutex_unlock(&hbtp->mutex);
+
+ return 0;
+}
+
+static int hbtp_input_release(struct inode *inode, struct file *file)
+{
+ mutex_lock(&hbtp->mutex);
+ if (!hbtp->count) {
+ pr_err("%s wasn't opened\n", HBTP_INPUT_NAME);
+ mutex_unlock(&hbtp->mutex);
+ return -ENOTTY;
+ }
+ hbtp->count--;
+ if (hbtp->power_sig_enabled)
+ hbtp->power_sig_enabled = false;
+ mutex_unlock(&hbtp->mutex);
+
+ return 0;
+}
+
+static int hbtp_input_create_input_dev(struct hbtp_input_absinfo *absinfo)
+{
+ struct input_dev *input_dev;
+ struct hbtp_input_absinfo *abs;
+ int error;
+ int i;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ pr_err("%s: input_allocate_device failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ kfree(input_dev->name);
+ input_dev->name = kstrndup(HBTP_INPUT_NAME, sizeof(HBTP_INPUT_NAME),
+ GFP_KERNEL);
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ for (i = KEY_HOME; i <= KEY_MICMUTE; i++)
+ __set_bit(i, input_dev->keybit);
+
+ /* For multi touch */
+ input_mt_init_slots(input_dev, HBTP_MAX_FINGER, 0);
+ for (i = 0; i <= ABS_MT_LAST - ABS_MT_FIRST; i++) {
+ abs = absinfo + i;
+ if (abs->active) {
+ if (abs->code >= 0 && abs->code < ABS_CNT)
+ input_set_abs_params(input_dev, abs->code,
+ abs->minimum, abs->maximum, 0, 0);
+ else
+ pr_err("%s: ABS code out of bound\n", __func__);
+ }
+ }
+
+ if (hbtp->override_disp_coords) {
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, hbtp->disp_maxx, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, hbtp->disp_maxy, 0, 0);
+ }
+
+ error = input_register_device(input_dev);
+ if (error) {
+ pr_err("%s: input_register_device failed\n", __func__);
+ goto err_input_reg_dev;
+ }
+
+ hbtp->input_dev = input_dev;
+ return 0;
+
+err_input_reg_dev:
+ input_free_device(input_dev);
+
+ return error;
+}
+
+static int hbtp_input_report_events(struct hbtp_data *hbtp_data,
+ struct hbtp_input_mt *mt_data)
+{
+ int i;
+ struct hbtp_input_touch *tch;
+
+ for (i = 0; i < HBTP_MAX_FINGER; i++) {
+ tch = &(mt_data->touches[i]);
+ if (tch->active || hbtp_data->touch_status[i]) {
+ input_mt_slot(hbtp_data->input_dev, i);
+ input_mt_report_slot_state(hbtp_data->input_dev,
+ MT_TOOL_FINGER, tch->active);
+
+ if (tch->active) {
+ input_report_abs(hbtp_data->input_dev,
+ ABS_MT_TOOL_TYPE,
+ tch->tool);
+ input_report_abs(hbtp_data->input_dev,
+ ABS_MT_TOUCH_MAJOR,
+ tch->major);
+ input_report_abs(hbtp_data->input_dev,
+ ABS_MT_TOUCH_MINOR,
+ tch->minor);
+ input_report_abs(hbtp_data->input_dev,
+ ABS_MT_ORIENTATION,
+ tch->orientation);
+ input_report_abs(hbtp_data->input_dev,
+ ABS_MT_PRESSURE,
+ tch->pressure);
+ /*
+ * Scale up/down the X-coordinate as per
+ * DT property
+ */
+ if (hbtp_data->use_scaling &&
+ hbtp_data->def_maxx > 0 &&
+ hbtp_data->des_maxx > 0)
+ tch->x = (tch->x * hbtp_data->des_maxx)
+ / hbtp_data->def_maxx;
+
+ input_report_abs(hbtp_data->input_dev,
+ ABS_MT_POSITION_X,
+ tch->x);
+ /*
+ * Scale up/down the Y-coordinate as per
+ * DT property
+ */
+ if (hbtp_data->use_scaling &&
+ hbtp_data->def_maxy > 0 &&
+ hbtp_data->des_maxy > 0)
+ tch->y = (tch->y * hbtp_data->des_maxy)
+ / hbtp_data->def_maxy;
+
+ input_report_abs(hbtp_data->input_dev,
+ ABS_MT_POSITION_Y,
+ tch->y);
+ }
+ hbtp_data->touch_status[i] = tch->active;
+ }
+ }
+
+ input_report_key(hbtp->input_dev, BTN_TOUCH, mt_data->num_touches > 0);
+ input_sync(hbtp->input_dev);
+
+ return 0;
+}
+
+static int reg_set_load_check(struct regulator *reg, int load_uA)
+{
+ return (regulator_count_voltages(reg) > 0) ?
+ regulator_set_load(reg, load_uA) : 0;
+}
+
+static int hbtp_pdev_power_on(struct hbtp_data *hbtp, bool on)
+{
+ int ret;
+
+ if (!hbtp->vcc_ana)
+ pr_err("%s: analog regulator is not available\n", __func__);
+
+ if (!hbtp->vcc_dig)
+ pr_err("%s: digital regulator is not available\n", __func__);
+
+ if (!hbtp->vcc_ana && !hbtp->vcc_dig) {
+ pr_err("%s: no regulators available\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!on)
+ goto reg_off;
+
+ if (hbtp->vcc_ana) {
+ ret = reg_set_load_check(hbtp->vcc_ana,
+ hbtp->afe_load_ua);
+ if (ret < 0) {
+ pr_err("%s: Regulator vcc_ana set_opt failed rc=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = regulator_enable(hbtp->vcc_ana);
+ if (ret) {
+ pr_err("%s: Regulator vcc_ana enable failed rc=%d\n",
+ __func__, ret);
+ reg_set_load_check(hbtp->vcc_ana, 0);
+ return ret;
+ }
+ }
+
+ if (hbtp->power_on_delay) {
+ pr_debug("%s: power-on-delay = %u\n", __func__,
+ hbtp->power_on_delay);
+ usleep_range(hbtp->power_on_delay,
+ hbtp->power_on_delay + HBTP_HOLD_DURATION_US);
+ }
+
+ if (hbtp->vcc_dig) {
+ ret = reg_set_load_check(hbtp->vcc_dig,
+ hbtp->dig_load_ua);
+ if (ret < 0) {
+ pr_err("%s: Regulator vcc_dig set_opt failed rc=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = regulator_enable(hbtp->vcc_dig);
+ if (ret) {
+ pr_err("%s: Regulator vcc_dig enable failed rc=%d\n",
+ __func__, ret);
+ reg_set_load_check(hbtp->vcc_dig, 0);
+ return ret;
+ }
+ }
+
+ return 0;
+
+reg_off:
+ if (hbtp->vcc_dig) {
+ reg_set_load_check(hbtp->vcc_dig, 0);
+ regulator_disable(hbtp->vcc_dig);
+ }
+
+ if (hbtp->power_off_delay) {
+ pr_debug("%s: power-off-delay = %u\n", __func__,
+ hbtp->power_off_delay);
+ usleep_range(hbtp->power_off_delay,
+ hbtp->power_off_delay + HBTP_HOLD_DURATION_US);
+ }
+
+ if (hbtp->vcc_ana) {
+ reg_set_load_check(hbtp->vcc_ana, 0);
+ regulator_disable(hbtp->vcc_ana);
+ }
+ return 0;
+}
+
+static int hbtp_gpio_select(struct hbtp_data *data, bool on)
+{
+ struct pinctrl_state *pins_state;
+ int ret = 0;
+
+ pins_state = on ? data->gpio_state_active : data->gpio_state_suspend;
+ if (!IS_ERR_OR_NULL(pins_state)) {
+ ret = pinctrl_select_state(data->ts_pinctrl, pins_state);
+ if (ret) {
+ dev_err(&data->pdev->dev,
+ "can not set %s pins\n",
+ on ? "ts_active" : "ts_suspend");
+ return ret;
+ }
+
+ if (on) {
+ if (data->ts_pinctrl_seq_delay) {
+ usleep_range(data->ts_pinctrl_seq_delay,
+ data->ts_pinctrl_seq_delay +
+ HBTP_HOLD_DURATION_US);
+ dev_dbg(&data->pdev->dev, "ts_pinctrl_seq_delay = %u\n",
+ data->ts_pinctrl_seq_delay);
+ }
+ }
+ } else {
+ dev_warn(&data->pdev->dev,
+ "not a valid '%s' pinstate\n",
+ on ? "ts_active" : "ts_suspend");
+ return ret;
+ }
+
+ return ret;
+}
+
+static int hbtp_ddic_rst_select(struct hbtp_data *data, bool on)
+{
+ struct pinctrl_state *active, *suspend;
+ int ret = 0;
+
+ active = data->ddic_rst_state_active;
+ if (IS_ERR_OR_NULL(active)) {
+ dev_warn(&data->pdev->dev,
+ "not a valid ddic_rst_active pinstate\n");
+ return ret;
+ }
+
+ suspend = data->ddic_rst_state_suspend;
+ if (IS_ERR_OR_NULL(suspend)) {
+ dev_warn(&data->pdev->dev,
+ "not a valid ddic_rst_suspend pinstate\n");
+ return ret;
+ }
+
+ if (on) {
+ if (data->ddic_pinctrl_seq_delay[0]) {
+ usleep_range(data->ddic_pinctrl_seq_delay[0],
+ data->ddic_pinctrl_seq_delay[0] +
+ HBTP_HOLD_DURATION_US);
+ dev_dbg(&data->pdev->dev, "ddic_seq_delay[0] = %u\n",
+ data->ddic_pinctrl_seq_delay[0]);
+ }
+
+ ret = pinctrl_select_state(data->ts_pinctrl, active);
+ if (ret) {
+ dev_err(&data->pdev->dev,
+ "can not set ddic_rst_active pins\n");
+ return ret;
+ }
+ if (data->ddic_pinctrl_seq_delay[1]) {
+ usleep_range(data->ddic_pinctrl_seq_delay[1],
+ data->ddic_pinctrl_seq_delay[1] +
+ HBTP_HOLD_DURATION_US);
+ dev_dbg(&data->pdev->dev, "ddic_seq_delay[1] = %u\n",
+ data->ddic_pinctrl_seq_delay[1]);
+ }
+ ret = pinctrl_select_state(data->ts_pinctrl, suspend);
+ if (ret) {
+ dev_err(&data->pdev->dev,
+ "can not set ddic_rst_suspend pins\n");
+ return ret;
+ }
+
+ if (data->ddic_pinctrl_seq_delay[2]) {
+ usleep_range(data->ddic_pinctrl_seq_delay[2],
+ data->ddic_pinctrl_seq_delay[2] +
+ HBTP_HOLD_DURATION_US);
+ dev_dbg(&data->pdev->dev, "ddic_seq_delay[2] = %u\n",
+ data->ddic_pinctrl_seq_delay[2]);
+ }
+
+ ret = pinctrl_select_state(data->ts_pinctrl, active);
+ if (ret) {
+ dev_err(&data->pdev->dev,
+ "can not set ddic_rst_active pins\n");
+ return ret;
+ }
+
+ if (data->ddic_pinctrl_seq_delay[3]) {
+ usleep_range(data->ddic_pinctrl_seq_delay[3],
+ data->ddic_pinctrl_seq_delay[3] +
+ HBTP_HOLD_DURATION_US);
+ dev_dbg(&data->pdev->dev, "ddic_seq_delay[3] = %u\n",
+ data->ddic_pinctrl_seq_delay[3]);
+ }
+ } else {
+ ret = pinctrl_select_state(data->ts_pinctrl, suspend);
+ if (ret) {
+ dev_err(&data->pdev->dev,
+ "can not set ddic_rst_suspend pins\n");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int hbtp_pinctrl_enable(struct hbtp_data *ts, bool on)
+{
+ int rc = 0;
+
+ if (!ts->manage_pin_ctrl) {
+ pr_info("%s: pinctrl info is not available\n", __func__);
+ return 0;
+ }
+
+ if (!on)
+ goto pinctrl_suspend;
+
+ rc = hbtp_gpio_select(ts, true);
+ if (rc < 0)
+ return -EINVAL;
+
+ if (ts->ddic_rst_enabled) {
+ rc = hbtp_ddic_rst_select(ts, true);
+ if (rc < 0)
+ goto err_ddic_rst_pinctrl_enable;
+ }
+
+ return rc;
+
+pinctrl_suspend:
+ if (ts->ddic_rst_enabled)
+ hbtp_ddic_rst_select(ts, false);
+err_ddic_rst_pinctrl_enable:
+ hbtp_gpio_select(ts, false);
+ return rc;
+}
+
+static long hbtp_input_ioctl_handler(struct file *file, unsigned int cmd,
+ unsigned long arg, void __user *p)
+{
+ int error = 0;
+ struct hbtp_input_mt mt_data;
+ struct hbtp_input_absinfo absinfo[ABS_MT_LAST - ABS_MT_FIRST + 1];
+ struct hbtp_input_key key_data;
+ enum hbtp_afe_power_cmd power_cmd;
+ enum hbtp_afe_signal afe_signal;
+ enum hbtp_afe_power_ctrl afe_power_ctrl;
+
+ switch (cmd) {
+ case HBTP_SET_ABSPARAM:
+ if (hbtp && hbtp->input_dev) {
+ pr_err("%s: The input device is already created\n",
+ __func__);
+ return 0;
+ }
+
+ if (copy_from_user(absinfo, (void *)arg,
+ sizeof(struct hbtp_input_absinfo) *
+ (ABS_MT_LAST - ABS_MT_FIRST + 1))) {
+ pr_err("%s: Error copying data for ABS param\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ error = hbtp_input_create_input_dev(absinfo);
+ if (error)
+ pr_err("%s, hbtp_input_create_input_dev failed (%d)\n",
+ __func__, error);
+ break;
+
+ case HBTP_SET_TOUCHDATA:
+ if (!hbtp || !hbtp->input_dev) {
+ pr_err("%s: The input device hasn't been created\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&mt_data, (void *)arg,
+ sizeof(struct hbtp_input_mt))) {
+ pr_err("%s: Error copying data\n", __func__);
+ return -EFAULT;
+ }
+
+ hbtp_input_report_events(hbtp, &mt_data);
+ error = 0;
+ break;
+
+ case HBTP_SET_POWERSTATE:
+ if (!hbtp || !hbtp->input_dev) {
+ pr_err("%s: The input device hasn't been created\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&power_cmd, (void *)arg,
+ sizeof(enum hbtp_afe_power_cmd))) {
+ pr_err("%s: Error copying data\n", __func__);
+ return -EFAULT;
+ }
+
+ switch (power_cmd) {
+ case HBTP_AFE_POWER_ON:
+ error = hbtp_pdev_power_on(hbtp, true);
+ if (error)
+ pr_err("%s: failed to power on\n", __func__);
+ break;
+ case HBTP_AFE_POWER_OFF:
+ error = hbtp_pdev_power_on(hbtp, false);
+ if (error)
+ pr_err("%s: failed to power off\n", __func__);
+ break;
+ default:
+ pr_err("%s: Unsupported command for power state, %d\n",
+ __func__, power_cmd);
+ return -EINVAL;
+ }
+ break;
+
+ case HBTP_SET_KEYDATA:
+ if (!hbtp || !hbtp->input_dev) {
+ pr_err("%s: The input device hasn't been created\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&key_data, (void *)arg,
+ sizeof(struct hbtp_input_key))) {
+ pr_err("%s: Error copying data for key info\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ input_report_key(hbtp->input_dev, key_data.code,
+ key_data.value);
+ input_sync(hbtp->input_dev);
+ break;
+
+ case HBTP_SET_SYNCSIGNAL:
+ if (!hbtp || !hbtp->input_dev) {
+ pr_err("%s: The input device hasn't been created\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ if (!hbtp->power_sig_enabled) {
+ pr_err("%s: power_signal is not enabled", __func__);
+ return -EPERM;
+ }
+
+ if (copy_from_user(&afe_signal, (void *)arg,
+ sizeof(enum hbtp_afe_signal))) {
+ pr_err("%s: Error copying data\n", __func__);
+ return -EFAULT;
+ }
+
+ pr_debug("%s: receives %d signal\n", __func__, afe_signal);
+
+ switch (afe_signal) {
+ case HBTP_AFE_SIGNAL_ON_RESUME:
+ mutex_lock(&hbtp->mutex);
+ if (!hbtp->power_suspended) {
+ complete(&hbtp->power_resume_sig);
+ } else {
+ pr_err("%s: resume signal in wrong state\n",
+ __func__);
+ }
+ mutex_unlock(&hbtp->mutex);
+ break;
+ case HBTP_AFE_SIGNAL_ON_SUSPEND:
+ mutex_lock(&hbtp->mutex);
+ if (hbtp->power_suspended) {
+ complete(&hbtp->power_suspend_sig);
+ } else {
+ pr_err("%s: suspend signal in wrong state\n",
+ __func__);
+ }
+ mutex_unlock(&hbtp->mutex);
+ break;
+ default:
+ pr_err("%s: Unsupported command for afe signal, %d\n",
+ __func__, afe_signal);
+ return -EINVAL;
+ }
+ break;
+ case HBTP_SET_POWER_CTRL:
+ if (!hbtp || !hbtp->input_dev) {
+ pr_err("%s: The input device hasn't been created\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&afe_power_ctrl, (void *)arg,
+ sizeof(enum hbtp_afe_power_ctrl))) {
+ pr_err("%s: Error copying data\n", __func__);
+ return -EFAULT;
+ }
+ switch (afe_power_ctrl) {
+ case HBTP_AFE_POWER_ENABLE_SYNC:
+ pr_debug("%s: power_sync is enabled\n", __func__);
+ if (!hbtp->manage_pin_ctrl || !hbtp->manage_power_dig ||
+ !hbtp->manage_afe_power_ana) {
+ pr_err("%s: power/pin is not available\n",
+ __func__);
+ return -EFAULT;
+ }
+ mutex_lock(&hbtp->mutex);
+ error = hbtp_pdev_power_on(hbtp, true);
+ if (error) {
+ mutex_unlock(&hbtp->mutex);
+ pr_err("%s: failed to power on\n", __func__);
+ return error;
+ }
+ error = hbtp_pinctrl_enable(hbtp, true);
+ if (error) {
+ mutex_unlock(&hbtp->mutex);
+ pr_err("%s: failed to enable pins\n", __func__);
+ hbtp_pdev_power_on(hbtp, false);
+ return error;
+ }
+ hbtp->power_sync_enabled = true;
+ mutex_unlock(&hbtp->mutex);
+ pr_debug("%s: power_sync option is enabled\n",
+ __func__);
+ break;
+ case HBTP_AFE_POWER_ENABLE_SYNC_SIGNAL:
+ if (!hbtp->power_sync_enabled) {
+ pr_err("%s: power_sync is not enabled\n",
+ __func__);
+ return -EFAULT;
+ }
+ mutex_lock(&hbtp->mutex);
+ if (hbtp->init_completion_done_once) {
+ reinit_completion(&hbtp->power_resume_sig);
+ reinit_completion(&hbtp->power_suspend_sig);
+ } else {
+ init_completion(&hbtp->power_resume_sig);
+ init_completion(&hbtp->power_suspend_sig);
+ hbtp->init_completion_done_once = true;
+ }
+ hbtp->power_sig_enabled = true;
+ mutex_unlock(&hbtp->mutex);
+ pr_err("%s: sync_signal option is enabled\n", __func__);
+ break;
+ default:
+ pr_err("%s: unsupported power ctrl, %d\n",
+ __func__, afe_power_ctrl);
+ return -EINVAL;
+ }
+ break;
+
+ case HBTP_SET_SENSORDATA:
+ if (copy_from_user(hbtp->sensor_data, (void *)arg,
+ sizeof(struct hbtp_sensor_data))) {
+ pr_err("%s: Error copying data\n", __func__);
+ return -EFAULT;
+ }
+ mutex_lock(&hbtp->sensormutex);
+ memcpy(hbtp->ROI, hbtp->sensor_data->ROI, sizeof(hbtp->ROI));
+ memcpy(hbtp->accelBuffer, hbtp->sensor_data->accelBuffer,
+ sizeof(hbtp->accelBuffer));
+ mutex_unlock(&hbtp->sensormutex);
+
+ error = 0;
+ break;
+
+ default:
+ pr_err("%s: Unsupported ioctl command %u\n", __func__, cmd);
+ error = -EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+static long hbtp_input_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return hbtp_input_ioctl_handler(file, cmd, arg, (void __user *)arg);
+}
+
+#ifdef CONFIG_COMPAT
+static long hbtp_input_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return hbtp_input_ioctl_handler(file, cmd, arg, compat_ptr(arg));
+}
+#endif
+
+static const struct file_operations hbtp_input_fops = {
+ .owner = THIS_MODULE,
+ .open = hbtp_input_open,
+ .release = hbtp_input_release,
+ .unlocked_ioctl = hbtp_input_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = hbtp_input_compat_ioctl,
+#endif
+};
+
+static struct miscdevice hbtp_input_misc = {
+ .fops = &hbtp_input_fops,
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = HBTP_INPUT_NAME,
+};
+MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR);
+MODULE_ALIAS("devname:" HBTP_INPUT_NAME);
+
+#ifdef CONFIG_OF
+static int hbtp_parse_dt(struct device *dev)
+{
+ int rc, size;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ u32 temp_val;
+ u32 disp_reso[DISP_COORDS_SIZE];
+
+ if (of_find_property(np, "vcc_ana-supply", NULL))
+ hbtp->manage_afe_power_ana = true;
+ if (of_find_property(np, "vcc_dig-supply", NULL))
+ hbtp->manage_power_dig = true;
+
+ if (hbtp->manage_afe_power_ana) {
+ rc = of_property_read_u32(np, "qcom,afe-load", &temp_val);
+ if (!rc) {
+ hbtp->afe_load_ua = (int) temp_val;
+ } else {
+ dev_err(dev, "Unable to read AFE load\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "qcom,afe-vtg-min", &temp_val);
+ if (!rc) {
+ hbtp->afe_vtg_min_uv = (int) temp_val;
+ } else {
+ dev_err(dev, "Unable to read AFE min voltage\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "qcom,afe-vtg-max", &temp_val);
+ if (!rc) {
+ hbtp->afe_vtg_max_uv = (int) temp_val;
+ } else {
+ dev_err(dev, "Unable to read AFE max voltage\n");
+ return rc;
+ }
+ }
+ if (hbtp->manage_power_dig) {
+ rc = of_property_read_u32(np, "qcom,dig-load", &temp_val);
+ if (!rc) {
+ hbtp->dig_load_ua = (int) temp_val;
+ } else {
+ dev_err(dev, "Unable to read digital load\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "qcom,dig-vtg-min", &temp_val);
+ if (!rc) {
+ hbtp->dig_vtg_min_uv = (int) temp_val;
+ } else {
+ dev_err(dev, "Unable to read digital min voltage\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "qcom,dig-vtg-max", &temp_val);
+ if (!rc) {
+ hbtp->dig_vtg_max_uv = (int) temp_val;
+ } else {
+ dev_err(dev, "Unable to read digital max voltage\n");
+ return rc;
+ }
+ }
+
+ if (hbtp->manage_power_dig && hbtp->manage_afe_power_ana) {
+ rc = of_property_read_u32(np,
+ "qcom,afe-power-on-delay-us", &temp_val);
+ if (!rc)
+ hbtp->power_on_delay = (u32)temp_val;
+ else
+ dev_info(dev, "Power-On Delay is not specified\n");
+
+ rc = of_property_read_u32(np,
+ "qcom,afe-power-off-delay-us", &temp_val);
+ if (!rc)
+ hbtp->power_off_delay = (u32)temp_val;
+ else
+ dev_info(dev, "Power-Off Delay is not specified\n");
+
+ dev_dbg(dev, "power-on-delay = %u, power-off-delay = %u\n",
+ hbtp->power_on_delay, hbtp->power_off_delay);
+ }
+
+ prop = of_find_property(np, "qcom,display-resolution", NULL);
+ if (prop != NULL) {
+ if (!prop->value)
+ return -ENODATA;
+
+ size = prop->length / sizeof(u32);
+ if (size != DISP_COORDS_SIZE) {
+ dev_err(dev, "invalid qcom,display-resolution DT property\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, "qcom,display-resolution",
+ disp_reso, size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read DT property qcom,display-resolution\n");
+ return rc;
+ }
+
+ hbtp->disp_maxx = disp_reso[0];
+ hbtp->disp_maxy = disp_reso[1];
+
+ hbtp->override_disp_coords = true;
+ }
+
+ hbtp->use_scaling = of_property_read_bool(np, "qcom,use-scale");
+ if (hbtp->use_scaling) {
+ rc = of_property_read_u32(np, "qcom,default-max-x", &temp_val);
+ if (!rc) {
+ hbtp->def_maxx = (int) temp_val;
+ } else if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read default max x\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "qcom,desired-max-x", &temp_val);
+ if (!rc) {
+ hbtp->des_maxx = (int) temp_val;
+ } else if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read desired max x\n");
+ return rc;
+ }
+
+ /*
+ * Either both DT properties i.e. Default max X and
+ * Desired max X should be defined simultaneously, or none
+ * of them should be defined.
+ */
+ if ((hbtp->def_maxx == 0 && hbtp->des_maxx != 0) ||
+ (hbtp->def_maxx != 0 && hbtp->des_maxx == 0)) {
+ dev_err(dev, "default or desired max-X properties are incorrect\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(np, "qcom,default-max-y", &temp_val);
+ if (!rc) {
+ hbtp->def_maxy = (int) temp_val;
+ } else if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read default max y\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "qcom,desired-max-y", &temp_val);
+ if (!rc) {
+ hbtp->des_maxy = (int) temp_val;
+ } else if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read desired max y\n");
+ return rc;
+ }
+
+ /*
+ * Either both DT properties i.e. Default max X and
+ * Desired max X should be defined simultaneously, or none
+ * of them should be defined.
+ */
+ if ((hbtp->def_maxy == 0 && hbtp->des_maxy != 0) ||
+ (hbtp->def_maxy != 0 && hbtp->des_maxy == 0)) {
+ dev_err(dev, "default or desired max-Y properties are incorrect\n");
+ return -EINVAL;
+ }
+
+ }
+
+ return 0;
+}
+#else
+static int hbtp_parse_dt(struct device *dev)
+{
+ return -ENODEV;
+}
+#endif
+
+static int hbtp_pinctrl_init(struct hbtp_data *data)
+{
+ const char *statename;
+ int rc;
+ int state_cnt, i;
+ struct device_node *np = data->pdev->dev.of_node;
+ bool pinctrl_state_act_found = false;
+ bool pinctrl_state_sus_found = false;
+ bool pinctrl_ddic_act_found = false;
+ bool pinctrl_ddic_sus_found = false;
+ int count = 0;
+
+ data->ts_pinctrl = devm_pinctrl_get(&(data->pdev->dev));
+ if (IS_ERR_OR_NULL(data->ts_pinctrl)) {
+ dev_err(&data->pdev->dev,
+ "Target does not use pinctrl\n");
+ rc = PTR_ERR(data->ts_pinctrl);
+ data->ts_pinctrl = NULL;
+ return rc;
+ }
+
+ state_cnt = of_property_count_strings(np, "pinctrl-names");
+ if (state_cnt < HBTP_PINCTRL_VALID_STATE_CNT) {
+ /*
+ *if pinctrl names are not available then,
+ *power_sync can't be enabled
+ */
+ dev_info(&data->pdev->dev,
+ "pinctrl names are not available\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ for (i = 0; i < state_cnt; i++) {
+ rc = of_property_read_string_index(np,
+ "pinctrl-names", i, &statename);
+ if (rc) {
+ dev_err(&data->pdev->dev,
+ "failed to read pinctrl states by index\n");
+ goto error;
+ }
+
+ if (!strcmp(statename, "pmx_ts_active")) {
+ data->gpio_state_active
+ = pinctrl_lookup_state(data->ts_pinctrl,
+ statename);
+ if (IS_ERR_OR_NULL(data->gpio_state_active)) {
+ dev_err(&data->pdev->dev,
+ "Can not get ts default state\n");
+ rc = PTR_ERR(data->gpio_state_active);
+ goto error;
+ }
+ pinctrl_state_act_found = true;
+ } else if (!strcmp(statename, "pmx_ts_suspend")) {
+ data->gpio_state_suspend
+ = pinctrl_lookup_state(data->ts_pinctrl,
+ statename);
+ if (IS_ERR_OR_NULL(data->gpio_state_suspend)) {
+ dev_err(&data->pdev->dev,
+ "Can not get ts sleep state\n");
+ rc = PTR_ERR(data->gpio_state_suspend);
+ goto error;
+ }
+ pinctrl_state_sus_found = true;
+ } else if (!strcmp(statename, "ddic_rst_active")) {
+ data->ddic_rst_state_active
+ = pinctrl_lookup_state(data->ts_pinctrl,
+ statename);
+ if (IS_ERR(data->ddic_rst_state_active)) {
+ dev_err(&data->pdev->dev,
+ "Can not get DDIC rst act state\n");
+ rc = PTR_ERR(data->ddic_rst_state_active);
+ goto error;
+ }
+ pinctrl_ddic_act_found = true;
+ } else if (!strcmp(statename, "ddic_rst_suspend")) {
+ data->ddic_rst_state_suspend
+ = pinctrl_lookup_state(data->ts_pinctrl,
+ statename);
+ if (IS_ERR(data->ddic_rst_state_suspend)) {
+ dev_err(&data->pdev->dev,
+ "Can not get DDIC rst sleep state\n");
+ rc = PTR_ERR(data->ddic_rst_state_suspend);
+ goto error;
+ }
+ pinctrl_ddic_sus_found = true;
+ } else {
+ dev_err(&data->pdev->dev, "invalid pinctrl state\n");
+ rc = -EINVAL;
+ goto error;
+ }
+ }
+
+ if (!pinctrl_state_act_found || !pinctrl_state_sus_found) {
+ dev_err(&data->pdev->dev,
+ "missing required pinctrl states\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ if (of_property_read_u32(np, "qcom,pmx-ts-on-seq-delay-us",
+ &data->ts_pinctrl_seq_delay)) {
+ dev_warn(&data->pdev->dev, "Can not find ts seq delay\n");
+ }
+
+ if (of_property_read_u32(np, "qcom,fb-resume-delay-us",
+ &data->fb_resume_seq_delay)) {
+ dev_warn(&data->pdev->dev, "Can not find fb resume seq delay\n");
+ }
+
+ if (pinctrl_ddic_act_found && pinctrl_ddic_sus_found) {
+ count = of_property_count_u32_elems(np,
+ "qcom,ddic-rst-on-seq-delay-us");
+ if (count == HBTP_PINCTRL_DDIC_SEQ_NUM) {
+ of_property_read_u32_array(np,
+ "qcom,ddic-rst-on-seq-delay-us",
+ data->ddic_pinctrl_seq_delay, count);
+ } else {
+ dev_err(&data->pdev->dev, "count(%u) is not same as %u\n",
+ (u32)count, HBTP_PINCTRL_DDIC_SEQ_NUM);
+ }
+
+ data->ddic_rst_enabled = true;
+ } else {
+ dev_warn(&data->pdev->dev, "ddic pinctrl act/sus not found\n");
+ }
+
+ data->manage_pin_ctrl = true;
+ return 0;
+
+error:
+ devm_pinctrl_put(data->ts_pinctrl);
+ data->ts_pinctrl = NULL;
+ return rc;
+}
+
+static int hbtp_fb_early_suspend(struct hbtp_data *ts)
+{
+ int rc = 0;
+ char *envp[2] = {HBTP_EVENT_TYPE_DISPLAY, NULL};
+
+ mutex_lock(&hbtp->mutex);
+ if (ts->pdev && (!ts->power_sync_enabled)) {
+ pr_debug("%s: power_sync is not enabled\n", __func__);
+
+ if (ts->input_dev) {
+ kobject_uevent_env(&ts->input_dev->dev.kobj,
+ KOBJ_OFFLINE, envp);
+
+ if (ts->power_sig_enabled) {
+ pr_debug("%s: power_sig is enabled, wait for signal\n",
+ __func__);
+ mutex_unlock(&hbtp->mutex);
+ rc = wait_for_completion_interruptible(
+ &hbtp->power_suspend_sig);
+ if (rc != 0) {
+ pr_err("%s: wait for early suspend is interrupted\n",
+ __func__);
+ }
+ mutex_lock(&hbtp->mutex);
+ pr_debug("%s: Wait is done for early suspend\n",
+ __func__);
+ } else {
+ pr_debug("%s: power_sig is NOT enabled",
+ __func__);
+ }
+ }
+ }
+
+ mutex_unlock(&hbtp->mutex);
+ return rc;
+}
+
+static int hbtp_fb_suspend(struct hbtp_data *ts)
+{
+ int rc;
+ char *envp[2] = {HBTP_EVENT_TYPE_DISPLAY, NULL};
+
+ mutex_lock(&hbtp->mutex);
+ if (ts->pdev && ts->power_sync_enabled) {
+ pr_debug("%s: power_sync is enabled\n", __func__);
+ if (ts->power_suspended) {
+ mutex_unlock(&hbtp->mutex);
+ pr_err("%s: power is not resumed\n", __func__);
+ return 0;
+ }
+ rc = hbtp_pinctrl_enable(ts, false);
+ if (rc) {
+ pr_err("%s: failed to disable GPIO pins\n", __func__);
+ goto err_pin_disable;
+ }
+
+ rc = hbtp_pdev_power_on(ts, false);
+ if (rc) {
+ pr_err("%s: failed to disable power\n", __func__);
+ goto err_power_disable;
+ }
+ ts->power_suspended = true;
+ }
+
+ if (ts->input_dev) {
+ kobject_uevent_env(&ts->input_dev->dev.kobj,
+ KOBJ_OFFLINE, envp);
+
+ if (ts->power_sig_enabled) {
+ pr_debug("%s: power_sig is enabled, wait for signal\n",
+ __func__);
+ mutex_unlock(&hbtp->mutex);
+ rc = wait_for_completion_interruptible(
+ &hbtp->power_suspend_sig);
+ if (rc != 0) {
+ pr_err("%s: wait for suspend is interrupted\n",
+ __func__);
+ }
+ mutex_lock(&hbtp->mutex);
+ pr_debug("%s: Wait is done for suspend\n",
+ __func__);
+ } else {
+ pr_debug("%s: power_sig is NOT enabled",
+ __func__);
+ }
+ }
+
+ mutex_unlock(&hbtp->mutex);
+ return 0;
+err_power_disable:
+ hbtp_pinctrl_enable(ts, true);
+err_pin_disable:
+ mutex_unlock(&hbtp->mutex);
+ return rc;
+}
+
+static int hbtp_fb_early_resume(struct hbtp_data *ts)
+{
+ char *envp[2] = {HBTP_EVENT_TYPE_DISPLAY, NULL};
+ int rc;
+
+ mutex_lock(&hbtp->mutex);
+
+ pr_debug("%s: hbtp_fb_early_resume\n", __func__);
+
+ if (ts->pdev && ts->power_sync_enabled) {
+ pr_debug("%s: power_sync is enabled\n", __func__);
+ if (!ts->power_suspended) {
+ pr_err("%s: power is not suspended\n", __func__);
+ mutex_unlock(&hbtp->mutex);
+ return 0;
+ }
+ rc = hbtp_pdev_power_on(ts, true);
+ if (rc) {
+ pr_err("%s: failed to enable panel power\n", __func__);
+ goto err_power_on;
+ }
+
+ rc = hbtp_pinctrl_enable(ts, true);
+
+ if (rc) {
+ pr_err("%s: failed to enable pin\n", __func__);
+ goto err_pin_enable;
+ }
+
+ if (ts->fb_resume_seq_delay) {
+ usleep_range(ts->fb_resume_seq_delay,
+ ts->fb_resume_seq_delay +
+ HBTP_HOLD_DURATION_US);
+ pr_debug("%s: fb_resume_seq_delay = %u\n",
+ __func__, ts->fb_resume_seq_delay);
+ }
+
+ ts->power_suspended = false;
+ }
+
+ if (ts->input_dev) {
+
+ kobject_uevent_env(&ts->input_dev->dev.kobj,
+ KOBJ_ONLINE, envp);
+
+ if (ts->power_sig_enabled) {
+ pr_err("%s: power_sig is enabled, wait for signal\n",
+ __func__);
+ mutex_unlock(&hbtp->mutex);
+ rc = wait_for_completion_interruptible(
+ &hbtp->power_resume_sig);
+ if (rc != 0) {
+ pr_err("%s: wait for resume is interrupted\n",
+ __func__);
+ }
+ mutex_lock(&hbtp->mutex);
+ pr_debug("%s: wait is done\n", __func__);
+ } else {
+ pr_debug("%s: power_sig is NOT enabled\n",
+ __func__);
+ }
+ }
+
+ mutex_unlock(&hbtp->mutex);
+ return 0;
+
+err_pin_enable:
+ hbtp_pdev_power_on(ts, false);
+err_power_on:
+ mutex_unlock(&hbtp->mutex);
+ return rc;
+}
+
+static int hbtp_fb_revert_resume(struct hbtp_data *ts)
+{
+ char *envp[2] = {HBTP_EVENT_TYPE_DISPLAY, NULL};
+ int rc = 0;
+
+ mutex_lock(&hbtp->mutex);
+
+ pr_debug("%s: hbtp_fb_revert_resume\n", __func__);
+
+ if (ts->pdev && (!ts->power_sync_enabled)) {
+ pr_debug("%s: power_sync is not enabled\n", __func__);
+
+ if (ts->input_dev) {
+ kobject_uevent_env(&ts->input_dev->dev.kobj,
+ KOBJ_ONLINE, envp);
+
+ if (ts->power_sig_enabled) {
+ pr_debug("%s: power_sig is enabled, wait for signal\n",
+ __func__);
+ mutex_unlock(&hbtp->mutex);
+ rc = wait_for_completion_interruptible(
+ &hbtp->power_resume_sig);
+ if (rc != 0) {
+ pr_warn("%s: wait for revert resume is interrupted\n",
+ __func__);
+ }
+ pr_debug("%s: wait is done\n", __func__);
+ } else {
+ pr_debug("%s: power_sig is NOT enabled\n",
+ __func__);
+ }
+ }
+ }
+
+ return rc;
+}
+
+static int hbtp_pdev_probe(struct platform_device *pdev)
+{
+ int error;
+ struct regulator *vcc_ana, *vcc_dig;
+
+ hbtp->pdev = pdev;
+
+ if (pdev->dev.of_node) {
+ error = hbtp_parse_dt(&pdev->dev);
+ if (error) {
+ pr_err("%s: parse dt failed, rc=%d\n", __func__, error);
+ return error;
+ }
+ }
+
+ platform_set_drvdata(pdev, hbtp);
+
+ error = hbtp_pinctrl_init(hbtp);
+ if (error) {
+ pr_info("%s: pinctrl isn't available, rc=%d\n", __func__,
+ error);
+ }
+
+ if (hbtp->manage_afe_power_ana) {
+ vcc_ana = regulator_get(&pdev->dev, "vcc_ana");
+ if (IS_ERR(vcc_ana)) {
+ error = PTR_ERR(vcc_ana);
+ pr_err("%s: regulator get failed vcc_ana rc=%d\n",
+ __func__, error);
+ return error;
+ }
+
+ if (regulator_count_voltages(vcc_ana) > 0) {
+ error = regulator_set_voltage(vcc_ana,
+ hbtp->afe_vtg_min_uv, hbtp->afe_vtg_max_uv);
+ if (error) {
+ pr_err("%s: regulator set vtg failed vcc_ana rc=%d\n",
+ __func__, error);
+ regulator_put(vcc_ana);
+ return error;
+ }
+ }
+ hbtp->vcc_ana = vcc_ana;
+ }
+
+ if (hbtp->manage_power_dig) {
+ vcc_dig = regulator_get(&pdev->dev, "vcc_dig");
+ if (IS_ERR(vcc_dig)) {
+ error = PTR_ERR(vcc_dig);
+ pr_err("%s: regulator get failed vcc_dig rc=%d\n",
+ __func__, error);
+ return error;
+ }
+
+ if (regulator_count_voltages(vcc_dig) > 0) {
+ error = regulator_set_voltage(vcc_dig,
+ hbtp->dig_vtg_min_uv, hbtp->dig_vtg_max_uv);
+ if (error) {
+ pr_err("%s: regulator set vtg failed vcc_dig rc=%d\n",
+ __func__, error);
+ regulator_put(vcc_dig);
+ return error;
+ }
+ }
+ hbtp->vcc_dig = vcc_dig;
+ }
+
+ return 0;
+}
+
+static int hbtp_pdev_remove(struct platform_device *pdev)
+{
+ if (hbtp->vcc_ana || hbtp->vcc_dig) {
+ hbtp_pdev_power_on(hbtp, false);
+ if (hbtp->vcc_ana)
+ regulator_put(hbtp->vcc_ana);
+ if (hbtp->vcc_dig)
+ regulator_put(hbtp->vcc_dig);
+ }
+
+ if (hbtp->ts_pinctrl)
+ devm_pinctrl_put(hbtp->ts_pinctrl);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id hbtp_match_table[] = {
+ { .compatible = "qcom,hbtp-input",},
+ { },
+};
+#else
+#define hbtp_match_table NULL
+#endif
+
+static struct platform_driver hbtp_pdev_driver = {
+ .probe = hbtp_pdev_probe,
+ .remove = hbtp_pdev_remove,
+ .driver = {
+ .name = "hbtp",
+ .owner = THIS_MODULE,
+ .of_match_table = hbtp_match_table,
+ },
+};
+
+static int __init hbtp_init(void)
+{
+ int error;
+
+ hbtp = kzalloc(sizeof(struct hbtp_data), GFP_KERNEL);
+ if (!hbtp)
+ return -ENOMEM;
+
+ hbtp->sensor_data = kzalloc(sizeof(struct hbtp_sensor_data),
+ GFP_KERNEL);
+ if (!hbtp->sensor_data) {
+ error = -ENOMEM;
+ goto err_sensordata;
+ }
+
+ mutex_init(&hbtp->mutex);
+ mutex_init(&hbtp->sensormutex);
+ hbtp->init_completion_done_once = false;
+
+ error = misc_register(&hbtp_input_misc);
+ if (error) {
+ pr_err("%s: misc_register failed\n", HBTP_INPUT_NAME);
+ goto err_misc_reg;
+ }
+
+#if defined(CONFIG_FB)
+ hbtp->fb_notif.notifier_call = fb_notifier_callback;
+ error = fb_register_client(&hbtp->fb_notif);
+ if (error) {
+ pr_err("%s: Unable to register fb_notifier: %d\n",
+ HBTP_INPUT_NAME, error);
+ goto err_fb_reg;
+ }
+#endif
+
+ sensor_kobject = kobject_create_and_add("hbtpsensor", kernel_kobj);
+ if (!sensor_kobject) {
+ pr_err("%s: Could not create hbtpsensor kobject\n", __func__);
+ error = -ENOMEM;
+ goto err_kobject_create;
+ }
+
+ error = sysfs_create_bin_file(sensor_kobject, &capdata_attr);
+ if (error < 0) {
+ pr_err("%s: hbtp capdata sysfs creation failed: %d\n", __func__,
+ error);
+ goto err_sysfs_create_capdata;
+ }
+ pr_debug("capdata sysfs creation success\n");
+
+ error = sysfs_create_bin_file(sensor_kobject, &vibdata_attr);
+ if (error < 0) {
+ pr_err("%s: vibdata sysfs creation failed: %d\n", __func__,
+ error);
+ goto err_sysfs_create_vibdata;
+ }
+ pr_debug("vibdata sysfs creation success\n");
+
+ error = platform_driver_register(&hbtp_pdev_driver);
+ if (error) {
+ pr_err("Failed to register platform driver: %d\n", error);
+ goto err_platform_drv_reg;
+ }
+
+ return 0;
+
+err_platform_drv_reg:
+ sysfs_remove_bin_file(sensor_kobject, &vibdata_attr);
+err_sysfs_create_vibdata:
+ sysfs_remove_bin_file(sensor_kobject, &capdata_attr);
+err_sysfs_create_capdata:
+ kobject_put(sensor_kobject);
+err_kobject_create:
+#if defined(CONFIG_FB)
+ fb_unregister_client(&hbtp->fb_notif);
+err_fb_reg:
+#endif
+ misc_deregister(&hbtp_input_misc);
+err_misc_reg:
+ kfree(hbtp->sensor_data);
+err_sensordata:
+ kfree(hbtp);
+
+ return error;
+}
+
+static void __exit hbtp_exit(void)
+{
+ sysfs_remove_bin_file(sensor_kobject, &vibdata_attr);
+ sysfs_remove_bin_file(sensor_kobject, &capdata_attr);
+ kobject_put(sensor_kobject);
+ misc_deregister(&hbtp_input_misc);
+ if (hbtp->input_dev)
+ input_unregister_device(hbtp->input_dev);
+
+#if defined(CONFIG_FB)
+ fb_unregister_client(&hbtp->fb_notif);
+#endif
+
+ platform_driver_unregister(&hbtp_pdev_driver);
+
+ kfree(hbtp->sensor_data);
+ kfree(hbtp);
+}
+
+MODULE_DESCRIPTION("Kernel driver to support host based touch processing");
+MODULE_LICENSE("GPLv2");
+
+module_init(hbtp_init);
+module_exit(hbtp_exit);
diff --git a/drivers/input/misc/hbtp_vm.c b/drivers/input/misc/hbtp_vm.c
new file mode 100644
index 000000000000..408bf5d67b63
--- /dev/null
+++ b/drivers/input/misc/hbtp_vm.c
@@ -0,0 +1,293 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/input/mt.h>
+#include <uapi/linux/hbtp_input.h>
+#include <uapi/linux/hbtp_vm.h>
+
+#define hbtp_vm_name "hbtp_vm"
+
+struct hbtp_virtual_mouse {
+ struct input_dev *input_dev;
+ s32 open_count;
+ struct mutex mutex;
+ bool touch_status[HBTP_MAX_FINGER];
+
+ int enabled;
+ int last_x;
+ int last_y;
+ int parking_dist_x;
+};
+
+static struct hbtp_virtual_mouse *hbtp_vm;
+
+static int hbtp_vm_open(struct inode *inode, struct file *file)
+{
+ mutex_lock(&hbtp_vm->mutex);
+ if (hbtp_vm->open_count)
+ pr_debug("hbtp_vm was already opened\n");
+ hbtp_vm->open_count++;
+ mutex_unlock(&hbtp_vm->mutex);
+
+ return 0;
+}
+
+static int hbtp_vm_release(struct inode *inode, struct file *file)
+{
+ mutex_lock(&hbtp_vm->mutex);
+ if (!hbtp_vm->open_count) {
+ pr_err("%s wasn't opened\n", hbtp_vm_name);
+ mutex_unlock(&hbtp_vm->mutex);
+ return -ENOTTY;
+ }
+ hbtp_vm->open_count--;
+ mutex_unlock(&hbtp_vm->mutex);
+ return 0;
+}
+
+static int hbtp_vm_create_input_dev(void)
+{
+ struct input_dev *input_dev;
+ int error;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ pr_err("%s: input_allocate_device failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ kfree(input_dev->name);
+ input_dev->name = kstrndup(hbtp_vm_name, sizeof(hbtp_vm_name),
+ GFP_KERNEL);
+
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+ __set_bit(EV_REL, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_LEFT, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+ __set_bit(REL_HWHEEL, input_dev->relbit);
+
+ input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+
+ error = input_register_device(input_dev);
+ if (error) {
+ pr_err("%s: input_register_device failed\n", __func__);
+ goto err_input_reg_dev;
+ }
+
+ hbtp_vm->input_dev = input_dev;
+ return 0;
+
+err_input_reg_dev:
+ input_free_device(input_dev);
+ return error;
+}
+
+static int hbtp_vm_report_events(struct hbtp_virtual_mouse *hbtp_data,
+ struct hbtp_input_mt *mt_data)
+{
+ struct hbtp_input_touch *tch;
+ int dx = 0;
+ int dy = 0;
+
+ if (mt_data->num_touches > 1) {
+ pr_err("virtual mouse received multi touch reports\n");
+ return 0;
+ }
+
+ if (mt_data->num_touches == 1) {
+ tch = &(mt_data->touches[0]);
+ if (hbtp_vm->last_x != -1 && hbtp_vm->last_x != -1) {
+ dx = tch->x - hbtp_vm->last_x;
+ dy = tch->y - hbtp_vm->last_y;
+ }
+
+ if (!(dx == 0 && dy == 0)) {
+ input_report_rel(hbtp_vm->input_dev, REL_X, dx);
+ input_report_rel(hbtp_vm->input_dev, REL_Y, dy);
+ input_sync(hbtp_vm->input_dev);
+ }
+
+ hbtp_vm->last_x = tch->x;
+ hbtp_vm->last_y = tch->y;
+ } else {
+ hbtp_vm->last_x = -1;
+ hbtp_vm->last_y = -1;
+ }
+
+ return 0;
+}
+
+static int hbtp_vm_report_clicks(struct hbtp_virtual_mouse *hbtp_data,
+ struct hbtp_vm_click *click_data)
+{
+ unsigned int code = BTN_LEFT;
+ int value = 1;
+
+ if (click_data->mask & HBTP_VM_BUTTON_RIGHT)
+ code = BTN_RIGHT;
+
+ if (click_data->mask & HBTP_VM_BUTTON_UP)
+ value = 0;
+
+ input_report_key(hbtp_vm->input_dev, code, value);
+ input_sync(hbtp_vm->input_dev);
+
+ return 0;
+}
+
+static long hbtp_vm_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int error = 0;
+ struct hbtp_input_mt mt_data;
+ struct hbtp_vm_click clik_data;
+
+ if (!hbtp_vm) {
+ pr_err("%s: virtual mouse driver not initialized\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ switch (cmd) {
+ case HBTP_VM_ENABLE:
+ if (hbtp_vm->enabled) {
+ pr_err("virtual mouse device is already enabled\n");
+ return 0;
+ }
+ hbtp_vm->enabled = true;
+ input_report_rel(hbtp_vm->input_dev, REL_X, -2000);
+ input_report_rel(hbtp_vm->input_dev, REL_Y, -2000);
+ input_sync(hbtp_vm->input_dev);
+ input_report_rel(hbtp_vm->input_dev, REL_X, 100);
+ input_report_rel(hbtp_vm->input_dev, REL_Y, 100);
+ input_sync(hbtp_vm->input_dev);
+
+ break;
+
+ case HBTP_VM_DISABLE:
+ if (!hbtp_vm->enabled) {
+ pr_err("virtual mouse device is already disabled\n");
+ return 0;
+ }
+ hbtp_vm->enabled = false;
+ input_report_rel(hbtp_vm->input_dev, REL_X, 2000);
+ input_report_rel(hbtp_vm->input_dev, REL_Y, 2000);
+ input_sync(hbtp_vm->input_dev);
+ break;
+
+ case HBTP_VM_SET_TOUCHDATA:
+ if (!hbtp_vm->input_dev) {
+ pr_err("%s: virtual mouse input device hasn't been created\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&mt_data, (void *)arg,
+ sizeof(struct hbtp_input_mt))) {
+ pr_err("%s: Error copying data\n", __func__);
+ return -EFAULT;
+ }
+
+ hbtp_vm_report_events(hbtp_vm, &mt_data);
+ error = 0;
+ break;
+
+ case HBTP_VM_SEND_CLICK:
+ if (!hbtp_vm->input_dev) {
+ pr_err("%s: virtual mouse input device hasn't been created\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&clik_data, (void *)arg,
+ sizeof(struct hbtp_vm_click))) {
+ pr_err("%s: Error copying data\n", __func__);
+ return -EFAULT;
+ }
+
+ hbtp_vm_report_clicks(hbtp_vm, &clik_data);
+ error = 0;
+ break;
+ default:
+ pr_err("%s: Unsupported ioctl command %u\n", __func__, cmd);
+ error = -EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+static const struct file_operations hbtp_vm_fops = {
+ .owner = THIS_MODULE,
+ .open = hbtp_vm_open,
+ .release = hbtp_vm_release,
+ .unlocked_ioctl = hbtp_vm_ioctl,
+ .compat_ioctl = hbtp_vm_ioctl,
+};
+
+static struct miscdevice hbtp_vm_misc = {
+ .fops = &hbtp_vm_fops,
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = hbtp_vm_name,
+};
+
+static int __init hbtp_vm_init(void)
+{
+ int error;
+
+ hbtp_vm = kzalloc(sizeof(struct hbtp_virtual_mouse), GFP_KERNEL);
+
+ if (!hbtp_vm)
+ return -ENOMEM;
+
+ hbtp_vm->last_x = -1;
+ hbtp_vm->last_y = -1;
+
+ mutex_init(&hbtp_vm->mutex);
+ error = misc_register(&hbtp_vm_misc);
+ if (error) {
+ pr_err("%s: misc_register failed\n", hbtp_vm_name);
+ goto err_misc_reg;
+ }
+
+ hbtp_vm_create_input_dev();
+ return 0;
+
+err_misc_reg:
+ kfree(hbtp_vm);
+ return error;
+}
+
+static void __exit hbtp_vm_exit(void)
+{
+ misc_deregister(&hbtp_vm_misc);
+ if (hbtp_vm->input_dev) {
+ input_unregister_device(hbtp_vm->input_dev);
+ hbtp_vm->input_dev = NULL;
+ }
+ kfree(hbtp_vm);
+}
+
+MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR);
+MODULE_ALIAS("devname:" hbtp_vm_name);
+MODULE_DESCRIPTION("kernel module to support virtual mouse");
+MODULE_LICENSE("GPL v2");
+module_init(hbtp_vm_init);
+module_exit(hbtp_vm_exit);
diff --git a/drivers/input/misc/ots_pat9125/Kconfig b/drivers/input/misc/ots_pat9125/Kconfig
new file mode 100644
index 000000000000..af82edd0faae
--- /dev/null
+++ b/drivers/input/misc/ots_pat9125/Kconfig
@@ -0,0 +1,14 @@
+#
+# PixArt OTS switch driver configuration
+#
+
+config INPUT_PIXART_OTS_PAT9125_SWITCH
+ tristate "PixArt PAT9125 Rotating Switch driver"
+ depends on INPUT && I2C && GPIOLIB
+ help
+ Say Y to enable support for the PixArt OTS pat9125
+ rotating switch driver.
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ots_pat9125.
diff --git a/drivers/input/misc/ots_pat9125/Makefile b/drivers/input/misc/ots_pat9125/Makefile
new file mode 100644
index 000000000000..a697caf69644
--- /dev/null
+++ b/drivers/input/misc/ots_pat9125/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the PixArt OST switch driver.
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_INPUT_PIXART_OTS_PAT9125_SWITCH) += pat9125_linux_driver.o pixart_ots.o
diff --git a/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
new file mode 100644
index 000000000000..fa5e4cca129d
--- /dev/null
+++ b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
@@ -0,0 +1,627 @@
+/* drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
+ *
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include <linux/input.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include "pixart_ots.h"
+
+struct pixart_pat9125_data {
+ struct i2c_client *client;
+ struct input_dev *input;
+ int irq_gpio;
+ u32 press_keycode;
+ bool press_en;
+ bool inverse_x;
+ bool inverse_y;
+ struct regulator *vdd;
+ struct regulator *vld;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pinctrl_state_active;
+ struct pinctrl_state *pinctrl_state_suspend;
+ struct pinctrl_state *pinctrl_state_release;
+};
+
+/* Declaration of suspend and resume functions */
+static int pat9125_suspend(struct device *dev);
+static int pat9125_resume(struct device *dev);
+
+static int pat9125_i2c_write(struct i2c_client *client, u8 reg, u8 *data,
+ int len)
+{
+ u8 buf[MAX_BUF_SIZE];
+ int ret = 0, i;
+ struct device *dev = &client->dev;
+
+ buf[0] = reg;
+ if (len >= MAX_BUF_SIZE) {
+ dev_err(dev, "%s Failed: buffer size is %d [Max Limit is %d]\n",
+ __func__, len, MAX_BUF_SIZE);
+ return -ENODEV;
+ }
+ for (i = 0 ; i < len; i++)
+ buf[i+1] = data[i];
+ /* Returns negative errno, or else the number of bytes written. */
+ ret = i2c_master_send(client, buf, len+1);
+ if (ret != len+1)
+ dev_err(dev, "%s Failed: writing to reg 0x%x\n", __func__, reg);
+
+ return ret;
+}
+
+static int pat9125_i2c_read(struct i2c_client *client, u8 reg, u8 *data)
+{
+ u8 buf[MAX_BUF_SIZE];
+ int ret;
+ struct device *dev = &client->dev;
+
+ buf[0] = reg;
+ /*
+ * If everything went ok (1 msg transmitted), return #bytes transmitted,
+ * else error code. thus if transmit is ok return value 1
+ */
+ ret = i2c_master_send(client, buf, 1);
+ if (ret != 1) {
+ dev_err(dev, "%s Failed: writing to reg 0x%x\n", __func__, reg);
+ return ret;
+ }
+ /* returns negative errno, or else the number of bytes read */
+ ret = i2c_master_recv(client, buf, 1);
+ if (ret != 1) {
+ dev_err(dev, "%s Failed: reading reg 0x%x\n", __func__, reg);
+ return ret;
+ }
+ *data = buf[0];
+
+ return ret;
+}
+
+u8 read_data(struct i2c_client *client, u8 addr)
+{
+ u8 data = 0xff;
+
+ pat9125_i2c_read(client, addr, &data);
+ return data;
+}
+
+void write_data(struct i2c_client *client, u8 addr, u8 data)
+{
+ pat9125_i2c_write(client, addr, &data, 1);
+}
+
+static irqreturn_t pat9125_irq(int irq, void *dev_data)
+{
+ u8 delta_x = 0, delta_y = 0, motion;
+ struct pixart_pat9125_data *data = dev_data;
+ struct input_dev *ipdev = data->input;
+ struct device *dev = &data->client->dev;
+
+ motion = read_data(data->client, PIXART_PAT9125_MOTION_STATUS_REG);
+ do {
+ /* check if MOTION bit is set or not */
+ if (motion & PIXART_PAT9125_VALID_MOTION_DATA) {
+ delta_x = read_data(data->client,
+ PIXART_PAT9125_DELTA_X_LO_REG);
+ delta_y = read_data(data->client,
+ PIXART_PAT9125_DELTA_Y_LO_REG);
+
+ /* Inverse x depending upon the device orientation */
+ delta_x = (data->inverse_x) ? -delta_x : delta_x;
+ /* Inverse y depending upon the device orientation */
+ delta_y = (data->inverse_y) ? -delta_y : delta_y;
+ }
+
+ dev_dbg(dev, "motion = %x, delta_x = %x, delta_y = %x\n",
+ motion, delta_x, delta_y);
+
+ if (delta_x != 0) {
+ /* Send delta_x as REL_WHEEL for rotation */
+ input_report_rel(ipdev, REL_WHEEL, (s8) delta_x);
+ input_sync(ipdev);
+ }
+
+ if (data->press_en && delta_y != 0) {
+ if ((s8) delta_y > 0) {
+ /* Send DOWN event for press keycode */
+ input_report_key(ipdev, data->press_keycode, 1);
+ input_sync(ipdev);
+ } else {
+ /* Send UP event for press keycode */
+ input_report_key(ipdev, data->press_keycode, 0);
+ input_sync(ipdev);
+ }
+ }
+ usleep_range(PIXART_SAMPLING_PERIOD_US_MIN,
+ PIXART_SAMPLING_PERIOD_US_MAX);
+
+ motion = read_data(data->client,
+ PIXART_PAT9125_MOTION_STATUS_REG);
+ } while (motion & PIXART_PAT9125_VALID_MOTION_DATA);
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t pat9125_suspend_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct pixart_pat9125_data *data =
+ (struct pixart_pat9125_data *) dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int mode;
+
+ if (kstrtoint(buf, 10, &mode)) {
+ dev_err(dev, "failed to read input for sysfs\n");
+ return -EINVAL;
+ }
+
+ if (mode == 1)
+ pat9125_suspend(&client->dev);
+ else if (mode == 0)
+ pat9125_resume(&client->dev);
+
+ return count;
+}
+
+static ssize_t pat9125_test_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ char s[256], *p = s;
+ int reg_data = 0, i;
+ long rd_addr, wr_addr, wr_data;
+ struct pixart_pat9125_data *data =
+ (struct pixart_pat9125_data *) dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+
+ for (i = 0; i < sizeof(s); i++)
+ s[i] = buf[i];
+ *(s+1) = '\0';
+ *(s+4) = '\0';
+ *(s+7) = '\0';
+ /* example(in console): echo w 12 34 > rw_reg */
+ if (*p == 'w') {
+ p += 2;
+ if (!kstrtol(p, 16, &wr_addr)) {
+ p += 3;
+ if (!kstrtol(p, 16, &wr_data)) {
+ dev_dbg(dev, "w 0x%x 0x%x\n",
+ (u8)wr_addr, (u8)wr_data);
+ write_data(client, (u8)wr_addr, (u8)wr_data);
+ }
+ }
+ }
+ /* example(in console): echo r 12 > rw_reg */
+ else if (*p == 'r') {
+ p += 2;
+
+ if (!kstrtol(p, 16, &rd_addr)) {
+ reg_data = read_data(client, (u8)rd_addr);
+ dev_dbg(dev, "r 0x%x 0x%x\n",
+ (unsigned int)rd_addr, reg_data);
+ }
+ }
+ return count;
+}
+
+static ssize_t pat9125_test_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return 0;
+}
+
+static DEVICE_ATTR(suspend, S_IRUGO | S_IWUSR | S_IWGRP,
+ NULL, pat9125_suspend_store);
+static DEVICE_ATTR(test, S_IRUGO | S_IWUSR | S_IWGRP,
+ pat9125_test_show, pat9125_test_store);
+
+static struct attribute *pat9125_attr_list[] = {
+ &dev_attr_test.attr,
+ &dev_attr_suspend.attr,
+ NULL,
+};
+
+static struct attribute_group pat9125_attr_grp = {
+ .attrs = pat9125_attr_list,
+};
+
+static int pixart_pinctrl_init(struct pixart_pat9125_data *data)
+{
+ int err;
+ struct device *dev = &data->client->dev;
+
+ data->pinctrl = devm_pinctrl_get(&(data->client->dev));
+ if (IS_ERR_OR_NULL(data->pinctrl)) {
+ err = PTR_ERR(data->pinctrl);
+ dev_err(dev, "Target does not use pinctrl %d\n", err);
+ return err;
+ }
+
+ data->pinctrl_state_active = pinctrl_lookup_state(data->pinctrl,
+ PINCTRL_STATE_ACTIVE);
+ if (IS_ERR_OR_NULL(data->pinctrl_state_active)) {
+ err = PTR_ERR(data->pinctrl_state_active);
+ dev_err(dev, "Can not lookup active pinctrl state %d\n", err);
+ return err;
+ }
+
+ data->pinctrl_state_suspend = pinctrl_lookup_state(data->pinctrl,
+ PINCTRL_STATE_SUSPEND);
+ if (IS_ERR_OR_NULL(data->pinctrl_state_suspend)) {
+ err = PTR_ERR(data->pinctrl_state_suspend);
+ dev_err(dev, "Can not lookup suspend pinctrl state %d\n", err);
+ return err;
+ }
+
+ data->pinctrl_state_release = pinctrl_lookup_state(data->pinctrl,
+ PINCTRL_STATE_RELEASE);
+ if (IS_ERR_OR_NULL(data->pinctrl_state_release)) {
+ err = PTR_ERR(data->pinctrl_state_release);
+ dev_err(dev, "Can not lookup release pinctrl state %d\n", err);
+ return err;
+ }
+ return 0;
+}
+
+static int pat9125_regulator_init(struct pixart_pat9125_data *data)
+{
+ int err = 0;
+ struct device *dev = &data->client->dev;
+
+ data->vdd = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(data->vdd)) {
+ dev_err(dev, "Failed to get regulator vdd %ld\n",
+ PTR_ERR(data->vdd));
+ return PTR_ERR(data->vdd);
+ }
+
+ data->vld = devm_regulator_get(dev, "vld");
+ if (IS_ERR(data->vld)) {
+ dev_err(dev, "Failed to get regulator vld %ld\n",
+ PTR_ERR(data->vld));
+ return PTR_ERR(data->vld);
+ }
+
+ err = regulator_set_voltage(data->vdd, VDD_VTG_MIN_UV, VDD_VTG_MAX_UV);
+ if (err) {
+ dev_err(dev, "Failed to set voltage for vdd reg %d\n", err);
+ return err;
+ }
+
+ err = regulator_set_load(data->vdd, VDD_ACTIVE_LOAD_UA);
+ if (err < 0) {
+ dev_err(dev, "Failed to set opt mode for vdd reg %d\n", err);
+ return err;
+ }
+
+ err = regulator_set_voltage(data->vld, VLD_VTG_MIN_UV, VLD_VTG_MAX_UV);
+ if (err) {
+ dev_err(dev, "Failed to set voltage for vld reg %d\n", err);
+ return err;
+ }
+
+ err = regulator_set_load(data->vld, VLD_ACTIVE_LOAD_UA);
+ if (err < 0) {
+ dev_err(dev, "Failed to set opt mode for vld reg %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int pat9125_power_on(struct pixart_pat9125_data *data, bool on)
+{
+ int err = 0;
+ struct device *dev = &data->client->dev;
+
+ if (on) {
+ err = regulator_enable(data->vdd);
+ if (err) {
+ dev_err(dev, "Failed to enable vdd reg %d\n", err);
+ return err;
+ }
+
+ usleep_range(DELAY_BETWEEN_REG_US, DELAY_BETWEEN_REG_US + 1);
+
+ /*
+ * Initialize pixart sensor after some delay, when vdd
+ * regulator is enabled
+ */
+ if (!ots_sensor_init(data->client)) {
+ err = -ENODEV;
+ dev_err(dev, "Failed to initialize sensor %d\n", err);
+ return err;
+ }
+
+ err = regulator_enable(data->vld);
+ if (err) {
+ dev_err(dev, "Failed to enable vld reg %d\n", err);
+ return err;
+ }
+ } else {
+ err = regulator_disable(data->vld);
+ if (err) {
+ dev_err(dev, "Failed to disable vld reg %d\n", err);
+ return err;
+ }
+
+ err = regulator_disable(data->vdd);
+ if (err) {
+ dev_err(dev, "Failed to disable vdd reg %d\n", err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int pat9125_parse_dt(struct device *dev,
+ struct pixart_pat9125_data *data)
+{
+ struct device_node *np = dev->of_node;
+ u32 temp_val;
+ int ret;
+
+ data->inverse_x = of_property_read_bool(np, "pixart,inverse-x");
+ data->inverse_y = of_property_read_bool(np, "pixart,inverse-y");
+ data->press_en = of_property_read_bool(np, "pixart,press-enabled");
+ if (data->press_en) {
+ ret = of_property_read_u32(np, "pixart,press-keycode",
+ &temp_val);
+ if (!ret) {
+ data->press_keycode = temp_val;
+ } else {
+ dev_err(dev, "Unable to parse press-keycode\n");
+ return ret;
+ }
+ }
+
+ data->irq_gpio = of_get_named_gpio_flags(np, "pixart,irq-gpio",
+ 0, NULL);
+
+ return 0;
+}
+
+static int pat9125_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct pixart_pat9125_data *data;
+ struct input_dev *input;
+ struct device *dev = &client->dev;
+
+ err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE);
+ if (err < 0) {
+ dev_err(dev, "I2C not supported\n");
+ return -ENXIO;
+ }
+
+ if (client->dev.of_node) {
+ data = devm_kzalloc(dev, sizeof(struct pixart_pat9125_data),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ err = pat9125_parse_dt(dev, data);
+ if (err) {
+ dev_err(dev, "DT parsing failed, errno:%d\n", err);
+ return err;
+ }
+ } else {
+ data = client->dev.platform_data;
+ if (!data) {
+ dev_err(dev, "Invalid pat9125 data\n");
+ return -EINVAL;
+ }
+ }
+ data->client = client;
+
+ input = devm_input_allocate_device(dev);
+ if (!input) {
+ dev_err(dev, "Failed to alloc input device\n");
+ return -ENOMEM;
+ }
+
+ input_set_capability(input, EV_REL, REL_WHEEL);
+ if (data->press_en)
+ input_set_capability(input, EV_KEY, data->press_keycode);
+
+ i2c_set_clientdata(client, data);
+ input_set_drvdata(input, data);
+ input->name = PAT9125_DEV_NAME;
+
+ data->input = input;
+ err = input_register_device(data->input);
+ if (err < 0) {
+ dev_err(dev, "Failed to register input device\n");
+ return err;
+ }
+
+ err = pixart_pinctrl_init(data);
+ if (!err && data->pinctrl) {
+ /*
+ * Pinctrl handle is optional. If pinctrl handle is found
+ * let pins to be configured in active state. If not
+ * found continue further without error.
+ */
+ err = pinctrl_select_state(data->pinctrl,
+ data->pinctrl_state_active);
+ if (err < 0)
+ dev_err(dev, "Could not set pin to active state %d\n",
+ err);
+ } else {
+ if (gpio_is_valid(data->irq_gpio)) {
+ err = devm_gpio_request(dev, data->irq_gpio,
+ "pixart_pat9125_irq_gpio");
+ if (err) {
+ dev_err(dev, "Couldn't request gpio %d\n", err);
+ return err;
+ }
+ err = gpio_direction_input(data->irq_gpio);
+ if (err) {
+ dev_err(dev, "Couldn't set dir for gpio %d\n",
+ err);
+ return err;
+ }
+ } else {
+ dev_err(dev, "Invalid gpio %d\n", data->irq_gpio);
+ return -EINVAL;
+ }
+ }
+
+ err = pat9125_regulator_init(data);
+ if (err) {
+ dev_err(dev, "Failed to init regulator, %d\n", err);
+ return err;
+ }
+
+ err = pat9125_power_on(data, true);
+ if (err) {
+ dev_err(dev, "Failed to power-on the sensor %d\n", err);
+ goto err_power_on;
+ }
+
+ err = devm_request_threaded_irq(dev, client->irq, NULL, pat9125_irq,
+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW,
+ "pixart_pat9125_irq", data);
+ if (err) {
+ dev_err(dev, "Req irq %d failed, errno:%d\n", client->irq, err);
+ goto err_request_threaded_irq;
+ }
+
+ err = sysfs_create_group(&(input->dev.kobj), &pat9125_attr_grp);
+ if (err) {
+ dev_err(dev, "Failed to create sysfs group, errno:%d\n", err);
+ goto err_sysfs_create;
+ }
+
+ return 0;
+
+err_sysfs_create:
+err_request_threaded_irq:
+err_power_on:
+ regulator_set_load(data->vdd, 0);
+ regulator_set_load(data->vld, 0);
+ if (pat9125_power_on(data, false) < 0)
+ dev_err(dev, "Failed to disable regulators\n");
+ if (data->pinctrl)
+ if (pinctrl_select_state(data->pinctrl,
+ data->pinctrl_state_release) < 0)
+ dev_err(dev, "Couldn't set pin to release state\n");
+
+ return err;
+}
+
+static int pat9125_i2c_remove(struct i2c_client *client)
+{
+ struct pixart_pat9125_data *data = i2c_get_clientdata(client);
+ struct device *dev = &data->client->dev;
+
+ sysfs_remove_group(&(data->input->dev.kobj), &pat9125_attr_grp);
+ if (data->pinctrl)
+ if (pinctrl_select_state(data->pinctrl,
+ data->pinctrl_state_release) < 0)
+ dev_err(dev, "Couldn't set pin to release state\n");
+ regulator_set_load(data->vdd, 0);
+ regulator_set_load(data->vld, 0);
+ pat9125_power_on(data, false);
+ return 0;
+}
+
+static int pat9125_suspend(struct device *dev)
+{
+ int rc;
+ struct pixart_pat9125_data *data =
+ (struct pixart_pat9125_data *) dev_get_drvdata(dev);
+
+ disable_irq(data->client->irq);
+ if (data->pinctrl) {
+ rc = pinctrl_select_state(data->pinctrl,
+ data->pinctrl_state_suspend);
+ if (rc < 0)
+ dev_err(dev, "Could not set pin to suspend state %d\n",
+ rc);
+ }
+
+ rc = pat9125_power_on(data, false);
+ if (rc) {
+ dev_err(dev, "Failed to disable regulators %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int pat9125_resume(struct device *dev)
+{
+ int rc;
+ struct pixart_pat9125_data *data =
+ (struct pixart_pat9125_data *) dev_get_drvdata(dev);
+
+ if (data->pinctrl) {
+ rc = pinctrl_select_state(data->pinctrl,
+ data->pinctrl_state_active);
+ if (rc < 0)
+ dev_err(dev, "Could not set pin to active state %d\n",
+ rc);
+ }
+
+ rc = pat9125_power_on(data, true);
+ if (rc) {
+ dev_err(dev, "Failed to power-on the sensor %d\n", rc);
+ goto err_sensor_init;
+ }
+
+ enable_irq(data->client->irq);
+
+ return 0;
+
+err_sensor_init:
+ if (data->pinctrl)
+ if (pinctrl_select_state(data->pinctrl,
+ data->pinctrl_state_suspend) < 0)
+ dev_err(dev, "Couldn't set pin to suspend state\n");
+ if (pat9125_power_on(data, false) < 0)
+ dev_err(dev, "Failed to disable regulators\n");
+
+ return rc;
+}
+
+static const struct i2c_device_id pat9125_device_id[] = {
+ {PAT9125_DEV_NAME, 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, pat9125_device_id);
+
+static const struct dev_pm_ops pat9125_pm_ops = {
+ .suspend = pat9125_suspend,
+ .resume = pat9125_resume
+};
+
+static const struct of_device_id pixart_pat9125_match_table[] = {
+ { .compatible = "pixart,pat9125",},
+ { },
+};
+
+static struct i2c_driver pat9125_i2c_driver = {
+ .driver = {
+ .name = PAT9125_DEV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &pat9125_pm_ops,
+ .of_match_table = pixart_pat9125_match_table,
+ },
+ .probe = pat9125_i2c_probe,
+ .remove = pat9125_i2c_remove,
+ .id_table = pat9125_device_id,
+};
+module_i2c_driver(pat9125_i2c_driver);
+
+MODULE_AUTHOR("pixart");
+MODULE_DESCRIPTION("pixart pat9125 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/ots_pat9125/pixart_ots.c b/drivers/input/misc/ots_pat9125/pixart_ots.c
new file mode 100644
index 000000000000..3d44d068423a
--- /dev/null
+++ b/drivers/input/misc/ots_pat9125/pixart_ots.c
@@ -0,0 +1,78 @@
+/* drivers/input/misc/ots_pat9125/pixart_ots.c
+ *
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include "pixart_platform.h"
+#include "pixart_ots.h"
+
+static void ots_write_read(struct i2c_client *client, u8 address, u8 wdata)
+{
+ u8 read_value;
+
+ do {
+ write_data(client, address, wdata);
+ read_value = read_data(client, address);
+ } while (read_value != wdata);
+}
+
+bool ots_sensor_init(struct i2c_client *client)
+{
+ u8 sensor_pid = 0;
+ bool read_id_ok = false;
+
+ /*
+ * Read sensor_pid in address 0x00 to check if the
+ * serial link is valid, read value should be 0x31.
+ */
+ sensor_pid = read_data(client, PIXART_PAT9125_PRODUCT_ID1_REG);
+
+ if (sensor_pid == PIXART_PAT9125_SENSOR_ID) {
+ read_id_ok = true;
+
+ /*
+ * PAT9125 sensor recommended settings:
+ * switch to bank0, not allowed to perform ots_write_read
+ */
+ write_data(client, PIXART_PAT9125_SELECT_BANK_REG,
+ PIXART_PAT9125_BANK0);
+ /*
+ * software reset (i.e. set bit7 to 1).
+ * It will reset to 0 automatically
+ * so perform OTS_RegWriteRead is not allowed.
+ */
+ write_data(client, PIXART_PAT9125_CONFIG_REG,
+ PIXART_PAT9125_RESET);
+
+ /* delay 1ms */
+ usleep_range(RESET_DELAY_US, RESET_DELAY_US + 1);
+
+ /* disable write protect */
+ ots_write_read(client, PIXART_PAT9125_WRITE_PROTECT_REG,
+ PIXART_PAT9125_DISABLE_WRITE_PROTECT);
+ /* set X-axis resolution (depends on application) */
+ ots_write_read(client, PIXART_PAT9125_SET_CPI_RES_X_REG,
+ PIXART_PAT9125_CPI_RESOLUTION_X);
+ /* set Y-axis resolution (depends on application) */
+ ots_write_read(client, PIXART_PAT9125_SET_CPI_RES_Y_REG,
+ PIXART_PAT9125_CPI_RESOLUTION_Y);
+ /* set 12-bit X/Y data format (depends on application) */
+ ots_write_read(client, PIXART_PAT9125_ORIENTATION_REG,
+ PIXART_PAT9125_MOTION_DATA_LENGTH);
+ /* ONLY for VDD=VDDA=1.7~1.9V: for power saving */
+ ots_write_read(client, PIXART_PAT9125_VOLTAGE_SEGMENT_SEL_REG,
+ PIXART_PAT9125_LOW_VOLTAGE_SEGMENT);
+
+ if (read_data(client, PIXART_PAT9125_MISC2_REG) == 0x04) {
+ ots_write_read(client, PIXART_PAT9125_MISC2_REG, 0x08);
+ if (read_data(client, PIXART_PAT9125_MISC1_REG) == 0x10)
+ ots_write_read(client, PIXART_PAT9125_MISC1_REG,
+ 0x19);
+ }
+ /* enable write protect */
+ ots_write_read(client, PIXART_PAT9125_WRITE_PROTECT_REG,
+ PIXART_PAT9125_ENABLE_WRITE_PROTECT);
+ }
+ return read_id_ok;
+}
diff --git a/drivers/input/misc/ots_pat9125/pixart_ots.h b/drivers/input/misc/ots_pat9125/pixart_ots.h
new file mode 100644
index 000000000000..5320d588d341
--- /dev/null
+++ b/drivers/input/misc/ots_pat9125/pixart_ots.h
@@ -0,0 +1,58 @@
+/* drivers/input/misc/ots_pat9125/pixart_ots.h
+ *
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#ifndef __PIXART_OTS_H_
+#define __PIXART_OTS_H_
+
+#define PAT9125_DEV_NAME "pixart_pat9125"
+#define MAX_BUF_SIZE 20
+#define RESET_DELAY_US 1000
+#define PINCTRL_STATE_ACTIVE "pmx_rot_switch_active"
+#define PINCTRL_STATE_SUSPEND "pmx_rot_switch_suspend"
+#define PINCTRL_STATE_RELEASE "pmx_rot_switch_release"
+#define VDD_VTG_MIN_UV 1800000
+#define VDD_VTG_MAX_UV 1800000
+#define VDD_ACTIVE_LOAD_UA 10000
+#define VLD_VTG_MIN_UV 2800000
+#define VLD_VTG_MAX_UV 3300000
+#define VLD_ACTIVE_LOAD_UA 10000
+#define DELAY_BETWEEN_REG_US 20000
+
+/* Register addresses */
+#define PIXART_PAT9125_PRODUCT_ID1_REG 0x00
+#define PIXART_PAT9125_PRODUCT_ID2_REG 0x01
+#define PIXART_PAT9125_MOTION_STATUS_REG 0x02
+#define PIXART_PAT9125_DELTA_X_LO_REG 0x03
+#define PIXART_PAT9125_DELTA_Y_LO_REG 0x04
+#define PIXART_PAT9125_CONFIG_REG 0x06
+#define PIXART_PAT9125_WRITE_PROTECT_REG 0x09
+#define PIXART_PAT9125_SET_CPI_RES_X_REG 0x0D
+#define PIXART_PAT9125_SET_CPI_RES_Y_REG 0x0E
+#define PIXART_PAT9125_DELTA_XY_HI_REG 0x12
+#define PIXART_PAT9125_ORIENTATION_REG 0x19
+#define PIXART_PAT9125_VOLTAGE_SEGMENT_SEL_REG 0x4B
+#define PIXART_PAT9125_SELECT_BANK_REG 0x7F
+#define PIXART_PAT9125_MISC1_REG 0x5D
+#define PIXART_PAT9125_MISC2_REG 0x5E
+/*Register configuration data */
+#define PIXART_PAT9125_SENSOR_ID 0x31
+#define PIXART_PAT9125_RESET 0x97
+#define PIXART_PAT9125_MOTION_DATA_LENGTH 0x04
+#define PIXART_PAT9125_BANK0 0x00
+#define PIXART_PAT9125_DISABLE_WRITE_PROTECT 0x5A
+#define PIXART_PAT9125_ENABLE_WRITE_PROTECT 0x00
+#define PIXART_PAT9125_CPI_RESOLUTION_X 0x65
+#define PIXART_PAT9125_CPI_RESOLUTION_Y 0xFF
+#define PIXART_PAT9125_LOW_VOLTAGE_SEGMENT 0x04
+#define PIXART_PAT9125_VALID_MOTION_DATA 0x80
+
+#define PIXART_SAMPLING_PERIOD_US_MIN 4000
+#define PIXART_SAMPLING_PERIOD_US_MAX 8000
+
+/* Export functions */
+bool ots_sensor_init(struct i2c_client *);
+
+#endif
diff --git a/drivers/input/misc/ots_pat9125/pixart_platform.h b/drivers/input/misc/ots_pat9125/pixart_platform.h
new file mode 100644
index 000000000000..1fe448fdc2cb
--- /dev/null
+++ b/drivers/input/misc/ots_pat9125/pixart_platform.h
@@ -0,0 +1,17 @@
+/* drivers/input/misc/ots_pat9125/pixart_platform.h
+ *
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#ifndef __PIXART_PLATFORM_H_
+#define __PIXART_PLATFORM_H_
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+
+/* extern functions */
+extern unsigned char read_data(struct i2c_client *, u8 addr);
+extern void write_data(struct i2c_client *, u8 addr, u8 data);
+
+#endif
diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c
new file mode 100644
index 000000000000..339f94c072f4
--- /dev/null
+++ b/drivers/input/misc/qpnp-power-on.c
@@ -0,0 +1,2413 @@
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/input.h>
+#include <linux/log2.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/input/qpnp-power-on.h>
+#include <linux/power_supply.h>
+
+#define PMIC_VER_8941 0x01
+#define PMIC_VERSION_REG 0x0105
+#define PMIC_VERSION_REV4_REG 0x0103
+
+#define PMIC8941_V1_REV4 0x01
+#define PMIC8941_V2_REV4 0x02
+#define PON_PRIMARY 0x01
+#define PON_SECONDARY 0x02
+#define PON_1REG 0x03
+#define PON_GEN2_PRIMARY 0x04
+#define PON_GEN2_SECONDARY 0x05
+
+#define PON_OFFSET(subtype, offset_gen1, offset_gen2) \
+ (((subtype == PON_PRIMARY) || \
+ (subtype == PON_SECONDARY) || \
+ (subtype == PON_1REG)) ? offset_gen1 : offset_gen2)
+
+/* Common PNP defines */
+#define QPNP_PON_REVISION2(pon) ((pon)->base + 0x01)
+#define QPNP_PON_PERPH_SUBTYPE(pon) ((pon)->base + 0x05)
+
+/* PON common register addresses */
+#define QPNP_PON_RT_STS(pon) ((pon)->base + 0x10)
+#define QPNP_PON_PULL_CTL(pon) ((pon)->base + 0x70)
+#define QPNP_PON_DBC_CTL(pon) ((pon)->base + 0x71)
+
+/* PON/RESET sources register addresses */
+#define QPNP_PON_REASON1(pon) \
+ ((pon)->base + PON_OFFSET((pon)->subtype, 0x8, 0xC0))
+#define QPNP_PON_WARM_RESET_REASON1(pon) \
+ ((pon)->base + PON_OFFSET((pon)->subtype, 0xA, 0xC2))
+#define QPNP_POFF_REASON1(pon) \
+ ((pon)->base + PON_OFFSET((pon)->subtype, 0xC, 0xC5))
+#define QPNP_PON_WARM_RESET_REASON2(pon) ((pon)->base + 0xB)
+#define QPNP_PON_OFF_REASON(pon) ((pon)->base + 0xC7)
+#define QPNP_FAULT_REASON1(pon) ((pon)->base + 0xC8)
+#define QPNP_S3_RESET_REASON(pon) ((pon)->base + 0xCA)
+#define QPNP_PON_KPDPWR_S1_TIMER(pon) ((pon)->base + 0x40)
+#define QPNP_PON_KPDPWR_S2_TIMER(pon) ((pon)->base + 0x41)
+#define QPNP_PON_KPDPWR_S2_CNTL(pon) ((pon)->base + 0x42)
+#define QPNP_PON_KPDPWR_S2_CNTL2(pon) ((pon)->base + 0x43)
+#define QPNP_PON_RESIN_S1_TIMER(pon) ((pon)->base + 0x44)
+#define QPNP_PON_RESIN_S2_TIMER(pon) ((pon)->base + 0x45)
+#define QPNP_PON_RESIN_S2_CNTL(pon) ((pon)->base + 0x46)
+#define QPNP_PON_RESIN_S2_CNTL2(pon) ((pon)->base + 0x47)
+#define QPNP_PON_KPDPWR_RESIN_S1_TIMER(pon) ((pon)->base + 0x48)
+#define QPNP_PON_KPDPWR_RESIN_S2_TIMER(pon) ((pon)->base + 0x49)
+#define QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon) ((pon)->base + 0x4A)
+#define QPNP_PON_KPDPWR_RESIN_S2_CNTL2(pon) ((pon)->base + 0x4B)
+#define QPNP_PON_PS_HOLD_RST_CTL(pon) ((pon)->base + 0x5A)
+#define QPNP_PON_PS_HOLD_RST_CTL2(pon) ((pon)->base + 0x5B)
+#define QPNP_PON_WD_RST_S2_CTL(pon) ((pon)->base + 0x56)
+#define QPNP_PON_WD_RST_S2_CTL2(pon) ((pon)->base + 0x57)
+#define QPNP_PON_S3_SRC(pon) ((pon)->base + 0x74)
+#define QPNP_PON_S3_DBC_CTL(pon) ((pon)->base + 0x75)
+#define QPNP_PON_SMPL_CTL(pon) ((pon)->base + 0x7F)
+#define QPNP_PON_TRIGGER_EN(pon) ((pon)->base + 0x80)
+#define QPNP_PON_XVDD_RB_SPARE(pon) ((pon)->base + 0x8E)
+#define QPNP_PON_SOFT_RB_SPARE(pon) ((pon)->base + 0x8F)
+#define QPNP_PON_SEC_ACCESS(pon) ((pon)->base + 0xD0)
+
+#define QPNP_PON_SEC_UNLOCK 0xA5
+
+#define QPNP_PON_WARM_RESET_TFT BIT(4)
+
+#define QPNP_PON_RESIN_PULL_UP BIT(0)
+#define QPNP_PON_KPDPWR_PULL_UP BIT(1)
+#define QPNP_PON_CBLPWR_PULL_UP BIT(2)
+#define QPNP_PON_FAULT_PULL_UP BIT(4)
+#define QPNP_PON_S2_CNTL_EN BIT(7)
+#define QPNP_PON_S2_RESET_ENABLE BIT(7)
+#define QPNP_PON_DELAY_BIT_SHIFT 6
+#define QPNP_PON_GEN2_DELAY_BIT_SHIFT 14
+
+#define QPNP_PON_S1_TIMER_MASK (0xF)
+#define QPNP_PON_S2_TIMER_MASK (0x7)
+#define QPNP_PON_S2_CNTL_TYPE_MASK (0xF)
+
+#define QPNP_PON_DBC_DELAY_MASK(pon) \
+ PON_OFFSET((pon)->subtype, 0x7, 0xF)
+
+#define QPNP_PON_KPDPWR_N_SET BIT(0)
+#define QPNP_PON_RESIN_N_SET BIT(1)
+#define QPNP_PON_CBLPWR_N_SET BIT(2)
+#define QPNP_PON_RESIN_BARK_N_SET BIT(4)
+#define QPNP_PON_KPDPWR_RESIN_BARK_N_SET BIT(5)
+
+#define QPNP_PON_WD_EN BIT(7)
+#define QPNP_PON_RESET_EN BIT(7)
+#define QPNP_PON_POWER_OFF_MASK 0xF
+#define QPNP_GEN2_POFF_SEQ BIT(7)
+#define QPNP_GEN2_FAULT_SEQ BIT(6)
+#define QPNP_GEN2_S3_RESET_SEQ BIT(5)
+
+#define QPNP_PON_S3_SRC_KPDPWR 0
+#define QPNP_PON_S3_SRC_RESIN 1
+#define QPNP_PON_S3_SRC_KPDPWR_AND_RESIN 2
+#define QPNP_PON_S3_SRC_KPDPWR_OR_RESIN 3
+#define QPNP_PON_S3_SRC_MASK 0x3
+#define QPNP_PON_HARD_RESET_MASK GENMASK(7, 5)
+
+#define QPNP_PON_UVLO_DLOAD_EN BIT(7)
+#define QPNP_PON_SMPL_EN BIT(7)
+
+/* Ranges */
+#define QPNP_PON_S1_TIMER_MAX 10256
+#define QPNP_PON_S2_TIMER_MAX 2000
+#define QPNP_PON_S3_TIMER_SECS_MAX 128
+#define QPNP_PON_S3_DBC_DELAY_MASK 0x07
+#define QPNP_PON_RESET_TYPE_MAX 0xF
+#define PON_S1_COUNT_MAX 0xF
+#define QPNP_PON_MIN_DBC_US (USEC_PER_SEC / 64)
+#define QPNP_PON_MAX_DBC_US (USEC_PER_SEC * 2)
+#define QPNP_PON_GEN2_MIN_DBC_US 62
+#define QPNP_PON_GEN2_MAX_DBC_US (USEC_PER_SEC / 4)
+
+#define QPNP_KEY_STATUS_DELAY msecs_to_jiffies(250)
+
+#define QPNP_PON_BUFFER_SIZE 9
+
+#define QPNP_POFF_REASON_UVLO 13
+
+enum qpnp_pon_version {
+ QPNP_PON_GEN1_V1,
+ QPNP_PON_GEN1_V2,
+ QPNP_PON_GEN2,
+};
+
+enum pon_type {
+ PON_KPDPWR,
+ PON_RESIN,
+ PON_CBLPWR,
+ PON_KPDPWR_RESIN,
+};
+
+struct qpnp_pon_config {
+ u32 pon_type;
+ u32 support_reset;
+ u32 key_code;
+ u32 s1_timer;
+ u32 s2_timer;
+ u32 s2_type;
+ u32 pull_up;
+ u32 state_irq;
+ u32 bark_irq;
+ u16 s2_cntl_addr;
+ u16 s2_cntl2_addr;
+ bool old_state;
+ bool use_bark;
+ bool config_reset;
+};
+
+struct pon_regulator {
+ struct qpnp_pon *pon;
+ struct regulator_dev *rdev;
+ struct regulator_desc rdesc;
+ u32 addr;
+ u32 bit;
+ bool enabled;
+};
+
+struct qpnp_pon {
+ struct platform_device *pdev;
+ struct regmap *regmap;
+ struct input_dev *pon_input;
+ struct qpnp_pon_config *pon_cfg;
+ struct pon_regulator *pon_reg_cfg;
+ struct list_head list;
+ struct delayed_work bark_work;
+ struct dentry *debugfs;
+ int pon_trigger_reason;
+ int pon_power_off_reason;
+ int num_pon_reg;
+ int num_pon_config;
+ u32 dbc_time_us;
+ u32 uvlo;
+ int warm_reset_poff_type;
+ int hard_reset_poff_type;
+ int shutdown_poff_type;
+ u16 base;
+ u8 subtype;
+ u8 pon_ver;
+ u8 warm_reset_reason1;
+ u8 warm_reset_reason2;
+ bool is_spon;
+ bool store_hard_reset_reason;
+ bool kpdpwr_dbc_enable;
+ ktime_t kpdpwr_last_release_time;
+};
+
+static int pon_ship_mode_en;
+module_param_named(
+ ship_mode_en, pon_ship_mode_en, int, 0600
+);
+
+static struct qpnp_pon *sys_reset_dev;
+static DEFINE_SPINLOCK(spon_list_slock);
+static LIST_HEAD(spon_dev_list);
+
+static u32 s1_delay[PON_S1_COUNT_MAX + 1] = {
+ 0, 32, 56, 80, 138, 184, 272, 408, 608, 904, 1352, 2048,
+ 3072, 4480, 6720, 10256
+};
+
+static const char * const qpnp_pon_reason[] = {
+ [0] = "Triggered from Hard Reset",
+ [1] = "Triggered from SMPL (sudden momentary power loss)",
+ [2] = "Triggered from RTC (RTC alarm expiry)",
+ [3] = "Triggered from DC (DC charger insertion)",
+ [4] = "Triggered from USB (USB charger insertion)",
+ [5] = "Triggered from PON1 (secondary PMIC)",
+ [6] = "Triggered from CBL (external power supply)",
+ [7] = "Triggered from KPD (power key press)",
+};
+
+#define POFF_REASON_FAULT_OFFSET 16
+#define POFF_REASON_S3_RESET_OFFSET 32
+static const char * const qpnp_poff_reason[] = {
+ /* QPNP_PON_GEN1 POFF reasons */
+ [0] = "Triggered from SOFT (Software)",
+ [1] = "Triggered from PS_HOLD (PS_HOLD/MSM controlled shutdown)",
+ [2] = "Triggered from PMIC_WD (PMIC watchdog)",
+ [3] = "Triggered from GP1 (Keypad_Reset1)",
+ [4] = "Triggered from GP2 (Keypad_Reset2)",
+ [5] = "Triggered from KPDPWR_AND_RESIN (Simultaneous power key and reset line)",
+ [6] = "Triggered from RESIN_N (Reset line/Volume Down Key)",
+ [7] = "Triggered from KPDPWR_N (Long Power Key hold)",
+ [8] = "N/A",
+ [9] = "N/A",
+ [10] = "N/A",
+ [11] = "Triggered from CHARGER (Charger ENUM_TIMER, BOOT_DONE)",
+ [12] = "Triggered from TFT (Thermal Fault Tolerance)",
+ [13] = "Triggered from UVLO (Under Voltage Lock Out)",
+ [14] = "Triggered from OTST3 (Overtemp)",
+ [15] = "Triggered from STAGE3 (Stage 3 reset)",
+
+ /* QPNP_PON_GEN2 FAULT reasons */
+ [16] = "Triggered from GP_FAULT0",
+ [17] = "Triggered from GP_FAULT1",
+ [18] = "Triggered from GP_FAULT2",
+ [19] = "Triggered from GP_FAULT3",
+ [20] = "Triggered from MBG_FAULT",
+ [21] = "Triggered from OVLO (Over Voltage Lock Out)",
+ [22] = "Triggered from UVLO (Under Voltage Lock Out)",
+ [23] = "Triggered from AVDD_RB",
+ [24] = "N/A",
+ [25] = "N/A",
+ [26] = "N/A",
+ [27] = "Triggered from FAULT_FAULT_N",
+ [28] = "Triggered from FAULT_PBS_WATCHDOG_TO",
+ [29] = "Triggered from FAULT_PBS_NACK",
+ [30] = "Triggered from FAULT_RESTART_PON",
+ [31] = "Triggered from OTST3 (Overtemp)",
+
+ /* QPNP_PON_GEN2 S3_RESET reasons */
+ [32] = "N/A",
+ [33] = "N/A",
+ [34] = "N/A",
+ [35] = "N/A",
+ [36] = "Triggered from S3_RESET_FAULT_N",
+ [37] = "Triggered from S3_RESET_PBS_WATCHDOG_TO",
+ [38] = "Triggered from S3_RESET_PBS_NACK",
+ [39] = "Triggered from S3_RESET_KPDPWR_ANDOR_RESIN (power key and/or reset line)",
+};
+
+static int
+qpnp_pon_masked_write(struct qpnp_pon *pon, u16 addr, u8 mask, u8 val)
+{
+ int rc;
+
+ rc = regmap_update_bits(pon->regmap, addr, mask, val);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to regmap_update_bits to addr=%hx, rc(%d)\n",
+ addr, rc);
+ return rc;
+}
+
+static bool is_pon_gen1(struct qpnp_pon *pon)
+{
+ return pon->subtype == PON_PRIMARY ||
+ pon->subtype == PON_SECONDARY;
+}
+
+static bool is_pon_gen2(struct qpnp_pon *pon)
+{
+ return pon->subtype == PON_GEN2_PRIMARY ||
+ pon->subtype == PON_GEN2_SECONDARY;
+}
+
+/**
+ * qpnp_pon_set_restart_reason - Store device restart reason in PMIC register.
+ *
+ * Returns = 0 if PMIC feature is not available or store restart reason
+ * successfully.
+ * Returns > 0 for errors
+ *
+ * This function is used to store device restart reason in PMIC register.
+ * It checks here to see if the restart reason register has been specified.
+ * If it hasn't, this function should immediately return 0
+ */
+int qpnp_pon_set_restart_reason(enum pon_restart_reason reason)
+{
+ int rc = 0;
+ struct qpnp_pon *pon = sys_reset_dev;
+
+ if (!pon)
+ return 0;
+
+ if (!pon->store_hard_reset_reason)
+ return 0;
+
+ if (is_pon_gen2(pon))
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_SOFT_RB_SPARE(pon),
+ GENMASK(7, 1), (reason << 1));
+ else
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_SOFT_RB_SPARE(pon),
+ GENMASK(7, 2), (reason << 2));
+
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_SOFT_RB_SPARE(pon), rc);
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_pon_set_restart_reason);
+
+/*
+ * qpnp_pon_check_hard_reset_stored - Checks if the PMIC need to
+ * store hard reset reason.
+ *
+ * Returns true if reset reason can be stored, false if it cannot be stored
+ *
+ */
+bool qpnp_pon_check_hard_reset_stored(void)
+{
+ struct qpnp_pon *pon = sys_reset_dev;
+
+ if (!pon)
+ return false;
+
+ return pon->store_hard_reset_reason;
+}
+EXPORT_SYMBOL(qpnp_pon_check_hard_reset_stored);
+
+static int qpnp_pon_set_dbc(struct qpnp_pon *pon, u32 delay)
+{
+ int rc = 0;
+ u32 val;
+
+ if (delay == pon->dbc_time_us)
+ goto out;
+
+ if (pon->pon_input)
+ mutex_lock(&pon->pon_input->mutex);
+
+ if (is_pon_gen2(pon)) {
+ if (delay < QPNP_PON_GEN2_MIN_DBC_US)
+ delay = QPNP_PON_GEN2_MIN_DBC_US;
+ else if (delay > QPNP_PON_GEN2_MAX_DBC_US)
+ delay = QPNP_PON_GEN2_MAX_DBC_US;
+ val = (delay << QPNP_PON_GEN2_DELAY_BIT_SHIFT) / USEC_PER_SEC;
+ } else {
+ if (delay < QPNP_PON_MIN_DBC_US)
+ delay = QPNP_PON_MIN_DBC_US;
+ else if (delay > QPNP_PON_MAX_DBC_US)
+ delay = QPNP_PON_MAX_DBC_US;
+ val = (delay << QPNP_PON_DELAY_BIT_SHIFT) / USEC_PER_SEC;
+ }
+
+ val = ilog2(val);
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_DBC_CTL(pon),
+ QPNP_PON_DBC_DELAY_MASK(pon), val);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to set PON debounce\n");
+ goto unlock;
+ }
+
+ pon->dbc_time_us = delay;
+
+unlock:
+ if (pon->pon_input)
+ mutex_unlock(&pon->pon_input->mutex);
+out:
+ return rc;
+}
+
+static int qpnp_pon_get_dbc(struct qpnp_pon *pon, u32 *delay)
+{
+ int rc;
+ unsigned int val;
+
+ rc = regmap_read(pon->regmap, QPNP_PON_DBC_CTL(pon), &val);
+ if (rc) {
+ pr_err("Unable to read pon_dbc_ctl rc=%d\n", rc);
+ return rc;
+ }
+ val &= QPNP_PON_DBC_DELAY_MASK(pon);
+
+ if (is_pon_gen2(pon))
+ *delay = USEC_PER_SEC /
+ (1 << (QPNP_PON_GEN2_DELAY_BIT_SHIFT - val));
+ else
+ *delay = USEC_PER_SEC /
+ (1 << (QPNP_PON_DELAY_BIT_SHIFT - val));
+
+ return rc;
+}
+
+static ssize_t qpnp_pon_dbc_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qpnp_pon *pon = dev_get_drvdata(dev);
+
+ return snprintf(buf, QPNP_PON_BUFFER_SIZE, "%d\n", pon->dbc_time_us);
+}
+
+static ssize_t qpnp_pon_dbc_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct qpnp_pon *pon = dev_get_drvdata(dev);
+ u32 value;
+ int rc;
+
+ if (size > QPNP_PON_BUFFER_SIZE)
+ return -EINVAL;
+
+ rc = kstrtou32(buf, 10, &value);
+ if (rc)
+ return rc;
+
+ rc = qpnp_pon_set_dbc(pon, value);
+ if (rc < 0)
+ return rc;
+
+ return size;
+}
+
+static DEVICE_ATTR(debounce_us, 0664, qpnp_pon_dbc_show, qpnp_pon_dbc_store);
+
+static int qpnp_pon_reset_config(struct qpnp_pon *pon,
+ enum pon_power_off_type type)
+{
+ int rc;
+ u16 rst_en_reg;
+
+ if (pon->pon_ver == QPNP_PON_GEN1_V1)
+ rst_en_reg = QPNP_PON_PS_HOLD_RST_CTL(pon);
+ else
+ rst_en_reg = QPNP_PON_PS_HOLD_RST_CTL2(pon);
+
+ /*
+ * Based on the poweroff type set for a PON device through device tree
+ * change the type being configured into PS_HOLD_RST_CTL.
+ */
+ switch (type) {
+ case PON_POWER_OFF_WARM_RESET:
+ if (pon->warm_reset_poff_type != -EINVAL)
+ type = pon->warm_reset_poff_type;
+ break;
+ case PON_POWER_OFF_HARD_RESET:
+ if (pon->hard_reset_poff_type != -EINVAL)
+ type = pon->hard_reset_poff_type;
+ break;
+ case PON_POWER_OFF_SHUTDOWN:
+ if (pon->shutdown_poff_type != -EINVAL)
+ type = pon->shutdown_poff_type;
+ break;
+ default:
+ break;
+ }
+
+ rc = qpnp_pon_masked_write(pon, rst_en_reg, QPNP_PON_RESET_EN, 0);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%hx, rc(%d)\n",
+ rst_en_reg, rc);
+
+ /*
+ * We need 10 sleep clock cycles here. But since the clock is
+ * internally generated, we need to add 50% tolerance to be
+ * conservative.
+ */
+ udelay(500);
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon),
+ QPNP_PON_POWER_OFF_MASK, type);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_PS_HOLD_RST_CTL(pon), rc);
+
+ rc = qpnp_pon_masked_write(pon, rst_en_reg, QPNP_PON_RESET_EN,
+ QPNP_PON_RESET_EN);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%hx, rc(%d)\n",
+ rst_en_reg, rc);
+
+ dev_dbg(&pon->pdev->dev, "power off type = 0x%02X\n", type);
+ return rc;
+}
+
+/**
+ * qpnp_pon_system_pwr_off - Configure system-reset PMIC for shutdown or reset
+ * @type: Determines the type of power off to perform - shutdown, reset, etc
+ *
+ * This function will support configuring for multiple PMICs. In some cases, the
+ * PON of secondary PMICs also needs to be configured. So this supports that
+ * requirement. Once the system-reset and secondary PMIC is configured properly,
+ * the MSM can drop PS_HOLD to activate the specified configuration. Note that
+ * this function may be called from atomic context as in the case of the panic
+ * notifier path and thus it should not rely on function calls that may sleep.
+ */
+int qpnp_pon_system_pwr_off(enum pon_power_off_type type)
+{
+ int rc = 0;
+ struct qpnp_pon *pon = sys_reset_dev;
+ struct qpnp_pon *tmp;
+ struct power_supply *batt_psy;
+ union power_supply_propval val;
+ unsigned long flags;
+
+ if (!pon)
+ return -ENODEV;
+
+ rc = qpnp_pon_reset_config(pon, type);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Error configuring main PON rc: %d\n",
+ rc);
+ return rc;
+ }
+
+ /*
+ * Check if a secondary PON device needs to be configured. If it
+ * is available, configure that also as per the requested power off
+ * type
+ */
+ spin_lock_irqsave(&spon_list_slock, flags);
+ if (list_empty(&spon_dev_list))
+ goto out;
+
+ list_for_each_entry_safe(pon, tmp, &spon_dev_list, list) {
+ dev_emerg(&pon->pdev->dev,
+ "PMIC@SID%d: configuring PON for reset\n",
+ to_spmi_device(pon->pdev->dev.parent)->usid);
+ rc = qpnp_pon_reset_config(pon, type);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Error configuring secondary PON rc: %d\n",
+ rc);
+ goto out;
+ }
+ }
+ /* Set ship mode here if it has been requested */
+ if (!!pon_ship_mode_en) {
+ batt_psy = power_supply_get_by_name("battery");
+ if (batt_psy) {
+ pr_debug("Set ship mode!\n");
+ val.intval = 1;
+ rc = power_supply_set_property(batt_psy,
+ POWER_SUPPLY_PROP_SET_SHIP_MODE, &val);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Set ship-mode failed\n");
+ }
+ }
+out:
+ spin_unlock_irqrestore(&spon_list_slock, flags);
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_pon_system_pwr_off);
+
+/**
+ * qpnp_pon_is_warm_reset - Checks if the PMIC went through a warm reset.
+ *
+ * Returns > 0 for warm resets, 0 for not warm reset, < 0 for errors
+ *
+ * Note that this function will only return the warm vs not-warm reset status
+ * of the PMIC that is configured as the system-reset device.
+ */
+int qpnp_pon_is_warm_reset(void)
+{
+ struct qpnp_pon *pon = sys_reset_dev;
+
+ if (!pon)
+ return -EPROBE_DEFER;
+
+ if (is_pon_gen1(pon) || pon->subtype == PON_1REG)
+ return pon->warm_reset_reason1
+ || (pon->warm_reset_reason2 & QPNP_PON_WARM_RESET_TFT);
+ else
+ return pon->warm_reset_reason1;
+}
+EXPORT_SYMBOL(qpnp_pon_is_warm_reset);
+
+/**
+ * qpnp_pon_wd_config - Disable the wd in a warm reset.
+ * @enable: to enable or disable the PON watch dog
+ *
+ * Returns = 0 for operate successfully, < 0 for errors
+ */
+int qpnp_pon_wd_config(bool enable)
+{
+ struct qpnp_pon *pon = sys_reset_dev;
+ int rc = 0;
+
+ if (!pon)
+ return -EPROBE_DEFER;
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_WD_RST_S2_CTL2(pon),
+ QPNP_PON_WD_EN, enable ? QPNP_PON_WD_EN : 0);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_WD_RST_S2_CTL2(pon), rc);
+
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_pon_wd_config);
+
+static int qpnp_pon_get_trigger_config(enum pon_trigger_source pon_src,
+ bool *enabled)
+{
+ struct qpnp_pon *pon = sys_reset_dev;
+ int rc;
+ u16 addr;
+ int val;
+ u8 mask;
+
+ if (!pon)
+ return -ENODEV;
+
+ if (pon_src < PON_SMPL || pon_src > PON_KPDPWR_N) {
+ dev_err(&pon->pdev->dev, "Invalid PON source\n");
+ return -EINVAL;
+ }
+
+ addr = QPNP_PON_TRIGGER_EN(pon);
+ mask = BIT(pon_src);
+ if (is_pon_gen2(pon) && pon_src == PON_SMPL) {
+ addr = QPNP_PON_SMPL_CTL(pon);
+ mask = QPNP_PON_SMPL_EN;
+ }
+
+
+ rc = regmap_read(pon->regmap, addr, &val);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to read from addr=%hx, rc(%d)\n",
+ addr, rc);
+ else
+ *enabled = !!(val & mask);
+
+ return rc;
+}
+
+/**
+ * qpnp_pon_trigger_config - Configures (enable/disable) the PON trigger source
+ * @pon_src: PON source to be configured
+ * @enable: to enable or disable the PON trigger
+ *
+ * This function configures the power-on trigger capability of a
+ * PON source. If a specific PON trigger is disabled it cannot act
+ * as a power-on source to the PMIC.
+ */
+
+int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable)
+{
+ struct qpnp_pon *pon = sys_reset_dev;
+ int rc;
+
+ if (!pon)
+ return -EPROBE_DEFER;
+
+ if (pon_src < PON_SMPL || pon_src > PON_KPDPWR_N) {
+ dev_err(&pon->pdev->dev, "Invalid PON source\n");
+ return -EINVAL;
+ }
+
+ if (is_pon_gen2(pon) && pon_src == PON_SMPL) {
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_SMPL_CTL(pon),
+ QPNP_PON_SMPL_EN, enable ? QPNP_PON_SMPL_EN : 0);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_SMPL_CTL(pon), rc);
+ } else {
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_TRIGGER_EN(pon),
+ BIT(pon_src), enable ? BIT(pon_src) : 0);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_TRIGGER_EN(pon), rc);
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_pon_trigger_config);
+
+/*
+ * This function stores the PMIC warm reset reason register values. It also
+ * clears these registers if the qcom,clear-warm-reset device tree property
+ * is specified.
+ */
+static int qpnp_pon_store_and_clear_warm_reset(struct qpnp_pon *pon)
+{
+ int rc;
+ u8 reg = 0;
+ uint val;
+
+ rc = regmap_read(pon->regmap, QPNP_PON_WARM_RESET_REASON1(pon),
+ &val);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to read addr=%x, rc(%d)\n",
+ QPNP_PON_WARM_RESET_REASON1(pon), rc);
+ return rc;
+ }
+ pon->warm_reset_reason1 = (u8)val;
+
+ if (is_pon_gen1(pon) || pon->subtype == PON_1REG) {
+ rc = regmap_read(pon->regmap, QPNP_PON_WARM_RESET_REASON2(pon),
+ &val);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read addr=%x, rc(%d)\n",
+ QPNP_PON_WARM_RESET_REASON2(pon), rc);
+ return rc;
+ }
+ pon->warm_reset_reason2 = (u8)val;
+ }
+
+ if (of_property_read_bool(pon->pdev->dev.of_node,
+ "qcom,clear-warm-reset")) {
+ rc = regmap_write(pon->regmap,
+ QPNP_PON_WARM_RESET_REASON1(pon), reg);
+ if (rc)
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%hx, rc(%d)\n",
+ QPNP_PON_WARM_RESET_REASON1(pon), rc);
+ }
+
+ return 0;
+}
+
+static struct qpnp_pon_config *
+qpnp_get_cfg(struct qpnp_pon *pon, u32 pon_type)
+{
+ int i;
+
+ for (i = 0; i < pon->num_pon_config; i++) {
+ if (pon_type == pon->pon_cfg[i].pon_type)
+ return &pon->pon_cfg[i];
+ }
+
+ return NULL;
+}
+
+static int
+qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
+{
+ int rc;
+ struct qpnp_pon_config *cfg = NULL;
+ u8 pon_rt_bit = 0;
+ u32 key_status;
+ uint pon_rt_sts;
+ u64 elapsed_us;
+
+ cfg = qpnp_get_cfg(pon, pon_type);
+ if (!cfg)
+ return -EINVAL;
+
+ /* Check if key reporting is supported */
+ if (!cfg->key_code)
+ return 0;
+
+ if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) {
+ elapsed_us = ktime_us_delta(ktime_get(),
+ pon->kpdpwr_last_release_time);
+ if (elapsed_us < pon->dbc_time_us) {
+ pr_debug("Ignoring kpdpwr event - within debounce time\n");
+ return 0;
+ }
+ }
+
+ /* check the RT status to get the current status of the line */
+ rc = regmap_read(pon->regmap, QPNP_PON_RT_STS(pon), &pon_rt_sts);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to read PON RT status\n");
+ return rc;
+ }
+
+ switch (cfg->pon_type) {
+ case PON_KPDPWR:
+ pon_rt_bit = QPNP_PON_KPDPWR_N_SET;
+ break;
+ case PON_RESIN:
+ pon_rt_bit = QPNP_PON_RESIN_N_SET;
+ break;
+ case PON_CBLPWR:
+ pon_rt_bit = QPNP_PON_CBLPWR_N_SET;
+ break;
+ case PON_KPDPWR_RESIN:
+ pon_rt_bit = QPNP_PON_KPDPWR_RESIN_BARK_N_SET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ pr_debug("PMIC input: code=%d, sts=0x%hhx\n",
+ cfg->key_code, pon_rt_sts);
+ key_status = pon_rt_sts & pon_rt_bit;
+
+ if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) {
+ if (!key_status)
+ pon->kpdpwr_last_release_time = ktime_get();
+ }
+
+ /*
+ * simulate press event in case release event occurred
+ * without a press event
+ */
+ if (!cfg->old_state && !key_status) {
+ input_report_key(pon->pon_input, cfg->key_code, 1);
+ input_sync(pon->pon_input);
+ }
+
+ input_report_key(pon->pon_input, cfg->key_code, key_status);
+ input_sync(pon->pon_input);
+
+ cfg->old_state = !!key_status;
+
+ return 0;
+}
+
+static irqreturn_t qpnp_kpdpwr_irq(int irq, void *_pon)
+{
+ int rc;
+ struct qpnp_pon *pon = _pon;
+
+ rc = qpnp_pon_input_dispatch(pon, PON_KPDPWR);
+ if (rc)
+ dev_err(&pon->pdev->dev, "Unable to send input event\n");
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t qpnp_kpdpwr_bark_irq(int irq, void *_pon)
+{
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t qpnp_resin_irq(int irq, void *_pon)
+{
+ int rc;
+ struct qpnp_pon *pon = _pon;
+
+ rc = qpnp_pon_input_dispatch(pon, PON_RESIN);
+ if (rc)
+ dev_err(&pon->pdev->dev, "Unable to send input event\n");
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t qpnp_kpdpwr_resin_bark_irq(int irq, void *_pon)
+{
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t qpnp_cblpwr_irq(int irq, void *_pon)
+{
+ int rc;
+ struct qpnp_pon *pon = _pon;
+
+ rc = qpnp_pon_input_dispatch(pon, PON_CBLPWR);
+ if (rc)
+ dev_err(&pon->pdev->dev, "Unable to send input event\n");
+
+ return IRQ_HANDLED;
+}
+
+static void print_pon_reg(struct qpnp_pon *pon, u16 offset)
+{
+ int rc;
+ u16 addr;
+ uint reg;
+
+ addr = pon->base + offset;
+ rc = regmap_read(pon->regmap, addr, &reg);
+ if (rc)
+ dev_emerg(&pon->pdev->dev,
+ "Unable to read reg at 0x%04hx\n", addr);
+ else
+ dev_emerg(&pon->pdev->dev, "reg@0x%04hx: %02hhx\n", addr, reg);
+}
+
+#define PON_PBL_STATUS 0x7
+#define PON_PON_REASON1(subtype) PON_OFFSET(subtype, 0x8, 0xC0)
+#define PON_PON_REASON2 0x9
+#define PON_WARM_RESET_REASON1(subtype) PON_OFFSET(subtype, 0xA, 0xC2)
+#define PON_WARM_RESET_REASON2 0xB
+#define PON_POFF_REASON1(subtype) PON_OFFSET(subtype, 0xC, 0xC5)
+#define PON_POFF_REASON2 0xD
+#define PON_SOFT_RESET_REASON1(subtype) PON_OFFSET(subtype, 0xE, 0xCB)
+#define PON_SOFT_RESET_REASON2 0xF
+#define PON_FAULT_REASON1 0xC8
+#define PON_FAULT_REASON2 0xC9
+#define PON_PMIC_WD_RESET_S1_TIMER 0x54
+#define PON_PMIC_WD_RESET_S2_TIMER 0x55
+static irqreturn_t qpnp_pmic_wd_bark_irq(int irq, void *_pon)
+{
+ struct qpnp_pon *pon = _pon;
+
+ print_pon_reg(pon, PON_PBL_STATUS);
+ print_pon_reg(pon, PON_PON_REASON1(pon->subtype));
+ print_pon_reg(pon, PON_WARM_RESET_REASON1(pon->subtype));
+ print_pon_reg(pon, PON_SOFT_RESET_REASON1(pon->subtype));
+ print_pon_reg(pon, PON_POFF_REASON1(pon->subtype));
+ if (is_pon_gen1(pon) || pon->subtype == PON_1REG) {
+ print_pon_reg(pon, PON_PON_REASON2);
+ print_pon_reg(pon, PON_WARM_RESET_REASON2);
+ print_pon_reg(pon, PON_POFF_REASON2);
+ print_pon_reg(pon, PON_SOFT_RESET_REASON2);
+ } else {
+ print_pon_reg(pon, PON_FAULT_REASON1);
+ print_pon_reg(pon, PON_FAULT_REASON2);
+ }
+ print_pon_reg(pon, PON_PMIC_WD_RESET_S1_TIMER);
+ print_pon_reg(pon, PON_PMIC_WD_RESET_S2_TIMER);
+ panic("PMIC Watch dog triggered");
+
+ return IRQ_HANDLED;
+}
+
+static void bark_work_func(struct work_struct *work)
+{
+ int rc;
+ uint pon_rt_sts = 0;
+ struct qpnp_pon_config *cfg;
+ struct qpnp_pon *pon =
+ container_of(work, struct qpnp_pon, bark_work.work);
+
+ cfg = qpnp_get_cfg(pon, PON_RESIN);
+ if (!cfg) {
+ dev_err(&pon->pdev->dev, "Invalid config pointer\n");
+ goto err_return;
+ }
+
+ /* enable reset */
+ rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
+ QPNP_PON_S2_CNTL_EN, QPNP_PON_S2_CNTL_EN);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to configure S2 enable\n");
+ goto err_return;
+ }
+ /* bark RT status update delay */
+ msleep(100);
+ /* read the bark RT status */
+ rc = regmap_read(pon->regmap, QPNP_PON_RT_STS(pon), &pon_rt_sts);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to read PON RT status\n");
+ goto err_return;
+ }
+
+ if (!(pon_rt_sts & QPNP_PON_RESIN_BARK_N_SET)) {
+ /* report the key event and enable the bark IRQ */
+ input_report_key(pon->pon_input, cfg->key_code, 0);
+ input_sync(pon->pon_input);
+ enable_irq(cfg->bark_irq);
+ } else {
+ /* disable reset */
+ rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
+ QPNP_PON_S2_CNTL_EN, 0);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to configure S2 enable\n");
+ goto err_return;
+ }
+ /* re-arm the work */
+ schedule_delayed_work(&pon->bark_work, QPNP_KEY_STATUS_DELAY);
+ }
+
+err_return:
+ return;
+}
+
+static irqreturn_t qpnp_resin_bark_irq(int irq, void *_pon)
+{
+ int rc;
+ struct qpnp_pon *pon = _pon;
+ struct qpnp_pon_config *cfg;
+
+ /* disable the bark interrupt */
+ disable_irq_nosync(irq);
+
+ cfg = qpnp_get_cfg(pon, PON_RESIN);
+ if (!cfg) {
+ dev_err(&pon->pdev->dev, "Invalid config pointer\n");
+ goto err_exit;
+ }
+
+ /* disable reset */
+ rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
+ QPNP_PON_S2_CNTL_EN, 0);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to configure S2 enable\n");
+ goto err_exit;
+ }
+
+ /* report the key event */
+ input_report_key(pon->pon_input, cfg->key_code, 1);
+ input_sync(pon->pon_input);
+ /* schedule work to check the bark status for key-release */
+ schedule_delayed_work(&pon->bark_work, QPNP_KEY_STATUS_DELAY);
+err_exit:
+ return IRQ_HANDLED;
+}
+
+static int
+qpnp_config_pull(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
+{
+ int rc;
+ u8 pull_bit;
+
+ switch (cfg->pon_type) {
+ case PON_KPDPWR:
+ pull_bit = QPNP_PON_KPDPWR_PULL_UP;
+ break;
+ case PON_RESIN:
+ pull_bit = QPNP_PON_RESIN_PULL_UP;
+ break;
+ case PON_CBLPWR:
+ pull_bit = QPNP_PON_CBLPWR_PULL_UP;
+ break;
+ case PON_KPDPWR_RESIN:
+ pull_bit = QPNP_PON_KPDPWR_PULL_UP | QPNP_PON_RESIN_PULL_UP;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_PULL_CTL(pon),
+ pull_bit, cfg->pull_up ? pull_bit : 0);
+ if (rc)
+ dev_err(&pon->pdev->dev, "Unable to config pull-up\n");
+
+ return rc;
+}
+
+static int
+qpnp_config_reset(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
+{
+ int rc;
+ u8 i;
+ u16 s1_timer_addr, s2_timer_addr;
+
+ switch (cfg->pon_type) {
+ case PON_KPDPWR:
+ s1_timer_addr = QPNP_PON_KPDPWR_S1_TIMER(pon);
+ s2_timer_addr = QPNP_PON_KPDPWR_S2_TIMER(pon);
+ break;
+ case PON_RESIN:
+ s1_timer_addr = QPNP_PON_RESIN_S1_TIMER(pon);
+ s2_timer_addr = QPNP_PON_RESIN_S2_TIMER(pon);
+ break;
+ case PON_KPDPWR_RESIN:
+ s1_timer_addr = QPNP_PON_KPDPWR_RESIN_S1_TIMER(pon);
+ s2_timer_addr = QPNP_PON_KPDPWR_RESIN_S2_TIMER(pon);
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* disable S2 reset */
+ rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
+ QPNP_PON_S2_CNTL_EN, 0);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to configure S2 enable\n");
+ return rc;
+ }
+
+ usleep_range(100, 120);
+
+ /* configure s1 timer, s2 timer and reset type */
+ for (i = 0; i < PON_S1_COUNT_MAX + 1; i++) {
+ if (cfg->s1_timer <= s1_delay[i])
+ break;
+ }
+ rc = qpnp_pon_masked_write(pon, s1_timer_addr,
+ QPNP_PON_S1_TIMER_MASK, i);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to configure S1 timer\n");
+ return rc;
+ }
+
+ i = 0;
+ if (cfg->s2_timer) {
+ i = cfg->s2_timer / 10;
+ i = ilog2(i + 1);
+ }
+
+ rc = qpnp_pon_masked_write(pon, s2_timer_addr,
+ QPNP_PON_S2_TIMER_MASK, i);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to configure S2 timer\n");
+ return rc;
+ }
+
+ rc = qpnp_pon_masked_write(pon, cfg->s2_cntl_addr,
+ QPNP_PON_S2_CNTL_TYPE_MASK, (u8)cfg->s2_type);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to configure S2 reset type\n");
+ return rc;
+ }
+
+ /* enable S2 reset */
+ rc = qpnp_pon_masked_write(pon, cfg->s2_cntl2_addr,
+ QPNP_PON_S2_CNTL_EN, QPNP_PON_S2_CNTL_EN);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to configure S2 enable\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+qpnp_pon_request_irqs(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
+{
+ int rc = 0;
+
+ switch (cfg->pon_type) {
+ case PON_KPDPWR:
+ rc = devm_request_irq(&pon->pdev->dev, cfg->state_irq,
+ qpnp_kpdpwr_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "qpnp_kpdpwr_status", pon);
+ if (rc < 0) {
+ dev_err(&pon->pdev->dev, "Can't request %d IRQ\n",
+ cfg->state_irq);
+ return rc;
+ }
+ if (cfg->use_bark) {
+ rc = devm_request_irq(&pon->pdev->dev, cfg->bark_irq,
+ qpnp_kpdpwr_bark_irq,
+ IRQF_TRIGGER_RISING,
+ "qpnp_kpdpwr_bark", pon);
+ if (rc < 0) {
+ dev_err(&pon->pdev->dev,
+ "Can't request %d IRQ\n",
+ cfg->bark_irq);
+ return rc;
+ }
+ }
+ break;
+ case PON_RESIN:
+ rc = devm_request_irq(&pon->pdev->dev, cfg->state_irq,
+ qpnp_resin_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "qpnp_resin_status", pon);
+ if (rc < 0) {
+ dev_err(&pon->pdev->dev, "Can't request %d IRQ\n",
+ cfg->state_irq);
+ return rc;
+ }
+ if (cfg->use_bark) {
+ rc = devm_request_irq(&pon->pdev->dev, cfg->bark_irq,
+ qpnp_resin_bark_irq,
+ IRQF_TRIGGER_RISING,
+ "qpnp_resin_bark", pon);
+ if (rc < 0) {
+ dev_err(&pon->pdev->dev,
+ "Can't request %d IRQ\n",
+ cfg->bark_irq);
+ return rc;
+ }
+ }
+ break;
+ case PON_CBLPWR:
+ rc = devm_request_irq(&pon->pdev->dev, cfg->state_irq,
+ qpnp_cblpwr_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "qpnp_cblpwr_status", pon);
+ if (rc < 0) {
+ dev_err(&pon->pdev->dev, "Can't request %d IRQ\n",
+ cfg->state_irq);
+ return rc;
+ }
+ break;
+ case PON_KPDPWR_RESIN:
+ if (cfg->use_bark) {
+ rc = devm_request_irq(&pon->pdev->dev, cfg->bark_irq,
+ qpnp_kpdpwr_resin_bark_irq,
+ IRQF_TRIGGER_RISING,
+ "qpnp_kpdpwr_resin_bark", pon);
+ if (rc < 0) {
+ dev_err(&pon->pdev->dev,
+ "Can't request %d IRQ\n",
+ cfg->bark_irq);
+ return rc;
+ }
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* mark the interrupts wakeable if they support linux-key */
+ if (cfg->key_code) {
+ enable_irq_wake(cfg->state_irq);
+ /* special handling for RESIN due to a hardware bug */
+ if (cfg->pon_type == PON_RESIN && cfg->support_reset)
+ enable_irq_wake(cfg->bark_irq);
+ }
+
+ return rc;
+}
+
+static int
+qpnp_pon_config_input(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
+{
+ if (!pon->pon_input) {
+ pon->pon_input = input_allocate_device();
+ if (!pon->pon_input) {
+ dev_err(&pon->pdev->dev,
+ "Can't allocate pon input device\n");
+ return -ENOMEM;
+ }
+ pon->pon_input->name = "qpnp_pon";
+ pon->pon_input->phys = "qpnp_pon/input0";
+ }
+
+ input_set_capability(pon->pon_input, EV_KEY, cfg->key_code);
+
+ return 0;
+}
+
+static int qpnp_pon_config_init(struct qpnp_pon *pon)
+{
+ int rc = 0, i = 0, pmic_wd_bark_irq;
+ struct device_node *pp = NULL;
+ struct qpnp_pon_config *cfg;
+ uint pmic_type;
+ uint revid_rev4;
+
+ if (!pon->num_pon_config) {
+ dev_dbg(&pon->pdev->dev, "num_pon_config: %d\n",
+ pon->num_pon_config);
+ return 0;
+ }
+
+ /* iterate through the list of pon configs */
+ for_each_available_child_of_node(pon->pdev->dev.of_node, pp) {
+ if (!of_find_property(pp, "qcom,pon-type", NULL))
+ continue;
+
+ cfg = &pon->pon_cfg[i++];
+
+ rc = of_property_read_u32(pp, "qcom,pon-type", &cfg->pon_type);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "PON type not specified\n");
+ return rc;
+ }
+
+ switch (cfg->pon_type) {
+ case PON_KPDPWR:
+ cfg->state_irq = platform_get_irq_byname(pon->pdev,
+ "kpdpwr");
+ if (cfg->state_irq < 0) {
+ dev_err(&pon->pdev->dev,
+ "Unable to get kpdpwr irq\n");
+ return cfg->state_irq;
+ }
+
+ rc = of_property_read_u32(pp, "qcom,support-reset",
+ &cfg->support_reset);
+
+ if (rc) {
+ if (rc == -EINVAL) {
+ dev_dbg(&pon->pdev->dev,
+ "'qcom,support-reset' DT property doesn't exist\n");
+ } else {
+ dev_err(&pon->pdev->dev,
+ "Unable to read 'qcom,support-reset'\n");
+ return rc;
+ }
+ } else {
+ cfg->config_reset = true;
+ }
+
+ cfg->use_bark = of_property_read_bool(pp,
+ "qcom,use-bark");
+ if (cfg->use_bark) {
+ cfg->bark_irq
+ = platform_get_irq_byname(pon->pdev,
+ "kpdpwr-bark");
+ if (cfg->bark_irq < 0) {
+ dev_err(&pon->pdev->dev,
+ "Unable to get kpdpwr-bark irq\n");
+ return cfg->bark_irq;
+ }
+ }
+
+ /*
+ * If the value read from REVISION2 register is 0x00,
+ * then there is a single register to control s2 reset.
+ * Otherwise there are separate registers for s2 reset
+ * type and s2 reset enable.
+ */
+ if (pon->pon_ver == QPNP_PON_GEN1_V1) {
+ cfg->s2_cntl_addr = cfg->s2_cntl2_addr =
+ QPNP_PON_KPDPWR_S2_CNTL(pon);
+ } else {
+ cfg->s2_cntl_addr =
+ QPNP_PON_KPDPWR_S2_CNTL(pon);
+ cfg->s2_cntl2_addr =
+ QPNP_PON_KPDPWR_S2_CNTL2(pon);
+ }
+
+ break;
+ case PON_RESIN:
+ cfg->state_irq = platform_get_irq_byname(pon->pdev,
+ "resin");
+ if (cfg->state_irq < 0) {
+ dev_err(&pon->pdev->dev,
+ "Unable to get resin irq\n");
+ return cfg->bark_irq;
+ }
+
+ rc = of_property_read_u32(pp, "qcom,support-reset",
+ &cfg->support_reset);
+
+ if (rc) {
+ if (rc == -EINVAL) {
+ dev_dbg(&pon->pdev->dev,
+ "'qcom,support-reset' DT property doesn't exist\n");
+ } else {
+ dev_err(&pon->pdev->dev,
+ "Unable to read 'qcom,support-reset'\n");
+ return rc;
+ }
+ } else {
+ cfg->config_reset = true;
+ }
+
+ cfg->use_bark = of_property_read_bool(pp,
+ "qcom,use-bark");
+
+ rc = regmap_read(pon->regmap, PMIC_VERSION_REG,
+ &pmic_type);
+
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read PMIC type\n");
+ return rc;
+ }
+
+ if (pmic_type == PMIC_VER_8941) {
+
+ rc = regmap_read(pon->regmap,
+ PMIC_VERSION_REV4_REG,
+ &revid_rev4);
+
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read PMIC revision ID\n");
+ return rc;
+ }
+
+ /*
+ * PM8941 V3 does not have hardware bug. Hence
+ * bark is not required from PMIC versions 3.0.
+ */
+ if (!(revid_rev4 == PMIC8941_V1_REV4 ||
+ revid_rev4 == PMIC8941_V2_REV4)) {
+ cfg->support_reset = false;
+ cfg->use_bark = false;
+ }
+ }
+
+ if (cfg->use_bark) {
+ cfg->bark_irq
+ = platform_get_irq_byname(pon->pdev,
+ "resin-bark");
+ if (cfg->bark_irq < 0) {
+ dev_err(&pon->pdev->dev,
+ "Unable to get resin-bark irq\n");
+ return cfg->bark_irq;
+ }
+ }
+
+ if (pon->pon_ver == QPNP_PON_GEN1_V1) {
+ cfg->s2_cntl_addr = cfg->s2_cntl2_addr =
+ QPNP_PON_RESIN_S2_CNTL(pon);
+ } else {
+ cfg->s2_cntl_addr =
+ QPNP_PON_RESIN_S2_CNTL(pon);
+ cfg->s2_cntl2_addr =
+ QPNP_PON_RESIN_S2_CNTL2(pon);
+ }
+
+ break;
+ case PON_CBLPWR:
+ cfg->state_irq = platform_get_irq_byname(pon->pdev,
+ "cblpwr");
+ if (cfg->state_irq < 0) {
+ dev_err(&pon->pdev->dev,
+ "Unable to get cblpwr irq\n");
+ return rc;
+ }
+ break;
+ case PON_KPDPWR_RESIN:
+ rc = of_property_read_u32(pp, "qcom,support-reset",
+ &cfg->support_reset);
+
+ if (rc) {
+ if (rc == -EINVAL) {
+ dev_dbg(&pon->pdev->dev,
+ "'qcom,support-reset' DT property doesn't exist\n");
+ } else {
+ dev_err(&pon->pdev->dev,
+ "Unable to read 'qcom,support-reset'\n");
+ return rc;
+ }
+ } else {
+ cfg->config_reset = true;
+ }
+
+ cfg->use_bark = of_property_read_bool(pp,
+ "qcom,use-bark");
+ if (cfg->use_bark) {
+ cfg->bark_irq
+ = platform_get_irq_byname(pon->pdev,
+ "kpdpwr-resin-bark");
+ if (cfg->bark_irq < 0) {
+ dev_err(&pon->pdev->dev,
+ "Unable to get kpdpwr-resin-bark irq\n");
+ return cfg->bark_irq;
+ }
+ }
+
+ if (pon->pon_ver == QPNP_PON_GEN1_V1) {
+ cfg->s2_cntl_addr = cfg->s2_cntl2_addr =
+ QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon);
+ } else {
+ cfg->s2_cntl_addr =
+ QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon);
+ cfg->s2_cntl2_addr =
+ QPNP_PON_KPDPWR_RESIN_S2_CNTL2(pon);
+ }
+
+ break;
+ default:
+ dev_err(&pon->pdev->dev, "PON RESET %d not supported",
+ cfg->pon_type);
+ return -EINVAL;
+ }
+
+ if (cfg->support_reset) {
+ /*
+ * Get the reset parameters (bark debounce time and
+ * reset debounce time) for the reset line.
+ */
+ rc = of_property_read_u32(pp, "qcom,s1-timer",
+ &cfg->s1_timer);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read s1-timer\n");
+ return rc;
+ }
+ if (cfg->s1_timer > QPNP_PON_S1_TIMER_MAX) {
+ dev_err(&pon->pdev->dev,
+ "Incorrect S1 debounce time\n");
+ return -EINVAL;
+ }
+ rc = of_property_read_u32(pp, "qcom,s2-timer",
+ &cfg->s2_timer);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read s2-timer\n");
+ return rc;
+ }
+ if (cfg->s2_timer > QPNP_PON_S2_TIMER_MAX) {
+ dev_err(&pon->pdev->dev,
+ "Incorrect S2 debounce time\n");
+ return -EINVAL;
+ }
+ rc = of_property_read_u32(pp, "qcom,s2-type",
+ &cfg->s2_type);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read s2-type\n");
+ return rc;
+ }
+ if (cfg->s2_type > QPNP_PON_RESET_TYPE_MAX) {
+ dev_err(&pon->pdev->dev,
+ "Incorrect reset type specified\n");
+ return -EINVAL;
+ }
+ }
+ /*
+ * Get the standard-key parameters. This might not be
+ * specified if there is no key mapping on the reset line.
+ */
+ rc = of_property_read_u32(pp, "linux,code", &cfg->key_code);
+ if (rc && rc != -EINVAL) {
+ dev_err(&pon->pdev->dev, "Unable to read key-code\n");
+ return rc;
+ }
+ /* Register key configuration */
+ if (cfg->key_code) {
+ rc = qpnp_pon_config_input(pon, cfg);
+ if (rc < 0)
+ return rc;
+ }
+ /* get the pull-up configuration */
+ rc = of_property_read_u32(pp, "qcom,pull-up", &cfg->pull_up);
+ if (rc && rc != -EINVAL) {
+ dev_err(&pon->pdev->dev, "Unable to read pull-up\n");
+ return rc;
+ }
+ }
+
+ pmic_wd_bark_irq = platform_get_irq_byname(pon->pdev, "pmic-wd-bark");
+ /* request the pmic-wd-bark irq only if it is defined */
+ if (pmic_wd_bark_irq >= 0) {
+ rc = devm_request_irq(&pon->pdev->dev, pmic_wd_bark_irq,
+ qpnp_pmic_wd_bark_irq,
+ IRQF_TRIGGER_RISING,
+ "qpnp_pmic_wd_bark", pon);
+ if (rc < 0) {
+ dev_err(&pon->pdev->dev,
+ "Can't request %d IRQ\n",
+ pmic_wd_bark_irq);
+ goto free_input_dev;
+ }
+ }
+
+ /* register the input device */
+ if (pon->pon_input) {
+ rc = input_register_device(pon->pon_input);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Can't register pon key: %d\n", rc);
+ goto free_input_dev;
+ }
+ }
+
+ for (i = 0; i < pon->num_pon_config; i++) {
+ cfg = &pon->pon_cfg[i];
+ /* Configure the pull-up */
+ rc = qpnp_config_pull(pon, cfg);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to config pull-up\n");
+ goto unreg_input_dev;
+ }
+
+ if (cfg->config_reset) {
+ /* Configure the reset-configuration */
+ if (cfg->support_reset) {
+ rc = qpnp_config_reset(pon, cfg);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to config pon reset\n");
+ goto unreg_input_dev;
+ }
+ } else {
+ if (cfg->pon_type != PON_CBLPWR) {
+ /* disable S2 reset */
+ rc = qpnp_pon_masked_write(pon,
+ cfg->s2_cntl2_addr,
+ QPNP_PON_S2_CNTL_EN, 0);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to disable S2 reset\n");
+ goto unreg_input_dev;
+ }
+ }
+ }
+ }
+
+ rc = qpnp_pon_request_irqs(pon, cfg);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to request-irq's\n");
+ goto unreg_input_dev;
+ }
+ }
+
+ device_init_wakeup(&pon->pdev->dev, 1);
+
+ return rc;
+
+unreg_input_dev:
+ if (pon->pon_input)
+ input_unregister_device(pon->pon_input);
+free_input_dev:
+ if (pon->pon_input)
+ input_free_device(pon->pon_input);
+ return rc;
+}
+
+static int pon_spare_regulator_enable(struct regulator_dev *rdev)
+{
+ int rc = 0;
+ u8 value;
+ struct pon_regulator *pon_reg = rdev_get_drvdata(rdev);
+
+ pr_debug("reg %s enable addr: %x bit: %d\n", rdev->desc->name,
+ pon_reg->addr, pon_reg->bit);
+
+ value = BIT(pon_reg->bit) & 0xFF;
+ rc = qpnp_pon_masked_write(pon_reg->pon, pon_reg->pon->base +
+ pon_reg->addr, value, value);
+ if (rc)
+ dev_err(&pon_reg->pon->pdev->dev, "Unable to write to %x\n",
+ pon_reg->pon->base + pon_reg->addr);
+ else
+ pon_reg->enabled = true;
+ return rc;
+}
+
+static int pon_spare_regulator_disable(struct regulator_dev *rdev)
+{
+ int rc = 0;
+ u8 mask;
+ struct pon_regulator *pon_reg = rdev_get_drvdata(rdev);
+
+ pr_debug("reg %s disable addr: %x bit: %d\n", rdev->desc->name,
+ pon_reg->addr, pon_reg->bit);
+
+ mask = BIT(pon_reg->bit) & 0xFF;
+ rc = qpnp_pon_masked_write(pon_reg->pon, pon_reg->pon->base +
+ pon_reg->addr, mask, 0);
+ if (rc)
+ dev_err(&pon_reg->pon->pdev->dev, "Unable to write to %x\n",
+ pon_reg->pon->base + pon_reg->addr);
+ else
+ pon_reg->enabled = false;
+ return rc;
+}
+
+static int pon_spare_regulator_is_enable(struct regulator_dev *rdev)
+{
+ struct pon_regulator *pon_reg = rdev_get_drvdata(rdev);
+
+ return pon_reg->enabled;
+}
+
+struct regulator_ops pon_spare_reg_ops = {
+ .enable = pon_spare_regulator_enable,
+ .disable = pon_spare_regulator_disable,
+ .is_enabled = pon_spare_regulator_is_enable,
+};
+
+static int pon_regulator_init(struct qpnp_pon *pon)
+{
+ int rc = 0, i = 0;
+ struct regulator_init_data *init_data;
+ struct regulator_config reg_cfg = {};
+ struct device_node *node = NULL;
+ struct device *dev = &pon->pdev->dev;
+ struct pon_regulator *pon_reg;
+
+ if (!pon->num_pon_reg)
+ return 0;
+
+ pon->pon_reg_cfg = devm_kcalloc(dev, pon->num_pon_reg,
+ sizeof(*(pon->pon_reg_cfg)),
+ GFP_KERNEL);
+
+ if (!pon->pon_reg_cfg)
+ return -ENOMEM;
+
+ for_each_available_child_of_node(dev->of_node, node) {
+ if (!of_find_property(node, "regulator-name", NULL))
+ continue;
+
+ pon_reg = &pon->pon_reg_cfg[i++];
+ pon_reg->pon = pon;
+
+ rc = of_property_read_u32(node, "qcom,pon-spare-reg-addr",
+ &pon_reg->addr);
+ if (rc) {
+ dev_err(dev, "Unable to read address for regulator, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,pon-spare-reg-bit",
+ &pon_reg->bit);
+ if (rc) {
+ dev_err(dev, "Unable to read bit for regulator, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ init_data = of_get_regulator_init_data(dev, node,
+ &pon_reg->rdesc);
+ if (!init_data) {
+ dev_err(dev, "regulator init data is missing\n");
+ return -EINVAL;
+ }
+ init_data->constraints.valid_ops_mask
+ |= REGULATOR_CHANGE_STATUS;
+
+ if (!init_data->constraints.name) {
+ dev_err(dev, "regulator-name is missing\n");
+ return -EINVAL;
+ }
+
+ pon_reg->rdesc.owner = THIS_MODULE;
+ pon_reg->rdesc.type = REGULATOR_VOLTAGE;
+ pon_reg->rdesc.ops = &pon_spare_reg_ops;
+ pon_reg->rdesc.name = init_data->constraints.name;
+
+ reg_cfg.dev = dev;
+ reg_cfg.init_data = init_data;
+ reg_cfg.driver_data = pon_reg;
+ reg_cfg.of_node = node;
+
+ pon_reg->rdev = regulator_register(&pon_reg->rdesc, &reg_cfg);
+ if (IS_ERR(pon_reg->rdev)) {
+ rc = PTR_ERR(pon_reg->rdev);
+ pon_reg->rdev = NULL;
+ if (rc != -EPROBE_DEFER)
+ dev_err(dev, "regulator_register failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+ return rc;
+}
+
+static bool smpl_en;
+
+static int qpnp_pon_smpl_en_get(char *buf, const struct kernel_param *kp)
+{
+ bool enabled = 0;
+ int rc;
+
+ rc = qpnp_pon_get_trigger_config(PON_SMPL, &enabled);
+ if (rc < 0)
+ return rc;
+
+ return snprintf(buf, QPNP_PON_BUFFER_SIZE, "%d", enabled);
+}
+
+static int qpnp_pon_smpl_en_set(const char *val,
+ const struct kernel_param *kp)
+{
+ int rc;
+
+ rc = param_set_bool(val, kp);
+ if (rc < 0) {
+ pr_err("Unable to set smpl_en rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_pon_trigger_config(PON_SMPL, *(bool *)kp->arg);
+ return rc;
+}
+
+static struct kernel_param_ops smpl_en_ops = {
+ .set = qpnp_pon_smpl_en_set,
+ .get = qpnp_pon_smpl_en_get,
+};
+
+module_param_cb(smpl_en, &smpl_en_ops, &smpl_en, 0644);
+
+static bool dload_on_uvlo;
+
+static int qpnp_pon_debugfs_uvlo_dload_get(char *buf,
+ const struct kernel_param *kp)
+{
+ struct qpnp_pon *pon = sys_reset_dev;
+ int rc = 0;
+ uint reg;
+
+ if (!pon)
+ return -ENODEV;
+
+ rc = regmap_read(pon->regmap, QPNP_PON_XVDD_RB_SPARE(pon), &reg);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read addr=%x, rc(%d)\n",
+ QPNP_PON_XVDD_RB_SPARE(pon), rc);
+ return rc;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%d",
+ !!(QPNP_PON_UVLO_DLOAD_EN & reg));
+}
+
+static int qpnp_pon_debugfs_uvlo_dload_set(const char *val,
+ const struct kernel_param *kp)
+{
+ struct qpnp_pon *pon = sys_reset_dev;
+ int rc = 0;
+ uint reg;
+
+ if (!pon)
+ return -ENODEV;
+
+ rc = param_set_bool(val, kp);
+ if (rc) {
+ pr_err("Unable to set bms_reset: %d\n", rc);
+ return rc;
+ }
+
+ rc = regmap_read(pon->regmap, QPNP_PON_XVDD_RB_SPARE(pon), &reg);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read addr=%x, rc(%d)\n",
+ QPNP_PON_XVDD_RB_SPARE(pon), rc);
+ return rc;
+ }
+
+ reg &= ~QPNP_PON_UVLO_DLOAD_EN;
+ if (*(bool *)kp->arg)
+ reg |= QPNP_PON_UVLO_DLOAD_EN;
+
+ rc = regmap_write(pon->regmap, QPNP_PON_XVDD_RB_SPARE(pon), reg);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to write to addr=%hx, rc(%d)\n",
+ QPNP_PON_XVDD_RB_SPARE(pon), rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static struct kernel_param_ops dload_on_uvlo_ops = {
+ .set = qpnp_pon_debugfs_uvlo_dload_set,
+ .get = qpnp_pon_debugfs_uvlo_dload_get,
+};
+
+module_param_cb(dload_on_uvlo, &dload_on_uvlo_ops, &dload_on_uvlo, 0644);
+
+#if defined(CONFIG_DEBUG_FS)
+
+static int qpnp_pon_debugfs_uvlo_get(void *data, u64 *val)
+{
+ struct qpnp_pon *pon = (struct qpnp_pon *) data;
+
+ *val = pon->uvlo;
+
+ return 0;
+}
+
+static int qpnp_pon_debugfs_uvlo_set(void *data, u64 val)
+{
+ struct qpnp_pon *pon = (struct qpnp_pon *) data;
+
+ if (pon->pon_trigger_reason == PON_SMPL ||
+ pon->pon_power_off_reason == QPNP_POFF_REASON_UVLO)
+ panic("An UVLO was occurred.\n");
+ pon->uvlo = val;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(qpnp_pon_debugfs_uvlo_fops, qpnp_pon_debugfs_uvlo_get,
+ qpnp_pon_debugfs_uvlo_set, "0x%02llx\n");
+
+static void qpnp_pon_debugfs_init(struct platform_device *pdev)
+{
+ struct qpnp_pon *pon = dev_get_drvdata(&pdev->dev);
+ struct dentry *ent;
+
+ pon->debugfs = debugfs_create_dir(dev_name(&pdev->dev), NULL);
+ if (!pon->debugfs) {
+ dev_err(&pon->pdev->dev,
+ "Unable to create debugfs directory\n");
+ } else {
+ ent = debugfs_create_file("uvlo_panic", 0644,
+ pon->debugfs, pon, &qpnp_pon_debugfs_uvlo_fops);
+ if (!ent)
+ dev_err(&pon->pdev->dev,
+ "Unable to create uvlo_panic debugfs file.\n");
+ }
+}
+
+static void qpnp_pon_debugfs_remove(struct platform_device *pdev)
+{
+ struct qpnp_pon *pon = dev_get_drvdata(&pdev->dev);
+
+ debugfs_remove_recursive(pon->debugfs);
+}
+
+#else
+
+static void qpnp_pon_debugfs_init(struct platform_device *pdev)
+{}
+
+static void qpnp_pon_debugfs_remove(struct platform_device *pdev)
+{}
+#endif
+
+static int read_gen2_pon_off_reason(struct qpnp_pon *pon, u16 *reason,
+ int *reason_index_offset)
+{
+ int rc;
+ int buf[2], reg;
+
+ rc = regmap_read(pon->regmap,
+ QPNP_PON_OFF_REASON(pon),
+ &reg);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to read PON_OFF_REASON reg rc:%d\n",
+ rc);
+ return rc;
+ }
+
+ if (reg & QPNP_GEN2_POFF_SEQ) {
+ rc = regmap_read(pon->regmap,
+ QPNP_POFF_REASON1(pon),
+ buf);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to read POFF_REASON1 reg rc:%d\n",
+ rc);
+ return rc;
+ }
+ *reason = (u8)buf[0];
+ *reason_index_offset = 0;
+ } else if (reg & QPNP_GEN2_FAULT_SEQ) {
+ rc = regmap_bulk_read(pon->regmap,
+ QPNP_FAULT_REASON1(pon),
+ buf, 2);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to read FAULT_REASON regs rc:%d\n",
+ rc);
+ return rc;
+ }
+ *reason = (u8)buf[0] | (u16)(buf[1] << 8);
+ *reason_index_offset = POFF_REASON_FAULT_OFFSET;
+ } else if (reg & QPNP_GEN2_S3_RESET_SEQ) {
+ rc = regmap_read(pon->regmap,
+ QPNP_S3_RESET_REASON(pon),
+ buf);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to read S3_RESET_REASON reg rc:%d\n",
+ rc);
+ return rc;
+ }
+ *reason = (u8)buf[0];
+ *reason_index_offset = POFF_REASON_S3_RESET_OFFSET;
+ }
+
+ return 0;
+}
+
+static int qpnp_pon_probe(struct platform_device *pdev)
+{
+ struct qpnp_pon *pon;
+ unsigned int base;
+ struct device_node *node = NULL;
+ u32 delay = 0, s3_debounce = 0;
+ int rc, sys_reset, index;
+ int reason_index_offset = 0;
+ u8 buf[2];
+ uint pon_sts = 0;
+ u16 poff_sts = 0;
+ const char *s3_src;
+ u8 s3_src_reg;
+ unsigned long flags;
+ uint temp = 0;
+
+ pon = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_pon), GFP_KERNEL);
+ if (!pon)
+ return -ENOMEM;
+
+ pon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!pon->regmap) {
+ dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ return -EINVAL;
+ }
+
+ sys_reset = of_property_read_bool(pdev->dev.of_node,
+ "qcom,system-reset");
+ if (sys_reset && sys_reset_dev) {
+ dev_err(&pdev->dev,
+ "qcom,system-reset property can only be specified for one device on the system\n");
+ return -EINVAL;
+ } else if (sys_reset) {
+ sys_reset_dev = pon;
+ }
+
+ pon->pdev = pdev;
+
+ rc = of_property_read_u32(pdev->dev.of_node, "reg", &base);
+ if (rc < 0) {
+ dev_err(&pdev->dev,
+ "Couldn't find reg in node = %s rc = %d\n",
+ pdev->dev.of_node->full_name, rc);
+ return rc;
+ }
+ pon->base = base;
+
+ /* get the total number of pon configurations */
+ for_each_available_child_of_node(pdev->dev.of_node, node) {
+ if (of_find_property(node, "regulator-name", NULL)) {
+ pon->num_pon_reg++;
+ } else if (of_find_property(node, "qcom,pon-type", NULL)) {
+ pon->num_pon_config++;
+ } else {
+ pr_err("Unknown sub-node\n");
+ return -EINVAL;
+ }
+ }
+
+ pr_debug("PON@SID %d: num_pon_config: %d num_pon_reg: %d\n",
+ to_spmi_device(pon->pdev->dev.parent)->usid,
+ pon->num_pon_config, pon->num_pon_reg);
+
+ rc = pon_regulator_init(pon);
+ if (rc) {
+ dev_err(&pdev->dev, "Error in pon_regulator_init rc: %d\n",
+ rc);
+ return rc;
+ }
+
+ if (!pon->num_pon_config)
+ /* No PON config., do not register the driver */
+ dev_info(&pdev->dev, "No PON config. specified\n");
+ else
+ pon->pon_cfg = devm_kzalloc(&pdev->dev,
+ sizeof(struct qpnp_pon_config) *
+ pon->num_pon_config, GFP_KERNEL);
+
+ /* Read PON_PERPH_SUBTYPE register to get PON type */
+ rc = regmap_read(pon->regmap,
+ QPNP_PON_PERPH_SUBTYPE(pon),
+ &temp);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read PON_PERPH_SUBTYPE register rc: %d\n",
+ rc);
+ return rc;
+ }
+ pon->subtype = temp;
+
+ /* Check if it is rev B */
+ rc = regmap_read(pon->regmap,
+ QPNP_PON_REVISION2(pon), &temp);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read addr=%x, rc(%d)\n",
+ QPNP_PON_REVISION2(pon), rc);
+ return rc;
+ }
+
+ pon->pon_ver = temp;
+ if (is_pon_gen1(pon)) {
+ if (pon->pon_ver == 0)
+ pon->pon_ver = QPNP_PON_GEN1_V1;
+ else
+ pon->pon_ver = QPNP_PON_GEN1_V2;
+ } else if (is_pon_gen2(pon)) {
+ pon->pon_ver = QPNP_PON_GEN2;
+ } else if (pon->subtype == PON_1REG) {
+ pon->pon_ver = QPNP_PON_GEN1_V2;
+ } else {
+ dev_err(&pon->pdev->dev,
+ "Invalid PON_PERPH_SUBTYPE value %x\n",
+ pon->subtype);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: pon_subtype=%x, pon_version=%x\n", __func__,
+ pon->subtype, pon->pon_ver);
+
+ rc = qpnp_pon_store_and_clear_warm_reset(pon);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to store/clear WARM_RESET_REASONx registers rc: %d\n",
+ rc);
+ return rc;
+ }
+
+ /* PON reason */
+ rc = regmap_read(pon->regmap, QPNP_PON_REASON1(pon), &pon_sts);
+ if (rc) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read PON_RESASON1 reg rc: %d\n",
+ rc);
+ return rc;
+ }
+
+ if (sys_reset)
+ boot_reason = ffs(pon_sts);
+
+ index = ffs(pon_sts) - 1;
+ cold_boot = !qpnp_pon_is_warm_reset();
+ if (index >= ARRAY_SIZE(qpnp_pon_reason) || index < 0) {
+ dev_info(&pon->pdev->dev,
+ "PMIC@SID%d Power-on reason: Unknown and '%s' boot\n",
+ to_spmi_device(pon->pdev->dev.parent)->usid,
+ cold_boot ? "cold" : "warm");
+ } else {
+ pon->pon_trigger_reason = index;
+ dev_info(&pon->pdev->dev,
+ "PMIC@SID%d Power-on reason: %s and '%s' boot\n",
+ to_spmi_device(pon->pdev->dev.parent)->usid,
+ qpnp_pon_reason[index],
+ cold_boot ? "cold" : "warm");
+ }
+
+ /* POFF reason */
+ if (!is_pon_gen1(pon) && pon->subtype != PON_1REG) {
+ rc = read_gen2_pon_off_reason(pon, &poff_sts,
+ &reason_index_offset);
+ if (rc)
+ return rc;
+ } else {
+ rc = regmap_bulk_read(pon->regmap, QPNP_POFF_REASON1(pon),
+ buf, 2);
+ if (rc) {
+ dev_err(&pon->pdev->dev, "Unable to read POFF_REASON regs rc:%d\n",
+ rc);
+ return rc;
+ }
+ poff_sts = buf[0] | (buf[1] << 8);
+ }
+ index = ffs(poff_sts) - 1 + reason_index_offset;
+ if (index >= ARRAY_SIZE(qpnp_poff_reason) || index < 0) {
+ dev_info(&pon->pdev->dev,
+ "PMIC@SID%d: Unknown power-off reason\n",
+ to_spmi_device(pon->pdev->dev.parent)->usid);
+ } else {
+ pon->pon_power_off_reason = index;
+ dev_info(&pon->pdev->dev,
+ "PMIC@SID%d: Power-off reason: %s\n",
+ to_spmi_device(pon->pdev->dev.parent)->usid,
+ qpnp_poff_reason[index]);
+ }
+
+ if (pon->pon_trigger_reason == PON_SMPL ||
+ pon->pon_power_off_reason == QPNP_POFF_REASON_UVLO) {
+ if (of_property_read_bool(pdev->dev.of_node,
+ "qcom,uvlo-panic"))
+ panic("An UVLO was occurred.");
+ }
+
+ /* program s3 debounce */
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
+ "qcom,s3-debounce", &s3_debounce);
+ if (rc) {
+ if (rc != -EINVAL) {
+ dev_err(&pon->pdev->dev,
+ "Unable to read s3 timer rc:%d\n",
+ rc);
+ return rc;
+ }
+ } else {
+ if (s3_debounce > QPNP_PON_S3_TIMER_SECS_MAX) {
+ dev_info(&pon->pdev->dev,
+ "Exceeded S3 max value, set it to max\n");
+ s3_debounce = QPNP_PON_S3_TIMER_SECS_MAX;
+ }
+
+ /* 0 is a special value to indicate instant s3 reset */
+ if (s3_debounce != 0)
+ s3_debounce = ilog2(s3_debounce);
+
+ /* s3 debounce is SEC_ACCESS register */
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_SEC_ACCESS(pon),
+ 0xFF, QPNP_PON_SEC_UNLOCK);
+ if (rc) {
+ dev_err(&pdev->dev, "Unable to do SEC_ACCESS rc:%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_S3_DBC_CTL(pon),
+ QPNP_PON_S3_DBC_DELAY_MASK, s3_debounce);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Unable to set S3 debounce rc:%d\n",
+ rc);
+ return rc;
+ }
+ }
+
+ /* program s3 source */
+ s3_src = "kpdpwr-and-resin";
+ rc = of_property_read_string(pon->pdev->dev.of_node,
+ "qcom,s3-src", &s3_src);
+ if (rc && rc != -EINVAL) {
+ dev_err(&pon->pdev->dev, "Unable to read s3 timer rc: %d\n",
+ rc);
+ return rc;
+ }
+
+ if (!strcmp(s3_src, "kpdpwr"))
+ s3_src_reg = QPNP_PON_S3_SRC_KPDPWR;
+ else if (!strcmp(s3_src, "resin"))
+ s3_src_reg = QPNP_PON_S3_SRC_RESIN;
+ else if (!strcmp(s3_src, "kpdpwr-or-resin"))
+ s3_src_reg = QPNP_PON_S3_SRC_KPDPWR_OR_RESIN;
+ else /* default combination */
+ s3_src_reg = QPNP_PON_S3_SRC_KPDPWR_AND_RESIN;
+
+ /*
+ * S3 source is a write once register. If the register has
+ * been configured by bootloader then this operation will
+ * not be effective.
+ */
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_S3_SRC(pon),
+ QPNP_PON_S3_SRC_MASK, s3_src_reg);
+ if (rc) {
+ dev_err(&pdev->dev, "Unable to program s3 source rc: %d\n",
+ rc);
+ return rc;
+ }
+
+ dev_set_drvdata(&pdev->dev, pon);
+
+ INIT_DELAYED_WORK(&pon->bark_work, bark_work_func);
+
+ /* register the PON configurations */
+ rc = qpnp_pon_config_init(pon);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Unable to initialize PON configurations rc: %d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
+ "qcom,pon-dbc-delay", &delay);
+ if (rc) {
+ if (rc != -EINVAL) {
+ dev_err(&pdev->dev,
+ "Unable to read debounce delay rc: %d\n", rc);
+ return rc;
+ }
+ } else {
+ rc = qpnp_pon_set_dbc(pon, delay);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Unable to set PON debounce delay rc=%d\n", rc);
+ return rc;
+ }
+ }
+ rc = qpnp_pon_get_dbc(pon, &pon->dbc_time_us);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Unable to get PON debounce delay rc=%d\n", rc);
+ return rc;
+ }
+
+ pon->kpdpwr_dbc_enable = of_property_read_bool(pon->pdev->dev.of_node,
+ "qcom,kpdpwr-sw-debounce");
+
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
+ "qcom,warm-reset-poweroff-type",
+ &pon->warm_reset_poff_type);
+ if (rc) {
+ if (rc != -EINVAL) {
+ dev_err(&pdev->dev, "Unable to read warm reset poweroff type rc: %d\n",
+ rc);
+ return rc;
+ }
+ pon->warm_reset_poff_type = -EINVAL;
+ } else if (pon->warm_reset_poff_type <= PON_POWER_OFF_RESERVED ||
+ pon->warm_reset_poff_type >= PON_POWER_OFF_MAX_TYPE) {
+ dev_err(&pdev->dev, "Invalid warm-reset-poweroff-type\n");
+ pon->warm_reset_poff_type = -EINVAL;
+ }
+
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
+ "qcom,hard-reset-poweroff-type",
+ &pon->hard_reset_poff_type);
+ if (rc) {
+ if (rc != -EINVAL) {
+ dev_err(&pdev->dev, "Unable to read hard reset poweroff type rc: %d\n",
+ rc);
+ return rc;
+ }
+ pon->hard_reset_poff_type = -EINVAL;
+ } else if (pon->hard_reset_poff_type <= PON_POWER_OFF_RESERVED ||
+ pon->hard_reset_poff_type >= PON_POWER_OFF_MAX_TYPE) {
+ dev_err(&pdev->dev, "Invalid hard-reset-poweroff-type\n");
+ pon->hard_reset_poff_type = -EINVAL;
+ }
+
+ rc = of_property_read_u32(pon->pdev->dev.of_node,
+ "qcom,shutdown-poweroff-type",
+ &pon->shutdown_poff_type);
+ if (rc) {
+ if (rc != -EINVAL) {
+ dev_err(&pdev->dev, "Unable to read shutdown poweroff type rc: %d\n",
+ rc);
+ return rc;
+ }
+ pon->shutdown_poff_type = -EINVAL;
+ } else if (pon->shutdown_poff_type <= PON_POWER_OFF_RESERVED ||
+ pon->shutdown_poff_type >= PON_POWER_OFF_MAX_TYPE) {
+ dev_err(&pdev->dev, "Invalid shutdown-poweroff-type\n");
+ pon->shutdown_poff_type = -EINVAL;
+ }
+
+ rc = device_create_file(&pdev->dev, &dev_attr_debounce_us);
+ if (rc) {
+ dev_err(&pdev->dev, "sys file creation failed rc: %d\n", rc);
+ return rc;
+ }
+
+ if (of_property_read_bool(pdev->dev.of_node,
+ "qcom,secondary-pon-reset")) {
+ if (sys_reset) {
+ dev_err(&pdev->dev,
+ "qcom,system-reset property shouldn't be used along with qcom,secondary-pon-reset property\n");
+ return -EINVAL;
+ }
+ spin_lock_irqsave(&spon_list_slock, flags);
+ list_add(&pon->list, &spon_dev_list);
+ spin_unlock_irqrestore(&spon_list_slock, flags);
+ pon->is_spon = true;
+ }
+
+ /* config whether store the hard reset reason */
+ pon->store_hard_reset_reason = of_property_read_bool(pdev->dev.of_node,
+ "qcom,store-hard-reset-reason");
+
+ qpnp_pon_debugfs_init(pdev);
+ return 0;
+}
+
+static int qpnp_pon_remove(struct platform_device *pdev)
+{
+ struct qpnp_pon *pon = dev_get_drvdata(&pdev->dev);
+ unsigned long flags;
+
+ device_remove_file(&pdev->dev, &dev_attr_debounce_us);
+
+ cancel_delayed_work_sync(&pon->bark_work);
+
+ if (pon->pon_input)
+ input_unregister_device(pon->pon_input);
+ qpnp_pon_debugfs_remove(pdev);
+ if (pon->is_spon) {
+ spin_lock_irqsave(&spon_list_slock, flags);
+ list_del(&pon->list);
+ spin_unlock_irqrestore(&spon_list_slock, flags);
+ }
+ return 0;
+}
+
+static const struct of_device_id spmi_match_table[] = {
+ { .compatible = "qcom,qpnp-power-on", },
+ {}
+};
+
+static struct platform_driver qpnp_pon_driver = {
+ .driver = {
+ .name = "qcom,qpnp-power-on",
+ .of_match_table = spmi_match_table,
+ },
+ .probe = qpnp_pon_probe,
+ .remove = qpnp_pon_remove,
+};
+
+static int __init qpnp_pon_init(void)
+{
+ return platform_driver_register(&qpnp_pon_driver);
+}
+subsys_initcall(qpnp_pon_init);
+
+static void __exit qpnp_pon_exit(void)
+{
+ return platform_driver_unregister(&qpnp_pon_driver);
+}
+module_exit(qpnp_pon_exit);
+
+MODULE_DESCRIPTION("QPNP PMIC POWER-ON driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/misc/vl53L0/Makefile b/drivers/input/misc/vl53L0/Makefile
new file mode 100644
index 000000000000..f105e1c3c60f
--- /dev/null
+++ b/drivers/input/misc/vl53L0/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for the vl53L0 drivers.
+#
+
+# Each configuration option enables a list of files.
+#FEATURE_USE_CCI := false
+FEATURE_USE_CCI := true
+
+ifeq ($(FEATURE_USE_CCI), true)
+ccflags-y += -Idrivers/input/misc/vl53L0/inc -DCAMERA_CCI
+else
+ccflags-y += -Idrivers/input/misc/vl53L0/inc
+endif
+
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/common
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
+obj-$(CONFIG_INPUT_STMVL53L0) += stmvl53l0.o
+stmvl53l0-objs := stmvl53l0_module.o stmvl53l0_module-i2c.o stmvl53l0_module-cci.o src/vl53l0_api_calibration.o src/vl53l0_api_core.o src/vl53l0_api_histogram.o src/vl53l0_api_ranging.o src/vl53l0_api_strings.o src/vl53l0_api.o src/vl53l0_platform.o src/vl53l0_i2c_platform.o src/vl53l0_port_i2c.o src/vl53l010_api.o src/vl53l010_tuning.o
diff --git a/drivers/input/misc/vl53L0/inc/vl53l010_api.h b/drivers/input/misc/vl53L0/inc/vl53l010_api.h
new file mode 100644
index 000000000000..282c65e33a93
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l010_api.h
@@ -0,0 +1,1476 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+/*
+ * @file vl53l0_api.h
+ * $Date: 2014-12-04 16:15:06 +0100 (Thu, 04 Dec 2014) $
+ * Revision: 1906
+ */
+
+
+
+#ifndef _VL53L010_API_H_
+#define _VL53L010_API_H_
+
+#include "vl53l010_device.h"
+#include "vl53l010_strings.h"
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef _MSC_VER
+# ifdef VL53L0_API_EXPORTS
+# define VL53L010_API __declspec(dllexport)
+# else
+# define VL53L010_API
+# endif
+#else
+# define VL53L010_API
+#endif
+
+
+/** @defgroup VL53L010_cut10_group VL53L010 cut1.0 Function Definition
+ * @brief VL53L010 cut1.0 Function Definition
+ * @{
+ */
+
+/** @defgroup VL53L010_general_group VL53L010 General Functions
+ * @brief VL53L010 General functions and definitions
+ * @{
+ */
+
+/**
+ * @brief Return the VL53L0 PAL Implementation Version
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param pVersion Pointer to current PAL Implementation Version
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetVersion(VL53L0_Version_t *pVersion);
+
+/**
+ * @brief Return the PAL Specification Version used for the current
+ * implementation.
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param pPalSpecVersion Pointer to current PAL Specification Version
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetPalSpecVersion(
+ VL53L0_Version_t *pPalSpecVersion);
+
+
+/**
+ * @brief Reads the Device information for given Device
+ *
+ * @note This function Access to the device.\n
+ * Use ProductRevisionMajor and ProductRevisionMinor to know the cut
+ * of the device used.
+ *
+ * @param Dev Device Handle
+ * @param pVL53L0_DeviceInfo Pointer to current device info for a given
+ * Device
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetDeviceInfo(VL53L0_DEV Dev,
+ VL53L0_DeviceInfo_t *pVL53L0_DeviceInfo);
+
+
+/**
+ * @brief Read current status of the error register for the selected device
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pDeviceErrorStatus Pointer to current error code of the device
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetDeviceErrorStatus(VL53L0_DEV Dev,
+ VL53L010_DeviceError * pDeviceErrorStatus);
+
+/**
+ * @brief Human readable error string for a given Error Code
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param ErrorCode The error code as stored on
+ * ::VL53L0_DeviceError
+ * @param pDeviceErrorString The error string corresponding to the
+ * ErrorCode
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetDeviceErrorString(
+ VL53L010_DeviceError ErrorCode,
+ char *pDeviceErrorString);
+
+
+/**
+ * @brief Human readable error string for current PAL error status
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param PalErrorCode The error code as stored on @a VL53L0_Error
+ * @param pPalErrorString The error string corresponding to the
+ * PalErrorCode
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetPalErrorString(VL53L0_Error PalErrorCode,
+ char *pPalErrorString);
+
+
+/**
+ * @brief Reads the internal state of the PAL for a given Device
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param Dev Device Handle
+ * @param pPalState Pointer to current state of the PAL for a
+ * given Device
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetPalState(VL53L0_DEV Dev,
+ VL53L0_State * pPalState);
+
+
+/**
+ * @brief Set the power mode for a given Device
+ * The power mode can be Standby or Idle. Different level of both Standby and
+ * Idle can exists.
+ * This function should not be used when device is in Ranging state.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param PowerMode The value of the power mode to set.
+ * see ::VL53L0_PowerModes Valid values are:
+ * VL53L0_POWERMODE_STANDBY_LEVEL1, VL53L0_POWERMODE_IDLE_LEVEL1
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when PowerMode
+ * is not in the supported list
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetPowerMode(VL53L0_DEV Dev,
+ VL53L0_PowerModes PowerMode);
+
+/**
+ * @brief Get the power mode for a given Device
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pPowerMode Pointer to the current value of the power
+ * mode. see ::VL53L0_PowerModes. Valid values are:
+ * VL53L0_POWERMODE_STANDBY_LEVEL1, VL53L0_POWERMODE_IDLE_LEVEL1
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetPowerMode(VL53L0_DEV Dev,
+ VL53L0_PowerModes * pPowerMode);
+
+
+/**
+ * Set or over-hide part to part calibration offset
+ * \sa VL53L0_DataInit() VL53L0_GetOffsetCalibrationDataMicroMeter()
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param OffsetCalibrationDataMicroMeter Offset (in micrometer)
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetOffsetCalibrationDataMicroMeter(
+ VL53L0_DEV Dev,
+ int32_t OffsetCalibrationDataMicroMeter);
+
+/**
+ * @brief Get part to part calibration offset
+ *
+ * @par Function Description
+ * Should only be used after a successful call to @a VL53L0_DataInit to backup
+ * device NVM value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pOffsetCalibrationDataMicroMeter Return part to part calibration
+ * offset from device (in micro meter)
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetOffsetCalibrationDataMicroMeter(
+ VL53L0_DEV Dev,
+ int32_t *pOffsetCalibrationDataMicroMeter);
+
+/**
+ * Set Group parameter Hold state
+ *
+ * @par Function Description
+ * Set or remove device internal group parameter hold
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param GroupParamHold Group parameter Hold state to be set (on/off)
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L010_API VL53L0_Error VL53L010_SetGroupParamHold(VL53L0_DEV Dev,
+ uint8_t GroupParamHold);
+
+/**
+ * @brief Get the maximal distance for actual setup
+ * @par Function Description
+ * Device must be initialized through @a VL53L0_SetParameters() prior calling
+ * this function.
+ *
+ * Any range value more than the value returned is to be considered as "no
+ * target detected"
+ * or "no target in detectable range"\n
+ * @warning The maximal distance depends on the setup
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param pUpperLimitMilliMeter The maximal range limit for actual setup
+ * (in millimeter)
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L010_API VL53L0_Error VL53L010_GetUpperLimitMilliMeter(VL53L0_DEV Dev,
+ uint16_t *pUpperLimitMilliMeter);
+
+/** @} VL53L010_general_group */
+
+
+/** @defgroup VL53L010_init_group VL53L010 Init Functions
+ * @brief VL53L010 Init Functions
+ * @{
+ */
+
+/**
+ * @brief Set new device address
+ *
+ * After completion the device will answer to the new address programmed. This
+ * function should be called when several devices are used in parallel
+ * before start programming the sensor.
+ * When a single device us used, there is no need to call this function.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param DeviceAddress The new Device address
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetDeviceAddress(VL53L0_DEV Dev,
+ uint8_t DeviceAddress);
+
+/**
+ *
+ * @brief One time device initialization
+ *
+ * To be called once and only once after device is brought out of reset (Chip
+ * enable) and booted see @a VL53L0_WaitDeviceBooted()
+ *
+ * @par Function Description
+ * When not used after a fresh device "power up" or reset, it may return @a
+ * #VL53L0_ERROR_CALIBRATION_WARNING
+ * meaning wrong calibration data may have been fetched from device that can
+ * result in ranging offset error\n
+ * If application cannot execute device reset or need to run VL53L0_DataInit
+ * multiple time
+ * then it must ensure proper offset calibration saving and restore on its own
+ * by using @a VL53L0_GetOffsetCalibrationData() on first power up and then @a
+ * VL53L0_SetOffsetCalibrationData() in all subsequent init
+ * This function will change the VL53L0_State from VL53L0_STATE_POWERDOWN to
+ * VL53L0_STATE_WAIT_STATICINIT.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_DataInit(VL53L0_DEV Dev);
+
+/**
+ * @brief Do basic device init (and eventually patch loading)
+ * This function will change the VL53L0_State from VL53L0_STATE_WAIT_STATICINIT
+ * to VL53L0_STATE_IDLE.
+ * In this stage all defalut setting will be applied.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_StaticInit(VL53L0_DEV Dev);
+
+/**
+ * @brief Wait for device booted after chip enable (hardware standby)
+ * This function can be run only when VL53L0_State is VL53L0_STATE_POWERDOWN.
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ *
+ */
+VL53L010_API VL53L0_Error VL53L010_WaitDeviceBooted(VL53L0_DEV Dev);
+
+/**
+ * @brief Do an hard reset or soft reset (depending on implementation) of the
+ * device \n
+ * After call of this function, device must be in same state as right after a
+ * power-up sequence.
+ * This function will change the VL53L0_State to VL53L0_STATE_POWERDOWN.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_ResetDevice(VL53L0_DEV Dev);
+
+/** @} VL53L010_init_group */
+
+
+/** @defgroup VL53L010_parameters_group VL53L010 Parameters Functions
+ * @brief VL53L010 Functions used to prepare and setup the device
+ * @{
+ */
+
+/**
+ * @brief Prepare device for operation
+ * @par Function Description
+ * Update device with provided parameters
+ * @li Then start ranging operation.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pDeviceParameters Pointer to store current device parameters.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetDeviceParameters(VL53L0_DEV Dev,
+ const VL53L0_DeviceParameters_t *pDeviceParameters);
+
+/**
+ * @brief Retrieve current device parameters
+ * @par Function Description
+ * Get actual parameters of the device
+ * @li Then start ranging operation.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pDeviceParameters Pointer to store current device parameters.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetDeviceParameters(VL53L0_DEV Dev,
+ VL53L0_DeviceParameters_t *pDeviceParameters);
+
+/**
+ * @brief Set a new device mode
+ * @par Function Description
+ * Set device to a new mode (ranging, histogram ...)
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param DeviceMode New device mode to apply
+ * Valid values are:
+ * VL53L0_DEVICEMODE_SINGLE_RANGING
+ * VL53L0_DEVICEMODE_CONTINUOUS_RANGING
+ * VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING
+ * VL53L0_DEVICEMODE_SINGLE_HISTOGRAM
+ * (functionality not available)
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when
+ * DeviceMode is not in the supported list
+ */
+VL53L010_API VL53L0_Error VL53L010_SetDeviceMode(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode);
+
+/**
+ * @brief Get current new device mode
+ * @par Function Description
+ * Get actual mode of the device(ranging, histogram ...)
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pDeviceMode Pointer to current apply mode value
+ * Valid values are:
+ * VL53L0_DEVICEMODE_SINGLE_RANGING
+ * VL53L0_DEVICEMODE_CONTINUOUS_RANGING
+ * VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING
+ * VL53L0_DEVICEMODE_SINGLE_HISTOGRAM
+ * (functionality not available)
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when
+ * DeviceMode is not in the supported list
+ */
+VL53L010_API VL53L0_Error VL53L010_GetDeviceMode(VL53L0_DEV Dev,
+ VL53L0_DeviceModes * pDeviceMode);
+
+/**
+ * @brief Set a new Histogram mode
+ * @par Function Description
+ * Set device to a new Histogram mode
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param HistogramMode New device mode to apply
+ * Valid values are:
+ * VL53L0_HISTOGRAMMODE_DISABLED
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when
+ * HistogramMode is not in the supported list
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetHistogramMode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes HistogramMode);
+
+/**
+ * @brief Get current new device mode
+ * @par Function Description
+ * Get current Histogram mode of a Device
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pHistogramMode Pointer to current Histogram Mode value
+ * Valid values are:
+ * VL53L0_HISTOGRAMMODE_DISABLED
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetHistogramMode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes * pHistogramMode);
+
+/**
+ * @brief Set Ranging Timing Budget in microseconds
+ *
+ * @par Function Description
+ * Defines the maximum time allowed by the user to the device to run a full
+ * ranging sequence
+ * for the current mode (ranging, histogram, ASL ...)
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param MeasurementTimingBudgetMicroSeconds Max measurement time in
+ * microseconds.
+ * Valid values are:
+ * >= 17000 microseconds when
+ * wraparound is enabled
+ * >= 12000 microseconds when
+ * wraparound is disabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned if
+ * MeasurementTimingBudgetMicroSeconds is out of range
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetMeasurementTimingBudgetMicroSeconds(
+ VL53L0_DEV Dev,
+ uint32_t MeasurementTimingBudgetMicroSeconds);
+
+/**
+ * @brief Get Ranging Timing Budget in microseconds
+ *
+ * @par Function Description
+ * Returns the programmed the maximum time allowed by the user to the device to
+ * run a full ranging sequence
+ * for the current mode (ranging, histogram, ASL ...)
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pMeasurementTimingBudgetMicroSeconds Max measurement time in
+ * microseconds.
+ * Valid values are:
+ * >= 17000 microseconds when
+ * wraparound is enabled
+ * >= 12000 microseconds when
+ * wraparound is disabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetMeasurementTimingBudgetMicroSeconds(
+ VL53L0_DEV Dev,
+ uint32_t *pMeasurementTimingBudgetMicroSeconds);
+
+/**
+ * Program continuous mode Inter-Measurement period in milliseconds
+ *
+ * @par Function Description
+ * When trying to set too short time return INVALID_PARAMS minimal value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param InterMeasurementPeriodMilliSeconds Requires Inter-Measurement
+ * Period in milliseconds.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetInterMeasurementPeriodMilliSeconds(
+ VL53L0_DEV Dev,
+ uint32_t InterMeasurementPeriodMilliSeconds);
+
+/**
+ * Get continuous mode Inter-Measurement period in milliseconds
+ *
+ * @par Function Description
+ * When trying to set too short time return INVALID_PARAMS minimal value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pInterMeasurementPeriodMilliSeconds Pointer to programmed
+ * Inter-Measurement Period in milliseconds.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetInterMeasurementPeriodMilliSeconds(
+ VL53L0_DEV Dev,
+ uint32_t *pInterMeasurementPeriodMilliSeconds);
+
+/**
+ * @brief Enable/Disable Cross talk compensation feature
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param XTalkCompensationEnable Cross talk compensation to be set
+ * 0=disabled else = enabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetXTalkCompensationEnable(
+ VL53L0_DEV Dev, uint8_t XTalkCompensationEnable);
+
+/**
+ * @brief Get Cross talk compensation rate
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pXTalkCompensationEnable Pointer to the Cross talk compensation
+ * state 0=disabled or 1 = enabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetXTalkCompensationEnable(
+ VL53L0_DEV Dev, uint8_t *pXTalkCompensationEnable);
+
+/**
+ * @brief Set Cross talk compensation rate
+ *
+ * @par Function Description
+ * Set Cross talk compensation rate.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param XTalkCompensationRateMegaCps Compensation rate in Mega counts per
+ * second (16.16 fix point) see datasheet for details
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetXTalkCompensationRateMegaCps(
+ VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCompensationRateMegaCps);
+
+/**
+ * @brief Get Cross talk compensation rate
+ *
+ * @par Function Description
+ * Get Cross talk compensation rate.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pXTalkCompensationRateMegaCps Pointer to Compensation rate in Mega
+ * counts per second (16.16 fix point) see datasheet for details
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetXTalkCompensationRateMegaCps(
+ VL53L0_DEV Dev,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps);
+
+
+/**
+ * @brief Get the number of the check limit managed by a given Device
+ *
+ * @par Function Description
+ * This function give the number of the check limit managed by the Device
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param pNumberOfLimitCheck Pointer to the number of check limit.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetNumberOfLimitCheck(
+ uint16_t *pNumberOfLimitCheck);
+
+/**
+ * @brief Return a description string for a given limit check number
+ *
+ * @par Function Description
+ * This function returns a description string for a given limit check number.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID (0<= LimitCheckId <
+ * VL53L0_GetNumberOfLimitCheck() ).
+ * @param pLimitCheckString Pointer to the description string of
+ * the given check limit.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned when
+ * LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetLimitCheckInfo(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, char *pLimitCheckString);
+
+
+/**
+ * @brief Enable/Disable a specific limit check
+ *
+ * @par Function Description
+ * This function Enable/Disable a specific limit check.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID (0<= LimitCheckId <
+ * VL53L0_GetNumberOfLimitCheck() ).
+ * @param LimitCheckEnable if 1 the check limit corresponding to
+ * LimitCheckId is Enabled
+ * if 0 the check limit corresponding to
+ * LimitCheckId is disabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned when
+ * LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetLimitCheckEnable(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, uint8_t LimitCheckEnable);
+
+
+/**
+ * @brief Get specific limit check enable state
+ *
+ * @par Function Description
+ * This function get the enable state of a specific limit check.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID (0<= LimitCheckId <
+ * VL53L0_GetNumberOfLimitCheck() ).
+ * @param pLimitCheckEnable Pointer to the check limit enable
+ * value.
+ * if 1 the check limit corresponding to
+ * LimitCheckId is Enabled
+ * if 0 the check limit corresponding to
+ * LimitCheckId is disabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned when
+ * LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetLimitCheckEnable(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, uint8_t *pLimitCheckEnable);
+
+/**
+ * @brief Set a specific limit check value
+ *
+ * @par Function Description
+ * This function set a specific limit check value.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID (0<= LimitCheckId <
+ * VL53L0_GetNumberOfLimitCheck() ).
+ * @param LimitCheckValue Limit check Value for a given
+ * LimitCheckId
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned when either
+ * LimitCheckId or LimitCheckValue value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetLimitCheckValue(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, FixPoint1616_t LimitCheckValue);
+
+/**
+ * @brief Get a specific limit check value
+ *
+ * @par Function Description
+ * This function get a specific limit check value from device then it updates
+ * internal values and check enables.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID (0<= LimitCheckId <
+ * VL53L0_GetNumberOfLimitCheck() ).
+ * @param pLimitCheckValue Pointer to Limit check Value for a
+ * given LimitCheckId.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned when
+ * LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetLimitCheckValue(VL53L0_DEV Dev,
+ uint16_t LimitCheckId,
+ FixPoint1616_t *pLimitCheckValue);
+
+
+/**
+ * @brief Get the current value of the signal used for the limit check
+ *
+ * @par Function Description
+ * This function get a the current value of the signal used for the limit check.
+ * To obtain the latest value you should run a ranging before.
+ * The value reported is linked to the limit check identified with the
+ * LimitCheckId.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID (0<= LimitCheckId <
+ * VL53L0_GetNumberOfLimitCheck() ).
+ * @param pLimitCheckCurrent Pointer to current Value for a
+ * given LimitCheckId.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned when
+ * LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetLimitCheckCurrent(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, FixPoint1616_t *pLimitCheckCurrent);
+
+/**
+ * @brief Enable (or disable) Wrap around Check
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param WrapAroundCheckEnable Wrap around Check to be set 0=disabled,
+ * other = enabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetWrapAroundCheckEnable(VL53L0_DEV Dev,
+ uint8_t WrapAroundCheckEnable);
+
+/**
+ * @brief Get setup of Wrap around Check
+ *
+ * @par Function Description
+ * This function get the wrapAround check enable parameters
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pWrapAroundCheckEnable Pointer to the Wrap around Check state
+ * 0=disabled or 1 = enabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetWrapAroundCheckEnable(VL53L0_DEV Dev,
+ uint8_t *pWrapAroundCheckEnable);
+
+/** @} VL53L010_parameters_group */
+
+
+/** @defgroup VL53L010_measurement_group VL53L010 Measurement Functions
+ * @brief VL53L010 Functions used for the measurements
+ * @{
+ */
+
+/**
+ * @brief Single shot measurement.
+ *
+ * @par Function Description
+ * Perform simple measurement sequence (Start measure, Wait measure to end, and
+ * returns when measurement is done).
+ * Once function returns, user can get valid data by calling
+ * VL53L0_GetRangingMeasurement or VL53L0_GetHistogramMeasurement depending on
+ * defined measurement mode
+ * User should Clear the interrupt in case this are enabled by using the
+ * function VL53L0_ClearInterruptMask().
+ *
+ * @warning This function is a blocking function
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_PerformSingleMeasurement(VL53L0_DEV Dev);
+
+/**
+ * @brief Perform Reference Calibration
+ *
+ * @details Perform a reference calibration of the Device.
+ * This function should be run from time to time before doing a ranging
+ * measurement.
+ * This function will launch a special ranging measurement, so if interrupt are
+ * enable an interrupt will be done.
+ * This function will clear the interrupt generated automatically.
+ *
+ * @warning This function is a blocking function
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_PerformRefCalibration(VL53L0_DEV Dev);
+
+/**
+ * @brief Perform XTalk Calibration
+ *
+ * @details Perform a XTalk calibration of the Device.
+ * This function will launch a ranging measurement, if interrupts are enabled
+ * an interrupt will be done.
+ * This function will clear the interrupt generated automatically.
+ * This function will program a new value for the XTalk compensation and it
+ * will enable the cross talk before exit.
+ *
+ * @warning This function is a blocking function
+ *
+ * @note This function Access to the device
+ *
+ * @note This function change the device mode to
+ * VL53L0_DEVICEMODE_SINGLE_RANGING
+ *
+ * @param Dev Device Handle
+ * @param XTalkCalDistance XTalkCalDistance value used for the
+ * XTalk computation.
+ * @param pXTalkCompensationRateMegaCps Pointer to new XTalkCompensation
+ * value.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_PerformXTalkCalibration(VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCalDistance,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps);
+
+/**
+ * @brief Perform Offset Calibration
+ *
+ * @details Perform a Offset calibration of the Device.
+ * This function will launch a ranging measurement, if interrupts are
+ * enabled an interrupt will be done.
+ * This function will clear the interrupt generated automatically.
+ * This function will program a new value for the Offset calibration value and
+ *
+ * @warning This function is a blocking function
+ *
+ * @note This function Access to the device
+ *
+ * @note This function does not change the device mode.
+ *
+ * @param Dev Device Handle
+ * @param CalDistanceMilliMeter Calibration distance value used for the
+ * offset compensation.
+ * @param pOffsetMicroMeter Pointer to new Offset value computed by the
+ * function.
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_PerformOffsetCalibration(VL53L0_DEV Dev,
+ FixPoint1616_t CalDistanceMilliMeter, int32_t *pOffsetMicroMeter);
+
+/**
+ * @brief Start device measurement
+ *
+ * @details Started measurement will depend on device parameters set through @a
+ * VL53L0_SetParameters()
+ * This is a non-blocking function
+ * This function will change the VL53L0_State from VL53L0_STATE_IDLE to
+ * VL53L0_STATE_RUNNING.
+ *
+ * @note This function Access to the device
+ *
+
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when
+ * DeviceMode programmed with @a VL53L0_SetDeviceMode is not in the supported
+ * list:
+ * Supported mode are:
+ * VL53L0_DEVICEMODE_SINGLE_RANGING, VL53L0_DEVICEMODE_CONTINUOUS_RANGING,
+ * VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING
+ * @return VL53L0_ERROR_TIME_OUT Time out on start measurement
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_StartMeasurement(VL53L0_DEV Dev);
+
+/**
+ * @brief Stop device measurement
+ *
+ * @details Will set the device in standby mode at end of current measurement \n
+ * Not necessary in single mode as device shall return automatically
+ * in standby mode at end of measurement.
+ * This function will change the VL53L0_State from
+ * VL53L0_STATE_RUNNING to VL53L0_STATE_IDLE.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_StopMeasurement(VL53L0_DEV Dev);
+
+/**
+ * @brief Return Measurement Data Ready
+ *
+ * @par Function Description
+ * This function indicate that a measurement data is ready.
+ * This function check if interrupt mode is used then check is done accordingly.
+ * If perform function clear the interrupt, this function will not work, like
+ * in case of @a VL53L0_PerformSingleRangingMeasurement().
+ * The previous function is blocking function, VL53L0_GetMeasurementDataReady
+ * is used for non-blocking capture.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pMeasurementDataReady Pointer to Measurement Data Ready. 0=data
+ * not ready, 1 = data ready
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetMeasurementDataReady(VL53L0_DEV Dev,
+ uint8_t *pMeasurementDataReady);
+
+/**
+ * @brief Wait for device ready for a new measurement command. Blocking
+ * function.
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param MaxLoop Max Number of polling loop (timeout).
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L010_API VL53L0_Error VL53L010_WaitDeviceReadyForNewMeasurement(
+ VL53L0_DEV Dev,
+ uint32_t MaxLoop);
+
+
+/**
+ * @brief Retrieve the measurements from device for a given setup
+ *
+ * @par Function Description
+ * Get data from last successful Ranging measurement
+ * @warning USER should take care about @a VL53L0_GetNumberOfROIZones() before
+ * get data.
+ * PAL will fill a NumberOfROIZones times the corresponding data structure used
+ * in the measurement function.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pRangingMeasurementData Pointer to the data structure to fill up.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetRangingMeasurementData(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData);
+
+/**
+ * @brief Retrieve the measurements from device for a given setup
+ *
+ * @par Function Description
+ * Get data from last successful Histogram measurement
+ * @warning USER should take care about @a VL53L0_GetNumberOfROIZones() before
+ * get data.
+ * PAL will fill a NumberOfROIZones times the corresponding data structure used
+ * in the measurement function.
+ * @note This function is not Implemented
+ * @param Dev Device Handle
+ * @param pHistogramMeasurementData Pointer to the data structure to fill
+ * up.
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L010_API VL53L0_Error VL53L010_GetHistogramMeasurementData(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData);
+
+/**
+ * @brief Performs a single ranging measurement and retrieve the ranging
+ * measurement data
+ *
+ * @par Function Description
+ * This function will change the device mode to
+ * VL53L0_DEVICEMODE_SINGLE_RANGING with @a VL53L0_SetDeviceMode(),
+ * It performs measurement with @a VL53L0_PerformSingleMeasurement()
+ * It get data from last successful Ranging measurement with @a
+ * VL53L0_GetRangingMeasurementData.
+ * Finally it clear the interrupt with @a VL53L0_ClearInterruptMask().
+ * @note This function Access to the device
+ *
+ * @note This function change the device mode to
+ * VL53L0_DEVICEMODE_SINGLE_RANGING
+ *
+ * @param Dev Device Handle
+ * @param pRangingMeasurementData Pointer to the data structure to fill up.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_PerformSingleRangingMeasurement(
+ VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData);
+
+/**
+ * @brief Performs a single histogram measurement and retrieve the histogram
+ * measurement data
+ * Is equivalent to VL53L0_PerformSingleMeasurement +
+ * VL53L0_GetHistogramMeasurementData
+ *
+ * @par Function Description
+ * Get data from last successful Ranging measurement.
+ * This function will clear the interrupt in case of these are enabled.
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param pHistogramMeasurementData Pointer to the data structure to fill
+ * up.
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L010_API VL53L0_Error VL53L010_PerformSingleHistogramMeasurement(
+ VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData);
+
+
+
+/**
+ * @brief Set the number of ROI Zones to be used for a specific Device
+ *
+ * @par Function Description
+ * Set the number of ROI Zones to be used for a specific Device.
+ * The programmed value should be less than the max number of ROI Zones given
+ * with @a VL53L0_GetMaxNumberOfROIZones().
+ * This version of API manage only one zone.
+ *
+ * @param Dev Device Handle
+ * @param NumberOfROIZones Number of ROI Zones to be used for a
+ * specific Device.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned if
+ * NumberOfROIZones != 1
+ */
+VL53L010_API VL53L0_Error VL53L010_SetNumberOfROIZones(VL53L0_DEV Dev,
+ uint8_t NumberOfROIZones);
+
+/**
+ * @brief Get the number of ROI Zones managed by the Device
+ *
+ * @par Function Description
+ * Get number of ROI Zones managed by the Device
+ * USER should take care about @a VL53L0_GetNumberOfROIZones() before get data
+ * after a perform measurement.
+ * PAL will fill a NumberOfROIZones times the corresponding data structure used
+ * in the measurement function.
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pNumberOfROIZones Pointer to the Number of ROI Zones
+ * value.
+ * @return VL53L0_ERROR_NONE Success
+ */
+VL53L010_API VL53L0_Error VL53L010_GetNumberOfROIZones(VL53L0_DEV Dev,
+ uint8_t *pNumberOfROIZones);
+
+/**
+ * @brief Get the Maximum number of ROI Zones managed by the Device
+ *
+ * @par Function Description
+ * Get Maximum number of ROI Zones managed by the Device.
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pMaxNumberOfROIZones Pointer to the Maximum Number of ROI
+ * Zones value.
+ * @return VL53L0_ERROR_NONE Success
+ */
+VL53L010_API VL53L0_Error VL53L010_GetMaxNumberOfROIZones(VL53L0_DEV Dev,
+ uint8_t *pMaxNumberOfROIZones);
+
+
+/** @} VL53L010_measurement_group */
+
+
+/** @defgroup VL53L010_interrupt_group VL53L010 Interrupt Functions
+ * @brief VL53L010 Functions used for interrupt managements
+ * @{
+ */
+
+/**
+ * @brief Set the configuration of GPIO pin for a given device
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param Pin ID of the GPIO Pin
+ * @param Functionality Select Pin functionality. Refer to
+ * ::VL53L0_GpioFunctionality
+ * @param DeviceMode Device Mode associated to the Gpio.
+ * @param Polarity Set interrupt polarity. Active high or active
+ * low see ::VL53L0_InterruptPolarity
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_GPIO_NOT_EXISTING Only Pin=0 is
+ * accepted.
+ * @return VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED This error occurs
+ * when Functionality programmed is not in the supported list:
+ * Supported value
+ * are:
+ *
+ * VL53L0_GPIOFUNCTIONALITY_OFF, VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW,
+ * VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH,
+ * VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT,
+ *
+ * VL53L0_GPIOFUNCTIONALITY_NEW_MEASURE_READY
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetGpioConfig(VL53L0_DEV Dev, uint8_t Pin,
+ VL53L0_DeviceModes DeviceMode,
+ VL53L0_GpioFunctionality Functionality,
+ VL53L0_InterruptPolarity Polarity);
+
+
+/**
+ * @brief Get current configuration for GPIO pin for a given device
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param Pin ID of the GPIO Pin
+ * @param pDeviceMode Pointer to Device Mode associated to the Gpio.
+ * @param pFunctionality Pointer to Pin functionality.
+ * Refer to ::VL53L0_GpioFunctionality
+ * @param pPolarity Pointer to interrupt polarity. Active high or
+ * active low see ::VL53L0_InterruptPolarity
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_GPIO_NOT_EXISTING Only Pin=0 is accepted.
+ * @return VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED This error occurs
+ * when Functionality programmed is not in the supported list:
+ * Supported value are:
+ * VL53L0_GPIOFUNCTIONALITY_OFF, VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW,
+ * VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH,
+ * VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT,
+ * VL53L0_GPIOFUNCTIONALITY_NEW_MEASURE_READY
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetGpioConfig(VL53L0_DEV Dev, uint8_t Pin,
+ VL53L0_DeviceModes * pDeviceMode,
+ VL53L0_GpioFunctionality * pFunctionality,
+ VL53L0_InterruptPolarity * pPolarity);
+
+/**
+ * @brief Set low and high Interrupt thresholds for a given mode (ranging, ALS,
+ * ...) for a given device
+ *
+ * @par Function Description
+ * Set low and high Interrupt thresholds for a given mode (ranging, ALS, ...)
+ * for a given device
+ *
+ * @note This function Access to the device
+ *
+ * @note DeviceMode is ignored for the current device
+ *
+ * @param Dev Device Handle
+ * @param DeviceMode Device Mode for which change thresholds
+ * @param ThresholdLow Low threshold (mm, lux ..., depending on the
+ * mode)
+ * @param ThresholdHigh High threshold (mm, lux ..., depending on the
+ * mode)
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetInterruptThresholds(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode,
+ FixPoint1616_t ThresholdLow,
+ FixPoint1616_t ThresholdHigh);
+
+/**
+ * @brief Get high and low Interrupt thresholds for a given mode (ranging,
+ * ALS, ...) for a given device
+ *
+ * @par Function Description
+ * Get high and low Interrupt thresholds for a given mode (ranging, ALS, ...)
+ * for a given device
+ *
+ * @note This function Access to the device
+ *
+ * @note DeviceMode is ignored for the current device
+ *
+ * @param Dev Device Handle
+ * @param DeviceMode Device Mode from which read thresholds
+ * @param pThresholdLow Low threshold (mm, lux ..., depending on the
+ * mode)
+ * @param pThresholdHigh High threshold (mm, lux ..., depending on the
+ * mode)
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetInterruptThresholds(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode,
+ FixPoint1616_t *pThresholdLow,
+ FixPoint1616_t *pThresholdHigh);
+
+/**
+ * @brief Clear given system interrupt condition
+ *
+ * @par Function Description
+ * Clear given interrupt(s).
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param InterruptMask Mask of interrupts to clear
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_ClearInterruptMask(VL53L0_DEV Dev,
+ uint32_t InterruptMask);
+
+/**
+ * @brief Return device interrupt status
+ *
+ * @par Function Description
+ * Returns currently raised interrupts by the device.
+ * User shall be able to activate/deactivate interrupts through
+ * @a VL53L0_SetGpioConfig()
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pInterruptMaskStatus Pointer to status variable to update
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetInterruptMaskStatus(VL53L0_DEV Dev,
+ uint32_t *pInterruptMaskStatus);
+
+
+/**
+ * @brief Configure ranging interrupt reported to system
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param InterruptMask Mask of interrupt to Enable/disable
+ * (0:interrupt disabled or 1: interrupt enabled)
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L010_API VL53L0_Error VL53L010_EnableInterruptMask(VL53L0_DEV Dev,
+ uint32_t InterruptMask);
+
+
+/** @} VL53L010_interrupt_group */
+
+
+/** @defgroup VL53L010_SPADfunctions_group VL53L010 SPAD Functions
+ * @brief VL53L010 Functions used for SPAD managements
+ * @{
+ */
+
+
+
+/**
+ * @brief Set the SPAD Ambient Damper Threshold value
+ *
+ * @par Function Description
+ * This function set the SPAD Ambient Damper Threshold value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param SpadAmbientDamperThreshold SPAD Ambient Damper Threshold value
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetSpadAmbientDamperThreshold(VL53L0_DEV Dev,
+ uint16_t SpadAmbientDamperThreshold);
+
+/**
+ * @brief Get the current SPAD Ambient Damper Threshold value
+ *
+ * @par Function Description
+ * This function get the SPAD Ambient Damper Threshold value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pSpadAmbientDamperThreshold Pointer to programmed SPAD Ambient
+ * Damper Threshold value
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetSpadAmbientDamperThreshold(VL53L0_DEV Dev,
+ uint16_t *pSpadAmbientDamperThreshold);
+
+
+/**
+ * @brief Set the SPAD Ambient Damper Factor value
+ *
+ * @par Function Description
+ * This function set the SPAD Ambient Damper Factor value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param SpadAmbientDamperFactor SPAD Ambient Damper Factor value
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_SetSpadAmbientDamperFactor(VL53L0_DEV Dev,
+ uint16_t SpadAmbientDamperFactor);
+
+/**
+ * @brief Get the current SPAD Ambient Damper Factor value
+ *
+ * @par Function Description
+ * This function get the SPAD Ambient Damper Factor value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pSpadAmbientDamperFactor Pointer to programmed SPAD Ambient
+ * Damper Factor value
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L010_API VL53L0_Error VL53L010_GetSpadAmbientDamperFactor(VL53L0_DEV Dev,
+ uint16_t *pSpadAmbientDamperFactor);
+
+
+/** @} VL53L010_SPADfunctions_group */
+
+/** @} VL53L010_cut10_group */
+#define VL53L010_EXTERNAL
+
+
+/* Internal functions declaration */
+VL53L010_EXTERNAL VL53L0_Error VL53L010_get_vcsel_pulse_period(VL53L0_DEV Dev,
+ uint8_t *pVCSELPulsePeriod,
+ uint8_t RangeIndex);
+VL53L010_EXTERNAL uint8_t VL53L010_encode_vcsel_period(
+ uint8_t vcsel_period_pclks);
+VL53L010_EXTERNAL uint8_t VL53L010_decode_vcsel_period(uint8_t
+ vcsel_period_reg);
+VL53L010_EXTERNAL uint16_t VL53L010_calc_encoded_timeout(VL53L0_DEV Dev,
+ uint32_t
+ timeout_period_us,
+ uint8_t vcsel_period);
+VL53L010_EXTERNAL uint32_t VL53L010_calc_ranging_wait_us(VL53L0_DEV Dev,
+ uint16_t
+ timeout_overall_periods,
+ uint8_t vcsel_period);
+VL53L010_EXTERNAL VL53L0_Error VL53L010_load_additional_settings1(VL53L0_DEV
+ Dev);
+VL53L010_EXTERNAL VL53L0_Error VL53L010_load_additional_settings3(VL53L0_DEV
+ Dev);
+VL53L010_EXTERNAL VL53L0_Error VL53L010_check_part_used(VL53L0_DEV Dev,
+ uint8_t *Revision,
+ VL53L0_DeviceInfo_t *
+ pVL53L0_DeviceInfo);
+VL53L010_EXTERNAL VL53L0_Error VL53L010_get_info_from_device(VL53L0_DEV Dev);
+VL53L010_EXTERNAL VL53L0_Error VL53L010_device_read_strobe(VL53L0_DEV Dev);
+VL53L010_EXTERNAL VL53L0_Error VL53L010_get_pal_range_status(VL53L0_DEV Dev,
+ uint8_t
+ DeviceRangeStatus,
+ FixPoint1616_t
+ SignalRate,
+ FixPoint1616_t
+ CrosstalkCompensation,
+ uint16_t
+ EffectiveSpadRtnCount,
+ VL53L0_RangingMeasurementData_t
+ *
+ pRangingMeasurementData,
+ uint8_t *
+ pPalRangeStatus);
+
+
+VL53L010_EXTERNAL uint32_t VL53L010_calc_macro_period_ps(VL53L0_DEV Dev,
+ uint8_t vcsel_period);
+VL53L010_EXTERNAL uint16_t VL53L010_encode_timeout(uint32_t timeout_mclks);
+VL53L010_EXTERNAL uint32_t VL53L010_decode_timeout(uint16_t encoded_timeout);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L010_API_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l010_device.h b/drivers/input/misc/vl53L0/inc/vl53l010_device.h
new file mode 100644
index 000000000000..5d36ab0f65e4
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l010_device.h
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+/**
+ * Device specific defines. To be adapted by implementer for the targeted
+ * device.
+ */
+
+#ifndef _VL53L010_DEVICE_H_
+#define _VL53L010_DEVICE_H_
+
+#include "vl53l0_types.h"
+
+/** @defgroup VL53L010_SpecDefines_group VL53L010 cut1.0 Device Specific Defines
+ * @brief VL53L010 cut1.0 Device Specific Defines
+ * @{
+ */
+
+/** @defgroup VL53L010_DeviceError_group Device Error
+ * @brief Device Error code
+ *
+ * This enum is Device specific it should be updated in the implementation
+ * Use @a VL53L010_GetStatusErrorString() to get the string.
+ * It is related to Status Register of the Device.
+ * @{
+ */
+typedef uint8_t VL53L010_DeviceError;
+
+#define VL53L010_DEVICEERROR_NONE ((VL53L010_DeviceError) 0)
+#define VL53L010_DEVICEERROR_VCSELCONTINUITYTESTFAILURE \
+ ((VL53L010_DeviceError) 1)
+#define VL53L010_DEVICEERROR_VCSELWATCHDOGTESTFAILURE \
+ ((VL53L010_DeviceError) 2)
+#define VL53L010_DEVICEERROR_NOVHVVALUEFOUND \
+ ((VL53L010_DeviceError) 3)
+#define VL53L010_DEVICEERROR_MSRCNOTARGET \
+ ((VL53L010_DeviceError) 4)
+#define VL53L010_DEVICEERROR_MSRCMINIMUMSNR \
+ ((VL53L010_DeviceError) 5)
+#define VL53L010_DEVICEERROR_MSRCWRAPAROUND \
+ ((VL53L010_DeviceError) 6)
+#define VL53L010_DEVICEERROR_TCC \
+ ((VL53L010_DeviceError) 7)
+#define VL53L010_DEVICEERROR_RANGEAWRAPAROUND ((VL53L010_DeviceError)8)
+#define VL53L010_DEVICEERROR_RANGEBWRAPAROUND ((VL53L010_DeviceError)9)
+#define VL53L010_DEVICEERROR_MINCLIP ((VL53L010_DeviceError) 10)
+#define VL53L010_DEVICEERROR_RANGECOMPLETE ((VL53L010_DeviceError) 11)
+#define VL53L010_DEVICEERROR_ALGOUNDERFLOW ((VL53L010_DeviceError) 12)
+#define VL53L010_DEVICEERROR_ALGOOVERFLOW ((VL53L010_DeviceError) 13)
+#define VL53L010_DEVICEERROR_FINALSNRLIMIT ((VL53L010_DeviceError) 14)
+#define VL53L010_DEVICEERROR_NOTARGETIGNORE ((VL53L010_DeviceError) 15)
+
+/** @} VL53L010_DeviceError_group */
+
+/** @defgroup VL53L010_CheckEnable_group Check Enable list
+ * @brief Check Enable code
+ *
+ * Define used to specify the LimitCheckId.
+ * Use @a VL53L010_GetLimitCheckInfo() to get the string.
+ * @{
+ */
+
+#define VL53L010_CHECKENABLE_SIGMA_FINAL_RANGE 0
+#define VL53L010_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE 1
+#define VL53L010_CHECKENABLE_NUMBER_OF_CHECKS 2
+
+/** @} VL53L010_CheckEnable_group */
+
+/** @defgroup VL53L010_GpioFunctionality_group Gpio Functionality
+ * @brief Defines the different functionalities for the device GPIO(s)
+ * @{
+ */
+typedef uint8_t VL53L010_GpioFunctionality;
+
+#define VL53L010_GPIOFUNCTIONALITY_OFF \
+ ((VL53L010_GpioFunctionality) 0)/*!< NO Interrupt */
+#define VL53L010_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW \
+ ((VL53L010_GpioFunctionality) 1)/*!< Level Low (value < thresh_low) */
+#define VL53L010_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH \
+ ((VL53L010_GpioFunctionality) 2)/*!< Level High (value>thresh_high) */
+/*!< Out Of Window (value < thresh_low OR value > thresh_high) */
+#define VL53L010_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT \
+ ((VL53L010_GpioFunctionality) 3)
+#define VL53L010_GPIOFUNCTIONALITY_NEW_MEASURE_READY \
+ ((VL53L010_GpioFunctionality) 4) /*!< New Sample Ready */
+
+/** @} VL53L010_GpioFunctionality_group */
+
+/* Device register map */
+
+/** @defgroup VL53L010_DefineRegisters_group Define Registers
+ * @brief List of all the defined registers
+ * @{
+ */
+#define VL53L010_REG_SYSRANGE_START 0x000
+ /** mask existing bit in #VL53L010_REG_SYSRANGE_START*/
+#define VL53L010_REG_SYSRANGE_MODE_MASK 0x0F
+ /** bit 0 in #VL53L010_REG_SYSRANGE_START write 1 toggle state in
+ * continuous mode and arm next shot in single shot mode
+ */
+#define VL53L010_REG_SYSRANGE_MODE_START_STOP 0x01
+ /** bit 1 write 0 in #VL53L010_REG_SYSRANGE_START set single shot mode */
+#define VL53L010_REG_SYSRANGE_MODE_SINGLESHOT 0x00
+ /** bit 1 write 1 in #VL53L010_REG_SYSRANGE_START set back-to-back
+ * operation mode
+ */
+#define VL53L010_REG_SYSRANGE_MODE_BACKTOBACK 0x02
+ /** bit 2 write 1 in #VL53L010_REG_SYSRANGE_START set timed operation
+ * mode
+ */
+#define VL53L010_REG_SYSRANGE_MODE_TIMED 0x04
+ /** bit 3 write 1 in #VL53L010_REG_SYSRANGE_START set histogram
+ * operation mode
+ */
+#define VL53L010_REG_SYSRANGE_MODE_HISTOGRAM 0x08
+
+#define VL53L010_REG_SYSTEM_THRESH_HIGH 0x000C /* NOSLC 2 bytes */
+#define VL53L010_REG_SYSTEM_THRESH_LOW 0x000E /* NOSLC 2 bytes */
+
+/* FPGA bitstream */
+#define VL53L010_REG_SYSTEM_SEQUENCE_CONFIG 0x0001
+#define VL53L010_REG_SYSTEM_INTERMEASUREMENT_PERIOD 0x0004
+
+#define VL53L010_REG_SYSTEM_REPORT_REQUEST 0x0009
+#define VL53L010_REG_SYSTEM_RANGEA_DATA 0x04
+#define VL53L010_REG_SYSTEM_RANGEB_DATA 0x05
+
+#define VL53L010_REG_SYSTEM_INTERRUPT_CONFIG_GPIO 0x000A
+#define VL53L010_REG_SYSTEM_INTERRUPT_GPIO_DISABLED 0x00
+#define VL53L010_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_LOW 0x01
+#define VL53L010_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_HIGH 0x02
+#define VL53L010_REG_SYSTEM_INTERRUPT_GPIO_OUT_OF_WINDOW 0x03
+#define VL53L010_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY 0x04
+
+#define VL53L010_REG_GPIO_HV_MUX_ACTIVE_HIGH 0x0084
+
+#define VL53L010_REG_SYSTEM_INTERRUPT_CLEAR 0x000B
+
+/* Result registers */
+#define VL53L010_REG_RESULT_INTERRUPT_STATUS 0x0013
+#define VL53L010_REG_RESULT_RANGE_STATUS 0x0014
+
+#define VL53L010_REG_RESULT_SIGNAL_COUNT_RATE_RET 0x001A
+#define VL53L010_REG_RESULT_AMBIENT_COUNT_RATE_RET 0x001C
+#define VL53L010_REG_RESULT_FINAL_RANGE 0x001E
+
+/* Algo register */
+#define VL53L010_REG_ALGO_CROSSTALK_COMPENSATION_RATE 0x0020
+#define VL53L010_REG_ALGO_RANGE_IGNORE_VALID_HEIGHT 0x0025
+#define VL53L010_REG_ALGO_RANGE_IGNORE_THRESHOLD 0x0026
+#define VL53L010_REG_ALGO_SNR_RATIO 0x0027
+#define VL53L010_REG_ALGO_RANGE_CHECK_ENABLES 0x0028
+
+#define VL53L010_REG_ALGO_PART_TO_PART_RANGE_OFFSET 0x0029
+
+#define VL53L010_REG_I2C_SLAVE_DEVICE_ADDRESS 0x008a
+
+/* MSRC registers */
+#define VL53L010_REG_MSRC_CONFIG_COUNT 0x0044
+#define VL53L010_REG_MSRC_CONFIG_TIMEOUT 0x0046
+#define VL53L010_REG_MSRC_CONFIG_MIN_SNR 0x0055
+#define VL53L010_REG_MSRC_CONFIG_VALID_PHASE_LOW 0x0047
+#define VL53L010_REG_MSRC_CONFIG_VALID_PHASE_HIGH 0x0048
+
+/* RANGE A registers */
+#define VL53L010_REG_RNGA_CONFIG_VCSEL_PERIOD 0x0050
+#define VL53L010_REG_RNGA_TIMEOUT_MSB 0x0051
+#define VL53L010_REG_RNGA_TIMEOUT_LSB 0x0052
+#define VL53L010_REG_RNGA_CONFIG_VALID_PHASE_LOW 0x0056
+#define VL53L010_REG_RNGA_CONFIG_VALID_PHASE_HIGH 0x0057
+
+/* RANGE B1 registers */
+#define VL53L010_REG_RNGB1_CONFIG_VCSEL_PERIOD 0x0060
+#define VL53L010_REG_RNGB1_TIMEOUT_MSB 0x0061
+#define VL53L010_REG_RNGB1_TIMEOUT_LSB 0x0062
+#define VL53L010_REG_RNGB1_CONFIG_VALID_PHASE_LOW 0x0066
+#define VL53L010_REG_RNGB1_CONFIG_VALID_PHASE_HIGH 0x0067
+
+/* RANGE B2 registers */
+#define VL53L010_REG_RNGB2_CONFIG_VCSEL_PERIOD 0x0070
+#define VL53L010_REG_RNGB2_TIMEOUT_MSB 0x0071
+#define VL53L010_REG_RNGB2_TIMEOUT_LSB 0x0072
+#define VL53L010_REG_RNGB2_CONFIG_VALID_PHASE_LOW 0x0076
+#define VL53L010_REG_RNGB2_CONFIG_VALID_PHASE_HIGH 0x0077
+
+#define VL53L010_REG_SOFT_RESET_GO2_SOFT_RESET_N 0x00bf
+#define VL53L010_REG_IDENTIFICATION_MODEL_ID 0x00c0
+#define VL53L010_REG_IDENTIFICATION_REVISION_ID 0x00c2
+#define VL53L010_REG_IDENTIFICATION_MODULE_ID 0x00c3
+
+#define VL53L010_REG_OSC_CALIBRATE_VAL 0x00f8
+
+#define VL53L010_REG_FIRMWARE_MODE_STATUS 0x00C5
+
+#define VL53L010_REG_DYNAMIC_SPAD_ACTUAL_RTN_SPADS_INT 0x0016
+
+#define VL53L010_SIGMA_ESTIMATE_MAX_VALUE 65535
+/*equivalent to a range sigma of 655.35mm */
+
+/*
+ * Speed of light in um per 1E-10 Seconds
+ */
+
+#define VL53L010_SPEED_OF_LIGHT_IN_AIR 2997
+
+/** @} VL53L010_DefineRegisters_group */
+
+/** @} VL53L010_SpecDefines_group */
+
+#endif
+
+/* _VL53L010_DEVICE_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l010_strings.h b/drivers/input/misc/vl53L0/inc/vl53l010_strings.h
new file mode 100644
index 000000000000..714a0f1c479f
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l010_strings.h
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef VL53L010_STRINGS_H_
+#define VL53L010_STRINGS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #define VL53L010_STRING_DEVICE_INFO_NAME \
+ "VL53L0 cut1.0"
+ #define VL53L010_STRING_DEVICE_INFO_NAME_TS0 \
+ "VL53L0 TS0"
+ #define VL53L010_STRING_DEVICE_INFO_NAME_TS1 \
+ "VL53L0 TS1"
+ #define VL53L010_STRING_DEVICE_INFO_NAME_TS2 \
+ "VL53L0 TS2"
+ #define VL53L010_STRING_DEVICE_INFO_NAME_ES1 \
+ "VL53L0 ES1 or later"
+ #define VL53L010_STRING_DEVICE_INFO_TYPE \
+ "VL53L0"
+
+ /* PAL ERROR strings */
+ #define VL53L010_STRING_ERROR_NONE \
+ "No Error"
+ #define VL53L010_STRING_ERROR_CALIBRATION_WARNING \
+ "Calibration Warning Error"
+ #define VL53L010_STRING_ERROR_MIN_CLIPPED \
+ "Min clipped error"
+ #define VL53L010_STRING_ERROR_UNDEFINED \
+ "Undefined error"
+ #define VL53L010_STRING_ERROR_INVALID_PARAMS \
+ "Invalid parameters error"
+ #define VL53L010_STRING_ERROR_NOT_SUPPORTED \
+ "Not supported error"
+ #define VL53L010_STRING_ERROR_RANGE_ERROR \
+ "Range error"
+ #define VL53L010_STRING_ERROR_TIME_OUT \
+ "Time out error"
+ #define VL53L010_STRING_ERROR_MODE_NOT_SUPPORTED \
+ "Mode not supported error"
+ #define VL53L010_STRING_ERROR_NOT_IMPLEMENTED \
+ "Not implemented error"
+
+ #define VL53L010_STRING_UNKNOW_ERROR_CODE \
+ "Unknow Error Code"
+ #define VL53L010_STRING_ERROR_BUFFER_TOO_SMALL \
+ "Buffer too small"
+
+ #define VL53L010_STRING_ERROR_GPIO_NOT_EXISTING \
+ "GPIO not existing"
+ #define VL53L010_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED \
+ "GPIO functionality not supported"
+ #define VL53L010_STRING_ERROR_CONTROL_INTERFACE \
+ "Control Interface Error"
+
+
+ /* Device Specific */
+ #define VL53L010_STRING_DEVICEERROR_NONE \
+ "No Update"
+ #define VL53L010_STRING_DEVICEERROR_VCSELCONTINUITYTESTFAILURE \
+ "VCSEL Continuity Test Failure"
+ #define VL53L010_STRING_DEVICEERROR_VCSELWATCHDOGTESTFAILURE \
+ "VCSEL Watchdog Test Failure"
+ #define VL53L010_STRING_DEVICEERROR_NOVHVVALUEFOUND \
+ "No VHV Value found"
+ #define VL53L010_STRING_DEVICEERROR_MSRCNOTARGET \
+ "MSRC No Target Error"
+ #define VL53L010_STRING_DEVICEERROR_MSRCMINIMUMSNR \
+ "MSRC Minimum SNR Error"
+ #define VL53L010_STRING_DEVICEERROR_MSRCWRAPAROUND \
+ "MSRC Wraparound Error"
+ #define VL53L010_STRING_DEVICEERROR_TCC \
+ "TCC Error"
+ #define VL53L010_STRING_DEVICEERROR_RANGEAWRAPAROUND \
+ "Range A Wraparound Error"
+ #define VL53L010_STRING_DEVICEERROR_RANGEBWRAPAROUND \
+ "Range B Wraparound Error"
+ #define VL53L010_STRING_DEVICEERROR_MINCLIP \
+ "Min Clip Error"
+ #define VL53L010_STRING_DEVICEERROR_RANGECOMPLETE \
+ "Range Complete"
+ #define VL53L010_STRING_DEVICEERROR_ALGOUNDERFLOW \
+ "Range Algo Underflow Error"
+ #define VL53L010_STRING_DEVICEERROR_ALGOOVERFLOW \
+ "Range Algo Overlow Error"
+ #define VL53L010_STRING_DEVICEERROR_FINALSNRLIMIT \
+ "Final Minimum SNR Error"
+ #define VL53L010_STRING_DEVICEERROR_NOTARGETIGNORE \
+ "No Target Ignore Error"
+ #define VL53L010_STRING_DEVICEERROR_UNKNOWN \
+ "Unknown error code"
+
+
+ /* Check Enable */
+ #define VL53L010_STRING_CHECKENABLE_SIGMA \
+ "SIGMA"
+ #define VL53L010_STRING_CHECKENABLE_SIGNAL_RATE \
+ "SIGNAL RATE"
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/drivers/input/misc/vl53L0/inc/vl53l010_tuning.h b/drivers/input/misc/vl53L0/inc/vl53l010_tuning.h
new file mode 100644
index 000000000000..fe7906044feb
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l010_tuning.h
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef _VL53L010_TUNING_H_
+#define _VL53L010_TUNING_H_
+
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief Internal function used to Program the default tuning settings
+ *
+ * @ingroup VL53L0_general_group
+ * @note This function access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L010_load_tuning_settings(VL53L0_DEV Dev);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L010_TUNING_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_api.h b/drivers/input/misc/vl53L0/inc/vl53l0_api.h
new file mode 100644
index 000000000000..4f6f8020de49
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_api.h
@@ -0,0 +1,1950 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+ IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef _VL53L0_API_H_
+#define _VL53L0_API_H_
+
+#include "vl53l0_api_strings.h"
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef _MSC_VER
+# ifdef VL53L0_API_EXPORTS
+# define VL53L0_API __declspec(dllexport)
+# else
+# define VL53L0_API
+# endif
+#else
+# define VL53L0_API
+#endif
+
+/** @defgroup VL53L0_cut11_group VL53L0 cut1.1 Function Definition
+ * @brief VL53L0 cut1.1 Function Definition
+ * @{
+ */
+
+/** @defgroup VL53L0_general_group VL53L0 General Functions
+ * @brief General functions and definitions
+ * @{
+ */
+
+/**
+ * @brief Return the VL53L0 PAL Implementation Version
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param pVersion Pointer to current PAL Implementation Version
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetVersion(VL53L0_Version_t *pVersion);
+
+/**
+ * @brief Return the PAL Specification Version used for the current
+ * implementation.
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param pPalSpecVersion Pointer to current PAL Specification Version
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetPalSpecVersion(
+ VL53L0_Version_t *pPalSpecVersion);
+
+/**
+ * @brief Reads the Product Revision for a for given Device
+ * This function can be used to distinguish cut1.0 from cut1.1.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pProductRevisionMajor Pointer to Product Revision Major
+ * for a given Device
+ * @param pProductRevisionMinor Pointer to Product Revision Minor
+ * for a given Device
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetProductRevision(VL53L0_DEV Dev,
+ uint8_t *pProductRevisionMajor, uint8_t *pProductRevisionMinor);
+
+/**
+ * @brief Reads the Device information for given Device
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pVL53L0_DeviceInfo Pointer to current device info for a given
+ * Device
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetDeviceInfo(VL53L0_DEV Dev,
+ VL53L0_DeviceInfo_t *pVL53L0_DeviceInfo);
+
+/**
+ * @brief Read current status of the error register for the selected device
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pDeviceErrorStatus Pointer to current error code of the device
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetDeviceErrorStatus(VL53L0_DEV Dev,
+ VL53L0_DeviceError * pDeviceErrorStatus);
+
+/**
+ * @brief Human readable Range Status string for a given RangeStatus
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param RangeStatus The RangeStatus code as stored on
+ * @a VL53L0_RangingMeasurementData_t
+ * @param pRangeStatusString The returned RangeStatus string.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetRangeStatusString(uint8_t RangeStatus,
+ char *pRangeStatusString);
+
+/**
+ * @brief Human readable error string for a given Error Code
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param ErrorCode The error code as stored on ::VL53L0_DeviceError
+ * @param pDeviceErrorString The error string corresponding to the ErrorCode
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetDeviceErrorString(
+ VL53L0_DeviceError ErrorCode, char *pDeviceErrorString);
+
+/**
+ * @brief Human readable error string for current PAL error status
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param PalErrorCode The error code as stored on @a VL53L0_Error
+ * @param pPalErrorString The error string corresponding to the
+ * PalErrorCode
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetPalErrorString(VL53L0_Error PalErrorCode,
+ char *pPalErrorString);
+
+/**
+ * @brief Human readable PAL State string
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param PalStateCode The State code as stored on @a VL53L0_State
+ * @param pPalStateString The State string corresponding to the
+ * PalStateCode
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetPalStateString(VL53L0_State PalStateCode,
+ char *pPalStateString);
+
+/**
+ * @brief Reads the internal state of the PAL for a given Device
+ *
+ * @note This function doesn't access to the device
+ *
+ * @param Dev Device Handle
+ * @param pPalState Pointer to current state of the PAL for a
+ * given Device
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetPalState(VL53L0_DEV Dev,
+ VL53L0_State * pPalState);
+
+/**
+ * @brief Set the power mode for a given Device
+ * The power mode can be Standby or Idle. Different level of both Standby and
+ * Idle can exists.
+ * This function should not be used when device is in Ranging state.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param PowerMode The value of the power mode to set.
+ * see ::VL53L0_PowerModes
+ * Valid values are:
+ * VL53L0_POWERMODE_STANDBY_LEVEL1,
+ * VL53L0_POWERMODE_IDLE_LEVEL1
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when PowerMode
+ * is not in the supported list
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetPowerMode(VL53L0_DEV Dev,
+ VL53L0_PowerModes PowerMode);
+
+/**
+ * @brief Get the power mode for a given Device
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pPowerMode Pointer to the current value of the power
+ * mode. see ::VL53L0_PowerModes
+ * Valid values are:
+ * VL53L0_POWERMODE_STANDBY_LEVEL1,
+ * VL53L0_POWERMODE_IDLE_LEVEL1
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetPowerMode(VL53L0_DEV Dev,
+ VL53L0_PowerModes * pPowerMode);
+
+/**
+ * Set or over-hide part to part calibration offset
+ * \sa VL53L0_DataInit() VL53L0_GetOffsetCalibrationDataMicroMeter()
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param OffsetCalibrationDataMicroMeter Offset (microns)
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetOffsetCalibrationDataMicroMeter(
+ VL53L0_DEV Dev, int32_t OffsetCalibrationDataMicroMeter);
+
+/**
+ * @brief Get part to part calibration offset
+ *
+ * @par Function Description
+ * Should only be used after a successful call to @a VL53L0_DataInit to backup
+ * device NVM value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pOffsetCalibrationDataMicroMeter Return part to part
+ * calibration offset from device (microns)
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetOffsetCalibrationDataMicroMeter(
+ VL53L0_DEV Dev, int32_t *pOffsetCalibrationDataMicroMeter);
+
+/**
+ * Set the linearity corrective gain
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LinearityCorrectiveGain Linearity corrective
+ * gain in x1000
+ * if value is 1000 then no modification is applied.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetLinearityCorrectiveGain(VL53L0_DEV Dev,
+ int16_t LinearityCorrectiveGain);
+
+/**
+ * @brief Get the linearity corrective gain
+ *
+ * @par Function Description
+ * Should only be used after a successful call to @a VL53L0_DataInit to backup
+ * device NVM value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pLinearityCorrectiveGain Pointer to the linearity
+ * corrective gain in x1000
+ * if value is 1000 then no modification is applied.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetLinearityCorrectiveGain(VL53L0_DEV Dev,
+ uint16_t *pLinearityCorrectiveGain);
+
+/**
+ * Set Group parameter Hold state
+ *
+ * @par Function Description
+ * Set or remove device internal group parameter hold
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param GroupParamHold Group parameter Hold state to be set (on/off)
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L0_API VL53L0_Error VL53L0_SetGroupParamHold(VL53L0_DEV Dev,
+ uint8_t GroupParamHold);
+
+/**
+ * @brief Get the maximal distance for actual setup
+ * @par Function Description
+ * Device must be initialized through @a VL53L0_SetParameters() prior calling
+ * this function.
+ *
+ * Any range value more than the value returned is to be considered as
+ * "no target detected" or
+ * "no target in detectable range"\n
+ * @warning The maximal distance depends on the setup
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param pUpperLimitMilliMeter The maximal range limit for actual setup
+ * (in millimeter)
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L0_API VL53L0_Error VL53L0_GetUpperLimitMilliMeter(VL53L0_DEV Dev,
+ uint16_t *pUpperLimitMilliMeter);
+
+
+/**
+ * @brief Get the Total Signal Rate
+ * @par Function Description
+ * This function will return the Total Signal Rate after a good ranging is done.
+ *
+ * @note This function access to Device
+ *
+ * @param Dev Device Handle
+ * @param pTotalSignalRate Total Signal Rate value in Mega count per second
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_GetTotalSignalRate(VL53L0_DEV Dev,
+ FixPoint1616_t *pTotalSignalRate);
+
+/** @} VL53L0_general_group */
+
+/** @defgroup VL53L0_init_group VL53L0 Init Functions
+ * @brief VL53L0 Init Functions
+ * @{
+ */
+
+/**
+ * @brief Set new device address
+ *
+ * After completion the device will answer to the new address programmed.
+ * This function should be called when several devices are used in parallel
+ * before start programming the sensor.
+ * When a single device us used, there is no need to call this function.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param DeviceAddress The new Device address
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetDeviceAddress(VL53L0_DEV Dev,
+ uint8_t DeviceAddress);
+
+/**
+ *
+ * @brief One time device initialization
+ *
+ * To be called once and only once after device is brought out of reset
+ * (Chip enable) and booted see @a VL53L0_WaitDeviceBooted()
+ *
+ * @par Function Description
+ * When not used after a fresh device "power up" or reset, it may return
+ * @a #VL53L0_ERROR_CALIBRATION_WARNING meaning wrong calibration data
+ * may have been fetched from device that can result in ranging offset error\n
+ * If application cannot execute device reset or need to run VL53L0_DataInit
+ * multiple time then it must ensure proper offset calibration saving and
+ * restore on its own by using @a VL53L0_GetOffsetCalibrationData() on first
+ * power up and then @a VL53L0_SetOffsetCalibrationData() in all subsequent init
+ * This function will change the VL53L0_State from VL53L0_STATE_POWERDOWN to
+ * VL53L0_STATE_WAIT_STATICINIT.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_DataInit(VL53L0_DEV Dev);
+
+/**
+ * @brief Set the tuning settings pointer
+ *
+ * This function is used to specify the Tuning settings buffer to be used
+ * for a given device. The buffer contains all the necessary data to permit
+ * the API to write tuning settings.
+ * This function permit to force the usage of either external or internal
+ * tuning settings.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pTuningSettingBuffer Pointer to tuning settings buffer.
+ * @param UseInternalTuningSettings Use internal tuning settings value.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetTuningSettingBuffer(VL53L0_DEV Dev,
+ uint8_t *pTuningSettingBuffer, uint8_t UseInternalTuningSettings);
+
+/**
+ * @brief Get the tuning settings pointer and the internal external switch
+ * value.
+ *
+ * This function is used to get the Tuning settings buffer pointer and the
+ * value.
+ * of the switch to select either external or internal tuning settings.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param ppTuningSettingBuffer Pointer to tuning settings buffer.
+ * @param pUseInternalTuningSettings Pointer to store Use internal tuning
+ * settings value.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetTuningSettingBuffer(VL53L0_DEV Dev,
+ uint8_t **ppTuningSettingBuffer, uint8_t *pUseInternalTuningSettings);
+
+/**
+ * @brief Do basic device init (and eventually patch loading)
+ * This function will change the VL53L0_State from
+ * VL53L0_STATE_WAIT_STATICINIT to VL53L0_STATE_IDLE.
+ * In this stage all default setting will be applied.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_StaticInit(VL53L0_DEV Dev);
+
+/**
+ * @brief Wait for device booted after chip enable (hardware standby)
+ * This function can be run only when VL53L0_State is VL53L0_STATE_POWERDOWN.
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ *
+ */
+VL53L0_API VL53L0_Error VL53L0_WaitDeviceBooted(VL53L0_DEV Dev);
+
+/**
+ * @brief Do an hard reset or soft reset (depending on implementation) of the
+ * device \nAfter call of this function, device must be in same state as right
+ * after a power-up sequence.This function will change the VL53L0_State to
+ * VL53L0_STATE_POWERDOWN.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_ResetDevice(VL53L0_DEV Dev);
+
+/** @} VL53L0_init_group */
+
+/** @defgroup VL53L0_parameters_group VL53L0 Parameters Functions
+ * @brief Functions used to prepare and setup the device
+ * @{
+ */
+
+/**
+ * @brief Prepare device for operation
+ * @par Function Description
+ * Update device with provided parameters
+ * @li Then start ranging operation.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pDeviceParameters Pointer to store current device parameters.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetDeviceParameters(VL53L0_DEV Dev,
+ const VL53L0_DeviceParameters_t *pDeviceParameters);
+
+/**
+ * @brief Retrieve current device parameters
+ * @par Function Description
+ * Get actual parameters of the device
+ * @li Then start ranging operation.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pDeviceParameters Pointer to store current device parameters.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetDeviceParameters(VL53L0_DEV Dev,
+ VL53L0_DeviceParameters_t *pDeviceParameters);
+
+/**
+ * @brief Set a new device mode
+ * @par Function Description
+ * Set device to a new mode (ranging, histogram ...)
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param DeviceMode New device mode to apply
+ * Valid values are:
+ * VL53L0_DEVICEMODE_SINGLE_RANGING
+ * VL53L0_DEVICEMODE_CONTINUOUS_RANGING
+ * VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING
+ * VL53L0_DEVICEMODE_SINGLE_HISTOGRAM
+ * VL53L0_HISTOGRAMMODE_REFERENCE_ONLY
+ * VL53L0_HISTOGRAMMODE_RETURN_ONLY
+ * VL53L0_HISTOGRAMMODE_BOTH
+ *
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when DeviceMode is
+ * not in the supported list
+ */
+VL53L0_API VL53L0_Error VL53L0_SetDeviceMode(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode);
+
+/**
+ * @brief Get current new device mode
+ * @par Function Description
+ * Get actual mode of the device(ranging, histogram ...)
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pDeviceMode Pointer to current apply mode value
+ * Valid values are:
+ * VL53L0_DEVICEMODE_SINGLE_RANGING
+ * VL53L0_DEVICEMODE_CONTINUOUS_RANGING
+ * VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING
+ * VL53L0_DEVICEMODE_SINGLE_HISTOGRAM
+ * VL53L0_HISTOGRAMMODE_REFERENCE_ONLY
+ * VL53L0_HISTOGRAMMODE_RETURN_ONLY
+ * VL53L0_HISTOGRAMMODE_BOTH
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when
+ * DeviceMode is not in the supported list
+ */
+VL53L0_API VL53L0_Error VL53L0_GetDeviceMode(VL53L0_DEV Dev,
+ VL53L0_DeviceModes * pDeviceMode);
+
+/**
+ * @brief Sets the resolution of range measurements.
+ * @par Function Description
+ * Set resolution of range measurements to either 0.25mm if
+ * fraction enabled or 1mm if not enabled.
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param Enable Enable high resolution
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetRangeFractionEnable(VL53L0_DEV Dev,
+ uint8_t Enable);
+
+/**
+ * @brief Gets the fraction enable parameter indicating the resolution of
+ * range measurements.
+ *
+ * @par Function Description
+ * Gets the fraction enable state, which translates to the resolution of
+ * range measurements as follows :Enabled:=0.25mm resolution,
+ * Not Enabled:=1mm resolution.
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param pEnable Output Parameter reporting the fraction enable state.
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetFractionEnable(VL53L0_DEV Dev,
+ uint8_t *pEnable);
+
+/**
+ * @brief Set a new Histogram mode
+ * @par Function Description
+ * Set device to a new Histogram mode
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param HistogramMode New device mode to apply
+ * Valid values are:
+ * VL53L0_HISTOGRAMMODE_DISABLED
+ * VL53L0_DEVICEMODE_SINGLE_HISTOGRAM
+ * VL53L0_HISTOGRAMMODE_REFERENCE_ONLY
+ * VL53L0_HISTOGRAMMODE_RETURN_ONLY
+ * VL53L0_HISTOGRAMMODE_BOTH
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when
+ * HistogramMode is not in the supported list
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetHistogramMode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes HistogramMode);
+
+/**
+ * @brief Get current new device mode
+ * @par Function Description
+ * Get current Histogram mode of a Device
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pHistogramMode Pointer to current Histogram Mode value
+ * Valid values are:
+ * VL53L0_HISTOGRAMMODE_DISABLED
+ * VL53L0_DEVICEMODE_SINGLE_HISTOGRAM
+ * VL53L0_HISTOGRAMMODE_REFERENCE_ONLY
+ * VL53L0_HISTOGRAMMODE_RETURN_ONLY
+ * VL53L0_HISTOGRAMMODE_BOTH
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetHistogramMode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes * pHistogramMode);
+
+/**
+ * @brief Set Ranging Timing Budget in microseconds
+ *
+ * @par Function Description
+ * Defines the maximum time allowed by the user to the device to run a
+ * full ranging sequence for the current mode (ranging, histogram, ASL ...)
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param MeasurementTimingBudgetMicroSeconds Max measurement time in
+ * microseconds.
+ * Valid values are:
+ * >= 17000 microsecs when wraparound enabled
+ * >= 12000 microsecs when wraparound disabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned if
+ MeasurementTimingBudgetMicroSeconds out of range
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetMeasurementTimingBudgetMicroSeconds(
+ VL53L0_DEV Dev, uint32_t MeasurementTimingBudgetMicroSeconds);
+
+/**
+ * @brief Get Ranging Timing Budget in microseconds
+ *
+ * @par Function Description
+ * Returns the programmed the maximum time allowed by the user to the
+ * device to run a full ranging sequence for the current mode
+ * (ranging, histogram, ASL ...)
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pMeasurementTimingBudgetMicroSeconds Max measurement time in
+ * microseconds.
+ * Valid values are:
+ * >= 17000 microsecs when wraparound enabled
+ * >= 12000 microsecs when wraparound disabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetMeasurementTimingBudgetMicroSeconds(
+ VL53L0_DEV Dev, uint32_t *pMeasurementTimingBudgetMicroSeconds);
+
+/**
+ * @brief Gets the VCSEL pulse period.
+ *
+ * @par Function Description
+ * This function retrieves the VCSEL pulse period for the given period type.
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param VcselPeriodType VCSEL period identifier (pre-range|final).
+ * @param pVCSELPulsePeriod Pointer to VCSEL period value.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS Error VcselPeriodType parameter not
+ * supported.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetVcselPulsePeriod(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType, uint8_t *pVCSELPulsePeriod);
+
+/**
+ * @brief Sets the VCSEL pulse period.
+ *
+ * @par Function Description
+ * This function retrieves the VCSEL pulse period for the given period type.
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param VcselPeriodType VCSEL period identifier (pre-range|final).
+ * @param VCSELPulsePeriod VCSEL period value
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS Error VcselPeriodType parameter not
+ * supported.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetVcselPulsePeriod(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType, uint8_t VCSELPulsePeriod);
+
+/**
+ * @brief Sets the (on/off) state of a requested sequence step.
+ *
+ * @par Function Description
+ * This function enables/disables a requested sequence step.
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param SequenceStepId Sequence step identifier.
+ * @param SequenceStepEnabled Demanded state {0=Off,1=On}
+ * is enabled.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS Error SequenceStepId parameter not
+ * supported.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetSequenceStepEnable(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId, uint8_t SequenceStepEnabled);
+
+/**
+ * @brief Gets the (on/off) state of a requested sequence step.
+ *
+ * @par Function Description
+ * This function retrieves the state of a requested sequence step, i.e. on/off.
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param SequenceStepId Sequence step identifier.
+ * @param pSequenceStepEnabled Out parameter reporting if the sequence step
+ * is enabled {0=Off,1=On}.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS Error SequenceStepId parameter not
+ * supported.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetSequenceStepEnable(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId, uint8_t *pSequenceStepEnabled);
+
+/**
+ * @brief Gets the (on/off) state of all sequence steps.
+ *
+ * @par Function Description
+ * This function retrieves the state of all sequence step in the scheduler.
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param pSchedulerSequenceSteps Pointer to struct containing result.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetSequenceStepEnables(VL53L0_DEV Dev,
+ VL53L0_SchedulerSequenceSteps_t *pSchedulerSequenceSteps);
+
+/**
+ * @brief Sets the timeout of a requested sequence step.
+ *
+ * @par Function Description
+ * This function sets the timeout of a requested sequence step.
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param SequenceStepId Sequence step identifier.
+ * @param TimeOutMilliSecs Demanded timeout
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS Error SequenceStepId parameter not
+ * supported.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetSequenceStepTimeout(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId, FixPoint1616_t TimeOutMilliSecs);
+
+/**
+ * @brief Gets the timeout of a requested sequence step.
+ *
+ * @par Function Description
+ * This function retrieves the timeout of a requested sequence step.
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param SequenceStepId Sequence step identifier.
+ * @param pTimeOutMilliSecs Timeout value.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS Error SequenceStepId parameter not
+ * supported.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetSequenceStepTimeout(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId,
+ FixPoint1616_t *pTimeOutMilliSecs);
+
+/**
+ * @brief Gets number of sequence steps managed by the API.
+ *
+ * @par Function Description
+ * This function retrieves the number of sequence steps currently managed
+ * by the API
+ *
+ * @note This function Accesses the device
+ *
+ * @param Dev Device Handle
+ * @param pNumberOfSequenceSteps Out parameter reporting the number of
+ * sequence steps.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetNumberOfSequenceSteps(VL53L0_DEV Dev,
+ uint8_t *pNumberOfSequenceSteps);
+
+/**
+ * @brief Gets the name of a given sequence step.
+ *
+ * @par Function Description
+ * This function retrieves the name of sequence steps corresponding to
+ * SequenceStepId.
+ *
+ * @note This function doesn't Accesses the device
+ *
+ * @param SequenceStepId Sequence step identifier.
+ * @param pSequenceStepsString Pointer to Info string
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetSequenceStepsInfo(
+ VL53L0_SequenceStepId SequenceStepId, char *pSequenceStepsString);
+
+/**
+ * Program continuous mode Inter-Measurement period in milliseconds
+ *
+ * @par Function Description
+ * When trying to set too short time return INVALID_PARAMS minimal value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param InterMeasurementPeriodMilliSeconds Inter-Measurement Period in ms.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetInterMeasurementPeriodMilliSeconds(
+ VL53L0_DEV Dev, uint32_t InterMeasurementPeriodMilliSeconds);
+
+/**
+ * Get continuous mode Inter-Measurement period in milliseconds
+ *
+ * @par Function Description
+ * When trying to set too short time return INVALID_PARAMS minimal value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pInterMeasurementPeriodMilliSeconds Pointer to programmed
+ * Inter-Measurement Period in milliseconds.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetInterMeasurementPeriodMilliSeconds(
+ VL53L0_DEV Dev, uint32_t *pInterMeasurementPeriodMilliSeconds);
+
+/**
+ * @brief Enable/Disable Cross talk compensation feature
+ *
+ * @note This function is not Implemented.
+ * Enable/Disable Cross Talk by set to zero the Cross Talk value
+ * by using @a VL53L0_SetXTalkCompensationRateMegaCps().
+ *
+ * @param Dev Device Handle
+ * @param XTalkCompensationEnable Cross talk compensation
+ * to be set 0=disabled else = enabled
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L0_API VL53L0_Error VL53L0_SetXTalkCompensationEnable(VL53L0_DEV Dev,
+ uint8_t XTalkCompensationEnable);
+
+/**
+ * @brief Get Cross talk compensation rate
+ *
+ * @note This function is not Implemented.
+ * Enable/Disable Cross Talk by set to zero the Cross Talk value by
+ * using @a VL53L0_SetXTalkCompensationRateMegaCps().
+ *
+ * @param Dev Device Handle
+ * @param pXTalkCompensationEnable Pointer to the Cross talk compensation
+ * state 0=disabled or 1 = enabled
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L0_API VL53L0_Error VL53L0_GetXTalkCompensationEnable(VL53L0_DEV Dev,
+ uint8_t *pXTalkCompensationEnable);
+
+/**
+ * @brief Set Cross talk compensation rate
+ *
+ * @par Function Description
+ * Set Cross talk compensation rate.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param XTalkCompensationRateMegaCps Compensation rate in
+ * Mega counts per second (16.16 fix point) see datasheet for details
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetXTalkCompensationRateMegaCps(VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCompensationRateMegaCps);
+
+/**
+ * @brief Get Cross talk compensation rate
+ *
+ * @par Function Description
+ * Get Cross talk compensation rate.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pXTalkCompensationRateMegaCps Pointer to Compensation rate
+ in Mega counts per second (16.16 fix point) see datasheet for details
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetXTalkCompensationRateMegaCps(VL53L0_DEV Dev,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps);
+
+/**
+ * @brief Set Reference Calibration Parameters
+ *
+ * @par Function Description
+ * Set Reference Calibration Parameters.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param VhvSettings Parameter for VHV
+ * @param PhaseCal Parameter for PhaseCal
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetRefCalibration(VL53L0_DEV Dev,
+ uint8_t VhvSettings, uint8_t PhaseCal);
+
+/**
+ * @brief Get Reference Calibration Parameters
+ *
+ * @par Function Description
+ * Get Reference Calibration Parameters.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pVhvSettings Pointer to VHV parameter
+ * @param pPhaseCal Pointer to PhaseCal Parameter
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetRefCalibration(VL53L0_DEV Dev,
+ uint8_t *pVhvSettings, uint8_t *pPhaseCal);
+
+/**
+ * @brief Get the number of the check limit managed by a given Device
+ *
+ * @par Function Description
+ * This function give the number of the check limit managed by the Device
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param pNumberOfLimitCheck Pointer to the number of check limit.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetNumberOfLimitCheck(
+ uint16_t *pNumberOfLimitCheck);
+
+/**
+ * @brief Return a description string for a given limit check number
+ *
+ * @par Function Description
+ * This function returns a description string for a given limit check number.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID
+ (0<= LimitCheckId < VL53L0_GetNumberOfLimitCheck() ).
+ * @param pLimitCheckString Pointer to the
+ description string of the given check limit.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is
+ returned when LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetLimitCheckInfo(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, char *pLimitCheckString);
+
+/**
+ * @brief Return a the Status of the specified check limit
+ *
+ * @par Function Description
+ * This function returns the Status of the specified check limit.
+ * The value indicate if the check is fail or not.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID
+ (0<= LimitCheckId < VL53L0_GetNumberOfLimitCheck() ).
+ * @param pLimitCheckStatus Pointer to the
+ Limit Check Status of the given check limit.
+ * LimitCheckStatus :
+ * 0 the check is not fail
+ * 1 the check if fail or not enabled
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is
+ returned when LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetLimitCheckStatus(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, uint8_t *pLimitCheckStatus);
+
+/**
+ * @brief Enable/Disable a specific limit check
+ *
+ * @par Function Description
+ * This function Enable/Disable a specific limit check.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID
+ * (0<= LimitCheckId < VL53L0_GetNumberOfLimitCheck() ).
+ * @param LimitCheckEnable if 1 the check limit
+ * corresponding to LimitCheckId is Enabled
+ * if 0 the check limit
+ * corresponding to LimitCheckId is disabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned
+ * when LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetLimitCheckEnable(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, uint8_t LimitCheckEnable);
+
+/**
+ * @brief Get specific limit check enable state
+ *
+ * @par Function Description
+ * This function get the enable state of a specific limit check.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID
+ * (0<= LimitCheckId < VL53L0_GetNumberOfLimitCheck() ).
+ * @param pLimitCheckEnable Pointer to the check limit enable
+ * value.
+ * if 1 the check limit
+ * corresponding to LimitCheckId is Enabled
+ * if 0 the check limit
+ * corresponding to LimitCheckId is disabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned
+ * when LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetLimitCheckEnable(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, uint8_t *pLimitCheckEnable);
+
+/**
+ * @brief Set a specific limit check value
+ *
+ * @par Function Description
+ * This function set a specific limit check value.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID
+ * (0<= LimitCheckId < VL53L0_GetNumberOfLimitCheck() ).
+ * @param LimitCheckValue Limit check Value for a given
+ * LimitCheckId
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned when either
+ * LimitCheckId or LimitCheckValue value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetLimitCheckValue(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, FixPoint1616_t LimitCheckValue);
+
+/**
+ * @brief Get a specific limit check value
+ *
+ * @par Function Description
+ * This function get a specific limit check value from device then it updates
+ * internal values and check enables.
+ * The limit check is identified with the LimitCheckId.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID
+ * (0<= LimitCheckId < VL53L0_GetNumberOfLimitCheck() ).
+ * @param pLimitCheckValue Pointer to Limit
+ * check Value for a given LimitCheckId.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned
+ * when LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetLimitCheckValue(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, FixPoint1616_t *pLimitCheckValue);
+
+/**
+ * @brief Get the current value of the signal used for the limit check
+ *
+ * @par Function Description
+ * This function get a the current value of the signal used for the limit check.
+ * To obtain the latest value you should run a ranging before.
+ * The value reported is linked to the limit check identified with the
+ * LimitCheckId.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param LimitCheckId Limit Check ID
+ * (0<= LimitCheckId < VL53L0_GetNumberOfLimitCheck() ).
+ * @param pLimitCheckCurrent Pointer to current Value for a
+ * given LimitCheckId.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned when
+ * LimitCheckId value is out of range.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetLimitCheckCurrent(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, FixPoint1616_t *pLimitCheckCurrent);
+
+/**
+ * @brief Enable (or disable) Wrap around Check
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param WrapAroundCheckEnable Wrap around Check to be set
+ * 0=disabled, other = enabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetWrapAroundCheckEnable(VL53L0_DEV Dev,
+ uint8_t WrapAroundCheckEnable);
+
+/**
+ * @brief Get setup of Wrap around Check
+ *
+ * @par Function Description
+ * This function get the wrapAround check enable parameters
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pWrapAroundCheckEnable Pointer to the Wrap around Check state
+ * 0=disabled or 1 = enabled
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetWrapAroundCheckEnable(VL53L0_DEV Dev,
+ uint8_t *pWrapAroundCheckEnable);
+
+/**
+ * @brief Set Dmax Calibration Parameters for a given device
+ * When one of the parameter is zero, this function will get parameter
+ * from NVM.
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param RangeMilliMeter Calibration Distance
+ * @param SignalRateRtnMegaCps Signal rate return read at CalDistance
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetDmaxCalParameters(VL53L0_DEV Dev,
+ uint16_t RangeMilliMeter, FixPoint1616_t SignalRateRtnMegaCps);
+
+/**
+ * @brief Get Dmax Calibration Parameters for a given device
+ *
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pRangeMilliMeter Pointer to Calibration Distance
+ * @param pSignalRateRtnMegaCps Pointer to Signal rate return
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetDmaxCalParameters(VL53L0_DEV Dev,
+ uint16_t *pRangeMilliMeter, FixPoint1616_t *pSignalRateRtnMegaCps);
+
+/** @} VL53L0_parameters_group */
+
+/** @defgroup VL53L0_measurement_group VL53L0 Measurement Functions
+ * @brief Functions used for the measurements
+ * @{
+ */
+
+/**
+ * @brief Single shot measurement.
+ *
+ * @par Function Description
+ * Perform simple measurement sequence (Start measure, Wait measure to end,
+ * and returns when measurement is done).
+ * Once function returns, user can get valid data by calling
+ * VL53L0_GetRangingMeasurement or VL53L0_GetHistogramMeasurement
+ * depending on defined measurement mode
+ * User should Clear the interrupt in case this are enabled by using the
+ * function VL53L0_ClearInterruptMask().
+ *
+ * @warning This function is a blocking function
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_PerformSingleMeasurement(VL53L0_DEV Dev);
+
+/**
+ * @brief Perform Reference Calibration
+ *
+ * @details Perform a reference calibration of the Device.
+ * This function should be run from time to time before doing
+ * a ranging measurement.
+ * This function will launch a special ranging measurement, so
+ * if interrupt are enable an interrupt will be done.
+ * This function will clear the interrupt generated automatically.
+ *
+ * @warning This function is a blocking function
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pVhvSettings Pointer to vhv settings parameter.
+ * @param pPhaseCal Pointer to PhaseCal parameter.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_PerformRefCalibration(VL53L0_DEV Dev,
+ uint8_t *pVhvSettings, uint8_t *pPhaseCal);
+
+/**
+ * @brief Perform XTalk Measurement
+ *
+ * @details Measures the current cross talk from glass in front
+ * of the sensor.
+ * This functions performs a histogram measurement and uses the results
+ * to measure the crosstalk. For the function to be successful, there
+ * must be no target in front of the sensor.
+ *
+ * @warning This function is a blocking function
+ *
+ * @warning This function is not supported when the final range
+ * vcsel clock period is set below 10 PCLKS.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param TimeoutMs Histogram measurement duration.
+ * @param pXtalkPerSpad Output parameter containing the crosstalk
+ * measurement result, in MCPS/Spad. Format fixpoint 16:16.
+ * @param pAmbientTooHigh Output parameter which indicate that
+ * pXtalkPerSpad is not good if the Ambient is too high.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS vcsel clock period not supported
+ * for this operation. Must not be less than 10PCLKS.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_PerformXTalkMeasurement(VL53L0_DEV Dev,
+ uint32_t TimeoutMs, FixPoint1616_t *pXtalkPerSpad,
+ uint8_t *pAmbientTooHigh);
+
+/**
+ * @brief Perform XTalk Calibration
+ *
+ * @details Perform a XTalk calibration of the Device.
+ * This function will launch a ranging measurement, if interrupts
+ * are enabled an interrupt will be done.
+ * This function will clear the interrupt generated automatically.
+ * This function will program a new value for the XTalk compensation
+ * and it will enable the cross talk before exit.
+ * This function will disable the VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD.
+ *
+ * @warning This function is a blocking function
+ *
+ * @note This function Access to the device
+ *
+ * @note This function change the device mode to
+ * VL53L0_DEVICEMODE_SINGLE_RANGING
+ *
+ * @param Dev Device Handle
+ * @param XTalkCalDistance XTalkCalDistance value used for the XTalk
+ * computation.
+ * @param pXTalkCompensationRateMegaCps Pointer to new
+ * XTalkCompensation value.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_PerformXTalkCalibration(VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCalDistance,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps);
+
+/**
+ * @brief Perform Offset Calibration
+ *
+ * @details Perform a Offset calibration of the Device.
+ * This function will launch a ranging measurement, if interrupts are
+ * enabled an interrupt will be done.
+ * This function will clear the interrupt generated automatically.
+ * This function will program a new value for the Offset calibration value
+ * This function will disable the VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD.
+ *
+ * @warning This function is a blocking function
+ *
+ * @note This function Access to the device
+ *
+ * @note This function does not change the device mode.
+ *
+ * @param Dev Device Handle
+ * @param CalDistanceMilliMeter Calibration distance value used for the
+ * offset compensation.
+ * @param pOffsetMicroMeter Pointer to new Offset value computed by the
+ * function.
+ *
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_PerformOffsetCalibration(VL53L0_DEV Dev,
+ FixPoint1616_t CalDistanceMilliMeter, int32_t *pOffsetMicroMeter);
+
+/**
+ * @brief Start device measurement
+ *
+ * @details Started measurement will depend on device parameters set through
+ * @a VL53L0_SetParameters()
+ * This is a non-blocking function.
+ * This function will change the VL53L0_State from VL53L0_STATE_IDLE to
+ * VL53L0_STATE_RUNNING.
+ *
+ * @note This function Access to the device
+ *
+
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_MODE_NOT_SUPPORTED This error occurs when
+ * DeviceMode programmed with @a VL53L0_SetDeviceMode is not in the supported
+ * list:
+ * Supported mode are:
+ * VL53L0_DEVICEMODE_SINGLE_RANGING,
+ * VL53L0_DEVICEMODE_CONTINUOUS_RANGING,
+ * VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING
+ * @return VL53L0_ERROR_TIME_OUT Time out on start measurement
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_StartMeasurement(VL53L0_DEV Dev);
+
+/**
+ * @brief Stop device measurement
+ *
+ * @details Will set the device in standby mode at end of current measurement\n
+ * Not necessary in single mode as device shall return automatically
+ * in standby mode at end of measurement.
+ * This function will change the VL53L0_State from VL53L0_STATE_RUNNING
+ * to VL53L0_STATE_IDLE.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_StopMeasurement(VL53L0_DEV Dev);
+
+/**
+ * @brief Return Measurement Data Ready
+ *
+ * @par Function Description
+ * This function indicate that a measurement data is ready.
+ * This function check if interrupt mode is used then check is done accordingly.
+ * If perform function clear the interrupt, this function will not work,
+ * like in case of @a VL53L0_PerformSingleRangingMeasurement().
+ * The previous function is blocking function, VL53L0_GetMeasurementDataReady
+ * is used for non-blocking capture.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pMeasurementDataReady Pointer to Measurement Data Ready.
+ * 0=data not ready, 1 = data ready
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetMeasurementDataReady(VL53L0_DEV Dev,
+ uint8_t *pMeasurementDataReady);
+
+/**
+ * @brief Wait for device ready for a new measurement command.
+ * Blocking function.
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param MaxLoop Max Number of polling loop (timeout).
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L0_API VL53L0_Error VL53L0_WaitDeviceReadyForNewMeasurement(VL53L0_DEV Dev,
+ uint32_t MaxLoop);
+
+/**
+ * @brief Retrieve the Reference Signal after a measurements
+ *
+ * @par Function Description
+ * Get Reference Signal from last successful Ranging measurement
+ * This function return a valid value after that you call the
+ * @a VL53L0_GetRangingMeasurementData().
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pMeasurementRefSignal Pointer to the Ref Signal to fill up.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetMeasurementRefSignal(VL53L0_DEV Dev,
+ FixPoint1616_t *pMeasurementRefSignal);
+
+/**
+ * @brief Retrieve the measurements from device for a given setup
+ *
+ * @par Function Description
+ * Get data from last successful Ranging measurement
+ * @warning USER should take care about @a VL53L0_GetNumberOfROIZones()
+ * before get data.
+ * PAL will fill a NumberOfROIZones times the corresponding data
+ * structure used in the measurement function.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pRangingMeasurementData Pointer to the data structure to fill up.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetRangingMeasurementData(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData);
+
+/**
+ * @brief Retrieve the measurements from device for a given setup
+ *
+ * @par Function Description
+ * Get data from last successful Histogram measurement
+ * @warning USER should take care about @a VL53L0_GetNumberOfROIZones()
+ * before get data.
+ * PAL will fill a NumberOfROIZones times the corresponding data structure
+ * used in the measurement function.
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param pHistogramMeasurementData Pointer to the histogram data structure.
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L0_API VL53L0_Error VL53L0_GetHistogramMeasurementData(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData);
+
+/**
+ * @brief Performs a single ranging measurement and retrieve the ranging
+ * measurement data
+ *
+ * @par Function Description
+ * This function will change the device mode to VL53L0_DEVICEMODE_SINGLE_RANGING
+ * with @a VL53L0_SetDeviceMode(),
+ * It performs measurement with @a VL53L0_PerformSingleMeasurement()
+ * It get data from last successful Ranging measurement with
+ * @a VL53L0_GetRangingMeasurementData.
+ * Finally it clear the interrupt with @a VL53L0_ClearInterruptMask().
+ *
+ * @note This function Access to the device
+ *
+ * @note This function change the device mode to
+ * VL53L0_DEVICEMODE_SINGLE_RANGING
+ *
+ * @param Dev Device Handle
+ * @param pRangingMeasurementData Pointer to the data structure to fill up.
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_PerformSingleRangingMeasurement(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData);
+
+/**
+ * @brief Performs a single histogram measurement and retrieve the histogram
+ * measurement data
+ * Is equivalent to VL53L0_PerformSingleMeasurement +
+ * VL53L0_GetHistogramMeasurementData
+ *
+ * @par Function Description
+ * Get data from last successful Ranging measurement.
+ * This function will clear the interrupt in case of these are enabled.
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param pHistogramMeasurementData Pointer to the data structure to fill up.
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L0_API VL53L0_Error VL53L0_PerformSingleHistogramMeasurement(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData);
+
+/**
+ * @brief Set the number of ROI Zones to be used for a specific Device
+ *
+ * @par Function Description
+ * Set the number of ROI Zones to be used for a specific Device.
+ * The programmed value should be less than the max number of ROI Zones given
+ * with @a VL53L0_GetMaxNumberOfROIZones().
+ * This version of API manage only one zone.
+ *
+ * @param Dev Device Handle
+ * @param NumberOfROIZones Number of ROI Zones to be used for a
+ * specific Device.
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INVALID_PARAMS This error is returned if
+ * NumberOfROIZones != 1
+ */
+VL53L0_API VL53L0_Error VL53L0_SetNumberOfROIZones(VL53L0_DEV Dev,
+ uint8_t NumberOfROIZones);
+
+/**
+ * @brief Get the number of ROI Zones managed by the Device
+ *
+ * @par Function Description
+ * Get number of ROI Zones managed by the Device
+ * USER should take care about @a VL53L0_GetNumberOfROIZones()
+ * before get data after a perform measurement.
+ * PAL will fill a NumberOfROIZones times the corresponding data
+ * structure used in the measurement function.
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pNumberOfROIZones Pointer to the Number of ROI Zones value.
+ * @return VL53L0_ERROR_NONE Success
+ */
+VL53L0_API VL53L0_Error VL53L0_GetNumberOfROIZones(VL53L0_DEV Dev,
+ uint8_t *pNumberOfROIZones);
+
+/**
+ * @brief Get the Maximum number of ROI Zones managed by the Device
+ *
+ * @par Function Description
+ * Get Maximum number of ROI Zones managed by the Device.
+ *
+ * @note This function doesn't Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pMaxNumberOfROIZones Pointer to the Maximum Number
+ * of ROI Zones value.
+ * @return VL53L0_ERROR_NONE Success
+ */
+VL53L0_API VL53L0_Error VL53L0_GetMaxNumberOfROIZones(VL53L0_DEV Dev,
+ uint8_t *pMaxNumberOfROIZones);
+
+/** @} VL53L0_measurement_group */
+
+/** @defgroup VL53L0_interrupt_group VL53L0 Interrupt Functions
+ * @brief Functions used for interrupt managements
+ * @{
+ */
+
+/**
+ * @brief Set the configuration of GPIO pin for a given device
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param Pin ID of the GPIO Pin
+ * @param Functionality Select Pin functionality.
+ * Refer to ::VL53L0_GpioFunctionality
+ * @param DeviceMode Device Mode associated to the Gpio.
+ * @param Polarity Set interrupt polarity. Active high
+ * or active low see ::VL53L0_InterruptPolarity
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_GPIO_NOT_EXISTING Only Pin=0 is accepted.
+ * @return VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED This error occurs
+ * when Functionality programmed is not in the supported list:
+ * Supported value are:
+ * VL53L0_GPIOFUNCTIONALITY_OFF,
+ * VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW,
+ * VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH,
+ VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT,
+ * VL53L0_GPIOFUNCTIONALITY_NEW_MEASURE_READY
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetGpioConfig(VL53L0_DEV Dev, uint8_t Pin,
+ VL53L0_DeviceModes DeviceMode, VL53L0_GpioFunctionality Functionality,
+ VL53L0_InterruptPolarity Polarity);
+
+/**
+ * @brief Get current configuration for GPIO pin for a given device
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param Pin ID of the GPIO Pin
+ * @param pDeviceMode Pointer to Device Mode associated to the Gpio.
+ * @param pFunctionality Pointer to Pin functionality.
+ * Refer to ::VL53L0_GpioFunctionality
+ * @param pPolarity Pointer to interrupt polarity.
+ * Active high or active low see ::VL53L0_InterruptPolarity
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_GPIO_NOT_EXISTING Only Pin=0 is accepted.
+ * @return VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED This error occurs
+ * when Functionality programmed is not in the supported list:
+ * Supported value are:
+ * VL53L0_GPIOFUNCTIONALITY_OFF,
+ * VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW,
+ * VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH,
+ * VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT,
+ * VL53L0_GPIOFUNCTIONALITY_NEW_MEASURE_READY
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetGpioConfig(VL53L0_DEV Dev, uint8_t Pin,
+ VL53L0_DeviceModes * pDeviceMode,
+ VL53L0_GpioFunctionality * pFunctionality,
+ VL53L0_InterruptPolarity * pPolarity);
+
+/**
+ * @brief Set low and high Interrupt thresholds for a given mode
+ * (ranging, ALS, ...) for a given device
+ *
+ * @par Function Description
+ * Set low and high Interrupt thresholds for a given mode (ranging, ALS, ...)
+ * for a given device
+ *
+ * @note This function Access to the device
+ *
+ * @note DeviceMode is ignored for the current device
+ *
+ * @param Dev Device Handle
+ * @param DeviceMode Device Mode for which change thresholds
+ * @param ThresholdLow Low threshold (mm, lux ..., depending on the mode)
+ * @param ThresholdHigh High threshold (mm, lux ..., depending on the mode)
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetInterruptThresholds(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode, FixPoint1616_t ThresholdLow,
+ FixPoint1616_t ThresholdHigh);
+
+/**
+ * @brief Get high and low Interrupt thresholds for a given mode
+ * (ranging, ALS, ...) for a given device
+ *
+ * @par Function Description
+ * Get high and low Interrupt thresholds for a given mode (ranging, ALS, ...)
+ * for a given device
+ *
+ * @note This function Access to the device
+ *
+ * @note DeviceMode is ignored for the current device
+ *
+ * @param Dev Device Handle
+ * @param DeviceMode Device Mode from which read thresholds
+ * @param pThresholdLow Low threshold (mm, lux ..., depending on the mode)
+ * @param pThresholdHigh High threshold (mm, lux ..., depending on the mode)
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetInterruptThresholds(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode, FixPoint1616_t *pThresholdLow,
+ FixPoint1616_t *pThresholdHigh);
+
+/**
+ * @brief Return device stop completion status
+ *
+ * @par Function Description
+ * Returns stop completiob status.
+ * User shall call this function after a stop command
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pStopStatus Pointer to status variable to update
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetStopCompletedStatus(VL53L0_DEV Dev,
+ uint32_t *pStopStatus);
+
+
+/**
+ * @brief Clear given system interrupt condition
+ *
+ * @par Function Description
+ * Clear given interrupt(s).
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param InterruptMask Mask of interrupts to clear
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_INTERRUPT_NOT_CLEARED Cannot clear interrupts
+ *
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_ClearInterruptMask(VL53L0_DEV Dev,
+ uint32_t InterruptMask);
+
+/**
+ * @brief Return device interrupt status
+ *
+ * @par Function Description
+ * Returns currently raised interrupts by the device.
+ * User shall be able to activate/deactivate interrupts through
+ * @a VL53L0_SetGpioConfig()
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pInterruptMaskStatus Pointer to status variable to update
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetInterruptMaskStatus(VL53L0_DEV Dev,
+ uint32_t *pInterruptMaskStatus);
+
+/**
+ * @brief Configure ranging interrupt reported to system
+ *
+ * @note This function is not Implemented
+ *
+ * @param Dev Device Handle
+ * @param InterruptMask Mask of interrupt to Enable/disable
+ * (0:interrupt disabled or 1: interrupt enabled)
+ * @return VL53L0_ERROR_NOT_IMPLEMENTED Not implemented
+ */
+VL53L0_API VL53L0_Error VL53L0_EnableInterruptMask(VL53L0_DEV Dev,
+ uint32_t InterruptMask);
+
+/** @} VL53L0_interrupt_group */
+
+/** @defgroup VL53L0_SPADfunctions_group VL53L0 SPAD Functions
+ * @brief Functions used for SPAD managements
+ * @{
+ */
+
+/**
+ * @brief Set the SPAD Ambient Damper Threshold value
+ *
+ * @par Function Description
+ * This function set the SPAD Ambient Damper Threshold value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param SpadAmbientDamperThreshold SPAD Ambient Damper Threshold value
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetSpadAmbientDamperThreshold(VL53L0_DEV Dev,
+ uint16_t SpadAmbientDamperThreshold);
+
+/**
+ * @brief Get the current SPAD Ambient Damper Threshold value
+ *
+ * @par Function Description
+ * This function get the SPAD Ambient Damper Threshold value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pSpadAmbientDamperThreshold Pointer to programmed
+ * SPAD Ambient Damper Threshold value
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetSpadAmbientDamperThreshold(VL53L0_DEV Dev,
+ uint16_t *pSpadAmbientDamperThreshold);
+
+/**
+ * @brief Set the SPAD Ambient Damper Factor value
+ *
+ * @par Function Description
+ * This function set the SPAD Ambient Damper Factor value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param SpadAmbientDamperFactor SPAD Ambient Damper Factor value
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetSpadAmbientDamperFactor(VL53L0_DEV Dev,
+ uint16_t SpadAmbientDamperFactor);
+
+/**
+ * @brief Get the current SPAD Ambient Damper Factor value
+ *
+ * @par Function Description
+ * This function get the SPAD Ambient Damper Factor value
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param pSpadAmbientDamperFactor Pointer to programmed SPAD Ambient
+ * Damper Factor value
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetSpadAmbientDamperFactor(VL53L0_DEV Dev,
+ uint16_t *pSpadAmbientDamperFactor);
+
+/**
+ * @brief Performs Reference Spad Management
+ *
+ * @par Function Description
+ * The reference SPAD initialization procedure determines the minimum amount
+ * of reference spads to be enables to achieve a target reference signal rate
+ * and should be performed once during initialization.
+ *
+ * @note This function Access to the device
+ *
+ * @note This function change the device mode to
+ * VL53L0_DEVICEMODE_SINGLE_RANGING
+ *
+ * @param Dev Device Handle
+ * @param refSpadCount Reports ref Spad Count
+ * @param isApertureSpads Reports if spads are of type
+ * aperture or non-aperture.
+ * 1:=aperture, 0:=Non-Aperture
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_REF_SPAD_INIT Error in the Ref Spad procedure.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_PerformRefSpadManagement(VL53L0_DEV Dev,
+ uint32_t *refSpadCount, uint8_t *isApertureSpads);
+
+/**
+ * @brief Applies Reference SPAD configuration
+ *
+ * @par Function Description
+ * This function applies a given number of reference spads, identified as
+ * either Aperture or Non-Aperture.
+ * The requested spad count and type are stored within the device specific
+ * parameters data for access by the host.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param refSpadCount Number of ref spads.
+ * @param isApertureSpads Defines if spads are of type
+ * aperture or non-aperture.
+ * 1:=aperture, 0:=Non-Aperture
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_REF_SPAD_INIT Error in the in the reference
+ * spad configuration.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_SetReferenceSpads(VL53L0_DEV Dev,
+ uint32_t refSpadCount, uint8_t isApertureSpads);
+
+/**
+ * @brief Retrieves SPAD configuration
+ *
+ * @par Function Description
+ * This function retrieves the current number of applied reference spads
+ * and also their type : Aperture or Non-Aperture.
+ *
+ * @note This function Access to the device
+ *
+ * @param Dev Device Handle
+ * @param refSpadCount Number ref Spad Count
+ * @param isApertureSpads Reports if spads are of type
+ * aperture or non-aperture.
+ * 1:=aperture, 0:=Non-Aperture
+ * @return VL53L0_ERROR_NONE Success
+ * @return VL53L0_ERROR_REF_SPAD_INIT Error in the in the reference
+ * spad configuration.
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_API VL53L0_Error VL53L0_GetReferenceSpads(VL53L0_DEV Dev,
+ uint32_t *refSpadCount, uint8_t *isApertureSpads);
+
+/** @} VL53L0_SPADfunctions_group */
+
+/** @} VL53L0_cut11_group */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L0_API_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_api_calibration.h b/drivers/input/misc/vl53L0/inc/vl53l0_api_calibration.h
new file mode 100644
index 000000000000..df9b43987eb5
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_api_calibration.h
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef _VL53L0_API_CALIBRATION_H_
+#define _VL53L0_API_CALIBRATION_H_
+
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+VL53L0_Error VL53L0_perform_xtalk_calibration(VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCalDistance,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps);
+
+VL53L0_Error VL53L0_perform_offset_calibration(VL53L0_DEV Dev,
+ FixPoint1616_t CalDistanceMilliMeter,
+ int32_t *pOffsetMicroMeter);
+
+VL53L0_Error VL53L0_set_offset_calibration_data_micro_meter(VL53L0_DEV Dev,
+ int32_t OffsetCalibrationDataMicroMeter);
+
+VL53L0_Error VL53L0_get_offset_calibration_data_micro_meter(VL53L0_DEV Dev,
+ int32_t *pOffsetCalibrationDataMicroMeter);
+
+VL53L0_Error VL53L0_apply_offset_adjustment(VL53L0_DEV Dev);
+
+VL53L0_Error VL53L0_perform_ref_spad_management(VL53L0_DEV Dev,
+ uint32_t *refSpadCount, uint8_t *isApertureSpads);
+
+VL53L0_Error VL53L0_set_reference_spads(VL53L0_DEV Dev,
+ uint32_t count, uint8_t isApertureSpads);
+
+VL53L0_Error VL53L0_get_reference_spads(VL53L0_DEV Dev,
+ uint32_t *pSpadCount, uint8_t *pIsApertureSpads);
+
+VL53L0_Error VL53L0_perform_phase_calibration(VL53L0_DEV Dev,
+ uint8_t *pPhaseCal, const uint8_t get_data_enable,
+ const uint8_t restore_config);
+
+VL53L0_Error VL53L0_perform_ref_calibration(VL53L0_DEV Dev,
+ uint8_t *pVhvSettings, uint8_t *pPhaseCal, uint8_t get_data_enable);
+
+VL53L0_Error VL53L0_set_ref_calibration(VL53L0_DEV Dev,
+ uint8_t VhvSettings, uint8_t PhaseCal);
+
+VL53L0_Error VL53L0_get_ref_calibration(VL53L0_DEV Dev,
+ uint8_t *pVhvSettings, uint8_t *pPhaseCal);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L0_API_CALIBRATION_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_api_core.h b/drivers/input/misc/vl53L0/inc/vl53l0_api_core.h
new file mode 100644
index 000000000000..21cf9edec0e0
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_api_core.h
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef _VL53L0_API_CORE_H_
+#define _VL53L0_API_CORE_H_
+
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+VL53L0_Error VL53L0_reverse_bytes(uint8_t *data, uint32_t size);
+
+VL53L0_Error VL53L0_measurement_poll_for_completion(VL53L0_DEV Dev);
+
+uint8_t VL53L0_encode_vcsel_period(uint8_t vcsel_period_pclks);
+
+uint8_t VL53L0_decode_vcsel_period(uint8_t vcsel_period_reg);
+
+uint32_t VL53L0_isqrt(uint32_t num);
+
+uint32_t VL53L0_quadrature_sum(uint32_t a, uint32_t b);
+
+VL53L0_Error VL53L0_get_info_from_device(VL53L0_DEV Dev, uint8_t option);
+
+VL53L0_Error VL53L0_set_vcsel_pulse_period(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType, uint8_t VCSELPulsePeriodPCLK);
+
+VL53L0_Error VL53L0_get_vcsel_pulse_period(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType, uint8_t *pVCSELPulsePeriodPCLK);
+
+uint32_t VL53L0_decode_timeout(uint16_t encoded_timeout);
+
+VL53L0_Error get_sequence_step_timeout(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId,
+ uint32_t *pTimeOutMicroSecs);
+
+VL53L0_Error set_sequence_step_timeout(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId,
+ uint32_t TimeOutMicroSecs);
+
+VL53L0_Error VL53L0_set_measurement_timing_budget_micro_seconds(VL53L0_DEV Dev,
+ uint32_t MeasurementTimingBudgetMicroSeconds);
+
+VL53L0_Error VL53L0_get_measurement_timing_budget_micro_seconds(VL53L0_DEV Dev,
+ uint32_t *pMeasurementTimingBudgetMicroSeconds);
+
+VL53L0_Error VL53L0_load_tuning_settings(VL53L0_DEV Dev,
+ uint8_t *pTuningSettingBuffer);
+
+VL53L0_Error VL53L0_calc_sigma_estimate(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData,
+ FixPoint1616_t *pSigmaEstimate, uint32_t *pDmax_mm);
+
+VL53L0_Error VL53L0_get_total_xtalk_rate(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData,
+ FixPoint1616_t *ptotal_xtalk_rate_mcps);
+
+VL53L0_Error VL53L0_get_total_signal_rate(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData,
+ FixPoint1616_t *ptotal_signal_rate_mcps);
+
+VL53L0_Error VL53L0_get_pal_range_status(VL53L0_DEV Dev,
+ uint8_t DeviceRangeStatus,
+ FixPoint1616_t SignalRate,
+ uint16_t EffectiveSpadRtnCount,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData,
+ uint8_t *pPalRangeStatus);
+
+uint32_t VL53L0_calc_timeout_mclks(VL53L0_DEV Dev,
+ uint32_t timeout_period_us, uint8_t vcsel_period_pclks);
+
+uint16_t VL53L0_encode_timeout(uint32_t timeout_macro_clks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L0_API_CORE_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_api_histogram.h b/drivers/input/misc/vl53L0/inc/vl53l0_api_histogram.h
new file mode 100644
index 000000000000..c2438a8cd79b
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_api_histogram.h
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef _VL53L0_API_HISTOGRAM_H_
+#define _VL53L0_API_HISTOGRAM_H_
+
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+VL53L0_Error VL53L0_confirm_measurement_start(VL53L0_DEV Dev);
+
+VL53L0_Error VL53L0_set_histogram_mode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes HistogramMode);
+
+VL53L0_Error VL53L0_get_histogram_mode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes *pHistogramMode);
+
+VL53L0_Error VL53L0_start_histogram_measurement(VL53L0_DEV Dev,
+ VL53L0_HistogramModes histoMode,
+ uint32_t count);
+
+VL53L0_Error VL53L0_perform_single_histogram_measurement(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData);
+
+VL53L0_Error VL53L0_get_histogram_measurement_data(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData);
+
+VL53L0_Error VL53L0_read_histo_measurement(VL53L0_DEV Dev,
+ uint32_t *histoData, uint32_t offset, VL53L0_HistogramModes histoMode);
+
+VL53L0_Error VL53L0_perform_xtalk_measurement(VL53L0_DEV dev,
+ uint32_t timeout_ms, FixPoint1616_t *pxtalk_per_spad,
+ uint8_t *pambient_too_high);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L0_API_HISTOGRAM_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_api_ranging.h b/drivers/input/misc/vl53L0/inc/vl53l0_api_ranging.h
new file mode 100644
index 000000000000..ba0bd03fe71f
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_api_ranging.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef _VL53L0_API_RANGING_H_
+#define _VL53L0_API_RANGING_H_
+
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L0_API_RANGING_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_api_strings.h b/drivers/input/misc/vl53L0/inc/vl53l0_api_strings.h
new file mode 100644
index 000000000000..2bb6a1e8ea33
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_api_strings.h
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef VL53L0_API_STRINGS_H_
+#define VL53L0_API_STRINGS_H_
+
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+VL53L0_Error VL53L0_get_device_info(VL53L0_DEV Dev,
+ VL53L0_DeviceInfo_t *pVL53L0_DeviceInfo);
+
+VL53L0_Error VL53L0_get_device_error_string(VL53L0_DeviceError ErrorCode,
+ char *pDeviceErrorString);
+
+VL53L0_Error VL53L0_get_range_status_string(uint8_t RangeStatus,
+ char *pRangeStatusString);
+
+VL53L0_Error VL53L0_get_pal_error_string(VL53L0_Error PalErrorCode,
+ char *pPalErrorString);
+
+VL53L0_Error VL53L0_get_pal_state_string(VL53L0_State PalStateCode,
+ char *pPalStateString);
+
+VL53L0_Error VL53L0_get_sequence_steps_info(
+ VL53L0_SequenceStepId SequenceStepId,
+ char *pSequenceStepsString);
+
+VL53L0_Error VL53L0_get_limit_check_info(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ char *pLimitCheckString);
+
+
+#ifdef USE_EMPTY_STRING
+ #define VL53L0_STRING_DEVICE_INFO_NAME ""
+ #define VL53L0_STRING_DEVICE_INFO_NAME_TS0 ""
+ #define VL53L0_STRING_DEVICE_INFO_NAME_TS1 ""
+ #define VL53L0_STRING_DEVICE_INFO_NAME_TS2 ""
+ #define VL53L0_STRING_DEVICE_INFO_NAME_ES1 ""
+ #define VL53L0_STRING_DEVICE_INFO_TYPE ""
+
+ /* PAL ERROR strings */
+ #define VL53L0_STRING_ERROR_NONE ""
+ #define VL53L0_STRING_ERROR_CALIBRATION_WARNING ""
+ #define VL53L0_STRING_ERROR_MIN_CLIPPED ""
+ #define VL53L0_STRING_ERROR_UNDEFINED ""
+ #define VL53L0_STRING_ERROR_INVALID_PARAMS ""
+ #define VL53L0_STRING_ERROR_NOT_SUPPORTED ""
+ #define VL53L0_STRING_ERROR_RANGE_ERROR ""
+ #define VL53L0_STRING_ERROR_TIME_OUT ""
+ #define VL53L0_STRING_ERROR_MODE_NOT_SUPPORTED ""
+ #define VL53L0_STRING_ERROR_BUFFER_TOO_SMALL ""
+ #define VL53L0_STRING_ERROR_GPIO_NOT_EXISTING ""
+ #define VL53L0_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ""
+ #define VL53L0_STRING_ERROR_CONTROL_INTERFACE ""
+ #define VL53L0_STRING_ERROR_INVALID_COMMAND ""
+ #define VL53L0_STRING_ERROR_DIVISION_BY_ZERO ""
+ #define VL53L0_STRING_ERROR_REF_SPAD_INIT ""
+ #define VL53L0_STRING_ERROR_NOT_IMPLEMENTED ""
+
+ #define VL53L0_STRING_UNKNOW_ERROR_CODE ""
+
+
+
+ /* Range Status */
+ #define VL53L0_STRING_RANGESTATUS_NONE ""
+ #define VL53L0_STRING_RANGESTATUS_RANGEVALID ""
+ #define VL53L0_STRING_RANGESTATUS_SIGMA ""
+ #define VL53L0_STRING_RANGESTATUS_SIGNAL ""
+ #define VL53L0_STRING_RANGESTATUS_MINRANGE ""
+ #define VL53L0_STRING_RANGESTATUS_PHASE ""
+ #define VL53L0_STRING_RANGESTATUS_HW ""
+
+
+ /* Range Status */
+ #define VL53L0_STRING_STATE_POWERDOWN ""
+ #define VL53L0_STRING_STATE_WAIT_STATICINIT ""
+ #define VL53L0_STRING_STATE_STANDBY ""
+ #define VL53L0_STRING_STATE_IDLE ""
+ #define VL53L0_STRING_STATE_RUNNING ""
+ #define VL53L0_STRING_STATE_UNKNOWN ""
+ #define VL53L0_STRING_STATE_ERROR ""
+
+
+ /* Device Specific */
+ #define VL53L0_STRING_DEVICEERROR_NONE ""
+ #define VL53L0_STRING_DEVICEERROR_VCSELCONTINUITYTESTFAILURE ""
+ #define VL53L0_STRING_DEVICEERROR_VCSELWATCHDOGTESTFAILURE ""
+ #define VL53L0_STRING_DEVICEERROR_NOVHVVALUEFOUND ""
+ #define VL53L0_STRING_DEVICEERROR_MSRCNOTARGET ""
+ #define VL53L0_STRING_DEVICEERROR_SNRCHECK ""
+ #define VL53L0_STRING_DEVICEERROR_RANGEPHASECHECK ""
+ #define VL53L0_STRING_DEVICEERROR_SIGMATHRESHOLDCHECK ""
+ #define VL53L0_STRING_DEVICEERROR_TCC ""
+ #define VL53L0_STRING_DEVICEERROR_PHASECONSISTENCY ""
+ #define VL53L0_STRING_DEVICEERROR_MINCLIP ""
+ #define VL53L0_STRING_DEVICEERROR_RANGECOMPLETE ""
+ #define VL53L0_STRING_DEVICEERROR_ALGOUNDERFLOW ""
+ #define VL53L0_STRING_DEVICEERROR_ALGOOVERFLOW ""
+ #define VL53L0_STRING_DEVICEERROR_RANGEIGNORETHRESHOLD ""
+ #define VL53L0_STRING_DEVICEERROR_UNKNOWN ""
+
+ /* Check Enable */
+ #define VL53L0_STRING_CHECKENABLE_SIGMA_FINAL_RANGE ""
+ #define VL53L0_STRING_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE ""
+ #define VL53L0_STRING_CHECKENABLE_SIGNAL_REF_CLIP ""
+ #define VL53L0_STRING_CHECKENABLE_RANGE_IGNORE_THRESHOLD ""
+
+ /* Sequence Step */
+ #define VL53L0_STRING_SEQUENCESTEP_TCC ""
+ #define VL53L0_STRING_SEQUENCESTEP_DSS ""
+ #define VL53L0_STRING_SEQUENCESTEP_MSRC ""
+ #define VL53L0_STRING_SEQUENCESTEP_PRE_RANGE ""
+ #define VL53L0_STRING_SEQUENCESTEP_FINAL_RANGE ""
+#else
+ #define VL53L0_STRING_DEVICE_INFO_NAME "VL53L0 cut1.0"
+ #define VL53L0_STRING_DEVICE_INFO_NAME_TS0 "VL53L0 TS0"
+ #define VL53L0_STRING_DEVICE_INFO_NAME_TS1 "VL53L0 TS1"
+ #define VL53L0_STRING_DEVICE_INFO_NAME_TS2 "VL53L0 TS2"
+ #define VL53L0_STRING_DEVICE_INFO_NAME_ES1 "VL53L0 ES1 or later"
+ #define VL53L0_STRING_DEVICE_INFO_TYPE "VL53L0"
+
+ /* PAL ERROR strings */
+ #define VL53L0_STRING_ERROR_NONE \
+ "No Error"
+ #define VL53L0_STRING_ERROR_CALIBRATION_WARNING \
+ "Calibration Warning Error"
+ #define VL53L0_STRING_ERROR_MIN_CLIPPED \
+ "Min clipped error"
+ #define VL53L0_STRING_ERROR_UNDEFINED \
+ "Undefined error"
+ #define VL53L0_STRING_ERROR_INVALID_PARAMS \
+ "Invalid parameters error"
+ #define VL53L0_STRING_ERROR_NOT_SUPPORTED \
+ "Not supported error"
+ #define VL53L0_STRING_ERROR_RANGE_ERROR \
+ "Range error"
+ #define VL53L0_STRING_ERROR_TIME_OUT \
+ "Time out error"
+ #define VL53L0_STRING_ERROR_MODE_NOT_SUPPORTED \
+ "Mode not supported error"
+ #define VL53L0_STRING_ERROR_BUFFER_TOO_SMALL \
+ "Buffer too small"
+ #define VL53L0_STRING_ERROR_GPIO_NOT_EXISTING \
+ "GPIO not existing"
+ #define VL53L0_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED \
+ "GPIO funct not supported"
+ #define VL53L0_STRING_ERROR_INTERRUPT_NOT_CLEARED \
+ "Interrupt not Cleared"
+ #define VL53L0_STRING_ERROR_CONTROL_INTERFACE \
+ "Control Interface Error"
+ #define VL53L0_STRING_ERROR_INVALID_COMMAND \
+ "Invalid Command Error"
+ #define VL53L0_STRING_ERROR_DIVISION_BY_ZERO \
+ "Division by zero Error"
+ #define VL53L0_STRING_ERROR_REF_SPAD_INIT \
+ "Reference Spad Init Error"
+ #define VL53L0_STRING_ERROR_NOT_IMPLEMENTED \
+ "Not implemented error"
+
+ #define VL53L0_STRING_UNKNOW_ERROR_CODE \
+ "Unknown Error Code"
+
+
+
+ /* Range Status */
+ #define VL53L0_STRING_RANGESTATUS_NONE "No Update"
+ #define VL53L0_STRING_RANGESTATUS_RANGEVALID "Range Valid"
+ #define VL53L0_STRING_RANGESTATUS_SIGMA "Sigma Fail"
+ #define VL53L0_STRING_RANGESTATUS_SIGNAL "Signal Fail"
+ #define VL53L0_STRING_RANGESTATUS_MINRANGE "Min Range Fail"
+ #define VL53L0_STRING_RANGESTATUS_PHASE "Phase Fail"
+ #define VL53L0_STRING_RANGESTATUS_HW "Hardware Fail"
+
+
+ /* Range Status */
+ #define VL53L0_STRING_STATE_POWERDOWN "POWERDOWN State"
+ #define VL53L0_STRING_STATE_WAIT_STATICINIT \
+ "Wait for staticinit State"
+ #define VL53L0_STRING_STATE_STANDBY "STANDBY State"
+ #define VL53L0_STRING_STATE_IDLE "IDLE State"
+ #define VL53L0_STRING_STATE_RUNNING "RUNNING State"
+ #define VL53L0_STRING_STATE_UNKNOWN "UNKNOWN State"
+ #define VL53L0_STRING_STATE_ERROR "ERROR State"
+
+
+ /* Device Specific */
+ #define VL53L0_STRING_DEVICEERROR_NONE "No Update"
+ #define VL53L0_STRING_DEVICEERROR_VCSELCONTINUITYTESTFAILURE \
+ "VCSEL Continuity Test Failure"
+ #define VL53L0_STRING_DEVICEERROR_VCSELWATCHDOGTESTFAILURE \
+ "VCSEL Watchdog Test Failure"
+ #define VL53L0_STRING_DEVICEERROR_NOVHVVALUEFOUND \
+ "No VHV Value found"
+ #define VL53L0_STRING_DEVICEERROR_MSRCNOTARGET \
+ "MSRC No Target Error"
+ #define VL53L0_STRING_DEVICEERROR_SNRCHECK \
+ "SNR Check Exit"
+ #define VL53L0_STRING_DEVICEERROR_RANGEPHASECHECK \
+ "Range Phase Check Error"
+ #define VL53L0_STRING_DEVICEERROR_SIGMATHRESHOLDCHECK \
+ "Sigma Threshold Check Error"
+ #define VL53L0_STRING_DEVICEERROR_TCC \
+ "TCC Error"
+ #define VL53L0_STRING_DEVICEERROR_PHASECONSISTENCY \
+ "Phase Consistency Error"
+ #define VL53L0_STRING_DEVICEERROR_MINCLIP \
+ "Min Clip Error"
+ #define VL53L0_STRING_DEVICEERROR_RANGECOMPLETE \
+ "Range Complete"
+ #define VL53L0_STRING_DEVICEERROR_ALGOUNDERFLOW \
+ "Range Algo Underflow Error"
+ #define VL53L0_STRING_DEVICEERROR_ALGOOVERFLOW \
+ "Range Algo Overlow Error"
+ #define VL53L0_STRING_DEVICEERROR_RANGEIGNORETHRESHOLD \
+ "Range Ignore Threshold Error"
+ #define VL53L0_STRING_DEVICEERROR_UNKNOWN \
+ "Unknown error code"
+
+ /* Check Enable */
+ #define VL53L0_STRING_CHECKENABLE_SIGMA_FINAL_RANGE \
+ "SIGMA FINAL RANGE"
+ #define VL53L0_STRING_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE \
+ "SIGNAL RATE FINAL RANGE"
+ #define VL53L0_STRING_CHECKENABLE_SIGNAL_REF_CLIP \
+ "SIGNAL REF CLIP"
+ #define VL53L0_STRING_CHECKENABLE_RANGE_IGNORE_THRESHOLD \
+ "RANGE IGNORE THRESHOLD"
+ #define VL53L0_STRING_CHECKENABLE_SIGNAL_RATE_MSRC \
+ "SIGNAL RATE MSRC"
+ #define VL53L0_STRING_CHECKENABLE_SIGNAL_RATE_PRE_RANGE \
+ "SIGNAL RATE PRE RANGE"
+
+ /* Sequence Step */
+ #define VL53L0_STRING_SEQUENCESTEP_TCC "TCC"
+ #define VL53L0_STRING_SEQUENCESTEP_DSS "DSS"
+ #define VL53L0_STRING_SEQUENCESTEP_MSRC "MSRC"
+ #define VL53L0_STRING_SEQUENCESTEP_PRE_RANGE "PRE RANGE"
+ #define VL53L0_STRING_SEQUENCESTEP_FINAL_RANGE "FINAL RANGE"
+#endif /* USE_EMPTY_STRING */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_def.h b/drivers/input/misc/vl53L0/inc/vl53l0_def.h
new file mode 100644
index 000000000000..009715a5924f
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_def.h
@@ -0,0 +1,663 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+/**
+ * @file VL53L0_def.h
+ *
+ * @brief Type definitions for VL53L0 API.
+ *
+ */
+
+
+#ifndef _VL53L0_DEF_H_
+#define _VL53L0_DEF_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup VL53L0_globaldefine_group VL53L0 Defines
+ * @brief VL53L0 Defines
+ * @{
+ */
+
+
+/** PAL SPECIFICATION major version */
+#define VL53L010_SPECIFICATION_VER_MAJOR 1
+/** PAL SPECIFICATION minor version */
+#define VL53L010_SPECIFICATION_VER_MINOR 2
+/** PAL SPECIFICATION sub version */
+#define VL53L010_SPECIFICATION_VER_SUB 7
+/** PAL SPECIFICATION sub version */
+#define VL53L010_SPECIFICATION_VER_REVISION 1440
+
+/** VL53L0 PAL IMPLEMENTATION major version */
+#define VL53L010_IMPLEMENTATION_VER_MAJOR 1
+/** VL53L0 PAL IMPLEMENTATION minor version */
+#define VL53L010_IMPLEMENTATION_VER_MINOR 0
+/** VL53L0 PAL IMPLEMENTATION sub version */
+#define VL53L010_IMPLEMENTATION_VER_SUB 9
+/** VL53L0 PAL IMPLEMENTATION sub version */
+#define VL53L010_IMPLEMENTATION_VER_REVISION 3673
+
+/** PAL SPECIFICATION major version */
+#define VL53L0_SPECIFICATION_VER_MAJOR 1
+/** PAL SPECIFICATION minor version */
+#define VL53L0_SPECIFICATION_VER_MINOR 2
+/** PAL SPECIFICATION sub version */
+#define VL53L0_SPECIFICATION_VER_SUB 7
+/** PAL SPECIFICATION sub version */
+#define VL53L0_SPECIFICATION_VER_REVISION 1440
+
+/** VL53L0 PAL IMPLEMENTATION major version */
+#define VL53L0_IMPLEMENTATION_VER_MAJOR 1
+/** VL53L0 PAL IMPLEMENTATION minor version */
+#define VL53L0_IMPLEMENTATION_VER_MINOR 1
+/** VL53L0 PAL IMPLEMENTATION sub version */
+#define VL53L0_IMPLEMENTATION_VER_SUB 20
+/** VL53L0 PAL IMPLEMENTATION sub version */
+#define VL53L0_IMPLEMENTATION_VER_REVISION 4606
+#define VL53L0_DEFAULT_MAX_LOOP 200
+#define VL53L0_MAX_STRING_LENGTH 32
+
+
+#include "vl53l0_device.h"
+#include "vl53l0_types.h"
+
+
+/****************************************
+ * PRIVATE define do not edit
+ ****************************************/
+
+/** @brief Defines the parameters of the Get Version Functions
+ */
+typedef struct {
+ uint32_t revision; /*!< revision number */
+ uint8_t major; /*!< major number */
+ uint8_t minor; /*!< minor number */
+ uint8_t build; /*!< build number */
+} VL53L0_Version_t;
+
+
+/** @brief Defines the parameters of the Get Device Info Functions
+ */
+typedef struct {
+ char Name[VL53L0_MAX_STRING_LENGTH];
+ /*!< Name of the Device e.g. Left_Distance */
+ char Type[VL53L0_MAX_STRING_LENGTH];
+ /*!< Type of the Device e.g VL53L0 */
+ char ProductId[VL53L0_MAX_STRING_LENGTH];
+ /*!< Product Identifier String */
+ uint8_t ProductType;
+ /*!< Product Type, VL53L0 = 1, VL53L1 = 2 */
+ uint8_t ProductRevisionMajor;
+ /*!< Product revision major */
+ uint8_t ProductRevisionMinor;
+ /*!< Product revision minor */
+} VL53L0_DeviceInfo_t;
+
+
+/** @defgroup VL53L0_define_Error_group Error and Warning code returned by API
+ * The following DEFINE are used to identify the PAL ERROR
+ * @{
+ */
+
+typedef int8_t VL53L0_Error;
+
+#define VL53L0_ERROR_NONE ((VL53L0_Error) 0)
+#define VL53L0_ERROR_CALIBRATION_WARNING ((VL53L0_Error) - 1)
+ /*!< Warning invalid calibration data may be in used
+ * \a VL53L0_InitData()
+ * \a VL53L0_GetOffsetCalibrationData
+ * \a VL53L0_SetOffsetCalibrationData
+ */
+#define VL53L0_ERROR_MIN_CLIPPED ((VL53L0_Error) - 2)
+ /*!< Warning parameter passed was clipped to min before to be applied */
+
+#define VL53L0_ERROR_UNDEFINED ((VL53L0_Error) - 3)
+ /*!< Unqualified error */
+#define VL53L0_ERROR_INVALID_PARAMS ((VL53L0_Error) - 4)
+ /*!< Parameter passed is invalid or out of range */
+#define VL53L0_ERROR_NOT_SUPPORTED ((VL53L0_Error) - 5)
+ /*!< Function is not supported in current mode or configuration */
+#define VL53L0_ERROR_RANGE_ERROR ((VL53L0_Error) - 6)
+ /*!< Device report a ranging error interrupt status */
+#define VL53L0_ERROR_TIME_OUT ((VL53L0_Error) - 7)
+ /*!< Aborted due to time out */
+#define VL53L0_ERROR_MODE_NOT_SUPPORTED ((VL53L0_Error) - 8)
+ /*!< Asked mode is not supported by the device */
+#define VL53L0_ERROR_BUFFER_TOO_SMALL ((VL53L0_Error) - 9)
+ /*!< ... */
+#define VL53L0_ERROR_GPIO_NOT_EXISTING ((VL53L0_Error) - 10)
+ /*!< User tried to setup a non-existing GPIO pin */
+#define VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ((VL53L0_Error) - 11)
+ /*!< unsupported GPIO functionality */
+#define VL53L0_ERROR_INTERRUPT_NOT_CLEARED ((VL53L0_Error) - 12)
+ /*!< Error during interrupt clear */
+#define VL53L0_ERROR_CONTROL_INTERFACE ((VL53L0_Error) - 20)
+ /*!< error reported from IO functions */
+#define VL53L0_ERROR_INVALID_COMMAND ((VL53L0_Error) - 30)
+ /*!< The command is not allowed in the current device state
+ * (power down)
+ */
+#define VL53L0_ERROR_DIVISION_BY_ZERO ((VL53L0_Error) - 40)
+ /*!< In the function a division by zero occurs */
+#define VL53L0_ERROR_REF_SPAD_INIT ((VL53L0_Error) - 50)
+ /*!< Error during reference SPAD initialization */
+#define VL53L0_ERROR_NOT_IMPLEMENTED ((VL53L0_Error) - 99)
+ /*!< Tells requested functionality has not been implemented yet or
+ * not compatible with the device
+ */
+/** @} VL53L0_define_Error_group */
+
+
+/** @defgroup VL53L0_define_DeviceModes_group Defines Device modes
+ * Defines all possible modes for the device
+ * @{
+ */
+typedef uint8_t VL53L0_DeviceModes;
+
+#define VL53L0_DEVICEMODE_SINGLE_RANGING ((VL53L0_DeviceModes) 0)
+#define VL53L0_DEVICEMODE_CONTINUOUS_RANGING ((VL53L0_DeviceModes) 1)
+#define VL53L0_DEVICEMODE_SINGLE_HISTOGRAM ((VL53L0_DeviceModes) 2)
+#define VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING ((VL53L0_DeviceModes) 3)
+#define VL53L0_DEVICEMODE_SINGLE_ALS ((VL53L0_DeviceModes) 10)
+#define VL53L0_DEVICEMODE_GPIO_DRIVE ((VL53L0_DeviceModes) 20)
+#define VL53L0_DEVICEMODE_GPIO_OSC ((VL53L0_DeviceModes) 21)
+ /* ... Modes to be added depending on device */
+/** @} VL53L0_define_DeviceModes_group */
+
+
+
+/** @defgroup VL53L0_define_HistogramModes_group Defines Histogram modes
+ * Defines all possible Histogram modes for the device
+ * @{
+ */
+typedef uint8_t VL53L0_HistogramModes;
+
+#define VL53L0_HISTOGRAMMODE_DISABLED ((VL53L0_HistogramModes) 0)
+ /*!< Histogram Disabled */
+#define VL53L0_HISTOGRAMMODE_REFERENCE_ONLY ((VL53L0_HistogramModes) 1)
+ /*!< Histogram Reference array only */
+#define VL53L0_HISTOGRAMMODE_RETURN_ONLY ((VL53L0_HistogramModes) 2)
+ /*!< Histogram Return array only */
+#define VL53L0_HISTOGRAMMODE_BOTH ((VL53L0_HistogramModes) 3)
+ /*!< Histogram both Reference and Return Arrays */
+ /* ... Modes to be added depending on device */
+/** @} VL53L0_define_HistogramModes_group */
+
+
+/** @defgroup VL53L0_define_PowerModes_group List of available Power Modes
+ * List of available Power Modes
+ * @{
+ */
+
+typedef uint8_t VL53L0_PowerModes;
+
+#define VL53L0_POWERMODE_STANDBY_LEVEL1 ((VL53L0_PowerModes) 0)
+ /*!< Standby level 1 */
+#define VL53L0_POWERMODE_STANDBY_LEVEL2 ((VL53L0_PowerModes) 1)
+ /*!< Standby level 2 */
+#define VL53L0_POWERMODE_IDLE_LEVEL1 ((VL53L0_PowerModes) 2)
+ /*!< Idle level 1 */
+#define VL53L0_POWERMODE_IDLE_LEVEL2 ((VL53L0_PowerModes) 3)
+ /*!< Idle level 2 */
+
+/** @} VL53L0_define_PowerModes_group */
+
+
+/** @brief Defines all parameters for the device
+ */
+typedef struct {
+ VL53L0_DeviceModes DeviceMode;
+ /*!< Defines type of measurement to be done for the next measure */
+ VL53L0_HistogramModes HistogramMode;
+ /*!< Defines type of histogram measurement to be done for the next
+ * measure
+ */
+ uint32_t MeasurementTimingBudgetMicroSeconds;
+ /*!< Defines the allowed total time for a single measurement */
+ uint32_t InterMeasurementPeriodMilliSeconds;
+ /*!< Defines time between two consecutive measurements (between two
+ * measurement starts). If set to 0 means back-to-back mode
+ */
+ uint8_t XTalkCompensationEnable;
+ /*!< Tells if Crosstalk compensation shall be enable or not */
+ uint16_t XTalkCompensationRangeMilliMeter;
+ /*!< CrossTalk compensation range in millimeter */
+ FixPoint1616_t XTalkCompensationRateMegaCps;
+ /*!< CrossTalk compensation rate in Mega counts per seconds.
+ * Expressed in 16.16 fixed point format.
+ */
+ int32_t RangeOffsetMicroMeters;
+ /*!< Range offset adjustment (mm). */
+
+ uint8_t LimitChecksEnable[VL53L0_CHECKENABLE_NUMBER_OF_CHECKS];
+ /*!< This Array store all the Limit Check enable for this device. */
+ uint8_t LimitChecksStatus[VL53L0_CHECKENABLE_NUMBER_OF_CHECKS];
+ /*!< This Array store all the Status of the check linked to last
+ * measurement.
+ */
+ FixPoint1616_t LimitChecksValue[VL53L0_CHECKENABLE_NUMBER_OF_CHECKS];
+ /*!< This Array store all the Limit Check value for this device */
+
+ uint8_t WrapAroundCheckEnable;
+ /*!< Tells if Wrap Around Check shall be enable or not */
+} VL53L0_DeviceParameters_t;
+
+
+/** @defgroup VL53L0_define_State_group Defines the current status of the device
+ * Defines the current status of the device
+ * @{
+ */
+
+typedef uint8_t VL53L0_State;
+
+#define VL53L0_STATE_POWERDOWN ((VL53L0_State) 0)
+ /*!< Device is in HW reset */
+#define VL53L0_STATE_WAIT_STATICINIT ((VL53L0_State) 1)
+ /*!< Device is initialized and wait for static initialization */
+#define VL53L0_STATE_STANDBY ((VL53L0_State) 2)
+ /*!< Device is in Low power Standby mode */
+#define VL53L0_STATE_IDLE ((VL53L0_State) 3)
+ /*!< Device has been initialized and ready to do measurements */
+#define VL53L0_STATE_RUNNING ((VL53L0_State) 4)
+ /*!< Device is performing measurement */
+#define VL53L0_STATE_UNKNOWN ((VL53L0_State) 98)
+ /*!< Device is in unknown state and need to be rebooted */
+#define VL53L0_STATE_ERROR ((VL53L0_State) 99)
+ /*!< Device is in error state and need to be rebooted */
+
+/** @} VL53L0_define_State_group */
+
+
+/** @brief Structure containing the Dmax computation parameters and data
+ */
+typedef struct {
+ int32_t AmbTuningWindowFactor_K;
+ /*!< internal algo tuning (*1000) */
+ int32_t RetSignalAt0mm;
+ /*!< intermediate dmax computation value caching */
+} VL53L0_DMaxData_t;
+
+/**
+ * @struct VL53L0_RangeData_t
+ * @brief Range measurement data.
+ */
+typedef struct {
+ uint32_t TimeStamp; /*!< 32-bit time stamp. */
+ uint32_t MeasurementTimeUsec;
+ /*!< Give the Measurement time needed by the device to do the
+ * measurement.
+ */
+
+
+ uint16_t RangeMilliMeter; /*!< range distance in millimeter. */
+
+ uint16_t RangeDMaxMilliMeter;
+ /*!< Tells what is the maximum detection distance of the device
+ * in current setup and environment conditions (Filled when
+ * applicable)
+ */
+
+ FixPoint1616_t SignalRateRtnMegaCps;
+ /*!< Return signal rate (MCPS)\n these is a 16.16 fix point
+ * value, which is effectively a measure of target
+ * reflectance.
+ */
+ FixPoint1616_t AmbientRateRtnMegaCps;
+ /*!< Return ambient rate (MCPS)\n these is a 16.16 fix point
+ * value, which is effectively a measure of the ambien
+ * t light.
+ */
+
+ uint16_t EffectiveSpadRtnCount;
+ /*!< Return the effective SPAD count for the return signal.
+ * To obtain Real value it should be divided by 256
+ */
+
+ uint8_t ZoneId;
+ /*!< Denotes which zone and range scheduler stage the range
+ * data relates to.
+ */
+ uint8_t RangeFractionalPart;
+ /*!< Fractional part of range distance. Final value is a
+ * FixPoint168 value.
+ */
+ uint8_t RangeStatus;
+ /*!< Range Status for the current measurement. This is device
+ * dependent. Value = 0 means value is valid.
+ * See \ref RangeStatusPage
+ */
+} VL53L0_RangingMeasurementData_t;
+
+
+#define VL53L0_HISTOGRAM_BUFFER_SIZE 24
+
+/**
+ * @struct VL53L0_HistogramData_t
+ * @brief Histogram measurement data.
+ */
+typedef struct {
+ /* Histogram Measurement data */
+ uint32_t HistogramData[VL53L0_HISTOGRAM_BUFFER_SIZE];
+ /*!< Histogram data */
+ /*!< Indicate the types of histogram data :
+ *Return only, Reference only, both Return and Reference
+ */
+ uint8_t HistogramType;
+ uint8_t FirstBin; /*!< First Bin value */
+ uint8_t BufferSize; /*!< Buffer Size - Set by the user.*/
+ uint8_t NumberOfBins;
+ /*!< Number of bins filled by the histogram measurement */
+
+ VL53L0_DeviceError ErrorStatus;
+ /*!< Error status of the current measurement. \n
+ * see @a ::VL53L0_DeviceError @a VL53L0_GetStatusErrorString()
+ */
+} VL53L0_HistogramMeasurementData_t;
+
+#define VL53L0_REF_SPAD_BUFFER_SIZE 6
+
+/**
+ * @struct VL53L0_SpadData_t
+ * @brief Spad Configuration Data.
+ */
+typedef struct {
+ uint8_t RefSpadEnables[VL53L0_REF_SPAD_BUFFER_SIZE];
+ /*!< Reference Spad Enables */
+ uint8_t RefGoodSpadMap[VL53L0_REF_SPAD_BUFFER_SIZE];
+ /*!< Reference Spad Good Spad Map */
+} VL53L0_SpadData_t;
+
+typedef struct {
+ FixPoint1616_t OscFrequencyMHz; /* Frequency used */
+
+ uint16_t LastEncodedTimeout;
+ /* last encoded Time out used for timing budget*/
+
+ VL53L0_GpioFunctionality Pin0GpioFunctionality;
+ /* store the functionality of the GPIO: pin0 */
+
+ uint32_t FinalRangeTimeoutMicroSecs;
+ /*!< Execution time of the final range*/
+ uint8_t FinalRangeVcselPulsePeriod;
+ /*!< Vcsel pulse period (pll clocks) for the final range measurement*/
+ uint32_t PreRangeTimeoutMicroSecs;
+ /*!< Execution time of the final range*/
+ uint8_t PreRangeVcselPulsePeriod;
+ /*!< Vcsel pulse period (pll clocks) for the pre-range measurement*/
+
+ uint16_t SigmaEstRefArray;
+ /*!< Reference array sigma value in 1/100th of [mm] e.g. 100 = 1mm */
+ uint16_t SigmaEstEffPulseWidth;
+ /*!< Effective Pulse width for sigma estimate in 1/100th
+ * of ns e.g. 900 = 9.0ns
+ */
+ uint16_t SigmaEstEffAmbWidth;
+ /*!< Effective Ambient width for sigma estimate in 1/100th of ns
+ * e.g. 500 = 5.0ns
+ */
+
+
+ /* Indicate if read from device has been done (==1) or not (==0) */
+ uint8_t ReadDataFromDeviceDone;
+ uint8_t ModuleId; /* Module ID */
+ uint8_t Revision; /* test Revision */
+ char ProductId[VL53L0_MAX_STRING_LENGTH];
+ /* Product Identifier String */
+ uint8_t ReferenceSpadCount; /* used for ref spad management */
+ uint8_t ReferenceSpadType; /* used for ref spad management */
+ uint8_t RefSpadsInitialised; /* reports if ref spads are initialised. */
+ uint32_t PartUIDUpper; /*!< Unique Part ID Upper */
+ uint32_t PartUIDLower; /*!< Unique Part ID Lower */
+ /*!< Peek Signal rate at 400 mm*/
+ FixPoint1616_t SignalRateMeasFixed400mm;
+
+} VL53L0_DeviceSpecificParameters_t;
+
+/**
+ * @struct VL53L0_DevData_t
+ *
+ * @brief VL53L0 PAL device ST private data structure \n
+ * End user should never access any of these field directly
+ *
+ * These must never access directly but only via macro
+ */
+typedef struct {
+ VL53L0_DMaxData_t DMaxData;
+ /*!< Dmax Data */
+ int32_t Part2PartOffsetNVMMicroMeter;
+ /*!< backed up NVM value */
+ int32_t Part2PartOffsetAdjustmentNVMMicroMeter;
+ /*!< backed up NVM value representing additional offset adjustment */
+ VL53L0_DeviceParameters_t CurrentParameters;
+ /*!< Current Device Parameter */
+ VL53L0_RangingMeasurementData_t LastRangeMeasure;
+ /*!< Ranging Data */
+ VL53L0_HistogramMeasurementData_t LastHistogramMeasure;
+ /*!< Histogram Data */
+ VL53L0_DeviceSpecificParameters_t DeviceSpecificParameters;
+ /*!< Parameters specific to the device */
+ VL53L0_SpadData_t SpadData;
+ /*!< Spad Data */
+ uint8_t SequenceConfig;
+ /*!< Internal value for the sequence config */
+ uint8_t RangeFractionalEnable;
+ /*!< Enable/Disable fractional part of ranging data */
+ VL53L0_State PalState;
+ /*!< Current state of the PAL for this device */
+ VL53L0_PowerModes PowerMode;
+ /*!< Current Power Mode */
+ uint16_t SigmaEstRefArray;
+ /*!< Reference array sigma value in 1/100th of [mm] e.g. 100 = 1mm */
+ uint16_t SigmaEstEffPulseWidth;
+ /*!< Effective Pulse width for sigma estimate in 1/100th
+ * of ns e.g. 900 = 9.0ns
+ */
+ uint16_t SigmaEstEffAmbWidth;
+ /*!< Effective Ambient width for sigma estimate in 1/100th of ns
+ * e.g. 500 = 5.0ns
+ */
+ uint8_t StopVariable;
+ /*!< StopVariable used during the stop sequence */
+ uint16_t targetRefRate;
+ /*!< Target Ambient Rate for Ref spad management */
+ FixPoint1616_t SigmaEstimate;
+ /*!< Sigma Estimate - based on ambient & VCSEL rates and
+ * signal_total_events
+ */
+ FixPoint1616_t SignalEstimate;
+ /*!< Signal Estimate - based on ambient & VCSEL rates and cross talk */
+ FixPoint1616_t LastSignalRefMcps;
+ /*!< Latest Signal ref in Mcps */
+ uint8_t *pTuningSettingsPointer;
+ /*!< Pointer for Tuning Settings table */
+ uint8_t UseInternalTuningSettings;
+ /*!< Indicate if we use Tuning Settings table */
+ uint16_t LinearityCorrectiveGain;
+ /*!< Linearity Corrective Gain value in x1000 */
+ uint16_t DmaxCalRangeMilliMeter;
+ /*!< Dmax Calibration Range millimeter */
+ FixPoint1616_t DmaxCalSignalRateRtnMegaCps;
+ /*!< Dmax Calibration Signal Rate Return MegaCps */
+
+} VL53L0_DevData_t;
+
+
+/** @defgroup VL53L0_define_InterruptPolarity_group Defines the Polarity
+ * of the Interrupt
+ * Defines the Polarity of the Interrupt
+ * @{
+ */
+typedef uint8_t VL53L0_InterruptPolarity;
+
+#define VL53L0_INTERRUPTPOLARITY_LOW ((VL53L0_InterruptPolarity) 0)
+/*!< Set active low polarity best setup for falling edge. */
+#define VL53L0_INTERRUPTPOLARITY_HIGH ((VL53L0_InterruptPolarity) 1)
+/*!< Set active high polarity best setup for rising edge. */
+
+/** @} VL53L0_define_InterruptPolarity_group */
+
+
+/** @defgroup VL53L0_define_VcselPeriod_group Vcsel Period Defines
+ * Defines the range measurement for which to access the vcsel period.
+ * @{
+ */
+typedef uint8_t VL53L0_VcselPeriod;
+
+#define VL53L0_VCSEL_PERIOD_PRE_RANGE ((VL53L0_VcselPeriod) 0)
+/*!<Identifies the pre-range vcsel period. */
+#define VL53L0_VCSEL_PERIOD_FINAL_RANGE ((VL53L0_VcselPeriod) 1)
+/*!<Identifies the final range vcsel period. */
+
+/** @} VL53L0_define_VcselPeriod_group */
+
+/** @defgroup VL53L0_define_SchedulerSequence_group Defines the steps
+ * carried out by the scheduler during a range measurement.
+ * @{
+ * Defines the states of all the steps in the scheduler
+ * i.e. enabled/disabled.
+ */
+typedef struct {
+ uint8_t TccOn; /*!<Reports if Target Centre Check On */
+ uint8_t MsrcOn; /*!<Reports if MSRC On */
+ uint8_t DssOn; /*!<Reports if DSS On */
+ uint8_t PreRangeOn; /*!<Reports if Pre-Range On */
+ uint8_t FinalRangeOn; /*!<Reports if Final-Range On */
+} VL53L0_SchedulerSequenceSteps_t;
+
+/** @} VL53L0_define_SchedulerSequence_group */
+
+/** @defgroup VL53L0_define_SequenceStepId_group Defines the Polarity
+ * of the Interrupt
+ * Defines the the sequence steps performed during ranging..
+ * @{
+ */
+typedef uint8_t VL53L0_SequenceStepId;
+
+#define VL53L0_SEQUENCESTEP_TCC ((VL53L0_VcselPeriod) 0)
+/*!<Target CentreCheck identifier. */
+#define VL53L0_SEQUENCESTEP_DSS ((VL53L0_VcselPeriod) 1)
+/*!<Dynamic Spad Selection function Identifier. */
+#define VL53L0_SEQUENCESTEP_MSRC ((VL53L0_VcselPeriod) 2)
+/*!<Minimum Signal Rate Check function Identifier. */
+#define VL53L0_SEQUENCESTEP_PRE_RANGE ((VL53L0_VcselPeriod) 3)
+/*!<Pre-Range check Identifier. */
+#define VL53L0_SEQUENCESTEP_FINAL_RANGE ((VL53L0_VcselPeriod) 4)
+/*!<Final Range Check Identifier. */
+
+#define VL53L0_SEQUENCESTEP_NUMBER_OF_CHECKS 5
+/*!<Number of Sequence Step Managed by the API. */
+
+/** @} VL53L0_define_SequenceStepId_group */
+
+
+/* MACRO Definitions */
+/** @defgroup VL53L0_define_GeneralMacro_group General Macro Defines
+ * General Macro Defines
+ * @{
+ */
+
+/* Defines */
+#define VL53L0_SETPARAMETERFIELD(Dev, field, value) \
+ PALDevDataSet(Dev, CurrentParameters.field, value)
+
+#define VL53L0_GETPARAMETERFIELD(Dev, field, variable) \
+ (variable = ((PALDevDataGet(Dev, CurrentParameters)).field))
+
+
+#define VL53L0_SETARRAYPARAMETERFIELD(Dev, field, index, value) \
+ PALDevDataSet(Dev, CurrentParameters.field[index], value)
+
+#define VL53L0_GETARRAYPARAMETERFIELD(Dev, field, index, variable) \
+ (variable = (PALDevDataGet(Dev, CurrentParameters)).field[index])
+
+
+#define VL53L0_SETDEVICESPECIFICPARAMETER(Dev, field, value) \
+ PALDevDataSet(Dev, DeviceSpecificParameters.field, value)
+
+#define VL53L0_GETDEVICESPECIFICPARAMETER(Dev, field) \
+ PALDevDataGet(Dev, DeviceSpecificParameters).field
+
+
+#define VL53L0_FIXPOINT1616TOFIXPOINT97(Value) \
+ (uint16_t)((Value>>9)&0xFFFF)
+#define VL53L0_FIXPOINT97TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value<<9)
+
+#define VL53L0_FIXPOINT1616TOFIXPOINT88(Value) \
+ (uint16_t)((Value>>8)&0xFFFF)
+#define VL53L0_FIXPOINT88TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value<<8)
+
+#define VL53L0_FIXPOINT1616TOFIXPOINT412(Value) \
+ (uint16_t)((Value>>4)&0xFFFF)
+#define VL53L0_FIXPOINT412TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value<<4)
+
+#define VL53L0_FIXPOINT1616TOFIXPOINT313(Value) \
+ (uint16_t)((Value>>3)&0xFFFF)
+#define VL53L0_FIXPOINT313TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value<<3)
+
+#define VL53L0_FIXPOINT1616TOFIXPOINT08(Value) \
+ (uint8_t)((Value>>8)&0x00FF)
+#define VL53L0_FIXPOINT08TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value<<8)
+
+#define VL53L0_FIXPOINT1616TOFIXPOINT53(Value) \
+ (uint8_t)((Value>>13)&0x00FF)
+#define VL53L0_FIXPOINT53TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value<<13)
+
+#define VL53L0_FIXPOINT1616TOFIXPOINT102(Value) \
+ (uint16_t)((Value>>14)&0x0FFF)
+#define VL53L0_FIXPOINT102TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value<<12)
+
+#define VL53L0_MAKEUINT16(lsb, msb) (uint16_t)((((uint16_t)msb)<<8) + \
+ (uint16_t)lsb)
+
+/** @} VL53L0_define_GeneralMacro_group */
+
+/** @} VL53L0_globaldefine_group */
+
+
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _VL53L0_DEF_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_device.h b/drivers/input/misc/vl53L0/inc/vl53l0_device.h
new file mode 100644
index 000000000000..b69b9cf72279
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_device.h
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+/**
+ * Device specific defines. To be adapted by implementer for the targeted
+ * device.
+ */
+
+#ifndef _VL53L0_DEVICE_H_
+#define _VL53L0_DEVICE_H_
+
+#include "vl53l0_types.h"
+
+
+/** @defgroup VL53L0_DevSpecDefines_group VL53L0 cut1.1 Device Specific Defines
+ * @brief VL53L0 cut1.1 Device Specific Defines
+ * @{
+ */
+
+
+/** @defgroup VL53L0_DeviceError_group Device Error
+ * @brief Device Error code
+ *
+ * This enum is Device specific it should be updated in the implementation
+ * Use @a VL53L0_GetStatusErrorString() to get the string.
+ * It is related to Status Register of the Device.
+ * @{
+ */
+typedef uint8_t VL53L0_DeviceError;
+
+#define VL53L0_DEVICEERROR_NONE ((VL53L0_DeviceError) 0)
+ /*!< 0 NoError */
+#define VL53L0_DEVICEERROR_VCSELCONTINUITYTESTFAILURE ((VL53L0_DeviceError) 1)
+#define VL53L0_DEVICEERROR_VCSELWATCHDOGTESTFAILURE ((VL53L0_DeviceError) 2)
+#define VL53L0_DEVICEERROR_NOVHVVALUEFOUND ((VL53L0_DeviceError) 3)
+#define VL53L0_DEVICEERROR_MSRCNOTARGET ((VL53L0_DeviceError) 4)
+#define VL53L0_DEVICEERROR_SNRCHECK ((VL53L0_DeviceError) 5)
+#define VL53L0_DEVICEERROR_RANGEPHASECHECK ((VL53L0_DeviceError) 6)
+#define VL53L0_DEVICEERROR_SIGMATHRESHOLDCHECK ((VL53L0_DeviceError) 7)
+#define VL53L0_DEVICEERROR_TCC ((VL53L0_DeviceError) 8)
+#define VL53L0_DEVICEERROR_PHASECONSISTENCY ((VL53L0_DeviceError) 9)
+#define VL53L0_DEVICEERROR_MINCLIP ((VL53L0_DeviceError) 10)
+#define VL53L0_DEVICEERROR_RANGECOMPLETE ((VL53L0_DeviceError) 11)
+#define VL53L0_DEVICEERROR_ALGOUNDERFLOW ((VL53L0_DeviceError) 12)
+#define VL53L0_DEVICEERROR_ALGOOVERFLOW ((VL53L0_DeviceError) 13)
+#define VL53L0_DEVICEERROR_RANGEIGNORETHRESHOLD ((VL53L0_DeviceError) 14)
+
+/** @} end of VL53L0_DeviceError_group */
+
+
+/** @defgroup VL53L0_CheckEnable_group Check Enable list
+ * @brief Check Enable code
+ *
+ * Define used to specify the LimitCheckId.
+ * Use @a VL53L0_GetLimitCheckInfo() to get the string.
+ * @{
+ */
+
+#define VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE 0
+#define VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE 1
+#define VL53L0_CHECKENABLE_SIGNAL_REF_CLIP 2
+#define VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD 3
+#define VL53L0_CHECKENABLE_SIGNAL_RATE_MSRC 4
+#define VL53L0_CHECKENABLE_SIGNAL_RATE_PRE_RANGE 5
+
+#define VL53L0_CHECKENABLE_NUMBER_OF_CHECKS 6
+
+/** @} end of VL53L0_CheckEnable_group */
+
+
+/** @defgroup VL53L0_GpioFunctionality_group Gpio Functionality
+ * @brief Defines the different functionalities for the device GPIO(s)
+ * @{
+ */
+typedef uint8_t VL53L0_GpioFunctionality;
+
+#define VL53L0_GPIOFUNCTIONALITY_OFF \
+ ((VL53L0_GpioFunctionality) 0) /*!< NO Interrupt */
+#define VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW \
+ ((VL53L0_GpioFunctionality) 1) /*!< Level Low (value < thresh_low) */
+#define VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH \
+ ((VL53L0_GpioFunctionality) 2) /*!< Level High (value > thresh_high) */
+#define VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT \
+ ((VL53L0_GpioFunctionality) 3)
+ /*!< Out Of Window (value < thresh_low OR value > thresh_high) */
+#define VL53L0_GPIOFUNCTIONALITY_NEW_MEASURE_READY \
+ ((VL53L0_GpioFunctionality) 4) /*!< New Sample Ready */
+
+/** @} end of VL53L0_GpioFunctionality_group */
+
+
+/* Device register map */
+
+/** @defgroup VL53L0_DefineRegisters_group Define Registers
+ * @brief List of all the defined registers
+ * @{
+ */
+#define VL53L0_REG_SYSRANGE_START 0x000
+ /** mask existing bit in #VL53L0_REG_SYSRANGE_START*/
+ #define VL53L0_REG_SYSRANGE_MODE_MASK 0x0F
+ /** bit 0 in #VL53L0_REG_SYSRANGE_START write 1 toggle state in
+ * continuous mode and arm next shot in single shot mode
+ */
+ #define VL53L0_REG_SYSRANGE_MODE_START_STOP 0x01
+ /** bit 1 write 0 in #VL53L0_REG_SYSRANGE_START set single shot mode */
+ #define VL53L0_REG_SYSRANGE_MODE_SINGLESHOT 0x00
+ /** bit 1 write 1 in #VL53L0_REG_SYSRANGE_START set back-to-back
+ * operation mode
+ */
+ #define VL53L0_REG_SYSRANGE_MODE_BACKTOBACK 0x02
+ /** bit 2 write 1 in #VL53L0_REG_SYSRANGE_START set timed operation
+ * mode
+ */
+ #define VL53L0_REG_SYSRANGE_MODE_TIMED 0x04
+ /** bit 3 write 1 in #VL53L0_REG_SYSRANGE_START set histogram operation
+ * mode
+ */
+ #define VL53L0_REG_SYSRANGE_MODE_HISTOGRAM 0x08
+
+
+#define VL53L0_REG_SYSTEM_THRESH_HIGH 0x000C
+#define VL53L0_REG_SYSTEM_THRESH_LOW 0x000E
+
+
+#define VL53L0_REG_SYSTEM_SEQUENCE_CONFIG 0x0001
+#define VL53L0_REG_SYSTEM_RANGE_CONFIG 0x0009
+#define VL53L0_REG_SYSTEM_INTERMEASUREMENT_PERIOD 0x0004
+
+
+#define VL53L0_REG_SYSTEM_INTERRUPT_CONFIG_GPIO 0x000A
+ #define VL53L0_REG_SYSTEM_INTERRUPT_GPIO_DISABLED 0x00
+ #define VL53L0_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_LOW 0x01
+ #define VL53L0_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_HIGH 0x02
+ #define VL53L0_REG_SYSTEM_INTERRUPT_GPIO_OUT_OF_WINDOW 0x03
+ #define VL53L0_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY 0x04
+
+#define VL53L0_REG_GPIO_HV_MUX_ACTIVE_HIGH 0x0084
+
+
+#define VL53L0_REG_SYSTEM_INTERRUPT_CLEAR 0x000B
+
+/* Result registers */
+#define VL53L0_REG_RESULT_INTERRUPT_STATUS 0x0013
+#define VL53L0_REG_RESULT_RANGE_STATUS 0x0014
+
+#define VL53L0_REG_RESULT_CORE_PAGE 1
+#define VL53L0_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN 0x00BC
+#define VL53L0_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_RTN 0x00C0
+#define VL53L0_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF 0x00D0
+#define VL53L0_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_REF 0x00D4
+#define VL53L0_REG_RESULT_PEAK_SIGNAL_RATE_REF 0x00B6
+
+/* Algo register */
+
+#define VL53L0_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM 0x0028
+
+#define VL53L0_REG_I2C_SLAVE_DEVICE_ADDRESS 0x008a
+
+/* Check Limit registers */
+#define VL53L0_REG_MSRC_CONFIG_CONTROL 0x0060
+
+#define VL53L0_REG_PRE_RANGE_CONFIG_MIN_SNR 0X0027
+#define VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW 0x0056
+#define VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH 0x0057
+#define VL53L0_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT 0x0064
+
+#define VL53L0_REG_FINAL_RANGE_CONFIG_MIN_SNR 0X0067
+#define VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW 0x0047
+#define VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH 0x0048
+#define VL53L0_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT 0x0044
+
+
+#define VL53L0_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_HI 0X0061
+#define VL53L0_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_LO 0X0062
+
+/* PRE RANGE registers */
+#define VL53L0_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD 0x0050
+#define VL53L0_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x0051
+#define VL53L0_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x0052
+
+#define VL53L0_REG_SYSTEM_HISTOGRAM_BIN 0x0081
+#define VL53L0_REG_HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT 0x0033
+#define VL53L0_REG_HISTOGRAM_CONFIG_READOUT_CTRL 0x0055
+
+#define VL53L0_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x0070
+#define VL53L0_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x0071
+#define VL53L0_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x0072
+#define VL53L0_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS 0x0020
+
+#define VL53L0_REG_MSRC_CONFIG_TIMEOUT_MACROP 0x0046
+
+
+#define VL53L0_REG_SOFT_RESET_GO2_SOFT_RESET_N 0x00bf
+#define VL53L0_REG_IDENTIFICATION_MODEL_ID 0x00c0
+#define VL53L0_REG_IDENTIFICATION_REVISION_ID 0x00c2
+
+#define VL53L0_REG_OSC_CALIBRATE_VAL 0x00f8
+
+
+#define VL53L0_SIGMA_ESTIMATE_MAX_VALUE 65535
+/* equivalent to a range sigma of 655.35mm */
+
+#define VL53L0_REG_GLOBAL_CONFIG_VCSEL_WIDTH 0x032
+#define VL53L0_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0 0x0B0
+#define VL53L0_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_1 0x0B1
+#define VL53L0_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_2 0x0B2
+#define VL53L0_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_3 0x0B3
+#define VL53L0_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_4 0x0B4
+#define VL53L0_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_5 0x0B5
+
+#define VL53L0_REG_GLOBAL_CONFIG_REF_EN_START_SELECT 0xB6
+#define VL53L0_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD 0x4E /* 0x14E */
+#define VL53L0_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET 0x4F /* 0x14F */
+#define VL53L0_REG_POWER_MANAGEMENT_GO1_POWER_FORCE 0x80
+
+/*
+ * Speed of light in um per 1E-10 Seconds
+ */
+
+#define VL53L0_SPEED_OF_LIGHT_IN_AIR 2997
+
+#define VL53L0_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV 0x0089
+
+#define VL53L0_REG_ALGO_PHASECAL_LIM 0x0030 /* 0x130 */
+#define VL53L0_REG_ALGO_PHASECAL_CONFIG_TIMEOUT 0x0030
+
+/** @} VL53L0_DefineRegisters_group */
+
+/** @} VL53L0_DevSpecDefines_group */
+
+
+#endif
+
+/* _VL53L0_DEVICE_H_ */
+
+
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_i2c_platform.h b/drivers/input/misc/vl53L0/inc/vl53l0_i2c_platform.h
new file mode 100644
index 000000000000..9b1bdd7f3c54
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_i2c_platform.h
@@ -0,0 +1,402 @@
+/*
+ * vl53l0_i2c_platform.h - Linux kernel modules for STM VL53L0 FlightSense TOF
+ * sensor
+ *
+ * Copyright (C) 2016 STMicroelectronics Imaging Division.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/**
+ * @file VL53L0_i2c_platform.h
+ * @brief Function prototype definitions for EWOK Platform layer.
+ *
+ */
+
+
+#ifndef _VL53L0_I2C_PLATFORM_H_
+#define _VL53L0_I2C_PLATFORM_H_
+
+#include "vl53l0_def.h"
+
+
+/** Maximum buffer size to be used in i2c */
+#define VL53L0_MAX_I2C_XFER_SIZE 64
+
+/**
+ * @brief Typedef defining .\n
+ * The developer should modify this to suit the platform being deployed.
+ *
+ */
+
+/**
+ * @brief Typedef defining 8 bit unsigned char type.\n
+ * The developer should modify this to suit the platform being deployed.
+ *
+ */
+
+#ifndef bool_t
+typedef unsigned char bool_t;
+#endif
+
+
+#define I2C 0x01
+#define SPI 0x00
+
+#define COMMS_BUFFER_SIZE 64
+/*MUST be the same size as the SV task buffer */
+
+#define BYTES_PER_WORD 2
+#define BYTES_PER_DWORD 4
+
+#define VL53L0_MAX_STRING_LENGTH_PLT 256
+
+/**
+ * @brief Initialise platform comms.
+ *
+ * @param comms_type - selects between I2C and SPI
+ * @param comms_speed_khz - unsigned short containing the I2C speed in kHz
+ *
+ * @return status - status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_comms_initialise(uint8_t comms_type,
+ uint16_t comms_speed_khz);
+
+/**
+ * @brief Close platform comms.
+ *
+ * @return status - status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_comms_close(void);
+
+/**
+ * @brief Cycle Power to Device
+ *
+ * @return status - status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_cycle_power(void);
+
+int32_t VL53L0_set_page(VL53L0_DEV dev, uint8_t page_data);
+
+/**
+ * @brief Writes the supplied byte buffer to the device
+ *
+ * Wrapper for SystemVerilog Write Multi task
+ *
+ * @code
+ *
+ * Example:
+ *
+ * uint8_t *spad_enables;
+ *
+ * int status = VL53L0_write_multi(RET_SPAD_EN_0, spad_enables, 36);
+ *
+ * @endcode
+ *
+ * @param address - uint8_t device address value
+ * @param index - uint8_t register index value
+ * @param pdata - pointer to uint8_t buffer containing the data to be written
+ * @param count - number of bytes in the supplied byte buffer
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_write_multi(VL53L0_DEV dev, uint8_t index, uint8_t *pdata,
+ int32_t count);
+
+
+/**
+ * @brief Reads the requested number of bytes from the device
+ *
+ * Wrapper for SystemVerilog Read Multi task
+ *
+ * @code
+ *
+ * Example:
+ *
+ * uint8_t buffer[COMMS_BUFFER_SIZE];
+ *
+ * int status = status = VL53L0_read_multi(DEVICE_ID, buffer, 2)
+ *
+ * @endcode
+ *
+ * @param address - uint8_t device address value
+ * @param index - uint8_t register index value
+ * @param pdata - pointer to the uint8_t buffer to store read data
+ * @param count - number of uint8_t's to read
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_read_multi(VL53L0_DEV dev, uint8_t index, uint8_t *pdata,
+ int32_t count);
+
+
+/**
+ * @brief Writes a single byte to the device
+ *
+ * Wrapper for SystemVerilog Write Byte task
+ *
+ * @code
+ *
+ * Example:
+ *
+ * uint8_t page_number = MAIN_SELECT_PAGE;
+ *
+ * int status = VL53L0_write_byte(PAGE_SELECT, page_number);
+ *
+ * @endcode
+ *
+ * @param address - uint8_t device address value
+ * @param index - uint8_t register index value
+ * @param data - uint8_t data value to write
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_write_byte(VL53L0_DEV dev, uint8_t index, uint8_t data);
+
+
+/**
+ * @brief Writes a single word (16-bit unsigned) to the device
+ *
+ * Manages the big-endian nature of the device (first byte written is the
+ * MS byte).
+ * Uses SystemVerilog Write Multi task.
+ *
+ * @code
+ *
+ * Example:
+ *
+ * uint16_t nvm_ctrl_pulse_width = 0x0004;
+ *
+ * int status = VL53L0_write_word(NVM_CTRL__PULSE_WIDTH_MSB,
+ * nvm_ctrl_pulse_width);
+ *
+ * @endcode
+ *
+ * @param address - uint8_t device address value
+ * @param index - uint8_t register index value
+ * @param data - uin16_t data value write
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_write_word(VL53L0_DEV dev, uint8_t index, uint16_t data);
+
+
+/**
+ * @brief Writes a single dword (32-bit unsigned) to the device
+ *
+ * Manages the big-endian nature of the device (first byte written is the
+ * MS byte).
+ * Uses SystemVerilog Write Multi task.
+ *
+ * @code
+ *
+ * Example:
+ *
+ * uint32_t nvm_data = 0x0004;
+ *
+ * int status = VL53L0_write_dword(NVM_CTRL__DATAIN_MMM, nvm_data);
+ *
+ * @endcode
+ *
+ * @param address - uint8_t device address value
+ * @param index - uint8_t register index value
+ * @param data - uint32_t data value to write
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_write_dword(VL53L0_DEV dev, uint8_t index, uint32_t data);
+
+
+
+/**
+ * @brief Reads a single byte from the device
+ *
+ * Uses SystemVerilog Read Byte task.
+ *
+ * @code
+ *
+ * Example:
+ *
+ * uint8_t device_status = 0;
+ *
+ * int status = VL53L0_read_byte(STATUS, &device_status);
+ *
+ * @endcode
+ *
+ * @param address - uint8_t device address value
+ * @param index - uint8_t register index value
+ * @param pdata - pointer to uint8_t data value
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_read_byte(VL53L0_DEV dev, uint8_t index, uint8_t *pdata);
+
+
+/**
+ * @brief Reads a single word (16-bit unsigned) from the device
+ *
+ * Manages the big-endian nature of the device (first byte read is the MS byte).
+ * Uses SystemVerilog Read Multi task.
+ *
+ * @code
+ *
+ * Example:
+ *
+ * uint16_t timeout = 0;
+ *
+ * int status = VL53L0_read_word(TIMEOUT_OVERALL_PERIODS_MSB, &timeout);
+ *
+ * @endcode
+ *
+ * @param address - uint8_t device address value
+ * @param index - uint8_t register index value
+ * @param pdata - pointer to uint16_t data value
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_read_word(VL53L0_DEV dev, uint8_t index, uint16_t *pdata);
+
+
+/**
+ * @brief Reads a single dword (32-bit unsigned) from the device
+ *
+ * Manages the big-endian nature of the device (first byte read is the MS byte).
+ * Uses SystemVerilog Read Multi task.
+ *
+ * @code
+ *
+ * Example:
+ *
+ * uint32_t range_1 = 0;
+ *
+ * int status = VL53L0_read_dword(RANGE_1_MMM, &range_1);
+ *
+ * @endcode
+ *
+ * @param address - uint8_t device address value
+ * @param index - uint8_t register index value
+ * @param pdata - pointer to uint32_t data value
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_read_dword(VL53L0_DEV dev, uint8_t index, uint32_t *pdata);
+
+
+/**
+ * @brief Implements a programmable wait in us
+ *
+ * Wrapper for SystemVerilog Wait in micro seconds task
+ *
+ * @param wait_us - integer wait in micro seconds
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_platform_wait_us(int32_t wait_us);
+
+
+/**
+ * @brief Implements a programmable wait in ms
+ *
+ * Wrapper for SystemVerilog Wait in milli seconds task
+ *
+ * @param wait_ms - integer wait in milli seconds
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_wait_ms(int32_t wait_ms);
+
+
+/**
+ * @brief Set GPIO value
+ *
+ * @param level - input level - either 0 or 1
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_set_gpio(uint8_t level);
+
+
+/**
+ * @brief Get GPIO value
+ *
+ * @param plevel - uint8_t pointer to store GPIO level (0 or 1)
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_get_gpio(uint8_t *plevel);
+
+/**
+ * @brief Release force on GPIO
+ *
+ * @return status - SystemVerilog status 0 = ok, 1 = error
+ *
+ */
+
+int32_t VL53L0_release_gpio(void);
+
+
+/**
+* @brief Get the frequency of the timer used for ranging results time stamps
+*
+* @param[out] ptimer_freq_hz : pointer for timer frequency
+*
+* @return status : 0 = ok, 1 = error
+*
+*/
+
+int32_t VL53L0_get_timer_frequency(int32_t *ptimer_freq_hz);
+
+/**
+* @brief Get the timer value in units of timer_freq_hz
+* (see VL53L0_get_timestamp_frequency())
+*
+* @param[out] ptimer_count : pointer for timer count value
+*
+* @return status : 0 = ok, 1 = error
+*
+*/
+
+int32_t VL53L0_get_timer_value(int32_t *ptimer_count);
+int VL53L0_I2CWrite(VL53L0_DEV dev, uint8_t *buff, uint8_t len);
+int VL53L0_I2CRead(VL53L0_DEV dev, uint8_t *buff, uint8_t len);
+
+#endif /* _VL53L0_I2C_PLATFORM_H_ */
+
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_interrupt_threshold_settings.h b/drivers/input/misc/vl53L0/inc/vl53l0_interrupt_threshold_settings.h
new file mode 100644
index 000000000000..35acd8eb42e3
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_interrupt_threshold_settings.h
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+
+#ifndef _VL53L0_INTERRUPT_THRESHOLD_SETTINGS_H_
+#define _VL53L0_INTERRUPT_THRESHOLD_SETTINGS_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+uint8_t InterruptThresholdSettings[] = {
+
+ /* Start of Interrupt Threshold Settings */
+ 0x1, 0xff, 0x00,
+ 0x1, 0x80, 0x01,
+ 0x1, 0xff, 0x01,
+ 0x1, 0x00, 0x00,
+ 0x1, 0xff, 0x01,
+ 0x1, 0x4f, 0x02,
+ 0x1, 0xFF, 0x0E,
+ 0x1, 0x00, 0x03,
+ 0x1, 0x01, 0x84,
+ 0x1, 0x02, 0x0A,
+ 0x1, 0x03, 0x03,
+ 0x1, 0x04, 0x08,
+ 0x1, 0x05, 0xC8,
+ 0x1, 0x06, 0x03,
+ 0x1, 0x07, 0x8D,
+ 0x1, 0x08, 0x08,
+ 0x1, 0x09, 0xC6,
+ 0x1, 0x0A, 0x01,
+ 0x1, 0x0B, 0x02,
+ 0x1, 0x0C, 0x00,
+ 0x1, 0x0D, 0xD5,
+ 0x1, 0x0E, 0x18,
+ 0x1, 0x0F, 0x12,
+ 0x1, 0x10, 0x01,
+ 0x1, 0x11, 0x82,
+ 0x1, 0x12, 0x00,
+ 0x1, 0x13, 0xD5,
+ 0x1, 0x14, 0x18,
+ 0x1, 0x15, 0x13,
+ 0x1, 0x16, 0x03,
+ 0x1, 0x17, 0x86,
+ 0x1, 0x18, 0x0A,
+ 0x1, 0x19, 0x09,
+ 0x1, 0x1A, 0x08,
+ 0x1, 0x1B, 0xC2,
+ 0x1, 0x1C, 0x03,
+ 0x1, 0x1D, 0x8F,
+ 0x1, 0x1E, 0x0A,
+ 0x1, 0x1F, 0x06,
+ 0x1, 0x20, 0x01,
+ 0x1, 0x21, 0x02,
+ 0x1, 0x22, 0x00,
+ 0x1, 0x23, 0xD5,
+ 0x1, 0x24, 0x18,
+ 0x1, 0x25, 0x22,
+ 0x1, 0x26, 0x01,
+ 0x1, 0x27, 0x82,
+ 0x1, 0x28, 0x00,
+ 0x1, 0x29, 0xD5,
+ 0x1, 0x2A, 0x18,
+ 0x1, 0x2B, 0x0B,
+ 0x1, 0x2C, 0x28,
+ 0x1, 0x2D, 0x78,
+ 0x1, 0x2E, 0x28,
+ 0x1, 0x2F, 0x91,
+ 0x1, 0x30, 0x00,
+ 0x1, 0x31, 0x0B,
+ 0x1, 0x32, 0x00,
+ 0x1, 0x33, 0x0B,
+ 0x1, 0x34, 0x00,
+ 0x1, 0x35, 0xA1,
+ 0x1, 0x36, 0x00,
+ 0x1, 0x37, 0xA0,
+ 0x1, 0x38, 0x00,
+ 0x1, 0x39, 0x04,
+ 0x1, 0x3A, 0x28,
+ 0x1, 0x3B, 0x30,
+ 0x1, 0x3C, 0x0C,
+ 0x1, 0x3D, 0x04,
+ 0x1, 0x3E, 0x0F,
+ 0x1, 0x3F, 0x79,
+ 0x1, 0x40, 0x28,
+ 0x1, 0x41, 0x1E,
+ 0x1, 0x42, 0x2F,
+ 0x1, 0x43, 0x87,
+ 0x1, 0x44, 0x00,
+ 0x1, 0x45, 0x0B,
+ 0x1, 0x46, 0x00,
+ 0x1, 0x47, 0x0B,
+ 0x1, 0x48, 0x00,
+ 0x1, 0x49, 0xA7,
+ 0x1, 0x4A, 0x00,
+ 0x1, 0x4B, 0xA6,
+ 0x1, 0x4C, 0x00,
+ 0x1, 0x4D, 0x04,
+ 0x1, 0x4E, 0x01,
+ 0x1, 0x4F, 0x00,
+ 0x1, 0x50, 0x00,
+ 0x1, 0x51, 0x80,
+ 0x1, 0x52, 0x09,
+ 0x1, 0x53, 0x08,
+ 0x1, 0x54, 0x01,
+ 0x1, 0x55, 0x00,
+ 0x1, 0x56, 0x0F,
+ 0x1, 0x57, 0x79,
+ 0x1, 0x58, 0x09,
+ 0x1, 0x59, 0x05,
+ 0x1, 0x5A, 0x00,
+ 0x1, 0x5B, 0x60,
+ 0x1, 0x5C, 0x05,
+ 0x1, 0x5D, 0xD1,
+ 0x1, 0x5E, 0x0C,
+ 0x1, 0x5F, 0x3C,
+ 0x1, 0x60, 0x00,
+ 0x1, 0x61, 0xD0,
+ 0x1, 0x62, 0x0B,
+ 0x1, 0x63, 0x03,
+ 0x1, 0x64, 0x28,
+ 0x1, 0x65, 0x10,
+ 0x1, 0x66, 0x2A,
+ 0x1, 0x67, 0x39,
+ 0x1, 0x68, 0x0B,
+ 0x1, 0x69, 0x02,
+ 0x1, 0x6A, 0x28,
+ 0x1, 0x6B, 0x10,
+ 0x1, 0x6C, 0x2A,
+ 0x1, 0x6D, 0x61,
+ 0x1, 0x6E, 0x0C,
+ 0x1, 0x6F, 0x00,
+ 0x1, 0x70, 0x0F,
+ 0x1, 0x71, 0x79,
+ 0x1, 0x72, 0x00,
+ 0x1, 0x73, 0x0B,
+ 0x1, 0x74, 0x00,
+ 0x1, 0x75, 0x0B,
+ 0x1, 0x76, 0x00,
+ 0x1, 0x77, 0xA1,
+ 0x1, 0x78, 0x00,
+ 0x1, 0x79, 0xA0,
+ 0x1, 0x7A, 0x00,
+ 0x1, 0x7B, 0x04,
+ 0x1, 0xFF, 0x04,
+ 0x1, 0x79, 0x1D,
+ 0x1, 0x7B, 0x27,
+ 0x1, 0x96, 0x0E,
+ 0x1, 0x97, 0xFE,
+ 0x1, 0x98, 0x03,
+ 0x1, 0x99, 0xEF,
+ 0x1, 0x9A, 0x02,
+ 0x1, 0x9B, 0x44,
+ 0x1, 0x73, 0x07,
+ 0x1, 0x70, 0x01,
+ 0x1, 0xff, 0x01,
+ 0x1, 0x00, 0x01,
+ 0x1, 0xff, 0x00,
+ 0x00, 0x00, 0x00
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L0_INTERRUPT_THRESHOLD_SETTINGS_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_platform.h b/drivers/input/misc/vl53L0/inc/vl53l0_platform.h
new file mode 100644
index 000000000000..f723a552a7f1
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_platform.h
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * Copyright © 2015, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+
+#ifndef _VL53L0_PLATFORM_H_
+#define _VL53L0_PLATFORM_H_
+
+#include <linux/delay.h>
+#include "vl53l0_def.h"
+#include "vl53l0_platform_log.h"
+
+#include "stmvl53l0-i2c.h"
+#include "stmvl53l0-cci.h"
+#include "stmvl53l0.h"
+
+/**
+ * @file vl53l0_platform.h
+ *
+ * @brief All end user OS/platform/application porting
+ */
+
+/**
+ * @defgroup VL53L0_platform_group VL53L0 Platform Functions
+ * @brief VL53L0 Platform Functions
+ * @{
+ */
+
+/**
+ * @struct VL53L0_Dev_t
+ * @brief Generic PAL device type that does link between API and platform
+ * abstraction layer
+ *
+ */
+typedef struct stmvl53l0_data *VL53L0_DEV;
+
+/**
+ * @def PALDevDataGet
+ * @brief Get ST private structure @a VL53L0_DevData_t data access
+ *
+ * @param Dev Device Handle
+ * @param field ST structure field name
+ * It maybe used and as real data "ref" not just as "get" for sub-structure item
+ * like PALDevDataGet(FilterData.field)[i] or
+ * PALDevDataGet(FilterData.MeasurementIndex)++
+ */
+#define PALDevDataGet(Dev, field) (Dev->Data.field)
+
+/**
+ * @def PALDevDataSet(Dev, field, data)
+ * @brief Set ST private structure @a VL53L0_DevData_t data field
+ * @param Dev Device Handle
+ * @param field ST structure field na*me
+ * @param data Data to be set
+ */
+#define PALDevDataSet(Dev, field, data) ((Dev->Data.field) = (data))
+
+
+/**
+ * @defgroup VL53L0_registerAccess_group PAL Register Access Functions
+ * @brief PAL Register Access Functions
+ * @{
+ */
+
+/**
+ * Lock comms interface to serialize all commands to a shared I2C interface
+ * for a specific device
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_LockSequenceAccess(VL53L0_DEV Dev);
+
+/**
+ * Unlock comms interface to serialize all commands to a shared I2C interface
+ * for a specific device
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_UnlockSequenceAccess(VL53L0_DEV Dev);
+
+
+/**
+ * Writes the supplied byte buffer to the device
+ * @param Dev Device Handle
+ * @param index The register index
+ * @param pdata Pointer to uint8_t buffer containing the data to be written
+ * @param count Number of bytes in the supplied byte buffer
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_WriteMulti(VL53L0_DEV Dev, uint8_t index,
+ uint8_t *pdata, uint32_t count);
+
+/**
+ * Reads the requested number of bytes from the device
+ * @param Dev Device Handle
+ * @param index The register index
+ * @param pdata Pointer to the uint8_t buffer to store read data
+ * @param count Number of uint8_t's to read
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_ReadMulti(VL53L0_DEV Dev, uint8_t index,
+ uint8_t *pdata, uint32_t count);
+
+/**
+ * Write single byte register
+ * @param Dev Device Handle
+ * @param index The register index
+ * @param data 8 bit register data
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_WrByte(VL53L0_DEV Dev, uint8_t index, uint8_t data);
+
+/**
+ * Write word register
+ * @param Dev Device Handle
+ * @param index The register index
+ * @param data 16 bit register data
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_WrWord(VL53L0_DEV Dev, uint8_t index, uint16_t data);
+
+/**
+ * Write double word (4 byte) register
+ * @param Dev Device Handle
+ * @param index The register index
+ * @param data 32 bit register data
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_WrDWord(VL53L0_DEV Dev, uint8_t index, uint32_t data);
+
+/**
+ * Read single byte register
+ * @param Dev Device Handle
+ * @param index The register index
+ * @param data pointer to 8 bit data
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_RdByte(VL53L0_DEV Dev, uint8_t index, uint8_t *data);
+
+/**
+ * Read word (2byte) register
+ * @param Dev Device Handle
+ * @param index The register index
+ * @param data pointer to 16 bit data
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_RdWord(VL53L0_DEV Dev, uint8_t index, uint16_t *data);
+
+/**
+ * Read dword (4byte) register
+ * @param Dev Device Handle
+ * @param index The register index
+ * @param data pointer to 32 bit data
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_RdDWord(VL53L0_DEV Dev, uint8_t index, uint32_t *data);
+
+/**
+ * Threat safe Update (read/modify/write) single byte register
+ *
+ * Final_reg = (Initial_reg & and_data) |or_data
+ *
+ * @param Dev Device Handle
+ * @param index The register index
+ * @param AndData 8 bit and data
+ * @param OrData 8 bit or data
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_UpdateByte(VL53L0_DEV Dev, uint8_t index,
+ uint8_t AndData, uint8_t OrData);
+
+/** @} end of VL53L0_registerAccess_group */
+
+
+/**
+ * @brief execute delay in all polling API call
+ *
+ * A typical multi-thread or RTOs implementation is to sleep the task for
+ * some 5ms (with 100Hz max rate faster polling is not needed)
+ * if nothing specific is need you can define it as an empty/void macro
+ * @code
+ * #define VL53L0_PollingDelay(...) (void)0
+ * @endcode
+ * @param Dev Device Handle
+ * @return VL53L0_ERROR_NONE Success
+ * @return "Other error code" See ::VL53L0_Error
+ */
+VL53L0_Error VL53L0_PollingDelay(VL53L0_DEV Dev);
+/* usually best implemented as a real function */
+
+/** @} end of VL53L0_platform_group */
+
+#endif /* _VL53L0_PLATFORM_H_ */
+
+
+
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_platform_log.h b/drivers/input/misc/vl53L0/inc/vl53l0_platform_log.h
new file mode 100644
index 000000000000..8c38615239ad
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_platform_log.h
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright © 2015, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+
+#ifndef _VL53L0_PLATFORM_LOG_H_
+#define _VL53L0_PLATFORM_LOG_H_
+
+#include <linux/string.h>
+/* LOG Functions */
+
+
+/**
+ * @file vl53l0_platform_log.h
+ *
+ * @brief platform log function definition
+ */
+
+/* #define VL53L0_LOG_ENABLE */
+
+enum {
+ TRACE_LEVEL_NONE,
+ TRACE_LEVEL_ERRORS,
+ TRACE_LEVEL_WARNING,
+ TRACE_LEVEL_INFO,
+ TRACE_LEVEL_DEBUG,
+ TRACE_LEVEL_ALL,
+ TRACE_LEVEL_IGNORE
+};
+
+enum {
+ TRACE_FUNCTION_NONE = 0,
+ TRACE_FUNCTION_I2C = 1,
+ TRACE_FUNCTION_ALL = 0x7fffffff /* all bits except sign */
+};
+
+enum {
+ TRACE_MODULE_NONE = 0x0,
+ TRACE_MODULE_API = 0x1,
+ TRACE_MODULE_PLATFORM = 0x2,
+ TRACE_MODULE_ALL = 0x7fffffff /* all bits except sign */
+};
+
+
+#ifdef VL53L0_LOG_ENABLE
+
+#include <linux/module.h>
+
+
+extern uint32_t _trace_level;
+
+
+
+int32_t VL53L0_trace_config(char *filename, uint32_t modules,
+ uint32_t level, uint32_t functions);
+
+#if 0
+void trace_print_module_function(uint32_t module, uint32_t level,
+ uint32_t function, const char *format, ...);
+#else
+#define trace_print_module_function(...)
+#endif
+
+#define LOG_GET_TIME() (int)0
+/*
+ * #define _LOG_FUNCTION_START(module, fmt, ...) \
+ printk(KERN_INFO"beg %s start @%d\t" fmt "\n", \
+ __func__, LOG_GET_TIME(), ##__VA_ARGS__)
+
+ * #define _LOG_FUNCTION_END(module, status, ...)\
+ printk(KERN_INFO"end %s @%d %d\n", \
+ __func__, LOG_GET_TIME(), (int)status)
+
+ * #define _LOG_FUNCTION_END_FMT(module, status, fmt, ...)\
+ printk(KERN_INFO"End %s @%d %d\t"fmt"\n" , \
+ __func__, LOG_GET_TIME(), (int)status, ##__VA_ARGS__)
+*/
+#define _LOG_FUNCTION_START(module, fmt, ...) \
+ pr_err("beg %s start @%d\t" fmt "\n", \
+ __func__, LOG_GET_TIME(), ##__VA_ARGS__)
+
+#define _LOG_FUNCTION_END(module, status, ...)\
+ pr_err("end %s start @%d Status %d\n", \
+ __func__, LOG_GET_TIME(), (int)status)
+
+#define _LOG_FUNCTION_END_FMT(module, status, fmt, ...)\
+ pr_err("End %s @%d %d\t"fmt"\n", \
+ __func__, LOG_GET_TIME(), (int)status, ##__VA_ARGS__)
+
+
+#else /* VL53L0_LOG_ENABLE no logging */
+ #define VL53L0_ErrLog(...) (void)0
+ #define _LOG_FUNCTION_START(module, fmt, ...) (void)0
+ #define _LOG_FUNCTION_END(module, status, ...) (void)0
+ #define _LOG_FUNCTION_END_FMT(module, status, fmt, ...) (void)0
+#endif /* else */
+
+#define VL53L0_COPYSTRING(str, ...) strlcpy(str, ##__VA_ARGS__, sizeof(str))
+
+
+#endif /* _VL53L0_PLATFORM_LOG_H_ */
+
+
+
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_tuning.h b/drivers/input/misc/vl53L0/inc/vl53l0_tuning.h
new file mode 100644
index 000000000000..a9f7ca70b5ac
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_tuning.h
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+
+#ifndef _VL53L0_TUNING_H_
+#define _VL53L0_TUNING_H_
+
+#include "vl53l0_def.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+uint8_t DefaultTuningSettings[] = {
+
+ /* update 02/11/2015_v36 */
+ 0x01, 0xFF, 0x01,
+ 0x01, 0x00, 0x00,
+
+ 0x01, 0xFF, 0x00,
+ 0x01, 0x09, 0x00,
+ 0x01, 0x10, 0x00,
+ 0x01, 0x11, 0x00,
+
+ 0x01, 0x24, 0x01,
+ 0x01, 0x25, 0xff,
+ 0x01, 0x75, 0x00,
+
+ 0x01, 0xFF, 0x01,
+ 0x01, 0x4e, 0x2c,
+ 0x01, 0x48, 0x00,
+ 0x01, 0x30, 0x20,
+
+ 0x01, 0xFF, 0x00,
+ 0x01, 0x30, 0x09, /* mja changed from 0x64. */
+ 0x01, 0x54, 0x00,
+ 0x01, 0x31, 0x04,
+ 0x01, 0x32, 0x03,
+ 0x01, 0x40, 0x83,
+ 0x01, 0x46, 0x25,
+ 0x01, 0x60, 0x00,
+ 0x01, 0x27, 0x00,
+ 0x01, 0x50, 0x06,
+ 0x01, 0x51, 0x00,
+ 0x01, 0x52, 0x96,
+ 0x01, 0x56, 0x08,
+ 0x01, 0x57, 0x30,
+ 0x01, 0x61, 0x00,
+ 0x01, 0x62, 0x00,
+ 0x01, 0x64, 0x00,
+ 0x01, 0x65, 0x00,
+ 0x01, 0x66, 0xa0,
+
+ 0x01, 0xFF, 0x01,
+ 0x01, 0x22, 0x32,
+ 0x01, 0x47, 0x14,
+ 0x01, 0x49, 0xff,
+ 0x01, 0x4a, 0x00,
+
+ 0x01, 0xFF, 0x00,
+ 0x01, 0x7a, 0x0a,
+ 0x01, 0x7b, 0x00,
+ 0x01, 0x78, 0x21,
+
+ 0x01, 0xFF, 0x01,
+ 0x01, 0x23, 0x34,
+ 0x01, 0x42, 0x00,
+ 0x01, 0x44, 0xff,
+ 0x01, 0x45, 0x26,
+ 0x01, 0x46, 0x05,
+ 0x01, 0x40, 0x40,
+ 0x01, 0x0E, 0x06,
+ 0x01, 0x20, 0x1a,
+ 0x01, 0x43, 0x40,
+
+ 0x01, 0xFF, 0x00,
+ 0x01, 0x34, 0x03,
+ 0x01, 0x35, 0x44,
+
+ 0x01, 0xFF, 0x01,
+ 0x01, 0x31, 0x04,
+ 0x01, 0x4b, 0x09,
+ 0x01, 0x4c, 0x05,
+ 0x01, 0x4d, 0x04,
+
+
+ 0x01, 0xFF, 0x00,
+ 0x01, 0x44, 0x00,
+ 0x01, 0x45, 0x20,
+ 0x01, 0x47, 0x08,
+ 0x01, 0x48, 0x28,
+ 0x01, 0x67, 0x00,
+ 0x01, 0x70, 0x04,
+ 0x01, 0x71, 0x01,
+ 0x01, 0x72, 0xfe,
+ 0x01, 0x76, 0x00,
+ 0x01, 0x77, 0x00,
+
+ 0x01, 0xFF, 0x01,
+ 0x01, 0x0d, 0x01,
+
+ 0x01, 0xFF, 0x00,
+ 0x01, 0x80, 0x01,
+ 0x01, 0x01, 0xF8,
+
+ 0x01, 0xFF, 0x01,
+ 0x01, 0x8e, 0x01,
+ 0x01, 0x00, 0x01,
+ 0x01, 0xFF, 0x00,
+ 0x01, 0x80, 0x00,
+
+ 0x00, 0x00, 0x00
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L0_TUNING_H_ */
diff --git a/drivers/input/misc/vl53L0/inc/vl53l0_types.h b/drivers/input/misc/vl53L0/inc/vl53l0_types.h
new file mode 100644
index 000000000000..c509913146ed
--- /dev/null
+++ b/drivers/input/misc/vl53L0/inc/vl53l0_types.h
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef VL53L0_TYPES_H_
+#define VL53L0_TYPES_H_
+
+#include <linux/types.h>
+
+#ifndef NULL
+#error "TODO review NULL definition or add required include "
+#define NULL 0
+#endif
+/** use where fractional values are expected
+ *
+ * Given a floating point value f it's .16 bit point is (int)(f*(1<<16))
+ */
+typedef unsigned int FixPoint1616_t;
+
+#if !defined(STDINT_H) && !defined(_GCC_STDINT_H) \
+ && !defined(_STDINT_H) && !defined(_LINUX_TYPES_H)
+
+#pragma message("Please review type definition of STDINT define for your" \
+"platform and add to list above ")
+
+/*
+* target platform do not provide stdint or use a different #define than above
+* to avoid seeing the message below addapt the #define list above or implement
+* all type and delete these pragma
+*/
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+typedef unsigned short uint16_t;
+typedef short int16_t;
+
+typedef unsigned char uint8_t;
+
+typedef signed char int8_t;
+
+
+#endif /* VL53L0_TYPES_H_ */
+
+#endif /* VL6180x_TYPES_H_ */
diff --git a/drivers/input/misc/vl53L0/src/vl53l010_api.c b/drivers/input/misc/vl53L0/src/vl53l010_api.c
new file mode 100644
index 000000000000..6c706bd0fe3b
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l010_api.c
@@ -0,0 +1,4175 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+ IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#include "vl53l010_api.h"
+#include "vl53l010_device.h"
+#include "vl53l010_tuning.h"
+
+/* use macro for abs */
+#ifndef __KERNEL__
+#include <stdlib.h>
+#endif
+
+
+
+#define LOG_FUNCTION_START(fmt, ...) \
+ _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
+#define LOG_FUNCTION_END(status, ...) \
+ _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
+#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
+ _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
+
+#ifdef VL53L0_LOG_ENABLE
+#define trace_print(level, ...) trace_print_module_function(TRACE_MODULE_API, \
+ level, TRACE_FUNCTION_NONE, ##__VA_ARGS__)
+#endif
+
+/* Defines */
+#define VL53L010_SETPARAMETERFIELD(Dev, field, value) \
+ do { \
+ if (Status == VL53L0_ERROR_NONE) {\
+ CurrentParameters = \
+ PALDevDataGet(Dev, CurrentParameters); \
+ CurrentParameters.field = value; \
+ CurrentParameters = \
+ PALDevDataSet(Dev, CurrentParameters, \
+ CurrentParameters); \
+ } \
+ } while (0)
+#define VL53L010_SETARRAYPARAMETERFIELD(Dev, field, index, value) \
+ do { \
+ if (Status == VL53L0_ERROR_NONE) {\
+ CurrentParameters = \
+ PALDevDataGet(Dev, CurrentParameters); \
+ CurrentParameters.field[index] = value; \
+ CurrentParameters = \
+ PALDevDataSet(Dev, CurrentParameters, \
+ CurrentParameters); \
+ } \
+ } while (0)
+
+#define VL53L010_GETPARAMETERFIELD(Dev, field, variable) \
+ do { \
+ if (Status == VL53L0_ERROR_NONE) { \
+ CurrentParameters = \
+ PALDevDataGet(Dev, CurrentParameters); \
+ variable = CurrentParameters.field; \
+ } \
+ } while (0)
+
+#define VL53L010_GETARRAYPARAMETERFIELD(Dev, field, index, variable) \
+ do { \
+ if (Status == VL53L0_ERROR_NONE) { \
+ CurrentParameters = \
+ PALDevDataGet(Dev, CurrentParameters); \
+ variable = CurrentParameters.field[index]; \
+ } \
+ } while (0)
+
+#define VL53L010_SETDEVICESPECIFICPARAMETER(Dev, field, value) \
+ do { \
+ if (Status == VL53L0_ERROR_NONE) { \
+ DeviceSpecificParameters = \
+ PALDevDataGet(Dev, DeviceSpecificParameters); \
+ DeviceSpecificParameters.field = value; \
+ DeviceSpecificParameters = \
+ PALDevDataSet(Dev, DeviceSpecificParameters, \
+ DeviceSpecificParameters); \
+ } \
+ } while (0)
+
+#define VL53L010_GETDEVICESPECIFICPARAMETER(Dev, field) \
+ PALDevDataGet(Dev, DeviceSpecificParameters).field
+
+#define VL53L010_FIXPOINT1616TOFIXPOINT97(Value) \
+ (uint16_t)((Value >> 9) & 0xFFFF)
+#define VL53L010_FIXPOINT97TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value << 9)
+#define VL53L010_FIXPOINT1616TOFIXPOINT412(Value) \
+ (uint16_t)((Value >> 4) & 0xFFFF)
+#define VL53L010_FIXPOINT412TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value << 4)
+#define VL53L010_FIXPOINT1616TOFIXPOINT08(Value) \
+ (uint8_t)((Value >> 8) & 0x00FF)
+#define VL53L010_FIXPOINT08TOFIXPOINT1616(Value) \
+ (FixPoint1616_t)(Value << 8)
+#define VL53L010_MAKEUINT16(lsb, msb) \
+ (uint16_t)((((uint16_t)msb) << 8) + (uint16_t)lsb)
+
+
+
+/* Group PAL General Functions */
+VL53L0_Error VL53L010_GetVersion(VL53L0_Version_t *pVersion)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ pVersion->major = VL53L010_IMPLEMENTATION_VER_MAJOR;
+ pVersion->minor = VL53L010_IMPLEMENTATION_VER_MINOR;
+ pVersion->build = VL53L010_IMPLEMENTATION_VER_SUB;
+
+ pVersion->revision = VL53L0_IMPLEMENTATION_VER_REVISION;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetPalSpecVersion(VL53L0_Version_t *pPalSpecVersion)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ pPalSpecVersion->major = VL53L010_SPECIFICATION_VER_MAJOR;
+ pPalSpecVersion->minor = VL53L010_SPECIFICATION_VER_MINOR;
+ pPalSpecVersion->build = VL53L010_SPECIFICATION_VER_SUB;
+
+ pPalSpecVersion->revision = VL53L010_SPECIFICATION_VER_REVISION;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetDeviceInfo(VL53L0_DEV Dev,
+ VL53L0_DeviceInfo_t *pVL53L0_DeviceInfo)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t model_id;
+ uint8_t Revision;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L010_check_part_used(Dev, &Revision, pVL53L0_DeviceInfo);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Revision == 0) {
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Name,
+ VL53L010_STRING_DEVICE_INFO_NAME_TS0);
+ } else if ((Revision <= 34) && (Revision != 32)) {
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Name,
+ VL53L010_STRING_DEVICE_INFO_NAME_TS1);
+ } else if (Revision < 39) {
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Name,
+ VL53L010_STRING_DEVICE_INFO_NAME_TS2);
+ } else {
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Name,
+ VL53L010_STRING_DEVICE_INFO_NAME_ES1);
+ }
+
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Type,
+ VL53L010_STRING_DEVICE_INFO_TYPE);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status =
+ VL53L0_RdByte(Dev, VL53L010_REG_IDENTIFICATION_MODEL_ID,
+ &pVL53L0_DeviceInfo->ProductType);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status =
+ VL53L0_RdByte(Dev, VL53L010_REG_IDENTIFICATION_REVISION_ID,
+ &model_id);
+ pVL53L0_DeviceInfo->ProductRevisionMajor = 1;
+ pVL53L0_DeviceInfo->ProductRevisionMinor =
+ (model_id & 0xF0) >> 4;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetDeviceErrorStatus(VL53L0_DEV Dev,
+ VL53L010_DeviceError *
+ pDeviceErrorStatus)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t RangeStatus;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L010_REG_RESULT_RANGE_STATUS,
+ &RangeStatus);
+
+ *pDeviceErrorStatus = (VL53L0_DeviceError) ((RangeStatus & 0x78) >> 3);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+#define VL53L010_BUILDSTATUSERRORSTRING(BUFFER, ERRORCODE, STRINGVALUE) do {\
+ case ERRORCODE: \
+ VL53L0_COPYSTRING(BUFFER, STRINGVALUE);\
+ break;\
+ } while (0)
+
+VL53L0_Error VL53L010_GetDeviceErrorString(VL53L0_DeviceError ErrorCode,
+ char *pDeviceErrorString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ switch (ErrorCode) {
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_NONE,
+ VL53L010_STRING_DEVICEERROR_NONE);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_VCSELCONTINUITYTESTFAILURE,
+ VL53L010_STRING_DEVICEERROR_VCSELCONTINUITYTESTFAILURE);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_VCSELWATCHDOGTESTFAILURE,
+ VL53L010_STRING_DEVICEERROR_VCSELWATCHDOGTESTFAILURE);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_NOVHVVALUEFOUND,
+ VL53L010_STRING_DEVICEERROR_NOVHVVALUEFOUND);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_MSRCNOTARGET,
+ VL53L010_STRING_DEVICEERROR_MSRCNOTARGET);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_MSRCMINIMUMSNR,
+ VL53L010_STRING_DEVICEERROR_MSRCMINIMUMSNR);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_MSRCWRAPAROUND,
+ VL53L010_STRING_DEVICEERROR_MSRCWRAPAROUND);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_TCC,
+ VL53L010_STRING_DEVICEERROR_TCC);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_RANGEAWRAPAROUND,
+ VL53L010_STRING_DEVICEERROR_RANGEAWRAPAROUND);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_RANGEBWRAPAROUND,
+ VL53L010_STRING_DEVICEERROR_RANGEBWRAPAROUND);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_MINCLIP,
+ VL53L010_STRING_DEVICEERROR_MINCLIP);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_RANGECOMPLETE,
+ VL53L010_STRING_DEVICEERROR_RANGECOMPLETE);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_ALGOUNDERFLOW,
+ VL53L010_STRING_DEVICEERROR_ALGOUNDERFLOW);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_ALGOOVERFLOW,
+ VL53L010_STRING_DEVICEERROR_ALGOOVERFLOW);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_FINALSNRLIMIT,
+ VL53L010_STRING_DEVICEERROR_FINALSNRLIMIT);
+ VL53L010_BUILDSTATUSERRORSTRING(pDeviceErrorString,
+ VL53L010_DEVICEERROR_NOTARGETIGNORE,
+ VL53L010_STRING_DEVICEERROR_NOTARGETIGNORE);
+ default:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L010_STRING_UNKNOW_ERROR_CODE);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetPalErrorString(VL53L0_Error PalErrorCode,
+ char *pPalErrorString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ switch (PalErrorCode) {
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_NONE,
+ VL53L010_STRING_ERROR_NONE);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_CALIBRATION_WARNING,
+ VL53L010_STRING_ERROR_CALIBRATION_WARNING);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_MIN_CLIPPED,
+ VL53L010_STRING_ERROR_MIN_CLIPPED);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_UNDEFINED,
+ VL53L010_STRING_ERROR_UNDEFINED);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_INVALID_PARAMS,
+ VL53L010_STRING_ERROR_INVALID_PARAMS);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_NOT_SUPPORTED,
+ VL53L010_STRING_ERROR_NOT_SUPPORTED);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_RANGE_ERROR,
+ VL53L010_STRING_ERROR_RANGE_ERROR);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_TIME_OUT,
+ VL53L010_STRING_ERROR_TIME_OUT);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_MODE_NOT_SUPPORTED,
+ VL53L010_STRING_ERROR_MODE_NOT_SUPPORTED);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_NOT_IMPLEMENTED,
+ VL53L010_STRING_ERROR_NOT_IMPLEMENTED);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_BUFFER_TOO_SMALL,
+ VL53L010_STRING_ERROR_BUFFER_TOO_SMALL);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_GPIO_NOT_EXISTING,
+ VL53L010_STRING_ERROR_GPIO_NOT_EXISTING);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED,
+ VL53L010_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED);
+ VL53L010_BUILDSTATUSERRORSTRING(pPalErrorString,
+ VL53L0_ERROR_CONTROL_INTERFACE,
+ VL53L010_STRING_ERROR_CONTROL_INTERFACE);
+ default:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L010_STRING_UNKNOW_ERROR_CODE);
+ break;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetPalState(VL53L0_DEV Dev, VL53L0_State *pPalState)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pPalState = PALDevDataGet(Dev, PalState);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetPowerMode(VL53L0_DEV Dev, VL53L0_PowerModes PowerMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ /* Only level1 of Power mode exists */
+ if ((PowerMode != VL53L0_POWERMODE_STANDBY_LEVEL1) &&
+ (PowerMode != VL53L0_POWERMODE_IDLE_LEVEL1)) {
+ Status = VL53L0_ERROR_MODE_NOT_SUPPORTED;
+ } else if (PowerMode == VL53L0_POWERMODE_STANDBY_LEVEL1) {
+ /* set the standby level1 of power mode */
+ Status = VL53L0_WrByte(Dev, 0x80, 0x00);
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Set PAL State to standby */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_STANDBY);
+ PALDevDataSet(Dev, PowerMode,
+ VL53L0_POWERMODE_STANDBY_LEVEL1);
+ }
+
+ } else {
+ /* VL53L0_POWERMODE_IDLE_LEVEL1 */
+ Status = VL53L0_WrByte(Dev, 0x80, 0x01);
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_StaticInit(Dev);
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, PowerMode,
+ VL53L0_POWERMODE_IDLE_LEVEL1);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetPowerMode(VL53L0_DEV Dev,
+ VL53L0_PowerModes *pPowerMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ /* Only level1 of Power mode exists */
+ Status = VL53L0_RdByte(Dev, 0x80, &Byte);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Byte == 1)
+ PALDevDataSet(Dev, PowerMode,
+ VL53L0_POWERMODE_IDLE_LEVEL1);
+ else
+ PALDevDataSet(Dev, PowerMode,
+ VL53L0_POWERMODE_STANDBY_LEVEL1);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetOffsetCalibrationDataMicroMeter(VL53L0_DEV Dev,
+ int32_t
+ OffsetCalibrationDataMicroMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t OffsetCalibrationData;
+
+ LOG_FUNCTION_START("");
+
+ OffsetCalibrationData = (uint8_t) (OffsetCalibrationDataMicroMeter
+ / 1000);
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_ALGO_PART_TO_PART_RANGE_OFFSET,
+ *(uint8_t *) &OffsetCalibrationData);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetOffsetCalibrationDataMicroMeter(VL53L0_DEV Dev,
+ int32_t *
+ pOffsetCalibrationDataMicroMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t RangeOffsetRegister;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L010_REG_ALGO_PART_TO_PART_RANGE_OFFSET,
+ &RangeOffsetRegister);
+ if (Status == VL53L0_ERROR_NONE) {
+ *pOffsetCalibrationDataMicroMeter =
+ (*((int8_t *) (&RangeOffsetRegister))) * 1000;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetGroupParamHold(VL53L0_DEV Dev, uint8_t GroupParamHold)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented on VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetUpperLimitMilliMeter(VL53L0_DEV Dev,
+ uint16_t *pUpperLimitMilliMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented on VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* End Group PAL General Functions */
+
+/* Group PAL Init Functions */
+VL53L0_Error VL53L010_SetDeviceAddress(VL53L0_DEV Dev, uint8_t DeviceAddress)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_I2C_SLAVE_DEVICE_ADDRESS,
+ DeviceAddress / 2);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_DataInit(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ VL53L0_DeviceSpecificParameters_t DeviceSpecificParameters;
+ int32_t OffsetCalibrationData;
+
+ LOG_FUNCTION_START("");
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* read device info */
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev, ReadDataFromDeviceDone,
+ 0);
+
+ Status = VL53L010_get_info_from_device(Dev);
+ }
+
+ /* Set Default static parameters */
+ /* set first temporary values 11.3999MHz * 65536 = 748421 */
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev, OscFrequencyMHz, 748421);
+ /* 11.3999MHz * 65536 = 748421 */
+
+ /* Get default parameters */
+ Status = VL53L010_GetDeviceParameters(Dev, &CurrentParameters);
+ if (Status == VL53L0_ERROR_NONE) {
+ /* initialize PAL values */
+ CurrentParameters.DeviceMode = VL53L0_DEVICEMODE_SINGLE_RANGING;
+ CurrentParameters.HistogramMode = VL53L0_HISTOGRAMMODE_DISABLED;
+ PALDevDataSet(Dev, CurrentParameters, CurrentParameters);
+ }
+
+ /* Sigma estimator variable */
+ PALDevDataSet(Dev, SigmaEstRefArray, 100);
+ PALDevDataSet(Dev, SigmaEstEffPulseWidth, 900);
+ PALDevDataSet(Dev, SigmaEstEffAmbWidth, 500);
+
+ /* Set Signal and Sigma check */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetLimitCheckEnable(Dev,
+ VL53L010_CHECKENABLE_SIGMA_FINAL_RANGE,
+ 0);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetLimitCheckEnable(Dev,
+ VL53L010_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ 0);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetLimitCheckValue(Dev,
+ VL53L010_CHECKENABLE_SIGMA_FINAL_RANGE,
+ (FixPoint1616_t) (32 <<
+ 16));
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetLimitCheckValue(Dev,
+ VL53L010_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ (FixPoint1616_t) (25 * 65536 / 100));
+ /* 0.25 * 65538 */
+ }
+
+ /* Read back NVM offset */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetOffsetCalibrationDataMicroMeter(Dev,
+ &OffsetCalibrationData);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ PALDevDataSet(Dev, Part2PartOffsetNVMMicroMeter,
+ OffsetCalibrationData);
+
+ PALDevDataSet(Dev, SequenceConfig, 0xFF);
+
+ /* Set PAL state to tell that we are waiting for call
+ * to VL53L010_StaticInit
+ */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_WAIT_STATICINIT);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_StaticInit(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceSpecificParameters_t DeviceSpecificParameters;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ uint16_t TempWord;
+ uint8_t TempByte;
+ uint8_t localBuffer[32];
+ uint8_t i;
+ uint8_t Revision;
+
+ LOG_FUNCTION_START("");
+
+ /* Set I2C standard mode */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, 0x88, 0x00);
+
+ /* this function do nothing if it has been called before */
+ Status = VL53L010_get_info_from_device(Dev);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Revision = VL53L010_GETDEVICESPECIFICPARAMETER(Dev, Revision);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Revision == 0)
+ Status = VL53L010_load_additional_settings1(Dev);
+ }
+
+ /* update13_05_15 */
+ if (Status == VL53L0_ERROR_NONE) {
+ if ((Revision <= 34) && (Revision != 32)) {
+
+ for (i = 0; i < 32; i++)
+ localBuffer[i] = 0xff;
+
+ Status = VL53L0_WriteMulti(Dev, 0x90, localBuffer, 32);
+
+ Status |= VL53L0_WrByte(Dev, 0xb6, 16);
+ Status |= VL53L0_WrByte(Dev, 0xb0, 0x0);
+ Status |= VL53L0_WrByte(Dev, 0xb1, 0x0);
+ Status |= VL53L0_WrByte(Dev, 0xb2, 0xE0);
+ Status |= VL53L0_WrByte(Dev, 0xb3, 0xE0);
+ Status |= VL53L0_WrByte(Dev, 0xb4, 0xE0);
+ Status |= VL53L0_WrByte(Dev, 0xb5, 0xE0);
+ }
+ }
+
+ /* update 17_06_15_v10 */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_load_tuning_settings(Dev);
+
+ /* check if GO1 power is ON after load default tuning */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdByte(Dev, 0x80, &TempByte);
+ if ((TempByte != 0) && (Status == VL53L0_ERROR_NONE)) {
+ /* update 07_05_15 */
+ Status = VL53L010_load_additional_settings3(Dev);
+ }
+ }
+
+ /* Set interrupt config to new sample ready */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetGpioConfig(Dev, 0, 0,
+ VL53L010_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY,
+ VL53L0_INTERRUPTPOLARITY_LOW);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_RdWord(Dev, 0x84, &TempWord);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev, OscFrequencyMHz,
+ VL53L010_FIXPOINT412TOFIXPOINT1616
+ (TempWord));
+ }
+
+ /* After static init, some device parameters may be changed,
+ * so update them
+ */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_GetDeviceParameters(Dev, &CurrentParameters);
+
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, CurrentParameters, CurrentParameters);
+
+ /* read the sequence config and save it */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdByte(Dev, VL53L010_REG_SYSTEM_SEQUENCE_CONFIG,
+ &TempByte);
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, SequenceConfig, TempByte);
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_PerformRefCalibration(Dev);
+
+ /* Set PAL State to standby */
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_IDLE);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_WaitDeviceBooted(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented on VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_ResetDevice(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ /* Set reset bit */
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SOFT_RESET_GO2_SOFT_RESET_N,
+ 0x00);
+
+ /* Wait for some time */
+ if (Status == VL53L0_ERROR_NONE) {
+ do {
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_IDENTIFICATION_MODEL_ID,
+ &Byte);
+ } while (Byte != 0x00);
+ }
+
+ /* Release reset */
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SOFT_RESET_GO2_SOFT_RESET_N,
+ 0x01);
+
+ /* Wait until correct boot-up of the device */
+ if (Status == VL53L0_ERROR_NONE) {
+ do {
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_IDENTIFICATION_MODEL_ID,
+ &Byte);
+ } while (Byte == 0x00);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* End Group PAL Init Functions */
+
+/* Group PAL Parameters Functions */
+VL53L0_Error VL53L010_SetDeviceParameters(VL53L0_DEV Dev,
+ const VL53L0_DeviceParameters_t *
+ pDeviceParameters)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int i;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L010_SetDeviceMode(Dev, pDeviceParameters->DeviceMode);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetHistogramMode(Dev,
+ pDeviceParameters->
+ HistogramMode);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetInterMeasurementPeriodMilliSeconds(Dev,
+ pDeviceParameters->InterMeasurementPeriodMilliSeconds);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetXTalkCompensationEnable(Dev,
+ pDeviceParameters->
+ XTalkCompensationEnable);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetXTalkCompensationRateMegaCps(Dev,
+ pDeviceParameters->
+ XTalkCompensationRateMegaCps);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetOffsetCalibrationDataMicroMeter(Dev,
+ pDeviceParameters->
+ RangeOffsetMicroMeters);
+ }
+
+ for (i = 0; i < VL53L010_CHECKENABLE_NUMBER_OF_CHECKS; i++) {
+ if (Status == VL53L0_ERROR_NONE) {
+ Status |= VL53L010_SetLimitCheckEnable(Dev, i,
+ pDeviceParameters->
+ LimitChecksEnable
+ [i]);
+ } else {
+ break;
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status |= VL53L010_SetLimitCheckValue(Dev, i,
+ pDeviceParameters->
+ LimitChecksValue
+ [i]);
+ } else {
+ break;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetWrapAroundCheckEnable(Dev,
+ pDeviceParameters->
+ WrapAroundCheckEnable);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetMeasurementTimingBudgetMicroSeconds(Dev,
+ pDeviceParameters->MeasurementTimingBudgetMicroSeconds);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetDeviceParameters(VL53L0_DEV Dev,
+ VL53L0_DeviceParameters_t *
+ pDeviceParameters)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int i;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L010_GetDeviceMode(Dev, &(pDeviceParameters->DeviceMode));
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetHistogramMode(Dev,
+ &(pDeviceParameters->
+ HistogramMode));
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetInterMeasurementPeriodMilliSeconds(Dev,
+ &(pDeviceParameters->InterMeasurementPeriodMilliSeconds));
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetXTalkCompensationEnable(Dev,
+ &
+ (pDeviceParameters->
+ XTalkCompensationEnable));
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetXTalkCompensationRateMegaCps(Dev,
+ &(pDeviceParameters->XTalkCompensationRateMegaCps));
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetOffsetCalibrationDataMicroMeter(Dev,
+ &
+ (pDeviceParameters->
+ RangeOffsetMicroMeters));
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ for (i = 0; i < VL53L010_CHECKENABLE_NUMBER_OF_CHECKS; i++) {
+ /* get first the values, then the enables.
+ *VL53L0_GetLimitCheckValue will modify the enable flags
+ */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status |= VL53L010_GetLimitCheckValue(Dev, i,
+ &
+ (pDeviceParameters->
+ LimitChecksValue
+ [i]));
+ } else {
+ break;
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status |= VL53L010_GetLimitCheckEnable(Dev, i,
+ &
+ (pDeviceParameters->
+ LimitChecksEnable
+ [i]));
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetWrapAroundCheckEnable(Dev,
+ &(pDeviceParameters->
+ WrapAroundCheckEnable));
+ }
+
+ /* Need to be done at the end as it uses VCSELPulsePeriod */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetMeasurementTimingBudgetMicroSeconds(Dev,
+ &(pDeviceParameters->MeasurementTimingBudgetMicroSeconds));
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetDeviceMode(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("%d", (int)DeviceMode);
+
+ switch (DeviceMode) {
+ case VL53L0_DEVICEMODE_SINGLE_RANGING:
+ case VL53L0_DEVICEMODE_CONTINUOUS_RANGING:
+ case VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING:
+ case VL53L0_DEVICEMODE_SINGLE_HISTOGRAM:
+ case VL53L0_DEVICEMODE_GPIO_DRIVE:
+ case VL53L0_DEVICEMODE_GPIO_OSC:
+ /* Supported mode */
+ VL53L010_SETPARAMETERFIELD(Dev, DeviceMode, DeviceMode);
+ break;
+ default:
+ /* Unsupported mode */
+ Status = VL53L0_ERROR_MODE_NOT_SUPPORTED;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetDeviceMode(VL53L0_DEV Dev,
+ VL53L0_DeviceModes *pDeviceMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("");
+
+ VL53L010_GETPARAMETERFIELD(Dev, DeviceMode, *pDeviceMode);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetHistogramMode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes HistogramMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("%d", (int)HistogramMode);
+
+ switch (HistogramMode) {
+ case VL53L0_HISTOGRAMMODE_DISABLED:
+ /* Supported mode */
+ VL53L010_SETPARAMETERFIELD(Dev, HistogramMode, HistogramMode);
+ break;
+ case VL53L0_HISTOGRAMMODE_REFERENCE_ONLY:
+ case VL53L0_HISTOGRAMMODE_RETURN_ONLY:
+ case VL53L0_HISTOGRAMMODE_BOTH:
+ default:
+ /* Unsupported mode */
+ Status = VL53L0_ERROR_MODE_NOT_SUPPORTED;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetHistogramMode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes *pHistogramMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("");
+
+ VL53L010_GETPARAMETERFIELD(Dev, HistogramMode, *pHistogramMode);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetMeasurementTimingBudgetMicroSeconds(VL53L0_DEV Dev,
+ uint32_t MeasurementTimingBudgetMicroSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ VL53L0_DeviceSpecificParameters_t DeviceSpecificParameters;
+ uint8_t CurrentVCSELPulsePeriod;
+ uint8_t CurrentVCSELPulsePeriodPClk;
+ uint8_t Byte;
+ uint32_t NewTimingBudgetMicroSeconds;
+ uint16_t encodedTimeOut;
+
+ LOG_FUNCTION_START("");
+
+ /* check if rangeB is done: */
+ Status = VL53L010_GetWrapAroundCheckEnable(Dev, &Byte);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (((Byte == 1) && (MeasurementTimingBudgetMicroSeconds <
+ 17000)) ||
+ ((Byte == 0) && (MeasurementTimingBudgetMicroSeconds <
+ 12000))) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ NewTimingBudgetMicroSeconds =
+ MeasurementTimingBudgetMicroSeconds - 7000;
+ if (Byte == 1) {
+ NewTimingBudgetMicroSeconds =
+ (uint32_t) (NewTimingBudgetMicroSeconds >> 1);
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_get_vcsel_pulse_period(Dev,
+ &CurrentVCSELPulsePeriodPClk,
+ 0);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ CurrentVCSELPulsePeriod =
+ VL53L010_encode_vcsel_period(CurrentVCSELPulsePeriodPClk);
+ encodedTimeOut =
+ VL53L010_calc_encoded_timeout(Dev,
+ NewTimingBudgetMicroSeconds,
+ (uint8_t)
+ CurrentVCSELPulsePeriod);
+ VL53L010_SETPARAMETERFIELD(Dev,
+ MeasurementTimingBudgetMicroSeconds,
+ MeasurementTimingBudgetMicroSeconds);
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev, LastEncodedTimeout,
+ encodedTimeOut);
+ }
+
+ /* Program in register */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrWord(Dev, VL53L010_REG_RNGA_TIMEOUT_MSB,
+ encodedTimeOut);
+ }
+
+ /* Temp: program same value for rangeB1 and rangeB2 */
+ /* Range B1 */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_get_vcsel_pulse_period(Dev,
+ &CurrentVCSELPulsePeriodPClk,
+ 1);
+ if (Status == VL53L0_ERROR_NONE) {
+ CurrentVCSELPulsePeriod =
+ VL53L010_encode_vcsel_period
+ (CurrentVCSELPulsePeriodPClk);
+ encodedTimeOut =
+ VL53L010_calc_encoded_timeout(Dev,
+ NewTimingBudgetMicroSeconds,
+ (uint8_t)
+ CurrentVCSELPulsePeriod);
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrWord(Dev, VL53L010_REG_RNGB1_TIMEOUT_MSB,
+ encodedTimeOut);
+ }
+
+ /* Range B2 */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_get_vcsel_pulse_period(Dev,
+ &CurrentVCSELPulsePeriodPClk,
+ 2);
+ if (Status == VL53L0_ERROR_NONE) {
+ CurrentVCSELPulsePeriod =
+ VL53L010_encode_vcsel_period
+ (CurrentVCSELPulsePeriodPClk);
+ encodedTimeOut =
+ VL53L010_calc_encoded_timeout(Dev,
+ NewTimingBudgetMicroSeconds,
+ (uint8_t)
+ CurrentVCSELPulsePeriod);
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrWord(Dev, VL53L010_REG_RNGB2_TIMEOUT_MSB,
+ encodedTimeOut);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetMeasurementTimingBudgetMicroSeconds(VL53L0_DEV Dev,
+ uint32_t *pMeasurementTimingBudgetMicroSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ uint8_t CurrentVCSELPulsePeriod;
+ uint8_t CurrentVCSELPulsePeriodPClk;
+ uint16_t encodedTimeOut;
+ uint32_t RangATimingBudgetMicroSeconds = 0;
+ uint32_t RangBTimingBudgetMicroSeconds = 0;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ /* check if rangeB is done: */
+ Status = VL53L010_GetWrapAroundCheckEnable(Dev, &Byte);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L010_get_vcsel_pulse_period(Dev,
+ &CurrentVCSELPulsePeriodPClk,
+ 0);
+ CurrentVCSELPulsePeriod =
+ VL53L010_encode_vcsel_period(CurrentVCSELPulsePeriodPClk);
+
+ /* Read from register */
+ Status = VL53L0_RdWord(Dev, VL53L010_REG_RNGA_TIMEOUT_MSB,
+ &encodedTimeOut);
+ if (Status == VL53L0_ERROR_NONE) {
+ RangATimingBudgetMicroSeconds =
+ VL53L010_calc_ranging_wait_us(Dev,
+ encodedTimeOut,
+ CurrentVCSELPulsePeriod);
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Byte == 0) {
+ *pMeasurementTimingBudgetMicroSeconds =
+ RangATimingBudgetMicroSeconds + 7000;
+ VL53L010_SETPARAMETERFIELD(Dev,
+ MeasurementTimingBudgetMicroSeconds,
+ *pMeasurementTimingBudgetMicroSeconds);
+ } else {
+ VL53L010_get_vcsel_pulse_period(Dev,
+ &CurrentVCSELPulsePeriodPClk,
+ 1);
+ CurrentVCSELPulsePeriod =
+ VL53L010_encode_vcsel_period
+ (CurrentVCSELPulsePeriodPClk);
+
+ /* Read from register */
+ Status = VL53L0_RdWord(Dev,
+ VL53L010_REG_RNGB1_TIMEOUT_MSB,
+ &encodedTimeOut);
+ if (Status == VL53L0_ERROR_NONE) {
+ RangBTimingBudgetMicroSeconds =
+ VL53L010_calc_ranging_wait_us(Dev,
+ encodedTimeOut,
+ CurrentVCSELPulsePeriod);
+ }
+
+ *pMeasurementTimingBudgetMicroSeconds =
+ RangATimingBudgetMicroSeconds +
+ RangBTimingBudgetMicroSeconds + 7000;
+ VL53L010_SETPARAMETERFIELD(Dev,
+ MeasurementTimingBudgetMicroSeconds,
+ *pMeasurementTimingBudgetMicroSeconds);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetInterMeasurementPeriodMilliSeconds(VL53L0_DEV Dev,
+ uint32_t
+ InterMeasurementPeriodMilliSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ uint16_t osc_calibrate_val;
+ uint32_t IMPeriodMilliSeconds;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdWord(Dev, VL53L010_REG_OSC_CALIBRATE_VAL,
+ &osc_calibrate_val);
+
+ if (Status == VL53L0_ERROR_NONE) {
+
+ if (osc_calibrate_val != 0) {
+
+ IMPeriodMilliSeconds =
+ InterMeasurementPeriodMilliSeconds *
+ osc_calibrate_val;
+ } else {
+ IMPeriodMilliSeconds =
+ InterMeasurementPeriodMilliSeconds;
+ }
+ Status = VL53L0_WrDWord(Dev,
+ VL53L010_REG_SYSTEM_INTERMEASUREMENT_PERIOD,
+ IMPeriodMilliSeconds);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L010_SETPARAMETERFIELD(Dev,
+ InterMeasurementPeriodMilliSeconds,
+ InterMeasurementPeriodMilliSeconds);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetInterMeasurementPeriodMilliSeconds(VL53L0_DEV Dev,
+ uint32_t *
+ pInterMeasurementPeriodMilliSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ uint16_t osc_calibrate_val;
+ uint32_t IMPeriodMilliSeconds;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdWord(Dev, VL53L010_REG_OSC_CALIBRATE_VAL,
+ &osc_calibrate_val);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdDWord(Dev,
+ VL53L010_REG_SYSTEM_INTERMEASUREMENT_PERIOD,
+ &IMPeriodMilliSeconds);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (osc_calibrate_val != 0)
+ *pInterMeasurementPeriodMilliSeconds =
+ IMPeriodMilliSeconds / osc_calibrate_val;
+
+ VL53L010_SETPARAMETERFIELD(Dev,
+ InterMeasurementPeriodMilliSeconds,
+ *pInterMeasurementPeriodMilliSeconds);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetXTalkCompensationEnable(VL53L0_DEV Dev,
+ uint8_t
+ XTalkCompensationEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ uint8_t XTalkCompensationEnableValue;
+
+ LOG_FUNCTION_START("");
+
+ if (XTalkCompensationEnable == 0) {
+ /* Disable the crosstalk compensation */
+ XTalkCompensationEnableValue = 0x00;
+ } else {
+ /* Enable the crosstalk compensation */
+ XTalkCompensationEnableValue = 0x01;
+ }
+ Status = VL53L0_UpdateByte(Dev, VL53L010_REG_ALGO_RANGE_CHECK_ENABLES,
+ 0xFE, XTalkCompensationEnableValue);
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L010_SETPARAMETERFIELD(Dev, XTalkCompensationEnable,
+ XTalkCompensationEnableValue);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetXTalkCompensationEnable(VL53L0_DEV Dev, uint8_t *
+ pXTalkCompensationEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ uint8_t data;
+ uint8_t Temp;
+
+ LOG_FUNCTION_START("");
+
+ Status =
+ VL53L0_RdByte(Dev, VL53L010_REG_ALGO_RANGE_CHECK_ENABLES, &data);
+ if (Status == VL53L0_ERROR_NONE) {
+ if (data & 0x01)
+ Temp = 0x01;
+ else
+ Temp = 0x00;
+
+ *pXTalkCompensationEnable = Temp;
+ }
+ if (Status == VL53L0_ERROR_NONE)
+ VL53L010_SETPARAMETERFIELD(Dev, XTalkCompensationEnable, Temp);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetXTalkCompensationRateMegaCps(VL53L0_DEV Dev,
+ FixPoint1616_t
+ XTalkCompensationRateMegaCps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("");
+
+ Status =
+ VL53L0_WrWord(Dev, VL53L010_REG_ALGO_CROSSTALK_COMPENSATION_RATE,
+ VL53L010_FIXPOINT1616TOFIXPOINT412
+ (XTalkCompensationRateMegaCps));
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L010_SETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps,
+ XTalkCompensationRateMegaCps);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetXTalkCompensationRateMegaCps(VL53L0_DEV Dev,
+ FixPoint1616_t *
+ pXTalkCompensationRateMegaCps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t Value;
+ FixPoint1616_t TempFix1616;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("");
+
+ Status =
+ VL53L0_RdWord(Dev, VL53L010_REG_ALGO_CROSSTALK_COMPENSATION_RATE,
+ (uint16_t *) &Value);
+ if (Status == VL53L0_ERROR_NONE) {
+ TempFix1616 = VL53L010_FIXPOINT412TOFIXPOINT1616(Value);
+ *pXTalkCompensationRateMegaCps = TempFix1616;
+ VL53L010_SETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps,
+ TempFix1616);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/*
+ * CHECK LIMIT FUNCTIONS
+ */
+
+VL53L0_Error VL53L010_GetNumberOfLimitCheck(uint16_t *pNumberOfLimitCheck)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pNumberOfLimitCheck = VL53L010_CHECKENABLE_NUMBER_OF_CHECKS;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+#define VL53L010_BUILDCASESTRING(BUFFER, CODE, STRINGVALUE) \
+ do { \
+ case CODE: \
+ VL53L0_COPYSTRING(BUFFER, STRINGVALUE); \
+ break; \
+ } while (0)
+
+VL53L0_Error VL53L010_GetLimitCheckInfo(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ char *pLimitCheckString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ switch (LimitCheckId) {
+ VL53L010_BUILDCASESTRING(pLimitCheckString,
+ VL53L010_CHECKENABLE_SIGMA_FINAL_RANGE,
+ VL53L010_STRING_CHECKENABLE_SIGMA);
+ VL53L010_BUILDCASESTRING(pLimitCheckString,
+ VL53L010_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ VL53L010_STRING_CHECKENABLE_SIGNAL_RATE);
+
+ default:
+ VL53L0_COPYSTRING(pLimitCheckString,
+ VL53L010_STRING_UNKNOW_ERROR_CODE);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetLimitCheckEnable(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ uint8_t LimitCheckEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("");
+
+ if (LimitCheckId >= VL53L010_CHECKENABLE_NUMBER_OF_CHECKS) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else {
+ if (LimitCheckEnable == 0) {
+ VL53L010_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
+ LimitCheckId, 0);
+ } else {
+ VL53L010_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
+ LimitCheckId, 1);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetLimitCheckEnable(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ uint8_t *pLimitCheckEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ uint8_t Temp8;
+
+ LOG_FUNCTION_START("");
+
+ if (LimitCheckId >= VL53L010_CHECKENABLE_NUMBER_OF_CHECKS) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else {
+ VL53L010_GETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
+ LimitCheckId, Temp8);
+ *pLimitCheckEnable = Temp8;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetLimitCheckValue(VL53L0_DEV Dev,
+ uint16_t LimitCheckId,
+ FixPoint1616_t LimitCheckValue)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("");
+
+ if (LimitCheckId >= VL53L010_CHECKENABLE_NUMBER_OF_CHECKS) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else {
+ VL53L010_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ LimitCheckId, LimitCheckValue);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetLimitCheckValue(VL53L0_DEV Dev,
+ uint16_t LimitCheckId,
+ FixPoint1616_t *pLimitCheckValue)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("");
+
+ if (LimitCheckId >= VL53L010_CHECKENABLE_NUMBER_OF_CHECKS) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else {
+ VL53L010_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ LimitCheckId,
+ *pLimitCheckValue);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
+
+VL53L0_Error VL53L010_GetLimitCheckCurrent(VL53L0_DEV Dev,
+ uint16_t LimitCheckId,
+ FixPoint1616_t *pLimitCheckCurrent)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ if (LimitCheckId >= VL53L010_CHECKENABLE_NUMBER_OF_CHECKS) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else {
+ switch (LimitCheckId) {
+ case VL53L010_CHECKENABLE_SIGMA_FINAL_RANGE:
+ /* Need to run a ranging to have the latest values */
+ *pLimitCheckCurrent = PALDevDataGet(Dev, SigmaEstimate);
+
+ break;
+
+ case VL53L010_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE:
+ /* Need to run a ranging to have the latest values */
+ *pLimitCheckCurrent =
+ PALDevDataGet(Dev, SignalEstimate);
+
+ break;
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
+
+/*
+ * WRAPAROUND LIMIT
+ */
+VL53L0_Error VL53L010_SetWrapAroundCheckEnable(VL53L0_DEV Dev, uint8_t
+ WrapAroundCheckEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+ uint8_t WrapAroundCheckEnableInt;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L010_REG_SYSTEM_SEQUENCE_CONFIG, &Byte);
+ if (WrapAroundCheckEnable == 0) {
+ /* Disable wraparound */
+ Byte = Byte & 0x7F;
+ WrapAroundCheckEnableInt = 0;
+ } else {
+ /* Enable wraparound */
+ Byte = Byte | 0x80;
+ WrapAroundCheckEnableInt = 1;
+ }
+
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSTEM_SEQUENCE_CONFIG, Byte);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ PALDevDataSet(Dev, SequenceConfig, Byte);
+ VL53L010_SETPARAMETERFIELD(Dev, WrapAroundCheckEnable,
+ WrapAroundCheckEnableInt);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetWrapAroundCheckEnable(VL53L0_DEV Dev,
+ uint8_t *pWrapAroundCheckEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t data;
+ VL53L0_DeviceParameters_t CurrentParameters;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L010_REG_SYSTEM_SEQUENCE_CONFIG, &data);
+ if (Status == VL53L0_ERROR_NONE) {
+ PALDevDataSet(Dev, SequenceConfig, data);
+ if (data & (0x01 << 7))
+ *pWrapAroundCheckEnable = 0x01;
+ else
+ *pWrapAroundCheckEnable = 0x00;
+
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L010_SETPARAMETERFIELD(Dev, WrapAroundCheckEnable,
+ *pWrapAroundCheckEnable);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* End Group PAL Parameters Functions */
+
+/* Group PAL Measurement Functions */
+VL53L0_Error VL53L010_PerformSingleMeasurement(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceModes DeviceMode;
+ uint8_t NewDatReady = 0;
+ uint32_t LoopNb;
+
+ LOG_FUNCTION_START("");
+
+ /* Get Current DeviceMode */
+ Status = VL53L010_GetDeviceMode(Dev, &DeviceMode);
+
+ /* Start immediately to run a single ranging measurement in case of
+ * single ranging or single histogram
+ */
+ if ((Status == VL53L0_ERROR_NONE) &&
+ ((DeviceMode == VL53L0_DEVICEMODE_SINGLE_RANGING) ||
+ (DeviceMode == VL53L0_DEVICEMODE_SINGLE_HISTOGRAM))) {
+ Status = VL53L010_StartMeasurement(Dev);
+ }
+
+ /* Wait until it finished
+ * use timeout to avoid deadlock
+ */
+ if (Status == VL53L0_ERROR_NONE) {
+ LoopNb = 0;
+ do {
+ Status = VL53L010_GetMeasurementDataReady(Dev,
+ &NewDatReady);
+ if ((NewDatReady == 0x01) || Status !=
+ VL53L0_ERROR_NONE) {
+ break;
+ }
+ LoopNb = LoopNb + 1;
+ VL53L0_PollingDelay(Dev);
+ } while (LoopNb < VL53L0_DEFAULT_MAX_LOOP);
+
+ if (LoopNb >= VL53L0_DEFAULT_MAX_LOOP)
+ Status = VL53L0_ERROR_TIME_OUT;
+
+ }
+
+ /* Change PAL State in case of single ranging or single histogram
+ */
+ if ((Status == VL53L0_ERROR_NONE) &&
+ ((DeviceMode == VL53L0_DEVICEMODE_SINGLE_RANGING) ||
+ (DeviceMode == VL53L0_DEVICEMODE_SINGLE_HISTOGRAM))) {
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_IDLE);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_PerformRefCalibration(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t NewDatReady = 0;
+ uint8_t Byte = 0;
+ uint8_t SequenceConfig = 0;
+ uint32_t LoopNb;
+
+ LOG_FUNCTION_START("");
+
+ /* store the value of the sequence config,
+ * this will be reset before the end of the function
+ */
+
+ SequenceConfig = PALDevDataGet(Dev, SequenceConfig);
+
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSTEM_SEQUENCE_CONFIG, 0x03);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ PALDevDataSet(Dev, SequenceConfig, 0x03);
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSRANGE_START,
+ VL53L010_REG_SYSRANGE_MODE_START_STOP);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Wait until start bit has been cleared */
+ LoopNb = 0;
+ do {
+ if (LoopNb > 0)
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_SYSRANGE_START,
+ &Byte);
+ LoopNb = LoopNb + 1;
+ } while (((Byte & VL53L010_REG_SYSRANGE_MODE_START_STOP) ==
+ VL53L010_REG_SYSRANGE_MODE_START_STOP) &&
+ (Status == VL53L0_ERROR_NONE) &&
+ (LoopNb < VL53L0_DEFAULT_MAX_LOOP));
+ }
+
+ /* Wait until it finished
+ * use timeout to avoid deadlock
+ */
+ if (Status == VL53L0_ERROR_NONE) {
+ LoopNb = 0;
+ do {
+ Status = VL53L010_GetMeasurementDataReady(Dev,
+ &NewDatReady);
+ if ((NewDatReady == 0x01) || Status !=
+ VL53L0_ERROR_NONE) {
+ break;
+ }
+ LoopNb = LoopNb + 1;
+ VL53L0_PollingDelay(Dev);
+ } while (LoopNb < VL53L0_DEFAULT_MAX_LOOP);
+
+ if (LoopNb >= VL53L0_DEFAULT_MAX_LOOP)
+ Status = VL53L0_ERROR_TIME_OUT;
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x04);
+ Status |= VL53L0_RdByte(Dev, 0x30, &Byte);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x31, Byte);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_ClearInterruptMask(Dev, 0);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* restore the previous Sequence Config */
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSTEM_SEQUENCE_CONFIG,
+ SequenceConfig);
+ }
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, SequenceConfig, SequenceConfig);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L010_API VL53L0_Error VL53L010_PerformXTalkCalibration(VL53L0_DEV Dev,
+ FixPoint1616_t
+ XTalkCalDistance,
+ FixPoint1616_t *
+ pXTalkCompensationRateMegaCps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t sum_ranging = 0;
+ uint16_t sum_spads = 0;
+ FixPoint1616_t sum_signalRate = 0;
+ FixPoint1616_t total_count = 0;
+ uint8_t xtalk_meas = 0;
+ VL53L0_RangingMeasurementData_t RangingMeasurementData;
+ FixPoint1616_t xTalkStoredMeanSignalRate;
+ FixPoint1616_t xTalkStoredMeanRange;
+ FixPoint1616_t xTalkStoredMeanRtnSpads;
+ uint32_t signalXTalkTotalPerSpad;
+ uint32_t xTalkStoredMeanRtnSpadsAsInt;
+ uint32_t xTalkCalDistanceAsInt;
+ FixPoint1616_t XTalkCompensationRateMegaCps;
+
+ LOG_FUNCTION_START("");
+
+ if (XTalkCalDistance <= 0)
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+ /* Disable the XTalk compensation */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_SetXTalkCompensationEnable(Dev, 0);
+
+ /* Perform 50 measurements and compute the averages */
+ if (Status == VL53L0_ERROR_NONE) {
+ sum_ranging = 0;
+ sum_spads = 0;
+ sum_signalRate = 0;
+ total_count = 0;
+ for (xtalk_meas = 0; xtalk_meas < 50; xtalk_meas++) {
+ Status = VL53L010_PerformSingleRangingMeasurement(Dev,
+ &RangingMeasurementData);
+
+ if (Status != VL53L0_ERROR_NONE)
+ break;
+
+ /* The range is valid when RangeStatus = 0 */
+ if (RangingMeasurementData.RangeStatus == 0) {
+ sum_ranging = sum_ranging +
+ RangingMeasurementData.RangeMilliMeter;
+ sum_signalRate = sum_signalRate +
+ RangingMeasurementData.SignalRateRtnMegaCps;
+ sum_spads = sum_spads +
+ RangingMeasurementData.EffectiveSpadRtnCount
+ / 32;
+ total_count = total_count + 1;
+ }
+ }
+
+ if (total_count == 0) {
+ /* no valid values found */
+ Status = VL53L0_ERROR_DIVISION_BY_ZERO;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* FixPoint1616_t / uint16_t = FixPoint1616_t */
+ xTalkStoredMeanSignalRate = sum_signalRate / total_count;
+ xTalkStoredMeanRange =
+ (FixPoint1616_t) ((uint32_t) (sum_ranging << 16) /
+ total_count);
+ xTalkStoredMeanRtnSpads =
+ (FixPoint1616_t) ((uint32_t) (sum_spads << 16) /
+ total_count);
+
+ /* Round Mean Spads to Whole Number.
+ * Typically the calculated mean SPAD count is a whole number or
+ * very close to a whole
+ * number, therefore any truncation will not result in a
+ * significant loss in accuracy.
+ * Also, for a grey target at a typical distance of
+ * around 400mm, around 220 SPADs will
+ * be enabled, therefore, any truncation will result in a loss
+ * of accuracy of less than 0.5%.
+ */
+ xTalkStoredMeanRtnSpadsAsInt = (xTalkStoredMeanRtnSpads +
+ 0x8000) >> 16;
+
+ /* Round Cal Distance to Whole Number.
+ * Note that the cal distance is in mm,
+ * therefore no resolution is lost.
+ */
+ xTalkCalDistanceAsInt = (XTalkCalDistance + 0x8000) >> 16;
+
+ if (xTalkStoredMeanRtnSpadsAsInt == 0 || xTalkCalDistanceAsInt
+ == 0 || xTalkStoredMeanRange >= XTalkCalDistance) {
+ XTalkCompensationRateMegaCps = 0;
+ } else {
+ /* Round Cal Distance to Whole Number.
+ * Note that the cal distance is in mm, therefore no
+ * resolution is lost.
+ */
+ xTalkCalDistanceAsInt = (XTalkCalDistance + 0x8000) >>
+ 16;
+
+ /* Apply division by mean spad count early in the
+ * calculation to keep the numbers small.
+ * This ensures we can maintain a 32bit calculation.
+ * Fixed1616 / int := Fixed1616
+ */
+ signalXTalkTotalPerSpad =
+ (xTalkStoredMeanSignalRate) /
+ xTalkStoredMeanRtnSpadsAsInt;
+
+ /* Complete the calculation for total Signal XTalk per
+ * SPAD Fixed1616 * (Fixed1616 - Fixed1616/int)
+ * := (2^16 * Fixed1616)
+ */
+ signalXTalkTotalPerSpad *= ((1 << 16) -
+ (xTalkStoredMeanRange /
+ xTalkCalDistanceAsInt));
+
+ /* Round from 2^16 * Fixed1616, to Fixed1616. */
+ XTalkCompensationRateMegaCps = (signalXTalkTotalPerSpad
+ + 0x8000) >> 16;
+ }
+
+ *pXTalkCompensationRateMegaCps = XTalkCompensationRateMegaCps;
+
+ /* Enable the XTalk compensation */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_SetXTalkCompensationEnable(Dev, 1);
+
+ /* Enable the XTalk compensation */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_SetXTalkCompensationRateMegaCps(Dev,
+ XTalkCompensationRateMegaCps);
+ }
+
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L010_API VL53L0_Error VL53L010_PerformOffsetCalibration(VL53L0_DEV Dev,
+ FixPoint1616_t
+ CalDistanceMilliMeter,
+ int32_t *
+ pOffsetMicroMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t sum_ranging = 0;
+ FixPoint1616_t total_count = 0;
+ VL53L0_RangingMeasurementData_t RangingMeasurementData;
+ FixPoint1616_t StoredMeanRange;
+ uint32_t StoredMeanRangeAsInt;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ uint32_t CalDistanceAsInt_mm;
+ int meas = 0;
+
+ LOG_FUNCTION_START("");
+
+ if (CalDistanceMilliMeter <= 0)
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+ if (Status == VL53L0_ERROR_NONE)
+ VL53L010_SetOffsetCalibrationDataMicroMeter(Dev, 0);
+
+ /* Perform 50 measurements and compute the averages */
+ if (Status == VL53L0_ERROR_NONE) {
+ sum_ranging = 0;
+ total_count = 0;
+ for (meas = 0; meas < 50; meas++) {
+ Status =
+ VL53L010_PerformSingleRangingMeasurement(Dev,
+ &RangingMeasurementData);
+
+ if (Status != VL53L0_ERROR_NONE)
+ break;
+
+ /* The range is valid when RangeStatus = 0 */
+ if (RangingMeasurementData.RangeStatus == 0) {
+ sum_ranging =
+ sum_ranging +
+ RangingMeasurementData.RangeMilliMeter;
+ total_count = total_count + 1;
+ }
+ }
+
+ if (total_count == 0) {
+ /* no valid values found */
+ Status = VL53L0_ERROR_RANGE_ERROR;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* FixPoint1616_t / uint16_t = FixPoint1616_t */
+ StoredMeanRange =
+ (FixPoint1616_t) ((uint32_t) (sum_ranging << 16) /
+ total_count);
+
+ StoredMeanRangeAsInt = (StoredMeanRange + 0x8000) >> 16;
+
+ /* Round Cal Distance to Whole Number.
+ * Note that the cal distance is in mm,
+ * therefore no resolution is lost.
+ */
+ CalDistanceAsInt_mm = (CalDistanceMilliMeter + 0x8000) >> 16;
+
+ *pOffsetMicroMeter =
+ (CalDistanceAsInt_mm - StoredMeanRangeAsInt) * 1000;
+
+ /* Apply the calculated offset */
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L010_SETPARAMETERFIELD(Dev, RangeOffsetMicroMeters,
+ *pOffsetMicroMeter);
+ Status =
+ VL53L010_SetOffsetCalibrationDataMicroMeter(Dev,
+ *pOffsetMicroMeter);
+ }
+
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_StartMeasurement(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceModes DeviceMode;
+ uint8_t Byte = 0;
+ uint32_t LoopNb;
+
+ LOG_FUNCTION_START("");
+
+ /* Get Current DeviceMode */
+ VL53L010_GetDeviceMode(Dev, &DeviceMode);
+
+ switch (DeviceMode) {
+ case VL53L0_DEVICEMODE_SINGLE_RANGING:
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSRANGE_START,
+ VL53L010_REG_SYSRANGE_MODE_SINGLESHOT |
+ VL53L010_REG_SYSRANGE_MODE_START_STOP);
+ break;
+ case VL53L0_DEVICEMODE_CONTINUOUS_RANGING:
+ /* Back-to-back mode */
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSRANGE_START,
+ VL53L010_REG_SYSRANGE_MODE_BACKTOBACK |
+ VL53L010_REG_SYSRANGE_MODE_START_STOP);
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Set PAL State to Running */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_RUNNING);
+ }
+ break;
+ case VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING:
+ /* Continuous mode */
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSRANGE_START,
+ VL53L010_REG_SYSRANGE_MODE_TIMED |
+ VL53L010_REG_SYSRANGE_MODE_START_STOP);
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Set PAL State to Running */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_RUNNING);
+ }
+ break;
+ default:
+ /* Selected mode not supported */
+ Status = VL53L0_ERROR_MODE_NOT_SUPPORTED;
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Wait until start bit has been cleared */
+ LoopNb = 0;
+ do {
+ if (LoopNb > 0)
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_SYSRANGE_START,
+ &Byte);
+ LoopNb = LoopNb + 1;
+ } while (((Byte & VL53L010_REG_SYSRANGE_MODE_START_STOP) ==
+ VL53L010_REG_SYSRANGE_MODE_START_STOP) &&
+ (Status == VL53L0_ERROR_NONE) &&
+ (LoopNb < VL53L0_DEFAULT_MAX_LOOP));
+
+ if (LoopNb >= VL53L0_DEFAULT_MAX_LOOP)
+ Status = VL53L0_ERROR_TIME_OUT;
+
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_StopMeasurement(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSRANGE_START,
+ VL53L010_REG_SYSRANGE_MODE_SINGLESHOT);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Set PAL State to Idle */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_IDLE);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetMeasurementDataReady(VL53L0_DEV Dev, uint8_t
+ *pMeasurementDataReady)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t SysRangeStatusRegister;
+ uint8_t InterruptConfig;
+ uint32_t InterruptMask;
+
+ LOG_FUNCTION_START("");
+
+ InterruptConfig = VL53L010_GETDEVICESPECIFICPARAMETER(Dev,
+ Pin0GpioFunctionality);
+
+ if (InterruptConfig ==
+ VL53L010_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY) {
+ VL53L010_GetInterruptMaskStatus(Dev, &InterruptMask);
+ if (InterruptMask ==
+ VL53L010_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY) {
+ *pMeasurementDataReady = 1;
+ } else {
+ *pMeasurementDataReady = 0;
+ }
+ } else {
+ Status = VL53L0_RdByte(Dev, VL53L010_REG_RESULT_RANGE_STATUS,
+ &SysRangeStatusRegister);
+ if (Status == VL53L0_ERROR_NONE) {
+ if (SysRangeStatusRegister & 0x01)
+ *pMeasurementDataReady = 1;
+ else
+ *pMeasurementDataReady = 0;
+
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_WaitDeviceReadyForNewMeasurement(VL53L0_DEV Dev, uint32_t
+ MaxLoop)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented for VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetRangingMeasurementData(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t
+ *pRangingMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t DeviceRangeStatus;
+ uint8_t PalRangeStatus;
+ uint16_t AmbientRate;
+ FixPoint1616_t SignalRate;
+ FixPoint1616_t CrosstalkCompensation;
+ uint16_t EffectiveSpadRtnCount;
+ uint8_t localBuffer[14];
+ VL53L0_RangingMeasurementData_t LastRangeDataBuffer;
+
+ LOG_FUNCTION_START("");
+
+ /* use multi read even if some registers are not useful, result will be
+ * more efficient
+ * start reading at 0x14 dec20
+ * end reading at 0x21 dec33 total 14 bytes to read
+ */
+ Status = VL53L0_ReadMulti(Dev, 0x14, localBuffer, 14);
+
+ if (Status == VL53L0_ERROR_NONE) {
+
+ pRangingMeasurementData->ZoneId = 0; /* Only one zone */
+ pRangingMeasurementData->TimeStamp = 0; /* Not Implemented */
+
+ pRangingMeasurementData->RangeMilliMeter =
+ VL53L010_MAKEUINT16(localBuffer[11], localBuffer[10]);
+
+ pRangingMeasurementData->RangeDMaxMilliMeter = 0;
+ pRangingMeasurementData->RangeFractionalPart = 0;
+ pRangingMeasurementData->MeasurementTimeUsec = 0;
+
+ SignalRate =
+ VL53L010_FIXPOINT97TOFIXPOINT1616(VL53L010_MAKEUINT16
+ (localBuffer[7],
+ localBuffer[6]));
+ pRangingMeasurementData->SignalRateRtnMegaCps = SignalRate;
+
+ AmbientRate =
+ VL53L010_MAKEUINT16(localBuffer[9], localBuffer[8]);
+ pRangingMeasurementData->AmbientRateRtnMegaCps =
+ VL53L010_FIXPOINT97TOFIXPOINT1616(AmbientRate);
+
+ EffectiveSpadRtnCount = VL53L010_MAKEUINT16(localBuffer[3],
+ localBuffer[2]);
+ pRangingMeasurementData->EffectiveSpadRtnCount =
+ EffectiveSpadRtnCount;
+
+ DeviceRangeStatus = localBuffer[0];
+
+ /* initial format = 4.12, when pass to 16.16 from 9.7 we shift
+ * 5 bit more this will be absorbed in the further computation
+ */
+ CrosstalkCompensation =
+ VL53L010_FIXPOINT97TOFIXPOINT1616(VL53L010_MAKEUINT16
+ (localBuffer[13],
+ localBuffer[12]));
+
+ /*
+ * For a standard definition of RangeStatus, this should return
+ * 0 in case of good result after a ranging
+ * The range status depends on the device so call a device
+ * specific function to obtain the right Status.
+ */
+ Status = VL53L010_get_pal_range_status(Dev, DeviceRangeStatus,
+ SignalRate,
+ CrosstalkCompensation,
+ EffectiveSpadRtnCount,
+ pRangingMeasurementData,
+ &PalRangeStatus);
+
+ if (Status == VL53L0_ERROR_NONE)
+ pRangingMeasurementData->RangeStatus = PalRangeStatus;
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Copy last read data into Dev buffer */
+ LastRangeDataBuffer = PALDevDataGet(Dev, LastRangeMeasure);
+
+ LastRangeDataBuffer.RangeMilliMeter =
+ pRangingMeasurementData->RangeMilliMeter;
+ LastRangeDataBuffer.RangeFractionalPart =
+ pRangingMeasurementData->RangeFractionalPart;
+ LastRangeDataBuffer.RangeDMaxMilliMeter =
+ pRangingMeasurementData->RangeDMaxMilliMeter;
+ LastRangeDataBuffer.MeasurementTimeUsec =
+ pRangingMeasurementData->MeasurementTimeUsec;
+ LastRangeDataBuffer.SignalRateRtnMegaCps =
+ pRangingMeasurementData->SignalRateRtnMegaCps;
+ LastRangeDataBuffer.AmbientRateRtnMegaCps =
+ pRangingMeasurementData->AmbientRateRtnMegaCps;
+ LastRangeDataBuffer.EffectiveSpadRtnCount =
+ pRangingMeasurementData->EffectiveSpadRtnCount;
+ LastRangeDataBuffer.RangeStatus =
+ pRangingMeasurementData->RangeStatus;
+
+ PALDevDataSet(Dev, LastRangeMeasure, LastRangeDataBuffer);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetHistogramMeasurementData(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t
+ *pHistogramMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_PerformSingleRangingMeasurement(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t
+ *pRangingMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ /* This function will do a complete single ranging
+ * Here we fix the mode!
+ */
+ Status = VL53L010_SetDeviceMode(Dev, VL53L0_DEVICEMODE_SINGLE_RANGING);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_PerformSingleMeasurement(Dev);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetRangingMeasurementData(Dev,
+ pRangingMeasurementData);
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_ClearInterruptMask(Dev, 0);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_PerformSingleHistogramMeasurement(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t
+ *
+ pHistogramMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetNumberOfROIZones(VL53L0_DEV Dev, uint8_t
+ NumberOfROIZones)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ if (NumberOfROIZones != 1)
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetNumberOfROIZones(VL53L0_DEV Dev, uint8_t *
+ pNumberOfROIZones)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pNumberOfROIZones = 1;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetMaxNumberOfROIZones(VL53L0_DEV Dev, uint8_t
+ *pMaxNumberOfROIZones)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pMaxNumberOfROIZones = 1;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* End Group PAL Measurement Functions */
+
+VL53L0_Error VL53L010_SetGpioConfig(VL53L0_DEV Dev, uint8_t Pin,
+ VL53L0_DeviceModes DeviceMode,
+ VL53L0_GpioFunctionality Functionality,
+ VL53L0_InterruptPolarity Polarity)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceSpecificParameters_t DeviceSpecificParameters;
+ uint8_t data;
+
+ LOG_FUNCTION_START("");
+
+ if (Pin != 0) {
+ Status = VL53L0_ERROR_GPIO_NOT_EXISTING;
+ } else if (DeviceMode == VL53L0_DEVICEMODE_GPIO_DRIVE) {
+ if (Polarity == VL53L0_INTERRUPTPOLARITY_LOW)
+ data = 0x10;
+ else
+ data = 1;
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L010_REG_GPIO_HV_MUX_ACTIVE_HIGH,
+ data);
+
+ } else if (DeviceMode == VL53L0_DEVICEMODE_GPIO_OSC) {
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x85, 0x02);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0xcd, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xcc, 0x11);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0xbe, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x06);
+ Status |= VL53L0_WrByte(Dev, 0xcc, 0x09);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+
+ } else {
+
+ if (Status == VL53L0_ERROR_NONE) {
+ switch (Functionality) {
+ case VL53L010_GPIOFUNCTIONALITY_OFF:
+ data = 0x00;
+ break;
+ case VL53L010_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW:
+ data = 0x01;
+ break;
+ case VL53L010_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH:
+ data = 0x02;
+ break;
+ case VL53L010_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT:
+ data = 0x03;
+ break;
+ case VL53L010_GPIOFUNCTIONALITY_NEW_MEASURE_READY:
+ data = 0x04;
+ break;
+ default:
+ Status =
+ VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrByte(Dev,
+ VL53L010_REG_SYSTEM_INTERRUPT_CONFIG_GPIO,
+ data);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Polarity == VL53L0_INTERRUPTPOLARITY_LOW)
+ data = 0;
+ else
+ data = (uint8_t) (1 << 4);
+
+ Status = VL53L0_UpdateByte(Dev,
+ VL53L010_REG_GPIO_HV_MUX_ACTIVE_HIGH,
+ 0xEF, data);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev,
+ Pin0GpioFunctionality,
+ Functionality);
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L010_ClearInterruptMask(Dev, 0);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetGpioConfig(VL53L0_DEV Dev, uint8_t Pin,
+ VL53L0_DeviceModes *DeviceMode,
+ VL53L0_GpioFunctionality *pFunctionality,
+ VL53L0_InterruptPolarity *pPolarity)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceSpecificParameters_t DeviceSpecificParameters;
+ VL53L0_GpioFunctionality GpioFunctionality;
+ uint8_t data;
+
+ LOG_FUNCTION_START("");
+
+ if (Pin != 0) {
+ Status = VL53L0_ERROR_GPIO_NOT_EXISTING;
+ } else {
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_SYSTEM_INTERRUPT_CONFIG_GPIO,
+ &data);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ switch (data & 0x07) {
+ case 0x00:
+ GpioFunctionality = VL53L010_GPIOFUNCTIONALITY_OFF;
+ break;
+ case 0x01:
+ GpioFunctionality =
+ VL53L010_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW;
+ break;
+ case 0x02:
+ GpioFunctionality =
+ VL53L010_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH;
+ break;
+ case 0x03:
+ GpioFunctionality =
+ VL53L010_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT;
+ break;
+ case 0x04:
+ GpioFunctionality =
+ VL53L010_GPIOFUNCTIONALITY_NEW_MEASURE_READY;
+ break;
+ default:
+ Status = VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_GPIO_HV_MUX_ACTIVE_HIGH,
+ &data);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if ((data & (uint8_t) (1 << 4)) == 0)
+ *pPolarity = VL53L0_INTERRUPTPOLARITY_LOW;
+ else
+ *pPolarity = VL53L0_INTERRUPTPOLARITY_HIGH;
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ *pFunctionality = GpioFunctionality;
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev, Pin0GpioFunctionality,
+ GpioFunctionality);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetInterruptThresholds(VL53L0_DEV Dev, VL53L0_DeviceModes
+ DeviceMode,
+ FixPoint1616_t ThresholdLow,
+ FixPoint1616_t ThresholdHigh)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t Threshold16;
+
+ LOG_FUNCTION_START("");
+
+ /* no dependency on DeviceMode for Ewok */
+ /* Need to divide by 2 because the FW will apply a x2 */
+ Threshold16 = (uint16_t) ((ThresholdLow >> 17) & 0x00fff);
+ Status =
+ VL53L0_WrWord(Dev, VL53L010_REG_SYSTEM_THRESH_LOW, Threshold16);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Need to divide by 2 because the FW will apply a x2 */
+ Threshold16 = (uint16_t) ((ThresholdHigh >> 17) & 0x00fff);
+ Status = VL53L0_WrWord(Dev, VL53L010_REG_SYSTEM_THRESH_HIGH,
+ Threshold16);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetInterruptThresholds(VL53L0_DEV Dev, VL53L0_DeviceModes
+ DeviceMode,
+ FixPoint1616_t *pThresholdLow,
+ FixPoint1616_t *pThresholdHigh)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t Threshold16;
+
+ LOG_FUNCTION_START("");
+
+ /* no dependency on DeviceMode for Ewok */
+
+ Status =
+ VL53L0_RdWord(Dev, VL53L010_REG_SYSTEM_THRESH_LOW, &Threshold16);
+ /* Need to multiply by 2 because the FW will apply a x2 */
+ *pThresholdLow = (FixPoint1616_t) ((0x00fff & Threshold16) << 17);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdWord(Dev, VL53L010_REG_SYSTEM_THRESH_HIGH,
+ &Threshold16);
+ /* Need to multiply by 2 because the FW will apply a x2 */
+ *pThresholdHigh =
+ (FixPoint1616_t) ((0x00fff & Threshold16) << 17);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* Group PAL Interrupt Functions */
+VL53L0_Error VL53L010_ClearInterruptMask(VL53L0_DEV Dev, uint32_t InterruptMask)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t LoopCount;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ /* clear bit 0 range interrupt, bit 1 error interrupt */
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSTEM_INTERRUPT_CLEAR, 0x01);
+ LoopCount = 0;
+ do {
+ VL53L0_RdByte(Dev, VL53L010_REG_RESULT_INTERRUPT_STATUS, &Byte);
+ LoopCount++;
+ } while (((Byte & 0x07) != 0x00) && (LoopCount < 8));
+ Status = VL53L0_WrByte(Dev, VL53L010_REG_SYSTEM_INTERRUPT_CLEAR, 0x00);
+ /* clear all */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetInterruptMaskStatus(VL53L0_DEV Dev, uint32_t
+ *pInterruptMaskStatus)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ Status =
+ VL53L0_RdByte(Dev, VL53L010_REG_RESULT_INTERRUPT_STATUS, &Byte);
+ *pInterruptMaskStatus = Byte & 0x07;
+
+ /* check if some error occurs */
+ if (Byte & 0x18)
+ Status = VL53L0_ERROR_RANGE_ERROR;
+
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_EnableInterruptMask(VL53L0_DEV Dev,
+ uint32_t InterruptMask)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented for VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* End Group PAL Interrupt Functions */
+
+/* Group SPAD functions */
+
+VL53L0_Error VL53L010_SetSpadAmbientDamperThreshold(VL53L0_DEV Dev, uint16_t
+ SpadAmbientDamperThreshold)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status = VL53L0_WrWord(Dev, 0x40, SpadAmbientDamperThreshold);
+ VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetSpadAmbientDamperThreshold(VL53L0_DEV Dev, uint16_t
+ *
+ pSpadAmbientDamperThreshold)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status = VL53L0_RdWord(Dev, 0x40, pSpadAmbientDamperThreshold);
+ VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_SetSpadAmbientDamperFactor(VL53L0_DEV Dev, uint16_t
+ SpadAmbientDamperFactor)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ Byte = (uint8_t) (SpadAmbientDamperFactor & 0x00FF);
+
+ VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status = VL53L0_WrByte(Dev, 0x42, Byte);
+ VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_GetSpadAmbientDamperFactor(VL53L0_DEV Dev, uint16_t
+ *pSpadAmbientDamperFactor)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status = VL53L0_RdByte(Dev, 0x42, &Byte);
+ VL53L0_WrByte(Dev, 0xFF, 0x00);
+ *pSpadAmbientDamperFactor = (uint16_t) Byte;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* END Group SPAD functions */
+
+/*
+ * Internal functions
+ */
+
+
+
+VL53L010_EXTERNAL VL53L0_Error VL53L010_get_vcsel_pulse_period(VL53L0_DEV Dev,
+ uint8_t *
+ pVCSELPulsePeriod,
+ uint8_t
+ RangeIndex)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t vcsel_period_reg;
+
+ LOG_FUNCTION_START("");
+
+ switch (RangeIndex) {
+ case 0:
+ Status =
+ VL53L0_RdByte(Dev, VL53L010_REG_RNGA_CONFIG_VCSEL_PERIOD,
+ &vcsel_period_reg);
+ break;
+ case 1:
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_RNGB1_CONFIG_VCSEL_PERIOD,
+ &vcsel_period_reg);
+ break;
+ case 2:
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_RNGB2_CONFIG_VCSEL_PERIOD,
+ &vcsel_period_reg);
+ break;
+ default:
+ Status =
+ VL53L0_RdByte(Dev, VL53L010_REG_RNGA_CONFIG_VCSEL_PERIOD,
+ &vcsel_period_reg);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ *pVCSELPulsePeriod =
+ VL53L010_decode_vcsel_period(vcsel_period_reg);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* To convert ms into register value */
+VL53L010_EXTERNAL uint16_t VL53L010_calc_encoded_timeout(VL53L0_DEV Dev,
+ uint32_t
+ timeout_period_us,
+ uint8_t vcsel_period)
+{
+ uint32_t macro_period_ps;
+ uint32_t macro_period_ns;
+ uint32_t timeout_period_mclks = 0;
+ uint16_t timeout_overall_periods = 0;
+
+ macro_period_ps = VL53L010_calc_macro_period_ps(Dev, vcsel_period);
+ macro_period_ns = macro_period_ps / 1000;
+
+ timeout_period_mclks = (uint32_t) (((timeout_period_us * 1000) +
+ (macro_period_ns / 2)) /
+ macro_period_ns);
+ timeout_overall_periods = VL53L010_encode_timeout(timeout_period_mclks);
+
+ return timeout_overall_periods;
+}
+
+/* To convert register value into us */
+VL53L010_EXTERNAL uint32_t VL53L010_calc_ranging_wait_us(VL53L0_DEV Dev,
+ uint16_t
+ timeout_overall_periods,
+ uint8_t vcsel_period)
+{
+ uint32_t macro_period_ps;
+ uint32_t macro_period_ns;
+ uint32_t timeout_period_mclks = 0;
+ uint32_t actual_timeout_period_us = 0;
+
+ macro_period_ps = VL53L010_calc_macro_period_ps(Dev, vcsel_period);
+ macro_period_ns = macro_period_ps / 1000;
+
+ timeout_period_mclks = VL53L010_decode_timeout(timeout_overall_periods);
+ actual_timeout_period_us = ((timeout_period_mclks * macro_period_ns) +
+ (macro_period_ns / 2)) / 1000;
+
+ return actual_timeout_period_us;
+}
+
+VL53L010_EXTERNAL uint32_t VL53L010_calc_macro_period_ps(VL53L0_DEV Dev,
+ uint8_t vcsel_period)
+{
+ uint32_t PLL_multiplier;
+ uint64_t PLL_period_ps;
+ uint8_t vcsel_period_pclks;
+ uint32_t macro_period_vclks;
+ uint32_t macro_period_ps;
+ FixPoint1616_t OscFrequencyMHz;
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceSpecificParameters_t DeviceSpecificParameters;
+
+ LOG_FUNCTION_START("");
+
+ PLL_multiplier = 65536 / 64; /* PLL multiplier is 64 */
+
+ OscFrequencyMHz = VL53L010_GETDEVICESPECIFICPARAMETER(Dev,
+ OscFrequencyMHz);
+
+ if (OscFrequencyMHz == 0) {
+ /* Use default one */
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev, OscFrequencyMHz,
+ 748421);
+ OscFrequencyMHz = 748421;
+ }
+ PLL_period_ps = (1000 * 1000 * PLL_multiplier) / OscFrequencyMHz;
+
+ vcsel_period_pclks = VL53L010_decode_vcsel_period(vcsel_period);
+
+ macro_period_vclks = 2304;
+ macro_period_ps = (uint32_t) (macro_period_vclks * vcsel_period_pclks *
+ PLL_period_ps);
+
+ LOG_FUNCTION_END("");
+ return macro_period_ps;
+}
+
+VL53L010_EXTERNAL uint8_t VL53L010_decode_vcsel_period(uint8_t vcsel_period_reg)
+{
+
+ /*!
+ * Converts the encoded VCSEL period register value into the real
+ * period in PLL clocks
+ */
+
+ uint8_t vcsel_period_pclks = 0;
+
+ vcsel_period_pclks = (vcsel_period_reg + 1) << 1;
+
+ return vcsel_period_pclks;
+}
+
+VL53L010_EXTERNAL uint8_t VL53L010_encode_vcsel_period(uint8_t
+ vcsel_period_pclks)
+{
+
+ /*!
+ * Converts the encoded VCSEL period register value into the real
+ * period in PLL clocks
+ */
+
+ uint8_t vcsel_period_reg = 0;
+
+ vcsel_period_reg = (vcsel_period_pclks >> 1) - 1;
+
+ return vcsel_period_reg;
+}
+
+VL53L010_EXTERNAL uint16_t VL53L010_encode_timeout(uint32_t timeout_mclks)
+{
+ /*!
+ * Encode timeout in macro periods in (LSByte * 2^MSByte) + 1 format
+ *
+ */
+
+ uint16_t encoded_timeout = 0;
+ uint32_t ls_byte = 0;
+ uint16_t ms_byte = 0;
+
+ if (timeout_mclks > 0) {
+ ls_byte = timeout_mclks - 1;
+
+ while ((ls_byte & 0xFFFFFF00) > 0) {
+ ls_byte = ls_byte >> 1;
+ ms_byte++;
+ }
+
+ encoded_timeout = (ms_byte << 8) + (uint16_t) (ls_byte &
+ 0x000000FF);
+
+ }
+
+ return encoded_timeout;
+
+}
+
+VL53L010_EXTERNAL uint32_t VL53L010_decode_timeout(uint16_t encoded_timeout)
+{
+ /*!
+ * Decode 16-bit timeout register value - format (LSByte * 2^MSByte) + 1
+ *
+ */
+
+ uint32_t timeout_mclks = 0;
+
+ timeout_mclks = ((uint32_t) (encoded_timeout & 0x00FF) << (uint32_t)
+ ((encoded_timeout & 0xFF00) >> 8)) + 1;
+
+ return timeout_mclks;
+
+}
+
+VL53L010_EXTERNAL VL53L0_Error VL53L010_load_additional_settings1(VL53L0_DEV
+ Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ /* update 12_05_15_v6 */
+ /* OSCT */
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x14, 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xCD, 0x6C);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x86, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x87, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ /* update 12_05_15_v6 */
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xcd, 0x6c);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x90, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0x91, 0x3f);
+ Status |= VL53L0_WrByte(Dev, 0x92, 0x3f);
+ Status |= VL53L0_WrByte(Dev, 0x88, 0x2b);
+ Status |= VL53L0_WrByte(Dev, 0x89, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xcd, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ /* update 12_05_15 */
+ Status |= VL53L0_WrByte(Dev, 0xb0, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xb1, 0xfc);
+ Status |= VL53L0_WrByte(Dev, 0xb2, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xb3, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xb4, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xb5, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xb6, 0xb0);
+
+ Status |= VL53L0_WrByte(Dev, 0x32, 0x03);
+
+ Status |= VL53L0_WrByte(Dev, 0x41, 0xff);
+ Status |= VL53L0_WrByte(Dev, 0x42, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0x43, 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0x01, 0x01);
+
+ if (Status != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L010_EXTERNAL VL53L0_Error VL53L010_load_additional_settings3(VL53L0_DEV
+ Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ /* update 150624_b */
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x4f, 0x0B);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x0E);
+
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x0C);
+ Status |= VL53L0_WrByte(Dev, 0x01, 0x0C);
+ Status |= VL53L0_WrByte(Dev, 0x02, 0x0A);
+ Status |= VL53L0_WrByte(Dev, 0x03, 0x0D);
+ Status |= VL53L0_WrByte(Dev, 0x04, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x05, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0x06, 0x06);
+ Status |= VL53L0_WrByte(Dev, 0x07, 0x47);
+ Status |= VL53L0_WrByte(Dev, 0x08, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x09, 0x20);
+ Status |= VL53L0_WrByte(Dev, 0x0A, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x0B, 0x49);
+ Status |= VL53L0_WrByte(Dev, 0x0C, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x0D, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x0E, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x0F, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x10, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x11, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0x12, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x13, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0x14, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x15, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x16, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x17, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x18, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x19, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0x1A, 0x11);
+ Status |= VL53L0_WrByte(Dev, 0x1B, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x1C, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x1D, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x1E, 0x11);
+ Status |= VL53L0_WrByte(Dev, 0x1F, 0x08);
+ Status |= VL53L0_WrByte(Dev, 0x20, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x21, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0x22, 0x0C);
+ Status |= VL53L0_WrByte(Dev, 0x23, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x24, 0x0A);
+ Status |= VL53L0_WrByte(Dev, 0x25, 0x0D);
+ Status |= VL53L0_WrByte(Dev, 0x26, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x27, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x28, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x29, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x2A, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x2B, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x2C, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x2D, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0x2E, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x2F, 0x92);
+ Status |= VL53L0_WrByte(Dev, 0x30, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x31, 0x64);
+ Status |= VL53L0_WrByte(Dev, 0x32, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x33, 0x8A);
+ Status |= VL53L0_WrByte(Dev, 0x34, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x35, 0xE0);
+ Status |= VL53L0_WrByte(Dev, 0x36, 0x0F);
+ Status |= VL53L0_WrByte(Dev, 0x37, 0xAA);
+ Status |= VL53L0_WrByte(Dev, 0x38, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x39, 0xE4);
+ Status |= VL53L0_WrByte(Dev, 0x3A, 0x0F);
+ Status |= VL53L0_WrByte(Dev, 0x3B, 0xAE);
+ Status |= VL53L0_WrByte(Dev, 0x3C, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x3D, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x3E, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x3F, 0x54);
+ Status |= VL53L0_WrByte(Dev, 0x40, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x41, 0x88);
+ Status |= VL53L0_WrByte(Dev, 0x42, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x43, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0x44, 0x0C);
+ Status |= VL53L0_WrByte(Dev, 0x45, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x46, 0x06);
+ Status |= VL53L0_WrByte(Dev, 0x47, 0x87);
+ Status |= VL53L0_WrByte(Dev, 0x48, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x49, 0x38);
+ Status |= VL53L0_WrByte(Dev, 0x4A, 0x2B);
+ Status |= VL53L0_WrByte(Dev, 0x4B, 0x89);
+ Status |= VL53L0_WrByte(Dev, 0x4C, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x4D, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x4E, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x4F, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x50, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x51, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0x52, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x53, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0x54, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x55, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x56, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x57, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x58, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x59, 0x0D);
+ Status |= VL53L0_WrByte(Dev, 0x5A, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x5B, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0x5C, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x5D, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0x5E, 0x0D);
+ Status |= VL53L0_WrByte(Dev, 0x5F, 0x67);
+ Status |= VL53L0_WrByte(Dev, 0x60, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x61, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0x62, 0x0D);
+ Status |= VL53L0_WrByte(Dev, 0x63, 0xB0);
+ Status |= VL53L0_WrByte(Dev, 0x64, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x65, 0x20);
+ Status |= VL53L0_WrByte(Dev, 0x66, 0x29);
+ Status |= VL53L0_WrByte(Dev, 0x67, 0xC1);
+ Status |= VL53L0_WrByte(Dev, 0x68, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x69, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x6A, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x6B, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x6C, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x6D, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x6E, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x6F, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x70, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x71, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0x72, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x73, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0x74, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x75, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x76, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x77, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x78, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x79, 0x0D);
+ Status |= VL53L0_WrByte(Dev, 0x7A, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x7B, 0x1B);
+ Status |= VL53L0_WrByte(Dev, 0x7C, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x7D, 0x82);
+ Status |= VL53L0_WrByte(Dev, 0x7E, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x7F, 0x24);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x81, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x82, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x83, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x84, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x85, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x86, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x87, 0x21);
+ Status |= VL53L0_WrByte(Dev, 0x88, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x89, 0x58);
+ Status |= VL53L0_WrByte(Dev, 0x8A, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x8B, 0xCC);
+ Status |= VL53L0_WrByte(Dev, 0x8C, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x8D, 0xC3);
+ Status |= VL53L0_WrByte(Dev, 0x8E, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x8F, 0x94);
+ Status |= VL53L0_WrByte(Dev, 0x90, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x91, 0x53);
+ Status |= VL53L0_WrByte(Dev, 0x92, 0x1E);
+ Status |= VL53L0_WrByte(Dev, 0x93, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x95, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x96, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x97, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x98, 0x20);
+ Status |= VL53L0_WrByte(Dev, 0x99, 0x20);
+ Status |= VL53L0_WrByte(Dev, 0x9A, 0x08);
+ Status |= VL53L0_WrByte(Dev, 0x9B, 0x10);
+ Status |= VL53L0_WrByte(Dev, 0x9C, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x9D, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x9E, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x9F, 0x50);
+ Status |= VL53L0_WrByte(Dev, 0xA0, 0x2B);
+ Status |= VL53L0_WrByte(Dev, 0xA1, 0xB1);
+ Status |= VL53L0_WrByte(Dev, 0xA2, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xA3, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0xA4, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0xA5, 0x50);
+ Status |= VL53L0_WrByte(Dev, 0xA6, 0x2C);
+ Status |= VL53L0_WrByte(Dev, 0xA7, 0x11);
+ Status |= VL53L0_WrByte(Dev, 0xA8, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xA9, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xAA, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xAB, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xAC, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xAD, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0xAE, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xAF, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0xB0, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xB1, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0xB2, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0xB3, 0x4E);
+ Status |= VL53L0_WrByte(Dev, 0xB4, 0x2D);
+ Status |= VL53L0_WrByte(Dev, 0xB5, 0x47);
+ Status |= VL53L0_WrByte(Dev, 0xB6, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xB7, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xB8, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xB9, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xBA, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xBB, 0xA7);
+ Status |= VL53L0_WrByte(Dev, 0xBC, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xBD, 0xA6);
+ Status |= VL53L0_WrByte(Dev, 0xBE, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xBF, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0xC0, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0xC1, 0x30);
+ Status |= VL53L0_WrByte(Dev, 0xC2, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xC3, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0xC4, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0xC5, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0xC6, 0x2D);
+ Status |= VL53L0_WrByte(Dev, 0xC7, 0x89);
+ Status |= VL53L0_WrByte(Dev, 0xC8, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xC9, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xCA, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xCB, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xCC, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xCD, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0xCE, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xCF, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0xD0, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xD1, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0xD2, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xD3, 0x25);
+ Status |= VL53L0_WrByte(Dev, 0xD4, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xD5, 0x2E);
+ Status |= VL53L0_WrByte(Dev, 0xD6, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xD7, 0x25);
+ Status |= VL53L0_WrByte(Dev, 0xD8, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xD9, 0x2E);
+ Status |= VL53L0_WrByte(Dev, 0xDA, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0xDB, 0xF3);
+ Status |= VL53L0_WrByte(Dev, 0xDC, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0xDD, 0xEA);
+ Status |= VL53L0_WrByte(Dev, 0xDE, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0xDF, 0x58);
+ Status |= VL53L0_WrByte(Dev, 0xE0, 0x2C);
+ Status |= VL53L0_WrByte(Dev, 0xE1, 0xD9);
+ Status |= VL53L0_WrByte(Dev, 0xE2, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xE3, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xE4, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xE5, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xE6, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xE7, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0xE8, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xE9, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0xEA, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xEB, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0xEC, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xED, 0x26);
+ Status |= VL53L0_WrByte(Dev, 0xEE, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xEF, 0xDC);
+ Status |= VL53L0_WrByte(Dev, 0xF0, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0xF1, 0x58);
+ Status |= VL53L0_WrByte(Dev, 0xF2, 0x2F);
+ Status |= VL53L0_WrByte(Dev, 0xF3, 0x21);
+ Status |= VL53L0_WrByte(Dev, 0xF4, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xF5, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xF6, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xF7, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xF8, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xF9, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0xFA, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFB, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0xFC, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFD, 0x04);
+ Status |= VL53L0_WrWord(Dev, 0xFE, 0x01E3);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x0F);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x01, 0x48);
+ Status |= VL53L0_WrByte(Dev, 0x02, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x03, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0x04, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x05, 0xA4);
+ Status |= VL53L0_WrByte(Dev, 0x06, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x07, 0xB8);
+ Status |= VL53L0_WrByte(Dev, 0x08, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x09, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0x0A, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x0B, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0x0C, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x0D, 0x6B);
+ Status |= VL53L0_WrByte(Dev, 0x0E, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x0F, 0x64);
+ Status |= VL53L0_WrByte(Dev, 0x10, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x11, 0x3C);
+ Status |= VL53L0_WrByte(Dev, 0x12, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x13, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0x14, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x15, 0x74);
+ Status |= VL53L0_WrByte(Dev, 0x16, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x17, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0x18, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x19, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0x1A, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x1B, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x1C, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x1D, 0xA2);
+ Status |= VL53L0_WrByte(Dev, 0x1E, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0x1F, 0x8E);
+ Status |= VL53L0_WrByte(Dev, 0x20, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x21, 0x50);
+ Status |= VL53L0_WrByte(Dev, 0x22, 0x2E);
+ Status |= VL53L0_WrByte(Dev, 0x23, 0xC9);
+ Status |= VL53L0_WrByte(Dev, 0x24, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x25, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x26, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x27, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x28, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x29, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0x2A, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x2B, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0x2C, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x2D, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x2E, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x2F, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x30, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x31, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x32, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x33, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0x34, 0x11);
+ Status |= VL53L0_WrByte(Dev, 0x35, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x36, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x37, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x38, 0x11);
+ Status |= VL53L0_WrByte(Dev, 0x39, 0x08);
+ Status |= VL53L0_WrByte(Dev, 0x3A, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x3B, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x3C, 0x11);
+ Status |= VL53L0_WrByte(Dev, 0x3D, 0x18);
+ Status |= VL53L0_WrByte(Dev, 0x3E, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x3F, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x40, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x41, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x42, 0x0C);
+ Status |= VL53L0_WrByte(Dev, 0x43, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x44, 0x0A);
+ Status |= VL53L0_WrByte(Dev, 0x45, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x46, 0x0C);
+ Status |= VL53L0_WrByte(Dev, 0x47, 0x08);
+ Status |= VL53L0_WrByte(Dev, 0x48, 0x0A);
+ Status |= VL53L0_WrByte(Dev, 0x49, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x4A, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x4B, 0x40);
+ Status |= VL53L0_WrByte(Dev, 0x4C, 0x2F);
+ Status |= VL53L0_WrByte(Dev, 0x4D, 0xD1);
+ Status |= VL53L0_WrByte(Dev, 0x4E, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x4F, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x50, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x51, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x52, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x53, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0x54, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x55, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0x56, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x57, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x58, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x59, 0x11);
+ Status |= VL53L0_WrByte(Dev, 0x5A, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x5B, 0x48);
+ Status |= VL53L0_WrByte(Dev, 0x5C, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x5D, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0x5E, 0x0A);
+ Status |= VL53L0_WrByte(Dev, 0x5F, 0xA2);
+ Status |= VL53L0_WrByte(Dev, 0x60, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x61, 0x60);
+ Status |= VL53L0_WrByte(Dev, 0x62, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x63, 0x3E);
+ Status |= VL53L0_WrByte(Dev, 0x64, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x65, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x66, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x67, 0x54);
+ Status |= VL53L0_WrByte(Dev, 0x68, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x69, 0x80);
+ Status |= VL53L0_WrByte(Dev, 0x6A, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x6B, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x6C, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x6D, 0x38);
+ Status |= VL53L0_WrByte(Dev, 0x6E, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x6F, 0xE1);
+ Status |= VL53L0_WrByte(Dev, 0x70, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x71, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0x72, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x73, 0x38);
+ Status |= VL53L0_WrByte(Dev, 0x74, 0x29);
+ Status |= VL53L0_WrByte(Dev, 0x75, 0x21);
+ Status |= VL53L0_WrByte(Dev, 0x76, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x77, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x78, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x79, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x7A, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x7B, 0xA1);
+ Status |= VL53L0_WrByte(Dev, 0x7C, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x7D, 0xA0);
+ Status |= VL53L0_WrByte(Dev, 0x7E, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x7F, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x81, 0x33);
+ Status |= VL53L0_WrByte(Dev, 0x82, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x83, 0x6A);
+ Status |= VL53L0_WrByte(Dev, 0x84, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x85, 0x61);
+ Status |= VL53L0_WrByte(Dev, 0x86, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x87, 0xF9);
+ Status |= VL53L0_WrByte(Dev, 0x88, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x89, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x8A, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x8B, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x8C, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x8D, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0x8E, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x8F, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x90, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x91, 0x66);
+ Status |= VL53L0_WrByte(Dev, 0x92, 0x2A);
+ Status |= VL53L0_WrByte(Dev, 0x93, 0x67);
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x95, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0x96, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x97, 0x66);
+ Status |= VL53L0_WrByte(Dev, 0x98, 0x2A);
+ Status |= VL53L0_WrByte(Dev, 0x99, 0xAF);
+ Status |= VL53L0_WrByte(Dev, 0x9A, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x9B, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x9C, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x9D, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x9E, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x9F, 0xA7);
+ Status |= VL53L0_WrByte(Dev, 0xA0, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xA1, 0xA6);
+ Status |= VL53L0_WrByte(Dev, 0xA2, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xA3, 0x04);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x04);
+
+ Status |= VL53L0_WrByte(Dev, 0x79, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0x7B, 0x16);
+ Status |= VL53L0_WrByte(Dev, 0x7D, 0x2B);
+ Status |= VL53L0_WrByte(Dev, 0x7F, 0x3B);
+ Status |= VL53L0_WrByte(Dev, 0x81, 0x59);
+ Status |= VL53L0_WrByte(Dev, 0x83, 0x62);
+ Status |= VL53L0_WrByte(Dev, 0x85, 0x69);
+ Status |= VL53L0_WrByte(Dev, 0x87, 0x76);
+ Status |= VL53L0_WrByte(Dev, 0x89, 0x7F);
+ Status |= VL53L0_WrByte(Dev, 0x8B, 0x98);
+ Status |= VL53L0_WrByte(Dev, 0x8D, 0xAC);
+ Status |= VL53L0_WrByte(Dev, 0x8F, 0xC0);
+ Status |= VL53L0_WrByte(Dev, 0x90, 0x0C);
+ Status |= VL53L0_WrByte(Dev, 0x91, 0x30);
+ Status |= VL53L0_WrByte(Dev, 0x92, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0x93, 0x02);
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x37);
+ Status |= VL53L0_WrByte(Dev, 0x95, 0x62);
+
+ Status |= VL53L0_WrByte(Dev, 0x96, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x97, 0x08);
+ Status |= VL53L0_WrByte(Dev, 0x98, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0x99, 0x18);
+ Status |= VL53L0_WrByte(Dev, 0x9A, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0x9B, 0x6F);
+ Status |= VL53L0_WrByte(Dev, 0x9C, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x9D, 0xD4);
+ Status |= VL53L0_WrByte(Dev, 0x9E, 0x0A);
+ Status |= VL53L0_WrByte(Dev, 0x9F, 0x6E);
+ Status |= VL53L0_WrByte(Dev, 0xA0, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0xA1, 0xA2);
+ Status |= VL53L0_WrByte(Dev, 0xA2, 0x0C);
+ Status |= VL53L0_WrByte(Dev, 0xA3, 0xAA);
+ Status |= VL53L0_WrByte(Dev, 0xA4, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xA5, 0x97);
+ Status |= VL53L0_WrByte(Dev, 0xA6, 0x0B);
+ Status |= VL53L0_WrByte(Dev, 0xA7, 0xD8);
+ Status |= VL53L0_WrByte(Dev, 0xA8, 0x0A);
+ Status |= VL53L0_WrByte(Dev, 0xA9, 0xD7);
+ Status |= VL53L0_WrByte(Dev, 0xAA, 0x08);
+ Status |= VL53L0_WrByte(Dev, 0xAB, 0xF6);
+ Status |= VL53L0_WrByte(Dev, 0xAC, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0xAD, 0x1A);
+ Status |= VL53L0_WrByte(Dev, 0xAE, 0x0C);
+ Status |= VL53L0_WrByte(Dev, 0xAF, 0x49);
+ Status |= VL53L0_WrByte(Dev, 0xB0, 0x09);
+ Status |= VL53L0_WrByte(Dev, 0xB1, 0x17);
+ Status |= VL53L0_WrByte(Dev, 0xB2, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0xB3, 0xCD);
+ Status |= VL53L0_WrByte(Dev, 0xB4, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0xB5, 0x55);
+
+ Status |= VL53L0_WrByte(Dev, 0x72, 0xFF);
+ Status |= VL53L0_WrByte(Dev, 0x73, 0xFF);
+
+ Status |= VL53L0_WrByte(Dev, 0x74, 0xE0);
+
+ Status |= VL53L0_WrByte(Dev, 0x70, 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+
+ if (Status != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L010_EXTERNAL VL53L0_Error VL53L010_check_part_used(VL53L0_DEV Dev,
+ uint8_t *Revision,
+ VL53L0_DeviceInfo_t *
+ pVL53L0_DeviceInfo)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t ModuleIdInt;
+ char *ProductId_tmp;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L010_get_info_from_device(Dev);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ ModuleIdInt =
+ VL53L010_GETDEVICESPECIFICPARAMETER(Dev, ModuleId);
+
+ if (ModuleIdInt == 0) {
+ *Revision = 0;
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->ProductId, "");
+ } else {
+ *Revision =
+ VL53L010_GETDEVICESPECIFICPARAMETER(Dev, Revision);
+ ProductId_tmp =
+ VL53L010_GETDEVICESPECIFICPARAMETER(Dev, ProductId);
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->ProductId,
+ ProductId_tmp);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L010_EXTERNAL VL53L0_Error VL53L010_get_info_from_device(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t byte;
+ uint32_t TmpDWord;
+ VL53L0_DeviceSpecificParameters_t DeviceSpecificParameters;
+ uint8_t ModuleId;
+ uint8_t Revision;
+ uint8_t ReferenceSpadCount;
+ uint8_t ReferenceSpadType;
+ char ProductId[19];
+ char *ProductId_tmp;
+ uint8_t ReadDataFromDeviceDone;
+
+ LOG_FUNCTION_START("");
+
+ ReadDataFromDeviceDone = VL53L010_GETDEVICESPECIFICPARAMETER(Dev,
+ ReadDataFromDeviceDone);
+
+ /* This access is done only once after that a GetDeviceInfo or
+ * datainit is done
+ */
+ if (ReadDataFromDeviceDone == 0) {
+
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x06);
+ Status |= VL53L0_RdByte(Dev, 0x83, &byte);
+ Status |= VL53L0_WrByte(Dev, 0x83, byte | 4);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0x81, 0x01);
+
+ Status |= VL53L0_PollingDelay(Dev);
+
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x6b);
+ Status |= VL53L010_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ReferenceSpadCount = (uint8_t) ((TmpDWord >> 8) & 0x07f);
+ ReferenceSpadType = (uint8_t) ((TmpDWord >> 15) & 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x02);
+ Status |= VL53L010_device_read_strobe(Dev);
+ Status |= VL53L0_RdByte(Dev, 0x90, &ModuleId);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x7B);
+ Status |= VL53L010_device_read_strobe(Dev);
+ Status |= VL53L0_RdByte(Dev, 0x90, &Revision);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x77);
+ Status |= VL53L010_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ProductId[0] = (char)((TmpDWord >> 25) & 0x07f);
+ ProductId[1] = (char)((TmpDWord >> 18) & 0x07f);
+ ProductId[2] = (char)((TmpDWord >> 11) & 0x07f);
+ ProductId[3] = (char)((TmpDWord >> 4) & 0x07f);
+
+ byte = (uint8_t) ((TmpDWord & 0x00f) << 3);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x78);
+ Status |= VL53L010_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ProductId[4] = (char)(byte + ((TmpDWord >> 29) & 0x07f));
+ ProductId[5] = (char)((TmpDWord >> 22) & 0x07f);
+ ProductId[6] = (char)((TmpDWord >> 15) & 0x07f);
+ ProductId[7] = (char)((TmpDWord >> 8) & 0x07f);
+ ProductId[8] = (char)((TmpDWord >> 1) & 0x07f);
+
+ byte = (uint8_t) ((TmpDWord & 0x001) << 6);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x79);
+
+ Status |= VL53L010_device_read_strobe(Dev);
+
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ProductId[9] = (char)(byte + ((TmpDWord >> 26) & 0x07f));
+ ProductId[10] = (char)((TmpDWord >> 19) & 0x07f);
+ ProductId[11] = (char)((TmpDWord >> 12) & 0x07f);
+ ProductId[12] = (char)((TmpDWord >> 5) & 0x07f);
+
+ byte = (uint8_t) ((TmpDWord & 0x01f) << 2);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x80);
+
+ Status |= VL53L010_device_read_strobe(Dev);
+
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ProductId[13] = (char)(byte + ((TmpDWord >> 30) & 0x07f));
+ ProductId[14] = (char)((TmpDWord >> 23) & 0x07f);
+ ProductId[15] = (char)((TmpDWord >> 16) & 0x07f);
+ ProductId[16] = (char)((TmpDWord >> 9) & 0x07f);
+ ProductId[17] = (char)((TmpDWord >> 2) & 0x07f);
+ ProductId[18] = '\0';
+
+ Status |= VL53L0_WrByte(Dev, 0x81, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x06);
+ Status |= VL53L0_RdByte(Dev, 0x83, &byte);
+ Status |= VL53L0_WrByte(Dev, 0x83, byte & 0xfb);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x00);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev,
+ ModuleId, ModuleId);
+
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev,
+ Revision, Revision);
+
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadCount,
+ ReferenceSpadCount);
+
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadType,
+ ReferenceSpadType);
+
+ ProductId_tmp = VL53L010_GETDEVICESPECIFICPARAMETER(Dev,
+ ProductId);
+ VL53L0_COPYSTRING(ProductId_tmp, ProductId);
+
+ VL53L010_SETDEVICESPECIFICPARAMETER(Dev,
+ ReadDataFromDeviceDone,
+ 1);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+uint32_t VL53L010_isqrt(uint32_t num)
+{
+
+ /*
+ * Implements an integer square root
+ *
+ * From: http://en.wikipedia.org/wiki/Methods_of_computing_square_roots
+ */
+
+ uint32_t res = 0;
+ uint32_t bit = 1 << 30;
+ /* The second-to-top bit is set: 1 << 14 for
+ * 16-bits, 1 << 30 for 32 bits
+ */
+ /* "bit" starts at the highest power of four <= the argument. */
+ while (bit > num)
+ bit >>= 2;
+
+ while (bit != 0) {
+ if (num >= res + bit) {
+ num -= res + bit;
+ res = (res >> 1) + bit;
+ } else
+ res >>= 1;
+
+ bit >>= 2;
+ }
+
+ return res;
+}
+
+VL53L0_Error VL53L010_device_read_strobe(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t strobe;
+ uint32_t LoopNb;
+
+ LOG_FUNCTION_START("");
+
+ Status |= VL53L0_WrByte(Dev, 0x83, 0x00);
+
+ /* polling use timeout to avoid deadlock */
+ if (Status == VL53L0_ERROR_NONE) {
+ LoopNb = 0;
+ do {
+ Status = VL53L0_RdByte(Dev, 0x83, &strobe);
+ if ((strobe != 0x00) || Status != VL53L0_ERROR_NONE)
+ break;
+
+ LoopNb = LoopNb + 1;
+ } while (LoopNb < VL53L0_DEFAULT_MAX_LOOP);
+
+ if (LoopNb >= VL53L0_DEFAULT_MAX_LOOP)
+ Status = VL53L0_ERROR_TIME_OUT;
+
+ }
+
+ Status |= VL53L0_WrByte(Dev, 0x83, 0x01);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
+
+uint32_t VL53L010_quadrature_sum(uint32_t a, uint32_t b)
+{
+ /*
+ * Implements a quadrature sum
+ *
+ * rea = sqrt(a^2 + b^2)
+ *
+ * Trap overflow case max input value is 65535 (16-bit value)
+ * as internal calc are 32-bit wide
+ *
+ * If overflow then seta output to maximum
+ */
+ uint32_t res = 0;
+
+ if (a > 65535 || b > 65535)
+ res = 65535;
+ else
+ res = VL53L010_isqrt(a * a + b * b);
+
+ return res;
+}
+
+VL53L0_Error VL53L010_get_jmp_vcsel_ambient_rate(VL53L0_DEV Dev,
+ uint32_t *pAmbient_rate_kcps,
+ uint32_t *pVcsel_rate_kcps,
+ uint32_t *
+ pSignalTotalEventsRtn)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t encodedTimeOut;
+
+ uint32_t total_periods_elapsed_rtn__macrop = 0;
+ uint32_t result_core__total_periods_elapsed_rtn = 0;
+ uint32_t rngb1_config__timeout__macrop = 0;
+ uint32_t rngb2_config__timeout__macrop = 0;
+ uint32_t result_core__ambient_window_events_rtn = 0;
+ uint32_t result_core__signal_total_events_rtn = 0;
+ uint8_t last_woi_period;
+ uint8_t rnga_config__vcsel_period;
+ uint8_t rngb1_config__vcsel_period;
+ uint8_t rngb2_config__vcsel_period;
+ uint8_t global_config__vcsel_width;
+
+ uint32_t ambient_duration_us = 0;
+ uint32_t vcsel_duration_us = 0;
+
+ uint32_t pll_period_us = 0;
+
+ LOG_FUNCTION_START("");
+
+ /* read the following */
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_RdDWord(Dev, 0xC8,
+ &result_core__total_periods_elapsed_rtn);
+ Status |= VL53L0_RdDWord(Dev, 0xF0, &pll_period_us);
+ Status |= VL53L0_RdDWord(Dev, 0xbc,
+ &result_core__ambient_window_events_rtn);
+ Status |= VL53L0_RdDWord(Dev, 0xc4,
+ &result_core__signal_total_events_rtn);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ result_core__total_periods_elapsed_rtn =
+ (int32_t) (result_core__total_periods_elapsed_rtn &
+ 0x00ffffff);
+ pll_period_us = (int32_t) (pll_period_us & 0x3ffff);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdWord(Dev, VL53L010_REG_RNGB1_TIMEOUT_MSB,
+ &encodedTimeOut);
+ if (Status == VL53L0_ERROR_NONE)
+ rngb1_config__timeout__macrop =
+ VL53L010_decode_timeout(encodedTimeOut) - 1;
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status =
+ VL53L0_RdByte(Dev, VL53L010_REG_RNGA_CONFIG_VCSEL_PERIOD,
+ &rnga_config__vcsel_period);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_RNGB1_CONFIG_VCSEL_PERIOD,
+ &rngb1_config__vcsel_period);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdByte(Dev,
+ VL53L010_REG_RNGB2_CONFIG_VCSEL_PERIOD,
+ &rngb2_config__vcsel_period);
+ }
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_RdByte(Dev, 0x32, &global_config__vcsel_width);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdWord(Dev, VL53L010_REG_RNGB2_TIMEOUT_MSB,
+ &encodedTimeOut);
+ if (Status == VL53L0_ERROR_NONE)
+ rngb2_config__timeout__macrop =
+ VL53L010_decode_timeout(encodedTimeOut) - 1;
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ total_periods_elapsed_rtn__macrop =
+ result_core__total_periods_elapsed_rtn + 1;
+
+ if (result_core__total_periods_elapsed_rtn ==
+ rngb1_config__timeout__macrop) {
+ last_woi_period = rngb1_config__vcsel_period;
+ } else if (result_core__total_periods_elapsed_rtn ==
+ rngb2_config__timeout__macrop) {
+ last_woi_period = rngb2_config__vcsel_period;
+ } else {
+ last_woi_period = rnga_config__vcsel_period;
+
+ }
+ /* 512 = 1<<9 ==> 24-9=15 */
+ ambient_duration_us = last_woi_period *
+ total_periods_elapsed_rtn__macrop * pll_period_us;
+ ambient_duration_us = ambient_duration_us / 1000;
+
+ if (ambient_duration_us != 0) {
+ *pAmbient_rate_kcps = ((1 << 15) *
+ result_core__ambient_window_events_rtn)
+ / ambient_duration_us;
+ } else {
+ Status = VL53L0_ERROR_DIVISION_BY_ZERO;
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+
+ /* 2048 = 1<<11 ==> 24-11=13 */
+ vcsel_duration_us =
+ (10 * global_config__vcsel_width + 4)
+ * total_periods_elapsed_rtn__macrop * pll_period_us;
+ vcsel_duration_us = vcsel_duration_us / 10000;
+
+ if (vcsel_duration_us != 0) {
+ *pVcsel_rate_kcps = ((1 << 13) *
+ result_core__signal_total_events_rtn)
+ / vcsel_duration_us;
+ *pSignalTotalEventsRtn =
+ result_core__signal_total_events_rtn;
+ } else {
+ Status = VL53L0_ERROR_DIVISION_BY_ZERO;
+ }
+
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
+
+VL53L0_Error VL53L010_calc_sigma_estimate(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t
+ *pRangingMeasurementData,
+ FixPoint1616_t *pSigmaEstimate)
+{
+ /* Expressed in 100ths of a ns, i.e. centi-ns */
+ const uint32_t cPulseEffectiveWidth_centi_ns = 800;
+ /* Expressed in 100ths of a ns, i.e. centi-ns */
+ const uint32_t cAmbientEffectiveWidth_centi_ns = 600;
+ const FixPoint1616_t cSigmaEstRef = 0x00000042;
+ /* pico secs */
+ const uint32_t cVcselPulseWidth_ps = 4700;
+ const FixPoint1616_t cSigmaEstMax = 0x028F87AE;
+ /* Time Of Flight per mm (6.6 pico secs) */
+ const FixPoint1616_t cTOF_per_mm_ps = 0x0006999A;
+ const uint32_t c16BitRoundingParam = 0x00008000;
+ const FixPoint1616_t cMaxXTalk_kcps = 0x00320000;
+
+ uint32_t signalTotalEventsRtn;
+ FixPoint1616_t sigmaEstimateP1;
+ FixPoint1616_t sigmaEstimateP2;
+ FixPoint1616_t sigmaEstimateP3;
+ FixPoint1616_t deltaT_ps;
+ FixPoint1616_t pwMult;
+ FixPoint1616_t sigmaEstRtn;
+ FixPoint1616_t sigmaEstimate;
+ FixPoint1616_t xTalkCorrection;
+ uint32_t signalTotalEventsRtnRawVal;
+ FixPoint1616_t ambientRate_kcps;
+ FixPoint1616_t vcselRate_kcps;
+ FixPoint1616_t xTalkCompRate_mcps;
+ uint32_t xTalkCompRate_kcps;
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ FixPoint1616_t diff1_mcps;
+ FixPoint1616_t diff2_mcps;
+ FixPoint1616_t sqr1;
+ FixPoint1616_t sqr2;
+ FixPoint1616_t sqrSum;
+ FixPoint1616_t sqrtResult_centi_ns;
+ FixPoint1616_t sqrtResult;
+
+ /*! \addtogroup calc_sigma_estimate
+ * @{
+ *
+ * Estimates the range sigma based on the
+ *
+ * - vcsel_rate_kcps
+ * - ambient_rate_kcps
+ * - signal_total_events
+ * - xtalk_rate
+ *
+ * and the following parameters
+ *
+ * - SigmaEstRefArray
+ * - SigmaEstEffPulseWidth
+ * - SigmaEstEffAmbWidth
+ */
+
+ LOG_FUNCTION_START("");
+
+ VL53L010_GETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps,
+ xTalkCompRate_mcps);
+ /*
+ * We work in kcps rather than mcps as this helps keep
+ * within the confines of the 32 Fix1616 type.
+ */
+
+ xTalkCompRate_kcps = xTalkCompRate_mcps * 1000;
+ if (xTalkCompRate_kcps > cMaxXTalk_kcps)
+ xTalkCompRate_kcps = cMaxXTalk_kcps;
+
+ Status = VL53L010_get_jmp_vcsel_ambient_rate(Dev,
+ &ambientRate_kcps,
+ &vcselRate_kcps,
+ &signalTotalEventsRtnRawVal);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (vcselRate_kcps == 0) {
+ Status = VL53L0_ERROR_DIVISION_BY_ZERO;
+ } else {
+ signalTotalEventsRtn = signalTotalEventsRtnRawVal;
+ if (signalTotalEventsRtn < 1)
+ signalTotalEventsRtn = 1;
+
+ /*
+ * Calculate individual components of the main
+ * equation - replicating the equation implemented in
+ * the script OpenAll_Ewok_ranging_data.jsl.
+ *
+ * sigmaEstimateP1 represents the effective pulse width,
+ * which is a tuning parameter, rather than a real
+ * value.
+ *
+ * sigmaEstimateP2 represents the ambient/signal rate
+ * ratio expressed as a multiple of the effective
+ * ambient width (tuning parameter).
+ *
+ * sigmaEstimateP3 provides the signal event component,
+ * with the knowledge that
+ * - Noise of a square pulse is 1/sqrt(12) of the
+ * pulse width.
+ * - at 0Lux, sigma is proportional to
+ * effectiveVcselPulseWidth /
+ * sqrt(12 * signalTotalEvents)
+ *
+ * deltaT_ps represents the time of flight in pico secs
+ * for the current range measurement, using the
+ * "TOF per mm" constant (in ps).
+ */
+
+ sigmaEstimateP1 = cPulseEffectiveWidth_centi_ns;
+
+ /*
+ * ((FixPoint1616 << 16)* uint32)/FixPoint1616 =
+ * FixPoint1616
+ */
+ sigmaEstimateP2 = (ambientRate_kcps << 16) /
+ vcselRate_kcps;
+ sigmaEstimateP2 *= cAmbientEffectiveWidth_centi_ns;
+
+ sigmaEstimateP3 = 2 *
+ VL53L010_isqrt(signalTotalEventsRtn * 12);
+
+ /* uint32 * FixPoint1616 = FixPoint1616 */
+ deltaT_ps =
+ pRangingMeasurementData->RangeMilliMeter *
+ cTOF_per_mm_ps;
+
+ /*
+ * vcselRate - xtalkCompRate
+ * (uint32 << 16) - FixPoint1616 = FixPoint1616.
+ * Divide result by 1000 to convert to mcps.
+ * 500 is added to ensure rounding when integer
+ * division truncates.
+ */
+ diff1_mcps = (((vcselRate_kcps << 16) -
+ xTalkCompRate_kcps) + 500) / 1000;
+
+ /* vcselRate + xtalkCompRate */
+ diff2_mcps = (((vcselRate_kcps << 16) +
+ xTalkCompRate_kcps) + 500) / 1000;
+
+ /* Shift by 12 bits to increase resolution prior to the
+ * division
+ */
+ diff1_mcps <<= 12;
+
+ /* FixPoint0428/FixPoint1616 = FixPoint2012 */
+ xTalkCorrection = abs(diff1_mcps / diff2_mcps);
+
+ /* FixPoint2012 << 4 = FixPoint1616 */
+ xTalkCorrection <<= 4;
+
+ /* FixPoint1616/uint32 = FixPoint1616 */
+ pwMult = deltaT_ps / cVcselPulseWidth_ps;
+ /* smaller than 1.0f */
+
+ /*
+ * FixPoint1616 * FixPoint1616 = FixPoint3232, however
+ * both values are small enough such that32 bits will
+ * not be exceeded.
+ */
+ pwMult *= ((1 << 16) - xTalkCorrection);
+
+ /* (FixPoint3232 >> 16) = FixPoint1616 */
+ pwMult = (pwMult + c16BitRoundingParam) >> 16;
+
+ /* FixPoint1616 + FixPoint1616 = FixPoint1616 */
+ pwMult += (1 << 16);
+
+ /*
+ * At this point the value will be 1.xx, therefore if we
+ * square the value this will exceed 32 bits. To address
+ * this perform a single shift to the right before the
+ * multiplication.
+ */
+ pwMult >>= 1;
+ /* FixPoint1715 * FixPoint1715 = FixPoint3430 */
+ pwMult = pwMult * pwMult;
+
+ /* (FixPoint3430 >> 14) = Fix1616 */
+ pwMult >>= 14;
+
+ /* FixPoint1616 * FixPoint1616 = FixPoint3232 */
+ sqr1 = pwMult * sigmaEstimateP1;
+
+ /* (FixPoint1616 >> 12) = FixPoint2804 */
+ sqr1 = (sqr1 + 0x800) >> 12;
+
+ /* FixPoint2804 * FixPoint2804 = FixPoint5608 */
+ sqr1 *= sqr1;
+
+ sqr2 = sigmaEstimateP2;
+
+ /* (FixPoint1616 >> 12) = FixPoint2804 */
+ sqr2 = (sqr2 + 0x800) >> 12;
+
+ /* FixPoint2804 * FixPoint2804 = FixPoint5608 */
+ sqr2 *= sqr2;
+
+ /* FixPoint5608 + FixPoint5608 = FixPoint5608 */
+ sqrSum = sqr1 + sqr2;
+
+ /* SQRT(FixPoint5608) = FixPoint2804 */
+ sqrtResult_centi_ns = VL53L010_isqrt(sqrSum);
+
+ /* (FixPoint2804 << 12) = FixPoint1616 */
+ sqrtResult_centi_ns <<= 12;
+
+ /*
+ * Note that the Speed Of Light is expressed in um
+ * per 1E-10 seconds (2997). Therefore to get mm/ns
+ * we have to divide by 10000
+ */
+ sigmaEstRtn =
+ ((sqrtResult_centi_ns + 50) / 100 *
+ VL53L010_SPEED_OF_LIGHT_IN_AIR);
+ sigmaEstRtn /= (sigmaEstimateP3);
+ /* Add 5000 before dividing by 10000 to ensure
+ * rounding.
+ */
+ sigmaEstRtn += 5000;
+ sigmaEstRtn /= 10000;
+
+ /* FixPoint1616 * FixPoint1616 = FixPoint3232 */
+ sqr1 = sigmaEstRtn * sigmaEstRtn;
+ /* FixPoint1616 * FixPoint1616 = FixPoint3232 */
+ sqr2 = cSigmaEstRef * cSigmaEstRef;
+
+ /* sqrt(FixPoint3232 << 12) = FixPoint1022 */
+ sqrtResult = VL53L010_isqrt((sqr1 + sqr2) << 12);
+ sqrtResult = (sqrtResult + 0x20) >> 6;
+ /*
+ * Note that the Shift by 12bits increases resolution
+ * prior to the sqrt, therefore the result must be
+ * shifted by 6bits to the right to revert back to the
+ * FixPoint1616 format.
+ */
+
+ sigmaEstimate = 1000 * sqrtResult;
+
+ if ((vcselRate_kcps < 1) ||
+ (signalTotalEventsRtn < 1) ||
+ (sigmaEstimate > cSigmaEstMax)) {
+ sigmaEstimate = cSigmaEstMax;
+ }
+
+ *pSigmaEstimate = (uint32_t) (sigmaEstimate);
+ PALDevDataSet(Dev, SigmaEstimate, *pSigmaEstimate);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L010_get_pal_range_status(VL53L0_DEV Dev,
+ uint8_t DeviceRangeStatus,
+ FixPoint1616_t SignalRate,
+ FixPoint1616_t CrosstalkCompensation,
+ uint16_t EffectiveSpadRtnCount,
+ VL53L0_RangingMeasurementData_t *
+ pRangingMeasurementData,
+ uint8_t *pPalRangeStatus)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t tmpByte;
+ uint8_t SigmaLimitCheckEnable;
+ uint8_t SignalLimitCheckEnable;
+ FixPoint1616_t SigmaEstimate;
+ FixPoint1616_t SignalEstimate;
+ FixPoint1616_t SigmaLimitValue;
+ FixPoint1616_t SignalLimitValue;
+ uint8_t DeviceRangeStatusInternal = 0;
+
+ LOG_FUNCTION_START("");
+
+ /*
+ * VL53L0 has a good ranging when the value of the
+ * DeviceRangeStatus = 11. This function will replace
+ * the value 0 with the value 11 in the DeviceRangeStatus.
+ * In addition, the SigmaEstimator is not included in the
+ * VL53L0 DeviceRangeStatus, this will be added in the
+ * PalRangeStatus.
+ */
+
+ DeviceRangeStatusInternal = ((DeviceRangeStatus & 0x78) >> 3);
+
+ if (DeviceRangeStatusInternal == 11)
+ tmpByte = 0;
+ else if (DeviceRangeStatusInternal == 0)
+ tmpByte = 11;
+ else
+ tmpByte = DeviceRangeStatusInternal;
+
+ /*
+ * Check if Sigma limit is enabled, if yes then do comparison with
+ * limit value and put the result back into pPalRangeStatus.
+ */
+ Status = VL53L010_GetLimitCheckEnable(Dev,
+ VL53L010_CHECKENABLE_SIGMA_FINAL_RANGE,
+ &SigmaLimitCheckEnable);
+
+ if ((SigmaLimitCheckEnable != 0) && (Status == VL53L0_ERROR_NONE)) {
+ /*
+ * compute the Sigma and check with limit
+ */
+ Status = VL53L010_calc_sigma_estimate(Dev,
+ pRangingMeasurementData,
+ &SigmaEstimate);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L010_GetLimitCheckValue(Dev,
+ VL53L010_CHECKENABLE_SIGMA_FINAL_RANGE,
+ &SigmaLimitValue);
+
+ if ((SigmaLimitValue > 0) &&
+ (SigmaEstimate > SigmaLimitValue)) {
+ /* Limit Fail add 2^4 to range status */
+ tmpByte += 16;
+ }
+ }
+ }
+
+ /*
+ * Check if Signal limit is enabled, if yes then do comparison with
+ * limit value and put the result back into pPalRangeStatus.
+ */
+ Status = VL53L010_GetLimitCheckEnable(Dev,
+ VL53L010_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ &SignalLimitCheckEnable);
+
+ if ((SignalLimitCheckEnable != 0) && (Status == VL53L0_ERROR_NONE)) {
+ /*
+ * compute the Signal and check with limit
+ */
+
+ SignalEstimate = (FixPoint1616_t) (SignalRate -
+ (FixPoint1616_t)
+ ((EffectiveSpadRtnCount * CrosstalkCompensation) >> 1));
+
+ PALDevDataSet(Dev, SignalEstimate, SignalEstimate);
+
+ Status = VL53L010_GetLimitCheckValue(Dev,
+ VL53L010_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ &SignalLimitValue);
+
+ if ((SignalLimitValue > 0) && (SignalEstimate <
+ SignalLimitValue)) {
+ /* Limit Fail add 2^5 to range status */
+ tmpByte += 32;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ *pPalRangeStatus = tmpByte;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
diff --git a/drivers/input/misc/vl53L0/src/vl53l010_tuning.c b/drivers/input/misc/vl53L0/src/vl53l010_tuning.c
new file mode 100644
index 000000000000..ee3f57872ffc
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l010_tuning.c
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+ IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#include "vl53l010_tuning.h"
+
+#define LOG_FUNCTION_START(fmt, ...) \
+ _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
+#define LOG_FUNCTION_END(status, ...) \
+ _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
+#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
+ _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
+
+#ifdef VL53L0_LOG_ENABLE
+#define trace_print(level, ...) \
+ trace_print_module_function(TRACE_MODULE_API,\
+ level, TRACE_FUNCTION_NONE, ##__VA_ARGS__)
+#endif
+
+/*
+ * //////////////////////////////////////////////////////
+ * //// DEFAULT TUNING SETTINGS ////
+ * //////////////////////////////////////////////////////
+ */
+VL53L0_Error VL53L010_load_tuning_settings(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ /* update 14_12_15_v11 */
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x91, 0x3C);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x54, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x33, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x32, 0x03);
+ Status |= VL53L0_WrByte(Dev, 0x30, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x50, 0x05);
+ Status |= VL53L0_WrByte(Dev, 0x60, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x70, 0x06);
+
+ Status |= VL53L0_WrByte(Dev, 0x46, 0x1a);
+ Status |= VL53L0_WrWord(Dev, 0x51, 0x01a3);
+ Status |= VL53L0_WrWord(Dev, 0x61, 0x01c4);
+ Status |= VL53L0_WrWord(Dev, 0x71, 0x018c);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x31, 0x0f);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x66, 0x38);
+
+ Status |= VL53L0_WrByte(Dev, 0x47, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x48, 0xff);
+ Status |= VL53L0_WrByte(Dev, 0x57, 0x4c);
+ Status |= VL53L0_WrByte(Dev, 0x67, 0x3c);
+ Status |= VL53L0_WrByte(Dev, 0x77, 0x5c);
+
+ Status |= VL53L0_WrWord(Dev, 0x44, 0x0000);
+
+ Status |= VL53L0_WrByte(Dev, 0x27, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x55, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x30, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0x10, 0x0f);
+ Status |= VL53L0_WrByte(Dev, 0x11, 0xff);
+ Status |= VL53L0_WrByte(Dev, 0x40, 0x82);
+ Status |= VL53L0_WrByte(Dev, 0x41, 0xff);
+ Status |= VL53L0_WrByte(Dev, 0x42, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0x43, 0x12);
+
+ Status |= VL53L0_WrByte(Dev, 0x20, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x21, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0x28, 0x06);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x48, 0x28);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0x7a, 0x0a);
+ Status |= VL53L0_WrByte(Dev, 0x7b, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x78, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x44, 0xff);
+ Status |= VL53L0_WrByte(Dev, 0x45, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x46, 0x10);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0x04, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x05, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x06, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x07, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x0d, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x01, 0xF8);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x8e, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ if (Status != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
diff --git a/drivers/input/misc/vl53L0/src/vl53l0_api.c b/drivers/input/misc/vl53L0/src/vl53l0_api.c
new file mode 100644
index 000000000000..f9c2c2a4b7b7
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l0_api.c
@@ -0,0 +1,3109 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+ IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#include "vl53l0_api.h"
+#include "vl53l0_tuning.h"
+#include "vl53l0_interrupt_threshold_settings.h"
+#include "vl53l0_api_core.h"
+#include "vl53l0_api_histogram.h"
+#include "vl53l0_api_calibration.h"
+#include "vl53l0_api_strings.h"
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#endif
+#define LOG_FUNCTION_START(fmt, ...) \
+ _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
+#define LOG_FUNCTION_END(status, ...) \
+ _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
+#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
+ _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
+
+#ifdef VL53L0_LOG_ENABLE
+#define trace_print(level, ...) trace_print_module_function(TRACE_MODULE_API, \
+ level, TRACE_FUNCTION_NONE, ##__VA_ARGS__)
+#endif
+
+/* Group PAL General Functions */
+
+VL53L0_Error VL53L0_GetVersion(VL53L0_Version_t *pVersion)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ pVersion->major = VL53L0_IMPLEMENTATION_VER_MAJOR;
+ pVersion->minor = VL53L0_IMPLEMENTATION_VER_MINOR;
+ pVersion->build = VL53L0_IMPLEMENTATION_VER_SUB;
+
+ pVersion->revision = VL53L0_IMPLEMENTATION_VER_REVISION;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetPalSpecVersion(VL53L0_Version_t *pPalSpecVersion)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ pPalSpecVersion->major = VL53L0_SPECIFICATION_VER_MAJOR;
+ pPalSpecVersion->minor = VL53L0_SPECIFICATION_VER_MINOR;
+ pPalSpecVersion->build = VL53L0_SPECIFICATION_VER_SUB;
+
+ pPalSpecVersion->revision = VL53L0_SPECIFICATION_VER_REVISION;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetProductRevision(VL53L0_DEV Dev,
+ uint8_t *pProductRevisionMajor, uint8_t *pProductRevisionMinor)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t revision_id;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_IDENTIFICATION_REVISION_ID,
+ &revision_id);
+ *pProductRevisionMajor = 1;
+ *pProductRevisionMinor = (revision_id & 0xF0) >> 4;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
+
+VL53L0_Error VL53L0_GetDeviceInfo(VL53L0_DEV Dev,
+ VL53L0_DeviceInfo_t *pVL53L0_DeviceInfo)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_device_info(Dev, pVL53L0_DeviceInfo);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetDeviceErrorStatus(VL53L0_DEV Dev,
+ VL53L0_DeviceError *pDeviceErrorStatus)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t RangeStatus;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_RESULT_RANGE_STATUS,
+ &RangeStatus);
+
+ *pDeviceErrorStatus = (VL53L0_DeviceError)((RangeStatus & 0x78) >> 3);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_GetDeviceErrorString(VL53L0_DeviceError ErrorCode,
+ char *pDeviceErrorString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_device_error_string(ErrorCode, pDeviceErrorString);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetRangeStatusString(uint8_t RangeStatus,
+ char *pRangeStatusString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_range_status_string(RangeStatus,
+ pRangeStatusString);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetPalErrorString(VL53L0_Error PalErrorCode,
+ char *pPalErrorString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_pal_error_string(PalErrorCode, pPalErrorString);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetPalStateString(VL53L0_State PalStateCode,
+ char *pPalStateString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_pal_state_string(PalStateCode, pPalStateString);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetPalState(VL53L0_DEV Dev, VL53L0_State *pPalState)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pPalState = PALDevDataGet(Dev, PalState);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetPowerMode(VL53L0_DEV Dev, VL53L0_PowerModes PowerMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ /* Only level1 of Power mode exists */
+ if ((PowerMode != VL53L0_POWERMODE_STANDBY_LEVEL1)
+ && (PowerMode != VL53L0_POWERMODE_IDLE_LEVEL1)) {
+ Status = VL53L0_ERROR_MODE_NOT_SUPPORTED;
+ } else if (PowerMode == VL53L0_POWERMODE_STANDBY_LEVEL1) {
+ /* set the standby level1 of power mode */
+ Status = VL53L0_WrByte(Dev, 0x80, 0x00);
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Set PAL State to standby */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_STANDBY);
+ PALDevDataSet(Dev, PowerMode,
+ VL53L0_POWERMODE_STANDBY_LEVEL1);
+ }
+
+ } else {
+ /* VL53L0_POWERMODE_IDLE_LEVEL1 */
+ Status = VL53L0_WrByte(Dev, 0x80, 0x00);
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_StaticInit(Dev);
+
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, PowerMode,
+ VL53L0_POWERMODE_IDLE_LEVEL1);
+
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetPowerMode(VL53L0_DEV Dev, VL53L0_PowerModes *pPowerMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ /* Only level1 of Power mode exists */
+ Status = VL53L0_RdByte(Dev, 0x80, &Byte);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Byte == 1) {
+ PALDevDataSet(Dev, PowerMode,
+ VL53L0_POWERMODE_IDLE_LEVEL1);
+ } else {
+ PALDevDataSet(Dev, PowerMode,
+ VL53L0_POWERMODE_STANDBY_LEVEL1);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetOffsetCalibrationDataMicroMeter(VL53L0_DEV Dev,
+ int32_t OffsetCalibrationDataMicroMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_set_offset_calibration_data_micro_meter(Dev,
+ OffsetCalibrationDataMicroMeter);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetOffsetCalibrationDataMicroMeter(VL53L0_DEV Dev,
+ int32_t *pOffsetCalibrationDataMicroMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_offset_calibration_data_micro_meter(Dev,
+ pOffsetCalibrationDataMicroMeter);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetLinearityCorrectiveGain(VL53L0_DEV Dev,
+ int16_t LinearityCorrectiveGain)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ if ((LinearityCorrectiveGain < 0) || (LinearityCorrectiveGain > 1000))
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ else {
+ PALDevDataSet(Dev, LinearityCorrectiveGain,
+ LinearityCorrectiveGain);
+
+ if (LinearityCorrectiveGain != 1000) {
+ /* Disable FW Xtalk */
+ Status = VL53L0_WrWord(Dev,
+ VL53L0_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, 0);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetLinearityCorrectiveGain(VL53L0_DEV Dev,
+ uint16_t *pLinearityCorrectiveGain)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pLinearityCorrectiveGain = PALDevDataGet(Dev, LinearityCorrectiveGain);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetGroupParamHold(VL53L0_DEV Dev, uint8_t GroupParamHold)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented on VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetUpperLimitMilliMeter(VL53L0_DEV Dev,
+ uint16_t *pUpperLimitMilliMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented on VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetTotalSignalRate(VL53L0_DEV Dev,
+ FixPoint1616_t *pTotalSignalRate)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_RangingMeasurementData_t LastRangeDataBuffer;
+
+ LOG_FUNCTION_START("");
+
+ LastRangeDataBuffer = PALDevDataGet(Dev, LastRangeMeasure);
+
+ Status = VL53L0_get_total_signal_rate(
+ Dev, &LastRangeDataBuffer, pTotalSignalRate);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* End Group PAL General Functions */
+
+/* Group PAL Init Functions */
+VL53L0_Error VL53L0_SetDeviceAddress(VL53L0_DEV Dev, uint8_t DeviceAddress)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_I2C_SLAVE_DEVICE_ADDRESS,
+ DeviceAddress / 2);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_DataInit(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters;
+ int i;
+ uint8_t StopVariable;
+
+ LOG_FUNCTION_START("");
+
+ /* by default the I2C is running at 1V8 if you want to change it you
+ * need to include this define at compilation level.
+ */
+#ifdef USE_I2C_2V8
+ Status = VL53L0_UpdateByte(Dev,
+ VL53L0_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV,
+ 0xFE,
+ 0x01);
+#endif
+
+ /* Set I2C standard mode */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, 0x88, 0x00);
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev, ReadDataFromDeviceDone, 0);
+
+#ifdef USE_IQC_STATION
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_apply_offset_adjustment(Dev);
+#endif
+
+ /* Default value is 1000 for Linearity Corrective Gain */
+ PALDevDataSet(Dev, LinearityCorrectiveGain, 1000);
+
+ /* Dmax default Parameter */
+ PALDevDataSet(Dev, DmaxCalRangeMilliMeter, 400);
+ PALDevDataSet(Dev, DmaxCalSignalRateRtnMegaCps,
+ (FixPoint1616_t)((0x00016B85))); /* 1.42 No Cover Glass*/
+
+ /* Set Default static parameters
+ *set first temporary values 9.44MHz * 65536 = 618660
+ */
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev, OscFrequencyMHz, 618660);
+
+ /* Set Default XTalkCompensationRateMegaCps to 0 */
+ VL53L0_SETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps, 0);
+
+ /* Get default parameters */
+ Status = VL53L0_GetDeviceParameters(Dev, &CurrentParameters);
+ if (Status == VL53L0_ERROR_NONE) {
+ /* initialize PAL values */
+ CurrentParameters.DeviceMode = VL53L0_DEVICEMODE_SINGLE_RANGING;
+ CurrentParameters.HistogramMode = VL53L0_HISTOGRAMMODE_DISABLED;
+ PALDevDataSet(Dev, CurrentParameters, CurrentParameters);
+ }
+
+ /* Sigma estimator variable */
+ PALDevDataSet(Dev, SigmaEstRefArray, 100);
+ PALDevDataSet(Dev, SigmaEstEffPulseWidth, 900);
+ PALDevDataSet(Dev, SigmaEstEffAmbWidth, 500);
+ PALDevDataSet(Dev, targetRefRate, 0x0A00); /* 20 MCPS in 9:7 format */
+
+ /* Use internal default settings */
+ PALDevDataSet(Dev, UseInternalTuningSettings, 1);
+
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+ Status |= VL53L0_RdByte(Dev, 0x91, &StopVariable);
+ PALDevDataSet(Dev, StopVariable, StopVariable);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x00);
+
+ /* Enable all check */
+ for (i = 0; i < VL53L0_CHECKENABLE_NUMBER_OF_CHECKS; i++) {
+ if (Status == VL53L0_ERROR_NONE)
+ Status |= VL53L0_SetLimitCheckEnable(Dev, i, 1);
+ else
+ break;
+
+ }
+
+ /* Disable the following checks */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP, 0);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_MSRC, 0);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_PRE_RANGE, 0);
+
+ /* Limit default values */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_SetLimitCheckValue(Dev,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ (FixPoint1616_t)(18 * 65536));
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_SetLimitCheckValue(Dev,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ (FixPoint1616_t)(25 * 65536 / 100));
+ /* 0.25 * 65536 */
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_SetLimitCheckValue(Dev,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP,
+ (FixPoint1616_t)(35 * 65536));
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_SetLimitCheckValue(Dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ (FixPoint1616_t)(0 * 65536));
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+
+ PALDevDataSet(Dev, SequenceConfig, 0xFF);
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG,
+ 0xFF);
+
+ /* Set PAL state to tell that we are waiting for call to
+ * VL53L0_StaticInit
+ */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_WAIT_STATICINIT);
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev, RefSpadsInitialised, 0);
+
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetTuningSettingBuffer(VL53L0_DEV Dev,
+ uint8_t *pTuningSettingBuffer, uint8_t UseInternalTuningSettings)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ if (UseInternalTuningSettings == 1) {
+ /* Force use internal settings */
+ PALDevDataSet(Dev, UseInternalTuningSettings, 1);
+ } else {
+
+ /* check that the first byte is not 0 */
+ if (*pTuningSettingBuffer != 0) {
+ PALDevDataSet(Dev, pTuningSettingsPointer,
+ pTuningSettingBuffer);
+ PALDevDataSet(Dev, UseInternalTuningSettings, 0);
+
+ } else {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetTuningSettingBuffer(VL53L0_DEV Dev,
+ uint8_t **ppTuningSettingBuffer, uint8_t *pUseInternalTuningSettings)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *ppTuningSettingBuffer = PALDevDataGet(Dev, pTuningSettingsPointer);
+ *pUseInternalTuningSettings = PALDevDataGet(Dev,
+ UseInternalTuningSettings);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_StaticInit(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceParameters_t CurrentParameters = {0};
+ uint8_t *pTuningSettingBuffer;
+ uint16_t tempword = 0;
+ uint8_t tempbyte = 0;
+ uint8_t UseInternalTuningSettings = 0;
+ uint32_t count = 0;
+ uint8_t isApertureSpads = 0;
+ uint32_t refSpadCount = 0;
+ uint8_t ApertureSpads = 0;
+ uint8_t vcselPulsePeriodPCLK;
+ FixPoint1616_t seqTimeoutMilliSecs;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_info_from_device(Dev, 1);
+
+ /* set the ref spad from NVM */
+ count = (uint32_t)VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadCount);
+ ApertureSpads = VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadType);
+
+ /* NVM value invalid */
+ if ((ApertureSpads > 1) ||
+ ((ApertureSpads == 1) && (count > 32)) ||
+ ((ApertureSpads == 0) && (count > 12)))
+ Status = VL53L0_perform_ref_spad_management(Dev, &refSpadCount,
+ &isApertureSpads);
+ else
+ Status = VL53L0_set_reference_spads(Dev, count, ApertureSpads);
+
+
+ /* Initialize tuning settings buffer to prevent compiler warning. */
+ pTuningSettingBuffer = DefaultTuningSettings;
+
+ if (Status == VL53L0_ERROR_NONE) {
+ UseInternalTuningSettings = PALDevDataGet(Dev,
+ UseInternalTuningSettings);
+
+ if (UseInternalTuningSettings == 0)
+ pTuningSettingBuffer = PALDevDataGet(Dev,
+ pTuningSettingsPointer);
+ else
+ pTuningSettingBuffer = DefaultTuningSettings;
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_load_tuning_settings(Dev, pTuningSettingBuffer);
+
+
+ /* Set interrupt config to new sample ready */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_SetGpioConfig(Dev, 0, 0,
+ VL53L0_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY,
+ VL53L0_INTERRUPTPOLARITY_LOW);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_RdWord(Dev, 0x84, &tempword);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev, OscFrequencyMHz,
+ VL53L0_FIXPOINT412TOFIXPOINT1616(tempword));
+ }
+
+ /* After static init, some device parameters may be changed,
+ * so update them
+ */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetDeviceParameters(Dev, &CurrentParameters);
+
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetFractionEnable(Dev, &tempbyte);
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, RangeFractionalEnable, tempbyte);
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, CurrentParameters, CurrentParameters);
+
+
+ /* read the sequence config and save it */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdByte(Dev,
+ VL53L0_REG_SYSTEM_SEQUENCE_CONFIG, &tempbyte);
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, SequenceConfig, tempbyte);
+
+ }
+
+ /* Disable MSRC and TCC by default */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_TCC, 0);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_MSRC, 0);
+
+
+ /* Set PAL State to standby */
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_IDLE);
+
+
+
+ /* Store pre-range vcsel period */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetVcselPulsePeriod(
+ Dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ &vcselPulsePeriodPCLK);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(
+ Dev,
+ PreRangeVcselPulsePeriod,
+ vcselPulsePeriodPCLK);
+ }
+
+ /* Store final-range vcsel period */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetVcselPulsePeriod(
+ Dev,
+ VL53L0_VCSEL_PERIOD_FINAL_RANGE,
+ &vcselPulsePeriodPCLK);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(
+ Dev,
+ FinalRangeVcselPulsePeriod,
+ vcselPulsePeriodPCLK);
+ }
+
+ /* Store pre-range timeout */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetSequenceStepTimeout(
+ Dev,
+ VL53L0_SEQUENCESTEP_PRE_RANGE,
+ &seqTimeoutMilliSecs);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(
+ Dev,
+ PreRangeTimeoutMicroSecs,
+ seqTimeoutMilliSecs);
+ }
+
+ /* Store final-range timeout */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetSequenceStepTimeout(
+ Dev,
+ VL53L0_SEQUENCESTEP_FINAL_RANGE,
+ &seqTimeoutMilliSecs);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(
+ Dev,
+ FinalRangeTimeoutMicroSecs,
+ seqTimeoutMilliSecs);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_WaitDeviceBooted(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented on VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_ResetDevice(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ /* Set reset bit */
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SOFT_RESET_GO2_SOFT_RESET_N,
+ 0x00);
+
+ /* Wait for some time */
+ if (Status == VL53L0_ERROR_NONE) {
+ do {
+ Status = VL53L0_RdByte(Dev,
+ VL53L0_REG_IDENTIFICATION_MODEL_ID, &Byte);
+ } while (Byte != 0x00);
+ }
+
+ /* Release reset */
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SOFT_RESET_GO2_SOFT_RESET_N,
+ 0x01);
+
+ /* Wait until correct boot-up of the device */
+ if (Status == VL53L0_ERROR_NONE) {
+ do {
+ Status = VL53L0_RdByte(Dev,
+ VL53L0_REG_IDENTIFICATION_MODEL_ID, &Byte);
+ } while (Byte == 0x00);
+ }
+
+ /* Set PAL State to VL53L0_STATE_POWERDOWN */
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_POWERDOWN);
+
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+/* End Group PAL Init Functions */
+
+/* Group PAL Parameters Functions */
+VL53L0_Error VL53L0_SetDeviceParameters(VL53L0_DEV Dev,
+ const VL53L0_DeviceParameters_t *pDeviceParameters)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int i;
+
+ LOG_FUNCTION_START("");
+ Status = VL53L0_SetDeviceMode(Dev, pDeviceParameters->DeviceMode);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetHistogramMode(Dev,
+ pDeviceParameters->HistogramMode);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetInterMeasurementPeriodMilliSeconds(Dev,
+ pDeviceParameters->InterMeasurementPeriodMilliSeconds);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetXTalkCompensationRateMegaCps(Dev,
+ pDeviceParameters->XTalkCompensationRateMegaCps);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetOffsetCalibrationDataMicroMeter(Dev,
+ pDeviceParameters->RangeOffsetMicroMeters);
+
+
+ for (i = 0; i < VL53L0_CHECKENABLE_NUMBER_OF_CHECKS; i++) {
+ if (Status == VL53L0_ERROR_NONE)
+ Status |= VL53L0_SetLimitCheckEnable(Dev, i,
+ pDeviceParameters->LimitChecksEnable[i]);
+ else
+ break;
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status |= VL53L0_SetLimitCheckValue(Dev, i,
+ pDeviceParameters->LimitChecksValue[i]);
+ else
+ break;
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetWrapAroundCheckEnable(Dev,
+ pDeviceParameters->WrapAroundCheckEnable);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetMeasurementTimingBudgetMicroSeconds(Dev,
+ pDeviceParameters->MeasurementTimingBudgetMicroSeconds);
+
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetDeviceParameters(VL53L0_DEV Dev,
+ VL53L0_DeviceParameters_t *pDeviceParameters)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int i;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_GetDeviceMode(Dev, &(pDeviceParameters->DeviceMode));
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetHistogramMode(Dev,
+ &(pDeviceParameters->HistogramMode));
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetInterMeasurementPeriodMilliSeconds(Dev,
+ &(pDeviceParameters->InterMeasurementPeriodMilliSeconds));
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ pDeviceParameters->XTalkCompensationEnable = 0;
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetXTalkCompensationRateMegaCps(Dev,
+ &(pDeviceParameters->XTalkCompensationRateMegaCps));
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetOffsetCalibrationDataMicroMeter(Dev,
+ &(pDeviceParameters->RangeOffsetMicroMeters));
+
+
+ if (Status == VL53L0_ERROR_NONE) {
+ for (i = 0; i < VL53L0_CHECKENABLE_NUMBER_OF_CHECKS; i++) {
+ /* get first the values, then the enables.
+ * VL53L0_GetLimitCheckValue will modify the enable
+ * flags
+ */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status |= VL53L0_GetLimitCheckValue(Dev, i,
+ &(pDeviceParameters->LimitChecksValue[i]));
+ } else {
+ break;
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status |= VL53L0_GetLimitCheckEnable(Dev, i,
+ &(pDeviceParameters->LimitChecksEnable[i]));
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetWrapAroundCheckEnable(Dev,
+ &(pDeviceParameters->WrapAroundCheckEnable));
+ }
+
+ /* Need to be done at the end as it uses VCSELPulsePeriod */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetMeasurementTimingBudgetMicroSeconds(Dev,
+ &(pDeviceParameters->MeasurementTimingBudgetMicroSeconds));
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetDeviceMode(VL53L0_DEV Dev, VL53L0_DeviceModes DeviceMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("%d", (int)DeviceMode);
+
+ switch (DeviceMode) {
+ case VL53L0_DEVICEMODE_SINGLE_RANGING:
+ case VL53L0_DEVICEMODE_CONTINUOUS_RANGING:
+ case VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING:
+ case VL53L0_DEVICEMODE_SINGLE_HISTOGRAM:
+ case VL53L0_DEVICEMODE_GPIO_DRIVE:
+ case VL53L0_DEVICEMODE_GPIO_OSC:
+ /* Supported modes */
+ VL53L0_SETPARAMETERFIELD(Dev, DeviceMode, DeviceMode);
+ break;
+ default:
+ /* Unsupported mode */
+ Status = VL53L0_ERROR_MODE_NOT_SUPPORTED;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetDeviceMode(VL53L0_DEV Dev,
+ VL53L0_DeviceModes *pDeviceMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ VL53L0_GETPARAMETERFIELD(Dev, DeviceMode, *pDeviceMode);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetRangeFractionEnable(VL53L0_DEV Dev, uint8_t Enable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("%d", (int)Enable);
+
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_RANGE_CONFIG, Enable);
+
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, RangeFractionalEnable, Enable);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetFractionEnable(VL53L0_DEV Dev, uint8_t *pEnabled)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_SYSTEM_RANGE_CONFIG, pEnabled);
+
+ if (Status == VL53L0_ERROR_NONE)
+ *pEnabled = (*pEnabled & 1);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetHistogramMode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes HistogramMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("%d", (int)HistogramMode);
+
+ Status = VL53L0_set_histogram_mode(Dev, HistogramMode);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetHistogramMode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes *pHistogramMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_histogram_mode(Dev, pHistogramMode);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetMeasurementTimingBudgetMicroSeconds(VL53L0_DEV Dev,
+ uint32_t MeasurementTimingBudgetMicroSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_set_measurement_timing_budget_micro_seconds(Dev,
+ MeasurementTimingBudgetMicroSeconds);
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetMeasurementTimingBudgetMicroSeconds(VL53L0_DEV Dev,
+ uint32_t *pMeasurementTimingBudgetMicroSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_measurement_timing_budget_micro_seconds(Dev,
+ pMeasurementTimingBudgetMicroSeconds);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetVcselPulsePeriod(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType, uint8_t VCSELPulsePeriodPCLK)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_set_vcsel_pulse_period(Dev, VcselPeriodType,
+ VCSELPulsePeriodPCLK);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetVcselPulsePeriod(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType, uint8_t *pVCSELPulsePeriodPCLK)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_vcsel_pulse_period(Dev, VcselPeriodType,
+ pVCSELPulsePeriodPCLK);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetSequenceStepEnable(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId, uint8_t SequenceStepEnabled)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t SequenceConfig = 0;
+ uint8_t SequenceConfigNew = 0;
+ uint32_t MeasurementTimingBudgetMicroSeconds;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG,
+ &SequenceConfig);
+
+ SequenceConfigNew = SequenceConfig;
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (SequenceStepEnabled == 1) {
+
+ /* Enable requested sequence step
+ */
+ switch (SequenceStepId) {
+ case VL53L0_SEQUENCESTEP_TCC:
+ SequenceConfigNew |= 0x10;
+ break;
+ case VL53L0_SEQUENCESTEP_DSS:
+ SequenceConfigNew |= 0x28;
+ break;
+ case VL53L0_SEQUENCESTEP_MSRC:
+ SequenceConfigNew |= 0x04;
+ break;
+ case VL53L0_SEQUENCESTEP_PRE_RANGE:
+ SequenceConfigNew |= 0x40;
+ break;
+ case VL53L0_SEQUENCESTEP_FINAL_RANGE:
+ SequenceConfigNew |= 0x80;
+ break;
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ } else {
+ /* Disable requested sequence step
+ */
+ switch (SequenceStepId) {
+ case VL53L0_SEQUENCESTEP_TCC:
+ SequenceConfigNew &= 0xef;
+ break;
+ case VL53L0_SEQUENCESTEP_DSS:
+ SequenceConfigNew &= 0xd7;
+ break;
+ case VL53L0_SEQUENCESTEP_MSRC:
+ SequenceConfigNew &= 0xfb;
+ break;
+ case VL53L0_SEQUENCESTEP_PRE_RANGE:
+ SequenceConfigNew &= 0xbf;
+ break;
+ case VL53L0_SEQUENCESTEP_FINAL_RANGE:
+ SequenceConfigNew &= 0x7f;
+ break;
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+ }
+
+ if (SequenceConfigNew != SequenceConfig) {
+ /* Apply New Setting */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_SYSTEM_SEQUENCE_CONFIG, SequenceConfigNew);
+ }
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, SequenceConfig, SequenceConfigNew);
+
+
+ /* Recalculate timing budget */
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_GETPARAMETERFIELD(Dev,
+ MeasurementTimingBudgetMicroSeconds,
+ MeasurementTimingBudgetMicroSeconds);
+
+ VL53L0_SetMeasurementTimingBudgetMicroSeconds(Dev,
+ MeasurementTimingBudgetMicroSeconds);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+VL53L0_Error sequence_step_enabled(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId, uint8_t SequenceConfig,
+ uint8_t *pSequenceStepEnabled)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ *pSequenceStepEnabled = 0;
+ LOG_FUNCTION_START("");
+
+ switch (SequenceStepId) {
+ case VL53L0_SEQUENCESTEP_TCC:
+ *pSequenceStepEnabled = (SequenceConfig & 0x10) >> 4;
+ break;
+ case VL53L0_SEQUENCESTEP_DSS:
+ *pSequenceStepEnabled = (SequenceConfig & 0x08) >> 3;
+ break;
+ case VL53L0_SEQUENCESTEP_MSRC:
+ *pSequenceStepEnabled = (SequenceConfig & 0x04) >> 2;
+ break;
+ case VL53L0_SEQUENCESTEP_PRE_RANGE:
+ *pSequenceStepEnabled = (SequenceConfig & 0x40) >> 6;
+ break;
+ case VL53L0_SEQUENCESTEP_FINAL_RANGE:
+ *pSequenceStepEnabled = (SequenceConfig & 0x80) >> 7;
+ break;
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetSequenceStepEnable(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId, uint8_t *pSequenceStepEnabled)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t SequenceConfig = 0;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG,
+ &SequenceConfig);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = sequence_step_enabled(Dev, SequenceStepId,
+ SequenceConfig, pSequenceStepEnabled);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetSequenceStepEnables(VL53L0_DEV Dev,
+ VL53L0_SchedulerSequenceSteps_t *pSchedulerSequenceSteps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t SequenceConfig = 0;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG,
+ &SequenceConfig);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = sequence_step_enabled(Dev,
+ VL53L0_SEQUENCESTEP_TCC, SequenceConfig,
+ &pSchedulerSequenceSteps->TccOn);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = sequence_step_enabled(Dev,
+ VL53L0_SEQUENCESTEP_DSS, SequenceConfig,
+ &pSchedulerSequenceSteps->DssOn);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = sequence_step_enabled(Dev,
+ VL53L0_SEQUENCESTEP_MSRC, SequenceConfig,
+ &pSchedulerSequenceSteps->MsrcOn);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = sequence_step_enabled(Dev,
+ VL53L0_SEQUENCESTEP_PRE_RANGE, SequenceConfig,
+ &pSchedulerSequenceSteps->PreRangeOn);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = sequence_step_enabled(Dev,
+ VL53L0_SEQUENCESTEP_FINAL_RANGE, SequenceConfig,
+ &pSchedulerSequenceSteps->FinalRangeOn);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetNumberOfSequenceSteps(VL53L0_DEV Dev,
+ uint8_t *pNumberOfSequenceSteps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pNumberOfSequenceSteps = VL53L0_SEQUENCESTEP_NUMBER_OF_CHECKS;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetSequenceStepsInfo(VL53L0_SequenceStepId SequenceStepId,
+ char *pSequenceStepsString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_sequence_steps_info(
+ SequenceStepId,
+ pSequenceStepsString);
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetSequenceStepTimeout(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId, FixPoint1616_t TimeOutMilliSecs)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_Error Status1 = VL53L0_ERROR_NONE;
+ uint32_t TimeoutMicroSeconds = ((TimeOutMilliSecs * 1000) + 0x8000)
+ >> 16;
+ uint32_t MeasurementTimingBudgetMicroSeconds;
+ FixPoint1616_t OldTimeOutMicroSeconds;
+
+ LOG_FUNCTION_START("");
+
+ /* Read back the current value in case we need to revert back to this.
+ */
+ Status = get_sequence_step_timeout(Dev, SequenceStepId,
+ &OldTimeOutMicroSeconds);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = set_sequence_step_timeout(Dev, SequenceStepId,
+ TimeoutMicroSeconds);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_GETPARAMETERFIELD(Dev,
+ MeasurementTimingBudgetMicroSeconds,
+ MeasurementTimingBudgetMicroSeconds);
+
+ /* At this point we don't know if the requested value is valid,
+ * therefore proceed to update the entire timing budget and
+ * if this fails, revert back to the previous value.
+ */
+ Status = VL53L0_SetMeasurementTimingBudgetMicroSeconds(Dev,
+ MeasurementTimingBudgetMicroSeconds);
+
+ if (Status != VL53L0_ERROR_NONE) {
+ Status1 = set_sequence_step_timeout(Dev, SequenceStepId,
+ OldTimeOutMicroSeconds);
+
+ if (Status1 == VL53L0_ERROR_NONE) {
+ Status1 =
+ VL53L0_SetMeasurementTimingBudgetMicroSeconds(
+ Dev,
+ MeasurementTimingBudgetMicroSeconds);
+ }
+
+ Status = Status1;
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetSequenceStepTimeout(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId, FixPoint1616_t *pTimeOutMilliSecs)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint32_t TimeoutMicroSeconds;
+ uint32_t WholeNumber_ms = 0;
+ uint32_t Fraction_ms = 0;
+
+ LOG_FUNCTION_START("");
+
+ Status = get_sequence_step_timeout(Dev, SequenceStepId,
+ &TimeoutMicroSeconds);
+ if (Status == VL53L0_ERROR_NONE) {
+ WholeNumber_ms = TimeoutMicroSeconds / 1000;
+ Fraction_ms = TimeoutMicroSeconds - (WholeNumber_ms * 1000);
+ *pTimeOutMilliSecs = (WholeNumber_ms << 16)
+ + (((Fraction_ms * 0xffff) + 500) / 1000);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetInterMeasurementPeriodMilliSeconds(VL53L0_DEV Dev,
+ uint32_t InterMeasurementPeriodMilliSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t osc_calibrate_val;
+ uint32_t IMPeriodMilliSeconds;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdWord(Dev, VL53L0_REG_OSC_CALIBRATE_VAL,
+ &osc_calibrate_val);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (osc_calibrate_val != 0) {
+ IMPeriodMilliSeconds =
+ InterMeasurementPeriodMilliSeconds
+ * osc_calibrate_val;
+ } else {
+ IMPeriodMilliSeconds =
+ InterMeasurementPeriodMilliSeconds;
+ }
+ Status = VL53L0_WrDWord(Dev,
+ VL53L0_REG_SYSTEM_INTERMEASUREMENT_PERIOD,
+ IMPeriodMilliSeconds);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETPARAMETERFIELD(Dev,
+ InterMeasurementPeriodMilliSeconds,
+ InterMeasurementPeriodMilliSeconds);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetInterMeasurementPeriodMilliSeconds(VL53L0_DEV Dev,
+ uint32_t *pInterMeasurementPeriodMilliSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t osc_calibrate_val;
+ uint32_t IMPeriodMilliSeconds;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdWord(Dev, VL53L0_REG_OSC_CALIBRATE_VAL,
+ &osc_calibrate_val);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdDWord(Dev,
+ VL53L0_REG_SYSTEM_INTERMEASUREMENT_PERIOD,
+ &IMPeriodMilliSeconds);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (osc_calibrate_val != 0) {
+ *pInterMeasurementPeriodMilliSeconds =
+ IMPeriodMilliSeconds / osc_calibrate_val;
+ }
+ VL53L0_SETPARAMETERFIELD(Dev,
+ InterMeasurementPeriodMilliSeconds,
+ *pInterMeasurementPeriodMilliSeconds);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetXTalkCompensationEnable(VL53L0_DEV Dev,
+ uint8_t XTalkCompensationEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ FixPoint1616_t TempFix1616;
+ uint16_t LinearityCorrectiveGain;
+
+ LOG_FUNCTION_START("");
+
+ LinearityCorrectiveGain = PALDevDataGet(Dev, LinearityCorrectiveGain);
+
+ if ((XTalkCompensationEnable == 0)
+ || (LinearityCorrectiveGain != 1000)) {
+ TempFix1616 = 0;
+ } else {
+ VL53L0_GETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps,
+ TempFix1616);
+ }
+
+ /* the following register has a format 3.13 */
+ Status = VL53L0_WrWord(Dev,
+ VL53L0_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS,
+ VL53L0_FIXPOINT1616TOFIXPOINT313(TempFix1616));
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (XTalkCompensationEnable == 0) {
+ VL53L0_SETPARAMETERFIELD(Dev, XTalkCompensationEnable,
+ 0);
+ } else {
+ VL53L0_SETPARAMETERFIELD(Dev, XTalkCompensationEnable,
+ 1);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetXTalkCompensationEnable(VL53L0_DEV Dev,
+ uint8_t *pXTalkCompensationEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Temp8;
+
+ LOG_FUNCTION_START("");
+
+ VL53L0_GETPARAMETERFIELD(Dev, XTalkCompensationEnable, Temp8);
+ *pXTalkCompensationEnable = Temp8;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetXTalkCompensationRateMegaCps(VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCompensationRateMegaCps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Temp8;
+ uint16_t LinearityCorrectiveGain;
+ uint16_t data;
+
+ LOG_FUNCTION_START("");
+
+ VL53L0_GETPARAMETERFIELD(Dev, XTalkCompensationEnable, Temp8);
+ LinearityCorrectiveGain = PALDevDataGet(Dev, LinearityCorrectiveGain);
+
+ if (Temp8 == 0) { /* disabled write only internal value */
+ VL53L0_SETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps,
+ XTalkCompensationRateMegaCps);
+ } else {
+ /* the following register has a format 3.13 */
+ if (LinearityCorrectiveGain == 1000) {
+ data = VL53L0_FIXPOINT1616TOFIXPOINT313(
+ XTalkCompensationRateMegaCps);
+ } else {
+ data = 0;
+ }
+
+ Status = VL53L0_WrWord(Dev,
+ VL53L0_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, data);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETPARAMETERFIELD(Dev,
+ XTalkCompensationRateMegaCps,
+ XTalkCompensationRateMegaCps);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetXTalkCompensationRateMegaCps(VL53L0_DEV Dev,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t Value;
+ FixPoint1616_t TempFix1616;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdWord(Dev,
+ VL53L0_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, (uint16_t *)&Value);
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Value == 0) {
+ /* the Xtalk is disabled return value from memory */
+ VL53L0_GETPARAMETERFIELD(Dev,
+ XTalkCompensationRateMegaCps, TempFix1616);
+ *pXTalkCompensationRateMegaCps = TempFix1616;
+ VL53L0_SETPARAMETERFIELD(Dev, XTalkCompensationEnable,
+ 0);
+ } else {
+ TempFix1616 = VL53L0_FIXPOINT313TOFIXPOINT1616(Value);
+ *pXTalkCompensationRateMegaCps = TempFix1616;
+ VL53L0_SETPARAMETERFIELD(Dev,
+ XTalkCompensationRateMegaCps, TempFix1616);
+ VL53L0_SETPARAMETERFIELD(Dev, XTalkCompensationEnable,
+ 1);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetRefCalibration(VL53L0_DEV Dev, uint8_t VhvSettings,
+ uint8_t PhaseCal)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_set_ref_calibration(Dev, VhvSettings, PhaseCal);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetRefCalibration(VL53L0_DEV Dev, uint8_t *pVhvSettings,
+ uint8_t *pPhaseCal)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_ref_calibration(Dev, pVhvSettings, pPhaseCal);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/*
+ * CHECK LIMIT FUNCTIONS
+ */
+
+VL53L0_Error VL53L0_GetNumberOfLimitCheck(uint16_t *pNumberOfLimitCheck)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pNumberOfLimitCheck = VL53L0_CHECKENABLE_NUMBER_OF_CHECKS;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetLimitCheckInfo(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ char *pLimitCheckString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_limit_check_info(Dev, LimitCheckId,
+ pLimitCheckString);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetLimitCheckStatus(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ uint8_t *pLimitCheckStatus)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Temp8;
+
+ LOG_FUNCTION_START("");
+
+ if (LimitCheckId >= VL53L0_CHECKENABLE_NUMBER_OF_CHECKS) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else {
+
+ VL53L0_GETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
+ LimitCheckId, Temp8);
+
+ *pLimitCheckStatus = Temp8;
+
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetLimitCheckEnable(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ uint8_t LimitCheckEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ FixPoint1616_t TempFix1616 = 0;
+ uint8_t LimitCheckEnableInt = 0;
+ uint8_t LimitCheckDisable = 0;
+ uint8_t Temp8;
+
+ LOG_FUNCTION_START("");
+
+ if (LimitCheckId >= VL53L0_CHECKENABLE_NUMBER_OF_CHECKS) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else {
+ if (LimitCheckEnable == 0) {
+ TempFix1616 = 0;
+ LimitCheckEnableInt = 0;
+ LimitCheckDisable = 1;
+
+ } else {
+ VL53L0_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ LimitCheckId, TempFix1616);
+ LimitCheckDisable = 0;
+ /* this to be sure to have either 0 or 1 */
+ LimitCheckEnableInt = 1;
+ }
+
+ switch (LimitCheckId) {
+
+ case VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE:
+ /* internal computation: */
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ LimitCheckEnableInt);
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE:
+
+ Status = VL53L0_WrWord(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT,
+ VL53L0_FIXPOINT1616TOFIXPOINT97(TempFix1616));
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_REF_CLIP:
+
+ /* internal computation: */
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP,
+ LimitCheckEnableInt);
+
+ break;
+
+ case VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD:
+
+ /* internal computation: */
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ LimitCheckEnableInt);
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_MSRC:
+
+ Temp8 = (uint8_t)(LimitCheckDisable << 1);
+ Status = VL53L0_UpdateByte(Dev,
+ VL53L0_REG_MSRC_CONFIG_CONTROL,
+ 0xFE, Temp8);
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_PRE_RANGE:
+
+ Temp8 = (uint8_t)(LimitCheckDisable << 4);
+ Status = VL53L0_UpdateByte(Dev,
+ VL53L0_REG_MSRC_CONFIG_CONTROL,
+ 0xEF, Temp8);
+
+ break;
+
+
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+ }
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (LimitCheckEnable == 0) {
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
+ LimitCheckId, 0);
+ } else {
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
+ LimitCheckId, 1);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetLimitCheckEnable(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ uint8_t *pLimitCheckEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Temp8;
+
+ LOG_FUNCTION_START("");
+
+ if (LimitCheckId >= VL53L0_CHECKENABLE_NUMBER_OF_CHECKS) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ *pLimitCheckEnable = 0;
+ } else {
+ VL53L0_GETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
+ LimitCheckId, Temp8);
+ *pLimitCheckEnable = Temp8;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetLimitCheckValue(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ FixPoint1616_t LimitCheckValue)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Temp8;
+
+ LOG_FUNCTION_START("");
+
+ VL53L0_GETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, LimitCheckId,
+ Temp8);
+
+ if (Temp8 == 0) { /* disabled write only internal value */
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ LimitCheckId, LimitCheckValue);
+ } else {
+
+ switch (LimitCheckId) {
+
+ case VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE:
+ /* internal computation: */
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ LimitCheckValue);
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE:
+
+ Status = VL53L0_WrWord(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT,
+ VL53L0_FIXPOINT1616TOFIXPOINT97(
+ LimitCheckValue));
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_REF_CLIP:
+
+ /* internal computation: */
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP,
+ LimitCheckValue);
+
+ break;
+
+ case VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD:
+
+ /* internal computation: */
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ LimitCheckValue);
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_MSRC:
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_PRE_RANGE:
+
+ Status = VL53L0_WrWord(Dev,
+ VL53L0_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT,
+ VL53L0_FIXPOINT1616TOFIXPOINT97(
+ LimitCheckValue));
+
+ break;
+
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ LimitCheckId, LimitCheckValue);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetLimitCheckValue(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ FixPoint1616_t *pLimitCheckValue)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t EnableZeroValue = 0;
+ uint16_t Temp16;
+ FixPoint1616_t TempFix1616;
+
+ LOG_FUNCTION_START("");
+
+ switch (LimitCheckId) {
+
+ case VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE:
+ /* internal computation: */
+ VL53L0_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE, TempFix1616);
+ EnableZeroValue = 0;
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE:
+ Status = VL53L0_RdWord(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT,
+ &Temp16);
+ if (Status == VL53L0_ERROR_NONE)
+ TempFix1616 = VL53L0_FIXPOINT97TOFIXPOINT1616(Temp16);
+
+
+ EnableZeroValue = 1;
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_REF_CLIP:
+ /* internal computation: */
+ VL53L0_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP, TempFix1616);
+ EnableZeroValue = 0;
+ break;
+
+ case VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD:
+ /* internal computation: */
+ VL53L0_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD, TempFix1616);
+ EnableZeroValue = 0;
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_MSRC:
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_PRE_RANGE:
+ Status = VL53L0_RdWord(Dev,
+ VL53L0_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT,
+ &Temp16);
+ if (Status == VL53L0_ERROR_NONE)
+ TempFix1616 = VL53L0_FIXPOINT97TOFIXPOINT1616(Temp16);
+
+
+ EnableZeroValue = 0;
+ break;
+
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+
+ if (EnableZeroValue == 1) {
+
+ if (TempFix1616 == 0) {
+ /* disabled: return value from memory */
+ VL53L0_GETARRAYPARAMETERFIELD(Dev,
+ LimitChecksValue, LimitCheckId,
+ TempFix1616);
+ *pLimitCheckValue = TempFix1616;
+ VL53L0_SETARRAYPARAMETERFIELD(Dev,
+ LimitChecksEnable, LimitCheckId, 0);
+ } else {
+ *pLimitCheckValue = TempFix1616;
+ VL53L0_SETARRAYPARAMETERFIELD(Dev,
+ LimitChecksValue, LimitCheckId,
+ TempFix1616);
+ VL53L0_SETARRAYPARAMETERFIELD(Dev,
+ LimitChecksEnable, LimitCheckId, 1);
+ }
+ } else {
+ *pLimitCheckValue = TempFix1616;
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
+
+VL53L0_Error VL53L0_GetLimitCheckCurrent(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ FixPoint1616_t *pLimitCheckCurrent)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_RangingMeasurementData_t LastRangeDataBuffer;
+
+ LOG_FUNCTION_START("");
+
+ if (LimitCheckId >= VL53L0_CHECKENABLE_NUMBER_OF_CHECKS) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else {
+ switch (LimitCheckId) {
+ case VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE:
+ /* Need to run a ranging to have the latest values */
+ *pLimitCheckCurrent = PALDevDataGet(Dev, SigmaEstimate);
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE:
+ /* Need to run a ranging to have the latest values */
+ LastRangeDataBuffer = PALDevDataGet(Dev,
+ LastRangeMeasure);
+ *pLimitCheckCurrent =
+ LastRangeDataBuffer.SignalRateRtnMegaCps;
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_REF_CLIP:
+ /* Need to run a ranging to have the latest values */
+ *pLimitCheckCurrent = PALDevDataGet(Dev,
+ LastSignalRefMcps);
+
+ break;
+
+ case VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD:
+ /* Need to run a ranging to have the latest values */
+ LastRangeDataBuffer = PALDevDataGet(Dev,
+ LastRangeMeasure);
+ *pLimitCheckCurrent =
+ LastRangeDataBuffer.SignalRateRtnMegaCps;
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_MSRC:
+ /* Need to run a ranging to have the latest values */
+ LastRangeDataBuffer = PALDevDataGet(Dev,
+ LastRangeMeasure);
+ *pLimitCheckCurrent =
+ LastRangeDataBuffer.SignalRateRtnMegaCps;
+
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_PRE_RANGE:
+ /* Need to run a ranging to have the latest values */
+ LastRangeDataBuffer = PALDevDataGet(Dev,
+ LastRangeMeasure);
+ *pLimitCheckCurrent =
+ LastRangeDataBuffer.SignalRateRtnMegaCps;
+
+ break;
+
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
+
+/*
+ * WRAPAROUND Check
+ */
+VL53L0_Error VL53L0_SetWrapAroundCheckEnable(VL53L0_DEV Dev,
+ uint8_t WrapAroundCheckEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+ uint8_t WrapAroundCheckEnableInt;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG, &Byte);
+ if (WrapAroundCheckEnable == 0) {
+ /* Disable wraparound */
+ Byte = Byte & 0x7F;
+ WrapAroundCheckEnableInt = 0;
+ } else {
+ /*Enable wraparound */
+ Byte = Byte | 0x80;
+ WrapAroundCheckEnableInt = 1;
+ }
+
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG, Byte);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ PALDevDataSet(Dev, SequenceConfig, Byte);
+ VL53L0_SETPARAMETERFIELD(Dev, WrapAroundCheckEnable,
+ WrapAroundCheckEnableInt);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetWrapAroundCheckEnable(VL53L0_DEV Dev,
+ uint8_t *pWrapAroundCheckEnable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t data;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG, &data);
+ if (Status == VL53L0_ERROR_NONE) {
+ PALDevDataSet(Dev, SequenceConfig, data);
+ if (data & (0x01 << 7))
+ *pWrapAroundCheckEnable = 0x01;
+ else
+ *pWrapAroundCheckEnable = 0x00;
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETPARAMETERFIELD(Dev, WrapAroundCheckEnable,
+ *pWrapAroundCheckEnable);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetDmaxCalParameters(VL53L0_DEV Dev,
+ uint16_t RangeMilliMeter, FixPoint1616_t SignalRateRtnMegaCps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ FixPoint1616_t SignalRateRtnMegaCpsTemp = 0;
+
+ LOG_FUNCTION_START("");
+
+ /* Check if one of input parameter is zero, in that case the
+ * value are get from NVM
+ */
+ if ((RangeMilliMeter == 0) || (SignalRateRtnMegaCps == 0)) {
+ /* NVM parameters */
+ /* Run VL53L0_get_info_from_device wit option 4 to get
+ * signal rate at 400 mm if the value have been already
+ * get this function will return with no access to device
+ */
+ VL53L0_get_info_from_device(Dev, 4);
+
+ SignalRateRtnMegaCpsTemp = VL53L0_GETDEVICESPECIFICPARAMETER(
+ Dev, SignalRateMeasFixed400mm);
+
+ PALDevDataSet(Dev, DmaxCalRangeMilliMeter, 400);
+ PALDevDataSet(Dev, DmaxCalSignalRateRtnMegaCps,
+ SignalRateRtnMegaCpsTemp);
+ } else {
+ /* User parameters */
+ PALDevDataSet(Dev, DmaxCalRangeMilliMeter, RangeMilliMeter);
+ PALDevDataSet(Dev, DmaxCalSignalRateRtnMegaCps,
+ SignalRateRtnMegaCps);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetDmaxCalParameters(VL53L0_DEV Dev,
+ uint16_t *pRangeMilliMeter, FixPoint1616_t *pSignalRateRtnMegaCps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pRangeMilliMeter = PALDevDataGet(Dev, DmaxCalRangeMilliMeter);
+ *pSignalRateRtnMegaCps = PALDevDataGet(Dev,
+ DmaxCalSignalRateRtnMegaCps);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* End Group PAL Parameters Functions */
+
+/* Group PAL Measurement Functions */
+VL53L0_Error VL53L0_PerformSingleMeasurement(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceModes DeviceMode;
+
+ LOG_FUNCTION_START("");
+
+ /* Get Current DeviceMode */
+ Status = VL53L0_GetDeviceMode(Dev, &DeviceMode);
+
+ /* Start immediately to run a single ranging measurement in case of
+ * single ranging or single histogram
+ */
+ if (Status == VL53L0_ERROR_NONE
+ && DeviceMode == VL53L0_DEVICEMODE_SINGLE_RANGING)
+ Status = VL53L0_StartMeasurement(Dev);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_measurement_poll_for_completion(Dev);
+
+
+ /* Change PAL State in case of single ranging or single histogram */
+ if (Status == VL53L0_ERROR_NONE
+ && DeviceMode == VL53L0_DEVICEMODE_SINGLE_RANGING)
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_IDLE);
+
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_PerformSingleHistogramMeasurement(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_perform_single_histogram_measurement(Dev,
+ pHistogramMeasurementData);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_PerformRefCalibration(VL53L0_DEV Dev, uint8_t *pVhvSettings,
+ uint8_t *pPhaseCal)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_perform_ref_calibration(Dev, pVhvSettings,
+ pPhaseCal, 1);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_PerformXTalkMeasurement(VL53L0_DEV Dev,
+ uint32_t TimeoutMs, FixPoint1616_t *pXtalkPerSpad,
+ uint8_t *pAmbientTooHigh)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_perform_xtalk_measurement(Dev, TimeoutMs,
+ pXtalkPerSpad, pAmbientTooHigh);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_PerformXTalkCalibration(VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCalDistance,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_perform_xtalk_calibration(Dev, XTalkCalDistance,
+ pXTalkCompensationRateMegaCps);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_PerformOffsetCalibration(VL53L0_DEV Dev,
+ FixPoint1616_t CalDistanceMilliMeter, int32_t *pOffsetMicroMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_perform_offset_calibration(Dev, CalDistanceMilliMeter,
+ pOffsetMicroMeter);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_CheckAndLoadInterruptSettings(VL53L0_DEV Dev,
+ uint8_t StartNotStopFlag)
+{
+ uint8_t InterruptConfig;
+ FixPoint1616_t ThresholdLow;
+ FixPoint1616_t ThresholdHigh;
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ InterruptConfig = VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ Pin0GpioFunctionality);
+
+ if ((InterruptConfig ==
+ VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW) ||
+ (InterruptConfig ==
+ VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH) ||
+ (InterruptConfig ==
+ VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT)) {
+
+ Status = VL53L0_GetInterruptThresholds(Dev,
+ VL53L0_DEVICEMODE_CONTINUOUS_RANGING,
+ &ThresholdLow, &ThresholdHigh);
+
+ if (((ThresholdLow > 255*65536) ||
+ (ThresholdHigh > 255*65536)) &&
+ (Status == VL53L0_ERROR_NONE)) {
+
+ if (StartNotStopFlag != 0) {
+ Status = VL53L0_load_tuning_settings(Dev,
+ InterruptThresholdSettings);
+ } else {
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0x70, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x00);
+ }
+
+ }
+
+
+ }
+
+ return Status;
+
+}
+
+
+VL53L0_Error VL53L0_StartMeasurement(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceModes DeviceMode;
+ uint8_t Byte;
+ uint8_t StartStopByte = VL53L0_REG_SYSRANGE_MODE_START_STOP;
+ uint32_t LoopNb;
+
+ LOG_FUNCTION_START("");
+
+ /* Get Current DeviceMode */
+ VL53L0_GetDeviceMode(Dev, &DeviceMode);
+
+ Status = VL53L0_WrByte(Dev, 0x80, 0x01);
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status = VL53L0_WrByte(Dev, 0x00, 0x00);
+ Status = VL53L0_WrByte(Dev, 0x91, PALDevDataGet(Dev, StopVariable));
+ Status = VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status = VL53L0_WrByte(Dev, 0x80, 0x00);
+
+ switch (DeviceMode) {
+ case VL53L0_DEVICEMODE_SINGLE_RANGING:
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSRANGE_START, 0x01);
+
+ Byte = StartStopByte;
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Wait until start bit has been cleared */
+ LoopNb = 0;
+ do {
+ if (LoopNb > 0)
+ Status = VL53L0_RdByte(Dev,
+ VL53L0_REG_SYSRANGE_START, &Byte);
+ LoopNb = LoopNb + 1;
+ } while (((Byte & StartStopByte) == StartStopByte)
+ && (Status == VL53L0_ERROR_NONE)
+ && (LoopNb < VL53L0_DEFAULT_MAX_LOOP));
+
+ if (LoopNb >= VL53L0_DEFAULT_MAX_LOOP)
+ Status = VL53L0_ERROR_TIME_OUT;
+
+ }
+
+ break;
+ case VL53L0_DEVICEMODE_CONTINUOUS_RANGING:
+ /* Back-to-back mode */
+
+ /* Check if need to apply interrupt settings */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_CheckAndLoadInterruptSettings(Dev, 1);
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_SYSRANGE_START,
+ VL53L0_REG_SYSRANGE_MODE_BACKTOBACK);
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Set PAL State to Running */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_RUNNING);
+ }
+ break;
+ case VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING:
+ /* Continuous mode */
+ /* Check if need to apply interrupt settings */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_CheckAndLoadInterruptSettings(Dev, 1);
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_SYSRANGE_START,
+ VL53L0_REG_SYSRANGE_MODE_TIMED);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Set PAL State to Running */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_RUNNING);
+ }
+ break;
+ default:
+ /* Selected mode not supported */
+ Status = VL53L0_ERROR_MODE_NOT_SUPPORTED;
+ }
+
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_StopMeasurement(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSRANGE_START,
+ VL53L0_REG_SYSRANGE_MODE_SINGLESHOT);
+
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status = VL53L0_WrByte(Dev, 0x00, 0x00);
+ Status = VL53L0_WrByte(Dev, 0x91, 0x00);
+ Status = VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Set PAL State to Idle */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_IDLE);
+ }
+
+ /* Check if need to apply interrupt settings */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_CheckAndLoadInterruptSettings(Dev, 0);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetMeasurementDataReady(VL53L0_DEV Dev,
+ uint8_t *pMeasurementDataReady)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t SysRangeStatusRegister;
+ uint8_t InterruptConfig;
+ uint32_t InterruptMask;
+
+ LOG_FUNCTION_START("");
+
+ InterruptConfig = VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ Pin0GpioFunctionality);
+
+ if (InterruptConfig ==
+ VL53L0_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY) {
+ Status = VL53L0_GetInterruptMaskStatus(Dev, &InterruptMask);
+ if (InterruptMask ==
+ VL53L0_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY)
+ *pMeasurementDataReady = 1;
+ else
+ *pMeasurementDataReady = 0;
+ } else {
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_RESULT_RANGE_STATUS,
+ &SysRangeStatusRegister);
+ if (Status == VL53L0_ERROR_NONE) {
+ if (SysRangeStatusRegister & 0x01)
+ *pMeasurementDataReady = 1;
+ else
+ *pMeasurementDataReady = 0;
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_WaitDeviceReadyForNewMeasurement(VL53L0_DEV Dev,
+ uint32_t MaxLoop)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented for VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_GetRangingMeasurementData(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t DeviceRangeStatus;
+ uint8_t RangeFractionalEnable;
+ uint8_t PalRangeStatus;
+ uint8_t XTalkCompensationEnable;
+ uint16_t AmbientRate;
+ FixPoint1616_t SignalRate;
+ uint16_t XTalkCompensationRateMegaCps;
+ uint16_t EffectiveSpadRtnCount;
+ uint16_t tmpuint16;
+ uint16_t XtalkRangeMilliMeter;
+ uint16_t LinearityCorrectiveGain;
+ uint8_t localBuffer[12];
+ VL53L0_RangingMeasurementData_t LastRangeDataBuffer;
+
+ LOG_FUNCTION_START("");
+
+ /*
+ * use multi read even if some registers are not useful, result will
+ * be more efficient
+ * start reading at 0x14 dec20
+ * end reading at 0x21 dec33 total 14 bytes to read
+ */
+ Status = VL53L0_ReadMulti(Dev, 0x14, localBuffer, 12);
+
+ if (Status == VL53L0_ERROR_NONE) {
+
+ pRangingMeasurementData->ZoneId = 0; /* Only one zone */
+ pRangingMeasurementData->TimeStamp = 0; /* Not Implemented */
+
+ tmpuint16 = VL53L0_MAKEUINT16(localBuffer[11], localBuffer[10]);
+ /* cut1.1 if SYSTEM__RANGE_CONFIG if 1 range is 2bits fractional
+ *(format 11.2) else no fractional
+ */
+
+ pRangingMeasurementData->MeasurementTimeUsec = 0;
+
+ SignalRate = VL53L0_FIXPOINT97TOFIXPOINT1616(
+ VL53L0_MAKEUINT16(localBuffer[7], localBuffer[6]));
+ /* peak_signal_count_rate_rtn_mcps */
+ pRangingMeasurementData->SignalRateRtnMegaCps = SignalRate;
+
+ AmbientRate = VL53L0_MAKEUINT16(localBuffer[9], localBuffer[8]);
+ pRangingMeasurementData->AmbientRateRtnMegaCps =
+ VL53L0_FIXPOINT97TOFIXPOINT1616(AmbientRate);
+
+ EffectiveSpadRtnCount = VL53L0_MAKEUINT16(localBuffer[3],
+ localBuffer[2]);
+ /* EffectiveSpadRtnCount is 8.8 format */
+ pRangingMeasurementData->EffectiveSpadRtnCount =
+ EffectiveSpadRtnCount;
+
+ DeviceRangeStatus = localBuffer[0];
+
+ /* Get Linearity Corrective Gain */
+ LinearityCorrectiveGain = PALDevDataGet(Dev,
+ LinearityCorrectiveGain);
+
+ /* Get ranging configuration */
+ RangeFractionalEnable = PALDevDataGet(Dev,
+ RangeFractionalEnable);
+
+ if (LinearityCorrectiveGain != 1000) {
+
+ tmpuint16 = (uint16_t)((LinearityCorrectiveGain
+ * tmpuint16 + 500) / 1000);
+
+ /* Implement Xtalk */
+ VL53L0_GETPARAMETERFIELD(Dev,
+ XTalkCompensationRateMegaCps,
+ XTalkCompensationRateMegaCps);
+ VL53L0_GETPARAMETERFIELD(Dev, XTalkCompensationEnable,
+ XTalkCompensationEnable);
+
+ if (XTalkCompensationEnable) {
+
+ if ((SignalRate
+ - ((XTalkCompensationRateMegaCps
+ * EffectiveSpadRtnCount) >> 8))
+ <= 0) {
+ if (RangeFractionalEnable)
+ XtalkRangeMilliMeter = 8888;
+ else
+ XtalkRangeMilliMeter = 8888
+ << 2;
+ } else {
+ XtalkRangeMilliMeter =
+ (tmpuint16 * SignalRate)
+ / (SignalRate
+ - ((XTalkCompensationRateMegaCps
+ * EffectiveSpadRtnCount)
+ >> 8));
+ }
+
+ tmpuint16 = XtalkRangeMilliMeter;
+ }
+
+ }
+
+ if (RangeFractionalEnable) {
+ pRangingMeasurementData->RangeMilliMeter =
+ (uint16_t)((tmpuint16) >> 2);
+ pRangingMeasurementData->RangeFractionalPart =
+ (uint8_t)((tmpuint16 & 0x03) << 6);
+ } else {
+ pRangingMeasurementData->RangeMilliMeter = tmpuint16;
+ pRangingMeasurementData->RangeFractionalPart = 0;
+ }
+
+ /*
+ * For a standard definition of RangeStatus, this should
+ * return 0 in case of good result after a ranging
+ * The range status depends on the device so call a device
+ * specific function to obtain the right Status.
+ */
+ Status |= VL53L0_get_pal_range_status(Dev, DeviceRangeStatus,
+ SignalRate, EffectiveSpadRtnCount,
+ pRangingMeasurementData, &PalRangeStatus);
+
+ if (Status == VL53L0_ERROR_NONE)
+ pRangingMeasurementData->RangeStatus = PalRangeStatus;
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Copy last read data into Dev buffer */
+ LastRangeDataBuffer = PALDevDataGet(Dev, LastRangeMeasure);
+
+ LastRangeDataBuffer.RangeMilliMeter =
+ pRangingMeasurementData->RangeMilliMeter;
+ LastRangeDataBuffer.RangeFractionalPart =
+ pRangingMeasurementData->RangeFractionalPart;
+ LastRangeDataBuffer.RangeDMaxMilliMeter =
+ pRangingMeasurementData->RangeDMaxMilliMeter;
+ LastRangeDataBuffer.MeasurementTimeUsec =
+ pRangingMeasurementData->MeasurementTimeUsec;
+ LastRangeDataBuffer.SignalRateRtnMegaCps =
+ pRangingMeasurementData->SignalRateRtnMegaCps;
+ LastRangeDataBuffer.AmbientRateRtnMegaCps =
+ pRangingMeasurementData->AmbientRateRtnMegaCps;
+ LastRangeDataBuffer.EffectiveSpadRtnCount =
+ pRangingMeasurementData->EffectiveSpadRtnCount;
+ LastRangeDataBuffer.RangeStatus =
+ pRangingMeasurementData->RangeStatus;
+
+ PALDevDataSet(Dev, LastRangeMeasure, LastRangeDataBuffer);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetMeasurementRefSignal(VL53L0_DEV Dev,
+ FixPoint1616_t *pMeasurementRefSignal)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pMeasurementRefSignal = PALDevDataGet(Dev, LastSignalRefMcps);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
+
+VL53L0_Error VL53L0_GetHistogramMeasurementData(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_PerformSingleRangingMeasurement(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ /* This function will do a complete single ranging
+ * Here we fix the mode!
+ */
+ Status = VL53L0_SetDeviceMode(Dev, VL53L0_DEVICEMODE_SINGLE_RANGING);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_PerformSingleMeasurement(Dev);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetRangingMeasurementData(Dev,
+ pRangingMeasurementData);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_ClearInterruptMask(Dev, 0);
+
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetNumberOfROIZones(VL53L0_DEV Dev,
+ uint8_t NumberOfROIZones)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ if (NumberOfROIZones != 1)
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetNumberOfROIZones(VL53L0_DEV Dev,
+ uint8_t *pNumberOfROIZones)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pNumberOfROIZones = 1;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetMaxNumberOfROIZones(VL53L0_DEV Dev,
+ uint8_t *pMaxNumberOfROIZones)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ *pMaxNumberOfROIZones = 1;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* End Group PAL Measurement Functions */
+
+VL53L0_Error VL53L0_SetGpioConfig(VL53L0_DEV Dev, uint8_t Pin,
+ VL53L0_DeviceModes DeviceMode, VL53L0_GpioFunctionality Functionality,
+ VL53L0_InterruptPolarity Polarity)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t data;
+
+ LOG_FUNCTION_START("");
+
+ if (Pin != 0) {
+ Status = VL53L0_ERROR_GPIO_NOT_EXISTING;
+ } else if (DeviceMode == VL53L0_DEVICEMODE_GPIO_DRIVE) {
+ if (Polarity == VL53L0_INTERRUPTPOLARITY_LOW)
+ data = 0x10;
+ else
+ data = 1;
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_GPIO_HV_MUX_ACTIVE_HIGH, data);
+
+ } else if (DeviceMode == VL53L0_DEVICEMODE_GPIO_OSC) {
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x85, 0x02);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x04);
+ Status |= VL53L0_WrByte(Dev, 0xcd, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xcc, 0x11);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0xbe, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x06);
+ Status |= VL53L0_WrByte(Dev, 0xcc, 0x09);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+
+ } else {
+
+ if (Status == VL53L0_ERROR_NONE) {
+ switch (Functionality) {
+ case VL53L0_GPIOFUNCTIONALITY_OFF:
+ data = 0x00;
+ break;
+ case VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW:
+ data = 0x01;
+ break;
+ case VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH:
+ data = 0x02;
+ break;
+ case VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT:
+ data = 0x03;
+ break;
+ case VL53L0_GPIOFUNCTIONALITY_NEW_MEASURE_READY:
+ data = 0x04;
+ break;
+ default:
+ Status =
+ VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, data);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Polarity == VL53L0_INTERRUPTPOLARITY_LOW)
+ data = 0;
+ else
+ data = (uint8_t)(1 << 4);
+
+ Status = VL53L0_UpdateByte(Dev,
+ VL53L0_REG_GPIO_HV_MUX_ACTIVE_HIGH, 0xEF, data);
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ Pin0GpioFunctionality, Functionality);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_ClearInterruptMask(Dev, 0);
+
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetGpioConfig(VL53L0_DEV Dev, uint8_t Pin,
+ VL53L0_DeviceModes *pDeviceMode,
+ VL53L0_GpioFunctionality *pFunctionality,
+ VL53L0_InterruptPolarity *pPolarity)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_GpioFunctionality GpioFunctionality;
+ uint8_t data;
+
+ LOG_FUNCTION_START("");
+
+ /* pDeviceMode not managed by Ewok it return the current mode */
+
+ Status = VL53L0_GetDeviceMode(Dev, pDeviceMode);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Pin != 0) {
+ Status = VL53L0_ERROR_GPIO_NOT_EXISTING;
+ } else {
+ Status = VL53L0_RdByte(Dev,
+ VL53L0_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, &data);
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ switch (data & 0x07) {
+ case 0x00:
+ GpioFunctionality = VL53L0_GPIOFUNCTIONALITY_OFF;
+ break;
+ case 0x01:
+ GpioFunctionality =
+ VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW;
+ break;
+ case 0x02:
+ GpioFunctionality =
+ VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH;
+ break;
+ case 0x03:
+ GpioFunctionality =
+ VL53L0_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT;
+ break;
+ case 0x04:
+ GpioFunctionality =
+ VL53L0_GPIOFUNCTIONALITY_NEW_MEASURE_READY;
+ break;
+ default:
+ Status = VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_GPIO_HV_MUX_ACTIVE_HIGH,
+ &data);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if ((data & (uint8_t)(1 << 4)) == 0)
+ *pPolarity = VL53L0_INTERRUPTPOLARITY_LOW;
+ else
+ *pPolarity = VL53L0_INTERRUPTPOLARITY_HIGH;
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ *pFunctionality = GpioFunctionality;
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev, Pin0GpioFunctionality,
+ GpioFunctionality);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetInterruptThresholds(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode, FixPoint1616_t ThresholdLow,
+ FixPoint1616_t ThresholdHigh)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t Threshold16;
+
+ LOG_FUNCTION_START("");
+
+ /* no dependency on DeviceMode for Ewok */
+ /* Need to divide by 2 because the FW will apply a x2 */
+ Threshold16 = (uint16_t)((ThresholdLow >> 17) & 0x00fff);
+ Status = VL53L0_WrWord(Dev, VL53L0_REG_SYSTEM_THRESH_LOW, Threshold16);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Need to divide by 2 because the FW will apply a x2 */
+ Threshold16 = (uint16_t)((ThresholdHigh >> 17) & 0x00fff);
+ Status = VL53L0_WrWord(Dev, VL53L0_REG_SYSTEM_THRESH_HIGH,
+ Threshold16);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetInterruptThresholds(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode, FixPoint1616_t *pThresholdLow,
+ FixPoint1616_t *pThresholdHigh)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t Threshold16;
+
+ LOG_FUNCTION_START("");
+
+ /* no dependency on DeviceMode for Ewok */
+
+ Status = VL53L0_RdWord(Dev, VL53L0_REG_SYSTEM_THRESH_LOW, &Threshold16);
+ /* Need to multiply by 2 because the FW will apply a x2 */
+ *pThresholdLow = (FixPoint1616_t)((0x00fff & Threshold16) << 17);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdWord(Dev, VL53L0_REG_SYSTEM_THRESH_HIGH,
+ &Threshold16);
+ /* Need to multiply by 2 because the FW will apply a x2 */
+ *pThresholdHigh =
+ (FixPoint1616_t)((0x00fff & Threshold16) << 17);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetStopCompletedStatus(VL53L0_DEV Dev,
+ uint32_t *pStopStatus)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte = 0;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_RdByte(Dev, 0x04, &Byte);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x0);
+
+ *pStopStatus = Byte;
+
+ if (Byte == 0) {
+ Status = VL53L0_WrByte(Dev, 0x80, 0x01);
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status = VL53L0_WrByte(Dev, 0x00, 0x00);
+ Status = VL53L0_WrByte(Dev, 0x91,
+ PALDevDataGet(Dev, StopVariable));
+ Status = VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status = VL53L0_WrByte(Dev, 0x80, 0x00);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* Group PAL Interrupt Functions */
+VL53L0_Error VL53L0_ClearInterruptMask(VL53L0_DEV Dev, uint32_t InterruptMask)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t LoopCount;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ /* clear bit 0 range interrupt, bit 1 error interrupt */
+ LoopCount = 0;
+ do {
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_SYSTEM_INTERRUPT_CLEAR, 0x01);
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_SYSTEM_INTERRUPT_CLEAR, 0x00);
+ Status |= VL53L0_RdByte(Dev,
+ VL53L0_REG_RESULT_INTERRUPT_STATUS, &Byte);
+ LoopCount++;
+ } while (((Byte & 0x07) != 0x00)
+ && (LoopCount < 3)
+ && (Status == VL53L0_ERROR_NONE));
+
+
+ if (LoopCount >= 3)
+ Status = VL53L0_ERROR_INTERRUPT_NOT_CLEARED;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetInterruptMaskStatus(VL53L0_DEV Dev,
+ uint32_t *pInterruptMaskStatus)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_RESULT_INTERRUPT_STATUS, &Byte);
+ *pInterruptMaskStatus = Byte & 0x07;
+
+ if (Byte & 0x18)
+ Status = VL53L0_ERROR_RANGE_ERROR;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_EnableInterruptMask(VL53L0_DEV Dev, uint32_t InterruptMask)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ /* not implemented for VL53L0 */
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* End Group PAL Interrupt Functions */
+
+/* Group SPAD functions */
+
+VL53L0_Error VL53L0_SetSpadAmbientDamperThreshold(VL53L0_DEV Dev,
+ uint16_t SpadAmbientDamperThreshold)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrWord(Dev, 0x40, SpadAmbientDamperThreshold);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetSpadAmbientDamperThreshold(VL53L0_DEV Dev,
+ uint16_t *pSpadAmbientDamperThreshold)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_RdWord(Dev, 0x40, pSpadAmbientDamperThreshold);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_SetSpadAmbientDamperFactor(VL53L0_DEV Dev,
+ uint16_t SpadAmbientDamperFactor)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ Byte = (uint8_t)(SpadAmbientDamperFactor & 0x00FF);
+
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x42, Byte);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetSpadAmbientDamperFactor(VL53L0_DEV Dev,
+ uint16_t *pSpadAmbientDamperFactor)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t Byte;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_RdByte(Dev, 0x42, &Byte);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ *pSpadAmbientDamperFactor = (uint16_t)Byte;
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+/* END Group SPAD functions */
+
+/*****************************************************************************
+ * Internal functions
+ *****************************************************************************/
+
+VL53L0_Error VL53L0_SetReferenceSpads(VL53L0_DEV Dev, uint32_t count,
+ uint8_t isApertureSpads)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_set_reference_spads(Dev, count, isApertureSpads);
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_GetReferenceSpads(VL53L0_DEV Dev, uint32_t *pSpadCount,
+ uint8_t *pIsApertureSpads)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_reference_spads(Dev, pSpadCount, pIsApertureSpads);
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_PerformRefSpadManagement(VL53L0_DEV Dev,
+ uint32_t *refSpadCount, uint8_t *isApertureSpads)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_perform_ref_spad_management(Dev, refSpadCount,
+ isApertureSpads);
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
diff --git a/drivers/input/misc/vl53L0/src/vl53l0_api_calibration.c b/drivers/input/misc/vl53L0/src/vl53l0_api_calibration.c
new file mode 100644
index 000000000000..fa7e579ddc17
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l0_api_calibration.c
@@ -0,0 +1,1284 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+ IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#include "vl53l0_api.h"
+#include "vl53l0_api_core.h"
+#include "vl53l0_api_calibration.h"
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#endif
+
+#define LOG_FUNCTION_START(fmt, ...) \
+ _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
+#define LOG_FUNCTION_END(status, ...) \
+ _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
+#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
+ _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
+
+#define REF_ARRAY_SPAD_0 0
+#define REF_ARRAY_SPAD_5 5
+#define REF_ARRAY_SPAD_10 10
+
+uint32_t refArrayQuadrants[4] = {REF_ARRAY_SPAD_10, REF_ARRAY_SPAD_5,
+ REF_ARRAY_SPAD_0, REF_ARRAY_SPAD_5 };
+
+VL53L0_Error VL53L0_perform_xtalk_calibration(VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCalDistance,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t sum_ranging = 0;
+ uint16_t sum_spads = 0;
+ FixPoint1616_t sum_signalRate = 0;
+ FixPoint1616_t total_count = 0;
+ uint8_t xtalk_meas = 0;
+ VL53L0_RangingMeasurementData_t RangingMeasurementData;
+ FixPoint1616_t xTalkStoredMeanSignalRate;
+ FixPoint1616_t xTalkStoredMeanRange;
+ FixPoint1616_t xTalkStoredMeanRtnSpads;
+ uint32_t signalXTalkTotalPerSpad;
+ uint32_t xTalkStoredMeanRtnSpadsAsInt;
+ uint32_t xTalkCalDistanceAsInt;
+ FixPoint1616_t XTalkCompensationRateMegaCps;
+
+ if (XTalkCalDistance <= 0)
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+ /* Disable the XTalk compensation */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetXTalkCompensationEnable(Dev, 0);
+
+ /* Disable the RIT */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_SetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0);
+ }
+
+ /* Perform 50 measurements and compute the averages */
+ if (Status == VL53L0_ERROR_NONE) {
+ sum_ranging = 0;
+ sum_spads = 0;
+ sum_signalRate = 0;
+ total_count = 0;
+ for (xtalk_meas = 0; xtalk_meas < 50; xtalk_meas++) {
+ Status = VL53L0_PerformSingleRangingMeasurement(Dev,
+ &RangingMeasurementData);
+
+ if (Status != VL53L0_ERROR_NONE)
+ break;
+
+ /* The range is valid when RangeStatus = 0 */
+ if (RangingMeasurementData.RangeStatus == 0) {
+ sum_ranging = sum_ranging +
+ RangingMeasurementData.RangeMilliMeter;
+ sum_signalRate = sum_signalRate +
+ RangingMeasurementData.SignalRateRtnMegaCps;
+ sum_spads = sum_spads +
+ RangingMeasurementData.EffectiveSpadRtnCount
+ / 256;
+ total_count = total_count + 1;
+ }
+ }
+
+ /* no valid values found */
+ if (total_count == 0)
+ Status = VL53L0_ERROR_RANGE_ERROR;
+
+ }
+
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* FixPoint1616_t / uint16_t = FixPoint1616_t */
+ xTalkStoredMeanSignalRate = sum_signalRate / total_count;
+ xTalkStoredMeanRange = (FixPoint1616_t)((uint32_t)(
+ sum_ranging << 16) / total_count);
+ xTalkStoredMeanRtnSpads = (FixPoint1616_t)((uint32_t)(
+ sum_spads << 16) / total_count);
+
+ /* Round Mean Spads to Whole Number.
+ * Typically the calculated mean SPAD count is a whole number
+ * or very close to a whole
+ * number, therefore any truncation will not result in a
+ * significant loss in accuracy.
+ * Also, for a grey target at a typical distance of around
+ * 400mm, around 220 SPADs will
+ * be enabled, therefore, any truncation will result in a loss
+ * of accuracy of less than
+ * 0.5%.
+ */
+ xTalkStoredMeanRtnSpadsAsInt = (xTalkStoredMeanRtnSpads +
+ 0x8000) >> 16;
+
+ /* Round Cal Distance to Whole Number.
+ * Note that the cal distance is in mm, therefore no resolution
+ * is lost.
+ */
+ xTalkCalDistanceAsInt = (XTalkCalDistance + 0x8000) >> 16;
+
+ if (xTalkStoredMeanRtnSpadsAsInt == 0 ||
+ xTalkCalDistanceAsInt == 0 ||
+ xTalkStoredMeanRange >= XTalkCalDistance) {
+ XTalkCompensationRateMegaCps = 0;
+ } else {
+ /* Round Cal Distance to Whole Number.
+ * Note that the cal distance is in mm, therefore no
+ * resolution is lost.
+ */
+ xTalkCalDistanceAsInt = (XTalkCalDistance +
+ 0x8000) >> 16;
+
+ /* Apply division by mean spad count early in the
+ * calculation to keep the numbers small.
+ * This ensures we can maintain a 32bit calculation.
+ * Fixed1616 / int := Fixed1616
+ */
+ signalXTalkTotalPerSpad = (xTalkStoredMeanSignalRate) /
+ xTalkStoredMeanRtnSpadsAsInt;
+
+ /* Complete the calculation for total Signal XTalk per
+ * SPAD
+ * Fixed1616 * (Fixed1616 - Fixed1616/int) :=
+ * (2^16 * Fixed1616)
+ */
+ signalXTalkTotalPerSpad *= ((1 << 16) -
+ (xTalkStoredMeanRange / xTalkCalDistanceAsInt));
+
+ /* Round from 2^16 * Fixed1616, to Fixed1616. */
+ XTalkCompensationRateMegaCps = (signalXTalkTotalPerSpad
+ + 0x8000) >> 16;
+ }
+
+ *pXTalkCompensationRateMegaCps = XTalkCompensationRateMegaCps;
+
+ /* Enable the XTalk compensation */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetXTalkCompensationEnable(Dev, 1);
+
+ /* Enable the XTalk compensation */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetXTalkCompensationRateMegaCps(Dev,
+ XTalkCompensationRateMegaCps);
+
+ }
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_perform_offset_calibration(VL53L0_DEV Dev,
+ FixPoint1616_t CalDistanceMilliMeter,
+ int32_t *pOffsetMicroMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t sum_ranging = 0;
+ FixPoint1616_t total_count = 0;
+ VL53L0_RangingMeasurementData_t RangingMeasurementData;
+ FixPoint1616_t StoredMeanRange;
+ uint32_t StoredMeanRangeAsInt;
+ uint32_t CalDistanceAsInt_mm;
+ uint8_t SequenceStepEnabled;
+ int meas = 0;
+
+ if (CalDistanceMilliMeter <= 0)
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetOffsetCalibrationDataMicroMeter(Dev, 0);
+
+
+ /* Get the value of the TCC */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_TCC, &SequenceStepEnabled);
+
+
+ /* Disable the TCC */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_TCC, 0);
+
+
+ /* Disable the RIT */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_SetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0);
+
+ /* Perform 50 measurements and compute the averages */
+ if (Status == VL53L0_ERROR_NONE) {
+ sum_ranging = 0;
+ total_count = 0;
+ for (meas = 0; meas < 50; meas++) {
+ Status = VL53L0_PerformSingleRangingMeasurement(Dev,
+ &RangingMeasurementData);
+
+ if (Status != VL53L0_ERROR_NONE)
+ break;
+
+ /* The range is valid when RangeStatus = 0 */
+ if (RangingMeasurementData.RangeStatus == 0) {
+ sum_ranging = sum_ranging +
+ RangingMeasurementData.RangeMilliMeter;
+ total_count = total_count + 1;
+ }
+ }
+
+ /* no valid values found */
+ if (total_count == 0)
+ Status = VL53L0_ERROR_RANGE_ERROR;
+ }
+
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* FixPoint1616_t / uint16_t = FixPoint1616_t */
+ StoredMeanRange = (FixPoint1616_t)((uint32_t)(sum_ranging << 16)
+ / total_count);
+
+ StoredMeanRangeAsInt = (StoredMeanRange + 0x8000) >> 16;
+
+ /* Round Cal Distance to Whole Number.
+ * Note that the cal distance is in mm, therefore no resolution
+ * is lost.
+ */
+ CalDistanceAsInt_mm = (CalDistanceMilliMeter + 0x8000) >> 16;
+
+ *pOffsetMicroMeter = (CalDistanceAsInt_mm -
+ StoredMeanRangeAsInt) * 1000;
+
+ /* Apply the calculated offset */
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETPARAMETERFIELD(Dev, RangeOffsetMicroMeters,
+ *pOffsetMicroMeter);
+ Status = VL53L0_SetOffsetCalibrationDataMicroMeter(Dev,
+ *pOffsetMicroMeter);
+ }
+
+ }
+
+ /* Restore the TCC */
+ if (Status == VL53L0_ERROR_NONE) {
+ if (SequenceStepEnabled != 0)
+ Status = VL53L0_SetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_TCC, 1);
+ }
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_set_offset_calibration_data_micro_meter(VL53L0_DEV Dev,
+ int32_t OffsetCalibrationDataMicroMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t cMaxOffsetMicroMeter = 511000;
+ int32_t cMinOffsetMicroMeter = -512000;
+ int16_t cOffsetRange = 4096;
+ uint32_t encodedOffsetVal;
+
+ LOG_FUNCTION_START("");
+
+ if (OffsetCalibrationDataMicroMeter > cMaxOffsetMicroMeter)
+ OffsetCalibrationDataMicroMeter = cMaxOffsetMicroMeter;
+ else if (OffsetCalibrationDataMicroMeter < cMinOffsetMicroMeter)
+ OffsetCalibrationDataMicroMeter = cMinOffsetMicroMeter;
+
+ /* The offset register is 10.2 format and units are mm
+ * therefore conversion is applied by a division of
+ * 250.
+ */
+ if (OffsetCalibrationDataMicroMeter >= 0) {
+ encodedOffsetVal =
+ OffsetCalibrationDataMicroMeter/250;
+ } else {
+ encodedOffsetVal =
+ cOffsetRange +
+ OffsetCalibrationDataMicroMeter/250;
+ }
+
+ Status = VL53L0_WrWord(Dev,
+ VL53L0_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM,
+ encodedOffsetVal);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_offset_calibration_data_micro_meter(VL53L0_DEV Dev,
+ int32_t *pOffsetCalibrationDataMicroMeter)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint16_t RangeOffsetRegister;
+ int16_t cMaxOffset = 2047;
+ int16_t cOffsetRange = 4096;
+
+ /* Note that offset has 10.2 format */
+
+ Status = VL53L0_RdWord(Dev,
+ VL53L0_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM,
+ &RangeOffsetRegister);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ RangeOffsetRegister = (RangeOffsetRegister & 0x0fff);
+
+ /* Apply 12 bit 2's compliment conversion */
+ if (RangeOffsetRegister > cMaxOffset)
+ *pOffsetCalibrationDataMicroMeter =
+ (int16_t)(RangeOffsetRegister - cOffsetRange)
+ * 250;
+ else
+ *pOffsetCalibrationDataMicroMeter =
+ (int16_t)RangeOffsetRegister * 250;
+
+ }
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_apply_offset_adjustment(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t CorrectedOffsetMicroMeters;
+ int32_t CurrentOffsetMicroMeters;
+
+ /* if we run on this function we can read all the NVM info
+ * used by the API
+ */
+ Status = VL53L0_get_info_from_device(Dev, 7);
+
+ /* Read back current device offset */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetOffsetCalibrationDataMicroMeter(Dev,
+ &CurrentOffsetMicroMeters);
+ }
+
+ /* Apply Offset Adjustment derived from 400mm measurements */
+ if (Status == VL53L0_ERROR_NONE) {
+
+ /* Store initial device offset */
+ PALDevDataSet(Dev, Part2PartOffsetNVMMicroMeter,
+ CurrentOffsetMicroMeters);
+
+ CorrectedOffsetMicroMeters = CurrentOffsetMicroMeters +
+ (int32_t)PALDevDataGet(Dev,
+ Part2PartOffsetAdjustmentNVMMicroMeter);
+
+ Status = VL53L0_SetOffsetCalibrationDataMicroMeter(Dev,
+ CorrectedOffsetMicroMeters);
+
+ /* store current, adjusted offset */
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETPARAMETERFIELD(Dev, RangeOffsetMicroMeters,
+ CorrectedOffsetMicroMeters);
+ }
+ }
+
+ return Status;
+}
+
+void get_next_good_spad(uint8_t goodSpadArray[], uint32_t size,
+ uint32_t curr, int32_t *next)
+{
+ uint32_t startIndex;
+ uint32_t fineOffset;
+ uint32_t cSpadsPerByte = 8;
+ uint32_t coarseIndex;
+ uint32_t fineIndex;
+ uint8_t dataByte;
+ uint8_t success = 0;
+
+ /*
+ * Starting with the current good spad, loop through the array to find
+ * the next. i.e. the next bit set in the sequence.
+ *
+ * The coarse index is the byte index of the array and the fine index is
+ * the index of the bit within each byte.
+ */
+
+ *next = -1;
+
+ startIndex = curr / cSpadsPerByte;
+ fineOffset = curr % cSpadsPerByte;
+
+ for (coarseIndex = startIndex; ((coarseIndex < size) && !success);
+ coarseIndex++) {
+ fineIndex = 0;
+ dataByte = goodSpadArray[coarseIndex];
+
+ if (coarseIndex == startIndex) {
+ /* locate the bit position of the provided current
+ * spad bit before iterating
+ */
+ dataByte >>= fineOffset;
+ fineIndex = fineOffset;
+ }
+
+ while (fineIndex < cSpadsPerByte) {
+ if ((dataByte & 0x1) == 1) {
+ success = 1;
+ *next = coarseIndex * cSpadsPerByte + fineIndex;
+ break;
+ }
+ dataByte >>= 1;
+ fineIndex++;
+ }
+ }
+}
+
+
+uint8_t is_aperture(uint32_t spadIndex)
+{
+ /*
+ * This function reports if a given spad index is an aperture SPAD by
+ * deriving the quadrant.
+ */
+ uint32_t quadrant;
+ uint8_t isAperture = 1;
+
+ quadrant = spadIndex >> 6;
+ if (refArrayQuadrants[quadrant] == REF_ARRAY_SPAD_0)
+ isAperture = 0;
+
+ return isAperture;
+}
+
+
+VL53L0_Error enable_spad_bit(uint8_t spadArray[], uint32_t size,
+ uint32_t spadIndex)
+{
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+ uint32_t cSpadsPerByte = 8;
+ uint32_t coarseIndex;
+ uint32_t fineIndex;
+
+ coarseIndex = spadIndex / cSpadsPerByte;
+ fineIndex = spadIndex % cSpadsPerByte;
+ if (coarseIndex >= size)
+ status = VL53L0_ERROR_REF_SPAD_INIT;
+ else
+ spadArray[coarseIndex] |= (1 << fineIndex);
+
+ return status;
+}
+
+VL53L0_Error count_enabled_spads(uint8_t spadArray[],
+ uint32_t byteCount, uint32_t maxSpads,
+ uint32_t *pTotalSpadsEnabled, uint8_t *pIsAperture)
+{
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+ uint32_t cSpadsPerByte = 8;
+ uint32_t lastByte;
+ uint32_t lastBit;
+ uint32_t byteIndex = 0;
+ uint32_t bitIndex = 0;
+ uint8_t tempByte;
+ uint8_t spadTypeIdentified = 0;
+
+ /* The entire array will not be used for spads, therefore the last
+ * byte and last bit is determined from the max spads value.
+ */
+
+ lastByte = maxSpads / cSpadsPerByte;
+ lastBit = maxSpads % cSpadsPerByte;
+
+ /* Check that the max spads value does not exceed the array bounds. */
+ if (lastByte >= byteCount)
+ status = VL53L0_ERROR_REF_SPAD_INIT;
+
+ *pTotalSpadsEnabled = 0;
+
+ /* Count the bits enabled in the whole bytes */
+ for (byteIndex = 0; byteIndex <= (lastByte - 1); byteIndex++) {
+ tempByte = spadArray[byteIndex];
+
+ for (bitIndex = 0; bitIndex <= cSpadsPerByte; bitIndex++) {
+ if ((tempByte & 0x01) == 1) {
+ (*pTotalSpadsEnabled)++;
+
+ if (!spadTypeIdentified) {
+ *pIsAperture = 1;
+ if ((byteIndex < 2) && (bitIndex < 4))
+ *pIsAperture = 0;
+ spadTypeIdentified = 1;
+ }
+ }
+ tempByte >>= 1;
+ }
+ }
+
+ /* Count the number of bits enabled in the last byte accounting
+ * for the fact that not all bits in the byte may be used.
+ */
+ tempByte = spadArray[lastByte];
+
+ for (bitIndex = 0; bitIndex <= lastBit; bitIndex++) {
+ if ((tempByte & 0x01) == 1)
+ (*pTotalSpadsEnabled)++;
+ }
+
+ return status;
+}
+
+VL53L0_Error set_ref_spad_map(VL53L0_DEV Dev, uint8_t *refSpadArray)
+{
+ VL53L0_Error status = VL53L0_WriteMulti(Dev,
+ VL53L0_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0,
+ refSpadArray, 6);
+ return status;
+}
+
+VL53L0_Error get_ref_spad_map(VL53L0_DEV Dev, uint8_t *refSpadArray)
+{
+ VL53L0_Error status = VL53L0_ReadMulti(Dev,
+ VL53L0_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0,
+ refSpadArray,
+ 6);
+ return status;
+}
+
+VL53L0_Error enable_ref_spads(VL53L0_DEV Dev,
+ uint8_t apertureSpads,
+ uint8_t goodSpadArray[],
+ uint8_t spadArray[],
+ uint32_t size,
+ uint32_t start,
+ uint32_t offset,
+ uint32_t spadCount,
+ uint32_t *lastSpad)
+{
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+ uint32_t index;
+ uint32_t i;
+ int32_t nextGoodSpad = offset;
+ uint32_t currentSpad;
+ uint8_t checkSpadArray[6];
+
+ /*
+ * This function takes in a spad array which may or may not have SPADS
+ * already enabled and appends from a given offset a requested number
+ * of new SPAD enables. The 'good spad map' is applied to
+ * determine the next SPADs to enable.
+ *
+ * This function applies to only aperture or only non-aperture spads.
+ * Checks are performed to ensure this.
+ */
+
+ currentSpad = offset;
+ for (index = 0; index < spadCount; index++) {
+ get_next_good_spad(goodSpadArray, size, currentSpad,
+ &nextGoodSpad);
+
+ if (nextGoodSpad == -1) {
+ status = VL53L0_ERROR_REF_SPAD_INIT;
+ break;
+ }
+
+ /* Confirm that the next good SPAD is non-aperture */
+ if (is_aperture(start + nextGoodSpad) != apertureSpads) {
+ /* if we can't get the required number of good aperture
+ * spads from the current quadrant then this is an error
+ */
+ status = VL53L0_ERROR_REF_SPAD_INIT;
+ break;
+ }
+ currentSpad = (uint32_t)nextGoodSpad;
+ enable_spad_bit(spadArray, size, currentSpad);
+ currentSpad++;
+ }
+ *lastSpad = currentSpad;
+
+ if (status == VL53L0_ERROR_NONE)
+ status = set_ref_spad_map(Dev, spadArray);
+
+
+ if (status == VL53L0_ERROR_NONE) {
+ status = get_ref_spad_map(Dev, checkSpadArray);
+
+ i = 0;
+
+ /* Compare spad maps. If not equal report error. */
+ while (i < size) {
+ if (spadArray[i] != checkSpadArray[i]) {
+ status = VL53L0_ERROR_REF_SPAD_INIT;
+ break;
+ }
+ i++;
+ }
+ }
+ return status;
+}
+
+
+VL53L0_Error perform_ref_signal_measurement(VL53L0_DEV Dev,
+ uint16_t *refSignalRate)
+{
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+ VL53L0_RangingMeasurementData_t rangingMeasurementData;
+
+ uint8_t SequenceConfig = 0;
+
+ /* store the value of the sequence config,
+ * this will be reset before the end of the function
+ */
+
+ SequenceConfig = PALDevDataGet(Dev, SequenceConfig);
+
+ /*
+ * This function performs a reference signal rate measurement.
+ */
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_WrByte(Dev,
+ VL53L0_REG_SYSTEM_SEQUENCE_CONFIG, 0xC0);
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_PerformSingleRangingMeasurement(Dev,
+ &rangingMeasurementData);
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_RdWord(Dev,
+ VL53L0_REG_RESULT_PEAK_SIGNAL_RATE_REF,
+ refSignalRate);
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ if (status == VL53L0_ERROR_NONE) {
+ /* restore the previous Sequence Config */
+ status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG,
+ SequenceConfig);
+ if (status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, SequenceConfig, SequenceConfig);
+ }
+
+ return status;
+}
+
+VL53L0_Error VL53L0_perform_ref_spad_management(VL53L0_DEV Dev,
+ uint32_t *refSpadCount,
+ uint8_t *isApertureSpads)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t lastSpadArray[6];
+ uint8_t startSelect = 0xB4;
+ uint32_t minimumSpadCount = 3;
+ uint32_t maxSpadCount = 44;
+ uint32_t currentSpadIndex = 0;
+ uint32_t lastSpadIndex = 0;
+ int32_t nextGoodSpad = 0;
+ uint16_t targetRefRate = 0x0A00; /* 20 MCPS in 9:7 format */
+ uint16_t peakSignalRateRef;
+ uint32_t needAptSpads = 0;
+ uint32_t index = 0;
+ uint32_t spadArraySize = 6;
+ uint32_t signalRateDiff = 0;
+ uint32_t lastSignalRateDiff = 0;
+ uint8_t complete = 0;
+ uint8_t VhvSettings = 0;
+ uint8_t PhaseCal = 0;
+ uint32_t refSpadCount_int = 0;
+ uint8_t isApertureSpads_int = 0;
+
+ /*
+ * The reference SPAD initialization procedure determines the minimum
+ * amount of reference spads to be enables to achieve a target reference
+ * signal rate and should be performed once during initialization.
+ *
+ * Either aperture or non-aperture spads are applied but never both.
+ * Firstly non-aperture spads are set, begining with 5 spads, and
+ * increased one spad at a time until the closest measurement to the
+ * target rate is achieved.
+ *
+ * If the target rate is exceeded when 5 non-aperture spads are enabled,
+ * initialization is performed instead with aperture spads.
+ *
+ * When setting spads, a 'Good Spad Map' is applied.
+ *
+ * This procedure operates within a SPAD window of interest of a maximum
+ * 44 spads.
+ * The start point is currently fixed to 180, which lies towards the end
+ * of the non-aperture quadrant and runs in to the adjacent aperture
+ * quadrant.
+ */
+
+
+ targetRefRate = PALDevDataGet(Dev, targetRefRate);
+
+ /*
+ * Initialize Spad arrays.
+ * Currently the good spad map is initialised to 'All good'.
+ * This is a short term implementation. The good spad map will be
+ * provided as an input.
+ * Note that there are 6 bytes. Only the first 44 bits will be used to
+ * represent spads.
+ */
+ for (index = 0; index < spadArraySize; index++)
+ Dev->Data.SpadData.RefSpadEnables[index] = 0;
+
+
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET, 0x00);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD, 0x2C);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_GLOBAL_CONFIG_REF_EN_START_SELECT,
+ startSelect);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_POWER_MANAGEMENT_GO1_POWER_FORCE, 0);
+
+ /* Perform ref calibration */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_perform_ref_calibration(Dev, &VhvSettings,
+ &PhaseCal, 0);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Enable Minimum NON-APERTURE Spads */
+ currentSpadIndex = 0;
+ lastSpadIndex = currentSpadIndex;
+ needAptSpads = 0;
+ Status = enable_ref_spads(Dev,
+ needAptSpads,
+ Dev->Data.SpadData.RefGoodSpadMap,
+ Dev->Data.SpadData.RefSpadEnables,
+ spadArraySize,
+ startSelect,
+ currentSpadIndex,
+ minimumSpadCount,
+ &lastSpadIndex);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ currentSpadIndex = lastSpadIndex;
+
+ Status = perform_ref_signal_measurement(Dev,
+ &peakSignalRateRef);
+ if ((Status == VL53L0_ERROR_NONE) &&
+ (peakSignalRateRef > targetRefRate)) {
+ /* Signal rate measurement too high,
+ * switch to APERTURE SPADs
+ */
+
+ for (index = 0; index < spadArraySize; index++)
+ Dev->Data.SpadData.RefSpadEnables[index] = 0;
+
+
+ /* Increment to the first APERTURE spad */
+ while ((is_aperture(startSelect + currentSpadIndex)
+ == 0) && (currentSpadIndex < maxSpadCount)) {
+ currentSpadIndex++;
+ }
+
+ needAptSpads = 1;
+
+ Status = enable_ref_spads(Dev,
+ needAptSpads,
+ Dev->Data.SpadData.RefGoodSpadMap,
+ Dev->Data.SpadData.RefSpadEnables,
+ spadArraySize,
+ startSelect,
+ currentSpadIndex,
+ minimumSpadCount,
+ &lastSpadIndex);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ currentSpadIndex = lastSpadIndex;
+ Status = perform_ref_signal_measurement(Dev,
+ &peakSignalRateRef);
+
+ if ((Status == VL53L0_ERROR_NONE) &&
+ (peakSignalRateRef > targetRefRate)) {
+ /* Signal rate still too high after
+ * setting the minimum number of
+ * APERTURE spads. Can do no more
+ * therefore set the min number of
+ * aperture spads as the result.
+ */
+ isApertureSpads_int = 1;
+ refSpadCount_int = minimumSpadCount;
+ }
+ }
+ } else {
+ needAptSpads = 0;
+ }
+ }
+
+ if ((Status == VL53L0_ERROR_NONE) &&
+ (peakSignalRateRef < targetRefRate)) {
+ /* At this point, the minimum number of either aperture
+ * or non-aperture spads have been set. Proceed to add
+ * spads and perform measurements until the target
+ * reference is reached.
+ */
+ isApertureSpads_int = needAptSpads;
+ refSpadCount_int = minimumSpadCount;
+
+ memcpy(lastSpadArray, Dev->Data.SpadData.RefSpadEnables,
+ spadArraySize);
+ lastSignalRateDiff = abs(peakSignalRateRef -
+ targetRefRate);
+ complete = 0;
+
+ while (!complete) {
+ get_next_good_spad(
+ Dev->Data.SpadData.RefGoodSpadMap,
+ spadArraySize, currentSpadIndex,
+ &nextGoodSpad);
+
+ if (nextGoodSpad == -1) {
+ Status = VL53L0_ERROR_REF_SPAD_INIT;
+ break;
+ }
+
+ (refSpadCount_int)++;
+
+ /* Cannot combine Aperture and Non-Aperture spads, so
+ * ensure the current spad is of the correct type.
+ */
+ if (is_aperture((uint32_t)startSelect + nextGoodSpad) !=
+ needAptSpads) {
+ Status = VL53L0_ERROR_REF_SPAD_INIT;
+ break;
+ }
+
+ currentSpadIndex = nextGoodSpad;
+ Status = enable_spad_bit(
+ Dev->Data.SpadData.RefSpadEnables,
+ spadArraySize, currentSpadIndex);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ currentSpadIndex++;
+ /* Proceed to apply the additional spad and
+ * perform measurement.
+ */
+ Status = set_ref_spad_map(Dev,
+ Dev->Data.SpadData.RefSpadEnables);
+ }
+
+ if (Status != VL53L0_ERROR_NONE)
+ break;
+
+ Status = perform_ref_signal_measurement(Dev,
+ &peakSignalRateRef);
+
+ if (Status != VL53L0_ERROR_NONE)
+ break;
+
+ signalRateDiff = abs(peakSignalRateRef - targetRefRate);
+
+ if (peakSignalRateRef > targetRefRate) {
+ /* Select the spad map that provides the
+ * measurement closest to the target rate,
+ * either above or below it.
+ */
+ if (signalRateDiff > lastSignalRateDiff) {
+ /* Previous spad map produced a closer
+ * measurement, so choose this.
+ */
+ Status = set_ref_spad_map(Dev,
+ lastSpadArray);
+ memcpy(
+ Dev->Data.SpadData.RefSpadEnables,
+ lastSpadArray, spadArraySize);
+
+ (refSpadCount_int)--;
+ }
+ complete = 1;
+ } else {
+ /* Continue to add spads */
+ lastSignalRateDiff = signalRateDiff;
+ memcpy(lastSpadArray,
+ Dev->Data.SpadData.RefSpadEnables,
+ spadArraySize);
+ }
+
+ } /* while */
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ *refSpadCount = refSpadCount_int;
+ *isApertureSpads = isApertureSpads_int;
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev, RefSpadsInitialised, 1);
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadCount, (uint8_t)(*refSpadCount));
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadType, *isApertureSpads);
+ }
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_set_reference_spads(VL53L0_DEV Dev,
+ uint32_t count, uint8_t isApertureSpads)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint32_t currentSpadIndex = 0;
+ uint8_t startSelect = 0xB4;
+ uint32_t spadArraySize = 6;
+ uint32_t maxSpadCount = 44;
+ uint32_t lastSpadIndex;
+ uint32_t index;
+
+ /*
+ * This function applies a requested number of reference spads, either
+ * aperture or
+ * non-aperture, as requested.
+ * The good spad map will be applied.
+ */
+
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET, 0x00);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD, 0x2C);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_GLOBAL_CONFIG_REF_EN_START_SELECT,
+ startSelect);
+
+ for (index = 0; index < spadArraySize; index++)
+ Dev->Data.SpadData.RefSpadEnables[index] = 0;
+
+ if (isApertureSpads) {
+ /* Increment to the first APERTURE spad */
+ while ((is_aperture(startSelect + currentSpadIndex) == 0) &&
+ (currentSpadIndex < maxSpadCount)) {
+ currentSpadIndex++;
+ }
+ }
+ Status = enable_ref_spads(Dev,
+ isApertureSpads,
+ Dev->Data.SpadData.RefGoodSpadMap,
+ Dev->Data.SpadData.RefSpadEnables,
+ spadArraySize,
+ startSelect,
+ currentSpadIndex,
+ count,
+ &lastSpadIndex);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev, RefSpadsInitialised, 1);
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadCount, (uint8_t)(count));
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadType, isApertureSpads);
+ }
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_reference_spads(VL53L0_DEV Dev,
+ uint32_t *pSpadCount, uint8_t *pIsApertureSpads)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t refSpadsInitialised;
+ uint8_t refSpadArray[6];
+ uint32_t cMaxSpadCount = 44;
+ uint32_t cSpadArraySize = 6;
+ uint32_t spadsEnabled;
+ uint8_t isApertureSpads = 0;
+
+ refSpadsInitialised = VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ RefSpadsInitialised);
+
+ if (refSpadsInitialised == 1) {
+
+ *pSpadCount = (uint32_t)VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadCount);
+ *pIsApertureSpads = VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadType);
+ } else {
+
+ /* obtain spad info from device.*/
+ Status = get_ref_spad_map(Dev, refSpadArray);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* count enabled spads within spad map array and
+ * determine if Aperture or Non-Aperture.
+ */
+ Status = count_enabled_spads(refSpadArray,
+ cSpadArraySize,
+ cMaxSpadCount,
+ &spadsEnabled,
+ &isApertureSpads);
+
+ if (Status == VL53L0_ERROR_NONE) {
+
+ *pSpadCount = spadsEnabled;
+ *pIsApertureSpads = isApertureSpads;
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ RefSpadsInitialised, 1);
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadCount,
+ (uint8_t)spadsEnabled);
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadType, isApertureSpads);
+ }
+ }
+ }
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_perform_single_ref_calibration(VL53L0_DEV Dev,
+ uint8_t vhv_init_byte)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSRANGE_START,
+ VL53L0_REG_SYSRANGE_MODE_START_STOP |
+ vhv_init_byte);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_measurement_poll_for_completion(Dev);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_ClearInterruptMask(Dev, 0);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSRANGE_START, 0x00);
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_ref_calibration_io(VL53L0_DEV Dev, uint8_t read_not_write,
+ uint8_t VhvSettings, uint8_t PhaseCal,
+ uint8_t *pVhvSettings, uint8_t *pPhaseCal,
+ const uint8_t vhv_enable, const uint8_t phase_enable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t PhaseCalint = 0;
+
+ /* Read VHV from device */
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ if (read_not_write) {
+ if (vhv_enable)
+ Status |= VL53L0_RdByte(Dev, 0xCB, pVhvSettings);
+ if (phase_enable)
+ Status |= VL53L0_RdByte(Dev, 0xEE, &PhaseCalint);
+ } else {
+ if (vhv_enable)
+ Status |= VL53L0_WrByte(Dev, 0xCB, VhvSettings);
+ if (phase_enable)
+ Status |= VL53L0_UpdateByte(Dev, 0xEE, 0x80, PhaseCal);
+ }
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ *pPhaseCal = (uint8_t)(PhaseCalint&0xEF);
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_perform_vhv_calibration(VL53L0_DEV Dev,
+ uint8_t *pVhvSettings, const uint8_t get_data_enable,
+ const uint8_t restore_config)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t SequenceConfig = 0;
+ uint8_t VhvSettings = 0;
+ uint8_t PhaseCal = 0;
+ uint8_t PhaseCalInt = 0;
+
+ /* store the value of the sequence config,
+ * this will be reset before the end of the function
+ */
+
+ if (restore_config)
+ SequenceConfig = PALDevDataGet(Dev, SequenceConfig);
+
+ /* Run VHV */
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG, 0x01);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_perform_single_ref_calibration(Dev, 0x40);
+
+ /* Read VHV from device */
+ if ((Status == VL53L0_ERROR_NONE) && (get_data_enable == 1)) {
+ Status = VL53L0_ref_calibration_io(Dev, 1,
+ VhvSettings, PhaseCal, /* Not used here */
+ pVhvSettings, &PhaseCalInt,
+ 1, 0);
+ } else
+ *pVhvSettings = 0;
+
+
+ if ((Status == VL53L0_ERROR_NONE) && restore_config) {
+ /* restore the previous Sequence Config */
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG,
+ SequenceConfig);
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, SequenceConfig, SequenceConfig);
+
+ }
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_perform_phase_calibration(VL53L0_DEV Dev,
+ uint8_t *pPhaseCal, const uint8_t get_data_enable,
+ const uint8_t restore_config)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t SequenceConfig = 0;
+ uint8_t VhvSettings = 0;
+ uint8_t PhaseCal = 0;
+ uint8_t VhvSettingsint;
+
+ /* store the value of the sequence config,
+ * this will be reset before the end of the function
+ */
+
+ if (restore_config)
+ SequenceConfig = PALDevDataGet(Dev, SequenceConfig);
+
+ /* Run PhaseCal */
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG, 0x02);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_perform_single_ref_calibration(Dev, 0x0);
+
+ /* Read PhaseCal from device */
+ if ((Status == VL53L0_ERROR_NONE) && (get_data_enable == 1)) {
+ Status = VL53L0_ref_calibration_io(Dev, 1,
+ VhvSettings, PhaseCal, /* Not used here */
+ &VhvSettingsint, pPhaseCal,
+ 0, 1);
+ } else
+ *pPhaseCal = 0;
+
+
+ if ((Status == VL53L0_ERROR_NONE) && restore_config) {
+ /* restore the previous Sequence Config */
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG,
+ SequenceConfig);
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, SequenceConfig, SequenceConfig);
+
+ }
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_perform_ref_calibration(VL53L0_DEV Dev,
+ uint8_t *pVhvSettings, uint8_t *pPhaseCal, uint8_t get_data_enable)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t SequenceConfig = 0;
+
+ /* store the value of the sequence config,
+ * this will be reset before the end of the function
+ */
+
+ SequenceConfig = PALDevDataGet(Dev, SequenceConfig);
+
+ /* In the following function we don't save the config to optimize
+ * writes on device. Config is saved and restored only once.
+ */
+ Status = VL53L0_perform_vhv_calibration(
+ Dev, pVhvSettings, get_data_enable, 0);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_perform_phase_calibration(
+ Dev, pPhaseCal, get_data_enable, 0);
+
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* restore the previous Sequence Config */
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_SEQUENCE_CONFIG,
+ SequenceConfig);
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, SequenceConfig, SequenceConfig);
+
+ }
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_set_ref_calibration(VL53L0_DEV Dev,
+ uint8_t VhvSettings, uint8_t PhaseCal)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t pVhvSettings;
+ uint8_t pPhaseCal;
+
+ Status = VL53L0_ref_calibration_io(Dev, 0,
+ VhvSettings, PhaseCal,
+ &pVhvSettings, &pPhaseCal,
+ 1, 1);
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_ref_calibration(VL53L0_DEV Dev,
+ uint8_t *pVhvSettings, uint8_t *pPhaseCal)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t VhvSettings = 0;
+ uint8_t PhaseCal = 0;
+
+ Status = VL53L0_ref_calibration_io(Dev, 1,
+ VhvSettings, PhaseCal,
+ pVhvSettings, pPhaseCal,
+ 1, 1);
+
+ return Status;
+}
diff --git a/drivers/input/misc/vl53L0/src/vl53l0_api_core.c b/drivers/input/misc/vl53L0/src/vl53l0_api_core.c
new file mode 100644
index 000000000000..a04d0c4f5915
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l0_api_core.c
@@ -0,0 +1,2270 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+ IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#include "vl53l0_api.h"
+#include "vl53l0_api_core.h"
+#include "vl53l0_api_calibration.h"
+
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#endif
+#define LOG_FUNCTION_START(fmt, ...) \
+ _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
+#define LOG_FUNCTION_END(status, ...) \
+ _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
+#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
+ _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
+
+VL53L0_Error VL53L0_reverse_bytes(uint8_t *data, uint32_t size)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t tempData;
+ uint32_t mirrorIndex;
+ uint32_t middle = size/2;
+ uint32_t index;
+
+ for (index = 0; index < middle; index++) {
+ mirrorIndex = size - index - 1;
+ tempData = data[index];
+ data[index] = data[mirrorIndex];
+ data[mirrorIndex] = tempData;
+ }
+ return Status;
+}
+
+VL53L0_Error VL53L0_measurement_poll_for_completion(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t NewDataReady = 0;
+ uint32_t LoopNb;
+
+ LOG_FUNCTION_START("");
+
+ LoopNb = 0;
+
+ do {
+ Status = VL53L0_GetMeasurementDataReady(Dev, &NewDataReady);
+ if (Status != 0)
+ break; /* the error is set */
+
+ if (NewDataReady == 1)
+ break; /* done note that status == 0 */
+
+ LoopNb++;
+ if (LoopNb >= VL53L0_DEFAULT_MAX_LOOP) {
+ Status = VL53L0_ERROR_TIME_OUT;
+ break;
+ }
+
+ VL53L0_PollingDelay(Dev);
+ } while (1);
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+
+uint8_t VL53L0_decode_vcsel_period(uint8_t vcsel_period_reg)
+{
+ /*!
+ * Converts the encoded VCSEL period register value into the real
+ * period in PLL clocks
+ */
+
+ uint8_t vcsel_period_pclks = 0;
+
+ vcsel_period_pclks = (vcsel_period_reg + 1) << 1;
+
+ return vcsel_period_pclks;
+}
+
+uint8_t VL53L0_encode_vcsel_period(uint8_t vcsel_period_pclks)
+{
+ /*!
+ * Converts the encoded VCSEL period register value into the real period
+ * in PLL clocks
+ */
+
+ uint8_t vcsel_period_reg = 0;
+
+ vcsel_period_reg = (vcsel_period_pclks >> 1) - 1;
+
+ return vcsel_period_reg;
+}
+
+
+uint32_t VL53L0_isqrt(uint32_t num)
+{
+ /*
+ * Implements an integer square root
+ *
+ * From: http://en.wikipedia.org/wiki/Methods_of_computing_square_roots
+ */
+
+ uint32_t res = 0;
+ uint32_t bit = 1 << 30;
+ /* The second-to-top bit is set:
+ * 1 << 14 for 16-bits, 1 << 30 for 32 bits
+ */
+
+ /* "bit" starts at the highest power of four <= the argument. */
+ while (bit > num)
+ bit >>= 2;
+
+
+ while (bit != 0) {
+ if (num >= res + bit) {
+ num -= res + bit;
+ res = (res >> 1) + bit;
+ } else
+ res >>= 1;
+
+ bit >>= 2;
+ }
+
+ return res;
+}
+
+
+uint32_t VL53L0_quadrature_sum(uint32_t a, uint32_t b)
+{
+ /*
+ * Implements a quadrature sum
+ *
+ * rea = sqrt(a^2 + b^2)
+ *
+ * Trap overflow case max input value is 65535 (16-bit value)
+ * as internal calc are 32-bit wide
+ *
+ * If overflow then seta output to maximum
+ */
+ uint32_t res = 0;
+
+ if (a > 65535 || b > 65535)
+ res = 65535;
+ else
+ res = VL53L0_isqrt(a * a + b * b);
+
+ return res;
+}
+
+
+VL53L0_Error VL53L0_device_read_strobe(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t strobe;
+ uint32_t LoopNb;
+
+ LOG_FUNCTION_START("");
+
+ Status |= VL53L0_WrByte(Dev, 0x83, 0x00);
+
+ /* polling
+ * use timeout to avoid deadlock
+ */
+ if (Status == VL53L0_ERROR_NONE) {
+ LoopNb = 0;
+ do {
+ Status = VL53L0_RdByte(Dev, 0x83, &strobe);
+ if ((strobe != 0x00) || Status != VL53L0_ERROR_NONE)
+ break;
+
+ LoopNb = LoopNb + 1;
+ } while (LoopNb < VL53L0_DEFAULT_MAX_LOOP);
+
+ if (LoopNb >= VL53L0_DEFAULT_MAX_LOOP)
+ Status = VL53L0_ERROR_TIME_OUT;
+
+ }
+
+ Status |= VL53L0_WrByte(Dev, 0x83, 0x01);
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
+
+VL53L0_Error VL53L0_get_info_from_device(VL53L0_DEV Dev, uint8_t option)
+{
+
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t byte;
+ uint32_t TmpDWord;
+ uint8_t ModuleId;
+ uint8_t Revision;
+ uint8_t ReferenceSpadCount = 0;
+ uint8_t ReferenceSpadType = 0;
+ uint32_t PartUIDUpper = 0;
+ uint32_t PartUIDLower = 0;
+ uint32_t OffsetFixed1104_mm = 0;
+ int16_t OffsetMicroMeters = 0;
+ uint32_t DistMeasTgtFixed1104_mm = 400 << 4;
+ uint32_t DistMeasFixed1104_400_mm = 0;
+ uint32_t SignalRateMeasFixed1104_400_mm = 0;
+ char ProductId[19];
+ char *ProductId_tmp;
+ uint8_t ReadDataFromDeviceDone;
+ FixPoint1616_t SignalRateMeasFixed400mmFix = 0;
+ uint8_t NvmRefGoodSpadMap[VL53L0_REF_SPAD_BUFFER_SIZE];
+ int i;
+
+
+ LOG_FUNCTION_START("");
+
+ ReadDataFromDeviceDone = VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ ReadDataFromDeviceDone);
+
+ /* This access is done only once after that a GetDeviceInfo or
+ * datainit is done
+ */
+ if (ReadDataFromDeviceDone != 7) {
+
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x00);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x06);
+ Status |= VL53L0_RdByte(Dev, 0x83, &byte);
+ Status |= VL53L0_WrByte(Dev, 0x83, byte|4);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x07);
+ Status |= VL53L0_WrByte(Dev, 0x81, 0x01);
+
+ Status |= VL53L0_PollingDelay(Dev);
+
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x01);
+
+ if (((option & 1) == 1) &&
+ ((ReadDataFromDeviceDone & 1) == 0)) {
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x6b);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ReferenceSpadCount = (uint8_t)((TmpDWord >> 8) & 0x07f);
+ ReferenceSpadType = (uint8_t)((TmpDWord >> 15) & 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x24);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+
+ NvmRefGoodSpadMap[0] = (uint8_t)((TmpDWord >> 24)
+ & 0xff);
+ NvmRefGoodSpadMap[1] = (uint8_t)((TmpDWord >> 16)
+ & 0xff);
+ NvmRefGoodSpadMap[2] = (uint8_t)((TmpDWord >> 8)
+ & 0xff);
+ NvmRefGoodSpadMap[3] = (uint8_t)(TmpDWord & 0xff);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x25);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ NvmRefGoodSpadMap[4] = (uint8_t)((TmpDWord >> 24)
+ & 0xff);
+ NvmRefGoodSpadMap[5] = (uint8_t)((TmpDWord >> 16)
+ & 0xff);
+ }
+
+ if (((option & 2) == 2) &&
+ ((ReadDataFromDeviceDone & 2) == 0)) {
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x02);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdByte(Dev, 0x90, &ModuleId);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x7B);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdByte(Dev, 0x90, &Revision);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x77);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ProductId[0] = (char)((TmpDWord >> 25) & 0x07f);
+ ProductId[1] = (char)((TmpDWord >> 18) & 0x07f);
+ ProductId[2] = (char)((TmpDWord >> 11) & 0x07f);
+ ProductId[3] = (char)((TmpDWord >> 4) & 0x07f);
+
+ byte = (uint8_t)((TmpDWord & 0x00f) << 3);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x78);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ProductId[4] = (char)(byte +
+ ((TmpDWord >> 29) & 0x07f));
+ ProductId[5] = (char)((TmpDWord >> 22) & 0x07f);
+ ProductId[6] = (char)((TmpDWord >> 15) & 0x07f);
+ ProductId[7] = (char)((TmpDWord >> 8) & 0x07f);
+ ProductId[8] = (char)((TmpDWord >> 1) & 0x07f);
+
+ byte = (uint8_t)((TmpDWord & 0x001) << 6);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x79);
+
+ Status |= VL53L0_device_read_strobe(Dev);
+
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ProductId[9] = (char)(byte +
+ ((TmpDWord >> 26) & 0x07f));
+ ProductId[10] = (char)((TmpDWord >> 19) & 0x07f);
+ ProductId[11] = (char)((TmpDWord >> 12) & 0x07f);
+ ProductId[12] = (char)((TmpDWord >> 5) & 0x07f);
+
+ byte = (uint8_t)((TmpDWord & 0x01f) << 2);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x7A);
+
+ Status |= VL53L0_device_read_strobe(Dev);
+
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ ProductId[13] = (char)(byte +
+ ((TmpDWord >> 30) & 0x07f));
+ ProductId[14] = (char)((TmpDWord >> 23) & 0x07f);
+ ProductId[15] = (char)((TmpDWord >> 16) & 0x07f);
+ ProductId[16] = (char)((TmpDWord >> 9) & 0x07f);
+ ProductId[17] = (char)((TmpDWord >> 2) & 0x07f);
+ ProductId[18] = '\0';
+
+ }
+
+ if (((option & 4) == 4) &&
+ ((ReadDataFromDeviceDone & 4) == 0)) {
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x7B);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &PartUIDUpper);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x7C);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &PartUIDLower);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x73);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ SignalRateMeasFixed1104_400_mm = (TmpDWord &
+ 0x0000000ff) << 8;
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x74);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ SignalRateMeasFixed1104_400_mm |= ((TmpDWord &
+ 0xff000000) >> 24);
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x75);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ DistMeasFixed1104_400_mm = (TmpDWord & 0x0000000ff)
+ << 8;
+
+ Status |= VL53L0_WrByte(Dev, 0x94, 0x76);
+ Status |= VL53L0_device_read_strobe(Dev);
+ Status |= VL53L0_RdDWord(Dev, 0x90, &TmpDWord);
+
+ DistMeasFixed1104_400_mm |= ((TmpDWord & 0xff000000)
+ >> 24);
+ }
+
+ Status |= VL53L0_WrByte(Dev, 0x81, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x06);
+ Status |= VL53L0_RdByte(Dev, 0x83, &byte);
+ Status |= VL53L0_WrByte(Dev, 0x83, byte&0xfb);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x01);
+ Status |= VL53L0_WrByte(Dev, 0x00, 0x01);
+
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+ Status |= VL53L0_WrByte(Dev, 0x80, 0x00);
+ }
+
+ if ((Status == VL53L0_ERROR_NONE) &&
+ (ReadDataFromDeviceDone != 7)) {
+ /* Assign to variable if status is ok */
+ if (((option & 1) == 1) &&
+ ((ReadDataFromDeviceDone & 1) == 0)) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadCount, ReferenceSpadCount);
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ ReferenceSpadType, ReferenceSpadType);
+
+ for (i = 0; i < VL53L0_REF_SPAD_BUFFER_SIZE; i++) {
+ Dev->Data.SpadData.RefGoodSpadMap[i] =
+ NvmRefGoodSpadMap[i];
+ }
+ }
+
+ if (((option & 2) == 2) &&
+ ((ReadDataFromDeviceDone & 2) == 0)) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ ModuleId, ModuleId);
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ Revision, Revision);
+
+ ProductId_tmp = VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ ProductId);
+ VL53L0_COPYSTRING(ProductId_tmp, ProductId);
+
+ }
+
+ if (((option & 4) == 4) &&
+ ((ReadDataFromDeviceDone & 4) == 0)) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ PartUIDUpper, PartUIDUpper);
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ PartUIDLower, PartUIDLower);
+
+ SignalRateMeasFixed400mmFix =
+ VL53L0_FIXPOINT97TOFIXPOINT1616(
+ SignalRateMeasFixed1104_400_mm);
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ SignalRateMeasFixed400mm,
+ SignalRateMeasFixed400mmFix);
+
+ OffsetMicroMeters = 0;
+ if (DistMeasFixed1104_400_mm != 0) {
+ OffsetFixed1104_mm =
+ DistMeasFixed1104_400_mm -
+ DistMeasTgtFixed1104_mm;
+ OffsetMicroMeters = (OffsetFixed1104_mm
+ * 1000) >> 4;
+ OffsetMicroMeters *= -1;
+ }
+
+ PALDevDataSet(Dev,
+ Part2PartOffsetAdjustmentNVMMicroMeter,
+ OffsetMicroMeters);
+ }
+ byte = (uint8_t)(ReadDataFromDeviceDone|option);
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev, ReadDataFromDeviceDone,
+ byte);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+
+uint32_t VL53L0_calc_macro_period_ps(VL53L0_DEV Dev, uint8_t vcsel_period_pclks)
+{
+ uint64_t PLL_period_ps;
+ uint32_t macro_period_vclks;
+ uint32_t macro_period_ps;
+
+ LOG_FUNCTION_START("");
+
+ /* The above calculation will produce rounding errors,
+ * therefore set fixed value
+ */
+ PLL_period_ps = 1655;
+
+ macro_period_vclks = 2304;
+ macro_period_ps = (uint32_t)(macro_period_vclks
+ * vcsel_period_pclks * PLL_period_ps);
+
+ LOG_FUNCTION_END("");
+ return macro_period_ps;
+}
+
+uint16_t VL53L0_encode_timeout(uint32_t timeout_macro_clks)
+{
+ /*!
+ * Encode timeout in macro periods in (LSByte * 2^MSByte) + 1 format
+ */
+
+ uint16_t encoded_timeout = 0;
+ uint32_t ls_byte = 0;
+ uint16_t ms_byte = 0;
+
+ if (timeout_macro_clks > 0) {
+ ls_byte = timeout_macro_clks - 1;
+
+ while ((ls_byte & 0xFFFFFF00) > 0) {
+ ls_byte = ls_byte >> 1;
+ ms_byte++;
+ }
+
+ encoded_timeout = (ms_byte << 8)
+ + (uint16_t) (ls_byte & 0x000000FF);
+ }
+
+ return encoded_timeout;
+
+}
+
+uint32_t VL53L0_decode_timeout(uint16_t encoded_timeout)
+{
+ /*!
+ * Decode 16-bit timeout register value - format (LSByte * 2^MSByte) + 1
+ */
+
+ uint32_t timeout_macro_clks = 0;
+
+ timeout_macro_clks = ((uint32_t) (encoded_timeout & 0x00FF)
+ << (uint32_t) ((encoded_timeout & 0xFF00) >> 8)) + 1;
+
+ return timeout_macro_clks;
+}
+
+
+/* To convert ms into register value */
+uint32_t VL53L0_calc_timeout_mclks(VL53L0_DEV Dev,
+ uint32_t timeout_period_us,
+ uint8_t vcsel_period_pclks)
+{
+ uint32_t macro_period_ps;
+ uint32_t macro_period_ns;
+ uint32_t timeout_period_mclks = 0;
+
+ macro_period_ps = VL53L0_calc_macro_period_ps(Dev, vcsel_period_pclks);
+ macro_period_ns = (macro_period_ps + 500) / 1000;
+
+ timeout_period_mclks =
+ (uint32_t) (((timeout_period_us * 1000)
+ + (macro_period_ns / 2)) / macro_period_ns);
+
+ return timeout_period_mclks;
+}
+
+/* To convert register value into us */
+uint32_t VL53L0_calc_timeout_us(VL53L0_DEV Dev,
+ uint16_t timeout_period_mclks,
+ uint8_t vcsel_period_pclks)
+{
+ uint32_t macro_period_ps;
+ uint32_t macro_period_ns;
+ uint32_t actual_timeout_period_us = 0;
+
+ macro_period_ps = VL53L0_calc_macro_period_ps(Dev, vcsel_period_pclks);
+ macro_period_ns = (macro_period_ps + 500) / 1000;
+
+ actual_timeout_period_us =
+ ((timeout_period_mclks * macro_period_ns)
+ + (macro_period_ns / 2)) / 1000;
+
+ return actual_timeout_period_us;
+}
+
+
+VL53L0_Error get_sequence_step_timeout(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId,
+ uint32_t *pTimeOutMicroSecs)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t CurrentVCSELPulsePeriodPClk;
+ uint8_t EncodedTimeOutByte = 0;
+ uint32_t TimeoutMicroSeconds = 0;
+ uint16_t PreRangeEncodedTimeOut = 0;
+ uint16_t MsrcTimeOutMClks;
+ uint16_t PreRangeTimeOutMClks;
+ uint16_t FinalRangeTimeOutMClks = 0;
+ uint16_t FinalRangeEncodedTimeOut;
+ VL53L0_SchedulerSequenceSteps_t SchedulerSequenceSteps;
+
+ if ((SequenceStepId == VL53L0_SEQUENCESTEP_TCC) ||
+ (SequenceStepId == VL53L0_SEQUENCESTEP_DSS) ||
+ (SequenceStepId == VL53L0_SEQUENCESTEP_MSRC)) {
+
+ Status = VL53L0_GetVcselPulsePeriod(Dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ &CurrentVCSELPulsePeriodPClk);
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdByte(Dev,
+ VL53L0_REG_MSRC_CONFIG_TIMEOUT_MACROP,
+ &EncodedTimeOutByte);
+ }
+ MsrcTimeOutMClks = VL53L0_decode_timeout(EncodedTimeOutByte);
+
+ TimeoutMicroSeconds = VL53L0_calc_timeout_us(Dev,
+ MsrcTimeOutMClks,
+ CurrentVCSELPulsePeriodPClk);
+ } else if (SequenceStepId == VL53L0_SEQUENCESTEP_PRE_RANGE) {
+ /* Retrieve PRE-RANGE VCSEL Period */
+ Status = VL53L0_GetVcselPulsePeriod(Dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ &CurrentVCSELPulsePeriodPClk);
+
+ /* Retrieve PRE-RANGE Timeout in Macro periods (MCLKS) */
+ if (Status == VL53L0_ERROR_NONE) {
+
+ /* Retrieve PRE-RANGE VCSEL Period */
+ Status = VL53L0_GetVcselPulsePeriod(Dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ &CurrentVCSELPulsePeriodPClk);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdWord(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI,
+ &PreRangeEncodedTimeOut);
+ }
+
+ PreRangeTimeOutMClks = VL53L0_decode_timeout(
+ PreRangeEncodedTimeOut);
+
+ TimeoutMicroSeconds = VL53L0_calc_timeout_us(Dev,
+ PreRangeTimeOutMClks,
+ CurrentVCSELPulsePeriodPClk);
+ }
+ } else if (SequenceStepId == VL53L0_SEQUENCESTEP_FINAL_RANGE) {
+
+ VL53L0_GetSequenceStepEnables(Dev, &SchedulerSequenceSteps);
+ PreRangeTimeOutMClks = 0;
+
+ if (SchedulerSequenceSteps.PreRangeOn) {
+ /* Retrieve PRE-RANGE VCSEL Period */
+ Status = VL53L0_GetVcselPulsePeriod(Dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ &CurrentVCSELPulsePeriodPClk);
+
+ /* Retrieve PRE-RANGE Timeout in Macro periods
+ * (MCLKS)
+ */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdWord(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI,
+ &PreRangeEncodedTimeOut);
+ PreRangeTimeOutMClks = VL53L0_decode_timeout(
+ PreRangeEncodedTimeOut);
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Retrieve FINAL-RANGE VCSEL Period */
+ Status = VL53L0_GetVcselPulsePeriod(Dev,
+ VL53L0_VCSEL_PERIOD_FINAL_RANGE,
+ &CurrentVCSELPulsePeriodPClk);
+ }
+
+ /* Retrieve FINAL-RANGE Timeout in Macro periods (MCLKS) */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdWord(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI,
+ &FinalRangeEncodedTimeOut);
+ FinalRangeTimeOutMClks = VL53L0_decode_timeout(
+ FinalRangeEncodedTimeOut);
+ }
+
+ FinalRangeTimeOutMClks -= PreRangeTimeOutMClks;
+ TimeoutMicroSeconds = VL53L0_calc_timeout_us(Dev,
+ FinalRangeTimeOutMClks,
+ CurrentVCSELPulsePeriodPClk);
+ }
+
+ *pTimeOutMicroSecs = TimeoutMicroSeconds;
+
+ return Status;
+}
+
+
+VL53L0_Error set_sequence_step_timeout(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId,
+ uint32_t TimeOutMicroSecs)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t CurrentVCSELPulsePeriodPClk;
+ uint8_t MsrcEncodedTimeOut;
+ uint16_t PreRangeEncodedTimeOut;
+ uint16_t PreRangeTimeOutMClks;
+ uint16_t MsrcRangeTimeOutMClks;
+ uint16_t FinalRangeTimeOutMClks;
+ uint16_t FinalRangeEncodedTimeOut;
+ VL53L0_SchedulerSequenceSteps_t SchedulerSequenceSteps;
+
+ if ((SequenceStepId == VL53L0_SEQUENCESTEP_TCC) ||
+ (SequenceStepId == VL53L0_SEQUENCESTEP_DSS) ||
+ (SequenceStepId == VL53L0_SEQUENCESTEP_MSRC)) {
+
+ Status = VL53L0_GetVcselPulsePeriod(Dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ &CurrentVCSELPulsePeriodPClk);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ MsrcRangeTimeOutMClks = VL53L0_calc_timeout_mclks(Dev,
+ TimeOutMicroSecs,
+ (uint8_t)CurrentVCSELPulsePeriodPClk);
+
+ if (MsrcRangeTimeOutMClks > 256)
+ MsrcEncodedTimeOut = 255;
+ else
+ MsrcEncodedTimeOut =
+ (uint8_t)MsrcRangeTimeOutMClks - 1;
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ LastEncodedTimeout,
+ MsrcEncodedTimeOut);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_MSRC_CONFIG_TIMEOUT_MACROP,
+ MsrcEncodedTimeOut);
+ }
+ } else {
+
+ if (SequenceStepId == VL53L0_SEQUENCESTEP_PRE_RANGE) {
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetVcselPulsePeriod(Dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ &CurrentVCSELPulsePeriodPClk);
+ PreRangeTimeOutMClks =
+ VL53L0_calc_timeout_mclks(Dev,
+ TimeOutMicroSecs,
+ (uint8_t)CurrentVCSELPulsePeriodPClk);
+ PreRangeEncodedTimeOut = VL53L0_encode_timeout(
+ PreRangeTimeOutMClks);
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(Dev,
+ LastEncodedTimeout,
+ PreRangeEncodedTimeOut);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrWord(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI,
+ PreRangeEncodedTimeOut);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(
+ Dev,
+ PreRangeTimeoutMicroSecs,
+ TimeOutMicroSecs);
+ }
+ } else if (SequenceStepId == VL53L0_SEQUENCESTEP_FINAL_RANGE) {
+
+ /* For the final range timeout, the pre-range timeout
+ * must be added. To do this both final and pre-range
+ * timeouts must be expressed in macro periods MClks
+ * because they have different vcsel periods.
+ */
+
+ VL53L0_GetSequenceStepEnables(Dev,
+ &SchedulerSequenceSteps);
+ PreRangeTimeOutMClks = 0;
+ if (SchedulerSequenceSteps.PreRangeOn) {
+
+ /* Retrieve PRE-RANGE VCSEL Period */
+ Status = VL53L0_GetVcselPulsePeriod(Dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ &CurrentVCSELPulsePeriodPClk);
+
+ /* Retrieve PRE-RANGE Timeout in Macro periods
+ * (MCLKS)
+ */
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdWord(Dev, 0x51,
+ &PreRangeEncodedTimeOut);
+ PreRangeTimeOutMClks =
+ VL53L0_decode_timeout(
+ PreRangeEncodedTimeOut);
+ }
+ }
+
+ /* Calculate FINAL RANGE Timeout in Macro Periods
+ * (MCLKS) and add PRE-RANGE value
+ */
+ if (Status == VL53L0_ERROR_NONE) {
+
+ Status = VL53L0_GetVcselPulsePeriod(Dev,
+ VL53L0_VCSEL_PERIOD_FINAL_RANGE,
+ &CurrentVCSELPulsePeriodPClk);
+ }
+ if (Status == VL53L0_ERROR_NONE) {
+
+ FinalRangeTimeOutMClks =
+ VL53L0_calc_timeout_mclks(Dev,
+ TimeOutMicroSecs,
+ (uint8_t) CurrentVCSELPulsePeriodPClk);
+
+ FinalRangeTimeOutMClks += PreRangeTimeOutMClks;
+
+ FinalRangeEncodedTimeOut =
+ VL53L0_encode_timeout(FinalRangeTimeOutMClks);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_WrWord(Dev, 0x71,
+ FinalRangeEncodedTimeOut);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETDEVICESPECIFICPARAMETER(
+ Dev,
+ FinalRangeTimeoutMicroSecs,
+ TimeOutMicroSecs);
+ }
+ }
+ } else
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+ }
+ return Status;
+}
+
+VL53L0_Error VL53L0_set_vcsel_pulse_period(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType, uint8_t VCSELPulsePeriodPCLK)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t vcsel_period_reg;
+ uint8_t MinPreVcselPeriodPCLK = 12;
+ uint8_t MaxPreVcselPeriodPCLK = 18;
+ uint8_t MinFinalVcselPeriodPCLK = 8;
+ uint8_t MaxFinalVcselPeriodPCLK = 14;
+ uint32_t MeasurementTimingBudgetMicroSeconds;
+ uint32_t FinalRangeTimeoutMicroSeconds;
+ uint32_t PreRangeTimeoutMicroSeconds;
+ uint32_t MsrcTimeoutMicroSeconds;
+ uint8_t PhaseCalInt = 0;
+
+ /* Check if valid clock period requested */
+
+ if ((VCSELPulsePeriodPCLK % 2) != 0) {
+ /* Value must be an even number */
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else if (VcselPeriodType == VL53L0_VCSEL_PERIOD_PRE_RANGE &&
+ (VCSELPulsePeriodPCLK < MinPreVcselPeriodPCLK ||
+ VCSELPulsePeriodPCLK > MaxPreVcselPeriodPCLK)) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ } else if (VcselPeriodType == VL53L0_VCSEL_PERIOD_FINAL_RANGE &&
+ (VCSELPulsePeriodPCLK < MinFinalVcselPeriodPCLK ||
+ VCSELPulsePeriodPCLK > MaxFinalVcselPeriodPCLK)) {
+
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+
+ /* Apply specific settings for the requested clock period */
+
+ if (Status != VL53L0_ERROR_NONE)
+ return Status;
+
+
+ if (VcselPeriodType == VL53L0_VCSEL_PERIOD_PRE_RANGE) {
+
+ /* Set phase check limits */
+ if (VCSELPulsePeriodPCLK == 12) {
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH,
+ 0x18);
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW,
+ 0x08);
+ } else if (VCSELPulsePeriodPCLK == 14) {
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH,
+ 0x30);
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW,
+ 0x08);
+ } else if (VCSELPulsePeriodPCLK == 16) {
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH,
+ 0x40);
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW,
+ 0x08);
+ } else if (VCSELPulsePeriodPCLK == 18) {
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH,
+ 0x50);
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW,
+ 0x08);
+ }
+ } else if (VcselPeriodType == VL53L0_VCSEL_PERIOD_FINAL_RANGE) {
+
+ if (VCSELPulsePeriodPCLK == 8) {
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH,
+ 0x10);
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW,
+ 0x08);
+
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x02);
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x0C);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_ALGO_PHASECAL_LIM,
+ 0x30);
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+ } else if (VCSELPulsePeriodPCLK == 10) {
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH,
+ 0x28);
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW,
+ 0x08);
+
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03);
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x09);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_ALGO_PHASECAL_LIM,
+ 0x20);
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+ } else if (VCSELPulsePeriodPCLK == 12) {
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH,
+ 0x38);
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW,
+ 0x08);
+
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03);
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x08);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_ALGO_PHASECAL_LIM,
+ 0x20);
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+ } else if (VCSELPulsePeriodPCLK == 14) {
+
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH,
+ 0x048);
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW,
+ 0x08);
+
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03);
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x07);
+
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x01);
+ Status |= VL53L0_WrByte(Dev,
+ VL53L0_REG_ALGO_PHASECAL_LIM,
+ 0x20);
+ Status |= VL53L0_WrByte(Dev, 0xff, 0x00);
+ }
+ }
+
+
+ /* Re-calculate and apply timeouts, in macro periods */
+
+ if (Status == VL53L0_ERROR_NONE) {
+ vcsel_period_reg = VL53L0_encode_vcsel_period((uint8_t)
+ VCSELPulsePeriodPCLK);
+
+ /* When the VCSEL period for the pre or final range is changed,
+ * the corresponding timeout must be read from the device using
+ * the current VCSEL period, then the new VCSEL period can be
+ * applied. The timeout then must be written back to the device
+ * using the new VCSEL period.
+ *
+ * For the MSRC timeout, the same applies - this timeout being
+ * dependant on the pre-range vcsel period.
+ */
+ switch (VcselPeriodType) {
+ case VL53L0_VCSEL_PERIOD_PRE_RANGE:
+ Status = get_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_PRE_RANGE,
+ &PreRangeTimeoutMicroSeconds);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = get_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_MSRC,
+ &MsrcTimeoutMicroSeconds);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD,
+ vcsel_period_reg);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = set_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_PRE_RANGE,
+ PreRangeTimeoutMicroSeconds);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = set_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_MSRC,
+ MsrcTimeoutMicroSeconds);
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(
+ Dev,
+ PreRangeVcselPulsePeriod,
+ VCSELPulsePeriodPCLK);
+ break;
+ case VL53L0_VCSEL_PERIOD_FINAL_RANGE:
+ Status = get_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_FINAL_RANGE,
+ &FinalRangeTimeoutMicroSeconds);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD,
+ vcsel_period_reg);
+
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = set_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_FINAL_RANGE,
+ FinalRangeTimeoutMicroSeconds);
+
+ VL53L0_SETDEVICESPECIFICPARAMETER(
+ Dev,
+ FinalRangeVcselPulsePeriod,
+ VCSELPulsePeriodPCLK);
+ break;
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ /* Finally, the timing budget must be re-applied */
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_GETPARAMETERFIELD(Dev,
+ MeasurementTimingBudgetMicroSeconds,
+ MeasurementTimingBudgetMicroSeconds);
+
+ Status = VL53L0_SetMeasurementTimingBudgetMicroSeconds(Dev,
+ MeasurementTimingBudgetMicroSeconds);
+ }
+
+ /* Perform the phase calibration. This is needed after changing on
+ * vcsel period.
+ * get_data_enable = 0, restore_config = 1
+ */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_perform_phase_calibration(
+ Dev, &PhaseCalInt, 0, 1);
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_vcsel_pulse_period(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType, uint8_t *pVCSELPulsePeriodPCLK)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t vcsel_period_reg;
+
+ switch (VcselPeriodType) {
+ case VL53L0_VCSEL_PERIOD_PRE_RANGE:
+ Status = VL53L0_RdByte(Dev,
+ VL53L0_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD,
+ &vcsel_period_reg);
+ break;
+ case VL53L0_VCSEL_PERIOD_FINAL_RANGE:
+ Status = VL53L0_RdByte(Dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD,
+ &vcsel_period_reg);
+ break;
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ *pVCSELPulsePeriodPCLK =
+ VL53L0_decode_vcsel_period(vcsel_period_reg);
+
+ return Status;
+}
+
+
+
+VL53L0_Error VL53L0_set_measurement_timing_budget_micro_seconds(VL53L0_DEV Dev,
+ uint32_t MeasurementTimingBudgetMicroSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint32_t FinalRangeTimingBudgetMicroSeconds;
+ VL53L0_SchedulerSequenceSteps_t SchedulerSequenceSteps;
+ uint32_t MsrcDccTccTimeoutMicroSeconds = 2000;
+ uint32_t StartOverheadMicroSeconds = 1320;
+ uint32_t EndOverheadMicroSeconds = 960;
+ uint32_t MsrcOverheadMicroSeconds = 660;
+ uint32_t TccOverheadMicroSeconds = 590;
+ uint32_t DssOverheadMicroSeconds = 690;
+ uint32_t PreRangeOverheadMicroSeconds = 660;
+ uint32_t FinalRangeOverheadMicroSeconds = 550;
+ uint32_t PreRangeTimeoutMicroSeconds = 0;
+ uint32_t cMinTimingBudgetMicroSeconds = 20000;
+ uint32_t SubTimeout = 0;
+
+ LOG_FUNCTION_START("");
+
+ if (MeasurementTimingBudgetMicroSeconds
+ < cMinTimingBudgetMicroSeconds) {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ return Status;
+ }
+
+ FinalRangeTimingBudgetMicroSeconds =
+ MeasurementTimingBudgetMicroSeconds -
+ (StartOverheadMicroSeconds + EndOverheadMicroSeconds);
+
+ Status = VL53L0_GetSequenceStepEnables(Dev, &SchedulerSequenceSteps);
+
+ if (Status == VL53L0_ERROR_NONE &&
+ (SchedulerSequenceSteps.TccOn ||
+ SchedulerSequenceSteps.MsrcOn ||
+ SchedulerSequenceSteps.DssOn)) {
+
+ /* TCC, MSRC and DSS all share the same timeout */
+ Status = get_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_MSRC,
+ &MsrcDccTccTimeoutMicroSeconds);
+
+ /* Subtract the TCC, MSRC and DSS timeouts if they are
+ * enabled.
+ */
+
+ if (Status != VL53L0_ERROR_NONE)
+ return Status;
+
+ /* TCC */
+ if (SchedulerSequenceSteps.TccOn) {
+
+ SubTimeout = MsrcDccTccTimeoutMicroSeconds
+ + TccOverheadMicroSeconds;
+
+ if (SubTimeout <
+ FinalRangeTimingBudgetMicroSeconds) {
+ FinalRangeTimingBudgetMicroSeconds -=
+ SubTimeout;
+ } else {
+ /* Requested timeout too big. */
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ if (Status != VL53L0_ERROR_NONE) {
+ LOG_FUNCTION_END(Status);
+ return Status;
+ }
+
+ /* DSS */
+ if (SchedulerSequenceSteps.DssOn) {
+
+ SubTimeout = 2 * (MsrcDccTccTimeoutMicroSeconds +
+ DssOverheadMicroSeconds);
+
+ if (SubTimeout < FinalRangeTimingBudgetMicroSeconds) {
+ FinalRangeTimingBudgetMicroSeconds
+ -= SubTimeout;
+ } else {
+ /* Requested timeout too big. */
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ } else if (SchedulerSequenceSteps.MsrcOn) {
+ /* MSRC */
+ SubTimeout = MsrcDccTccTimeoutMicroSeconds +
+ MsrcOverheadMicroSeconds;
+
+ if (SubTimeout < FinalRangeTimingBudgetMicroSeconds) {
+ FinalRangeTimingBudgetMicroSeconds
+ -= SubTimeout;
+ } else {
+ /* Requested timeout too big. */
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ }
+
+ if (Status != VL53L0_ERROR_NONE) {
+ LOG_FUNCTION_END(Status);
+ return Status;
+ }
+
+ if (SchedulerSequenceSteps.PreRangeOn) {
+
+ /* Subtract the Pre-range timeout if enabled. */
+
+ Status = get_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_PRE_RANGE,
+ &PreRangeTimeoutMicroSeconds);
+
+ SubTimeout = PreRangeTimeoutMicroSeconds +
+ PreRangeOverheadMicroSeconds;
+
+ if (SubTimeout < FinalRangeTimingBudgetMicroSeconds) {
+ FinalRangeTimingBudgetMicroSeconds -= SubTimeout;
+ } else {
+ /* Requested timeout too big. */
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+
+
+ if (Status == VL53L0_ERROR_NONE &&
+ SchedulerSequenceSteps.FinalRangeOn) {
+
+ FinalRangeTimingBudgetMicroSeconds -=
+ FinalRangeOverheadMicroSeconds;
+
+ /* Final Range Timeout
+ * Note that the final range timeout is determined by the timing
+ * budget and the sum of all other timeouts within the sequence.
+ * If there is no room for the final range timeout, then an error
+ * will be set. Otherwise the remaining time will be applied to
+ * the final range.
+ */
+ Status = set_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_FINAL_RANGE,
+ FinalRangeTimingBudgetMicroSeconds);
+
+ VL53L0_SETPARAMETERFIELD(Dev,
+ MeasurementTimingBudgetMicroSeconds,
+ MeasurementTimingBudgetMicroSeconds);
+ }
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_measurement_timing_budget_micro_seconds(VL53L0_DEV Dev,
+ uint32_t *pMeasurementTimingBudgetMicroSeconds)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_SchedulerSequenceSteps_t SchedulerSequenceSteps;
+ uint32_t FinalRangeTimeoutMicroSeconds;
+ uint32_t MsrcDccTccTimeoutMicroSeconds = 2000;
+ uint32_t StartOverheadMicroSeconds = 1910;
+ uint32_t EndOverheadMicroSeconds = 960;
+ uint32_t MsrcOverheadMicroSeconds = 660;
+ uint32_t TccOverheadMicroSeconds = 590;
+ uint32_t DssOverheadMicroSeconds = 690;
+ uint32_t PreRangeOverheadMicroSeconds = 660;
+ uint32_t FinalRangeOverheadMicroSeconds = 550;
+ uint32_t PreRangeTimeoutMicroSeconds = 0;
+
+ LOG_FUNCTION_START("");
+
+ /* Start and end overhead times always present */
+ *pMeasurementTimingBudgetMicroSeconds
+ = StartOverheadMicroSeconds + EndOverheadMicroSeconds;
+
+ Status = VL53L0_GetSequenceStepEnables(Dev, &SchedulerSequenceSteps);
+
+ if (Status != VL53L0_ERROR_NONE) {
+ LOG_FUNCTION_END(Status);
+ return Status;
+ }
+
+
+ if (SchedulerSequenceSteps.TccOn ||
+ SchedulerSequenceSteps.MsrcOn ||
+ SchedulerSequenceSteps.DssOn) {
+
+ Status = get_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_MSRC,
+ &MsrcDccTccTimeoutMicroSeconds);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (SchedulerSequenceSteps.TccOn) {
+ *pMeasurementTimingBudgetMicroSeconds +=
+ MsrcDccTccTimeoutMicroSeconds +
+ TccOverheadMicroSeconds;
+ }
+
+ if (SchedulerSequenceSteps.DssOn) {
+ *pMeasurementTimingBudgetMicroSeconds +=
+ 2 * (MsrcDccTccTimeoutMicroSeconds +
+ DssOverheadMicroSeconds);
+ } else if (SchedulerSequenceSteps.MsrcOn) {
+ *pMeasurementTimingBudgetMicroSeconds +=
+ MsrcDccTccTimeoutMicroSeconds +
+ MsrcOverheadMicroSeconds;
+ }
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (SchedulerSequenceSteps.PreRangeOn) {
+ Status = get_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_PRE_RANGE,
+ &PreRangeTimeoutMicroSeconds);
+ *pMeasurementTimingBudgetMicroSeconds +=
+ PreRangeTimeoutMicroSeconds +
+ PreRangeOverheadMicroSeconds;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (SchedulerSequenceSteps.FinalRangeOn) {
+ Status = get_sequence_step_timeout(Dev,
+ VL53L0_SEQUENCESTEP_FINAL_RANGE,
+ &FinalRangeTimeoutMicroSeconds);
+ *pMeasurementTimingBudgetMicroSeconds +=
+ (FinalRangeTimeoutMicroSeconds +
+ FinalRangeOverheadMicroSeconds);
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_SETPARAMETERFIELD(Dev,
+ MeasurementTimingBudgetMicroSeconds,
+ *pMeasurementTimingBudgetMicroSeconds);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+
+
+VL53L0_Error VL53L0_load_tuning_settings(VL53L0_DEV Dev,
+ uint8_t *pTuningSettingBuffer)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int i;
+ int Index;
+ uint8_t msb;
+ uint8_t lsb;
+ uint8_t SelectParam;
+ uint8_t NumberOfWrites;
+ uint8_t Address;
+ uint8_t localBuffer[4]; /* max */
+ uint16_t Temp16;
+
+ LOG_FUNCTION_START("");
+
+ Index = 0;
+
+ while ((*(pTuningSettingBuffer + Index) != 0) &&
+ (Status == VL53L0_ERROR_NONE)) {
+ NumberOfWrites = *(pTuningSettingBuffer + Index);
+ Index++;
+ if (NumberOfWrites == 0xFF) {
+ /* internal parameters */
+ SelectParam = *(pTuningSettingBuffer + Index);
+ Index++;
+ switch (SelectParam) {
+ case 0: /* uint16_t SigmaEstRefArray -> 2 bytes */
+ msb = *(pTuningSettingBuffer + Index);
+ Index++;
+ lsb = *(pTuningSettingBuffer + Index);
+ Index++;
+ Temp16 = VL53L0_MAKEUINT16(lsb, msb);
+ PALDevDataSet(Dev, SigmaEstRefArray, Temp16);
+ break;
+ case 1: /* uint16_t SigmaEstEffPulseWidth -> 2 bytes */
+ msb = *(pTuningSettingBuffer + Index);
+ Index++;
+ lsb = *(pTuningSettingBuffer + Index);
+ Index++;
+ Temp16 = VL53L0_MAKEUINT16(lsb, msb);
+ PALDevDataSet(Dev, SigmaEstEffPulseWidth,
+ Temp16);
+ break;
+ case 2: /* uint16_t SigmaEstEffAmbWidth -> 2 bytes */
+ msb = *(pTuningSettingBuffer + Index);
+ Index++;
+ lsb = *(pTuningSettingBuffer + Index);
+ Index++;
+ Temp16 = VL53L0_MAKEUINT16(lsb, msb);
+ PALDevDataSet(Dev, SigmaEstEffAmbWidth, Temp16);
+ break;
+ case 3: /* uint16_t targetRefRate -> 2 bytes */
+ msb = *(pTuningSettingBuffer + Index);
+ Index++;
+ lsb = *(pTuningSettingBuffer + Index);
+ Index++;
+ Temp16 = VL53L0_MAKEUINT16(lsb, msb);
+ PALDevDataSet(Dev, targetRefRate, Temp16);
+ break;
+ default: /* invalid parameter */
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+
+ } else if (NumberOfWrites <= 4) {
+ Address = *(pTuningSettingBuffer + Index);
+ Index++;
+
+ for (i = 0; i < NumberOfWrites; i++) {
+ localBuffer[i] = *(pTuningSettingBuffer +
+ Index);
+ Index++;
+ }
+
+ Status = VL53L0_WriteMulti(Dev, Address, localBuffer,
+ NumberOfWrites);
+
+ } else {
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_total_xtalk_rate(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData,
+ FixPoint1616_t *ptotal_xtalk_rate_mcps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ uint8_t xtalkCompEnable;
+ FixPoint1616_t totalXtalkMegaCps;
+ FixPoint1616_t xtalkPerSpadMegaCps;
+
+ *ptotal_xtalk_rate_mcps = 0;
+
+ Status = VL53L0_GetXTalkCompensationEnable(Dev, &xtalkCompEnable);
+ if (Status == VL53L0_ERROR_NONE) {
+
+ if (xtalkCompEnable) {
+
+ VL53L0_GETPARAMETERFIELD(
+ Dev,
+ XTalkCompensationRateMegaCps,
+ xtalkPerSpadMegaCps);
+
+ /* FixPoint1616 * FixPoint 8:8 = FixPoint0824 */
+ totalXtalkMegaCps =
+ pRangingMeasurementData->EffectiveSpadRtnCount *
+ xtalkPerSpadMegaCps;
+
+ /* FixPoint0824 >> 8 = FixPoint1616 */
+ *ptotal_xtalk_rate_mcps =
+ (totalXtalkMegaCps + 0x80) >> 8;
+ }
+ }
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_total_signal_rate(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData,
+ FixPoint1616_t *ptotal_signal_rate_mcps)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ FixPoint1616_t totalXtalkMegaCps;
+
+ LOG_FUNCTION_START("");
+
+ *ptotal_signal_rate_mcps =
+ pRangingMeasurementData->SignalRateRtnMegaCps;
+
+ Status = VL53L0_get_total_xtalk_rate(
+ Dev, pRangingMeasurementData, &totalXtalkMegaCps);
+
+ if (Status == VL53L0_ERROR_NONE)
+ *ptotal_signal_rate_mcps += totalXtalkMegaCps;
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_calc_dmax(
+ VL53L0_DEV Dev,
+ FixPoint1616_t totalSignalRate_mcps,
+ FixPoint1616_t totalCorrSignalRate_mcps,
+ FixPoint1616_t pwMult,
+ uint32_t sigmaEstimateP1,
+ FixPoint1616_t sigmaEstimateP2,
+ uint32_t peakVcselDuration_us,
+ uint32_t *pdmax_mm)
+{
+ const uint32_t cSigmaLimit = 18;
+ const FixPoint1616_t cSignalLimit = 0x4000; /* 0.25 */
+ const FixPoint1616_t cSigmaEstRef = 0x00000042; /* 0.001 */
+ const uint32_t cAmbEffWidthSigmaEst_ns = 6;
+ const uint32_t cAmbEffWidthDMax_ns = 7;
+ uint32_t dmaxCalRange_mm;
+ FixPoint1616_t dmaxCalSignalRateRtn_mcps;
+ FixPoint1616_t minSignalNeeded;
+ FixPoint1616_t minSignalNeeded_p1;
+ FixPoint1616_t minSignalNeeded_p2;
+ FixPoint1616_t minSignalNeeded_p3;
+ FixPoint1616_t minSignalNeeded_p4;
+ FixPoint1616_t sigmaLimitTmp;
+ FixPoint1616_t sigmaEstSqTmp;
+ FixPoint1616_t signalLimitTmp;
+ FixPoint1616_t SignalAt0mm;
+ FixPoint1616_t dmaxDark;
+ FixPoint1616_t dmaxAmbient;
+ FixPoint1616_t dmaxDarkTmp;
+ FixPoint1616_t sigmaEstP2Tmp;
+ uint32_t signalRateTemp_mcps;
+
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ dmaxCalRange_mm =
+ PALDevDataGet(Dev, DmaxCalRangeMilliMeter);
+
+ dmaxCalSignalRateRtn_mcps =
+ PALDevDataGet(Dev, DmaxCalSignalRateRtnMegaCps);
+
+ /* uint32 * FixPoint1616 = FixPoint1616 */
+ SignalAt0mm = dmaxCalRange_mm * dmaxCalSignalRateRtn_mcps;
+
+ /* FixPoint1616 >> 8 = FixPoint2408 */
+ SignalAt0mm = (SignalAt0mm + 0x80) >> 8;
+ SignalAt0mm *= dmaxCalRange_mm;
+
+ minSignalNeeded_p1 = 0;
+ if (totalCorrSignalRate_mcps > 0) {
+
+ /* Shift by 10 bits to increase resolution prior to the
+ * division
+ */
+ signalRateTemp_mcps = totalSignalRate_mcps << 10;
+
+ /* Add rounding value prior to division */
+ minSignalNeeded_p1 = signalRateTemp_mcps +
+ (totalCorrSignalRate_mcps/2);
+
+ /* FixPoint0626/FixPoint1616 = FixPoint2210 */
+ minSignalNeeded_p1 /= totalCorrSignalRate_mcps;
+
+ /* Apply a factored version of the speed of light.
+ * Correction to be applied at the end
+ */
+ minSignalNeeded_p1 *= 3;
+
+ /* FixPoint2210 * FixPoint2210 = FixPoint1220 */
+ minSignalNeeded_p1 *= minSignalNeeded_p1;
+
+ /* FixPoint1220 >> 16 = FixPoint2804 */
+ minSignalNeeded_p1 = (minSignalNeeded_p1 + 0x8000) >> 16;
+ }
+
+ minSignalNeeded_p2 = pwMult * sigmaEstimateP1;
+
+ /* FixPoint1616 >> 16 = uint32 */
+ minSignalNeeded_p2 = (minSignalNeeded_p2 + 0x8000) >> 16;
+
+ /* uint32 * uint32 = uint32 */
+ minSignalNeeded_p2 *= minSignalNeeded_p2;
+
+ /* Check sigmaEstimateP2
+ * If this value is too high there is not enough signal rate
+ * to calculate dmax value so set a suitable value to ensure
+ * a very small dmax.
+ */
+ sigmaEstP2Tmp = (sigmaEstimateP2 + 0x8000) >> 16;
+ sigmaEstP2Tmp = (sigmaEstP2Tmp + cAmbEffWidthSigmaEst_ns/2)/
+ cAmbEffWidthSigmaEst_ns;
+ sigmaEstP2Tmp *= cAmbEffWidthDMax_ns;
+
+ if (sigmaEstP2Tmp > 0xffff) {
+ minSignalNeeded_p3 = 0xfff00000;
+ } else {
+
+ /* DMAX uses a different ambient width from sigma, so apply
+ * correction.
+ * Perform division before multiplication to prevent overflow.
+ */
+ sigmaEstimateP2 = (sigmaEstimateP2 + cAmbEffWidthSigmaEst_ns/2)/
+ cAmbEffWidthSigmaEst_ns;
+ sigmaEstimateP2 *= cAmbEffWidthDMax_ns;
+
+ /* FixPoint1616 >> 16 = uint32 */
+ minSignalNeeded_p3 = (sigmaEstimateP2 + 0x8000) >> 16;
+
+ minSignalNeeded_p3 *= minSignalNeeded_p3;
+
+ }
+
+ /* FixPoint1814 / uint32 = FixPoint1814 */
+ sigmaLimitTmp = ((cSigmaLimit << 14) + 500) / 1000;
+
+ /* FixPoint1814 * FixPoint1814 = FixPoint3628 := FixPoint0428 */
+ sigmaLimitTmp *= sigmaLimitTmp;
+
+ /* FixPoint1616 * FixPoint1616 = FixPoint3232 */
+ sigmaEstSqTmp = cSigmaEstRef * cSigmaEstRef;
+
+ /* FixPoint3232 >> 4 = FixPoint0428 */
+ sigmaEstSqTmp = (sigmaEstSqTmp + 0x08) >> 4;
+
+ /* FixPoint0428 - FixPoint0428 = FixPoint0428 */
+ sigmaLimitTmp -= sigmaEstSqTmp;
+
+ /* uint32_t * FixPoint0428 = FixPoint0428 */
+ minSignalNeeded_p4 = 4 * 12 * sigmaLimitTmp;
+
+ /* FixPoint0428 >> 14 = FixPoint1814 */
+ minSignalNeeded_p4 = (minSignalNeeded_p4 + 0x2000) >> 14;
+
+ /* uint32 + uint32 = uint32 */
+ minSignalNeeded = (minSignalNeeded_p2 + minSignalNeeded_p3);
+
+ /* uint32 / uint32 = uint32 */
+ minSignalNeeded += (peakVcselDuration_us/2);
+ minSignalNeeded /= peakVcselDuration_us;
+
+ /* uint32 << 14 = FixPoint1814 */
+ minSignalNeeded <<= 14;
+
+ /* FixPoint1814 / FixPoint1814 = uint32 */
+ minSignalNeeded += (minSignalNeeded_p4/2);
+ minSignalNeeded /= minSignalNeeded_p4;
+
+ /* FixPoint3200 * FixPoint2804 := FixPoint2804*/
+ minSignalNeeded *= minSignalNeeded_p1;
+
+ /* Apply correction by dividing by 1000000.
+ * This assumes 10E16 on the numerator of the equation
+ * and 10E-22 on the denominator.
+ * We do this because 32bit fix point calculation can't
+ * handle the larger and smaller elements of this equation,
+ * i.e. speed of light and pulse widths.
+ */
+ minSignalNeeded = (minSignalNeeded + 500) / 1000;
+ minSignalNeeded <<= 4;
+
+ minSignalNeeded = (minSignalNeeded + 500) / 1000;
+
+ /* FixPoint1616 >> 8 = FixPoint2408 */
+ signalLimitTmp = (cSignalLimit + 0x80) >> 8;
+
+ /* FixPoint2408/FixPoint2408 = uint32 */
+ if (signalLimitTmp != 0)
+ dmaxDarkTmp = (SignalAt0mm + (signalLimitTmp / 2))
+ / signalLimitTmp;
+ else
+ dmaxDarkTmp = 0;
+
+ dmaxDark = VL53L0_isqrt(dmaxDarkTmp);
+
+ /* FixPoint2408/FixPoint2408 = uint32 */
+ if (minSignalNeeded != 0)
+ dmaxAmbient = (SignalAt0mm + minSignalNeeded/2)
+ / minSignalNeeded;
+ else
+ dmaxAmbient = 0;
+
+ dmaxAmbient = VL53L0_isqrt(dmaxAmbient);
+
+ *pdmax_mm = dmaxDark;
+ if (dmaxDark > dmaxAmbient)
+ *pdmax_mm = dmaxAmbient;
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_calc_sigma_estimate(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData,
+ FixPoint1616_t *pSigmaEstimate,
+ uint32_t *pDmax_mm)
+{
+ /* Expressed in 100ths of a ns, i.e. centi-ns */
+ const uint32_t cPulseEffectiveWidth_centi_ns = 800;
+ /* Expressed in 100ths of a ns, i.e. centi-ns */
+ const uint32_t cAmbientEffectiveWidth_centi_ns = 600;
+ const FixPoint1616_t cSigmaEstRef = 0x00000042; /* 0.001 */
+ const uint32_t cVcselPulseWidth_ps = 4700; /* pico secs */
+ const FixPoint1616_t cSigmaEstMax = 0x028F87AE;
+ const FixPoint1616_t cSigmaEstRtnMax = 0xF000;
+ const FixPoint1616_t cAmbToSignalRatioMax = 0xF0000000/
+ cAmbientEffectiveWidth_centi_ns;
+ /* Time Of Flight per mm (6.6 pico secs) */
+ const FixPoint1616_t cTOF_per_mm_ps = 0x0006999A;
+ const uint32_t c16BitRoundingParam = 0x00008000;
+ const FixPoint1616_t cMaxXTalk_kcps = 0x00320000;
+ const uint32_t cPllPeriod_ps = 1655;
+
+ uint32_t vcselTotalEventsRtn;
+ uint32_t finalRangeTimeoutMicroSecs;
+ uint32_t preRangeTimeoutMicroSecs;
+ FixPoint1616_t sigmaEstimateP1;
+ FixPoint1616_t sigmaEstimateP2;
+ FixPoint1616_t sigmaEstimateP3;
+ FixPoint1616_t deltaT_ps;
+ FixPoint1616_t pwMult;
+ FixPoint1616_t sigmaEstRtn;
+ FixPoint1616_t sigmaEstimate;
+ FixPoint1616_t xTalkCorrection;
+ FixPoint1616_t ambientRate_kcps;
+ FixPoint1616_t peakSignalRate_kcps;
+ FixPoint1616_t xTalkCompRate_mcps;
+ uint32_t xTalkCompRate_kcps;
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ FixPoint1616_t diff1_mcps;
+ FixPoint1616_t diff2_mcps;
+ FixPoint1616_t sqr1;
+ FixPoint1616_t sqr2;
+ FixPoint1616_t sqrSum;
+ FixPoint1616_t sqrtResult_centi_ns;
+ FixPoint1616_t sqrtResult;
+ FixPoint1616_t totalSignalRate_mcps;
+ FixPoint1616_t correctedSignalRate_mcps;
+ uint32_t vcselWidth;
+ uint32_t finalRangeMacroPCLKS;
+ uint32_t preRangeMacroPCLKS;
+ uint32_t peakVcselDuration_us;
+ uint8_t finalRangeVcselPCLKS;
+ uint8_t preRangeVcselPCLKS;
+ /*! \addtogroup calc_sigma_estimate
+ * @{
+ *
+ * Estimates the range sigma based on the
+ *
+ * - vcsel_rate_kcps
+ * - ambient_rate_kcps
+ * - signal_total_events
+ * - xtalk_rate
+ *
+ * and the following parameters
+ *
+ * - SigmaEstRefArray
+ * - SigmaEstEffPulseWidth
+ * - SigmaEstEffAmbWidth
+ */
+
+ LOG_FUNCTION_START("");
+
+ VL53L0_GETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps,
+ xTalkCompRate_mcps);
+
+ /*
+ * We work in kcps rather than mcps as this helps keep within the
+ * confines of the 32 Fix1616 type.
+ */
+
+ ambientRate_kcps =
+ (pRangingMeasurementData->AmbientRateRtnMegaCps * 1000) >> 16;
+
+ correctedSignalRate_mcps =
+ pRangingMeasurementData->SignalRateRtnMegaCps;
+
+
+ Status = VL53L0_get_total_signal_rate(
+ Dev, pRangingMeasurementData, &totalSignalRate_mcps);
+ Status = VL53L0_get_total_xtalk_rate(
+ Dev, pRangingMeasurementData, &xTalkCompRate_mcps);
+
+
+ /* Signal rate measurement provided by device is the
+ * peak signal rate, not average.
+ */
+ peakSignalRate_kcps = (totalSignalRate_mcps * 1000);
+ peakSignalRate_kcps = (peakSignalRate_kcps + 0x8000) >> 16;
+
+ xTalkCompRate_kcps = xTalkCompRate_mcps * 1000;
+
+ if (xTalkCompRate_kcps > cMaxXTalk_kcps)
+ xTalkCompRate_kcps = cMaxXTalk_kcps;
+
+ if (Status == VL53L0_ERROR_NONE) {
+
+ /* Calculate final range macro periods */
+ finalRangeTimeoutMicroSecs = VL53L0_GETDEVICESPECIFICPARAMETER(
+ Dev, FinalRangeTimeoutMicroSecs);
+
+ finalRangeVcselPCLKS = VL53L0_GETDEVICESPECIFICPARAMETER(
+ Dev, FinalRangeVcselPulsePeriod);
+
+ finalRangeMacroPCLKS = VL53L0_calc_timeout_mclks(
+ Dev, finalRangeTimeoutMicroSecs, finalRangeVcselPCLKS);
+
+ /* Calculate pre-range macro periods */
+ preRangeTimeoutMicroSecs = VL53L0_GETDEVICESPECIFICPARAMETER(
+ Dev, PreRangeTimeoutMicroSecs);
+
+ preRangeVcselPCLKS = VL53L0_GETDEVICESPECIFICPARAMETER(
+ Dev, PreRangeVcselPulsePeriod);
+
+ preRangeMacroPCLKS = VL53L0_calc_timeout_mclks(
+ Dev, preRangeTimeoutMicroSecs, preRangeVcselPCLKS);
+
+ vcselWidth = 3;
+ if (finalRangeVcselPCLKS == 8)
+ vcselWidth = 2;
+
+
+ peakVcselDuration_us = vcselWidth * 2048 *
+ (preRangeMacroPCLKS + finalRangeMacroPCLKS);
+ peakVcselDuration_us = (peakVcselDuration_us + 500)/1000;
+ peakVcselDuration_us *= cPllPeriod_ps;
+ peakVcselDuration_us = (peakVcselDuration_us + 500)/1000;
+
+ /* Fix1616 >> 8 = Fix2408 */
+ totalSignalRate_mcps = (totalSignalRate_mcps + 0x80) >> 8;
+
+ /* Fix2408 * uint32 = Fix2408 */
+ vcselTotalEventsRtn = totalSignalRate_mcps *
+ peakVcselDuration_us;
+
+ /* Fix2408 >> 8 = uint32 */
+ vcselTotalEventsRtn = (vcselTotalEventsRtn + 0x80) >> 8;
+
+ /* Fix2408 << 8 = Fix1616 = */
+ totalSignalRate_mcps <<= 8;
+ }
+
+ if (Status != VL53L0_ERROR_NONE) {
+ LOG_FUNCTION_END(Status);
+ return Status;
+ }
+
+ if (peakSignalRate_kcps == 0) {
+ *pSigmaEstimate = cSigmaEstMax;
+ PALDevDataSet(Dev, SigmaEstimate, cSigmaEstMax);
+ *pDmax_mm = 0;
+ } else {
+ if (vcselTotalEventsRtn < 1)
+ vcselTotalEventsRtn = 1;
+
+ /*
+ * Calculate individual components of the main equation -
+ * replicating the equation implemented in the script
+ * OpenAll_Ewok_ranging_data.jsl.
+ *
+ * sigmaEstimateP1 represents the effective pulse width, which
+ * is a tuning parameter, rather than a real value.
+ *
+ * sigmaEstimateP2 represents the ambient/signal rate ratio
+ * expressed as a multiple of the effective ambient width
+ * (tuning parameter).
+ *
+ * sigmaEstimateP3 provides the signal event component, with the
+ * knowledge that
+ * - Noise of a square pulse is 1/sqrt(12) of the pulse
+ * width.
+ * - at 0Lux, sigma is proportional to
+ * effectiveVcselPulseWidth/sqrt(12 * signalTotalEvents)
+ *
+ * deltaT_ps represents the time of flight in pico secs for the
+ * current range measurement, using the "TOF per mm" constant
+ * (in ps).
+ */
+
+ sigmaEstimateP1 = cPulseEffectiveWidth_centi_ns;
+
+ /* ((FixPoint1616 << 16)* uint32)/uint32 = FixPoint1616 */
+ sigmaEstimateP2 = (ambientRate_kcps << 16)/peakSignalRate_kcps;
+ if (sigmaEstimateP2 > cAmbToSignalRatioMax) {
+ /* Clip to prevent overflow. Will ensure safe
+ * max result.
+ */
+ sigmaEstimateP2 = cAmbToSignalRatioMax;
+ }
+ sigmaEstimateP2 *= cAmbientEffectiveWidth_centi_ns;
+
+ sigmaEstimateP3 = 2 * VL53L0_isqrt(vcselTotalEventsRtn * 12);
+
+ /* uint32 * FixPoint1616 = FixPoint1616 */
+ deltaT_ps = pRangingMeasurementData->RangeMilliMeter *
+ cTOF_per_mm_ps;
+
+ /*
+ * vcselRate - xtalkCompRate
+ * (uint32 << 16) - FixPoint1616 = FixPoint1616.
+ * Divide result by 1000 to convert to mcps.
+ * 500 is added to ensure rounding when integer division
+ * truncates.
+ */
+ diff1_mcps = (((peakSignalRate_kcps << 16) -
+ xTalkCompRate_kcps) + 500)/1000;
+
+ /* vcselRate + xtalkCompRate */
+ diff2_mcps = (((peakSignalRate_kcps << 16) +
+ xTalkCompRate_kcps) + 500)/1000;
+
+ /* Shift by 8 bits to increase resolution prior to the
+ * division
+ */
+ diff1_mcps <<= 8;
+
+ /* FixPoint0824/FixPoint1616 = FixPoint2408 */
+ xTalkCorrection = abs(diff1_mcps/diff2_mcps);
+
+ /* FixPoint2408 << 8 = FixPoint1616 */
+ xTalkCorrection <<= 8;
+
+ /* FixPoint1616/uint32 = FixPoint1616 */
+ pwMult = deltaT_ps/cVcselPulseWidth_ps; /* smaller than 1.0f */
+
+ /*
+ * FixPoint1616 * FixPoint1616 = FixPoint3232, however both
+ * values are small enough such that32 bits will not be
+ * exceeded.
+ */
+ pwMult *= ((1 << 16) - xTalkCorrection);
+
+ /* (FixPoint3232 >> 16) = FixPoint1616 */
+ pwMult = (pwMult + c16BitRoundingParam) >> 16;
+
+ /* FixPoint1616 + FixPoint1616 = FixPoint1616 */
+ pwMult += (1 << 16);
+
+ /*
+ * At this point the value will be 1.xx, therefore if we square
+ * the value this will exceed 32 bits. To address this perform
+ * a single shift to the right before the multiplication.
+ */
+ pwMult >>= 1;
+ /* FixPoint1715 * FixPoint1715 = FixPoint3430 */
+ pwMult = pwMult * pwMult;
+
+ /* (FixPoint3430 >> 14) = Fix1616 */
+ pwMult >>= 14;
+
+ /* FixPoint1616 * uint32 = FixPoint1616 */
+ sqr1 = pwMult * sigmaEstimateP1;
+
+ /* (FixPoint1616 >> 16) = FixPoint3200 */
+ sqr1 = (sqr1 + 0x8000) >> 16;
+
+ /* FixPoint3200 * FixPoint3200 = FixPoint6400 */
+ sqr1 *= sqr1;
+
+ sqr2 = sigmaEstimateP2;
+
+ /* (FixPoint1616 >> 16) = FixPoint3200 */
+ sqr2 = (sqr2 + 0x8000) >> 16;
+
+ /* FixPoint3200 * FixPoint3200 = FixPoint6400 */
+ sqr2 *= sqr2;
+
+ /* FixPoint64000 + FixPoint6400 = FixPoint6400 */
+ sqrSum = sqr1 + sqr2;
+
+ /* SQRT(FixPoin6400) = FixPoint3200 */
+ sqrtResult_centi_ns = VL53L0_isqrt(sqrSum);
+
+ /* (FixPoint3200 << 16) = FixPoint1616 */
+ sqrtResult_centi_ns <<= 16;
+
+ /*
+ * Note that the Speed Of Light is expressed in um per 1E-10
+ * seconds (2997) Therefore to get mm/ns we have to divide by
+ * 10000
+ */
+ sigmaEstRtn = (((sqrtResult_centi_ns+50)/100) /
+ sigmaEstimateP3);
+ sigmaEstRtn *= VL53L0_SPEED_OF_LIGHT_IN_AIR;
+
+ /* Add 5000 before dividing by 10000 to ensure rounding. */
+ sigmaEstRtn += 5000;
+ sigmaEstRtn /= 10000;
+
+ if (sigmaEstRtn > cSigmaEstRtnMax) {
+ /* Clip to prevent overflow. Will ensure safe
+ * max result.
+ */
+ sigmaEstRtn = cSigmaEstRtnMax;
+ }
+
+ /* FixPoint1616 * FixPoint1616 = FixPoint3232 */
+ sqr1 = sigmaEstRtn * sigmaEstRtn;
+ /* FixPoint1616 * FixPoint1616 = FixPoint3232 */
+ sqr2 = cSigmaEstRef * cSigmaEstRef;
+
+ /* sqrt(FixPoint3232) = FixPoint1616 */
+ sqrtResult = VL53L0_isqrt((sqr1 + sqr2));
+ /*
+ * Note that the Shift by 4 bits increases resolution prior to
+ * the sqrt, therefore the result must be shifted by 2 bits to
+ * the right to revert back to the FixPoint1616 format.
+ */
+
+ sigmaEstimate = 1000 * sqrtResult;
+
+ if ((peakSignalRate_kcps < 1) || (vcselTotalEventsRtn < 1) ||
+ (sigmaEstimate > cSigmaEstMax)) {
+ sigmaEstimate = cSigmaEstMax;
+ }
+
+ *pSigmaEstimate = (uint32_t)(sigmaEstimate);
+ PALDevDataSet(Dev, SigmaEstimate, *pSigmaEstimate);
+ Status = VL53L0_calc_dmax(
+ Dev,
+ totalSignalRate_mcps,
+ correctedSignalRate_mcps,
+ pwMult,
+ sigmaEstimateP1,
+ sigmaEstimateP2,
+ peakVcselDuration_us,
+ pDmax_mm);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_pal_range_status(VL53L0_DEV Dev,
+ uint8_t DeviceRangeStatus,
+ FixPoint1616_t SignalRate,
+ uint16_t EffectiveSpadRtnCount,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData,
+ uint8_t *pPalRangeStatus)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t NoneFlag;
+ uint8_t SigmaLimitflag = 0;
+ uint8_t SignalRefClipflag = 0;
+ uint8_t RangeIgnoreThresholdflag = 0;
+ uint8_t SigmaLimitCheckEnable = 0;
+ uint8_t SignalRateFinalRangeLimitCheckEnable = 0;
+ uint8_t SignalRefClipLimitCheckEnable = 0;
+ uint8_t RangeIgnoreThresholdLimitCheckEnable = 0;
+ FixPoint1616_t SigmaEstimate;
+ FixPoint1616_t SigmaLimitValue;
+ FixPoint1616_t SignalRefClipValue;
+ FixPoint1616_t RangeIgnoreThresholdValue;
+ FixPoint1616_t SignalRatePerSpad;
+ uint8_t DeviceRangeStatusInternal = 0;
+ uint16_t tmpWord = 0;
+ uint8_t Temp8;
+ uint32_t Dmax_mm = 0;
+ FixPoint1616_t LastSignalRefMcps;
+
+ LOG_FUNCTION_START("");
+
+
+ /*
+ * VL53L0 has a good ranging when the value of the
+ * DeviceRangeStatus = 11. This function will replace the value 0 with
+ * the value 11 in the DeviceRangeStatus.
+ * In addition, the SigmaEstimator is not included in the VL53L0
+ * DeviceRangeStatus, this will be added in the PalRangeStatus.
+ */
+
+ DeviceRangeStatusInternal = ((DeviceRangeStatus & 0x78) >> 3);
+
+ if (DeviceRangeStatusInternal == 0 ||
+ DeviceRangeStatusInternal == 5 ||
+ DeviceRangeStatusInternal == 7 ||
+ DeviceRangeStatusInternal == 12 ||
+ DeviceRangeStatusInternal == 13 ||
+ DeviceRangeStatusInternal == 14 ||
+ DeviceRangeStatusInternal == 15
+ ) {
+ NoneFlag = 1;
+ } else {
+ NoneFlag = 0;
+ }
+
+ /* LastSignalRefMcps */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x01);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_RdWord(Dev,
+ VL53L0_REG_RESULT_PEAK_SIGNAL_RATE_REF,
+ &tmpWord);
+
+ LastSignalRefMcps = VL53L0_FIXPOINT97TOFIXPOINT1616(tmpWord);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ PALDevDataSet(Dev, LastSignalRefMcps, LastSignalRefMcps);
+
+ /*
+ * Check if Sigma limit is enabled, if yes then do comparison with limit
+ * value and put the result back into pPalRangeStatus.
+ */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ &SigmaLimitCheckEnable);
+
+ if ((SigmaLimitCheckEnable != 0) && (Status == VL53L0_ERROR_NONE)) {
+ /*
+ * compute the Sigma and check with limit
+ */
+ Status = VL53L0_calc_sigma_estimate(
+ Dev,
+ pRangingMeasurementData,
+ &SigmaEstimate,
+ &Dmax_mm);
+ if (Status == VL53L0_ERROR_NONE)
+ pRangingMeasurementData->RangeDMaxMilliMeter = Dmax_mm;
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_GetLimitCheckValue(Dev,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ &SigmaLimitValue);
+
+ if ((SigmaLimitValue > 0) &&
+ (SigmaEstimate > SigmaLimitValue))
+ /* Limit Fail */
+ SigmaLimitflag = 1;
+ }
+ }
+
+ /*
+ * Check if Signal ref clip limit is enabled, if yes then do comparison
+ * with limit value and put the result back into pPalRangeStatus.
+ */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP,
+ &SignalRefClipLimitCheckEnable);
+
+ if ((SignalRefClipLimitCheckEnable != 0) &&
+ (Status == VL53L0_ERROR_NONE)) {
+
+ Status = VL53L0_GetLimitCheckValue(Dev,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP,
+ &SignalRefClipValue);
+
+ if ((SignalRefClipValue > 0) &&
+ (LastSignalRefMcps > SignalRefClipValue)) {
+ /* Limit Fail */
+ SignalRefClipflag = 1;
+ }
+ }
+
+ /*
+ * Check if Signal ref clip limit is enabled, if yes then do comparison
+ * with limit value and put the result back into pPalRangeStatus.
+ * EffectiveSpadRtnCount has a format 8.8
+ * If (Return signal rate < (1.5 x Xtalk x number of Spads)) : FAIL
+ */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ &RangeIgnoreThresholdLimitCheckEnable);
+
+ if ((RangeIgnoreThresholdLimitCheckEnable != 0) &&
+ (Status == VL53L0_ERROR_NONE)) {
+
+ /* Compute the signal rate per spad */
+ if (EffectiveSpadRtnCount == 0) {
+ SignalRatePerSpad = 0;
+ } else {
+ SignalRatePerSpad = (FixPoint1616_t)((256 * SignalRate)
+ / EffectiveSpadRtnCount);
+ }
+
+ Status = VL53L0_GetLimitCheckValue(Dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ &RangeIgnoreThresholdValue);
+
+ if ((RangeIgnoreThresholdValue > 0) &&
+ (SignalRatePerSpad < RangeIgnoreThresholdValue)) {
+ /* Limit Fail add 2^6 to range status */
+ RangeIgnoreThresholdflag = 1;
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (NoneFlag == 1) {
+ *pPalRangeStatus = 255; /* NONE */
+ } else if (DeviceRangeStatusInternal == 1 ||
+ DeviceRangeStatusInternal == 2 ||
+ DeviceRangeStatusInternal == 3) {
+ *pPalRangeStatus = 5; /* HW fail */
+ } else if (DeviceRangeStatusInternal == 6 ||
+ DeviceRangeStatusInternal == 9) {
+ *pPalRangeStatus = 4; /* Phase fail */
+ } else if (DeviceRangeStatusInternal == 8 ||
+ DeviceRangeStatusInternal == 10 ||
+ SignalRefClipflag == 1) {
+ *pPalRangeStatus = 3; /* Min range */
+ } else if (DeviceRangeStatusInternal == 4 ||
+ RangeIgnoreThresholdflag == 1) {
+ *pPalRangeStatus = 2; /* Signal Fail */
+ } else if (SigmaLimitflag == 1) {
+ *pPalRangeStatus = 1; /* Sigma Fail */
+ } else {
+ *pPalRangeStatus = 0; /* Range Valid */
+ }
+ }
+
+ /* DMAX only relevant during range error */
+ if (*pPalRangeStatus == 0)
+ pRangingMeasurementData->RangeDMaxMilliMeter = 0;
+
+ /* fill the Limit Check Status */
+
+ Status = VL53L0_GetLimitCheckEnable(Dev,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ &SignalRateFinalRangeLimitCheckEnable);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if ((SigmaLimitCheckEnable == 0) || (SigmaLimitflag == 1))
+ Temp8 = 1;
+ else
+ Temp8 = 0;
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE, Temp8);
+
+ if ((DeviceRangeStatusInternal == 4) ||
+ (SignalRateFinalRangeLimitCheckEnable == 0))
+ Temp8 = 1;
+ else
+ Temp8 = 0;
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ Temp8);
+
+ if ((SignalRefClipLimitCheckEnable == 0) ||
+ (SignalRefClipflag == 1))
+ Temp8 = 1;
+ else
+ Temp8 = 0;
+
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP, Temp8);
+
+ if ((RangeIgnoreThresholdLimitCheckEnable == 0) ||
+ (RangeIgnoreThresholdflag == 1))
+ Temp8 = 1;
+ else
+ Temp8 = 0;
+
+ VL53L0_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ Temp8);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+
+}
diff --git a/drivers/input/misc/vl53L0/src/vl53l0_api_histogram.c b/drivers/input/misc/vl53L0/src/vl53l0_api_histogram.c
new file mode 100644
index 000000000000..21b0410dd6ae
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l0_api_histogram.c
@@ -0,0 +1,750 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+ IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#include "vl53l0_api.h"
+#include "vl53l0_api_core.h"
+#include "vl53l0_api_histogram.h"
+
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#endif
+#define LOG_FUNCTION_START(fmt, ...) \
+ _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
+#define LOG_FUNCTION_END(status, ...) \
+ _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
+#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
+ _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
+
+
+typedef uint32_t WindowSelection;
+#define VL53L0_AMBIENT_WINDOW_ONLY ((WindowSelection) 0)
+ /*!< Measure Ambient Signal only */
+#define VL53L0_AMBIENT_AND_SIGNAL_WINDOW ((WindowSelection) 1)
+ /*!< Measure Combined Ambient and Signal Rate. */
+
+
+VL53L0_Error VL53L0_start_histogram_measurement(VL53L0_DEV Dev,
+ VL53L0_HistogramModes histoMode,
+ uint32_t count)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t dataByte;
+
+ LOG_FUNCTION_START("");
+
+
+ dataByte = VL53L0_REG_SYSRANGE_MODE_SINGLESHOT |
+ VL53L0_REG_SYSRANGE_MODE_START_STOP;
+
+ /* First histogram measurement must have bit 5 set */
+ if (count == 0)
+ dataByte |= (1 << 5);
+
+ switch (histoMode) {
+ case VL53L0_HISTOGRAMMODE_DISABLED:
+ /* Selected mode not supported */
+ Status = VL53L0_ERROR_INVALID_COMMAND;
+ break;
+
+ case VL53L0_HISTOGRAMMODE_REFERENCE_ONLY:
+ case VL53L0_HISTOGRAMMODE_RETURN_ONLY:
+ case VL53L0_HISTOGRAMMODE_BOTH:
+ dataByte |= (histoMode << 3);
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSRANGE_START,
+ dataByte);
+ if (Status == VL53L0_ERROR_NONE) {
+ /* Set PAL State to Running */
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_RUNNING);
+ }
+ break;
+
+ default:
+ /* Selected mode not supported */
+ Status = VL53L0_ERROR_MODE_NOT_SUPPORTED;
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_confirm_measurement_start(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t NewDataReady = 0;
+ uint32_t LoopNb;
+
+ LOG_FUNCTION_START("");
+
+ LoopNb = 0;
+ do {
+ Status = VL53L0_GetMeasurementDataReady(Dev, &NewDataReady);
+ if ((NewDataReady == 0x01) || Status != VL53L0_ERROR_NONE)
+ break;
+
+ LoopNb = LoopNb + 1;
+ VL53L0_PollingDelay(Dev);
+ } while (LoopNb < VL53L0_DEFAULT_MAX_LOOP);
+
+ if (LoopNb >= VL53L0_DEFAULT_MAX_LOOP)
+ Status = VL53L0_ERROR_TIME_OUT;
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_set_histogram_mode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes HistogramMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ switch (HistogramMode) {
+ case VL53L0_HISTOGRAMMODE_DISABLED:
+ case VL53L0_HISTOGRAMMODE_REFERENCE_ONLY:
+ case VL53L0_HISTOGRAMMODE_RETURN_ONLY:
+ case VL53L0_HISTOGRAMMODE_BOTH:
+ /* Supported mode */
+ VL53L0_SETPARAMETERFIELD(Dev, HistogramMode, HistogramMode);
+ break;
+ default:
+ /* Unsupported mode */
+ Status = VL53L0_ERROR_MODE_NOT_SUPPORTED;
+ }
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_histogram_mode(VL53L0_DEV Dev,
+ VL53L0_HistogramModes *pHistogramMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ VL53L0_GETPARAMETERFIELD(Dev, HistogramMode, *pHistogramMode);
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_perform_single_histogram_measurement(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceModes DeviceMode;
+ VL53L0_HistogramModes HistogramMode = VL53L0_HISTOGRAMMODE_DISABLED;
+ uint32_t MeasCount;
+ uint32_t Measurements;
+
+ /* Get Current DeviceMode */
+ Status = VL53L0_GetHistogramMode(Dev, &HistogramMode);
+
+
+ if (Status != VL53L0_ERROR_NONE)
+ return Status;
+
+
+ if (HistogramMode == VL53L0_HISTOGRAMMODE_BOTH) {
+ if (pHistogramMeasurementData->BufferSize <
+ VL53L0_HISTOGRAM_BUFFER_SIZE) {
+ Status = VL53L0_ERROR_BUFFER_TOO_SMALL;
+ }
+ } else {
+ if (pHistogramMeasurementData->BufferSize <
+ VL53L0_HISTOGRAM_BUFFER_SIZE/2) {
+ Status = VL53L0_ERROR_BUFFER_TOO_SMALL;
+ }
+ }
+ pHistogramMeasurementData->HistogramType = (uint8_t)HistogramMode;
+ pHistogramMeasurementData->ErrorStatus = VL53L0_DEVICEERROR_NONE;
+ pHistogramMeasurementData->FirstBin = 0;
+ pHistogramMeasurementData->NumberOfBins = 0;
+
+
+ /* Get Current DeviceMode */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetDeviceMode(Dev, &DeviceMode);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev, VL53L0_REG_SYSTEM_HISTOGRAM_BIN,
+ 0x00);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT, 0x00);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_WrByte(Dev,
+ VL53L0_REG_HISTOGRAM_CONFIG_READOUT_CTRL, 0x01);
+
+ if (Status != VL53L0_ERROR_NONE)
+ return Status;
+
+ Measurements = 3;
+ if (HistogramMode == VL53L0_HISTOGRAMMODE_BOTH)
+ Measurements = 6;
+
+ if (DeviceMode != VL53L0_DEVICEMODE_SINGLE_HISTOGRAM) {
+ Status = VL53L0_ERROR_INVALID_COMMAND;
+ return Status;
+ }
+
+ /* DeviceMode == VL53L0_DEVICEMODE_SINGLE_HISTOGRAM */
+ MeasCount = 0;
+ while ((MeasCount < Measurements) && (Status == VL53L0_ERROR_NONE)) {
+ Status = VL53L0_start_histogram_measurement(Dev, HistogramMode,
+ MeasCount);
+
+ if (Status == VL53L0_ERROR_NONE)
+ VL53L0_confirm_measurement_start(Dev);
+
+ if (Status == VL53L0_ERROR_NONE)
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_RUNNING);
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_measurement_poll_for_completion(Dev);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_read_histo_measurement(Dev,
+ pHistogramMeasurementData->HistogramData,
+ MeasCount,
+ HistogramMode);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ /*
+ * When reading both rtn and ref arrays,
+ * histograms are read two bins at a time.
+ * For rtn or ref only, histograms are read four
+ * bins at a time.
+ */
+ if (HistogramMode == VL53L0_HISTOGRAMMODE_BOTH)
+ pHistogramMeasurementData->NumberOfBins
+ += 2;
+ else
+ pHistogramMeasurementData->NumberOfBins
+ += 4;
+
+ }
+ }
+
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_ClearInterruptMask(Dev, 0);
+
+ MeasCount++;
+ }
+
+ /* Change PAL State in case of single ranging or single histogram */
+ if (Status == VL53L0_ERROR_NONE) {
+ pHistogramMeasurementData->NumberOfBins = 12;
+ PALDevDataSet(Dev, PalState, VL53L0_STATE_IDLE);
+ }
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_get_histogram_measurement_data(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NOT_IMPLEMENTED;
+
+ LOG_FUNCTION_START("");
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_read_histo_measurement(VL53L0_DEV Dev,
+ uint32_t *histoData,
+ uint32_t offset,
+ VL53L0_HistogramModes histoMode)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t localBuffer[28];
+ uint32_t cDataSize = 4;
+ uint32_t offset1;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_WrByte(Dev, 0xFF, VL53L0_REG_RESULT_CORE_PAGE);
+ Status = VL53L0_ReadMulti(Dev,
+ (uint8_t)VL53L0_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN,
+ localBuffer,
+ 28);
+ Status |= VL53L0_WrByte(Dev, 0xFF, 0x00);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ VL53L0_reverse_bytes(&localBuffer[0], cDataSize);
+ VL53L0_reverse_bytes(&localBuffer[4], cDataSize);
+ VL53L0_reverse_bytes(&localBuffer[20], cDataSize);
+ VL53L0_reverse_bytes(&localBuffer[24], cDataSize);
+
+ offset1 = offset * cDataSize;
+ if (histoMode == VL53L0_HISTOGRAMMODE_BOTH) {
+ /*
+ * When reading both return and ref data, each
+ * measurement reads two ref values and two return
+ * values. Data is stored in an interleaved sequence,
+ * starting with the return histogram.
+ *
+ * Some result Core registers are reused for the
+ * histogram measurements
+ *
+ * The bin values are retrieved in the following order
+ * VL53L0_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_RTN
+ * VL53L0_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_REF
+ * VL53L0_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN
+ * VL53L0_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF
+ */
+
+ memcpy(&histoData[offset1], &localBuffer[4],
+ cDataSize); /* rtn */
+ memcpy(&histoData[offset1 + 1], &localBuffer[24],
+ cDataSize); /* ref */
+ memcpy(&histoData[offset1 + 2], &localBuffer[0],
+ cDataSize); /* rtn */
+ memcpy(&histoData[offset1 + 3], &localBuffer[20],
+ cDataSize); /* ref */
+
+ } else {
+ /*
+ * When reading either return and ref data, each
+ * measurement reads four bin values.
+ *
+ * The bin values are retrieved in the following order
+ * VL53L0_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_RTN
+ * VL53L0_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN
+ * VL53L0_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_REF
+ * VL53L0_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF
+ */
+
+ memcpy(&histoData[offset1], &localBuffer[24],
+ cDataSize);
+ memcpy(&histoData[offset1 + 1], &localBuffer[20],
+ cDataSize);
+ memcpy(&histoData[offset1 + 2], &localBuffer[4],
+ cDataSize);
+ memcpy(&histoData[offset1 + 3], &localBuffer[0],
+ cDataSize);
+
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_get_max_spads(VL53L0_DEV Dev,
+ uint32_t *pmax_spads, uint8_t *pambient_too_high)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t TCC_Enabled;
+ uint8_t MSRC_Enabled;
+ VL53L0_RangingMeasurementData_t RangingMeasurementData;
+ FixPoint1616_t ratio = 0;
+ uint32_t max_spads = 0;
+
+ /* Get the value of the TCC */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_TCC, &TCC_Enabled);
+
+ /* Get the value of the MSRC */
+ if (Status == VL53L0_ERROR_NONE)
+ Status = VL53L0_GetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_MSRC, &MSRC_Enabled);
+
+ /* Disable the TCC */
+ if ((Status == VL53L0_ERROR_NONE) && (TCC_Enabled != 0))
+ Status = VL53L0_SetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_TCC, 0);
+
+ /* Disable the MSRC */
+ if ((Status == VL53L0_ERROR_NONE) && (MSRC_Enabled != 0))
+ Status = VL53L0_SetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_MSRC, 0);
+
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_PerformSingleRangingMeasurement(Dev,
+ &RangingMeasurementData);
+ max_spads = (RangingMeasurementData.EffectiveSpadRtnCount +
+ 128)/256;
+ *pmax_spads = max_spads;
+ }
+
+ /* Check Ambient per spad > 10 Kcps */
+ if (Status == VL53L0_ERROR_NONE) {
+ if (max_spads <= 0) {
+ *pambient_too_high = 1;
+ Status = VL53L0_ERROR_DIVISION_BY_ZERO;
+ } else {
+ ratio = RangingMeasurementData.AmbientRateRtnMegaCps /
+ max_spads;
+
+ /* ratio is given in mega count per second and
+ * FixPoint1616_t
+ */
+ if (ratio > 65536/100)
+ *pambient_too_high = 1;
+ else
+ *pambient_too_high = 0;
+
+ }
+ }
+
+
+ /* Restore the TCC */
+ if (Status == VL53L0_ERROR_NONE) {
+ if (TCC_Enabled != 0)
+ Status = VL53L0_SetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_TCC, 1);
+ }
+
+ /* Restore the MSRC */
+ if (Status == VL53L0_ERROR_NONE) {
+ if (MSRC_Enabled != 0)
+ Status = VL53L0_SetSequenceStepEnable(Dev,
+ VL53L0_SEQUENCESTEP_MSRC, 1);
+ }
+
+ return Status;
+
+}
+
+
+VL53L0_Error calc_xtalk_mcps_per_spad(
+ uint32_t rtn_signal_events,
+ uint32_t timeout_ms,
+ uint32_t max_spads,
+ uint8_t vcsel_pulse_period_pclk,
+ FixPoint1616_t *pxtalk_mcps_per_spad)
+{
+ /* Calculate the X-Talk per Spad based on given inputs.
+ *
+ * To calculate x-talk, only a portion of the vcsel pulse period is
+ * used, therefore we use the ratio between vcsel_width_pclk and
+ * vcsel_pulse_period_pclks to determine the integration time.
+ *
+ * With the rtn signal events, and the integration time,
+ * the x-talk rate per spad is then determined.
+ */
+
+ const FixPoint1616_t cmin_xtalk_per_spad = 8; /* 0.000122 */
+ const FixPoint1616_t ccompensation2 = 13;/* 0.0002 */
+ const FixPoint1616_t ccompensation1 = 7; /* 0.0001; */
+ const FixPoint1616_t ctalk_thresh = 66; /* 0.001 */
+ const uint32_t c16BitRoundingParam = 0x00008000;
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+ FixPoint1616_t xtalk_mcps;
+ FixPoint1616_t vcsel_width_to_period_ratio;
+ FixPoint1616_t integration_time_us;
+ uint32_t integration_time_us_int;
+ uint8_t vcsel_width_pclk = 3;
+
+ LOG_FUNCTION_START("");
+
+ if (vcsel_pulse_period_pclk == 0 || timeout_ms == 0)
+ status = VL53L0_ERROR_DIVISION_BY_ZERO;
+
+
+ if (status == VL53L0_ERROR_NONE) {
+
+ /* (FixPoint1616 + uint32)/uint32 = FixPoint1616 */
+ vcsel_width_to_period_ratio =
+ ((vcsel_width_pclk << 16) +
+ (vcsel_pulse_period_pclk/2))/vcsel_pulse_period_pclk;
+
+ /* uint32_t * FixPoint1616 = FixPoint1616 */
+ integration_time_us = timeout_ms * vcsel_width_to_period_ratio
+ * 1000;
+
+ /*FixPoint1616 >>16 = uint32_t */
+ integration_time_us_int = (integration_time_us +
+ c16BitRoundingParam) >> 16;
+
+ /* (uint32_t << 16)/uint32_t = FixPoint1616 */
+ xtalk_mcps = rtn_signal_events << 16;
+ xtalk_mcps = (xtalk_mcps +
+ (integration_time_us_int/2))/integration_time_us_int;
+
+ /* (FixPoint1616 + uint32)/uint32 = FixPoint1616 */
+ *pxtalk_mcps_per_spad = (xtalk_mcps + (max_spads/2))/max_spads;
+
+ /* Apply compensation to prevent overshoot.
+ */
+ if (*pxtalk_mcps_per_spad < ctalk_thresh)
+ *pxtalk_mcps_per_spad = *pxtalk_mcps_per_spad
+ - ccompensation2;
+ else
+ *pxtalk_mcps_per_spad = *pxtalk_mcps_per_spad
+ - ccompensation1;
+
+ if (*pxtalk_mcps_per_spad < cmin_xtalk_per_spad)
+ *pxtalk_mcps_per_spad = cmin_xtalk_per_spad;
+
+ }
+ LOG_FUNCTION_END("");
+
+ return status;
+}
+
+
+uint32_t bytes_to_int(uint8_t *data_bytes)
+{
+ /* Convert an array of 4 bytes to an integer.
+ */
+ uint32_t data = (uint32_t)data_bytes[0] << 24;
+
+ data += ((uint32_t)data_bytes[1] << 16);
+ data += ((uint32_t)data_bytes[2] << 8);
+ data += ((uint32_t)data_bytes[3]);
+ return data;
+}
+
+VL53L0_Error perform_histo_signal_meas(VL53L0_DEV dev,
+ WindowSelection window_select,
+ uint32_t *psignal_events)
+{
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+ uint8_t data[8];
+ uint8_t readout_ctrl_val;
+ uint32_t bin_width = 3;
+
+ LOG_FUNCTION_START("");
+
+ /* Select Ambient or Total Signal Measurement
+ */
+ if (status == VL53L0_ERROR_NONE) {
+ readout_ctrl_val = bin_width;
+ if (window_select == VL53L0_AMBIENT_WINDOW_ONLY)
+ readout_ctrl_val += 0x80;
+
+ status = VL53L0_WrByte(
+ dev, VL53L0_REG_HISTOGRAM_CONFIG_READOUT_CTRL,
+ readout_ctrl_val);
+ }
+
+ /* Perform Measurement.
+ */
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_start_histogram_measurement(
+ dev, VL53L0_HISTOGRAMMODE_RETURN_ONLY, 0);
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_measurement_poll_for_completion(dev);
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_ClearInterruptMask(dev, 0);
+
+ /* Read Measurement Data.
+ */
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_WrByte(dev, 0xFF, VL53L0_REG_RESULT_CORE_PAGE);
+
+
+ if (status == VL53L0_ERROR_NONE) {
+ status = VL53L0_ReadMulti(dev,
+ (uint8_t)VL53L0_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN,
+ data,
+ 8);
+ }
+
+ if (status == VL53L0_ERROR_NONE)
+ status |= VL53L0_WrByte(dev, 0xFF, 0x00);
+
+
+ /* Take the sum of the Ambient and Signal Window Event readings.
+ */
+ if (status == VL53L0_ERROR_NONE)
+ *psignal_events = bytes_to_int(data) +
+ bytes_to_int(&(data[4]));
+
+
+ LOG_FUNCTION_END(status);
+
+ return status;
+}
+
+VL53L0_Error set_final_range_timeout_us(
+ VL53L0_DEV dev, uint32_t timeout_microSecs,
+ uint16_t final_range_vcsel_period_pclks)
+{
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+ uint16_t final_range_timeout_mclks;
+ uint16_t final_range_encoded_timeOut;
+
+ LOG_FUNCTION_START("");
+
+ /* Calculate FINAL RANGE Timeout in Macro Periods (MCLKS)
+ */
+
+ /* convert timeout to mclks. */
+ final_range_timeout_mclks = VL53L0_calc_timeout_mclks(dev,
+ timeout_microSecs, (uint8_t) final_range_vcsel_period_pclks);
+
+ /* Encode timeout */
+ final_range_encoded_timeOut = VL53L0_encode_timeout(
+ final_range_timeout_mclks);
+
+ /* Write to device */
+ status = VL53L0_WrWord(dev,
+ VL53L0_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI,
+ final_range_encoded_timeOut);
+
+ LOG_FUNCTION_END(status);
+
+ return status;
+}
+
+
+VL53L0_Error perform_histogram_config(VL53L0_DEV dev,
+ uint32_t timeout_ms, uint16_t final_range_vcsel_period_pclks)
+{
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+ uint8_t phaseSelect = 1;
+
+ LOG_FUNCTION_START("");
+
+ if (status == VL53L0_ERROR_NONE)
+ status = set_final_range_timeout_us(
+ dev, timeout_ms * 1000, final_range_vcsel_period_pclks);
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_SetDeviceMode(dev,
+ VL53L0_DEVICEMODE_SINGLE_HISTOGRAM);
+
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_SetHistogramMode(dev,
+ VL53L0_HISTOGRAMMODE_BOTH);
+
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_WrByte(dev, VL53L0_REG_SYSTEM_HISTOGRAM_BIN,
+ 0x00);
+
+
+ /* Apply specific phase select for x-talk measurement */
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_WrByte(dev,
+ VL53L0_REG_HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT,
+ phaseSelect);
+
+
+ LOG_FUNCTION_END(status);
+
+ return status;
+}
+
+
+VL53L0_Error VL53L0_perform_xtalk_measurement(VL53L0_DEV dev,
+ uint32_t timeout_ms, FixPoint1616_t *pxtalk_per_spad,
+ uint8_t *pambient_too_high)
+{
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+ uint32_t signal_events = 0;
+ uint32_t amb_events = 0;
+ uint32_t meas_timing_budget_us;
+ VL53L0_DeviceModes device_mode;
+ uint8_t final_range_vcsel_period_pclks;
+ uint32_t max_spads;
+
+ /* Get Current DeviceMode */
+ status = VL53L0_GetDeviceMode(dev, &device_mode);
+
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_get_max_spads(dev, &max_spads,
+ pambient_too_high);
+
+ if (status != VL53L0_ERROR_NONE)
+ return status;
+
+
+ if (status == VL53L0_ERROR_NONE) {
+ status = VL53L0_GetVcselPulsePeriod(
+ dev,
+ VL53L0_VCSEL_PERIOD_FINAL_RANGE,
+ &final_range_vcsel_period_pclks);
+ }
+
+ if (status == VL53L0_ERROR_NONE) {
+ if (final_range_vcsel_period_pclks < 10)
+ status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+
+ if (status == VL53L0_ERROR_NONE) {
+ perform_histogram_config(
+ dev, timeout_ms, final_range_vcsel_period_pclks);
+ }
+
+ if (status == VL53L0_ERROR_NONE) {
+ status = perform_histo_signal_meas(
+ dev,
+ VL53L0_AMBIENT_WINDOW_ONLY,
+ &amb_events);
+ }
+
+ if (status == VL53L0_ERROR_NONE) {
+ status = perform_histo_signal_meas(
+ dev,
+ VL53L0_AMBIENT_AND_SIGNAL_WINDOW,
+ &signal_events);
+ }
+
+ if (status == VL53L0_ERROR_NONE) {
+ status = calc_xtalk_mcps_per_spad(
+ (signal_events - amb_events),
+ timeout_ms,
+ max_spads,
+ final_range_vcsel_period_pclks,
+ pxtalk_per_spad);
+ }
+
+ /* Revert previous device mode. */
+ if (status == VL53L0_ERROR_NONE)
+ status = VL53L0_SetDeviceMode(dev, device_mode);
+
+ /* Revert previous timing budget, to ensure previous final range vcsel
+ * period is applied.
+ */
+ if (status == VL53L0_ERROR_NONE) {
+ VL53L0_GETPARAMETERFIELD(
+ dev,
+ MeasurementTimingBudgetMicroSeconds,
+ meas_timing_budget_us);
+
+ status = VL53L0_SetMeasurementTimingBudgetMicroSeconds(
+ dev, meas_timing_budget_us);
+ }
+
+ return status;
+}
+
diff --git a/drivers/input/misc/vl53L0/src/vl53l0_api_ranging.c b/drivers/input/misc/vl53L0/src/vl53l0_api_ranging.c
new file mode 100644
index 000000000000..f575aec7c5ed
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l0_api_ranging.c
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+ IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#include "vl53l0_api.h"
+#include "vl53l0_api_core.h"
+
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#endif
+#define LOG_FUNCTION_START(fmt, ...) \
+ _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
+#define LOG_FUNCTION_END(status, ...) \
+ _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
+#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
+ _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
+
diff --git a/drivers/input/misc/vl53L0/src/vl53l0_api_strings.c b/drivers/input/misc/vl53L0/src/vl53l0_api_strings.c
new file mode 100644
index 000000000000..a5f2bbadd290
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l0_api_strings.c
@@ -0,0 +1,463 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+ IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#include "vl53l0_api.h"
+#include "vl53l0_api_core.h"
+#include "vl53l0_api_strings.h"
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#endif
+
+#define LOG_FUNCTION_START(fmt, ...) \
+ _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
+#define LOG_FUNCTION_END(status, ...) \
+ _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
+#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
+ _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
+
+
+VL53L0_Error VL53L0_check_part_used(VL53L0_DEV Dev,
+ uint8_t *Revision,
+ VL53L0_DeviceInfo_t *pVL53L0_DeviceInfo)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t ModuleIdInt;
+ char *ProductId_tmp;
+
+ LOG_FUNCTION_START("");
+
+ Status = VL53L0_get_info_from_device(Dev, 2);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ ModuleIdInt = VL53L0_GETDEVICESPECIFICPARAMETER(Dev, ModuleId);
+
+ if (ModuleIdInt == 0) {
+ *Revision = 0;
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->ProductId, "");
+ } else {
+ *Revision = VL53L0_GETDEVICESPECIFICPARAMETER(Dev, Revision);
+ ProductId_tmp = VL53L0_GETDEVICESPECIFICPARAMETER(Dev,
+ ProductId);
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->ProductId, ProductId_tmp);
+ }
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_get_device_info(VL53L0_DEV Dev,
+ VL53L0_DeviceInfo_t *pVL53L0_DeviceInfo)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint8_t revision_id;
+ uint8_t Revision;
+
+ Status = VL53L0_check_part_used(Dev, &Revision, pVL53L0_DeviceInfo);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ if (Revision == 0) {
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Name,
+ VL53L0_STRING_DEVICE_INFO_NAME_TS0);
+ } else if ((Revision <= 34) && (Revision != 32)) {
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Name,
+ VL53L0_STRING_DEVICE_INFO_NAME_TS1);
+ } else if (Revision < 39) {
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Name,
+ VL53L0_STRING_DEVICE_INFO_NAME_TS2);
+ } else {
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Name,
+ VL53L0_STRING_DEVICE_INFO_NAME_ES1);
+ }
+
+ VL53L0_COPYSTRING(pVL53L0_DeviceInfo->Type,
+ VL53L0_STRING_DEVICE_INFO_TYPE);
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdByte(Dev, VL53L0_REG_IDENTIFICATION_MODEL_ID,
+ &pVL53L0_DeviceInfo->ProductType);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = VL53L0_RdByte(Dev,
+ VL53L0_REG_IDENTIFICATION_REVISION_ID,
+ &revision_id);
+ pVL53L0_DeviceInfo->ProductRevisionMajor = 1;
+ pVL53L0_DeviceInfo->ProductRevisionMinor =
+ (revision_id & 0xF0) >> 4;
+ }
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_get_device_error_string(VL53L0_DeviceError ErrorCode,
+ char *pDeviceErrorString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ switch (ErrorCode) {
+ case VL53L0_DEVICEERROR_NONE:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_NONE);
+ break;
+ case VL53L0_DEVICEERROR_VCSELCONTINUITYTESTFAILURE:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_VCSELCONTINUITYTESTFAILURE);
+ break;
+ case VL53L0_DEVICEERROR_VCSELWATCHDOGTESTFAILURE:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_VCSELWATCHDOGTESTFAILURE);
+ break;
+ case VL53L0_DEVICEERROR_NOVHVVALUEFOUND:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_NOVHVVALUEFOUND);
+ break;
+ case VL53L0_DEVICEERROR_MSRCNOTARGET:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_MSRCNOTARGET);
+ break;
+ case VL53L0_DEVICEERROR_SNRCHECK:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_SNRCHECK);
+ break;
+ case VL53L0_DEVICEERROR_RANGEPHASECHECK:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_RANGEPHASECHECK);
+ break;
+ case VL53L0_DEVICEERROR_SIGMATHRESHOLDCHECK:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_SIGMATHRESHOLDCHECK);
+ break;
+ case VL53L0_DEVICEERROR_TCC:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_TCC);
+ break;
+ case VL53L0_DEVICEERROR_PHASECONSISTENCY:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_PHASECONSISTENCY);
+ break;
+ case VL53L0_DEVICEERROR_MINCLIP:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_MINCLIP);
+ break;
+ case VL53L0_DEVICEERROR_RANGECOMPLETE:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_RANGECOMPLETE);
+ break;
+ case VL53L0_DEVICEERROR_ALGOUNDERFLOW:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_ALGOUNDERFLOW);
+ break;
+ case VL53L0_DEVICEERROR_ALGOOVERFLOW:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_ALGOOVERFLOW);
+ break;
+ case VL53L0_DEVICEERROR_RANGEIGNORETHRESHOLD:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_DEVICEERROR_RANGEIGNORETHRESHOLD);
+ break;
+
+ default:
+ VL53L0_COPYSTRING(pDeviceErrorString,
+ VL53L0_STRING_UNKNOW_ERROR_CODE);
+
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_range_status_string(uint8_t RangeStatus,
+ char *pRangeStatusString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ switch (RangeStatus) {
+ case 0:
+ VL53L0_COPYSTRING(pRangeStatusString,
+ VL53L0_STRING_RANGESTATUS_RANGEVALID);
+ break;
+ case 1:
+ VL53L0_COPYSTRING(pRangeStatusString,
+ VL53L0_STRING_RANGESTATUS_SIGMA);
+ break;
+ case 2:
+ VL53L0_COPYSTRING(pRangeStatusString,
+ VL53L0_STRING_RANGESTATUS_SIGNAL);
+ break;
+ case 3:
+ VL53L0_COPYSTRING(pRangeStatusString,
+ VL53L0_STRING_RANGESTATUS_MINRANGE);
+ break;
+ case 4:
+ VL53L0_COPYSTRING(pRangeStatusString,
+ VL53L0_STRING_RANGESTATUS_PHASE);
+ break;
+ case 5:
+ VL53L0_COPYSTRING(pRangeStatusString,
+ VL53L0_STRING_RANGESTATUS_HW);
+ break;
+
+ default: /**/
+ VL53L0_COPYSTRING(pRangeStatusString,
+ VL53L0_STRING_RANGESTATUS_NONE);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_pal_error_string(VL53L0_Error PalErrorCode,
+ char *pPalErrorString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ switch (PalErrorCode) {
+ case VL53L0_ERROR_NONE:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_NONE);
+ break;
+ case VL53L0_ERROR_CALIBRATION_WARNING:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_CALIBRATION_WARNING);
+ break;
+ case VL53L0_ERROR_MIN_CLIPPED:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_MIN_CLIPPED);
+ break;
+ case VL53L0_ERROR_UNDEFINED:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_UNDEFINED);
+ break;
+ case VL53L0_ERROR_INVALID_PARAMS:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_INVALID_PARAMS);
+ break;
+ case VL53L0_ERROR_NOT_SUPPORTED:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_NOT_SUPPORTED);
+ break;
+ case VL53L0_ERROR_INTERRUPT_NOT_CLEARED:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_INTERRUPT_NOT_CLEARED);
+ break;
+ case VL53L0_ERROR_RANGE_ERROR:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_RANGE_ERROR);
+ break;
+ case VL53L0_ERROR_TIME_OUT:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_TIME_OUT);
+ break;
+ case VL53L0_ERROR_MODE_NOT_SUPPORTED:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_MODE_NOT_SUPPORTED);
+ break;
+ case VL53L0_ERROR_BUFFER_TOO_SMALL:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_BUFFER_TOO_SMALL);
+ break;
+ case VL53L0_ERROR_GPIO_NOT_EXISTING:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_GPIO_NOT_EXISTING);
+ break;
+ case VL53L0_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED);
+ break;
+ case VL53L0_ERROR_CONTROL_INTERFACE:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_CONTROL_INTERFACE);
+ break;
+ case VL53L0_ERROR_INVALID_COMMAND:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_INVALID_COMMAND);
+ break;
+ case VL53L0_ERROR_DIVISION_BY_ZERO:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_DIVISION_BY_ZERO);
+ break;
+ case VL53L0_ERROR_REF_SPAD_INIT:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_REF_SPAD_INIT);
+ break;
+ case VL53L0_ERROR_NOT_IMPLEMENTED:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_ERROR_NOT_IMPLEMENTED);
+ break;
+
+ default:
+ VL53L0_COPYSTRING(pPalErrorString,
+ VL53L0_STRING_UNKNOW_ERROR_CODE);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_pal_state_string(VL53L0_State PalStateCode,
+ char *pPalStateString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ switch (PalStateCode) {
+ case VL53L0_STATE_POWERDOWN:
+ VL53L0_COPYSTRING(pPalStateString,
+ VL53L0_STRING_STATE_POWERDOWN);
+ break;
+ case VL53L0_STATE_WAIT_STATICINIT:
+ VL53L0_COPYSTRING(pPalStateString,
+ VL53L0_STRING_STATE_WAIT_STATICINIT);
+ break;
+ case VL53L0_STATE_STANDBY:
+ VL53L0_COPYSTRING(pPalStateString,
+ VL53L0_STRING_STATE_STANDBY);
+ break;
+ case VL53L0_STATE_IDLE:
+ VL53L0_COPYSTRING(pPalStateString,
+ VL53L0_STRING_STATE_IDLE);
+ break;
+ case VL53L0_STATE_RUNNING:
+ VL53L0_COPYSTRING(pPalStateString,
+ VL53L0_STRING_STATE_RUNNING);
+ break;
+ case VL53L0_STATE_UNKNOWN:
+ VL53L0_COPYSTRING(pPalStateString,
+ VL53L0_STRING_STATE_UNKNOWN);
+ break;
+ case VL53L0_STATE_ERROR:
+ VL53L0_COPYSTRING(pPalStateString,
+ VL53L0_STRING_STATE_ERROR);
+ break;
+
+ default:
+ VL53L0_COPYSTRING(pPalStateString,
+ VL53L0_STRING_STATE_UNKNOWN);
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
+
+VL53L0_Error VL53L0_get_sequence_steps_info(
+ VL53L0_SequenceStepId SequenceStepId,
+ char *pSequenceStepsString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ switch (SequenceStepId) {
+ case VL53L0_SEQUENCESTEP_TCC:
+ VL53L0_COPYSTRING(pSequenceStepsString,
+ VL53L0_STRING_SEQUENCESTEP_TCC);
+ break;
+ case VL53L0_SEQUENCESTEP_DSS:
+ VL53L0_COPYSTRING(pSequenceStepsString,
+ VL53L0_STRING_SEQUENCESTEP_DSS);
+ break;
+ case VL53L0_SEQUENCESTEP_MSRC:
+ VL53L0_COPYSTRING(pSequenceStepsString,
+ VL53L0_STRING_SEQUENCESTEP_MSRC);
+ break;
+ case VL53L0_SEQUENCESTEP_PRE_RANGE:
+ VL53L0_COPYSTRING(pSequenceStepsString,
+ VL53L0_STRING_SEQUENCESTEP_PRE_RANGE);
+ break;
+ case VL53L0_SEQUENCESTEP_FINAL_RANGE:
+ VL53L0_COPYSTRING(pSequenceStepsString,
+ VL53L0_STRING_SEQUENCESTEP_FINAL_RANGE);
+ break;
+
+ default:
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+ }
+
+ LOG_FUNCTION_END(Status);
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_get_limit_check_info(VL53L0_DEV Dev, uint16_t LimitCheckId,
+ char *pLimitCheckString)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+
+ switch (LimitCheckId) {
+ case VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE:
+ VL53L0_COPYSTRING(pLimitCheckString,
+ VL53L0_STRING_CHECKENABLE_SIGMA_FINAL_RANGE);
+ break;
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE:
+ VL53L0_COPYSTRING(pLimitCheckString,
+ VL53L0_STRING_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE);
+ break;
+ case VL53L0_CHECKENABLE_SIGNAL_REF_CLIP:
+ VL53L0_COPYSTRING(pLimitCheckString,
+ VL53L0_STRING_CHECKENABLE_SIGNAL_REF_CLIP);
+ break;
+ case VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD:
+ VL53L0_COPYSTRING(pLimitCheckString,
+ VL53L0_STRING_CHECKENABLE_RANGE_IGNORE_THRESHOLD);
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_MSRC:
+ VL53L0_COPYSTRING(pLimitCheckString,
+ VL53L0_STRING_CHECKENABLE_SIGNAL_RATE_MSRC);
+ break;
+
+ case VL53L0_CHECKENABLE_SIGNAL_RATE_PRE_RANGE:
+ VL53L0_COPYSTRING(pLimitCheckString,
+ VL53L0_STRING_CHECKENABLE_SIGNAL_RATE_PRE_RANGE);
+ break;
+
+ default:
+ VL53L0_COPYSTRING(pLimitCheckString,
+ VL53L0_STRING_UNKNOW_ERROR_CODE);
+
+ }
+
+ LOG_FUNCTION_END(Status);
+ return Status;
+}
diff --git a/drivers/input/misc/vl53L0/src/vl53l0_i2c_platform.c b/drivers/input/misc/vl53L0/src/vl53l0_i2c_platform.c
new file mode 100644
index 000000000000..e4097e1ccdd5
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l0_i2c_platform.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2016 STMicroelectronics Imaging Division.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*!
+ * \file VL53L0_i2c_platform.c
+ * \brief Code function defintions for EWOK Platform Layer
+ *
+ */
+
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "stmvl53l0-i2c.h"
+#include "stmvl53l0-cci.h"
+
+#include "vl53l0_platform.h"
+#include "vl53l0_i2c_platform.h"
+#include "vl53l0_def.h"
+
+#include "vl53l0_platform_log.h"
+
+#ifdef VL53L0_LOG_ENABLE
+#define trace_print(level, ...) \
+ trace_print_module_function(TRACE_MODULE_PLATFORM, level,\
+ TRACE_FUNCTION_NONE, ##__VA_ARGS__)
+#define trace_i2c(...) \
+ trace_print_module_function(TRACE_MODULE_NONE, \
+ TRACE_LEVEL_NONE, TRACE_FUNCTION_I2C, ##__VA_ARGS__)
+#endif
+
+/**
+ * @def I2C_BUFFER_CONFIG
+ *
+ * @brief Configure Device register I2C access
+ *
+ * @li 0 : one GLOBAL buffer \n
+ * Use one global buffer of MAX_I2C_XFER_SIZE byte in data space \n
+ * This solution is not multi-Device compliant nor multi-thread cpu safe \n
+ * It can be the best option for small 8/16 bit MCU without stack and limited
+ * ram (STM8s, 80C51 ...)
+ *
+ * @li 1 : ON_STACK/local \n
+ * Use local variable (on stack) buffer \n
+ * This solution is multi-thread with use of i2c resource lock or mutex see
+ * VL6180x_GetI2CAccess() \n
+ *
+ * @li 2 : User defined \n
+ * Per Device potentially dynamic allocated. Requires VL6180x_GetI2cBuffer()
+ * to be implemented.
+ * @ingroup Configuration
+ */
+#define I2C_BUFFER_CONFIG 1
+
+#if I2C_BUFFER_CONFIG == 0
+ /* GLOBAL config buffer */
+ uint8_t i2c_global_buffer[VL53L0_MAX_I2C_XFER_SIZE];
+
+ #define DECL_I2C_BUFFER
+ #define VL53L0_GetLocalBuffer(Dev, n_byte) i2c_global_buffer
+
+#elif I2C_BUFFER_CONFIG == 1
+ /* ON STACK */
+ uint8_t LocBuffer[VL53L0_MAX_I2C_XFER_SIZE];
+ #define VL53L0_GetLocalBuffer(Dev, n_byte) LocBuffer
+#elif I2C_BUFFER_CONFIG == 2
+ /* user define buffer type declare DECL_I2C_BUFFER as access via
+ * VL53L0_GetLocalBuffer
+ */
+ #define DECL_I2C_BUFFER
+#else
+#error "invalid I2C_BUFFER_CONFIG "
+#endif
+
+
+/* none but could be for a flag var to
+ * get/pass to mutex interruptible return flags and try again
+ */
+#define VL53L0_I2C_USER_VAR
+#define VL53L0_GetI2CAccess(Dev) /* todo mutex acquire */
+#define VL53L0_DoneI2CAcces(Dev) /* todo mutex release */
+
+
+char debug_string[VL53L0_MAX_STRING_LENGTH_PLT];
+
+
+#define MIN_COMMS_VERSION_MAJOR 1
+#define MIN_COMMS_VERSION_MINOR 8
+#define MIN_COMMS_VERSION_BUILD 1
+#define MIN_COMMS_VERSION_REVISION 0
+
+#define STATUS_OK 0x00
+#define STATUS_FAIL 0x01
+
+bool_t _check_min_version(void)
+{
+ bool_t min_version_comms_dll = false;
+
+ min_version_comms_dll = true;
+
+ return min_version_comms_dll;
+}
+
+int32_t VL53L0_comms_initialise(uint8_t comms_type, uint16_t comms_speed_khz)
+{
+ int32_t status = STATUS_OK;
+
+ return status;
+}
+
+int32_t VL53L0_comms_close(void)
+{
+ int32_t status = STATUS_OK;
+
+
+ return status;
+}
+
+int32_t VL53L0_set_page(VL53L0_DEV dev, uint8_t page_data)
+{
+ int32_t status = STATUS_OK;
+ uint16_t page_index = 0xFF;
+ uint8_t *buffer;
+
+ buffer = VL53L0_GetLocalBuffer(dev, 3);
+ buffer[0] = page_index >> 8;
+ buffer[1] = page_index & 0xff;
+ buffer[2] = page_data;
+
+ status = VL53L0_I2CWrite(dev, buffer, (uint8_t) 3);
+ return status;
+}
+
+int32_t VL53L0_write_multi(VL53L0_DEV dev, uint8_t index, uint8_t *pdata,
+ int32_t count)
+{
+ int32_t status = STATUS_OK;
+ uint8_t *buffer;
+
+#ifdef VL53L0_LOG_ENABLE
+ int32_t i = 0;
+ char value_as_str[VL53L0_MAX_STRING_LENGTH_PLT];
+ char *pvalue_as_str;
+
+ pvalue_as_str = value_as_str;
+
+ for (i = 0 ; i < count ; i++) {
+ snprintf(pvalue_as_str, sizeof(pvalue_as_str),
+ "%02X", *(pdata + i));
+
+ pvalue_as_str += 2;
+ }
+ trace_i2c("Write reg : 0x%04X, Val : 0x%s\n", index, value_as_str);
+#endif
+ if ((count + 1) > VL53L0_MAX_I2C_XFER_SIZE)
+ return STATUS_FAIL;
+ buffer = VL53L0_GetLocalBuffer(dev, (count+1));
+ buffer[0] = index;
+ memcpy(&buffer[1], pdata, count);
+ status = VL53L0_I2CWrite(dev, buffer, (count+1));
+
+ return status;
+}
+
+int32_t VL53L0_read_multi(VL53L0_DEV dev, uint8_t index, uint8_t *pdata,
+ int32_t count)
+{
+ int32_t status = STATUS_OK;
+ uint8_t *buffer;
+
+#ifdef VL53L0_LOG_ENABLE
+ int32_t i = 0;
+ char value_as_str[VL53L0_MAX_STRING_LENGTH_PLT];
+ char *pvalue_as_str;
+#endif
+
+ if ((count + 1) > VL53L0_MAX_I2C_XFER_SIZE)
+ return STATUS_FAIL;
+
+ buffer = VL53L0_GetLocalBuffer(dev, 1);
+ buffer[0] = index;
+ status = VL53L0_I2CWrite(dev, (uint8_t *)buffer, (uint8_t)1);
+ if (!status) {
+ pdata[0] = index;
+ status = VL53L0_I2CRead(dev, pdata, count);
+ }
+
+#ifdef VL53L0_LOG_ENABLE
+ pvalue_as_str = value_as_str;
+
+ for (i = 0 ; i < count ; i++) {
+ snprintf(pvalue_as_str, sizeof(value_as_str),
+ "%02X", *(pdata+i));
+ pvalue_as_str += 2;
+ }
+
+ trace_i2c("Read reg : 0x%04X, Val : 0x%s\n", index, value_as_str);
+#endif
+
+ return status;
+}
+
+
+int32_t VL53L0_write_byte(VL53L0_DEV dev, uint8_t index, uint8_t data)
+{
+ int32_t status = STATUS_OK;
+ const int32_t cbyte_count = 1;
+
+ status = VL53L0_write_multi(dev, index, &data, cbyte_count);
+
+ return status;
+
+}
+
+
+int32_t VL53L0_write_word(VL53L0_DEV dev, uint8_t index, uint16_t data)
+{
+ int32_t status = STATUS_OK;
+
+ uint8_t buffer[BYTES_PER_WORD];
+
+ /* Split 16-bit word into MS and LS uint8_t */
+ buffer[0] = (uint8_t)(data >> 8);
+ buffer[1] = (uint8_t)(data & 0x00FF);
+
+ status = VL53L0_write_multi(dev, index, buffer, BYTES_PER_WORD);
+
+ return status;
+
+}
+
+
+int32_t VL53L0_write_dword(VL53L0_DEV dev, uint8_t index, uint32_t data)
+{
+ int32_t status = STATUS_OK;
+ uint8_t buffer[BYTES_PER_DWORD];
+
+ /* Split 32-bit word into MS ... LS bytes */
+ buffer[0] = (uint8_t) (data >> 24);
+ buffer[1] = (uint8_t)((data & 0x00FF0000) >> 16);
+ buffer[2] = (uint8_t)((data & 0x0000FF00) >> 8);
+ buffer[3] = (uint8_t) (data & 0x000000FF);
+
+ status = VL53L0_write_multi(dev, index, buffer, BYTES_PER_DWORD);
+
+ return status;
+
+}
+
+
+int32_t VL53L0_read_byte(VL53L0_DEV dev, uint8_t index, uint8_t *pdata)
+{
+ int32_t status = STATUS_OK;
+ int32_t cbyte_count = 1;
+
+ status = VL53L0_read_multi(dev, index, pdata, cbyte_count);
+
+ return status;
+
+}
+
+
+int32_t VL53L0_read_word(VL53L0_DEV dev, uint8_t index, uint16_t *pdata)
+{
+ int32_t status = STATUS_OK;
+ uint8_t buffer[BYTES_PER_WORD];
+
+ status = VL53L0_read_multi(dev, index, buffer, BYTES_PER_WORD);
+ *pdata = ((uint16_t)buffer[0]<<8) + (uint16_t)buffer[1];
+
+ return status;
+
+}
+
+int32_t VL53L0_read_dword(VL53L0_DEV dev, uint8_t index, uint32_t *pdata)
+{
+ int32_t status = STATUS_OK;
+ uint8_t buffer[BYTES_PER_DWORD];
+
+ status = VL53L0_read_multi(dev, index, buffer, BYTES_PER_DWORD);
+ *pdata = ((uint32_t)buffer[0]<<24) + ((uint32_t)buffer[1]<<16) +
+ ((uint32_t)buffer[2]<<8) + (uint32_t)buffer[3];
+
+ return status;
+
+}
+
+int32_t VL53L0_platform_wait_us(int32_t wait_us)
+{
+ int32_t status = STATUS_OK;
+
+ msleep((wait_us/1000));
+
+#ifdef VL53L0_LOG_ENABLE
+ trace_i2c("Wait us : %6d\n", wait_us);
+#endif
+
+ return status;
+
+}
+
+
+int32_t VL53L0_wait_ms(int32_t wait_ms)
+{
+ int32_t status = STATUS_OK;
+
+ msleep(wait_ms);
+
+#ifdef VL53L0_LOG_ENABLE
+ trace_i2c("Wait ms : %6d\n", wait_ms);
+#endif
+
+ return status;
+
+}
+
+
+int32_t VL53L0_set_gpio(uint8_t level)
+{
+ int32_t status = STATUS_OK;
+#ifdef VL53L0_LOG_ENABLE
+ trace_i2c("// Set GPIO = %d;\n", level);
+#endif
+
+ return status;
+
+}
+
+
+int32_t VL53L0_get_gpio(uint8_t *plevel)
+{
+ int32_t status = STATUS_OK;
+#ifdef VL53L0_LOG_ENABLE
+ trace_i2c("// Get GPIO = %d;\n", *plevel);
+#endif
+ return status;
+}
+
+
+int32_t VL53L0_release_gpio(void)
+{
+ int32_t status = STATUS_OK;
+#ifdef VL53L0_LOG_ENABLE
+ trace_i2c("// Releasing force on GPIO\n");
+#endif
+ return status;
+
+}
+
+int32_t VL53L0_cycle_power(void)
+{
+ int32_t status = STATUS_OK;
+#ifdef VL53L0_LOG_ENABLE
+ trace_i2c("// cycle sensor power\n");
+#endif
+
+ return status;
+}
+
+
+int32_t VL53L0_get_timer_frequency(int32_t *ptimer_freq_hz)
+{
+ *ptimer_freq_hz = 0;
+ return STATUS_FAIL;
+}
+
+
+int32_t VL53L0_get_timer_value(int32_t *ptimer_count)
+{
+ *ptimer_count = 0;
+ return STATUS_FAIL;
+}
diff --git a/drivers/input/misc/vl53L0/src/vl53l0_platform.c b/drivers/input/misc/vl53L0/src/vl53l0_platform.c
new file mode 100644
index 000000000000..f7292ab6f8f2
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l0_platform.c
@@ -0,0 +1,242 @@
+/*******************************************************************************
+ * Copyright © 2016, STMicroelectronics International N.V.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of STMicroelectronics nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
+IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+/**
+ * @file VL53L0_i2c.c
+ *
+ * Copyright (C) 2014 ST MicroElectronics
+ *
+ * provide variable word size byte/Word/dword VL6180x register access via i2c
+ *
+ */
+#include "vl53l0_platform.h"
+#include "vl53l0_i2c_platform.h"
+#include "vl53l0_api.h"
+
+#define LOG_FUNCTION_START(fmt, ...) \
+ _LOG_FUNCTION_START(TRACE_MODULE_PLATFORM, fmt, ##__VA_ARGS__)
+#define LOG_FUNCTION_END(status, ...) \
+ _LOG_FUNCTION_END(TRACE_MODULE_PLATFORM, status, ##__VA_ARGS__)
+#define LOG_FUNCTION_END_FMT(status, fmt, ...)\
+ _LOG_FUNCTION_END_FMT(TRACE_MODULE_PLATFORM, status,\
+ fmt, ##__VA_ARGS__)
+
+
+
+VL53L0_Error VL53L0_LockSequenceAccess(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_UnlockSequenceAccess(VL53L0_DEV Dev)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ return Status;
+}
+
+/* the ranging_sensor_comms.dll will take care of the page selection */
+VL53L0_Error VL53L0_WriteMulti(VL53L0_DEV Dev, uint8_t index,
+ uint8_t *pdata, uint32_t count)
+{
+
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t status_int = 0;
+ uint8_t deviceAddress;
+
+ if (count >= VL53L0_MAX_I2C_XFER_SIZE)
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+
+ deviceAddress = Dev->I2cDevAddr;
+
+ status_int = VL53L0_write_multi(Dev, index, pdata, count);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ return Status;
+}
+
+/* the ranging_sensor_comms.dll will take care of the page selection */
+VL53L0_Error VL53L0_ReadMulti(VL53L0_DEV Dev, uint8_t index,
+ uint8_t *pdata, uint32_t count)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t status_int;
+ uint8_t deviceAddress;
+
+ if (count >= VL53L0_MAX_I2C_XFER_SIZE)
+ Status = VL53L0_ERROR_INVALID_PARAMS;
+
+
+ deviceAddress = Dev->I2cDevAddr;
+
+ status_int = VL53L0_read_multi(Dev, index, pdata, count);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ return Status;
+}
+
+
+VL53L0_Error VL53L0_WrByte(VL53L0_DEV Dev, uint8_t index, uint8_t data)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t status_int;
+ uint8_t deviceAddress;
+
+ deviceAddress = Dev->I2cDevAddr;
+
+ status_int = VL53L0_write_byte(Dev, index, data);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_WrWord(VL53L0_DEV Dev, uint8_t index, uint16_t data)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t status_int;
+ uint8_t deviceAddress;
+
+ deviceAddress = Dev->I2cDevAddr;
+
+ status_int = VL53L0_write_word(Dev, index, data);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_WrDWord(VL53L0_DEV Dev, uint8_t index, uint32_t data)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t status_int;
+ uint8_t deviceAddress;
+
+ deviceAddress = Dev->I2cDevAddr;
+
+ status_int = VL53L0_write_dword(Dev, index, data);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_UpdateByte(VL53L0_DEV Dev, uint8_t index,
+ uint8_t AndData, uint8_t OrData)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t status_int;
+ uint8_t deviceAddress;
+ uint8_t data;
+
+ deviceAddress = Dev->I2cDevAddr;
+
+ status_int = VL53L0_read_byte(Dev, index, &data);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ if (Status == VL53L0_ERROR_NONE) {
+ data = (data & AndData) | OrData;
+ status_int = VL53L0_write_byte(Dev, index, data);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+ }
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_RdByte(VL53L0_DEV Dev, uint8_t index, uint8_t *data)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t status_int;
+ uint8_t deviceAddress;
+
+ deviceAddress = Dev->I2cDevAddr;
+
+ status_int = VL53L0_read_byte(Dev, index, data);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_RdWord(VL53L0_DEV Dev, uint8_t index, uint16_t *data)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t status_int;
+ uint8_t deviceAddress;
+
+ deviceAddress = Dev->I2cDevAddr;
+
+ status_int = VL53L0_read_word(Dev, index, data);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ return Status;
+}
+
+VL53L0_Error VL53L0_RdDWord(VL53L0_DEV Dev, uint8_t index, uint32_t *data)
+{
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int32_t status_int;
+ uint8_t deviceAddress;
+
+ deviceAddress = Dev->I2cDevAddr;
+
+ status_int = VL53L0_read_dword(Dev, index, data);
+
+ if (status_int != 0)
+ Status = VL53L0_ERROR_CONTROL_INTERFACE;
+
+ return Status;
+}
+
+#define VL53L0_POLLINGDELAY_LOOPNB 250
+VL53L0_Error VL53L0_PollingDelay(VL53L0_DEV Dev)
+{
+ VL53L0_Error status = VL53L0_ERROR_NONE;
+
+ LOG_FUNCTION_START("");
+ usleep_range(950, 1000);
+ LOG_FUNCTION_END(status);
+ return status;
+}
diff --git a/drivers/input/misc/vl53L0/src/vl53l0_port_i2c.c b/drivers/input/misc/vl53L0/src/vl53l0_port_i2c.c
new file mode 100644
index 000000000000..3dc085f60326
--- /dev/null
+++ b/drivers/input/misc/vl53L0/src/vl53l0_port_i2c.c
@@ -0,0 +1,155 @@
+/*
+ * vl53l0_port_i2c.c
+ *
+ * Created on: July, 2015
+ * Author: Teresa Tao
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include "stmvl53l0-i2c.h"
+#include "stmvl53l0-cci.h"
+#include "vl53l0_platform.h"
+#include "vl53l0_i2c_platform.h"
+#include "stmvl53l0.h"
+
+#define I2C_M_WR 0x00
+#define STATUS_OK 0x00
+#define STATUS_FAIL (-1)
+/** int VL53L0_I2CWrite(VL53L0_Dev_t dev, void *buff, uint8_t len);
+ * @brief Write data buffer to VL53L0 device via i2c
+ * @param dev The device to write to
+ * @param buff The data buffer
+ * @param len The length of the transaction in byte
+ * @return 0 on success
+ */
+int VL53L0_I2CWrite(VL53L0_DEV dev, uint8_t *buff, uint8_t len)
+{
+ int err = 0;
+
+ if (dev->bus_type == CCI_BUS) {
+#ifdef CAMERA_CCI
+ uint16_t index;
+ struct cci_data *cci_client_obj =
+ (struct cci_data *)dev->client_object;
+ struct msm_camera_i2c_client *client = cci_client_obj->client;
+
+ index = buff[0];
+ /*pr_err("%s: index: %d len: %d\n", __func__, index, len); */
+
+ if (len == 2) {
+ uint8_t data;
+
+ data = buff[1];
+ /* for byte access */
+ err = client->i2c_func_tbl->i2c_write(client, index,
+ data, MSM_CAMERA_I2C_BYTE_DATA);
+ if (err < 0) {
+ pr_err("%s:%d failed status=%d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+ } else if (len == 3) {
+ uint16_t data;
+
+ data = ((uint16_t)buff[1] << 8) | (uint16_t)buff[2];
+ err = client->i2c_func_tbl->i2c_write(client, index,
+ data, MSM_CAMERA_I2C_WORD_DATA);
+ if (err < 0) {
+ pr_err("%s:%d failed status=%d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+ } else if (len >= 5) {
+ err = client->i2c_func_tbl->i2c_write_seq(client,
+ index, &buff[1], (len-1));
+ if (err < 0) {
+ pr_err("%s:%d failed status=%d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+
+ }
+#endif
+#ifndef CAMERA_CCI
+ } else {
+ struct i2c_msg msg[1];
+ struct i2c_data *i2c_client_obj =
+ (struct i2c_data *)dev->client_object;
+ struct i2c_client *client =
+ (struct i2c_client *)i2c_client_obj->client;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = I2C_M_WR;
+ msg[0].buf = buff;
+ msg[0].len = len;
+
+ err = i2c_transfer(client->adapter, msg, 1);
+ /* return the actual messages transfer */
+ if (err != 1) {
+ pr_err("%s: i2c_transfer err:%d, addr:0x%x, reg:0x%x\n",
+ __func__, err, client->addr,
+ (buff[0] << 8 | buff[1]));
+ return STATUS_FAIL;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+
+/** int VL53L0_I2CRead(VL53L0_Dev_t dev, void *buff, uint8_t len);
+ * @brief Read data buffer from VL53L0 device via i2c
+ * @param dev The device to read from
+ * @param buff The data buffer to fill
+ * @param len The length of the transaction in byte
+ * @return transaction status
+ */
+int VL53L0_I2CRead(VL53L0_DEV dev, uint8_t *buff, uint8_t len)
+{
+
+ int err = 0;
+
+ if (dev->bus_type == CCI_BUS) {
+#ifdef CAMERA_CCI
+ uint16_t index;
+ struct cci_data *cci_client_obj =
+ (struct cci_data *)dev->client_object;
+ struct msm_camera_i2c_client *client = cci_client_obj->client;
+
+ index = buff[0];
+ /* pr_err("%s: index: %d\n", __func__, index); */
+ err = client->i2c_func_tbl->i2c_read_seq(client,
+ index, buff, len);
+ if (err < 0) {
+ pr_err("%s:%d failed status=%d\n",
+ __func__, __LINE__, err);
+ return err;
+ }
+#endif
+ } else {
+#ifndef CAMERA_CCI
+ struct i2c_msg msg[1];
+ struct i2c_data *i2c_client_obj =
+ (struct i2c_data *)dev->client_object;
+ struct i2c_client *client =
+ (struct i2c_client *) i2c_client_obj->client;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = I2C_M_RD|client->flags;
+ msg[0].buf = buff;
+ msg[0].len = len;
+
+ err = i2c_transfer(client->adapter, &msg[0], 1);
+ /* return the actual mesage transfer */
+ if (err != 1) {
+ pr_err("%s: Read i2c_transfer err:%d, addr:0x%x\n",
+ __func__, err, client->addr);
+ return STATUS_FAIL;
+ }
+#endif
+ }
+
+ return 0;
+}
diff --git a/drivers/input/misc/vl53L0/stmvl53l0-cci.h b/drivers/input/misc/vl53L0/stmvl53l0-cci.h
new file mode 100644
index 000000000000..b99ffe783e59
--- /dev/null
+++ b/drivers/input/misc/vl53L0/stmvl53l0-cci.h
@@ -0,0 +1,62 @@
+/*
+ * stmvl53l0-cci.h - Linux kernel modules for STM VL53L0 FlightSense TOF sensor
+ *
+ * Copyright (C) 2016 STMicroelectronics Imaging Division
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/*
+ * Defines
+ */
+#ifndef STMVL53L0_CCI_H
+#define STMVL53L0_CCI_H
+#include <linux/types.h>
+
+#ifdef CAMERA_CCI
+#include <soc/qcom/camera2.h>
+#include "msm_camera_i2c.h"
+#include "msm_camera_dt_util.h"
+#include "msm_camera_io_util.h"
+#include "msm_cci.h"
+
+#define MSM_TOF_MAX_VREGS (10)
+
+struct msm_tof_vreg {
+ struct camera_vreg_t *cam_vreg;
+ void *data[MSM_TOF_MAX_VREGS];
+ int num_vreg;
+};
+
+struct cci_data {
+ struct msm_camera_i2c_client g_client;
+ struct msm_camera_i2c_client *client;
+ struct platform_device *pdev;
+ enum msm_camera_device_type_t device_type;
+ enum cci_i2c_master_t cci_master;
+ struct msm_tof_vreg vreg_cfg;
+ struct msm_sd_subdev msm_sd;
+ struct v4l2_subdev sdev;
+ struct v4l2_subdev_ops *subdev_ops;
+ char subdev_initialized;
+ uint32_t subdev_id;
+ uint8_t power_up;
+ struct msm_camera_gpio_conf *gconf;
+ struct msm_pinctrl_info pinctrl_info;
+ uint8_t cam_pinctrl_status;
+};
+
+int stmvl53l0_init_cci(void);
+void stmvl53l0_exit_cci(void *);
+int stmvl53l0_power_down_cci(void *);
+int stmvl53l0_power_up_cci(void *, unsigned int *);
+int stmvl53l0_cci_power_status(void *);
+#endif /* CAMERA_CCI */
+#endif /* STMVL53L0_CCI_H */
diff --git a/drivers/input/misc/vl53L0/stmvl53l0-i2c.h b/drivers/input/misc/vl53L0/stmvl53l0-i2c.h
new file mode 100644
index 000000000000..51a02c60802b
--- /dev/null
+++ b/drivers/input/misc/vl53L0/stmvl53l0-i2c.h
@@ -0,0 +1,35 @@
+/*
+ * stmvl53l0-i2c.h - Linux kernel modules for STM VL53L0 FlightSense TOF sensor
+ *
+ * Copyright (C) 2016 STMicroelectronics Imaging Division
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/*
+ * Defines
+ */
+#ifndef STMVL53L0_I2C_H
+#define STMVL53L0_I2C_H
+#include <linux/types.h>
+
+#ifndef CAMERA_CCI
+struct i2c_data {
+ struct i2c_client *client;
+ struct regulator *vana;
+ uint8_t power_up;
+};
+int stmvl53l0_init_i2c(void);
+void stmvl53l0_exit_i2c(void *);
+int stmvl53l0_power_up_i2c(void *, unsigned int *);
+int stmvl53l0_power_down_i2c(void *);
+
+#endif /* NOT CAMERA_CCI */
+#endif /* STMVL53L0_I2C_H */
diff --git a/drivers/input/misc/vl53L0/stmvl53l0.h b/drivers/input/misc/vl53L0/stmvl53l0.h
new file mode 100644
index 000000000000..b6ef547e86e7
--- /dev/null
+++ b/drivers/input/misc/vl53L0/stmvl53l0.h
@@ -0,0 +1,219 @@
+/*
+ * stmvl53l0.h - Linux kernel modules for STM VL53L0 FlightSense TOF sensor
+ *
+ * Copyright (C) 2016 STMicroelectronics Imaging Division
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/*
+ * Defines
+ */
+#ifndef STMVL53L0_H
+#define STMVL53L0_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/miscdevice.h>
+#include <linux/wait.h>
+
+
+#define STMVL53L0_DRV_NAME "stmvl53l0"
+#define STMVL53L0_SLAVE_ADDR (0x52>>1)
+
+#define DRIVER_VERSION "1.0.5"
+#define I2C_M_WR 0x00
+/* #define INT_POLLING_DELAY 20 */
+
+/* if don't want to have output from vl53l0_dbgmsg, comment out #DEBUG macro */
+#define DEBUG
+#define vl53l0_dbgmsg(str, args...) \
+ pr_err("%s: " str, __func__, ##args)
+#define vl53l0_errmsg(str, args...) \
+ pr_err("%s: " str, __func__, ##args)
+
+#define VL53L0_VDD_MIN 2600000
+#define VL53L0_VDD_MAX 3000000
+
+typedef enum {
+ NORMAL_MODE = 0,
+ OFFSETCALIB_MODE = 1,
+ XTALKCALIB_MODE = 2,
+} init_mode_e;
+
+typedef enum {
+ OFFSET_PAR = 0,
+ XTALKRATE_PAR = 1,
+ XTALKENABLE_PAR = 2,
+ GPIOFUNC_PAR = 3,
+ LOWTHRESH_PAR = 4,
+ HIGHTHRESH_PAR = 5,
+ DEVICEMODE_PAR = 6,
+ INTERMEASUREMENT_PAR = 7,
+ REFERENCESPADS_PAR = 8,
+ REFCALIBRATION_PAR = 9,
+} parameter_name_e;
+
+enum {
+ CCI_BUS = 0,
+ I2C_BUS = 1,
+};
+
+/*
+ * IOCTL register data structs
+ */
+struct stmvl53l0_register {
+ uint32_t is_read; /*1: read 0: write*/
+ uint32_t reg_index;
+ uint32_t reg_bytes;
+ uint32_t reg_data;
+ int32_t status;
+};
+
+/*
+ * IOCTL parameter structs
+ */
+struct stmvl53l0_parameter {
+ uint32_t is_read; /*1: Get 0: Set*/
+ parameter_name_e name;
+ int32_t value;
+ int32_t value2;
+ int32_t status;
+};
+
+/*
+ * IOCTL Custom Use Case
+ */
+struct stmvl53l0_custom_use_case {
+ FixPoint1616_t signalRateLimit;
+ FixPoint1616_t sigmaLimit;
+ uint32_t preRangePulsePeriod;
+ uint32_t finalRangePulsePeriod;
+ uint32_t timingBudget;
+};
+
+
+/*
+ * driver data structs
+ */
+struct stmvl53l0_data {
+
+ /* !<embed ST VL53L0 Dev data as "dev_data" */
+ VL53L0_DevData_t Data;
+ /*!< i2c device address user specific field*/
+ uint8_t I2cDevAddr;
+ /*!< Type of comms : VL53L0_COMMS_I2C or VL53L0_COMMS_SPI */
+ uint8_t comms_type;
+ /*!< Comms speed [kHz] : typically 400kHz for I2C */
+ uint16_t comms_speed_khz;
+ /* CCI_BUS; I2C_BUS */
+ uint8_t bus_type;
+
+ void *client_object; /* cci or i2c client */
+
+ struct mutex update_lock;
+ struct delayed_work dwork; /* for PS work handler */
+ struct input_dev *input_dev_ps;
+ struct kobject *range_kobj;
+
+ const char *dev_name;
+ /* function pointer */
+
+ /* misc device */
+ struct miscdevice miscdev;
+
+ int irq;
+ int irq_gpio;
+ unsigned int reset;
+
+ /* control flag from HAL */
+ unsigned int enable_ps_sensor;
+
+ /* PS parameters */
+ unsigned int ps_data; /* to store PS data */
+
+ /* Calibration parameters */
+ unsigned int offsetCalDistance;
+ unsigned int xtalkCalDistance;
+
+ /* Calibration values */
+ uint32_t refSpadCount;
+ uint8_t isApertureSpads;
+ uint8_t VhvSettings;
+ uint8_t PhaseCal;
+ int32_t OffsetMicroMeter;
+ FixPoint1616_t XTalkCompensationRateMegaCps;
+ uint32_t setCalibratedValue;
+
+ /* Custom values set by app */
+ FixPoint1616_t signalRateLimit;
+ FixPoint1616_t sigmaLimit;
+ uint32_t preRangePulsePeriod;
+ uint32_t finalRangePulsePeriod;
+
+
+ /* Range Data */
+ VL53L0_RangingMeasurementData_t rangeData;
+
+ /* Device parameters */
+ VL53L0_DeviceModes deviceMode;
+ uint32_t interMeasurems;
+ VL53L0_GpioFunctionality gpio_function;
+ VL53L0_InterruptPolarity gpio_polarity;
+ FixPoint1616_t low_threshold;
+ FixPoint1616_t high_threshold;
+
+ /* delay time in miniseconds*/
+ uint8_t delay_ms;
+
+ /* Timing Budget */
+ uint32_t timingBudget;
+ /* Use this threshold to force restart ranging */
+ uint32_t noInterruptCount;
+ /* Use this flag to denote use case*/
+ uint8_t useCase;
+ /* Use this flag to indicate an update of use case */
+ uint8_t updateUseCase;
+ /* Polling thread */
+ struct task_struct *poll_thread;
+ /* Wait Queue on which the poll thread blocks */
+ wait_queue_head_t poll_thread_wq;
+
+ /* Recent interrupt status */
+ uint32_t interruptStatus;
+
+ struct mutex work_mutex;
+
+ struct timer_list timer;
+ uint32_t flushCount;
+
+ /* Debug */
+ unsigned int enableDebug;
+ uint8_t interrupt_received;
+};
+
+/*
+ * function pointer structs
+ */
+struct stmvl53l0_module_fn_t {
+ int (*init)(void);
+ void (*deinit)(void *);
+ int (*power_up)(void *, unsigned int *);
+ int (*power_down)(void *);
+ int (*query_power_status)(void *);
+};
+
+
+
+int stmvl53l0_setup(struct stmvl53l0_data *data);
+void stmvl53l0_cleanup(struct stmvl53l0_data *data);
+
+#endif /* STMVL53L0_H */
diff --git a/drivers/input/misc/vl53L0/stmvl53l0_module-cci.c b/drivers/input/misc/vl53L0/stmvl53l0_module-cci.c
new file mode 100644
index 000000000000..8520a74c9961
--- /dev/null
+++ b/drivers/input/misc/vl53L0/stmvl53l0_module-cci.c
@@ -0,0 +1,547 @@
+/*
+ * stmvl53l0_module-cci.c - Linux kernel modules for STM VL53L0 FlightSense TOF
+ * sensor
+ *
+ * Copyright (C) 2016 STMicroelectronics Imaging Division.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/miscdevice.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/platform_device.h>
+/*
+ * power specific includes
+ */
+#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/clk.h>
+#include <linux/of_gpio.h>
+/*
+ * API includes
+ */
+#include "vl53l0_api.h"
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+#include "stmvl53l0-cci.h"
+#include "stmvl53l0-i2c.h"
+#include "stmvl53l0.h"
+
+#ifdef CAMERA_CCI
+/*
+ * Global data
+ */
+static struct v4l2_file_operations msm_tof_v4l2_subdev_fops;
+static struct msm_camera_i2c_fn_t msm_sensor_cci_func_tbl = {
+ .i2c_read = msm_camera_cci_i2c_read,
+ .i2c_read_seq = msm_camera_cci_i2c_read_seq,
+ .i2c_write = msm_camera_cci_i2c_write,
+ .i2c_write_seq = msm_camera_cci_i2c_write_seq,
+ .i2c_write_table = msm_camera_cci_i2c_write_table,
+ .i2c_write_seq_table = msm_camera_cci_i2c_write_seq_table,
+ .i2c_write_table_w_microdelay =
+ msm_camera_cci_i2c_write_table_w_microdelay,
+ .i2c_util = msm_sensor_cci_i2c_util,
+ .i2c_poll = msm_camera_cci_i2c_poll,
+};
+
+static int stmvl53l0_get_dt_data(struct device *dev, struct cci_data *data);
+
+/*
+ * QCOM specific functions
+ */
+static int stmvl53l0_get_dt_data(struct device *dev, struct cci_data *data)
+{
+ int rc = 0;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ if (dev->of_node) {
+ struct device_node *of_node = dev->of_node;
+ struct msm_tof_vreg *vreg_cfg;
+
+ if (!of_node) {
+ vl53l0_errmsg("failed %d\n", __LINE__);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(of_node,
+ "cell-index", &data->pdev->id);
+ if (rc < 0) {
+ vl53l0_errmsg("failed %d\n", __LINE__);
+ return rc;
+ }
+ vl53l0_dbgmsg("cell-index: %d\n", data->pdev->id);
+ rc = of_property_read_u32(of_node, "qcom,cci-master",
+ &data->cci_master);
+ if (rc < 0) {
+ vl53l0_errmsg("failed %d\n", __LINE__);
+ /* Set default master 0 */
+ data->cci_master = MASTER_0;
+ rc = 0;
+ }
+ vl53l0_dbgmsg("cci_master: %d\n", data->cci_master);
+ if (of_find_property(of_node, "qcom,cam-vreg-name", NULL)) {
+ vreg_cfg = &data->vreg_cfg;
+ rc = msm_camera_get_dt_vreg_data(of_node,
+ &vreg_cfg->cam_vreg,
+ &vreg_cfg->num_vreg);
+ if (rc < 0) {
+ vl53l0_errmsg("failed %d\n", __LINE__);
+ return rc;
+ }
+ vl53l0_dbgmsg("vreg-name: %s min_volt: %d max_volt: %d",
+ vreg_cfg->cam_vreg->reg_name,
+ vreg_cfg->cam_vreg->min_voltage,
+ vreg_cfg->cam_vreg->max_voltage);
+ }
+
+ rc = msm_sensor_driver_get_gpio_data(&(data->gconf), of_node);
+ if ((rc < 0) || (data->gconf == NULL)) {
+ vl53l0_errmsg
+ ("No Laser Sensor GPIOs to be configured!\n");
+ }
+
+ }
+ vl53l0_dbgmsg("End rc =%d\n", rc);
+
+ return rc;
+}
+
+static int32_t stmvl53l0_vreg_control(struct cci_data *data, int config)
+{
+ int rc = 0, i, cnt;
+ struct msm_tof_vreg *vreg_cfg;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ vreg_cfg = &data->vreg_cfg;
+ cnt = vreg_cfg->num_vreg;
+ vl53l0_dbgmsg("num_vreg: %d\n", cnt);
+ if (!cnt) {
+ vl53l0_errmsg("failed %d\n", __LINE__);
+ return 0;
+ }
+
+ if (cnt >= MSM_TOF_MAX_VREGS) {
+ vl53l0_errmsg("failed %d cnt %d\n", __LINE__, cnt);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ rc = msm_camera_config_single_vreg(&(data->pdev->dev),
+ &vreg_cfg->cam_vreg[i],
+ (struct regulator **)
+ &vreg_cfg->data[i], config);
+ }
+
+ vl53l0_dbgmsg("EXIT rc =%d\n", rc);
+ return rc;
+}
+
+static int msm_tof_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ int rc = 0;
+/*
+ * struct msm_tof_ctrl_t *tof_ctrl = v4l2_get_subdevdata(sd);
+ * if (!tof_ctrl) {
+ * pr_err("failed\n");
+ * return -EINVAL;
+ * }
+ * if (tof_ctrl->tof_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ * rc = tof_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+ * &tof_ctrl->i2c_client, MSM_CCI_RELEASE);
+ * if (rc < 0)
+ * pr_err("cci_init failed\n");
+ * }
+ * tof_ctrl->i2c_state = TOF_I2C_RELEASE;
+ */
+ return rc;
+}
+
+static const struct v4l2_subdev_internal_ops msm_tof_internal_ops = {
+ .close = msm_tof_close,
+};
+
+static long msm_tof_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct cci_data *cci_object = NULL;
+ int32_t rc = 0;
+
+ cci_object = v4l2_get_subdevdata(sd);
+ if (cmd == MSM_SD_SHUTDOWN)
+ cci_object->power_up = 0;
+
+ vl53l0_dbgmsg("cmd = %d power_up = %d", cmd, cci_object->power_up);
+ return rc;
+}
+
+static int32_t msm_tof_power(struct v4l2_subdev *sd, int on)
+{
+ vl53l0_dbgmsg("TOF power called\n");
+ return 0;
+}
+
+static struct v4l2_subdev_core_ops msm_tof_subdev_core_ops = {
+ .ioctl = msm_tof_subdev_ioctl,
+ .s_power = msm_tof_power,
+};
+
+static struct v4l2_subdev_ops msm_tof_subdev_ops = {
+ .core = &msm_tof_subdev_core_ops,
+};
+
+static int stmvl53l0_cci_init(struct cci_data *data)
+{
+ int rc = 0;
+ struct msm_camera_cci_client *cci_client = data->client->cci_client;
+
+ if (data->subdev_initialized == FALSE) {
+ data->client->i2c_func_tbl = &msm_sensor_cci_func_tbl;
+ data->client->cci_client =
+ kzalloc(sizeof(struct msm_camera_cci_client), GFP_KERNEL);
+ if (!data->client->cci_client) {
+ vl53l0_errmsg("%d, failed no memory\n", __LINE__);
+ return -ENOMEM;
+ }
+ cci_client = data->client->cci_client;
+ cci_client->cci_subdev = msm_cci_get_subdev();
+ if (cci_client->cci_subdev == NULL) {
+ vl53l0_errmsg("CCI subdev is not initialized!!\n");
+ return -ENODEV;
+ }
+ cci_client->cci_i2c_master = data->cci_master;
+ v4l2_subdev_init(&data->msm_sd.sd, data->subdev_ops);
+ v4l2_set_subdevdata(&data->msm_sd.sd, data);
+ data->msm_sd.sd.internal_ops = &msm_tof_internal_ops;
+ data->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(data->msm_sd.sd.name,
+ ARRAY_SIZE(data->msm_sd.sd.name), "msm_tof");
+ media_entity_init(&data->msm_sd.sd.entity, 0, NULL, 0);
+ data->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ data->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_TOF;
+ data->msm_sd.close_seq =
+ MSM_SD_CLOSE_2ND_CATEGORY | 0x2;
+ msm_sd_register(&data->msm_sd);
+ msm_tof_v4l2_subdev_fops = v4l2_subdev_fops;
+ data->msm_sd.sd.devnode->fops =
+ &msm_tof_v4l2_subdev_fops;
+ data->subdev_initialized = TRUE;
+ }
+
+ cci_client->sid = 0x29;
+ cci_client->retries = 3;
+ cci_client->id_map = 0;
+ cci_client->cci_i2c_master = data->cci_master;
+ cci_client->i2c_freq_mode = I2C_FAST_MODE;
+ rc = data->client->i2c_func_tbl->i2c_util(data->client, MSM_CCI_INIT);
+ if (rc < 0) {
+ vl53l0_errmsg("%d: CCI Init failed\n", __LINE__);
+ return rc;
+ }
+ vl53l0_dbgmsg("CCI Init Succeeded\n");
+
+ data->client->addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+
+ return 0;
+}
+
+static int32_t stmvl53l0_platform_probe(struct platform_device *pdev)
+{
+ struct stmvl53l0_data *vl53l0_data = NULL;
+ struct cci_data *cci_object = NULL;
+ int32_t rc = 0;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ if (!pdev->dev.of_node) {
+ vl53l0_errmsg("of_node NULL\n");
+ return -EINVAL;
+ }
+
+ vl53l0_data = kzalloc(sizeof(struct stmvl53l0_data), GFP_KERNEL);
+ if (!vl53l0_data) {
+ rc = -ENOMEM;
+ return rc;
+ }
+ if (vl53l0_data) {
+ vl53l0_data->client_object =
+ kzalloc(sizeof(struct cci_data), GFP_KERNEL);
+ if (!vl53l0_data->client_object) {
+ rc = -ENOMEM;
+ kfree(vl53l0_data);
+ return rc;
+ }
+ cci_object = (struct cci_data *)vl53l0_data->client_object;
+ }
+ cci_object->client =
+ (struct msm_camera_i2c_client *)&cci_object->g_client;
+
+ /* setup bus type */
+ vl53l0_data->bus_type = CCI_BUS;
+
+ /* Set platform device handle */
+ cci_object->subdev_ops = &msm_tof_subdev_ops;
+ cci_object->pdev = pdev;
+ rc = stmvl53l0_get_dt_data(&pdev->dev, cci_object);
+ if (rc < 0) {
+ vl53l0_errmsg("%d, failed rc %d\n", __LINE__, rc);
+ kfree(vl53l0_data->client_object);
+ kfree(vl53l0_data);
+ return rc;
+ }
+ vl53l0_data->irq_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+ "stm,irq-gpio", 0, NULL);
+
+ if (!gpio_is_valid(vl53l0_data->irq_gpio)) {
+ vl53l0_errmsg("%d failed get irq gpio", __LINE__);
+ kfree(vl53l0_data->client_object);
+ kfree(vl53l0_data);
+ return -EINVAL;
+ }
+
+ cci_object->subdev_id = pdev->id;
+
+ /* Set device type as platform device */
+ cci_object->device_type = MSM_CAMERA_PLATFORM_DEVICE;
+ cci_object->subdev_initialized = FALSE;
+
+ /* setup device name */
+ vl53l0_data->dev_name = dev_name(&pdev->dev);
+
+ /* setup device data */
+ dev_set_drvdata(&pdev->dev, vl53l0_data);
+
+ /* setup other stuff */
+ rc = stmvl53l0_setup(vl53l0_data);
+
+ /* init default value */
+ cci_object->power_up = 0;
+
+ vl53l0_dbgmsg("End\n");
+
+ return rc;
+
+}
+
+static int32_t stmvl53l0_platform_remove(struct platform_device *pdev)
+{
+ struct stmvl53l0_data *vl53l0_data = platform_get_drvdata(pdev);
+
+ stmvl53l0_cleanup(vl53l0_data);
+ platform_set_drvdata(pdev, NULL);
+
+ kfree(vl53l0_data->client_object);
+ kfree(vl53l0_data);
+
+ return 0;
+}
+
+static const struct of_device_id st_stmvl53l0_dt_match[] = {
+ {.compatible = "st,stmvl53l0",},
+ {},
+};
+
+static struct platform_driver stmvl53l0_platform_driver = {
+ .probe = stmvl53l0_platform_probe,
+ .remove = stmvl53l0_platform_remove,
+ .driver = {
+ .name = STMVL53L0_DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = st_stmvl53l0_dt_match,
+ },
+};
+
+int stmvl53l0_power_up_cci(void *cci_object, unsigned int *preset_flag)
+{
+ int ret = 0;
+ struct cci_data *data = (struct cci_data *)cci_object;
+ struct gpio *gpio_tbl = NULL;
+ uint8_t gpio_tbl_size = 0;
+ int i = 0;
+
+ vl53l0_dbgmsg("Enter");
+
+ /* need to init cci first */
+ if (!data) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ ret = stmvl53l0_cci_init(data);
+ if (ret) {
+ vl53l0_errmsg("stmvl53l0_cci_init failed %d\n", __LINE__);
+ return ret;
+ }
+
+ /* Check if GPIO needs to be enabled for chip select */
+ vl53l0_dbgmsg("Get gpio table!size: %d\n",
+ data->gconf->cam_gpio_req_tbl_size);
+ gpio_tbl = data->gconf->cam_gpio_req_tbl;
+ gpio_tbl_size = data->gconf->cam_gpio_req_tbl_size;
+ if (gpio_tbl_size > 0) {
+ ret = msm_camera_pinctrl_init(&(data->pinctrl_info),
+ &(data->pdev->dev));
+ if (ret < 0) {
+ vl53l0_errmsg("Initialization of pinctrl failed\n");
+ data->cam_pinctrl_status = 0;
+ } else {
+ data->cam_pinctrl_status = 1;
+ }
+
+ for (i = 0; i < gpio_tbl_size; i++) {
+ ret = gpio_request_one(gpio_tbl[i].gpio,
+ gpio_tbl[i].flags,
+ gpio_tbl[i].label);
+ if (ret < 0) {
+ vl53l0_errmsg
+ ("Request for GPIO %d failed! Err: %d\n",
+ gpio_tbl[i].gpio, ret);
+ } else {
+ if (data->cam_pinctrl_status) {
+ ret =
+ pinctrl_select_state(
+ data->pinctrl_info.pinctrl,
+ data->pinctrl_info.gpio_state_active);
+ if (ret < 0) {
+ vl53l0_errmsg(
+ "%s: Cannot set pin to active state!\n",
+ __func__);
+ }
+ }
+ vl53l0_dbgmsg("Set pin %d value to 1!\n",
+ gpio_tbl[i].gpio);
+ gpio_set_value_cansleep(gpio_tbl[i].gpio, 1);
+ }
+ }
+ }
+
+ /* actual power up */
+ if (data->device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ ret = stmvl53l0_vreg_control(data, 1);
+ if (ret < 0) {
+ vl53l0_errmsg("stmvl53l0_vreg_control failed %d\n",
+ __LINE__);
+ return ret;
+ }
+ }
+ data->power_up = 1;
+ usleep_range(3000, 3500);
+ *preset_flag = 1;
+ vl53l0_dbgmsg("End\n");
+
+ return ret;
+}
+
+int stmvl53l0_power_down_cci(void *cci_object)
+{
+ int ret = 0;
+ struct cci_data *data = (struct cci_data *)cci_object;
+ int i = 0;
+ struct gpio *gpio_tbl = NULL;
+ uint8_t gpio_tbl_size = 0;
+
+ vl53l0_dbgmsg("Enter\n");
+ if (data->power_up) {
+ /* need to release cci first */
+ ret = data->client->i2c_func_tbl->i2c_util(data->client,
+ MSM_CCI_RELEASE);
+ if (ret < 0)
+ vl53l0_errmsg("CCI Release failed rc %d\n", ret);
+
+ /* actual power down */
+ if (data->device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ ret = stmvl53l0_vreg_control(data, 0);
+ if (ret < 0) {
+ vl53l0_errmsg
+ ("stmvl53l0_vreg_control failed %d\n",
+ __LINE__);
+ return ret;
+ }
+ }
+
+ /* reset GPIO pins */
+ gpio_tbl = data->gconf->cam_gpio_req_tbl;
+ gpio_tbl_size = data->gconf->cam_gpio_req_tbl_size;
+ if (gpio_tbl_size > 0) {
+ for (i = 0; i < gpio_tbl_size; i++)
+ gpio_set_value_cansleep(gpio_tbl[i].gpio, 0);
+ if (data->cam_pinctrl_status) {
+ ret =
+ pinctrl_select_state(data->pinctrl_info.
+ pinctrl,
+ data->pinctrl_info.
+ gpio_state_suspend);
+ if (ret < 0) {
+ vl53l0_errmsg(
+ "Error setting gpio pin to supsend state!\n");
+ }
+
+ devm_pinctrl_put(data->pinctrl_info.pinctrl);
+ data->cam_pinctrl_status = 0;
+ gpio_free_array(gpio_tbl, gpio_tbl_size);
+ }
+ }
+ }
+ data->power_up = 0;
+ vl53l0_dbgmsg("End\n");
+ return ret;
+}
+
+int stmvl53l0_cci_power_status(void *cci_object)
+{
+ struct cci_data *data = (struct cci_data *)cci_object;
+
+ return data->power_up;
+}
+
+int stmvl53l0_init_cci(void)
+{
+ int ret = 0;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ /* register as a platform device */
+ ret = platform_driver_register(&stmvl53l0_platform_driver);
+ if (ret)
+ vl53l0_errmsg("%d, error ret:%d\n", __LINE__, ret);
+
+ vl53l0_dbgmsg("End\n");
+
+ return ret;
+}
+
+void stmvl53l0_exit_cci(void *cci_object)
+{
+ struct cci_data *data = (struct cci_data *)cci_object;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ if (data && data->client->cci_client)
+ kfree(data->client->cci_client);
+
+ vl53l0_dbgmsg("End\n");
+}
+#endif /* end of CAMERA_CCI */
diff --git a/drivers/input/misc/vl53L0/stmvl53l0_module-i2c.c b/drivers/input/misc/vl53L0/stmvl53l0_module-i2c.c
new file mode 100644
index 000000000000..0bff754de15b
--- /dev/null
+++ b/drivers/input/misc/vl53L0/stmvl53l0_module-i2c.c
@@ -0,0 +1,266 @@
+/*
+ * stmvl53l0_module-i2c.c - Linux kernel modules for STM VL53L0 FlightSense TOF
+ * sensor
+ *
+ * Copyright (C) 2016 STMicroelectronics Imaging Division.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/miscdevice.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/platform_device.h>
+/*
+ * power specific includes
+ */
+#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/clk.h>
+#include <linux/of_gpio.h>
+/*
+ * API includes
+ */
+#include "vl53l0_api.h"
+#include "vl53l0_def.h"
+#include "vl53l0_platform.h"
+#include "stmvl53l0-i2c.h"
+#include "stmvl53l0-cci.h"
+#include "stmvl53l0.h"
+#ifndef CAMERA_CCI
+
+/*
+ * Global data
+ */
+static int stmvl53l0_parse_vdd(struct device *dev, struct i2c_data *data);
+
+/*
+ * QCOM specific functions
+ */
+static int stmvl53l0_parse_vdd(struct device *dev, struct i2c_data *data)
+{
+ int ret = 0;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ if (dev->of_node) {
+ data->vana = regulator_get(dev, "vdd");
+ if (IS_ERR(data->vana)) {
+ vl53l0_errmsg("vdd supply is not provided\n");
+ ret = -1;
+ }
+ }
+ vl53l0_dbgmsg("End\n");
+
+ return ret;
+}
+
+static int stmvl53l0_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc = 0;
+ struct stmvl53l0_data *vl53l0_data = NULL;
+ struct i2c_data *i2c_object = NULL;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
+ rc = -EIO;
+ return rc;
+ }
+
+ vl53l0_data = kzalloc(sizeof(struct stmvl53l0_data), GFP_KERNEL);
+ if (!vl53l0_data) {
+ rc = -ENOMEM;
+ return rc;
+ }
+ if (vl53l0_data) {
+ vl53l0_data->client_object =
+ kzalloc(sizeof(struct i2c_data), GFP_KERNEL);
+ i2c_object = (struct i2c_data *)vl53l0_data->client_object;
+ }
+ i2c_object->client = client;
+
+ /* setup bus type */
+ vl53l0_data->bus_type = I2C_BUS;
+
+ /* setup regulator */
+ stmvl53l0_parse_vdd(&i2c_object->client->dev, i2c_object);
+
+ /* setup device name */
+ vl53l0_data->dev_name = dev_name(&client->dev);
+
+ /* setup device data */
+ dev_set_drvdata(&client->dev, vl53l0_data);
+
+ /* setup client data */
+ i2c_set_clientdata(client, vl53l0_data);
+
+ /* setup other stuff */
+ rc = stmvl53l0_setup(vl53l0_data);
+
+ /* init default value */
+ i2c_object->power_up = 0;
+
+ vl53l0_dbgmsg("End\n");
+ return rc;
+}
+
+static int stmvl53l0_remove(struct i2c_client *client)
+{
+ struct stmvl53l0_data *data = i2c_get_clientdata(client);
+
+ vl53l0_dbgmsg("Enter\n");
+
+ /* Power down the device */
+ stmvl53l0_power_down_i2c(data->client_object);
+ stmvl53l0_cleanup(data);
+ kfree(data->client_object);
+ kfree(data);
+ vl53l0_dbgmsg("End\n");
+ return 0;
+}
+
+static const struct i2c_device_id stmvl53l0_id[] = {
+ {STMVL53L0_DRV_NAME, 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, stmvl53l0_id);
+
+static const struct of_device_id st_stmvl53l0_dt_match[] = {
+ {.compatible = "st,stmvl53l0",},
+ {},
+};
+
+static struct i2c_driver stmvl53l0_driver = {
+ .driver = {
+ .name = STMVL53L0_DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = st_stmvl53l0_dt_match,
+ },
+ .probe = stmvl53l0_probe,
+ .remove = stmvl53l0_remove,
+ .id_table = stmvl53l0_id,
+
+};
+
+int stmvl53l0_power_up_i2c(void *i2c_object, unsigned int *preset_flag)
+{
+ int ret = 0;
+#ifndef STM_TEST
+ struct i2c_data *data = (struct i2c_data *)i2c_object;
+#endif
+
+ vl53l0_dbgmsg("Enter\n");
+
+ /* actual power on */
+#ifndef STM_TEST
+ ret = regulator_set_voltage(data->vana, VL53L0_VDD_MIN, VL53L0_VDD_MAX);
+ if (ret < 0) {
+ vl53l0_errmsg("set_vol(%p) fail %d\n", data->vana, ret);
+ return ret;
+ }
+ ret = regulator_enable(data->vana);
+
+ usleep_range(2950, 3000);
+ if (ret < 0) {
+ vl53l0_errmsg("reg enable(%p) failed.rc=%d\n", data->vana, ret);
+ return ret;
+ }
+ data->power_up = 1;
+ *preset_flag = 1;
+#endif
+
+ vl53l0_dbgmsg("End\n");
+ return ret;
+}
+
+int stmvl53l0_power_down_i2c(void *i2c_object)
+{
+ int ret = 0;
+#ifndef STM_TEST
+ struct i2c_data *data = (struct i2c_data *)i2c_object;
+#endif
+
+ vl53l0_dbgmsg("Enter\n");
+#ifndef STM_TEST
+ usleep_range(2950, 3000);
+ ret = regulator_disable(data->vana);
+ if (ret < 0)
+ vl53l0_errmsg("reg disable(%p) failed.rc=%d\n",
+ data->vana, ret);
+
+ data->power_up = 0;
+#endif
+
+ vl53l0_dbgmsg("End\n");
+ return ret;
+}
+
+int stmvl53l0_init_i2c(void)
+{
+ int ret = 0;
+
+#ifdef STM_TEST
+ struct i2c_client *client = NULL;
+ struct i2c_adapter *adapter;
+ struct i2c_board_info info = {
+ .type = "stmvl53l0",
+ .addr = STMVL53L0_SLAVE_ADDR,
+ };
+#endif
+
+ vl53l0_dbgmsg("Enter\n");
+
+ /* register as a i2c client device */
+ ret = i2c_add_driver(&stmvl53l0_driver);
+ if (ret)
+ vl53l0_errmsg("%d erro ret:%d\n", __LINE__, ret);
+
+#ifdef STM_TEST
+ if (!ret) {
+ adapter = i2c_get_adapter(4);
+ if (!adapter)
+ ret = -EINVAL;
+ else
+ client = i2c_new_device(adapter, &info);
+ if (!client)
+ ret = -EINVAL;
+ }
+#endif
+
+ vl53l0_dbgmsg("End with rc:%d\n", ret);
+
+ return ret;
+}
+
+void stmvl53l0_exit_i2c(void *i2c_object)
+{
+ vl53l0_dbgmsg("Enter\n");
+ i2c_del_driver(&stmvl53l0_driver);
+
+ vl53l0_dbgmsg("End\n");
+}
+
+#endif /* end of NOT CAMERA_CCI */
diff --git a/drivers/input/misc/vl53L0/stmvl53l0_module.c b/drivers/input/misc/vl53L0/stmvl53l0_module.c
new file mode 100644
index 000000000000..27672d97448a
--- /dev/null
+++ b/drivers/input/misc/vl53L0/stmvl53l0_module.c
@@ -0,0 +1,2885 @@
+/*
+ * stmvl53l0_module.c - Linux kernel modules for STM VL53L0 FlightSense TOF
+ * sensor
+ *
+ * Copyright (C) 2016 STMicroelectronics Imaging Division.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/miscdevice.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/platform_device.h>
+#include <linux/kobject.h>
+#include <linux/kthread.h>
+/*
+ * API includes
+ */
+#include "vl53l0_api.h"
+#include "vl53l010_api.h"
+
+#define USE_INT
+/* #define DEBUG_TIME_LOG */
+#ifdef DEBUG_TIME_LOG
+struct timeval start_tv, stop_tv;
+#endif
+
+/*
+ * Global data
+ */
+
+#ifdef CAMERA_CCI
+static struct stmvl53l0_module_fn_t stmvl53l0_module_func_tbl = {
+ .init = stmvl53l0_init_cci,
+ .deinit = stmvl53l0_exit_cci,
+ .power_up = stmvl53l0_power_up_cci,
+ .power_down = stmvl53l0_power_down_cci,
+ .query_power_status = stmvl53l0_cci_power_status,
+};
+#else
+static struct stmvl53l0_module_fn_t stmvl53l0_module_func_tbl = {
+ .init = stmvl53l0_init_i2c,
+ .deinit = stmvl53l0_exit_i2c,
+ .power_up = stmvl53l0_power_up_i2c,
+ .power_down = stmvl53l0_power_down_i2c,
+ .stmv53l0_cci_power_status = NULL;
+};
+#endif
+struct stmvl53l0_module_fn_t *pmodule_func_tbl;
+
+struct stmvl53l0_api_fn_t {
+ int8_t (*GetVersion)(VL53L0_Version_t *pVersion);
+ int8_t (*GetPalSpecVersion)(VL53L0_Version_t *pPalSpecVersion);
+
+ int8_t (*GetProductRevision)(VL53L0_DEV Dev,
+ uint8_t *pProductRevisionMajor,
+ uint8_t *pProductRevisionMinor);
+ int8_t (*GetDeviceInfo)(VL53L0_DEV Dev,
+ VL53L0_DeviceInfo_t *pVL53L0_DeviceInfo);
+ int8_t (*GetDeviceErrorStatus)(VL53L0_DEV Dev,
+ VL53L0_DeviceError *pDeviceErrorStatus);
+ int8_t (*GetRangeStatusString)(uint8_t RangeStatus,
+ char *pRangeStatusString);
+ int8_t (*GetDeviceErrorString)(VL53L0_DeviceError ErrorCode,
+ char *pDeviceErrorString);
+ int8_t (*GetPalErrorString)(VL53L0_Error PalErrorCode,
+ char *pPalErrorString);
+ int8_t (*GetPalStateString)(VL53L0_State PalStateCode,
+ char *pPalStateString);
+ int8_t (*GetPalState)(VL53L0_DEV Dev, VL53L0_State *pPalState);
+ int8_t (*SetPowerMode)(VL53L0_DEV Dev,
+ VL53L0_PowerModes PowerMode);
+ int8_t (*GetPowerMode)(VL53L0_DEV Dev,
+ VL53L0_PowerModes *pPowerMode);
+ int8_t (*SetOffsetCalibrationDataMicroMeter)(VL53L0_DEV Dev,
+ int32_t OffsetCalibrationDataMicroMeter);
+ int8_t (*GetOffsetCalibrationDataMicroMeter)(VL53L0_DEV Dev,
+ int32_t *pOffsetCalibrationDataMicroMeter);
+ int8_t (*SetLinearityCorrectiveGain)(VL53L0_DEV Dev,
+ int16_t LinearityCorrectiveGain);
+ int8_t (*GetLinearityCorrectiveGain)(VL53L0_DEV Dev,
+ uint16_t *pLinearityCorrectiveGain);
+ int8_t (*SetGroupParamHold)(VL53L0_DEV Dev,
+ uint8_t GroupParamHold);
+ int8_t (*GetUpperLimitMilliMeter)(VL53L0_DEV Dev,
+ uint16_t *pUpperLimitMilliMeter);
+ int8_t (*SetDeviceAddress)(VL53L0_DEV Dev,
+ uint8_t DeviceAddress);
+ int8_t (*DataInit)(VL53L0_DEV Dev);
+ int8_t (*SetTuningSettingBuffer)(VL53L0_DEV Dev,
+ uint8_t *pTuningSettingBuffer,
+ uint8_t UseInternalTuningSettings);
+ int8_t (*GetTuningSettingBuffer)(VL53L0_DEV Dev,
+ uint8_t **pTuningSettingBuffer,
+ uint8_t *pUseInternalTuningSettings);
+ int8_t (*StaticInit)(VL53L0_DEV Dev);
+ int8_t (*WaitDeviceBooted)(VL53L0_DEV Dev);
+ int8_t (*ResetDevice)(VL53L0_DEV Dev);
+ int8_t (*SetDeviceParameters)(VL53L0_DEV Dev,
+ const VL53L0_DeviceParameters_t *pDeviceParameters);
+ int8_t (*GetDeviceParameters)(VL53L0_DEV Dev,
+ VL53L0_DeviceParameters_t *pDeviceParameters);
+ int8_t (*SetDeviceMode)(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode);
+ int8_t (*GetDeviceMode)(VL53L0_DEV Dev,
+ VL53L0_DeviceModes *pDeviceMode);
+ int8_t (*SetHistogramMode)(VL53L0_DEV Dev,
+ VL53L0_HistogramModes HistogramMode);
+ int8_t (*GetHistogramMode)(VL53L0_DEV Dev,
+ VL53L0_HistogramModes *pHistogramMode);
+ int8_t (*SetMeasurementTimingBudgetMicroSeconds)(VL53L0_DEV Dev,
+ uint32_t MeasurementTimingBudgetMicroSeconds);
+ int8_t (*GetMeasurementTimingBudgetMicroSeconds)(
+ VL53L0_DEV Dev,
+ uint32_t *pMeasurementTimingBudgetMicroSeconds);
+ int8_t (*GetVcselPulsePeriod)(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType,
+ uint8_t *pVCSELPulsePeriod);
+ int8_t (*SetVcselPulsePeriod)(VL53L0_DEV Dev,
+ VL53L0_VcselPeriod VcselPeriodType,
+ uint8_t VCSELPulsePeriod);
+ int8_t (*SetSequenceStepEnable)(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId,
+ uint8_t SequenceStepEnabled);
+ int8_t (*GetSequenceStepEnable)(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId,
+ uint8_t *pSequenceStepEnabled);
+ int8_t (*GetSequenceStepEnables)(VL53L0_DEV Dev,
+ VL53L0_SchedulerSequenceSteps_t *pSchedulerSequenceSteps);
+ int8_t (*SetSequenceStepTimeout)(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId,
+ FixPoint1616_t TimeOutMilliSecs);
+ int8_t (*GetSequenceStepTimeout)(VL53L0_DEV Dev,
+ VL53L0_SequenceStepId SequenceStepId,
+ FixPoint1616_t *pTimeOutMilliSecs);
+ int8_t (*GetNumberOfSequenceSteps)(VL53L0_DEV Dev,
+ uint8_t *pNumberOfSequenceSteps);
+ int8_t (*GetSequenceStepsInfo)(
+ VL53L0_SequenceStepId SequenceStepId,
+ char *pSequenceStepsString);
+ int8_t (*SetInterMeasurementPeriodMilliSeconds)(
+ VL53L0_DEV Dev,
+ uint32_t InterMeasurementPeriodMilliSeconds);
+ int8_t (*GetInterMeasurementPeriodMilliSeconds)(
+ VL53L0_DEV Dev,
+ uint32_t *pInterMeasurementPeriodMilliSeconds);
+ int8_t (*SetXTalkCompensationEnable)(VL53L0_DEV Dev,
+ uint8_t XTalkCompensationEnable);
+ int8_t (*GetXTalkCompensationEnable)(VL53L0_DEV Dev,
+ uint8_t *pXTalkCompensationEnable);
+ int8_t (*SetXTalkCompensationRateMegaCps)(
+ VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCompensationRateMegaCps);
+ int8_t (*GetXTalkCompensationRateMegaCps)(
+ VL53L0_DEV Dev,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps);
+ int8_t (*GetNumberOfLimitCheck)(
+ uint16_t *pNumberOfLimitCheck);
+ int8_t (*GetLimitCheckInfo)(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, char *pLimitCheckString);
+ int8_t (*SetLimitCheckEnable)(VL53L0_DEV Dev,
+ uint16_t LimitCheckId,
+ uint8_t LimitCheckEnable);
+ int8_t (*GetLimitCheckEnable)(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, uint8_t *pLimitCheckEnable);
+ int8_t (*SetLimitCheckValue)(VL53L0_DEV Dev,
+ uint16_t LimitCheckId,
+ FixPoint1616_t LimitCheckValue);
+ int8_t (*GetLimitCheckValue)(VL53L0_DEV Dev,
+ uint16_t LimitCheckId,
+ FixPoint1616_t *pLimitCheckValue);
+ int8_t (*GetLimitCheckCurrent)(VL53L0_DEV Dev,
+ uint16_t LimitCheckId, FixPoint1616_t *pLimitCheckCurrent);
+ int8_t (*SetWrapAroundCheckEnable)(VL53L0_DEV Dev,
+ uint8_t WrapAroundCheckEnable);
+ int8_t (*GetWrapAroundCheckEnable)(VL53L0_DEV Dev,
+ uint8_t *pWrapAroundCheckEnable);
+ int8_t (*PerformSingleMeasurement)(VL53L0_DEV Dev);
+ int8_t (*PerformRefCalibration)(VL53L0_DEV Dev,
+ uint8_t *pVhvSettings, uint8_t *pPhaseCal);
+ int8_t (*SetRefCalibration)(VL53L0_DEV Dev,
+ uint8_t VhvSettings,
+ uint8_t PhaseCal);
+ int8_t (*GetRefCalibration)(VL53L0_DEV Dev,
+ uint8_t *pVhvSettings,
+ uint8_t *pPhaseCal);
+ int8_t (*PerformXTalkCalibration)(VL53L0_DEV Dev,
+ FixPoint1616_t XTalkCalDistance,
+ FixPoint1616_t *pXTalkCompensationRateMegaCps);
+ int8_t (*PerformOffsetCalibration)(VL53L0_DEV Dev,
+ FixPoint1616_t CalDistanceMilliMeter,
+ int32_t *pOffsetMicroMeter);
+ int8_t (*StartMeasurement)(VL53L0_DEV Dev);
+ int8_t (*StopMeasurement)(VL53L0_DEV Dev);
+ int8_t (*GetMeasurementDataReady)(VL53L0_DEV Dev,
+ uint8_t *pMeasurementDataReady);
+ int8_t (*WaitDeviceReadyForNewMeasurement)(VL53L0_DEV Dev,
+ uint32_t MaxLoop);
+ int8_t (*GetRangingMeasurementData)(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData);
+ int8_t (*GetHistogramMeasurementData)(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData);
+ int8_t (*PerformSingleRangingMeasurement)(VL53L0_DEV Dev,
+ VL53L0_RangingMeasurementData_t *pRangingMeasurementData);
+ int8_t (*PerformSingleHistogramMeasurement)(VL53L0_DEV Dev,
+ VL53L0_HistogramMeasurementData_t *pHistogramMeasurementData);
+ int8_t (*SetNumberOfROIZones)(VL53L0_DEV Dev,
+ uint8_t NumberOfROIZones);
+ int8_t (*GetNumberOfROIZones)(VL53L0_DEV Dev,
+ uint8_t *pNumberOfROIZones);
+ int8_t (*GetMaxNumberOfROIZones)(VL53L0_DEV Dev,
+ uint8_t *pMaxNumberOfROIZones);
+ int8_t (*SetGpioConfig)(VL53L0_DEV Dev,
+ uint8_t Pin,
+ VL53L0_DeviceModes DeviceMode,
+ VL53L0_GpioFunctionality Functionality,
+ VL53L0_InterruptPolarity Polarity);
+ int8_t (*GetGpioConfig)(VL53L0_DEV Dev,
+ uint8_t Pin,
+ VL53L0_DeviceModes *pDeviceMode,
+ VL53L0_GpioFunctionality *pFunctionality,
+ VL53L0_InterruptPolarity *pPolarity);
+ int8_t (*SetInterruptThresholds)(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode,
+ FixPoint1616_t ThresholdLow,
+ FixPoint1616_t ThresholdHigh);
+ int8_t (*GetInterruptThresholds)(VL53L0_DEV Dev,
+ VL53L0_DeviceModes DeviceMode,
+ FixPoint1616_t *pThresholdLow,
+ FixPoint1616_t *pThresholdHigh);
+ int8_t (*ClearInterruptMask)(VL53L0_DEV Dev,
+ uint32_t InterruptMask);
+ int8_t (*GetInterruptMaskStatus)(VL53L0_DEV Dev,
+ uint32_t *pInterruptMaskStatus);
+ int8_t (*EnableInterruptMask)(VL53L0_DEV Dev, uint32_t InterruptMask);
+ int8_t (*SetSpadAmbientDamperThreshold)(VL53L0_DEV Dev,
+ uint16_t SpadAmbientDamperThreshold);
+ int8_t (*GetSpadAmbientDamperThreshold)(VL53L0_DEV Dev,
+ uint16_t *pSpadAmbientDamperThreshold);
+ int8_t (*SetSpadAmbientDamperFactor)(VL53L0_DEV Dev,
+ uint16_t SpadAmbientDamperFactor);
+ int8_t (*GetSpadAmbientDamperFactor)(VL53L0_DEV Dev,
+ uint16_t *pSpadAmbientDamperFactor);
+ int8_t (*PerformRefSpadManagement)(VL53L0_DEV Dev,
+ uint32_t *refSpadCount, uint8_t *isApertureSpads);
+ int8_t (*SetReferenceSpads)(VL53L0_DEV Dev,
+ uint32_t count, uint8_t isApertureSpads);
+ int8_t (*GetReferenceSpads)(VL53L0_DEV Dev,
+ uint32_t *pSpadCount, uint8_t *pIsApertureSpads);
+};
+
+static struct stmvl53l0_api_fn_t stmvl53l0_api_func_tbl = {
+ .GetVersion = VL53L0_GetVersion,
+ .GetPalSpecVersion = VL53L0_GetPalSpecVersion,
+ .GetProductRevision = VL53L0_GetProductRevision,
+ .GetDeviceInfo = VL53L0_GetDeviceInfo,
+ .GetDeviceErrorStatus = VL53L0_GetDeviceErrorStatus,
+ .GetRangeStatusString = VL53L0_GetRangeStatusString,
+ .GetDeviceErrorString = VL53L0_GetDeviceErrorString,
+ .GetPalErrorString = VL53L0_GetPalErrorString,
+ .GetPalState = VL53L0_GetPalState,
+ .SetPowerMode = VL53L0_SetPowerMode,
+ .GetPowerMode = VL53L0_GetPowerMode,
+ .SetOffsetCalibrationDataMicroMeter =
+ VL53L0_SetOffsetCalibrationDataMicroMeter,
+ .SetLinearityCorrectiveGain =
+ VL53L0_SetLinearityCorrectiveGain,
+ .GetLinearityCorrectiveGain =
+ VL53L0_GetLinearityCorrectiveGain,
+ .GetOffsetCalibrationDataMicroMeter =
+ VL53L0_GetOffsetCalibrationDataMicroMeter,
+ .SetGroupParamHold = VL53L0_SetGroupParamHold,
+ .GetUpperLimitMilliMeter = VL53L0_GetUpperLimitMilliMeter,
+ .SetDeviceAddress = VL53L0_SetDeviceAddress,
+ .DataInit = VL53L0_DataInit,
+ .SetTuningSettingBuffer = VL53L0_SetTuningSettingBuffer,
+ .GetTuningSettingBuffer = VL53L0_GetTuningSettingBuffer,
+ .StaticInit = VL53L0_StaticInit,
+ .WaitDeviceBooted = VL53L0_WaitDeviceBooted,
+ .ResetDevice = VL53L0_ResetDevice,
+ .SetDeviceParameters = VL53L0_SetDeviceParameters,
+ .SetDeviceMode = VL53L0_SetDeviceMode,
+ .GetDeviceMode = VL53L0_GetDeviceMode,
+ .SetHistogramMode = VL53L0_SetHistogramMode,
+ .GetHistogramMode = VL53L0_GetHistogramMode,
+ .SetMeasurementTimingBudgetMicroSeconds =
+ VL53L0_SetMeasurementTimingBudgetMicroSeconds,
+ .GetMeasurementTimingBudgetMicroSeconds =
+ VL53L0_GetMeasurementTimingBudgetMicroSeconds,
+ .GetVcselPulsePeriod = VL53L0_GetVcselPulsePeriod,
+ .SetVcselPulsePeriod = VL53L0_SetVcselPulsePeriod,
+ .SetSequenceStepEnable = VL53L0_SetSequenceStepEnable,
+ .GetSequenceStepEnable = VL53L0_GetSequenceStepEnable,
+ .GetSequenceStepEnables = VL53L0_GetSequenceStepEnables,
+ .SetSequenceStepTimeout = VL53L0_SetSequenceStepTimeout,
+ .GetSequenceStepTimeout = VL53L0_GetSequenceStepTimeout,
+ .GetNumberOfSequenceSteps = VL53L0_GetNumberOfSequenceSteps,
+ .GetSequenceStepsInfo = VL53L0_GetSequenceStepsInfo,
+ .SetInterMeasurementPeriodMilliSeconds =
+ VL53L0_SetInterMeasurementPeriodMilliSeconds,
+ .GetInterMeasurementPeriodMilliSeconds =
+ VL53L0_GetInterMeasurementPeriodMilliSeconds,
+ .SetXTalkCompensationEnable = VL53L0_SetXTalkCompensationEnable,
+ .GetXTalkCompensationEnable = VL53L0_GetXTalkCompensationEnable,
+ .SetXTalkCompensationRateMegaCps =
+ VL53L0_SetXTalkCompensationRateMegaCps,
+ .GetXTalkCompensationRateMegaCps =
+ VL53L0_GetXTalkCompensationRateMegaCps,
+ .GetNumberOfLimitCheck = VL53L0_GetNumberOfLimitCheck,
+ .GetLimitCheckInfo = VL53L0_GetLimitCheckInfo,
+ .SetLimitCheckEnable = VL53L0_SetLimitCheckEnable,
+ .GetLimitCheckEnable = VL53L0_GetLimitCheckEnable,
+ .SetLimitCheckValue = VL53L0_SetLimitCheckValue,
+ .GetLimitCheckValue = VL53L0_GetLimitCheckValue,
+ .GetLimitCheckCurrent = VL53L0_GetLimitCheckCurrent,
+ .SetWrapAroundCheckEnable = VL53L0_SetWrapAroundCheckEnable,
+ .GetWrapAroundCheckEnable = VL53L0_GetWrapAroundCheckEnable,
+ .PerformSingleMeasurement = VL53L0_PerformSingleMeasurement,
+ .PerformRefCalibration = VL53L0_PerformRefCalibration,
+ .SetRefCalibration = VL53L0_SetRefCalibration,
+ .GetRefCalibration = VL53L0_GetRefCalibration,
+ .PerformXTalkCalibration = VL53L0_PerformXTalkCalibration,
+ .PerformOffsetCalibration = VL53L0_PerformOffsetCalibration,
+ .StartMeasurement = VL53L0_StartMeasurement,
+ .StopMeasurement = VL53L0_StopMeasurement,
+ .GetMeasurementDataReady = VL53L0_GetMeasurementDataReady,
+ .WaitDeviceReadyForNewMeasurement =
+ VL53L0_WaitDeviceReadyForNewMeasurement,
+ .GetRangingMeasurementData = VL53L0_GetRangingMeasurementData,
+ .GetHistogramMeasurementData = VL53L0_GetHistogramMeasurementData,
+ .PerformSingleRangingMeasurement =
+ VL53L0_PerformSingleRangingMeasurement,
+ .PerformSingleHistogramMeasurement =
+ VL53L0_PerformSingleHistogramMeasurement,
+ .SetNumberOfROIZones = VL53L0_SetNumberOfROIZones,
+ .GetNumberOfROIZones = VL53L0_GetNumberOfROIZones,
+ .GetMaxNumberOfROIZones = VL53L0_GetMaxNumberOfROIZones,
+ .SetGpioConfig = VL53L0_SetGpioConfig,
+ .GetGpioConfig = VL53L0_GetGpioConfig,
+ .SetInterruptThresholds = VL53L0_SetInterruptThresholds,
+ .GetInterruptThresholds = VL53L0_GetInterruptThresholds,
+ .ClearInterruptMask = VL53L0_ClearInterruptMask,
+ .GetInterruptMaskStatus = VL53L0_GetInterruptMaskStatus,
+ .EnableInterruptMask = VL53L0_EnableInterruptMask,
+ .SetSpadAmbientDamperThreshold = VL53L0_SetSpadAmbientDamperThreshold,
+ .GetSpadAmbientDamperThreshold = VL53L0_GetSpadAmbientDamperThreshold,
+ .SetSpadAmbientDamperFactor = VL53L0_SetSpadAmbientDamperFactor,
+ .GetSpadAmbientDamperFactor = VL53L0_GetSpadAmbientDamperFactor,
+ .PerformRefSpadManagement = VL53L0_PerformRefSpadManagement,
+ .SetReferenceSpads = VL53L0_SetReferenceSpads,
+ .GetReferenceSpads = VL53L0_GetReferenceSpads,
+
+};
+struct stmvl53l0_api_fn_t *papi_func_tbl;
+
+/*
+ * IOCTL definitions
+ */
+#define VL53L0_IOCTL_INIT _IO('p', 0x01)
+#define VL53L0_IOCTL_XTALKCALB _IOW('p', 0x02, unsigned int)
+#define VL53L0_IOCTL_OFFCALB _IOW('p', 0x03, unsigned int)
+#define VL53L0_IOCTL_STOP _IO('p', 0x05)
+#define VL53L0_IOCTL_SETXTALK _IOW('p', 0x06, unsigned int)
+#define VL53L0_IOCTL_SETOFFSET _IOW('p', 0x07, int8_t)
+#define VL53L0_IOCTL_ACTIVATE_USE_CASE _IOW('p', 0x08, uint8_t)
+#define VL53L0_IOCTL_ACTIVATE_CUSTOM_USE_CASE \
+ _IOW('p', 0x09, struct stmvl53l0_custom_use_case)
+
+#define VL53L0_IOCTL_GETDATAS \
+ _IOR('p', 0x0b, VL53L0_RangingMeasurementData_t)
+#define VL53L0_IOCTL_REGISTER \
+ _IOWR('p', 0x0c, struct stmvl53l0_register)
+#define VL53L0_IOCTL_PARAMETER \
+ _IOWR('p', 0x0d, struct stmvl53l0_parameter)
+
+
+/* Mask fields to indicate Offset and Xtalk Comp
+ * values have been set by application
+ */
+#define SET_OFFSET_CALIB_DATA_MICROMETER_MASK 0x1
+#define SET_XTALK_COMP_RATE_MCPS_MASK 0x2
+
+/* Macros used across different functions */
+#define USE_CASE_LONG_DISTANCE 1
+#define USE_CASE_HIGH_ACCURACY 2
+#define USE_CASE_HIGH_SPEED 3
+#define USE_CASE_CUSTOM 4
+
+#define LONG_DISTANCE_TIMING_BUDGET 26000
+#define LONG_DISTANCE_SIGNAL_RATE_LIMIT (65536 / 10) /* 0.1 */
+#define LONG_DISTANCE_SIGMA_LIMIT (60*65536)
+#define LONG_DISTANCE_PRE_RANGE_PULSE_PERIOD 18
+#define LONG_DISTANCE_FINAL_RANGE_PULSE_PERIOD 14
+
+
+
+#define HIGH_ACCURACY_TIMING_BUDGET 200000
+#define HIGH_ACCURACY_SIGNAL_RATE_LIMIT (25 * 65536 / 100) /*0.25*/
+#define HIGH_ACCURACY_SIGMA_LIMIT (18*65536)
+#define HIGH_ACCURACY_PRE_RANGE_PULSE_PERIOD 14
+#define HIGH_ACCURACY_FINAL_RANGE_PULSE_PERIOD 10
+
+
+
+#define HIGH_SPEED_TIMING_BUDGET 20000
+#define HIGH_SPEED_SIGNAL_RATE_LIMIT (25 * 65536 / 100) /* 0.25 */
+#define HIGH_SPEED_SIGMA_LIMIT (32*65536)
+#define HIGH_SPEED_PRE_RANGE_PULSE_PERIOD 14
+#define HIGH_SPEED_FINAL_RANGE_PULSE_PERIOD 10
+
+
+
+
+
+static long stmvl53l0_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg);
+/*static int stmvl53l0_flush(struct file *file, fl_owner_t id);*/
+static int stmvl53l0_open(struct inode *inode, struct file *file);
+static int stmvl53l0_init_client(struct stmvl53l0_data *data);
+static int stmvl53l0_start(struct stmvl53l0_data *data, uint8_t scaling,
+ init_mode_e mode);
+static int stmvl53l0_stop(struct stmvl53l0_data *data);
+static int stmvl53l0_config_use_case(struct stmvl53l0_data *data);
+
+#ifdef DEBUG_TIME_LOG
+static void stmvl53l0_DebugTimeGet(struct timeval *ptv)
+{
+ do_gettimeofday(ptv);
+}
+
+static void stmvl53l0_DebugTimeDuration(struct timeval *pstart_tv,
+ struct timeval *pstop_tv)
+{
+ long total_sec, total_msec;
+
+ total_sec = pstop_tv->tv_sec - pstart_tv->tv_sec;
+ total_msec = (pstop_tv->tv_usec - pstart_tv->tv_usec)/1000;
+ total_msec += total_sec * 1000;
+ pr_err("elapsedTime:%ld\n", total_msec);
+}
+#endif
+
+static void stmvl53l0_setupAPIFunctions(struct stmvl53l0_data *data)
+{
+ uint8_t revision = 0;
+ VL53L0_DEV vl53l0_dev = data;
+
+ /* Read Revision ID */
+ VL53L0_RdByte(vl53l0_dev,
+ VL53L0_REG_IDENTIFICATION_REVISION_ID,
+ &revision);
+ vl53l0_errmsg("read REVISION_ID: 0x%x\n", revision);
+ revision = (revision & 0xF0) >> 4;
+ if (revision == 1) {
+ /*cut 1.1*/
+ vl53l0_errmsg("to setup API cut 1.1\n");
+ papi_func_tbl->GetVersion = VL53L0_GetVersion;
+ papi_func_tbl->GetPalSpecVersion = VL53L0_GetPalSpecVersion;
+ papi_func_tbl->GetProductRevision = VL53L0_GetProductRevision;
+ papi_func_tbl->GetDeviceInfo = VL53L0_GetDeviceInfo;
+ papi_func_tbl->GetDeviceErrorStatus =
+ VL53L0_GetDeviceErrorStatus;
+ papi_func_tbl->GetRangeStatusString =
+ VL53L0_GetRangeStatusString;
+ papi_func_tbl->GetDeviceErrorString =
+ VL53L0_GetDeviceErrorString;
+ papi_func_tbl->GetPalErrorString =
+ VL53L0_GetPalErrorString;
+ papi_func_tbl->GetPalState =
+ VL53L0_GetPalState;
+ papi_func_tbl->SetPowerMode =
+ VL53L0_SetPowerMode;
+ papi_func_tbl->GetPowerMode =
+ VL53L0_GetPowerMode;
+ papi_func_tbl->SetOffsetCalibrationDataMicroMeter =
+ VL53L0_SetOffsetCalibrationDataMicroMeter;
+ papi_func_tbl->GetOffsetCalibrationDataMicroMeter =
+ VL53L0_GetOffsetCalibrationDataMicroMeter;
+ papi_func_tbl->SetLinearityCorrectiveGain =
+VL53L0_SetLinearityCorrectiveGain;
+ papi_func_tbl->GetLinearityCorrectiveGain =
+VL53L0_GetLinearityCorrectiveGain;
+ papi_func_tbl->SetGroupParamHold = VL53L0_SetGroupParamHold;
+ papi_func_tbl->GetUpperLimitMilliMeter =
+ VL53L0_GetUpperLimitMilliMeter;
+ papi_func_tbl->SetDeviceAddress =
+ VL53L0_SetDeviceAddress;
+ papi_func_tbl->DataInit =
+ VL53L0_DataInit;
+ papi_func_tbl->SetTuningSettingBuffer =
+ VL53L0_SetTuningSettingBuffer;
+ papi_func_tbl->GetTuningSettingBuffer =
+ VL53L0_GetTuningSettingBuffer;
+ papi_func_tbl->StaticInit =
+ VL53L0_StaticInit;
+ papi_func_tbl->WaitDeviceBooted =
+ VL53L0_WaitDeviceBooted;
+ papi_func_tbl->ResetDevice =
+ VL53L0_ResetDevice;
+ papi_func_tbl->SetDeviceParameters =
+ VL53L0_SetDeviceParameters;
+ papi_func_tbl->SetDeviceMode = VL53L0_SetDeviceMode;
+ papi_func_tbl->GetDeviceMode = VL53L0_GetDeviceMode;
+ papi_func_tbl->SetHistogramMode = VL53L0_SetHistogramMode;
+ papi_func_tbl->GetHistogramMode = VL53L0_GetHistogramMode;
+ papi_func_tbl->SetMeasurementTimingBudgetMicroSeconds =
+ VL53L0_SetMeasurementTimingBudgetMicroSeconds;
+ papi_func_tbl->GetMeasurementTimingBudgetMicroSeconds =
+ VL53L0_GetMeasurementTimingBudgetMicroSeconds;
+ papi_func_tbl->GetVcselPulsePeriod = VL53L0_GetVcselPulsePeriod;
+ papi_func_tbl->SetVcselPulsePeriod = VL53L0_SetVcselPulsePeriod;
+ papi_func_tbl->SetSequenceStepEnable =
+ VL53L0_SetSequenceStepEnable;
+ papi_func_tbl->GetSequenceStepEnable =
+ VL53L0_GetSequenceStepEnable;
+ papi_func_tbl->GetSequenceStepEnables =
+ VL53L0_GetSequenceStepEnables;
+ papi_func_tbl->SetSequenceStepTimeout =
+ VL53L0_SetSequenceStepTimeout;
+ papi_func_tbl->GetSequenceStepTimeout =
+ VL53L0_GetSequenceStepTimeout;
+ papi_func_tbl->GetNumberOfSequenceSteps =
+ VL53L0_GetNumberOfSequenceSteps;
+ papi_func_tbl->GetSequenceStepsInfo =
+ VL53L0_GetSequenceStepsInfo;
+ papi_func_tbl->SetInterMeasurementPeriodMilliSeconds =
+ VL53L0_SetInterMeasurementPeriodMilliSeconds;
+ papi_func_tbl->GetInterMeasurementPeriodMilliSeconds =
+ VL53L0_GetInterMeasurementPeriodMilliSeconds;
+ papi_func_tbl->SetXTalkCompensationEnable =
+ VL53L0_SetXTalkCompensationEnable;
+ papi_func_tbl->GetXTalkCompensationEnable =
+ VL53L0_GetXTalkCompensationEnable;
+ papi_func_tbl->SetXTalkCompensationRateMegaCps =
+ VL53L0_SetXTalkCompensationRateMegaCps;
+ papi_func_tbl->GetXTalkCompensationRateMegaCps =
+ VL53L0_GetXTalkCompensationRateMegaCps;
+ papi_func_tbl->GetNumberOfLimitCheck =
+ VL53L0_GetNumberOfLimitCheck;
+ papi_func_tbl->GetLimitCheckInfo =
+ VL53L0_GetLimitCheckInfo;
+ papi_func_tbl->SetLimitCheckEnable =
+ VL53L0_SetLimitCheckEnable;
+ papi_func_tbl->GetLimitCheckEnable =
+ VL53L0_GetLimitCheckEnable;
+ papi_func_tbl->SetLimitCheckValue =
+ VL53L0_SetLimitCheckValue;
+ papi_func_tbl->GetLimitCheckValue =
+ VL53L0_GetLimitCheckValue;
+ papi_func_tbl->GetLimitCheckCurrent =
+ VL53L0_GetLimitCheckCurrent;
+ papi_func_tbl->SetWrapAroundCheckEnable =
+ VL53L0_SetWrapAroundCheckEnable;
+ papi_func_tbl->GetWrapAroundCheckEnable =
+ VL53L0_GetWrapAroundCheckEnable;
+ papi_func_tbl->PerformSingleMeasurement =
+ VL53L0_PerformSingleMeasurement;
+ papi_func_tbl->PerformRefCalibration =
+ VL53L0_PerformRefCalibration;
+ papi_func_tbl->SetRefCalibration =
+ VL53L0_SetRefCalibration;
+ papi_func_tbl->GetRefCalibration =
+ VL53L0_GetRefCalibration;
+ papi_func_tbl->PerformXTalkCalibration =
+ VL53L0_PerformXTalkCalibration;
+ papi_func_tbl->PerformOffsetCalibration =
+ VL53L0_PerformOffsetCalibration;
+ papi_func_tbl->StartMeasurement =
+ VL53L0_StartMeasurement;
+ papi_func_tbl->StopMeasurement =
+ VL53L0_StopMeasurement;
+ papi_func_tbl->GetMeasurementDataReady =
+ VL53L0_GetMeasurementDataReady;
+ papi_func_tbl->WaitDeviceReadyForNewMeasurement =
+ VL53L0_WaitDeviceReadyForNewMeasurement;
+ papi_func_tbl->GetRangingMeasurementData =
+ VL53L0_GetRangingMeasurementData;
+ papi_func_tbl->GetHistogramMeasurementData =
+ VL53L0_GetHistogramMeasurementData;
+ papi_func_tbl->PerformSingleRangingMeasurement =
+ VL53L0_PerformSingleRangingMeasurement;
+ papi_func_tbl->PerformSingleHistogramMeasurement =
+ VL53L0_PerformSingleHistogramMeasurement;
+ papi_func_tbl->SetNumberOfROIZones =
+ VL53L0_SetNumberOfROIZones;
+ papi_func_tbl->GetNumberOfROIZones =
+ VL53L0_GetNumberOfROIZones;
+ papi_func_tbl->GetMaxNumberOfROIZones =
+ VL53L0_GetMaxNumberOfROIZones;
+ papi_func_tbl->SetGpioConfig =
+ VL53L0_SetGpioConfig;
+ papi_func_tbl->GetGpioConfig =
+ VL53L0_GetGpioConfig;
+ papi_func_tbl->SetInterruptThresholds =
+ VL53L0_SetInterruptThresholds;
+ papi_func_tbl->GetInterruptThresholds =
+ VL53L0_GetInterruptThresholds;
+ papi_func_tbl->ClearInterruptMask =
+ VL53L0_ClearInterruptMask;
+ papi_func_tbl->GetInterruptMaskStatus =
+ VL53L0_GetInterruptMaskStatus;
+ papi_func_tbl->EnableInterruptMask = VL53L0_EnableInterruptMask;
+ papi_func_tbl->SetSpadAmbientDamperThreshold =
+ VL53L0_SetSpadAmbientDamperThreshold;
+ papi_func_tbl->GetSpadAmbientDamperThreshold =
+ VL53L0_GetSpadAmbientDamperThreshold;
+ papi_func_tbl->SetSpadAmbientDamperFactor =
+ VL53L0_SetSpadAmbientDamperFactor;
+ papi_func_tbl->GetSpadAmbientDamperFactor =
+ VL53L0_GetSpadAmbientDamperFactor;
+ papi_func_tbl->PerformRefSpadManagement =
+ VL53L0_PerformRefSpadManagement;
+ papi_func_tbl->SetReferenceSpads = VL53L0_SetReferenceSpads;
+ papi_func_tbl->GetReferenceSpads = VL53L0_GetReferenceSpads;
+ } else if (revision == 0) {
+ /*cut 1.0*/
+ vl53l0_errmsg("to setup API cut 1.0\n");
+ papi_func_tbl->GetVersion = VL53L010_GetVersion;
+ papi_func_tbl->GetPalSpecVersion = VL53L010_GetPalSpecVersion;
+ /* papi_func_tbl->GetProductRevision = NULL;*/
+ papi_func_tbl->GetDeviceInfo = VL53L010_GetDeviceInfo;
+ papi_func_tbl->GetDeviceErrorStatus =
+ VL53L010_GetDeviceErrorStatus;
+ papi_func_tbl->GetDeviceErrorString =
+ VL53L010_GetDeviceErrorString;
+ papi_func_tbl->GetPalErrorString =
+ VL53L010_GetPalErrorString;
+ papi_func_tbl->GetPalState =
+ VL53L010_GetPalState;
+ papi_func_tbl->SetPowerMode =
+ VL53L010_SetPowerMode;
+ papi_func_tbl->GetPowerMode =
+ VL53L010_GetPowerMode;
+ papi_func_tbl->SetOffsetCalibrationDataMicroMeter =
+ VL53L010_SetOffsetCalibrationDataMicroMeter;
+ papi_func_tbl->GetOffsetCalibrationDataMicroMeter =
+ VL53L010_GetOffsetCalibrationDataMicroMeter;
+ papi_func_tbl->SetGroupParamHold =
+ VL53L010_SetGroupParamHold;
+ papi_func_tbl->GetUpperLimitMilliMeter =
+ VL53L010_GetUpperLimitMilliMeter;
+ papi_func_tbl->SetDeviceAddress =
+ VL53L010_SetDeviceAddress;
+ papi_func_tbl->DataInit = VL53L010_DataInit;
+ /*
+ *papi_func_tbl->SetTuningSettingBuffer = NULL;
+ *papi_func_tbl->GetTuningSettingBuffer = NULL;
+ */
+ papi_func_tbl->StaticInit = VL53L010_StaticInit;
+ papi_func_tbl->WaitDeviceBooted = VL53L010_WaitDeviceBooted;
+ papi_func_tbl->ResetDevice = VL53L010_ResetDevice;
+ papi_func_tbl->SetDeviceParameters =
+ VL53L010_SetDeviceParameters;
+ papi_func_tbl->SetDeviceMode = VL53L010_SetDeviceMode;
+ papi_func_tbl->GetDeviceMode = VL53L010_GetDeviceMode;
+ papi_func_tbl->SetHistogramMode = VL53L010_SetHistogramMode;
+ papi_func_tbl->GetHistogramMode = VL53L010_GetHistogramMode;
+ papi_func_tbl->SetMeasurementTimingBudgetMicroSeconds =
+ VL53L010_SetMeasurementTimingBudgetMicroSeconds;
+ papi_func_tbl->GetMeasurementTimingBudgetMicroSeconds =
+ VL53L010_GetMeasurementTimingBudgetMicroSeconds;
+ /*
+ * papi_func_tbl->GetVcselPulsePeriod = NULL;
+ *papi_func_tbl->SetVcselPulsePeriod = NULL;
+ *papi_func_tbl->SetSequenceStepEnable = NULL;
+ *papi_func_tbl->GetSequenceStepEnable = NULL;
+ *papi_func_tbl->GetSequenceStepEnables = NULL;
+ *papi_func_tbl->SetSequenceStepTimeout = NULL;
+ *papi_func_tbl->GetSequenceStepTimeout = NULL;
+ *papi_func_tbl->GetNumberOfSequenceSteps =NULL;
+ *papi_func_tbl->GetSequenceStepsInfo = NULL;
+ */
+ papi_func_tbl->SetInterMeasurementPeriodMilliSeconds =
+ VL53L010_SetInterMeasurementPeriodMilliSeconds;
+ papi_func_tbl->GetInterMeasurementPeriodMilliSeconds =
+ VL53L010_GetInterMeasurementPeriodMilliSeconds;
+ papi_func_tbl->SetXTalkCompensationEnable =
+ VL53L010_SetXTalkCompensationEnable;
+ papi_func_tbl->GetXTalkCompensationEnable =
+ VL53L010_GetXTalkCompensationEnable;
+ papi_func_tbl->SetXTalkCompensationRateMegaCps =
+ VL53L010_SetXTalkCompensationRateMegaCps;
+ papi_func_tbl->GetXTalkCompensationRateMegaCps =
+ VL53L010_GetXTalkCompensationRateMegaCps;
+ papi_func_tbl->GetNumberOfLimitCheck =
+ VL53L010_GetNumberOfLimitCheck;
+ papi_func_tbl->GetLimitCheckInfo = VL53L010_GetLimitCheckInfo;
+ papi_func_tbl->SetLimitCheckEnable =
+ VL53L010_SetLimitCheckEnable;
+ papi_func_tbl->GetLimitCheckEnable =
+ VL53L010_GetLimitCheckEnable;
+ papi_func_tbl->SetLimitCheckValue =
+ VL53L010_SetLimitCheckValue;
+ papi_func_tbl->GetLimitCheckValue =
+ VL53L010_GetLimitCheckValue;
+ papi_func_tbl->GetLimitCheckCurrent =
+ VL53L010_GetLimitCheckCurrent;
+ papi_func_tbl->SetWrapAroundCheckEnable =
+ VL53L010_SetWrapAroundCheckEnable;
+ papi_func_tbl->GetWrapAroundCheckEnable =
+ VL53L010_GetWrapAroundCheckEnable;
+ papi_func_tbl->PerformSingleMeasurement =
+ VL53L010_PerformSingleMeasurement;
+ /*papi_func_tbl->PerformRefCalibration =
+ * VL53L010_PerformRefCalibration;
+ */
+ papi_func_tbl->PerformRefCalibration = NULL;
+ papi_func_tbl->SetRefCalibration = NULL;
+ papi_func_tbl->GetRefCalibration = NULL;
+ papi_func_tbl->PerformXTalkCalibration =
+ VL53L010_PerformXTalkCalibration;
+ papi_func_tbl->PerformOffsetCalibration =
+ VL53L010_PerformOffsetCalibration;
+ papi_func_tbl->StartMeasurement = VL53L010_StartMeasurement;
+ papi_func_tbl->StopMeasurement = VL53L010_StopMeasurement;
+ papi_func_tbl->GetMeasurementDataReady =
+ VL53L010_GetMeasurementDataReady;
+ papi_func_tbl->WaitDeviceReadyForNewMeasurement =
+ VL53L010_WaitDeviceReadyForNewMeasurement;
+ papi_func_tbl->GetRangingMeasurementData =
+ VL53L010_GetRangingMeasurementData;
+ papi_func_tbl->GetHistogramMeasurementData =
+ VL53L010_GetHistogramMeasurementData;
+ papi_func_tbl->PerformSingleRangingMeasurement =
+ VL53L010_PerformSingleRangingMeasurement;
+ papi_func_tbl->PerformSingleHistogramMeasurement =
+ VL53L010_PerformSingleHistogramMeasurement;
+ papi_func_tbl->SetNumberOfROIZones =
+ VL53L010_SetNumberOfROIZones;
+ papi_func_tbl->GetNumberOfROIZones =
+ VL53L010_GetNumberOfROIZones;
+ papi_func_tbl->GetMaxNumberOfROIZones =
+ VL53L010_GetMaxNumberOfROIZones;
+ papi_func_tbl->SetGpioConfig = VL53L010_SetGpioConfig;
+ papi_func_tbl->GetGpioConfig = VL53L010_GetGpioConfig;
+ papi_func_tbl->SetInterruptThresholds =
+ VL53L010_SetInterruptThresholds;
+ papi_func_tbl->GetInterruptThresholds =
+ VL53L010_GetInterruptThresholds;
+ papi_func_tbl->ClearInterruptMask =
+ VL53L010_ClearInterruptMask;
+ papi_func_tbl->GetInterruptMaskStatus =
+ VL53L010_GetInterruptMaskStatus;
+ papi_func_tbl->EnableInterruptMask =
+ VL53L010_EnableInterruptMask;
+ papi_func_tbl->SetSpadAmbientDamperThreshold =
+ VL53L010_SetSpadAmbientDamperThreshold;
+ papi_func_tbl->GetSpadAmbientDamperThreshold =
+ VL53L010_GetSpadAmbientDamperThreshold;
+ papi_func_tbl->SetSpadAmbientDamperFactor =
+ VL53L010_SetSpadAmbientDamperFactor;
+ papi_func_tbl->GetSpadAmbientDamperFactor =
+ VL53L010_GetSpadAmbientDamperFactor;
+ papi_func_tbl->PerformRefSpadManagement = NULL;
+ papi_func_tbl->SetReferenceSpads = NULL;
+ papi_func_tbl->GetReferenceSpads = NULL;
+ }
+
+}
+
+static void stmvl53l0_ps_read_measurement(struct stmvl53l0_data *data)
+{
+ struct timeval tv;
+ VL53L0_DEV vl53l0_dev = data;
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ FixPoint1616_t LimitCheckCurrent;
+
+ do_gettimeofday(&tv);
+
+ data->ps_data = data->rangeData.RangeMilliMeter;
+ input_report_abs(data->input_dev_ps, ABS_DISTANCE,
+ (int)(data->ps_data + 5) / 10);
+ input_report_abs(data->input_dev_ps, ABS_HAT0X, tv.tv_sec);
+ input_report_abs(data->input_dev_ps, ABS_HAT0Y, tv.tv_usec);
+ input_report_abs(data->input_dev_ps, ABS_HAT1X,
+ data->rangeData.RangeMilliMeter);
+ input_report_abs(data->input_dev_ps, ABS_HAT1Y,
+ data->rangeData.RangeStatus);
+ input_report_abs(data->input_dev_ps, ABS_HAT2X,
+ data->rangeData.SignalRateRtnMegaCps);
+ input_report_abs(data->input_dev_ps, ABS_HAT2Y,
+ data->rangeData.AmbientRateRtnMegaCps);
+ input_report_abs(data->input_dev_ps, ABS_HAT3X,
+ data->rangeData.MeasurementTimeUsec);
+ input_report_abs(data->input_dev_ps, ABS_HAT3Y,
+ data->rangeData.RangeDMaxMilliMeter);
+ Status = papi_func_tbl->GetLimitCheckCurrent(vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ &LimitCheckCurrent);
+ if (Status == VL53L0_ERROR_NONE) {
+ input_report_abs(data->input_dev_ps, ABS_WHEEL,
+ LimitCheckCurrent);
+ }
+ input_report_abs(data->input_dev_ps, ABS_PRESSURE,
+ data->rangeData.EffectiveSpadRtnCount);
+ input_sync(data->input_dev_ps);
+
+ if (data->enableDebug)
+ vl53l0_errmsg(
+"range:%d, RtnRateMcps:%d,err:0x%x,Dmax:%d,rtnambr:%d,time:%d,Spad:%d,SigmaLimit:%d\n",
+ data->rangeData.RangeMilliMeter,
+ data->rangeData.SignalRateRtnMegaCps,
+ data->rangeData.RangeStatus,
+ data->rangeData.RangeDMaxMilliMeter,
+ data->rangeData.AmbientRateRtnMegaCps,
+ data->rangeData.MeasurementTimeUsec,
+ data->rangeData.EffectiveSpadRtnCount,
+ LimitCheckCurrent
+ );
+
+
+}
+
+static void stmvl53l0_cancel_handler(struct stmvl53l0_data *data)
+{
+ unsigned long flags;
+ bool ret;
+
+ spin_lock_irqsave(&data->update_lock.wait_lock, flags);
+ /*
+ * If work is already scheduled then subsequent schedules will not
+ * change the scheduled time that's why we have to cancel it first.
+ */
+ ret = cancel_delayed_work(&data->dwork);
+ if (ret == 0)
+ vl53l0_errmsg("cancel_delayed_work return FALSE\n");
+
+ spin_unlock_irqrestore(&data->update_lock.wait_lock, flags);
+
+}
+
+void stmvl53l0_schedule_handler(struct stmvl53l0_data *data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&data->update_lock.wait_lock, flags);
+ /*
+ * If work is already scheduled then subsequent schedules will not
+ * change the scheduled time that's why we have to cancel it first.
+ */
+ cancel_delayed_work(&data->dwork);
+ schedule_delayed_work(&data->dwork, 0);
+ spin_unlock_irqrestore(&data->update_lock.wait_lock, flags);
+
+}
+
+
+#ifdef USE_INT
+static irqreturn_t stmvl53l0_interrupt_handler(int vec, void *info)
+{
+
+ struct stmvl53l0_data *data = (struct stmvl53l0_data *)info;
+
+ if (data->irq == vec) {
+ data->interrupt_received = 1;
+ schedule_delayed_work(&data->dwork, 0);
+ }
+ return IRQ_HANDLED;
+}
+#else
+/* Flag used to exit the thread when kthread_stop() is invoked */
+static int poll_thread_exit;
+int stmvl53l0_poll_thread(void *data)
+{
+ VL53L0_DEV vl53l0_dev = data;
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ uint32_t sleep_time = 0;
+ uint32_t interruptStatus = 0;
+
+ pr_err("%s(%d) : Starting Polling thread\n", __func__, __LINE__);
+
+ while (!kthread_should_stop()) {
+ /* Check if enable_ps_sensor is true or exit request is made.
+ * If not block
+ */
+ wait_event(vl53l0_dev->poll_thread_wq,
+ (vl53l0_dev->enable_ps_sensor || poll_thread_exit));
+ if (poll_thread_exit) {
+ pr_err(
+ "%s(%d) : Exiting the poll thread\n", __func__, __LINE__);
+ break;
+ }
+
+ mutex_lock(&vl53l0_dev->work_mutex);
+
+ sleep_time = vl53l0_dev->delay_ms;
+ Status = VL53L0_GetInterruptMaskStatus(vl53l0_dev,
+ &interruptStatus);
+ if (Status == VL53L0_ERROR_NONE &&
+ interruptStatus &&
+ interruptStatus != vl53l0_dev->interruptStatus) {
+ vl53l0_dev->interruptStatus = interruptStatus;
+ vl53l0_dev->noInterruptCount = 0;
+ stmvl53l0_schedule_handler(vl53l0_dev);
+ } else {
+ vl53l0_dev->noInterruptCount++;
+ }
+
+ /*Force Clear interrupt mask and restart if
+ *no interrupt after twice the timingBudget
+ */
+ if ((vl53l0_dev->noInterruptCount * vl53l0_dev->delay_ms) >
+ (vl53l0_dev->timingBudget * 2)) {
+ pr_err("No interrupt after (%u) msec(TimingBudget = %u) . Clear Interrupt Mask and restart\n",
+ (vl53l0_dev->noInterruptCount *
+ vl53l0_dev->delay_ms),
+ vl53l0_dev->timingBudget);
+ Status = papi_func_tbl->ClearInterruptMask(vl53l0_dev,
+ 0);
+ if (vl53l0_dev->deviceMode ==
+ VL53L0_DEVICEMODE_SINGLE_RANGING) {
+ Status = papi_func_tbl->StartMeasurement(
+ vl53l0_dev);
+ if (Status != VL53L0_ERROR_NONE) {
+ pr_err("%s(%d) : Status = %d\n",
+ __func__, __LINE__, Status);
+ }
+ }
+ }
+ mutex_unlock(&vl53l0_dev->work_mutex);
+ /* Sleep for delay_ms milliseconds */
+ msleep(sleep_time);
+ }
+
+ return 0;
+}
+#endif
+
+/* work handler */
+static void stmvl53l0_work_handler(struct work_struct *work)
+{
+ struct stmvl53l0_data *data = container_of(work, struct stmvl53l0_data,
+ dwork.work);
+ VL53L0_DEV vl53l0_dev = data;
+
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ mutex_lock(&data->work_mutex);
+ /* vl53l0_dbgmsg("Enter\n"); */
+
+ if (pmodule_func_tbl->query_power_status(data->client_object) == 0) {
+ if (data->enable_ps_sensor == 1) {
+ stmvl53l0_stop(data);
+ data->enable_ps_sensor = 0;
+ }
+ }
+
+ if (vl53l0_dev->enable_ps_sensor == 1) {
+#ifdef DEBUG_TIME_LOG
+ stmvl53l0_DebugTimeGet(&stop_tv);
+ stmvl53l0_DebugTimeDuration(&start_tv, &stop_tv);
+#endif
+ /* Check if ISR has scheduled this function */
+ if (vl53l0_dev->interrupt_received == 1) {
+ Status = papi_func_tbl->GetInterruptMaskStatus(
+ vl53l0_dev,
+ &vl53l0_dev->interruptStatus);
+ if (Status != VL53L0_ERROR_NONE)
+ pr_err("%s(%d) : Status = %d\n",
+ __func__, __LINE__, Status);
+ vl53l0_dev->interrupt_received = 0;
+ }
+ if (data->enableDebug)
+ pr_err("interruptStatus:0x%x, interrupt_received:%d\n",
+ vl53l0_dev->interruptStatus,
+ vl53l0_dev->interrupt_received);
+
+ if (vl53l0_dev->interruptStatus == vl53l0_dev->gpio_function) {
+ Status =
+ papi_func_tbl->GetRangingMeasurementData(
+ vl53l0_dev,
+ &(data->rangeData));
+ /* to push the measurement */
+ if (Status == VL53L0_ERROR_NONE)
+ stmvl53l0_ps_read_measurement(data);
+ else
+ pr_err("%s(%d) : Status = %d\n",
+ __func__, __LINE__, Status);
+
+ if (data->enableDebug)
+ pr_err("Measured range:%d\n",
+ data->rangeData.RangeMilliMeter);
+
+ Status = papi_func_tbl->ClearInterruptMask(
+ vl53l0_dev, 0);
+ if (Status != VL53L0_ERROR_NONE) {
+ pr_err("%s(%d) : Status = %d\n",
+ __func__, __LINE__, Status);
+ }
+
+ if (data->deviceMode ==
+ VL53L0_DEVICEMODE_SINGLE_RANGING) {
+ /* Before restarting measurement
+ * check if use case needs to be changed
+ */
+
+ if (data->updateUseCase) {
+ Status =
+ stmvl53l0_config_use_case(data);
+ if (Status !=
+ VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "Failed to configure Use case = %u\n",
+ vl53l0_dev->useCase);
+ } else {
+ data->updateUseCase = 0;
+ }
+ }
+ Status =
+ papi_func_tbl->StartMeasurement(
+ vl53l0_dev);
+ }
+ }
+#ifdef DEBUG_TIME_LOG
+ stmvl53l0_DebugTimeGet(&start_tv);
+#endif
+
+ }
+
+
+ vl53l0_dev->interruptStatus = 0;
+
+ mutex_unlock(&data->work_mutex);
+
+}
+
+
+/*
+ * SysFS support
+ */
+static ssize_t stmvl53l0_show_enable_ps_sensor(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, 5, "%d\n", data->enable_ps_sensor);
+}
+
+static ssize_t stmvl53l0_store_enable_ps_sensor(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+ unsigned long val = 0;
+
+ int ret = kstrtoul(buf, 10, &val);
+
+ if (ret != 0)
+ return ret;
+
+ if ((val != 0) && (val != 1)) {
+ vl53l0_errmsg("store unvalid value = %lu\n", val);
+ return count;
+ }
+ mutex_lock(&data->work_mutex);
+ vl53l0_dbgmsg("Enter, enable_ps_sensor flag:%d\n",
+ data->enable_ps_sensor);
+ vl53l0_dbgmsg("enable ps senosr ( %ld)\n", val);
+
+ if (val == 1) {
+ /* turn on tof sensor */
+ if (data->enable_ps_sensor == 0) {
+ /* to start */
+ stmvl53l0_start(data, 3, NORMAL_MODE);
+ } else {
+ vl53l0_errmsg("Already enabled. Skip !");
+ }
+ } else {
+ /* turn off tof sensor */
+ if (data->enable_ps_sensor == 1) {
+ data->enable_ps_sensor = 0;
+ /* to stop */
+ stmvl53l0_stop(data);
+ }
+ }
+ vl53l0_dbgmsg("End\n");
+ mutex_unlock(&data->work_mutex);
+
+ return count;
+}
+
+static DEVICE_ATTR(enable_ps_sensor, 0664/*S_IWUGO | S_IRUGO*/,
+ stmvl53l0_show_enable_ps_sensor,
+ stmvl53l0_store_enable_ps_sensor);
+
+static ssize_t stmvl53l0_show_enable_debug(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, 5, "%d\n", data->enableDebug);
+}
+
+/* for debug */
+static ssize_t stmvl53l0_store_enable_debug(struct device *dev,
+ struct device_attribute *attr, const
+ char *buf, size_t count)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+ unsigned long on = 0;
+
+ int ret = kstrtoul(buf, 10, &on);
+
+ if (ret != 0)
+ return ret;
+
+ if ((on != 0) && (on != 1)) {
+ vl53l0_errmsg("set debug=%lu\n", on);
+ return count;
+ }
+ data->enableDebug = on;
+
+ return count;
+}
+
+/* DEVICE_ATTR(name,mode,show,store) */
+static DEVICE_ATTR(enable_debug, 0660/*S_IWUSR | S_IRUGO*/,
+ stmvl53l0_show_enable_debug,
+ stmvl53l0_store_enable_debug);
+
+static ssize_t stmvl53l0_show_set_delay_ms(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, 5, "%d\n", data->delay_ms);
+}
+
+/* for work handler scheduler time */
+static ssize_t stmvl53l0_store_set_delay_ms(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+ unsigned long delay_ms = 0;
+
+ int ret = kstrtoul(buf, 10, &delay_ms);
+
+ if (ret != 0)
+ return ret;
+ if (delay_ms == 0) {
+ vl53l0_errmsg("set delay_ms=%lu\n", delay_ms);
+ return count;
+ }
+ mutex_lock(&data->work_mutex);
+ data->delay_ms = delay_ms;
+ mutex_unlock(&data->work_mutex);
+
+ return count;
+}
+
+/* DEVICE_ATTR(name,mode,show,store) */
+static DEVICE_ATTR(set_delay_ms, 0660/*S_IWUGO | S_IRUGO*/,
+ stmvl53l0_show_set_delay_ms,
+ stmvl53l0_store_set_delay_ms);
+
+/* Timing Budget */
+static ssize_t stmvl53l0_show_timing_budget(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, 10, "%d\n", data->timingBudget);
+}
+
+static ssize_t stmvl53l0_store_set_timing_budget(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+ unsigned long timingBudget = 0;
+ int ret = kstrtoul(buf, 10, &timingBudget);
+
+ if (ret != 0)
+ return ret;
+ if (timingBudget == 0) {
+ vl53l0_errmsg("set timingBudget=%lu\n", timingBudget);
+ return count;
+ }
+ mutex_lock(&data->work_mutex);
+ data->timingBudget = timingBudget;
+ mutex_unlock(&data->work_mutex);
+
+ return count;
+}
+
+/* DEVICE_ATTR(name,mode,show,store) */
+static DEVICE_ATTR(set_timing_budget, 0660/*S_IWUGO | S_IRUGO*/,
+ stmvl53l0_show_timing_budget,
+ stmvl53l0_store_set_timing_budget);
+
+
+/* Use case */
+static ssize_t stmvl53l0_show_use_case(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+
+ switch (data->useCase) {
+ case USE_CASE_LONG_DISTANCE:
+ return snprintf(buf, 20, "Long Distance\n");
+ case USE_CASE_HIGH_ACCURACY:
+ return snprintf(buf, 20, "High Accuracy\n");
+ case USE_CASE_HIGH_SPEED:
+ return snprintf(buf, 20, "High Speed\n");
+ default:
+ break;
+ }
+
+ return snprintf(buf, 25, "Unknown use case\n");
+}
+
+static ssize_t stmvl53l0_store_set_use_case(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+ unsigned long useCase = 0;
+ int ret = kstrtoul(buf, 10, &useCase);
+
+ if (ret != 0)
+ return ret;
+
+
+ mutex_lock(&data->work_mutex);
+
+ if (useCase == USE_CASE_LONG_DISTANCE) {
+ data->timingBudget = LONG_DISTANCE_TIMING_BUDGET;
+ } else if (useCase == USE_CASE_HIGH_SPEED) {
+ data->timingBudget = HIGH_SPEED_TIMING_BUDGET;
+ } else if (useCase == USE_CASE_HIGH_ACCURACY) {
+ data->timingBudget = HIGH_ACCURACY_TIMING_BUDGET;
+ } else {
+ count = -EINVAL;
+ mutex_unlock(&data->work_mutex);
+ return count;
+ }
+
+ data->useCase = useCase;
+ mutex_unlock(&data->work_mutex);
+
+ return count;
+}
+
+/* DEVICE_ATTR(name,mode,show,store) */
+static DEVICE_ATTR(set_use_case, 0660/*S_IWUGO | S_IRUGO*/,
+ stmvl53l0_show_use_case,
+ stmvl53l0_store_set_use_case);
+
+
+/* Get Current configuration info */
+static ssize_t stmvl53l0_show_current_configuration(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stmvl53l0_data *vl53l0_dev = dev_get_drvdata(dev);
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ int ret = -1;
+ FixPoint1616_t LimitValue = 0;
+ uint8_t LimitEnable = 0;
+ uint32_t refSpadCount = 0;
+ uint8_t isApertureSpads = 0;
+ uint8_t VhvSettings = 0;
+ uint8_t PhaseCal = 0;
+ uint8_t pulsePeriod = 0;
+ uint32_t timingBudget = 0;
+ int32_t offsetCalibrationDataMicroMeter = -1;
+ uint8_t XTalkCompensationEnable = 0;
+ FixPoint1616_t xTalkCompensationRateMegaCps = 0;
+
+
+ ret = scnprintf(buf, PAGE_SIZE, "VL53L0 current configuration:\n");
+
+ mutex_lock(&vl53l0_dev->work_mutex);
+ pr_err("Driver Config:UseCase:%d, offsetCalDistance:%u,xtalkCalDistance:%u,setCalibratedValue:0x%X\n",
+ vl53l0_dev->useCase, vl53l0_dev->offsetCalDistance,
+ vl53l0_dev->xtalkCalDistance,
+ vl53l0_dev->setCalibratedValue);
+
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "Driver Config:UseCase:%d, offsetCalDistance:%u,xtalkCalDistance:%u,setCalibratedValue:0x%X\n",
+ vl53l0_dev->useCase,
+ vl53l0_dev->offsetCalDistance,
+ vl53l0_dev->xtalkCalDistance,
+ vl53l0_dev->setCalibratedValue);
+
+ if (vl53l0_dev->useCase == USE_CASE_CUSTOM) {
+ pr_err("CustomUseCase : Sigma=%u :Signal=%u: Pre=%u :Final=%u\n",
+ vl53l0_dev->sigmaLimit,
+ vl53l0_dev->signalRateLimit,
+ vl53l0_dev->preRangePulsePeriod,
+ vl53l0_dev->finalRangePulsePeriod);
+
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "CustomUseCase : Sigma=%u :Signal=%u: Pre=%u :Final=%u\n",
+ vl53l0_dev->sigmaLimit,
+ vl53l0_dev->signalRateLimit,
+ vl53l0_dev->preRangePulsePeriod,
+ vl53l0_dev->finalRangePulsePeriod);
+ }
+
+
+ Status = papi_func_tbl->GetLimitCheckValue(vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ &LimitValue);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = papi_func_tbl->GetLimitCheckEnable(vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ &LimitEnable);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("Get LimitCheckValue SIGMA_FINAL_RANGE as:%d,Enable:%d\n",
+ (LimitValue>>16), LimitEnable);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "Sigma Limit:%u, Enable:%u\n",
+ (LimitValue>>16),
+ LimitEnable);
+ Status = papi_func_tbl->GetLimitCheckValue(vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ &LimitValue);
+ Status = papi_func_tbl->GetLimitCheckEnable(vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ &LimitEnable);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("Get LimitCheckValue SIGNAL_FINAL_RANGE as:%d(Fix1616),Enable:%d\n",
+ (LimitValue), LimitEnable);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "SIGNAL Limit:%u, Enable:%u\n",
+ LimitValue,
+ LimitEnable);
+
+ Status = papi_func_tbl->GetLimitCheckValue(vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP,
+ &LimitValue);
+ Status = papi_func_tbl->GetLimitCheckEnable(vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGNAL_REF_CLIP,
+ &LimitEnable);
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("Get LimitCheckValue SIGNAL_REF_CLIP as:%d(fix1616),Enable:%d\n",
+ (LimitValue), LimitEnable);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "RefClipLimit:%u, Enable:%u\n",
+ LimitValue,
+ LimitEnable);
+
+ Status = papi_func_tbl->GetLimitCheckValue(vl53l0_dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ &LimitValue);
+ Status = papi_func_tbl->GetLimitCheckEnable(vl53l0_dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ &LimitEnable);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err(
+ "Get LimitCheckValue RANGE_IGNORE_THRESHOLDas:%d(fix1616),Enable:%d\n",
+ (LimitValue),
+ LimitEnable);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "RngIgnoreThresh:%u, Enable:%u\n",
+ LimitValue,
+ LimitEnable);
+
+ Status = papi_func_tbl->GetRefCalibration(vl53l0_dev,
+ &VhvSettings, &PhaseCal); /* Ref calibration */
+
+
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("GetRefCalibration - Vhv = %u, PhaseCal = %u\n",
+ VhvSettings, PhaseCal);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "Vhv:%u, PhCal:%u\n",
+ VhvSettings,
+ PhaseCal);
+
+ /* Ref Spad Management */
+ Status = papi_func_tbl->GetReferenceSpads(vl53l0_dev,
+ &refSpadCount, &isApertureSpads);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("GetSpads - Count = %u, IsAperture = %u\n",
+ refSpadCount, isApertureSpads);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "SpadCount:%u, IsAperture:%u\n",
+ refSpadCount,
+ isApertureSpads);
+
+ Status = papi_func_tbl->GetMeasurementTimingBudgetMicroSeconds(
+ vl53l0_dev,
+ &timingBudget);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("TimingBudget = %u\n", timingBudget);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "TimBudget:%u\n",
+ timingBudget);
+ Status = papi_func_tbl->GetVcselPulsePeriod(vl53l0_dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ &pulsePeriod);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("GetVcselPulsePeriod - PRE_RANGE = %u\n",
+ pulsePeriod);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "PulsePreRange:%u\n",
+ pulsePeriod);
+
+ Status = papi_func_tbl->GetVcselPulsePeriod(vl53l0_dev,
+ VL53L0_VCSEL_PERIOD_FINAL_RANGE,
+ &pulsePeriod);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("GetVcselPulsePeriod - FINAL_RANGE = %u\n",
+ pulsePeriod);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "PulseFinalRange:%u\n",
+ pulsePeriod);
+
+ Status = papi_func_tbl->GetOffsetCalibrationDataMicroMeter(
+ vl53l0_dev,
+ &offsetCalibrationDataMicroMeter);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("OffsetCalibrationDataMicroMeter = %d\n",
+ offsetCalibrationDataMicroMeter);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "Offset:%d\n",
+ offsetCalibrationDataMicroMeter);
+
+ Status = papi_func_tbl->GetXTalkCompensationEnable(vl53l0_dev,
+ &XTalkCompensationEnable);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("Xtalk Enable = %u\n", XTalkCompensationEnable);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "XtalkEnable:%u\n",
+ XTalkCompensationEnable);
+
+ Status = papi_func_tbl->GetXTalkCompensationRateMegaCps(
+ vl53l0_dev,
+ &xTalkCompensationRateMegaCps);
+ }
+
+
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("XtalkComp MCPS = %u\n", xTalkCompensationRateMegaCps);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "XtalkMcps:%u\n",
+ xTalkCompensationRateMegaCps);
+
+ } else {
+ pr_err("Error = %d\n", Status);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "Error:%d\n",
+ Status);
+
+ }
+
+ pr_err("Total Bytes returned = %d\n", ret);
+
+ mutex_unlock(&vl53l0_dev->work_mutex);
+
+
+ return ret;
+}
+
+/* DEVICE_ATTR(name,mode,show,store) */
+static DEVICE_ATTR(show_current_configuration, 0660/*S_IWUGO | S_IRUGO*/,
+ stmvl53l0_show_current_configuration,
+ NULL);
+/* for work handler scheduler time */
+static ssize_t stmvl53l0_do_flush(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct stmvl53l0_data *data = dev_get_drvdata(dev);
+
+ int ret = 0;
+ /* Revisit : Avoid lock if it takes too long time */
+ mutex_lock(&data->work_mutex);
+
+ vl53l0_dbgmsg("Starting timer to fire in 1ms (%ld)\n", jiffies);
+ ret = mod_timer(&data->timer, jiffies + msecs_to_jiffies(1));
+ if (ret)
+ pr_err("Error from mod_timer = %d\n", ret);
+
+ mutex_unlock(&data->work_mutex);
+ return count;
+}
+
+/* DEVICE_ATTR(name,mode,show,store) */
+static DEVICE_ATTR(do_flush, 0660/*S_IWUGO | S_IRUGO*/,
+ NULL,
+ stmvl53l0_do_flush);
+static struct attribute *stmvl53l0_attributes[] = {
+ &dev_attr_enable_ps_sensor.attr,
+ &dev_attr_enable_debug.attr,
+ &dev_attr_set_delay_ms.attr,
+ &dev_attr_set_timing_budget.attr,
+ &dev_attr_set_use_case.attr,
+ &dev_attr_do_flush.attr,
+ &dev_attr_show_current_configuration.attr,
+ NULL
+};
+
+
+static const struct attribute_group stmvl53l0_attr_group = {
+ .attrs = stmvl53l0_attributes,
+};
+
+/*
+ * misc device file operation functions
+ */
+static int stmvl53l0_ioctl_handler(struct file *file,
+ unsigned int cmd, unsigned long arg,
+ void __user *p)
+{
+ int rc = 0;
+ unsigned int xtalkint = 0;
+ unsigned int targetDistance = 0;
+ int8_t offsetint = 0;
+ uint8_t useCase = 0;
+ struct stmvl53l0_custom_use_case customUseCase;
+ struct stmvl53l0_data *data =
+ container_of(file->private_data,
+ struct stmvl53l0_data, miscdev);
+ struct stmvl53l0_register reg;
+ struct stmvl53l0_parameter parameter;
+ VL53L0_DEV vl53l0_dev = data;
+ VL53L0_DeviceModes deviceMode;
+ uint8_t page_num = 0;
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ if (!data)
+ return -EINVAL;
+
+ vl53l0_dbgmsg("Enter enable_ps_sensor:%d\n", data->enable_ps_sensor);
+ switch (cmd) {
+ /* enable */
+ case VL53L0_IOCTL_INIT:
+ vl53l0_dbgmsg("VL53L0_IOCTL_INIT\n");
+ /* turn on tof sensor only if it's not enabled by other
+ * client
+ */
+ if (data->enable_ps_sensor == 0) {
+ /* to start */
+ stmvl53l0_start(data, 3, NORMAL_MODE);
+ } else
+ rc = -EINVAL;
+ break;
+ /* crosstalk calibration */
+ case VL53L0_IOCTL_XTALKCALB:
+ vl53l0_dbgmsg("VL53L0_IOCTL_XTALKCALB\n");
+ data->xtalkCalDistance = 100;
+ if (copy_from_user(&targetDistance, (unsigned int *)p,
+ sizeof(unsigned int))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+ data->xtalkCalDistance = targetDistance;
+
+ /* turn on tof sensor only if it's not enabled by other
+ * client
+ */
+ if (data->enable_ps_sensor == 0) {
+ /* to start */
+ stmvl53l0_start(data, 3, XTALKCALIB_MODE);
+ } else
+ rc = -EINVAL;
+ break;
+ /* set up Xtalk value */
+ case VL53L0_IOCTL_SETXTALK:
+ vl53l0_dbgmsg("VL53L0_IOCTL_SETXTALK\n");
+ if (copy_from_user(&xtalkint, (unsigned int *)p,
+ sizeof(unsigned int))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+ vl53l0_dbgmsg("SETXTALK as 0x%x\n", xtalkint);
+
+ /* later
+ * SetXTalkCompensationRate(vl53l0_dev, xtalkint);
+ */
+ break;
+ /* offset calibration */
+ case VL53L0_IOCTL_OFFCALB:
+ vl53l0_dbgmsg("VL53L0_IOCTL_OFFCALB\n");
+ data->offsetCalDistance = 50;
+ if (copy_from_user(&targetDistance, (unsigned int *)p,
+ sizeof(unsigned int))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+ data->offsetCalDistance = targetDistance;
+ if (data->enable_ps_sensor == 0) {
+ /* to start */
+ stmvl53l0_start(data, 3, OFFSETCALIB_MODE);
+ } else
+ rc = -EINVAL;
+ break;
+ /* set up offset value */
+ case VL53L0_IOCTL_SETOFFSET:
+ vl53l0_dbgmsg("VL53L0_IOCTL_SETOFFSET\n");
+ if (copy_from_user(&offsetint, (int8_t *)p, sizeof(int8_t))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+ vl53l0_dbgmsg("SETOFFSET as %d\n", offsetint);
+
+ /* later
+ * SetOffsetCalibrationData(vl53l0_dev, offsetint);
+ */
+ break;
+
+ /* Config use case */
+ case VL53L0_IOCTL_ACTIVATE_USE_CASE:
+ vl53l0_dbgmsg("VL53L0_IOCTL_ACTIVATE_USE_CASE\n");
+ if (copy_from_user(&useCase, (uint8_t *)p, sizeof(uint8_t))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+
+ /* Validate the user passed use case.
+ * Update the timingBudget value. The other
+ * parameters are updated approrpiately in config_use_case()
+ * Currently the timing budget can be updated through
+ * sysfs entry, and this needs additional steps to manage.
+ */
+ switch (useCase) {
+ case USE_CASE_LONG_DISTANCE:
+ data->timingBudget = LONG_DISTANCE_TIMING_BUDGET;
+ break;
+
+ case USE_CASE_HIGH_ACCURACY:
+ data->timingBudget = HIGH_ACCURACY_TIMING_BUDGET;
+ break;
+
+ case USE_CASE_HIGH_SPEED:
+ data->timingBudget = HIGH_SPEED_TIMING_BUDGET;
+ break;
+
+ default:
+ vl53l0_errmsg("%d, Unknown Use case = %u\n", __LINE__,
+ useCase);
+ return -EFAULT;
+ }
+ vl53l0_dbgmsg("useCase as %d\n", useCase);
+ /* record the use case */
+ data->useCase = useCase;
+
+ /* If ranging is in progress, let the work handler
+ * update the use case
+ */
+ if (data->enable_ps_sensor)
+ data->updateUseCase = 1;
+ break;
+
+ /* Config Custom use case */
+ case VL53L0_IOCTL_ACTIVATE_CUSTOM_USE_CASE:
+ vl53l0_dbgmsg("VL53L0_IOCTL_ACTIVATE_CUSTOM_USE_CASE\n");
+ if (copy_from_user(&customUseCase,
+ (struct stmvl53l0_custom_use_case *)p,
+ sizeof(struct stmvl53l0_custom_use_case))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+
+ data->sigmaLimit = customUseCase.sigmaLimit;
+ data->signalRateLimit = customUseCase.signalRateLimit;
+ data->preRangePulsePeriod = customUseCase.preRangePulsePeriod;
+ data->finalRangePulsePeriod =
+ customUseCase.finalRangePulsePeriod;
+ data->timingBudget = customUseCase.timingBudget;
+ vl53l0_dbgmsg(
+ "Sigma=%u,Signal=%u,Pre=%u,Final=%u,timingBudget=%u\n",
+ data->sigmaLimit,
+ data->signalRateLimit,
+ data->preRangePulsePeriod,
+ data->finalRangePulsePeriod,
+ data->timingBudget);
+
+ /* record the use case */
+ data->useCase = USE_CASE_CUSTOM;
+ /* If ranging is in progress,
+ * let the work handler update the use case
+ */
+ if (data->enable_ps_sensor)
+ data->updateUseCase = 1;
+
+ break;
+
+
+ /* disable */
+ case VL53L0_IOCTL_STOP:
+ vl53l0_dbgmsg("VL53L0_IOCTL_STOP\n");
+ /* turn off tof sensor only if it's enabled by other client */
+ if (data->enable_ps_sensor == 1) {
+ data->enable_ps_sensor = 0;
+ /* to stop */
+ stmvl53l0_stop(data);
+ }
+ break;
+ /* Get all range data */
+ case VL53L0_IOCTL_GETDATAS:
+ vl53l0_dbgmsg("VL53L0_IOCTL_GETDATAS\n");
+ if (copy_to_user((VL53L0_RangingMeasurementData_t *)p,
+ &(data->rangeData),
+ sizeof(VL53L0_RangingMeasurementData_t))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+ break;
+ /* Register tool */
+ case VL53L0_IOCTL_REGISTER:
+ vl53l0_dbgmsg("VL53L0_IOCTL_REGISTER\n");
+ if (copy_from_user(&reg, (struct stmvl53l0_register *)p,
+ sizeof(struct stmvl53l0_register))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+ reg.status = 0;
+ page_num = (uint8_t)((reg.reg_index & 0x0000ff00) >> 8);
+ vl53l0_dbgmsg(
+"VL53L0_IOCTL_REGISTER, page number:%d\n", page_num);
+ if (page_num != 0)
+ reg.status = VL53L0_WrByte(vl53l0_dev, 0xFF, page_num);
+
+ switch (reg.reg_bytes) {
+ case(4):
+ if (reg.is_read)
+ reg.status = VL53L0_RdDWord(vl53l0_dev,
+ (uint8_t)reg.reg_index,
+ &reg.reg_data);
+ else
+ reg.status = VL53L0_WrDWord(vl53l0_dev,
+ (uint8_t)reg.reg_index,
+ reg.reg_data);
+ break;
+ case(2):
+ if (reg.is_read)
+ reg.status = VL53L0_RdWord(vl53l0_dev,
+ (uint8_t)reg.reg_index,
+ (uint16_t *)&reg.reg_data);
+ else
+ reg.status = VL53L0_WrWord(vl53l0_dev,
+ (uint8_t)reg.reg_index,
+ (uint16_t)reg.reg_data);
+ break;
+ case(1):
+ if (reg.is_read)
+ reg.status = VL53L0_RdByte(vl53l0_dev,
+ (uint8_t)reg.reg_index,
+ (uint8_t *)&reg.reg_data);
+ else
+ reg.status = VL53L0_WrByte(vl53l0_dev,
+ (uint8_t)reg.reg_index,
+ (uint8_t)reg.reg_data);
+ break;
+ default:
+ reg.status = -1;
+
+ }
+ if (page_num != 0)
+ reg.status = VL53L0_WrByte(vl53l0_dev, 0xFF, 0);
+
+
+ if (copy_to_user((struct stmvl53l0_register *)p, &reg,
+ sizeof(struct stmvl53l0_register))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+ break;
+ /* parameter access */
+ case VL53L0_IOCTL_PARAMETER:
+ vl53l0_dbgmsg("VL53L0_IOCTL_PARAMETER\n");
+ if (copy_from_user(&parameter, (struct stmvl53l0_parameter *)p,
+ sizeof(struct stmvl53l0_parameter))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+ parameter.status = 0;
+ if (data->enableDebug)
+ vl53l0_dbgmsg(
+ "VL53L0_IOCTL_PARAMETER Name = %d\n", parameter.name);
+ switch (parameter.name) {
+ case (OFFSET_PAR):
+ if (parameter.is_read)
+ parameter.status =
+ papi_func_tbl->GetOffsetCalibrationDataMicroMeter(
+ vl53l0_dev, &parameter.value);
+ else {
+ parameter.status =
+ papi_func_tbl->SetOffsetCalibrationDataMicroMeter(
+ vl53l0_dev, parameter.value);
+ data->OffsetMicroMeter = parameter.value;
+ data->setCalibratedValue
+ |= SET_OFFSET_CALIB_DATA_MICROMETER_MASK;
+
+ }
+ vl53l0_dbgmsg("get parameter value as %d\n",
+ parameter.value);
+ break;
+
+ case (REFERENCESPADS_PAR):
+ if (parameter.is_read) {
+ parameter.status =
+ papi_func_tbl->GetReferenceSpads(vl53l0_dev,
+ (uint32_t *)&(parameter.value),
+ (uint8_t *)&(parameter.value2));
+ if (data->enableDebug)
+ vl53l0_dbgmsg(
+ "Get RefSpad : Count:%u, Type:%u\n",
+ parameter.value,
+ (uint8_t)parameter.value2);
+ } else {
+ if (data->enableDebug)
+ vl53l0_dbgmsg(
+ "Set RefSpad : Count:%u, Type:%u\n",
+ parameter.value,
+ (uint8_t)parameter.value2);
+
+ parameter.status =
+ papi_func_tbl->SetReferenceSpads(vl53l0_dev,
+ (uint32_t)(parameter.value),
+ (uint8_t)(parameter.value2));
+
+ data->refSpadCount = parameter.value;
+ data->isApertureSpads =
+ (uint8_t)(parameter.value2);
+ }
+ break;
+
+ case (REFCALIBRATION_PAR):
+ if (parameter.is_read) {
+ parameter.status =
+ papi_func_tbl->GetRefCalibration(vl53l0_dev,
+ (uint8_t *)&(parameter.value),
+ (uint8_t *)&(parameter.value2));
+ if (data->enableDebug)
+ vl53l0_dbgmsg(
+ "Get Ref : Vhv:%u, PhaseCal:%u\n",
+ (uint8_t)parameter.value,
+ (uint8_t)parameter.value2);
+ } else {
+ if (data->enableDebug)
+ vl53l0_dbgmsg(
+ "Set Ref : Vhv:%u, PhaseCal:%u\n",
+ (uint8_t)parameter.value,
+ (uint8_t)parameter.value2);
+ parameter.status =
+ papi_func_tbl->SetRefCalibration(
+ vl53l0_dev,
+ (uint8_t)(parameter.value),
+ (uint8_t)(parameter.value2));
+ data->VhvSettings = (uint8_t)parameter.value;
+ data->PhaseCal = (uint8_t)(parameter.value2);
+ }
+ break;
+ case (XTALKRATE_PAR):
+ if (parameter.is_read)
+ parameter.status =
+ papi_func_tbl->GetXTalkCompensationRateMegaCps(
+ vl53l0_dev,
+ (FixPoint1616_t *)
+ &parameter.value);
+ else {
+ /* Range Ignore Threshold value */
+ FixPoint1616_t ritValue = 0;
+
+ parameter.status =
+ papi_func_tbl->SetXTalkCompensationRateMegaCps(
+ vl53l0_dev,
+ (FixPoint1616_t)
+ parameter.value);
+ data->XTalkCompensationRateMegaCps =
+ parameter.value;
+ data->setCalibratedValue |=
+ SET_XTALK_COMP_RATE_MCPS_MASK;
+
+
+ /*0.7 KCps converted to MCps */
+ if (data->XTalkCompensationRateMegaCps <
+ 7*65536/10000) {
+ ritValue = 15 * 7 * 65536/100000;
+ } else {
+ ritValue = 15 *
+ vl53l0_dev->XTalkCompensationRateMegaCps
+ /10;
+ }
+
+ if (papi_func_tbl->SetLimitCheckEnable
+ != NULL) {
+ Status =
+ papi_func_tbl->SetLimitCheckEnable(
+ vl53l0_dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ 1);
+ }
+
+ if ((Status == VL53L0_ERROR_NONE) &&
+ (papi_func_tbl->SetLimitCheckValue
+ != NULL)) {
+ vl53l0_dbgmsg(
+ "Set RIT - %u\n", ritValue);
+ Status =
+ papi_func_tbl->SetLimitCheckValue(
+ vl53l0_dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ ritValue);
+ }
+
+ }
+ break;
+ case (XTALKENABLE_PAR):
+ if (parameter.is_read)
+ parameter.status =
+ papi_func_tbl->GetXTalkCompensationEnable(
+ vl53l0_dev,
+ (uint8_t *) &parameter.value);
+ else
+ parameter.status =
+ papi_func_tbl->SetXTalkCompensationEnable(
+ vl53l0_dev,
+ (uint8_t) parameter.value);
+ break;
+ case (GPIOFUNC_PAR):
+ if (parameter.is_read) {
+ parameter.status =
+ papi_func_tbl->GetGpioConfig(
+ vl53l0_dev,
+ 0,
+ &deviceMode,
+ &data->gpio_function,
+ &data->gpio_polarity);
+ parameter.value =
+ data->gpio_function;
+ } else {
+ data->gpio_function = parameter.value;
+ parameter.status =
+ papi_func_tbl->SetGpioConfig(
+ vl53l0_dev,
+ 0,
+ 0,
+ data->gpio_function,
+ data->gpio_polarity);
+ }
+ break;
+ case (LOWTHRESH_PAR):
+ if (parameter.is_read) {
+ parameter.status =
+ papi_func_tbl->GetInterruptThresholds(
+ vl53l0_dev,
+ 0,
+ &(data->low_threshold),
+ &(data->high_threshold));
+ parameter.value =
+ data->low_threshold >> 16;
+ } else {
+ data->low_threshold = parameter.value << 16;
+ parameter.status =
+ papi_func_tbl->SetInterruptThresholds(
+ vl53l0_dev,
+ 0,
+ data->low_threshold,
+ data->high_threshold);
+ }
+ break;
+ case (HIGHTHRESH_PAR):
+ if (parameter.is_read) {
+ parameter.status =
+ papi_func_tbl->GetInterruptThresholds(
+ vl53l0_dev,
+ 0,
+ &(data->low_threshold),
+ &(data->high_threshold));
+ parameter.value =
+ data->high_threshold >> 16;
+ } else {
+ data->high_threshold =
+ parameter.value << 16;
+ parameter.status =
+ papi_func_tbl->SetInterruptThresholds(
+ vl53l0_dev,
+ 0,
+ data->low_threshold,
+ data->high_threshold);
+ }
+ break;
+ case (DEVICEMODE_PAR):
+ if (parameter.is_read) {
+ parameter.status =
+ papi_func_tbl->GetDeviceMode(
+ vl53l0_dev,
+ (VL53L0_DeviceModes *)&(parameter.value));
+ } else {
+ parameter.status =
+ papi_func_tbl->SetDeviceMode(
+ vl53l0_dev,
+ (VL53L0_DeviceModes)(parameter.value));
+ data->deviceMode =
+ (VL53L0_DeviceModes)(parameter.value);
+ }
+ break;
+
+
+
+ case (INTERMEASUREMENT_PAR):
+ if (parameter.is_read) {
+ parameter.status =
+ papi_func_tbl->GetInterMeasurementPeriodMilliSeconds(
+ vl53l0_dev,
+ (uint32_t *)&(parameter.value));
+ } else {
+ parameter.status =
+ papi_func_tbl->SetInterMeasurementPeriodMilliSeconds(
+ vl53l0_dev,
+ (uint32_t)(parameter.value));
+ data->interMeasurems = parameter.value;
+ }
+ break;
+
+ }
+
+ if (copy_to_user((struct stmvl53l0_parameter *)p, &parameter,
+ sizeof(struct stmvl53l0_parameter))) {
+ vl53l0_errmsg("%d, fail\n", __LINE__);
+ return -EFAULT;
+ }
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static int stmvl53l0_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+/* Flush will be invoked on close(device_fd) */
+static int stmvl53l0_flush(struct file *file, fl_owner_t id)
+{
+ struct stmvl53l0_data *data = container_of(file->private_data,
+ struct stmvl53l0_data, miscdev);
+ (void) file;
+ (void) id;
+ /* Revisit : Check if the
+ *instance are opened multiple times on some platforms
+ */
+ mutex_lock(&data->work_mutex);
+ if (data) {
+ if (data->enable_ps_sensor == 1) {
+ /* turn off tof sensor if it's enabled */
+ data->enable_ps_sensor = 0;
+ /* to stop */
+ stmvl53l0_stop(data);
+ }
+ }
+ mutex_unlock(&data->work_mutex);
+
+ return 0;
+}
+
+static long stmvl53l0_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ long ret;
+ struct stmvl53l0_data *data =
+ container_of(file->private_data,
+ struct stmvl53l0_data, miscdev);
+ mutex_lock(&data->work_mutex);
+ ret = stmvl53l0_ioctl_handler(file, cmd, arg, (void __user *)arg);
+ mutex_unlock(&data->work_mutex);
+
+ return ret;
+}
+
+/*
+ * Initialization function
+ */
+static int stmvl53l0_init_client(struct stmvl53l0_data *data)
+{
+
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ VL53L0_DeviceInfo_t DeviceInfo;
+ VL53L0_DEV vl53l0_dev = data;
+ uint32_t refSpadCount = 0;
+ uint8_t isApertureSpads = 0;
+ uint8_t VhvSettings = 0;
+ uint8_t PhaseCal = 0;
+
+
+ vl53l0_dbgmsg("Enter\n");
+
+ data->I2cDevAddr = 0x52;
+ data->comms_type = 1;
+ data->comms_speed_khz = 400;
+
+
+
+ /* Setup API functions based on revision */
+ stmvl53l0_setupAPIFunctions(data);
+
+ /* Perform Ref and RefSpad calibrations and save the values */
+
+
+ if (data->reset) {
+ pr_err("Call of VL53L0_DataInit\n");
+ /* Data initialization */
+ Status = papi_func_tbl->DataInit(vl53l0_dev);
+ /* data->reset = 0; */
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "%d- error status %d\n", __LINE__, Status);
+ return Status;
+ }
+ }
+
+ vl53l0_dbgmsg("VL53L0_GetDeviceInfo:\n");
+ Status = papi_func_tbl->GetDeviceInfo(vl53l0_dev, &DeviceInfo);
+ if (Status == VL53L0_ERROR_NONE) {
+ pr_err("Device Name : %s\n", DeviceInfo.Name);
+ pr_err("Device Type : %s\n", DeviceInfo.Type);
+ pr_err("Device ID : %s\n", DeviceInfo.ProductId);
+ pr_err("Product type: %d\n", DeviceInfo.ProductType);
+ pr_err("ProductRevisionMajor : %d\n",
+ DeviceInfo.ProductRevisionMajor);
+ pr_err("ProductRevisionMinor : %d\n",
+ DeviceInfo.ProductRevisionMinor);
+ }
+ /* Device Initialization */
+ vl53l0_dbgmsg("Call of VL53L0_StaticInit\n");
+ Status = papi_func_tbl->StaticInit(vl53l0_dev);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg("%d- error status %d\n", __LINE__, Status);
+ return Status;
+ }
+
+
+
+
+
+ if (papi_func_tbl->PerformRefCalibration != NULL && data->reset) {
+ vl53l0_dbgmsg("Call of VL53L0_PerformRefCalibration\n");
+ Status = papi_func_tbl->PerformRefCalibration(vl53l0_dev,
+ &VhvSettings, &PhaseCal); /* Ref calibration */
+ if (Status !=
+ VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "%d- error status %d\n", __LINE__, Status);
+ return Status;
+ }
+ }
+ vl53l0_dbgmsg("VHV = %u, PhaseCal = %u\n", VhvSettings, PhaseCal);
+ vl53l0_dev->VhvSettings = VhvSettings;
+ vl53l0_dev->PhaseCal = PhaseCal;
+
+ if (papi_func_tbl->PerformRefSpadManagement != NULL && data->reset) {
+ vl53l0_dbgmsg(
+ "Call of VL53L0_PerformRefSpadManagement\n");
+ Status = papi_func_tbl->PerformRefSpadManagement(vl53l0_dev,
+ &refSpadCount,
+ &isApertureSpads); /* Ref Spad Management */
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "%d- error status %d\n", __LINE__, Status);
+ return Status;
+ }
+ }
+
+ vl53l0_dbgmsg(
+ "SpadCount = %u, isAperature = %u\n",
+ refSpadCount, isApertureSpads);
+ vl53l0_dev->refSpadCount = refSpadCount;
+ vl53l0_dev->isApertureSpads = isApertureSpads;
+
+
+
+
+ if (Status == VL53L0_ERROR_NONE && data->reset) {
+ if ((papi_func_tbl->SetOffsetCalibrationDataMicroMeter
+ != NULL) &&
+ (vl53l0_dev->setCalibratedValue &
+ SET_OFFSET_CALIB_DATA_MICROMETER_MASK)) {
+ vl53l0_dbgmsg(
+ "Call of SetOffsetCalibrationDataMicroMeter\n");
+ Status =
+ papi_func_tbl->SetOffsetCalibrationDataMicroMeter(
+ vl53l0_dev,
+ vl53l0_dev->OffsetMicroMeter);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "%d- error status %d\n", __LINE__, Status);
+ return Status;
+ }
+ }
+ }
+
+
+
+ if (data->reset) {
+ if ((papi_func_tbl->SetXTalkCompensationRateMegaCps != NULL) &&
+ (vl53l0_dev->setCalibratedValue &
+ SET_XTALK_COMP_RATE_MCPS_MASK)) {
+ vl53l0_dbgmsg(
+ "Call of SetXTalkCompensationRateMegaCps\n");
+ Status = papi_func_tbl->SetXTalkCompensationRateMegaCps(
+ vl53l0_dev,
+ vl53l0_dev->XTalkCompensationRateMegaCps);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "%d- error status %d\n",
+ __LINE__, Status);
+ return Status;
+ }
+ }
+ }
+
+ if (data->reset) {
+ if (vl53l0_dev->setCalibratedValue &
+ /* Xtalk calibration done*/
+ SET_XTALK_COMP_RATE_MCPS_MASK) {
+ /* Range Ignore Threshold */
+ FixPoint1616_t ritValue = 0;
+
+ if (vl53l0_dev->XTalkCompensationRateMegaCps <
+ 7*65536/10000) {
+ /*0.7 KCps converted to MCps */
+ ritValue = 15 * 7 * 65536/100000;
+ } else {
+ ritValue = 15 *
+ vl53l0_dev->XTalkCompensationRateMegaCps/10;
+ }
+
+ if (papi_func_tbl->SetLimitCheckEnable != NULL) {
+ Status = papi_func_tbl->SetLimitCheckEnable(
+ vl53l0_dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ 1);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "%d- error status %d\n", __LINE__,
+ Status);
+ return Status;
+ }
+ }
+
+ if (papi_func_tbl->SetLimitCheckValue != NULL) {
+ vl53l0_dbgmsg("Set RIT - %u\n", ritValue);
+ Status = papi_func_tbl->SetLimitCheckValue(
+ vl53l0_dev,
+ VL53L0_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
+ ritValue);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "%d- error status %d\n",
+ __LINE__, Status);
+ return Status;
+ }
+ }
+ }
+ data->reset = 0;
+ }
+
+ /* Setup in single ranging mode */
+
+ pr_err("Call of VL53L0_SetDeviceMode\n");
+ Status = papi_func_tbl->SetDeviceMode(vl53l0_dev,
+ VL53L0_DEVICEMODE_SINGLE_RANGING);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg("%d- error status %d\n", __LINE__, Status);
+ return Status;
+ }
+
+
+ Status = papi_func_tbl->SetWrapAroundCheckEnable(vl53l0_dev, 1);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg("%d- error status %d\n", __LINE__, Status);
+ return Status;
+ }
+
+
+ vl53l0_dbgmsg("End\n");
+
+ return 0;
+}
+
+
+static int stmvl53l0_config_use_case(struct stmvl53l0_data *data)
+{
+ VL53L0_DEV vl53l0_dev = data;
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+ FixPoint1616_t signalRateLimit;
+ FixPoint1616_t sigmaLimit;
+ uint32_t preRangePulsePeriod;
+ uint32_t finalRangePulsePeriod;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ switch (vl53l0_dev->useCase) {
+
+ case USE_CASE_LONG_DISTANCE:
+ sigmaLimit = LONG_DISTANCE_SIGMA_LIMIT;
+ signalRateLimit = LONG_DISTANCE_SIGNAL_RATE_LIMIT;
+ preRangePulsePeriod = LONG_DISTANCE_PRE_RANGE_PULSE_PERIOD;
+ finalRangePulsePeriod = LONG_DISTANCE_FINAL_RANGE_PULSE_PERIOD;
+ break;
+
+ case USE_CASE_HIGH_ACCURACY:
+ sigmaLimit = HIGH_ACCURACY_SIGMA_LIMIT;
+ signalRateLimit = HIGH_ACCURACY_SIGNAL_RATE_LIMIT;
+ preRangePulsePeriod = HIGH_ACCURACY_PRE_RANGE_PULSE_PERIOD;
+ finalRangePulsePeriod = HIGH_ACCURACY_FINAL_RANGE_PULSE_PERIOD;
+ break;
+
+ case USE_CASE_HIGH_SPEED:
+ sigmaLimit = HIGH_SPEED_SIGMA_LIMIT;
+ signalRateLimit = HIGH_SPEED_SIGNAL_RATE_LIMIT;
+ preRangePulsePeriod = HIGH_SPEED_PRE_RANGE_PULSE_PERIOD;
+ finalRangePulsePeriod = HIGH_SPEED_FINAL_RANGE_PULSE_PERIOD;
+ break;
+
+ case USE_CASE_CUSTOM:
+ /* Set by application through IOCTL interface */
+ sigmaLimit = vl53l0_dev->sigmaLimit;
+ signalRateLimit = vl53l0_dev->signalRateLimit;
+ preRangePulsePeriod = vl53l0_dev->preRangePulsePeriod;
+ finalRangePulsePeriod = vl53l0_dev->finalRangePulsePeriod;
+ break;
+
+ default:
+ vl53l0_errmsg(
+ "Invalid use case = %d\n", vl53l0_dev->useCase);
+ /* Invalid parameter, should not reach here */
+ return -EINVAL;
+ }
+
+ vl53l0_dbgmsg(
+ "Configure UseCase(%d) : Sigma=%u,Signal=%u,Pre=%u,Final=%u,timingBudget=%u\n",
+ vl53l0_dev->useCase,
+ sigmaLimit,
+ signalRateLimit,
+ preRangePulsePeriod,
+ finalRangePulsePeriod,
+ vl53l0_dev->timingBudget);
+
+ if (papi_func_tbl->SetLimitCheckEnable != NULL) {
+ Status = papi_func_tbl->SetLimitCheckEnable(
+ vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ 1);
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = papi_func_tbl->SetLimitCheckEnable(
+ vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ 1);
+ } else {
+ vl53l0_errmsg(
+ "SetLimitCheckEnable(SIGMA_FINAL_RANGE) failed with errcode = %d\n",
+ Status);
+ }
+ }
+
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = papi_func_tbl->SetLimitCheckValue(
+ vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ signalRateLimit);
+ } else {
+ vl53l0_errmsg(
+ "SetLimitCheckEnable(SIGNAL_RATE_FINAL_RANGE) failed with errcode = %d\n",
+ Status);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = papi_func_tbl->SetLimitCheckValue(vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
+ sigmaLimit);
+ } else {
+ vl53l0_dbgmsg(
+ "SIGNAL_RATE_FINAL_RANGE failed with errcode = %d\n",
+ Status);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status =
+ papi_func_tbl->SetMeasurementTimingBudgetMicroSeconds(
+ vl53l0_dev,
+ vl53l0_dev->timingBudget);
+ } else {
+ vl53l0_dbgmsg(
+ "SIGMA_FINAL_RANGE failed with errcode = %d\n",
+ Status);
+ }
+
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = papi_func_tbl->SetVcselPulsePeriod(vl53l0_dev,
+ VL53L0_VCSEL_PERIOD_PRE_RANGE,
+ preRangePulsePeriod);
+ } else {
+ vl53l0_dbgmsg(
+ "SetMeasurementTimingBudget failed with errcode = %d\n",
+ Status);
+ }
+
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = papi_func_tbl->SetVcselPulsePeriod(vl53l0_dev,
+ VL53L0_VCSEL_PERIOD_FINAL_RANGE,
+ finalRangePulsePeriod);
+ } else
+ vl53l0_dbgmsg(
+ "SetVcselPulsePeriod(PRE) failed with errcode = %d\n", Status);
+
+
+ if (Status != VL53L0_ERROR_NONE)
+ vl53l0_dbgmsg(
+ "SetVcselPulsePeriod(FINAL)failed with errcode = %d\n", Status);
+
+ vl53l0_dbgmsg("End\n");
+ return Status;
+}
+static int stmvl53l0_start(struct stmvl53l0_data *data, uint8_t scaling,
+ init_mode_e mode)
+{
+ int rc = 0;
+ VL53L0_DEV vl53l0_dev = data;
+ VL53L0_Error Status = VL53L0_ERROR_NONE;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ /* Power up */
+ rc = pmodule_func_tbl->power_up(data->client_object, &data->reset);
+ if (rc) {
+ vl53l0_errmsg("%d,error rc %d\n", __LINE__, rc);
+ return rc;
+ }
+
+ /* init */
+ rc = stmvl53l0_init_client(data);
+ if (rc) {
+ vl53l0_errmsg("%d, error rc %d\n", __LINE__, rc);
+ pmodule_func_tbl->power_down(data->client_object);
+ return -EINVAL;
+ }
+
+ /* check mode */
+ if (mode != NORMAL_MODE)
+ papi_func_tbl->SetXTalkCompensationEnable(vl53l0_dev, 1);
+
+ if (mode == OFFSETCALIB_MODE) {
+ /*VL53L0_SetOffsetCalibrationDataMicroMeter(vl53l0_dev, 0);*/
+ FixPoint1616_t OffsetMicroMeter;
+
+ papi_func_tbl->PerformOffsetCalibration(vl53l0_dev,
+ (data->offsetCalDistance<<16),
+ &OffsetMicroMeter);
+ pr_err("Offset calibration:%u\n", OffsetMicroMeter);
+ vl53l0_dev->OffsetMicroMeter = OffsetMicroMeter;
+ vl53l0_dev->setCalibratedValue |=
+ SET_OFFSET_CALIB_DATA_MICROMETER_MASK;
+
+ return rc;
+ } else if (mode == XTALKCALIB_MODE) {
+ FixPoint1616_t XTalkCompensationRateMegaCps;
+ /*caltarget distance : 100mm and convert to
+ * fixed point 16 16 format
+ */
+ papi_func_tbl->PerformXTalkCalibration(vl53l0_dev,
+ (data->xtalkCalDistance<<16),
+ &XTalkCompensationRateMegaCps);
+ pr_err("Xtalk calibration:%u\n",
+ XTalkCompensationRateMegaCps);
+ vl53l0_dev->XTalkCompensationRateMegaCps =
+ XTalkCompensationRateMegaCps;
+ vl53l0_dev->setCalibratedValue |=
+ SET_XTALK_COMP_RATE_MCPS_MASK;
+
+ return rc;
+ }
+ /* set up device parameters */
+ data->gpio_polarity = VL53L0_INTERRUPTPOLARITY_LOW;
+
+ /* Following two calls are made from IOCTL as well */
+ Status = papi_func_tbl->SetGpioConfig(vl53l0_dev, 0, 0,
+ data->gpio_function,
+ VL53L0_INTERRUPTPOLARITY_LOW);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg("Failed to SetGpioConfig. Error = %d\n", Status);
+ return -EPERM;
+ }
+
+
+ Status = papi_func_tbl->SetInterruptThresholds(vl53l0_dev, 0,
+ data->low_threshold,
+ data->high_threshold);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "Failed to SetInterruptThresholds. Error = %d\n", Status);
+ return -EPERM;
+ }
+
+
+ if (data->deviceMode == VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING) {
+ Status = papi_func_tbl->SetInterMeasurementPeriodMilliSeconds(
+ vl53l0_dev,
+ data->interMeasurems);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "Failed to SetInterMeasurementPeriodMilliSeconds. Error = %d\n",
+ Status);
+ return -EPERM;
+ }
+ pr_err(
+ "DeviceMode:0x%x, interMeasurems:%d==\n",
+ data->deviceMode,
+ data->interMeasurems);
+
+
+ }
+
+
+ Status = papi_func_tbl->SetDeviceMode(
+ vl53l0_dev,
+ data->deviceMode);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg("Failed to SetDeviceMode. Error = %d\n", Status);
+ return -EPERM;
+ }
+
+ Status = papi_func_tbl->ClearInterruptMask(vl53l0_dev,
+ 0);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "Failed to ClearInterruptMask. Error = %d\n", Status);
+ return -EPERM;
+ }
+
+
+
+ Status = stmvl53l0_config_use_case(vl53l0_dev);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "Failed to configure Use case = %u\n",
+ vl53l0_dev->useCase);
+ return -EPERM;
+ }
+
+ /* start the ranging */
+ Status = papi_func_tbl->StartMeasurement(vl53l0_dev);
+ if (Status != VL53L0_ERROR_NONE) {
+ vl53l0_errmsg(
+ "Failed to StartMeasurement. Error = %d\n", Status);
+ return -EPERM;
+ }
+
+ data->enable_ps_sensor = 1;
+
+#ifndef USE_INT
+ /* Unblock the thread execution */
+ wake_up(&vl53l0_dev->poll_thread_wq);
+#endif
+
+ vl53l0_dbgmsg("End\n");
+
+ return rc;
+}
+
+static int stmvl53l0_stop(struct stmvl53l0_data *data)
+{
+ int rc = 0;
+ VL53L0_DEV vl53l0_dev = data;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ /* stop - if continuous mode */
+ if (data->deviceMode == VL53L0_DEVICEMODE_CONTINUOUS_RANGING ||
+ data->deviceMode == VL53L0_DEVICEMODE_CONTINUOUS_TIMED_RANGING)
+ papi_func_tbl->StopMeasurement(vl53l0_dev);
+
+ /* clean interrupt */
+ papi_func_tbl->ClearInterruptMask(vl53l0_dev, 0);
+
+ /* cancel work handler */
+ stmvl53l0_cancel_handler(data);
+
+ /* Clear updateUseCase pending operation */
+ data->updateUseCase = 0;
+ /* power down */
+ rc = pmodule_func_tbl->power_down(data->client_object);
+ if (rc) {
+ vl53l0_errmsg("%d, error rc %d\n", __LINE__, rc);
+ return rc;
+ }
+ vl53l0_dbgmsg("End\n");
+
+ return rc;
+}
+static void stmvl53l0_timer_fn(unsigned long data)
+{
+
+ VL53L0_DEV vl53l0_dev = (VL53L0_DEV)data;
+
+ vl53l0_dev->flushCount++;
+
+ input_report_abs(vl53l0_dev->input_dev_ps, ABS_GAS,
+ vl53l0_dev->flushCount);
+
+
+ input_sync(vl53l0_dev->input_dev_ps);
+
+ vl53l0_dbgmsg("Sensor HAL Flush Count = %u\n", vl53l0_dev->flushCount);
+}
+
+
+
+/*
+ * I2C init/probing/exit functions
+ */
+static const struct file_operations stmvl53l0_ranging_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = stmvl53l0_ioctl,
+ .open = stmvl53l0_open,
+ .flush = stmvl53l0_flush,
+};
+
+
+
+int stmvl53l0_setup(struct stmvl53l0_data *data)
+{
+ int rc = 0;
+
+#ifdef USE_INT
+ int irq = 0;
+#endif
+
+ vl53l0_dbgmsg("Enter\n");
+
+ /* init mutex */
+ mutex_init(&data->update_lock);
+ mutex_init(&data->work_mutex);
+
+#ifdef USE_INT
+ /* init interrupt */
+ gpio_request(data->irq_gpio, "vl53l0_gpio_int");
+ gpio_direction_input(data->irq_gpio);
+ irq = gpio_to_irq(data->irq_gpio);
+ if (irq < 0) {
+ vl53l0_errmsg("filed to map GPIO: %d to interrupt:%d\n",
+ data->irq_gpio, irq);
+ } else {
+ vl53l0_dbgmsg("register_irq:%d\n", irq);
+ /* IRQF_TRIGGER_FALLING- poliarity:0 IRQF_TRIGGER_RISNG -
+ * poliarty:1
+ */
+ rc = request_threaded_irq(irq, NULL,
+ stmvl53l0_interrupt_handler,
+ IRQF_TRIGGER_FALLING|IRQF_ONESHOT,
+ "vl53l0_interrupt",
+ (void *)data);
+ if (rc) {
+ vl53l0_errmsg(
+"%d, Could not allocate STMVL53L0_INT ! result:%d\n", __LINE__, rc);
+ free_irq(irq, data);
+ goto exit_free_irq;
+ }
+ }
+ data->irq = irq;
+ vl53l0_errmsg("interrupt is hooked\n");
+#else
+
+ init_waitqueue_head(&data->poll_thread_wq);
+
+ data->poll_thread = kthread_run(&stmvl53l0_poll_thread,
+ (void *)data,
+ "STM-VL53L0");
+ if (data->poll_thread == NULL) {
+ pr_err(
+ "%s(%d) - Failed to create Polling thread\n", __func__, __LINE__);
+ goto exit_free_irq;
+ }
+#endif
+
+ /* init work handler */
+ INIT_DELAYED_WORK(&data->dwork, stmvl53l0_work_handler);
+
+ /* Register to Input Device */
+ data->input_dev_ps = input_allocate_device();
+ if (!data->input_dev_ps) {
+ rc = -ENOMEM;
+ vl53l0_errmsg("%d error:%d\n", __LINE__, rc);
+ goto exit_free_irq;
+ }
+ set_bit(EV_ABS, data->input_dev_ps->evbit);
+ /* range in cm*/
+ input_set_abs_params(data->input_dev_ps, ABS_DISTANCE, 0, 76, 0, 0);
+ /* tv_sec */
+ input_set_abs_params(data->input_dev_ps, ABS_HAT0X, 0, 0xffffffff,
+ 0, 0);
+ /* tv_usec */
+ input_set_abs_params(data->input_dev_ps, ABS_HAT0Y, 0, 0xffffffff,
+ 0, 0);
+ /* range in_mm */
+ input_set_abs_params(data->input_dev_ps, ABS_HAT1X, 0, 765, 0, 0);
+ /* error code change maximum to 0xff for more flexibility */
+ input_set_abs_params(data->input_dev_ps, ABS_HAT1Y, 0, 0xff, 0, 0);
+ /* rtnRate */
+ input_set_abs_params(data->input_dev_ps, ABS_HAT2X, 0, 0xffffffff,
+ 0, 0);
+ /* rtn_amb_rate */
+ input_set_abs_params(data->input_dev_ps, ABS_HAT2Y, 0, 0xffffffff,
+ 0, 0);
+ /* rtn_conv_time */
+ input_set_abs_params(data->input_dev_ps, ABS_HAT3X, 0, 0xffffffff,
+ 0, 0);
+ /* dmax */
+ input_set_abs_params(data->input_dev_ps, ABS_HAT3Y, 0, 0xffffffff,
+ 0, 0);
+
+ input_set_abs_params(data->input_dev_ps, ABS_PRESSURE, 0, 0xffffffff,
+ 0, 0);
+
+ input_set_abs_params(data->input_dev_ps, ABS_WHEEL, 0, 0xffffffff,
+ 0, 0);
+
+ input_set_abs_params(data->input_dev_ps, ABS_GAS, 0, 0xffffffff,
+ 0, 0);
+ data->input_dev_ps->name = "STM VL53L0 proximity sensor";
+
+ rc = input_register_device(data->input_dev_ps);
+ if (rc) {
+ rc = -ENOMEM;
+ vl53l0_errmsg("%d error:%d\n", __LINE__, rc);
+ goto exit_free_dev_ps;
+ }
+ /* setup drv data */
+ input_set_drvdata(data->input_dev_ps, data);
+
+ /* Register sysfs hooks */
+ data->range_kobj = kobject_create_and_add("range", kernel_kobj);
+ if (!data->range_kobj) {
+ rc = -ENOMEM;
+ vl53l0_errmsg("%d error:%d\n", __LINE__, rc);
+ goto exit_unregister_dev_ps;
+ }
+ rc = sysfs_create_group(&data->input_dev_ps->dev.kobj,
+ &stmvl53l0_attr_group);
+ if (rc) {
+ rc = -ENOMEM;
+ vl53l0_errmsg("%d error:%d\n", __LINE__, rc);
+ goto exit_unregister_dev_ps_1;
+ }
+
+ setup_timer(&data->timer,
+ stmvl53l0_timer_fn,
+ (unsigned long)data);
+
+ /* to register as a misc device */
+ data->miscdev.minor = MISC_DYNAMIC_MINOR;
+ data->miscdev.name = "stmvl53l0_ranging";
+ data->miscdev.fops = &stmvl53l0_ranging_fops;
+ vl53l0_errmsg("Misc device registration name:%s\n", data->dev_name);
+ if (misc_register(&data->miscdev) != 0)
+ vl53l0_errmsg(
+"Could not register misc. dev for stmvl53l0 ranging\n");
+
+ /* init default device parameter value */
+ data->enable_ps_sensor = 0;
+ data->reset = 1;
+ data->delay_ms = 30; /* delay time to 30ms */
+ data->enableDebug = 0;
+ data->gpio_polarity = VL53L0_INTERRUPTPOLARITY_LOW;
+ data->gpio_function = VL53L0_GPIOFUNCTIONALITY_NEW_MEASURE_READY;
+ data->low_threshold = 60;
+ data->high_threshold = 200;
+ data->deviceMode = VL53L0_DEVICEMODE_SINGLE_RANGING;
+ data->interMeasurems = 30;
+ data->useCase = USE_CASE_LONG_DISTANCE;
+ data->timingBudget = LONG_DISTANCE_TIMING_BUDGET;
+
+ /* Set default values used in Custom Mode Use Case */
+ data->signalRateLimit = LONG_DISTANCE_SIGNAL_RATE_LIMIT;
+ data->sigmaLimit = LONG_DISTANCE_SIGMA_LIMIT;
+ data->preRangePulsePeriod = LONG_DISTANCE_PRE_RANGE_PULSE_PERIOD;
+ data->finalRangePulsePeriod = LONG_DISTANCE_FINAL_RANGE_PULSE_PERIOD;
+
+
+
+
+ vl53l0_dbgmsg("support ver. %s enabled\n", DRIVER_VERSION);
+ vl53l0_dbgmsg("End");
+
+ return 0;
+exit_unregister_dev_ps_1:
+ kobject_put(data->range_kobj);
+exit_unregister_dev_ps:
+ input_unregister_device(data->input_dev_ps);
+exit_free_dev_ps:
+ input_free_device(data->input_dev_ps);
+exit_free_irq:
+#ifdef USE_INT
+ free_irq(irq, data);
+#endif
+ kfree(data);
+ return rc;
+}
+
+void stmvl53l0_cleanup(struct stmvl53l0_data *data)
+{
+#ifndef USE_INT
+ pr_err("%s(%d) : Stop poll_thread\n", __func__, __LINE__);
+ poll_thread_exit = 1;
+ kthread_stop(data->poll_thread);
+#endif
+}
+static int __init stmvl53l0_init(void)
+{
+ int ret = -1;
+
+ vl53l0_dbgmsg("Enter\n");
+
+ /* assign function table */
+ pmodule_func_tbl = &stmvl53l0_module_func_tbl;
+ papi_func_tbl = &stmvl53l0_api_func_tbl;
+
+ /* client specific init function */
+ ret = pmodule_func_tbl->init();
+
+ if (ret)
+ vl53l0_errmsg("%d failed with %d\n", __LINE__, ret);
+
+ vl53l0_dbgmsg("End\n");
+
+ return ret;
+}
+
+static void __exit stmvl53l0_exit(void)
+{
+ vl53l0_dbgmsg("Enter\n");
+
+ vl53l0_dbgmsg("End\n");
+}
+
+
+MODULE_AUTHOR("STMicroelectronics Imaging Division");
+MODULE_DESCRIPTION("ST FlightSense Time-of-Flight sensor driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
+module_init(stmvl53l0_init);
+module_exit(stmvl53l0_exit);
+
diff --git a/drivers/input/sensors/bmi160/Kconfig b/drivers/input/sensors/bmi160/Kconfig
new file mode 100644
index 000000000000..0b1feda156ce
--- /dev/null
+++ b/drivers/input/sensors/bmi160/Kconfig
@@ -0,0 +1,121 @@
+#
+# Makefile for Bosch sensors driver.
+#
+config BOSCH_DRIVER_LOG_FUNC
+ tristate "Bosch Sensortec driver smart log function support"
+ depends on (I2C || SPI_MASTER) && SYSFS
+ help
+ If you say yes here, you get support for smart log function in Bosch Sensortec driver.
+
+config SENSORS_BMA2X2
+ tristate "BMA2x2 acceleration sensor support"
+ depends on I2C
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ acceleration sensors BMA255/BMA254/BMA355/BMA250E/BMA222E/BMA280.
+
+config SENSORS_BMA2X2_ENABLE_INT1
+ tristate "BMA2X2 acceleration sensor interrupt INT1 support"
+ depends on SENSORS_BMA2X2
+ help
+ If you say yes here, you get INT1 support for Bosch Sensortec
+ acceleration sensors BMA255/BMA250E/BMA222E/BMA280.
+ Select it will disable interrupt INT2 support
+
+config SENSORS_BMA2X2_ENABLE_INT2
+ tristate "BMA2X2 acceleration sensor interrupt INT2 support"
+ depends on SENSORS_BMA2X2 && !SENSORS_BMA2X2_ENABLE_INT1
+ help
+ If you say yes here, you get INT2 support for Bosch Sensortec
+ acceleration sensors BMA255/BMA250E/BMA222E/BMA280.
+ Can only open if you do NOT open interrupt INT1 support
+
+config SIG_MOTION
+ tristate "support significant motion sensor function"
+ depends on SENSORS_BMA2X2 && ( SENSORS_BMA2X2_ENABLE_INT1 || SENSORS_BMA2X2_ENABLE_INT2)
+ help
+ If you say yes here, if you want to support Bosch significant motion sensor function
+
+config DOUBLE_TAP
+ tristate "support double tap sensor function"
+ depends on SENSORS_BMA2X2 && ( SENSORS_BMA2X2_ENABLE_INT1 || SENSORS_BMA2X2_ENABLE_INT2)
+ help
+ If you say yes here, you get support Bosch double tap sensor function
+
+config SENSORS_BMG
+ tristate "Bosch Gyroscope Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ gyroscope sensor drivers of BMG160/BMI055/BMI058 e.t.c.
+
+config SENSORS_BMG_FIFO
+ tristate "Bosch Gyroscope FIFO Support"
+ depends on SENSORS_BMG
+ help
+ If you say yes here, you get support for Gyroscope sensor FIFO operations.
+ Please check whether the chip supports fifo feature to open it.
+
+config SENSORS_BMI058
+ tristate "BMI058 Sensor Support"
+ depends on (SENSORS_BMG || SENSORS_BMA2X2)
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ sensor driver of BMI058.
+
+config SENSORS_YAS537
+ tristate "YAS537 Magnetic Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support for YAMAHA
+ sensor YAS537 Magnetic Sensor
+
+config SENSORS_BMM050
+ tristate "BMM050 Magnetic Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ sensor BMM050 Magnetic Sensor
+
+config SENSORS_AKM09911
+ tristate "AKM09911 Mag Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support AKM09911 Sensor support.
+
+config SENSORS_AKM09912
+ tristate "AKM09912 Mag Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support AKM09912 Sensor support.
+
+config SENSORS_BMA420
+ tristate "BMA4XY Sensor Support"
+ depends on I2C || SPI_MASTER
+ help
+ If you say yes here, you get support for Bosch Sensortec's sensor driver of BMA420.
+config SENSORS_BMA421
+ tristate "BMA4XY Sensor Support"
+ depends on I2C || SPI_MASTER
+ help
+ If you say yes here, you get support for Bosch Sensortec's sensor driver of BMA421.
+config SENSORS_BMA422
+ tristate "BMA4XY Sensor Support"
+ depends on I2C || SPI_MASTER
+ help
+ If you say yes here, you get support for Bosch Sensortec's sensor driver of BMA422.
+config SENSORS_BMA455
+ tristate "BMA4XY Sensor Support"
+ depends on I2C || SPI_MASTER
+ help
+ If you say yes here, you get support for Bosch Sensortec's sensor driver of BMA455.
+
+config BMA4XY_MAG_INTERFACE_SUPPORT
+tristate "BMA4XY Sensor mag interface support"
+depends on SENSORS_BMA4XY
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ sensor driver of BMA4XY with mag sensor support.
+
+
+
diff --git a/drivers/input/sensors/bmi160/Makefile b/drivers/input/sensors/bmi160/Makefile
new file mode 100644
index 000000000000..0a9bb56744ab
--- /dev/null
+++ b/drivers/input/sensors/bmi160/Makefile
@@ -0,0 +1,41 @@
+#
+# Makefile for Bosch sensor driver.
+#
+
+obj-$(CONFIG_BOSCH_DRIVER_LOG_FUNC) += bs_log.o
+obj-y += bstclass.o
+ifeq ($(CONFIG_BOSCH_DRIVER_LOG_FUNC),y)
+ EXTRA_CFLAGS += -DBOSCH_DRIVER_LOG_FUNC
+endif
+
+#obj-y += bma2x2.o
+
+ifeq ($(CONFIG_SENSORS_BMA2X2_ENABLE_INT1),y)
+ EXTRA_CFLAGS += -DBMA2X2_ENABLE_INT1
+endif
+
+ifeq ($(CONFIG_BOSCH_BMA2X2_ENABLE_INT2),y)
+ EXTRA_CFLAGS += -DBMA2X2_ENABLE_INT2
+endif
+
+#obj-y += bmg160_driver.o bmg160.o
+EXTRA_CFLAGS += -DBMG_USE_BASIC_I2C_FUNC
+
+obj-y += bmi160_driver.o bmi160.o
+ifeq ($(CONFIG_BMI160_MAG_INTERFACE_SUPPORT),y)
+ EXTRA_CFLAGS += -DBMI160_MAG_INTERFACE_SUPPORT
+endif
+ifeq ($(CONFIG_SENSORS_BMI160_ENABLE_INT1),y)
+ EXTRA_CFLAGS += -DBMI160_ENABLE_INT1
+endif
+
+ifeq ($(CONFIG_SENSORS_BMI160_ENABLE_INT2),y)
+ EXTRA_CFLAGS += -DBMI160_ENABLE_INT2
+endif
+
+obj-y += bmi160_i2c.o
+
+EXTRA_CFLAGS += -DBMI_USE_BASIC_I2C_FUNC
+
+obj-$(CONFIG_SENSORS_BMI160_SPI) += bmi160_spi.o
+
diff --git a/drivers/input/sensors/bmi160/bmi160.c b/drivers/input/sensors/bmi160/bmi160.c
new file mode 100644
index 000000000000..071f7e3fcc47
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bmi160.c
@@ -0,0 +1,18753 @@
+/*
+* @section LICENSE
+* (C) Copyright 2011~2018 Bosch Sensortec GmbH All Rights Reserved
+*
+* This software program is licensed subject to the GNU General
+* Public License (GPL).Version 2,June 1991,
+* available at http://www.fsf.org/copyleft/gpl.html
+
+*
+* @filename bmi160.c
+* @Date: 2015/04/02
+* @id 836294d
+* @Revision: 2.0.9 $
+*
+* Usage: Sensor Driver for BMI160 sensor
+*
+****************************************************************************
+* \section Disclaimer
+*
+* Common:
+* Bosch Sensortec products are developed for the consumer goods industry.
+* They may only be used within the parameters of the respective valid
+* product data sheet. Bosch Sensortec products are provided with the
+* express understanding that there is no warranty of fitness for a
+* particular purpose.They are not fit for use in life-sustaining,
+* safety or security sensitive systems or any system or device
+* that may lead to bodily harm or property damage if the system
+* or device malfunctions. In addition,Bosch Sensortec products are
+* not fit for use in products which interact with motor vehicle systems.
+* The resale and or use of products are at the purchasers own risk and
+* his own responsibility. The examination of fitness for the intended use
+* is the sole responsibility of the Purchaser.
+*
+* The purchaser shall indemnify Bosch Sensortec from all third party
+* claims, including any claims for incidental, or consequential damages,
+* arising from any product use not covered by the parameters of
+* the respective valid product data sheet or not approved by
+* Bosch Sensortec and reimburse Bosch Sensortec for all costs in
+* connection with such claims.
+*
+* The purchaser must monitor the market for the purchased products,
+* particularly with regard to product safety and inform Bosch Sensortec
+* without delay of all security relevant incidents.
+*
+* Engineering Samples are marked with an asterisk (*) or (e).
+* Samples may vary from the valid technical specifications of the product
+* series. They are therefore not intended or fit for resale to third
+* parties or for use in end products. Their sole purpose is internal
+* client testing. The testing of an engineering sample may in no way
+* replace the testing of a product series. Bosch Sensortec assumes
+* no liability for the use of engineering samples.
+* By accepting the engineering samples, the Purchaser agrees to indemnify
+* Bosch Sensortec from all claims arising from the use of engineering
+* samples.
+*
+* Special:
+* This software module (hereinafter called "Software") and any information
+* on application-sheets (hereinafter called "Information") is provided
+* free of charge for the sole purpose to support your application work.
+* The Software and Information is subject to the following
+* terms and conditions:
+*
+* The Software is specifically designed for the exclusive use for
+* Bosch Sensortec products by personnel who have special experience
+* and training. Do not use this Software if you do not have the
+* proper experience or training.
+*
+* This Software package is provided `` as is `` and without any expressed
+* or implied warranties,including without limitation, the implied warranties
+* of merchantability and fitness for a particular purpose.
+*
+* Bosch Sensortec and their representatives and agents deny any liability
+* for the functional impairment
+* of this Software in terms of fitness, performance and safety.
+* Bosch Sensortec and their representatives and agents shall not be liable
+* for any direct or indirect damages or injury, except as
+* otherwise stipulated in mandatory applicable law.
+*
+* The Information provided is believed to be accurate and reliable.
+* Bosch Sensortec assumes no responsibility for the consequences of use
+* of such Information nor for any infringement of patents or
+* other rights of third parties which may result from its use.
+* No license is granted by implication or otherwise under any patent or
+* patent rights of Bosch. Specifications mentioned in the Information are
+* subject to change without notice.
+**************************************************************************/
+/*! file <BMI160 >
+ brief <Sensor driver for BMI160> */
+#include "bmi160.h"
+#include <linux/kernel.h>
+
+/* user defined code to be added here ... */
+struct bmi160_t *p_bmi160;
+/* used for reading the mag trim values for compensation*/
+struct trim_data_t mag_trim;
+/* the following variable used for avoiding the selecting of auto mode
+when it is running in the manual mode of BMM150 mag interface*/
+u8 V_bmm150_maual_auto_condition_u8 = BMI160_INIT_VALUE;
+/* used for reading the AKM compensating data */
+struct bst_akm_sensitivity_data_t akm_asa_data;
+/* Assign the fifo time */
+u32 V_fifo_time_U32 = BMI160_INIT_VALUE;
+
+/* FIFO data read for 1024 bytes of data */
+u8 v_fifo_data_u8[FIFO_FRAME] = {BMI160_INIT_VALUE};
+/* YAMAHA-YAS532*/
+/* value of coeff*/
+static const int yas532_version_ac_coef[] = {YAS532_VERSION_AC_COEF_X,
+YAS532_VERSION_AC_COEF_Y1, YAS532_VERSION_AC_COEF_Y2};
+/* used for reading the yas532 calibration data*/
+struct yas532_t yas532_data;
+/* used for reading the yas537 calibration data*/
+struct yas537_t yas537_data;
+/*!
+ * @brief
+ * This function is used for initialize
+ * bus read and bus write functions
+ * assign the chip id and device address
+ * chip id is read in the register 0x00 bit from 0 to 7
+ *
+ * @param bmi160 : structure pointer
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * While changing the parameter of the bmi160_t
+ * consider the following point:
+ * Changing the reference value of the parameter
+ * will changes the local copy or local reference
+ * make sure your changes will not
+ * affect the reference value of the parameter
+ * (Better case don't change the reference value of the parameter)
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_init(struct bmi160_t *bmi160)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ u8 v_pmu_data_u8 = BMI160_INIT_VALUE;
+ /* assign bmi160 ptr */
+ p_bmi160 = bmi160;
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_CHIP_ID__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* read Chip Id */
+ p_bmi160->chip_id = v_data_u8;
+ /* To avoid gyro wakeup it is required to write 0x00 to 0x6C*/
+ com_rslt += bmi160_write_reg(BMI160_USER_PMU_TRIGGER_ADDR,
+ &v_pmu_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ return com_rslt;
+}
+/*!
+ * @brief
+ * This API write the data to
+ * the given register
+ *
+ *
+ * @param v_addr_u8 -> Address of the register
+ * @param v_data_u8 -> The data from the register
+ * @param v_len_u8 -> no of bytes to read
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_write_reg(u8 v_addr_u8,
+u8 *v_data_u8, u8 v_len_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write data from register*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->dev_addr,
+ v_addr_u8, v_data_u8, v_len_u8);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief
+ * This API reads the data from
+ * the given register
+ *
+ *
+ * @param v_addr_u8 -> Address of the register
+ * @param v_data_u8 -> The data from the register
+ * @param v_len_u8 -> no of bytes to read
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_reg(u8 v_addr_u8,
+u8 *v_data_u8, u8 v_len_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* Read data from register*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ v_addr_u8, v_data_u8, v_len_u8);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API used to reads the fatal error
+ * from the Register 0x02 bit 0
+ * This flag will be reset only by power-on-reset and soft reset
+ *
+ *
+ * @param v_fatal_err_u8 : The status of fatal error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fatal_err(u8
+*v_fatal_err_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* reading the fatal error status*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FATAL_ERR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fatal_err_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FATAL_ERR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API used to read the error code
+ * from register 0x02 bit 1 to 4
+ *
+ *
+ * @param v_err_code_u8 : The status of error codes
+ * error_code | description
+ * ------------|---------------
+ * 0x00 |no error
+ * 0x01 |ACC_CONF error (accel ODR and bandwidth not compatible)
+ * 0x02 |GYR_CONF error (Gyroscope ODR and bandwidth not compatible)
+ * 0x03 |Under sampling mode and interrupt uses pre filtered data
+ * 0x04 |reserved
+ * 0x05 |Selected trigger-readout offset in
+ * - |MAG_IF greater than selected ODR
+ * 0x06 |FIFO configuration error for header less mode
+ * 0x07 |Under sampling mode and pre filtered data as FIFO source
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_err_code(u8
+*v_err_code_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ERR_CODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_err_code_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_ERR_CODE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API Reads the i2c error code from the
+ * Register 0x02 bit 5.
+ * This error occurred in I2C master detected
+ *
+ * @param v_i2c_err_code_u8 : The status of i2c fail error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_i2c_fail_err(u8
+*v_i2c_err_code_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_I2C_FAIL_ERR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_i2c_err_code_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_I2C_FAIL_ERR);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API Reads the dropped command error
+ * from the register 0x02 bit 6
+ *
+ *
+ * @param v_drop_cmd_err_u8 : The status of drop command error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_drop_cmd_err(u8
+*v_drop_cmd_err_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_DROP_CMD_ERR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_drop_cmd_err_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_DROP_CMD_ERR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the magnetometer data ready
+ * interrupt not active.
+ * It reads from the error register 0x0x2 bit 7
+ *
+ *
+ *
+ *
+ * @param v_mag_data_rdy_err_u8 : The status of mag data ready interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_dada_rdy_err(
+u8 *v_mag_data_rdy_err_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_MAG_DADA_RDY_ERR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_data_rdy_err_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_DADA_RDY_ERR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the error status
+ * from the error register 0x02 bit 0 to 7
+ *
+ * @param v_mag_data_rdy_err_u8 : The status of mag data ready interrupt
+ * @param v_fatal_er_u8r : The status of fatal error
+ * @param v_err_code_u8 : The status of error code
+ * @param v_i2c_fail_err_u8 : The status of I2C fail error
+ * @param v_drop_cmd_err_u8 : The status of drop command error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_error_status(u8 *v_fatal_er_u8r,
+u8 *v_err_code_u8, u8 *v_i2c_fail_err_u8,
+u8 *v_drop_cmd_err_u8, u8 *v_mag_data_rdy_err_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the error codes*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ERR_STAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* fatal error*/
+ *v_fatal_er_u8r =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FATAL_ERR);
+ /* user error*/
+ *v_err_code_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_ERR_CODE);
+ /* i2c fail error*/
+ *v_i2c_fail_err_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_I2C_FAIL_ERR);
+ /* drop command error*/
+ *v_drop_cmd_err_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_DROP_CMD_ERR);
+ /* mag data ready error*/
+ *v_mag_data_rdy_err_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_DADA_RDY_ERR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the magnetometer power mode from
+ * PMU status register 0x03 bit 0 and 1
+ *
+ * @param v_mag_power_mode_stat_u8 : The value of mag power mode
+ * mag_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * LOW POWER | 0x02
+ *
+ *
+ * @note The power mode of mag set by the 0x7E command register
+ * @note using the function "bmi160_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x18 | MAG_MODE_SUSPEND
+ * 0x19 | MAG_MODE_NORMAL
+ * 0x1A | MAG_MODE_LOWPOWER
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_power_mode_stat(u8
+*v_mag_power_mode_stat_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_POWER_MODE_STAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_power_mode_stat_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_POWER_MODE_STAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the gyroscope power mode from
+ * PMU status register 0x03 bit 2 and 3
+ *
+ * @param v_gyro_power_mode_stat_u8 : The value of gyro power mode
+ * gyro_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * FAST POWER UP | 0x03
+ *
+ * @note The power mode of gyro set by the 0x7E command register
+ * @note using the function "bmi160_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x14 | GYRO_MODE_SUSPEND
+ * 0x15 | GYRO_MODE_NORMAL
+ * 0x17 | GYRO_MODE_FASTSTARTUP
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_power_mode_stat(u8
+*v_gyro_power_mode_stat_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_GYRO_POWER_MODE_STAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_power_mode_stat_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_POWER_MODE_STAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the accelerometer power mode from
+ * PMU status register 0x03 bit 4 and 5
+ *
+ *
+ * @param v_accel_power_mode_stat_u8 : The value of accel power mode
+ * accel_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * LOW POWER | 0x02
+ *
+ * @note The power mode of accel set by the 0x7E command register
+ * @note using the function "bmi160_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x11 | ACCEL_MODE_NORMAL
+ * 0x12 | ACCEL_LOWPOWER
+ * 0x10 | ACCEL_SUSPEND
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_power_mode_stat(u8
+*v_accel_power_mode_stat_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_POWER_MODE_STAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_power_mode_stat_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_POWER_MODE_STAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API switch mag interface to normal mode
+ * and confirm whether the mode switching done successfully or not
+*
+ * @return results of bus communication function and current MAG_PMU result
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_interface_normal(void)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = BMI160_INIT_VALUE;
+ /* aim to check the result of switching mag normal */
+ u8 v_try_times_u8 = BMI160_MAG_NOAMRL_SWITCH_TIMES;
+ u8 v_mag_pum_status_u8 = BMI160_INIT_VALUE;
+
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt = bmi160_set_command_register(MAG_MODE_NORMAL);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ while (v_try_times_u8) {
+ com_rslt = bmi160_get_mag_power_mode_stat(&v_mag_pum_status_u8);
+ if (v_mag_pum_status_u8 == MAG_INTERFACE_PMU_ENABLE)
+ break;
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ v_try_times_u8--;
+ }
+ if (v_mag_pum_status_u8 == MAG_INTERFACE_PMU_ENABLE)
+ com_rslt += SUCCESS;
+ else
+ com_rslt += E_BMI160_COMM_RES;
+
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data X values
+ * from the register 0x04 and 0x05
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_x_s16 : The value of mag x
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_x(s16 *v_mag_x_s16,
+u8 v_sensor_select_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the mag X lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[BMI160_MAG_X_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_sensor_select_u8) {
+ case BST_BMM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_DATA_MAG_X_LSB__REG,
+ v_data_u8, BMI160_MAG_X_DATA_LENGTH);
+ /* X axis*/
+ v_data_u8[BMI160_MAG_X_LSB_BYTE] =
+ BMI160_GET_BITSLICE(v_data_u8[BMI160_MAG_X_LSB_BYTE],
+ BMI160_USER_DATA_MAG_X_LSB);
+ *v_mag_x_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_MAG_X_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_05_BITS) |
+ (v_data_u8[BMI160_MAG_X_LSB_BYTE]));
+ break;
+ case BST_AKM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_0_MAG_X_LSB__REG,
+ v_data_u8, BMI160_MAG_X_DATA_LENGTH);
+ *v_mag_x_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_MAG_X_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_MAG_X_LSB_BYTE]));
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data Y values
+ * from the register 0x06 and 0x07
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_y_s16 : The value of mag y
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_y(s16 *v_mag_y_s16,
+u8 v_sensor_select_u8)
+{
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_OUT_OF_RANGE;
+ /* Array contains the mag Y lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[BMI160_MAG_Y_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_sensor_select_u8) {
+ case BST_BMM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_DATA_MAG_Y_LSB__REG,
+ v_data_u8, BMI160_MAG_Y_DATA_LENGTH);
+ /*Y-axis lsb value shifting*/
+ v_data_u8[BMI160_MAG_Y_LSB_BYTE] =
+ BMI160_GET_BITSLICE(v_data_u8[BMI160_MAG_Y_LSB_BYTE],
+ BMI160_USER_DATA_MAG_Y_LSB);
+ *v_mag_y_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_MAG_Y_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_05_BITS) |
+ (v_data_u8[BMI160_MAG_Y_LSB_BYTE]));
+ break;
+ case BST_AKM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_DATA_2_MAG_Y_LSB__REG,
+ v_data_u8, BMI160_MAG_Y_DATA_LENGTH);
+ *v_mag_y_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_MAG_Y_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_MAG_Y_LSB_BYTE]));
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data Z values
+ * from the register 0x08 and 0x09
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_z_s16 : The value of mag z
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_z(s16 *v_mag_z_s16,
+u8 v_sensor_select_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the mag Z lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[BMI160_MAG_Z_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_sensor_select_u8) {
+ case BST_BMM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_DATA_MAG_Z_LSB__REG,
+ v_data_u8, BMI160_MAG_Z_DATA_LENGTH);
+ /*Z-axis lsb value shifting*/
+ v_data_u8[BMI160_MAG_Z_LSB_BYTE] =
+ BMI160_GET_BITSLICE(v_data_u8[BMI160_MAG_Z_LSB_BYTE],
+ BMI160_USER_DATA_MAG_Z_LSB);
+ *v_mag_z_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_MAG_Z_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_07_BITS) |
+ (v_data_u8[BMI160_MAG_Z_LSB_BYTE]));
+ break;
+ case BST_AKM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_DATA_4_MAG_Z_LSB__REG,
+ v_data_u8, BMI160_MAG_Z_DATA_LENGTH);
+ *v_mag_z_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_MAG_Z_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | (
+ v_data_u8[BMI160_MAG_Z_LSB_BYTE]));
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data RHALL values
+ * from the register 0x0A and 0x0B
+ *
+ *
+ * @param v_mag_r_s16 : The value of BMM150 r data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_r(s16 *v_mag_r_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the mag R lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[BMI160_MAG_R_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_6_RHALL_LSB__REG,
+ v_data_u8, BMI160_MAG_R_DATA_LENGTH);
+ /*R-axis lsb value shifting*/
+ v_data_u8[BMI160_MAG_R_LSB_BYTE] =
+ BMI160_GET_BITSLICE(v_data_u8[BMI160_MAG_R_LSB_BYTE],
+ BMI160_USER_DATA_MAG_R_LSB);
+ *v_mag_r_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_MAG_R_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_06_BITS) |
+ (v_data_u8[BMI160_MAG_R_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data X,Y,Z values
+ * from the register 0x04 to 0x09
+ *
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param mag : The value of mag xyz data
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_xyz(
+struct bmi160_mag_t *mag, u8 v_sensor_select_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the mag XYZ lSB and MSB data
+ v_data_u8[0] - X-LSB
+ v_data_u8[1] - X-MSB
+ v_data_u8[0] - Y-LSB
+ v_data_u8[1] - Y-MSB
+ v_data_u8[0] - Z-LSB
+ v_data_u8[1] - Z-MSB
+ */
+ u8 v_data_u8[BMI160_MAG_XYZ_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_sensor_select_u8) {
+ case BST_BMM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_DATA_MAG_X_LSB__REG,
+ v_data_u8, BMI160_MAG_XYZ_DATA_LENGTH);
+ /*X-axis lsb value shifting*/
+ v_data_u8[BMI160_DATA_FRAME_MAG_X_LSB_BYTE] =
+ BMI160_GET_BITSLICE(
+ v_data_u8[BMI160_DATA_FRAME_MAG_X_LSB_BYTE],
+ BMI160_USER_DATA_MAG_X_LSB);
+ /* Data X */
+ mag->x = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_X_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_05_BITS) |
+ (v_data_u8[BMI160_DATA_FRAME_MAG_X_LSB_BYTE]));
+ /* Data Y */
+ /*Y-axis lsb value shifting*/
+ v_data_u8[BMI160_DATA_FRAME_MAG_Y_LSB_BYTE] =
+ BMI160_GET_BITSLICE(
+ v_data_u8[BMI160_DATA_FRAME_MAG_Y_LSB_BYTE],
+ BMI160_USER_DATA_MAG_Y_LSB);
+ mag->y = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_Y_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_05_BITS) |
+ (v_data_u8[BMI160_DATA_FRAME_MAG_Y_LSB_BYTE]));
+
+ /* Data Z */
+ /*Z-axis lsb value shifting*/
+ v_data_u8[BMI160_DATA_FRAME_MAG_Z_LSB_BYTE]
+ = BMI160_GET_BITSLICE(
+ v_data_u8[BMI160_DATA_FRAME_MAG_Z_LSB_BYTE],
+ BMI160_USER_DATA_MAG_Z_LSB);
+ mag->z = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_Z_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_07_BITS) |
+ (v_data_u8[BMI160_DATA_FRAME_MAG_Z_LSB_BYTE]));
+ break;
+ case BST_AKM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_0_MAG_X_LSB__REG,
+ v_data_u8, BMI160_MAG_XYZ_DATA_LENGTH);
+ /* Data X */
+ mag->x = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_X_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_DATA_FRAME_MAG_X_LSB_BYTE]));
+ /* Data Y */
+ mag->y = ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_Y_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_DATA_FRAME_MAG_Y_LSB_BYTE]));
+ /* Data Z */
+ mag->z = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_Z_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_DATA_FRAME_MAG_Z_LSB_BYTE]));
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!*
+ * @brief This API reads magnetometer data X,Y,Z,r
+ * values from the register 0x04 to 0x0B
+ *
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param mag : The value of mag-BMM150 xyzr data
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_xyzr(
+struct bmi160_mag_xyzr_t *mag)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8[BMI160_MAG_XYZR_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_MAG_X_LSB__REG,
+ v_data_u8, BMI160_MAG_XYZR_DATA_LENGTH);
+
+ /* Data X */
+ /*X-axis lsb value shifting*/
+ v_data_u8[BMI160_DATA_FRAME_MAG_X_LSB_BYTE]
+ = BMI160_GET_BITSLICE(
+ v_data_u8[BMI160_DATA_FRAME_MAG_X_LSB_BYTE],
+ BMI160_USER_DATA_MAG_X_LSB);
+ mag->x = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_X_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_05_BITS)
+ | (v_data_u8[BMI160_DATA_FRAME_MAG_X_LSB_BYTE]));
+ /* Data Y */
+ /*Y-axis lsb value shifting*/
+ v_data_u8[BMI160_DATA_FRAME_MAG_Y_LSB_BYTE]
+ = BMI160_GET_BITSLICE(
+ v_data_u8[BMI160_DATA_FRAME_MAG_Y_LSB_BYTE],
+ BMI160_USER_DATA_MAG_Y_LSB);
+ mag->y = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_Y_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_05_BITS)
+ | (v_data_u8[
+ BMI160_DATA_FRAME_MAG_Y_LSB_BYTE]));
+
+ /* Data Z */
+ /*Z-axis lsb value shifting*/
+ v_data_u8[BMI160_DATA_FRAME_MAG_Z_LSB_BYTE]
+ = BMI160_GET_BITSLICE(
+ v_data_u8[BMI160_DATA_FRAME_MAG_Z_LSB_BYTE],
+ BMI160_USER_DATA_MAG_Z_LSB);
+ mag->z = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_Z_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_07_BITS)
+ | (v_data_u8[BMI160_DATA_FRAME_MAG_Z_LSB_BYTE]));
+
+ /* RHall */
+ /*R-axis lsb value shifting*/
+ v_data_u8[BMI160_DATA_FRAME_MAG_R_LSB_BYTE]
+ = BMI160_GET_BITSLICE(
+ v_data_u8[BMI160_DATA_FRAME_MAG_R_LSB_BYTE],
+ BMI160_USER_DATA_MAG_R_LSB);
+ mag->r = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_MAG_R_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_06_BITS)
+ | (v_data_u8[BMI160_DATA_FRAME_MAG_R_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads gyro data X values
+ * form the register 0x0C and 0x0D
+ *
+ *
+ *
+ *
+ * @param v_gyro_x_s16 : The value of gyro x data
+ *
+ * @note Gyro Configuration use the following function
+ * @note bmi160_set_gyro_output_data_rate()
+ * @note bmi160_set_gyro_bw()
+ * @note bmi160_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_gyro_x(s16 *v_gyro_x_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the gyro X lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[MSB_ONE] - MSB*/
+ u8 v_data_u8[BMI160_GYRO_X_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_8_GYRO_X_LSB__REG,
+ v_data_u8, BMI160_GYRO_DATA_LENGTH);
+
+ *v_gyro_x_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_GYRO_X_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[BMI160_GYRO_X_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads gyro data Y values
+ * form the register 0x0E and 0x0F
+ *
+ *
+ *
+ *
+ * @param v_gyro_y_s16 : The value of gyro y data
+ *
+ * @note Gyro Configuration use the following function
+ * @note bmi160_set_gyro_output_data_rate()
+ * @note bmi160_set_gyro_bw()
+ * @note bmi160_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error result of communication routines
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_gyro_y(s16 *v_gyro_y_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the gyro Y lSB and MSB data
+ v_data_u8[LSB_ZERO] - LSB
+ v_data_u8[MSB_ONE] - MSB*/
+ u8 v_data_u8[BMI160_GYRO_Y_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro y data*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_10_GYRO_Y_LSB__REG,
+ v_data_u8, BMI160_GYRO_DATA_LENGTH);
+
+ *v_gyro_y_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_GYRO_Y_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[BMI160_GYRO_Y_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads gyro data Z values
+ * form the register 0x10 and 0x11
+ *
+ *
+ *
+ *
+ * @param v_gyro_z_s16 : The value of gyro z data
+ *
+ * @note Gyro Configuration use the following function
+ * @note bmi160_set_gyro_output_data_rate()
+ * @note bmi160_set_gyro_bw()
+ * @note bmi160_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_gyro_z(s16 *v_gyro_z_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the gyro Z lSB and MSB data
+ v_data_u8[LSB_ZERO] - LSB
+ v_data_u8[MSB_ONE] - MSB*/
+ u8 v_data_u8[BMI160_GYRO_Z_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro z data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_12_GYRO_Z_LSB__REG,
+ v_data_u8, BMI160_GYRO_DATA_LENGTH);
+
+ *v_gyro_z_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_GYRO_Z_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[BMI160_GYRO_Z_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads gyro data X,Y,Z values
+ * from the register 0x0C to 0x11
+ *
+ *
+ *
+ *
+ * @param gyro : The value of gyro xyz
+ *
+ * @note Gyro Configuration use the following function
+ * @note bmi160_set_gyro_output_data_rate()
+ * @note bmi160_set_gyro_bw()
+ * @note bmi160_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_gyro_xyz(struct bmi160_gyro_t *gyro)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the mag XYZ lSB and MSB data
+ v_data_u8[0] - X-LSB
+ v_data_u8[1] - X-MSB
+ v_data_u8[0] - Y-LSB
+ v_data_u8[1] - Y-MSB
+ v_data_u8[0] - Z-LSB
+ v_data_u8[1] - Z-MSB
+ */
+ u8 v_data_u8[BMI160_GYRO_XYZ_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the gyro xyz data*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_8_GYRO_X_LSB__REG,
+ v_data_u8, BMI160_GYRO_XYZ_DATA_LENGTH);
+
+ /* Data X */
+ gyro->x = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_GYRO_X_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[BMI160_DATA_FRAME_GYRO_X_LSB_BYTE]));
+ /* Data Y */
+ gyro->y = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_GYRO_Y_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[BMI160_DATA_FRAME_GYRO_Y_LSB_BYTE]));
+
+ /* Data Z */
+ gyro->z = (s16)
+ ((((s32)((s8)v_data_u8[
+ BMI160_DATA_FRAME_GYRO_Z_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[BMI160_DATA_FRAME_GYRO_Z_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads accelerometer data X values
+ * form the register 0x12 and 0x13
+ *
+ *
+ *
+ *
+ * @param v_accel_x_s16 : The value of accel x
+ *
+ * @note For accel configuration use the following functions
+ * @note bmi160_set_accel_output_data_rate()
+ * @note bmi160_set_accel_bw()
+ * @note bmi160_set_accel_under_sampling_parameter()
+ * @note bmi160_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_accel_x(s16 *v_accel_x_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the accel X lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[BMI160_ACCEL_X_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_14_ACCEL_X_LSB__REG,
+ v_data_u8, BMI160_ACCEL_DATA_LENGTH);
+
+ *v_accel_x_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_ACCEL_X_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[BMI160_ACCEL_X_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads accelerometer data Y values
+ * form the register 0x14 and 0x15
+ *
+ *
+ *
+ *
+ * @param v_accel_y_s16 : The value of accel y
+ *
+ * @note For accel configuration use the following functions
+ * @note bmi160_set_accel_output_data_rate()
+ * @note bmi160_set_accel_bw()
+ * @note bmi160_set_accel_under_sampling_parameter()
+ * @note bmi160_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_accel_y(s16 *v_accel_y_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the accel Y lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[BMI160_ACCEL_Y_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_16_ACCEL_Y_LSB__REG,
+ v_data_u8, BMI160_ACCEL_DATA_LENGTH);
+
+ *v_accel_y_s16 = (s16)
+ ((((s32)((s8)v_data_u8[BMI160_ACCEL_Y_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[BMI160_ACCEL_Y_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads accelerometer data Z values
+ * form the register 0x16 and 0x17
+ *
+ *
+ *
+ *
+ * @param v_accel_z_s16 : The value of accel z
+ *
+ * @note For accel configuration use the following functions
+ * @note bmi160_set_accel_output_data_rate()
+ * @note bmi160_set_accel_bw()
+ * @note bmi160_set_accel_under_sampling_parameter()
+ * @note bmi160_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_accel_z(s16 *v_accel_z_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the accel Z lSB and MSB data
+ a_data_u8r[LSB_ZERO] - LSB
+ a_data_u8r[MSB_ONE] - MSB*/
+ u8 a_data_u8r[BMI160_ACCEL_Z_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_18_ACCEL_Z_LSB__REG,
+ a_data_u8r, BMI160_ACCEL_DATA_LENGTH);
+
+ *v_accel_z_s16 = (s16)
+ ((((s32)((s8)a_data_u8r[BMI160_ACCEL_Z_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[BMI160_ACCEL_Z_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads accelerometer data X,Y,Z values
+ * from the register 0x12 to 0x17
+ *
+ *
+ *
+ *
+ * @param accel :The value of accel xyz
+ *
+ * @note For accel configuration use the following functions
+ * @note bmi160_set_accel_output_data_rate()
+ * @note bmi160_set_accel_bw()
+ * @note bmi160_set_accel_under_sampling_parameter()
+ * @note bmi160_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_accel_xyz(
+struct bmi160_accel_t *accel)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the accel XYZ lSB and MSB data
+ a_data_u8r[0] - X-LSB
+ a_data_u8r[1] - X-MSB
+ a_data_u8r[0] - Y-LSB
+ a_data_u8r[1] - Y-MSB
+ a_data_u8r[0] - Z-LSB
+ a_data_u8r[1] - Z-MSB
+ */
+ u8 a_data_u8r[BMI160_ACCEL_XYZ_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_14_ACCEL_X_LSB__REG,
+ a_data_u8r, BMI160_ACCEL_XYZ_DATA_LENGTH);
+
+ /* Data X */
+ accel->x = (s16)
+ ((((s32)((s8)a_data_u8r[
+ BMI160_DATA_FRAME_ACCEL_X_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[BMI160_DATA_FRAME_ACCEL_X_LSB_BYTE]));
+ /* Data Y */
+ accel->y = (s16)
+ ((((s32)((s8)a_data_u8r[
+ BMI160_DATA_FRAME_ACCEL_Y_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[BMI160_DATA_FRAME_ACCEL_Y_LSB_BYTE]));
+
+ /* Data Z */
+ accel->z = (s16)
+ ((((s32)((s8)a_data_u8r[
+ BMI160_DATA_FRAME_ACCEL_Z_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[BMI160_DATA_FRAME_ACCEL_Z_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads sensor_time from the register
+ * 0x18 to 0x1A
+ *
+ *
+ * @param v_sensor_time_u32 : The value of sensor time
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_sensor_time(u32 *v_sensor_time_u32)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the sensor time it is 32 bit data
+ a_data_u8r[0] - sensor time
+ a_data_u8r[1] - sensor time
+ a_data_u8r[0] - sensor time
+ */
+ u8 a_data_u8r[BMI160_SENSOR_TIME_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_SENSORTIME_0_SENSOR_TIME_LSB__REG,
+ a_data_u8r, BMI160_SENSOR_TIME_LENGTH);
+
+ *v_sensor_time_u32 = (u32)
+ ((((u32)a_data_u8r[BMI160_SENSOR_TIME_MSB_BYTE])
+ << BMI160_SHIFT_BIT_POSITION_BY_16_BITS)
+ |(((u32)a_data_u8r[BMI160_SENSOR_TIME_XLSB_BYTE])
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[BMI160_SENSOR_TIME_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the Gyroscope self test
+ * status from the register 0x1B bit 1
+ *
+ *
+ * @param v_gyro_selftest_u8 : The value of gyro self test status
+ * value | status
+ * ---------|----------------
+ * 0 | Gyroscope self test is running or failed
+ * 1 | Gyroscope self test completed successfully
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_selftest(u8
+*v_gyro_selftest_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STAT_GYRO_SELFTEST_OK__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_selftest_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_STAT_GYRO_SELFTEST_OK);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of
+ * mag manual interface operation form the register 0x1B bit 2
+ *
+ *
+ *
+ * @param v_mag_manual_stat_u8 : The value of mag manual operation status
+ * value | status
+ * ---------|----------------
+ * 0 | Indicates no manual magnetometer
+ * - | interface operation is ongoing
+ * 1 | Indicates manual magnetometer
+ * - | interface operation is ongoing
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_manual_operation_stat(u8
+*v_mag_manual_stat_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read manual operation*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STAT_MAG_MANUAL_OPERATION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_manual_stat_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_STAT_MAG_MANUAL_OPERATION);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the fast offset compensation
+ * status form the register 0x1B bit 3
+ *
+ *
+ * @param v_foc_rdy_u8 : The status of fast compensation
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_rdy(u8
+*v_foc_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the FOC status*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STAT_FOC_RDY__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_rdy_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_STAT_FOC_RDY);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API Reads the nvm_rdy status from the
+ * resister 0x1B bit 4
+ *
+ *
+ * @param v_nvm_rdy_u8 : The value of NVM ready status
+ * value | status
+ * ---------|----------------
+ * 0 | NVM write operation in progress
+ * 1 | NVM is ready to accept a new write trigger
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_nvm_rdy(u8
+*v_nvm_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the nvm ready status*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STAT_NVM_RDY__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_nvm_rdy_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_STAT_NVM_RDY);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of mag data ready
+ * from the register 0x1B bit 5
+ * The status get reset when one mag data register is read out
+ *
+ * @param v_data_rdy_u8 : The value of mag data ready status
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_data_rdy_mag(u8
+*v_data_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STAT_DATA_RDY_MAG__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_data_rdy_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_STAT_DATA_RDY_MAG);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of gyro data ready form the
+ * register 0x1B bit 6
+ * The status get reset when gyro data register read out
+ *
+ *
+ * @param v_data_rdy_u8 : The value of gyro data ready
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_data_rdy(u8
+*v_data_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STAT_DATA_RDY_GYRO__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_data_rdy_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_STAT_DATA_RDY_GYRO);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of accel data ready form the
+ * register 0x1B bit 7
+ * The status get reset when accel data register read out
+ *
+ *
+ * @param v_data_rdy_u8 : The value of accel data ready status
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_data_rdy(u8
+*v_data_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /*reads the status of accel data ready*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STAT_DATA_RDY_ACCEL__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_data_rdy_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_STAT_DATA_RDY_ACCEL);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the step detector interrupt status
+ * from the register 0x1C bit 0
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The status of step detector interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_step_intr(u8
+*v_step_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_0_STEP_INTR__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_step_intr_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_0_STEP_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the
+ * significant motion interrupt status
+ * from the register 0x1C bit 1
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ *
+ * @param v_significant_intr_u8 : The status of step
+ * motion interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_significant_intr(u8
+*v_significant_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_0_SIGNIFICANT_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_significant_intr_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_0_SIGNIFICANT_INTR);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API reads the any motion interrupt status
+ * from the register 0x1C bit 2
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ * @param v_any_motion_intr_u8 : The status of any-motion interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_any_motion_intr(u8
+*v_any_motion_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_0_ANY_MOTION__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_intr_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_0_ANY_MOTION);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the power mode trigger interrupt status
+ * from the register 0x1C bit 3
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ *
+ * @param v_pmu_trigger_intr_u8 : The status of power mode trigger interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_pmu_trigger_intr(u8
+*v_pmu_trigger_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_0_PMU_TRIGGER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_pmu_trigger_intr_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_0_PMU_TRIGGER);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the double tab status
+ * from the register 0x1C bit 4
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_double_tap_intr_u8 :The status of double tab interrupt
+ *
+ * @note Double tap interrupt can be configured by the following functions
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_double_tap()
+ * @note AXIS MAPPING
+ * @note bmi160_get_stat2_tap_first_x()
+ * @note bmi160_get_stat2_tap_first_y()
+ * @note bmi160_get_stat2_tap_first_z()
+ * @note DURATION
+ * @note bmi160_set_intr_tap_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_tap_thres()
+ * @note TAP QUIET
+ * @note bmi160_set_intr_tap_quiet()
+ * @note TAP SHOCK
+ * @note bmi160_set_intr_tap_shock()
+ * @note TAP SOURCE
+ * @note bmi160_set_intr_tap_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_double_tap_intr(u8
+*v_double_tap_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_0_DOUBLE_TAP_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_double_tap_intr_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_0_DOUBLE_TAP_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the single tab status
+ * from the register 0x1C bit 5
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_single_tap_intr_u8 :The status of single tap interrupt
+ *
+ * @note Single tap interrupt can be configured by the following functions
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_single_tap()
+ * @note AXIS MAPPING
+ * @note bmi160_get_stat2_tap_first_x()
+ * @note bmi160_get_stat2_tap_first_y()
+ * @note bmi160_get_stat2_tap_first_z()
+ * @note DURATION
+ * @note bmi160_set_intr_tap_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_tap_thres()
+ * @note TAP QUIET
+ * @note bmi160_set_intr_tap_quiet()
+ * @note TAP SHOCK
+ * @note bmi160_set_intr_tap_shock()
+ * @note TAP SOURCE
+ * @note bmi160_set_intr_tap_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_single_tap_intr(u8
+*v_single_tap_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_0_SINGLE_TAP_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_single_tap_intr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_0_SINGLE_TAP_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the orient status
+ * from the register 0x1C bit 6
+ * flag is associated with a specific interrupt function.
+ * It is set when the orient interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_orient_intr_u8 : The status of orient interrupt
+ *
+ * @note For orient interrupt configuration use the following functions
+ * @note STATUS
+ * @note bmi160_get_stat0_orient_intr()
+ * @note AXIS MAPPING
+ * @note bmi160_get_stat3_orient_xy()
+ * @note bmi160_get_stat3_orient_z()
+ * @note bmi160_set_intr_orient_axes_enable()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_orient()
+ * @note INTERRUPT OUTPUT
+ * @note bmi160_set_intr_orient_ud_enable()
+ * @note THETA
+ * @note bmi160_set_intr_orient_theta()
+ * @note HYSTERESIS
+ * @note bmi160_set_intr_orient_hyst()
+ * @note BLOCKING
+ * @note bmi160_set_intr_orient_blocking()
+ * @note MODE
+ * @note bmi160_set_intr_orient_mode()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_orient_intr(u8
+*v_orient_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_0_ORIENT__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_intr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_0_ORIENT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the flat interrupt status
+ * from the register 0x1C bit 7
+ * flag is associated with a specific interrupt function.
+ * It is set when the flat interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_flat_intr_u8 : The status of flat interrupt
+ *
+ * @note For flat configuration use the following functions
+ * @note STATS
+ * @note bmi160_get_stat0_flat_intr()
+ * @note bmi160_get_stat3_flat()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_flat()
+ * @note THETA
+ * @note bmi160_set_intr_flat_theta()
+ * @note HOLD TIME
+ * @note bmi160_set_intr_flat_hold()
+ * @note HYSTERESIS
+ * @note bmi160_set_intr_flat_hyst()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_flat_intr(u8
+*v_flat_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_0_FLAT__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_intr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_0_FLAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high_g interrupt status
+ * from the register 0x1D bit 2
+ * flag is associated with a specific interrupt function.
+ * It is set when the high g interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be permanently
+ * latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_high_g_intr_u8 : The status of high_g interrupt
+ *
+ * @note High_g interrupt configured by following functions
+ * @note STATUS
+ * @note bmi160_get_stat1_high_g_intr()
+ * @note AXIS MAPPING
+ * @note bmi160_get_stat3_high_g_first_x()
+ * @note bmi160_get_stat3_high_g_first_y()
+ * @note bmi160_get_stat3_high_g_first_z()
+ * @note SIGN MAPPING
+ * @note bmi160_get_stat3_high_g_first_sign()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_high_g()
+ * @note HYSTERESIS
+ * @note bmi160_set_intr_high_g_hyst()
+ * @note DURATION
+ * @note bmi160_set_intr_high_g_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_high_g_thres()
+ * @note SOURCE
+ * @note bmi160_set_intr_low_high_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_high_g_intr(u8
+*v_high_g_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_1_HIGH_G_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_intr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_1_HIGH_G_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the low g interrupt status
+ * from the register 0x1D bit 3
+ * flag is associated with a specific interrupt function.
+ * It is set when the low g interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_low_g_intr_u8 : The status of low_g interrupt
+ *
+ * @note Low_g interrupt configured by following functions
+ * @note STATUS
+ * @note bmi160_get_stat1_low_g_intr()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_low_g()
+ * @note SOURCE
+ * @note bmi160_set_intr_low_high_source()
+ * @note DURATION
+ * @note bmi160_set_intr_low_g_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_low_g_thres()
+ * @note HYSTERESIS
+ * @note bmi160_set_intr_low_g_hyst()
+ * @note MODE
+ * @note bmi160_set_intr_low_g_mode()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_low_g_intr(u8
+*v_low_g_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_1_LOW_G_INTR__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_g_intr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_1_LOW_G_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads data ready interrupt status
+ * from the register 0x1D bit 4
+ * flag is associated with a specific interrupt function.
+ * It is set when the data ready interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_data_rdy_intr_u8 : The status of data ready interrupt
+ *
+ * @note Data ready interrupt configured by following functions
+ * @note STATUS
+ * @note bmi160_get_stat1_data_rdy_intr()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_data_rdy()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_data_rdy_intr(u8
+*v_data_rdy_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_1_DATA_RDY_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_data_rdy_intr_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_1_DATA_RDY_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads data ready FIFO full interrupt status
+ * from the register 0x1D bit 5
+ * flag is associated with a specific interrupt function.
+ * It is set when the FIFO full interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will
+ * be permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_fifo_full_intr_u8 : The status of fifo full interrupt
+ *
+ * @note FIFO full interrupt can be configured by following functions
+ * @note bmi160_set_intr_fifo_full()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_fifo_full_intr(u8
+*v_fifo_full_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_1_FIFO_FULL_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_full_intr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_1_FIFO_FULL_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads data
+ * ready FIFO watermark interrupt status
+ * from the register 0x1D bit 6
+ * flag is associated with a specific interrupt function.
+ * It is set when the FIFO watermark interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_fifo_wm_intr_u8 : The status of fifo water mark interrupt
+ *
+ * @note FIFO full interrupt can be configured by following functions
+ * @note bmi160_set_intr_fifo_wm()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_fifo_wm_intr(u8
+*v_fifo_wm_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_1_FIFO_WM_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_wm_intr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_1_FIFO_WM_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads data ready no motion interrupt status
+ * from the register 0x1D bit 7
+ * flag is associated with a specific interrupt function.
+ * It is set when the no motion interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be permanently
+ * latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_nomotion_intr_u8 : The status of no motion interrupt
+ *
+ * @note No motion interrupt can be configured by following function
+ * @note STATUS
+ * @note bmi160_get_stat1_nomotion_intr()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_nomotion()
+ * @note DURATION
+ * @note bmi160_set_intr_slow_no_motion_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_slow_no_motion_thres()
+ * @note SLOW/NO MOTION SELECT
+ * @note bmi160_set_intr_slow_no_motion_select()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_nomotion_intr(u8
+*v_nomotion_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the no motion interrupt*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_1_NOMOTION_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_nomotion_intr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_1_NOMOTION_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ *@brief This API reads the status of any motion first x
+ * from the register 0x1E bit 0
+ *
+ *
+ *@param v_anymotion_first_x_u8 : The status of any motion first x interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_any_motion_first_x(u8
+*v_anymotion_first_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the any motion first x interrupt*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_anymotion_first_x_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of any motion first y interrupt
+ * from the register 0x1E bit 1
+ *
+ *
+ *
+ *@param v_any_motion_first_y_u8 : The status of any motion first y interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_any_motion_first_y(u8
+*v_any_motion_first_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the any motion first y interrupt*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_first_y_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of any motion first z interrupt
+ * from the register 0x1E bit 2
+ *
+ *
+ *
+ *
+ *@param v_any_motion_first_z_u8 : The status of any motion first z interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_any_motion_first_z(u8
+*v_any_motion_first_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the any motion first z interrupt*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_first_z_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the any motion sign status from the
+ * register 0x1E bit 3
+ *
+ *
+ *
+ *
+ * @param v_anymotion_sign_u8 : The status of any motion sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_any_motion_sign(u8
+*v_anymotion_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read any motion sign interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_SIGN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_anymotion_sign_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_SIGN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the any motion tap first x status from the
+ * register 0x1E bit 4
+ *
+ *
+ *
+ *
+ * @param v_tap_first_x_u8 :The status of any motion tap first x
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_tap_first_x(u8
+*v_tap_first_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read tap first x interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_2_TAP_FIRST_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_first_x_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_2_TAP_FIRST_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the tap first y interrupt status from the
+ * register 0x1E bit 5
+ *
+ *
+ *
+ *
+ * @param v_tap_first_y_u8 :The status of tap first y interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_tap_first_y(u8
+*v_tap_first_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read tap first y interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_2_TAP_FIRST_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_first_y_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_2_TAP_FIRST_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the tap first z interrupt status from the
+ * register 0x1E bit 6
+ *
+ *
+ *
+ *
+ * @param v_tap_first_z_u8 :The status of tap first z interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_tap_first_z(u8
+*v_tap_first_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read tap first z interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_2_TAP_FIRST_Z__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_first_z_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_2_TAP_FIRST_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the tap sign status from the
+ * register 0x1E bit 7
+ *
+ *
+ *
+ *
+ * @param v_tap_sign_u8 : The status of tap sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_tap_sign(u8
+*v_tap_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read tap_sign interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_2_TAP_SIGN__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_sign_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_2_TAP_SIGN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high_g first x status from the
+ * register 0x1F bit 0
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_x_u8 :The status of high_g first x
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_high_g_first_x(u8
+*v_high_g_first_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read highg_x interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_first_x_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high_g first y status from the
+ * register 0x1F bit 1
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_y_u8 : The status of high_g first y
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_high_g_first_y(u8
+*v_high_g_first_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read highg_y interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_first_y_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high_g first z status from the
+ * register 0x1F bit 3
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_z_u8 : The status of high_g first z
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_high_g_first_z(u8
+*v_high_g_first_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read highg_z interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Z__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_first_z_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high sign status from the
+ * register 0x1F bit 3
+ *
+ *
+ *
+ *
+ * @param v_high_g_sign_u8 :The status of high sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_high_g_sign(u8
+*v_high_g_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read highg_sign interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_3_HIGH_G_SIGN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_sign_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_3_HIGH_G_SIGN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of orient_xy plane
+ * from the register 0x1F bit 4 and 5
+ *
+ *
+ * @param v_orient_xy_u8 :The status of orient_xy plane
+ * value | status
+ * -----------|-------------
+ * 0x00 | portrait upright
+ * 0x01 | portrait upside down
+ * 0x02 | landscape left
+ * 0x03 | landscape right
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_orient_xy(u8
+*v_orient_xy_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read orient plane xy interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_3_ORIENT_XY__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_xy_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_3_ORIENT_XY);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of orient z plane
+ * from the register 0x1F bit 6
+ *
+ *
+ * @param v_orient_z_u8 :The status of orient z
+ * value | status
+ * -----------|-------------
+ * 0x00 | upward looking
+ * 0x01 | downward looking
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_orient_z(u8
+*v_orient_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read orient z plane interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_3_ORIENT_Z__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_z_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_3_ORIENT_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the flat status from the register
+ * 0x1F bit 7
+ *
+ *
+ * @param v_flat_u8 : The status of flat interrupt
+ * value | status
+ * -----------|-------------
+ * 0x00 | non flat
+ * 0x01 | flat position
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_flat(u8
+*v_flat_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read flat interrupt status */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_INTR_STAT_3_FLAT__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_STAT_3_FLAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the temperature of the sensor
+ * from the register 0x21 bit 0 to 7
+ *
+ *
+ *
+ * @param v_temp_s16 : The value of temperature
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_temp(s16
+*v_temp_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the temperature lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[BMI160_TEMP_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read temperature data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_TEMP_LSB_VALUE__REG, v_data_u8,
+ BMI160_TEMP_DATA_LENGTH);
+ *v_temp_s16 =
+ (s16)(((s32)((s8) (v_data_u8[BMI160_TEMP_MSB_BYTE]) <<
+ BMI160_SHIFT_BIT_POSITION_BY_08_BITS))
+ | v_data_u8[BMI160_TEMP_LSB_BYTE]);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the of the sensor
+ * form the register 0x23 and 0x24 bit 0 to 7 and 0 to 2
+ * @brief this byte counter is updated each time a complete frame
+ * was read or writtern
+ *
+ *
+ * @param v_fifo_length_u32 : The value of fifo byte counter
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_fifo_length(u32 *v_fifo_length_u32)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array contains the fifo length data
+ v_data_u8[0] - fifo length
+ v_data_u8[1] - fifo length*/
+ u8 a_data_u8r[BMI160_FIFO_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read fifo length*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_BYTE_COUNTER_LSB__REG, a_data_u8r,
+ BMI160_FIFO_DATA_LENGTH);
+
+ a_data_u8r[BMI160_FIFO_LENGTH_MSB_BYTE] =
+ BMI160_GET_BITSLICE(
+ a_data_u8r[BMI160_FIFO_LENGTH_MSB_BYTE],
+ BMI160_USER_FIFO_BYTE_COUNTER_MSB);
+
+ *v_fifo_length_u32 =
+ (u32)(((u32)((u8) (
+ a_data_u8r[BMI160_FIFO_LENGTH_MSB_BYTE]) <<
+ BMI160_SHIFT_BIT_POSITION_BY_08_BITS))
+ | a_data_u8r[BMI160_FIFO_LENGTH_LSB_BYTE]);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the fifo data of the sensor
+ * from the register 0x24
+ * @brief Data format depends on the setting of register FIFO_CONFIG
+ *
+ *
+ *
+ * @param v_fifodata_u8 : Pointer holding the fifo data
+ * @param fifo_length_u16 : The value of fifo length maximum
+ * 1024
+ *
+ * @note For reading FIFO data use the following functions
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_fifo_data(
+u8 *v_fifodata_u8, u16 v_fifo_length_u16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read fifo data*/
+ com_rslt =
+ p_bmi160->BMI160_BURST_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_DATA__REG,
+ v_fifodata_u8, v_fifo_length_u16);
+
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * accel output date rate form the register 0x40 bit 0 to 3
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of accel output date rate
+ * value | output data rate
+ * -------|--------------------------
+ * 0 | BMI160_ACCEL_OUTPUT_DATA_RATE_RESERVED
+ * 1 | BMI160_ACCEL_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | BMI160_ACCEL_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | BMI160_ACCEL_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | BMI160_ACCEL_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | BMI160_ACCEL_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | BMI160_ACCEL_OUTPUT_DATA_RATE_25HZ
+ * 7 | BMI160_ACCEL_OUTPUT_DATA_RATE_50HZ
+ * 8 | BMI160_ACCEL_OUTPUT_DATA_RATE_100HZ
+ * 9 | BMI160_ACCEL_OUTPUT_DATA_RATE_200HZ
+ * 10 | BMI160_ACCEL_OUTPUT_DATA_RATE_400HZ
+ * 11 | BMI160_ACCEL_OUTPUT_DATA_RATE_800HZ
+ * 12 | BMI160_ACCEL_OUTPUT_DATA_RATE_1600HZ
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_output_data_rate(
+u8 *v_output_data_rate_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel output data rate*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_data_rate_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * accel output date rate form the register 0x40 bit 0 to 3
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of accel output date rate
+ * value | output data rate
+ * -------|--------------------------
+ * 0 | BMI160_ACCEL_OUTPUT_DATA_RATE_RESERVED
+ * 1 | BMI160_ACCEL_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | BMI160_ACCEL_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | BMI160_ACCEL_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | BMI160_ACCEL_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | BMI160_ACCEL_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | BMI160_ACCEL_OUTPUT_DATA_RATE_25HZ
+ * 7 | BMI160_ACCEL_OUTPUT_DATA_RATE_50HZ
+ * 8 | BMI160_ACCEL_OUTPUT_DATA_RATE_100HZ
+ * 9 | BMI160_ACCEL_OUTPUT_DATA_RATE_200HZ
+ * 10 | BMI160_ACCEL_OUTPUT_DATA_RATE_400HZ
+ * 11 | BMI160_ACCEL_OUTPUT_DATA_RATE_800HZ
+ * 12 | BMI160_ACCEL_OUTPUT_DATA_RATE_1600HZ
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_output_data_rate(
+u8 v_output_data_rate_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* accel output data rate selection */
+ if ((v_output_data_rate_u8 != BMI160_INIT_VALUE) &&
+ (v_output_data_rate_u8 <= BMI160_MAX_ACCEL_OUTPUT_DATA_RATE)) {
+ /* write accel output data rate */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE,
+ v_output_data_rate_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * accel bandwidth from the register 0x40 bit 4 to 6
+ * @brief bandwidth parameter determines filter configuration(acc_us=0)
+ * and averaging for under sampling mode(acc_us=1)
+ *
+ *
+ * @param v_bw_u8 : The value of accel bandwidth
+ *
+ * @note accel bandwidth depends on under sampling parameter
+ * @note under sampling parameter cab be set by the function
+ * "BMI160_SET_ACCEL_UNDER_SAMPLING_PARAMETER"
+ *
+ * @note Filter configuration
+ * accel_us | Filter configuration
+ * -----------|---------------------
+ * 0x00 | OSR4 mode
+ * 0x01 | OSR2 mode
+ * 0x02 | normal mode
+ * 0x03 | CIC mode
+ * 0x04 | Reserved
+ * 0x05 | Reserved
+ * 0x06 | Reserved
+ * 0x07 | Reserved
+ *
+ * @note accel under sampling mode
+ * accel_us | Under sampling mode
+ * -----------|---------------------
+ * 0x00 | no averaging
+ * 0x01 | average 2 samples
+ * 0x02 | average 4 samples
+ * 0x03 | average 8 samples
+ * 0x04 | average 16 samples
+ * 0x05 | average 32 samples
+ * 0x06 | average 64 samples
+ * 0x07 | average 128 samples
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_bw(u8 *v_bw_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel bandwidth */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_BW__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_bw_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_BW);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * accel bandwidth from the register 0x40 bit 4 to 6
+ * @brief bandwidth parameter determines filter configuration(acc_us=0)
+ * and averaging for under sampling mode(acc_us=1)
+ *
+ *
+ * @param v_bw_u8 : The value of accel bandwidth
+ *
+ * @note accel bandwidth depends on under sampling parameter
+ * @note under sampling parameter cab be set by the function
+ * "BMI160_SET_ACCEL_UNDER_SAMPLING_PARAMETER"
+ *
+ * @note Filter configuration
+ * accel_us | Filter configuration
+ * -----------|---------------------
+ * 0x00 | OSR4 mode
+ * 0x01 | OSR2 mode
+ * 0x02 | normal mode
+ * 0x03 | CIC mode
+ * 0x04 | Reserved
+ * 0x05 | Reserved
+ * 0x06 | Reserved
+ * 0x07 | Reserved
+ *
+ * @note accel under sampling mode
+ * accel_us | Under sampling mode
+ * -----------|---------------------
+ * 0x00 | no averaging
+ * 0x01 | average 2 samples
+ * 0x02 | average 4 samples
+ * 0x03 | average 8 samples
+ * 0x04 | average 16 samples
+ * 0x05 | average 32 samples
+ * 0x06 | average 64 samples
+ * 0x07 | average 128 samples
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_bw(u8 v_bw_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* select accel bandwidth*/
+ if (v_bw_u8 <= BMI160_MAX_ACCEL_BW) {
+ /* write accel bandwidth*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_BW__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_BW,
+ v_bw_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_BW__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the accel
+ * under sampling parameter form the register 0x40 bit 7
+ *
+ *
+ *
+ *
+ * @param v_accel_under_sampling_u8 : The value of accel under sampling
+ * value | under_sampling
+ * ----------|---------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_under_sampling_parameter(
+u8 *v_accel_under_sampling_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel under sampling parameter */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_under_sampling_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the accel
+ * under sampling parameter form the register 0x40 bit 7
+ *
+ *
+ *
+ *
+ * @param v_accel_under_sampling_u8 : The value of accel under sampling
+ * value | under_sampling
+ * ----------|---------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_under_sampling_parameter(
+u8 v_accel_under_sampling_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_accel_under_sampling_u8 <= BMI160_MAX_UNDER_SAMPLING) {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ /* write the accel under sampling parameter */
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING,
+ v_accel_under_sampling_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API is used to get the ranges
+ * (g values) of the accel from the register 0x41 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_range_u8 : The value of accel g range
+ * value | g_range
+ * ----------|-----------
+ * 0x03 | BMI160_ACCEL_RANGE_2G
+ * 0x05 | BMI160_ACCEL_RANGE_4G
+ * 0x08 | BMI160_ACCEL_RANGE_8G
+ * 0x0C | BMI160_ACCEL_RANGE_16G
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_range(
+u8 *v_range_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel range*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_RANGE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_range_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_RANGE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the ranges
+ * (g values) of the accel from the register 0x41 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_range_u8 : The value of accel g range
+ * value | g_range
+ * ----------|-----------
+ * 0x03 | BMI160_ACCEL_RANGE_2G
+ * 0x05 | BMI160_ACCEL_RANGE_4G
+ * 0x08 | BMI160_ACCEL_RANGE_8G
+ * 0x0C | BMI160_ACCEL_RANGE_16G
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_range(u8 v_range_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if ((v_range_u8 == BMI160_ACCEL_RANGE0) ||
+ (v_range_u8 == BMI160_ACCEL_RANGE1) ||
+ (v_range_u8 == BMI160_ACCEL_RANGE3) ||
+ (v_range_u8 == BMI160_ACCEL_RANGE4)) {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_RANGE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(
+ v_data_u8, BMI160_USER_ACCEL_RANGE,
+ v_range_u8);
+ /* write the accel range*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_RANGE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * gyroscope output data rate from the register 0x42 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of gyro output data rate
+ * value | gyro output data rate
+ * -----------|-----------------------------
+ * 0x00 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x02 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x03 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x04 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x05 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x06 | BMI160_GYRO_OUTPUT_DATA_RATE_25HZ
+ * 0x07 | BMI160_GYRO_OUTPUT_DATA_RATE_50HZ
+ * 0x08 | BMI160_GYRO_OUTPUT_DATA_RATE_100HZ
+ * 0x09 | BMI160_GYRO_OUTPUT_DATA_RATE_200HZ
+ * 0x0A | BMI160_GYRO_OUTPUT_DATA_RATE_400HZ
+ * 0x0B | BMI160_GYRO_OUTPUT_DATA_RATE_800HZ
+ * 0x0C | BMI160_GYRO_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D | BMI160_GYRO_OUTPUT_DATA_RATE_3200HZ
+ * 0x0E | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x0F | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_output_data_rate(
+u8 *v_output_data_rate_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the gyro output data rate*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_data_rate_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_CONFIG_OUTPUT_DATA_RATE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * gyroscope output data rate from the register 0x42 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of gyro output data rate
+ * value | gyro output data rate
+ * -----------|-----------------------------
+ * 0x00 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x02 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x03 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x04 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x05 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x06 | BMI160_GYRO_OUTPUT_DATA_RATE_25HZ
+ * 0x07 | BMI160_GYRO_OUTPUT_DATA_RATE_50HZ
+ * 0x08 | BMI160_GYRO_OUTPUT_DATA_RATE_100HZ
+ * 0x09 | BMI160_GYRO_OUTPUT_DATA_RATE_200HZ
+ * 0x0A | BMI160_GYRO_OUTPUT_DATA_RATE_400HZ
+ * 0x0B | BMI160_GYRO_OUTPUT_DATA_RATE_800HZ
+ * 0x0C | BMI160_GYRO_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D | BMI160_GYRO_OUTPUT_DATA_RATE_3200HZ
+ * 0x0E | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x0F | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_output_data_rate(
+u8 v_output_data_rate_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* select the gyro output data rate*/
+ if ((v_output_data_rate_u8 < BMI160_OUTPUT_DATA_RATE6) &&
+ (v_output_data_rate_u8 != BMI160_INIT_VALUE)
+ && (v_output_data_rate_u8 != BMI160_OUTPUT_DATA_RATE1)
+ && (v_output_data_rate_u8 != BMI160_OUTPUT_DATA_RATE2)
+ && (v_output_data_rate_u8 != BMI160_OUTPUT_DATA_RATE3)
+ && (v_output_data_rate_u8 != BMI160_OUTPUT_DATA_RATE4)
+ && (v_output_data_rate_u8 != BMI160_OUTPUT_DATA_RATE5)
+ && (v_output_data_rate_u8 != BMI160_OUTPUT_DATA_RATE6)
+ && (v_output_data_rate_u8 != BMI160_OUTPUT_DATA_RATE7)) {
+ /* write the gyro output data rate */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_CONFIG_OUTPUT_DATA_RATE,
+ v_output_data_rate_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * data of gyro from the register 0x42 bit 4 to 5
+ *
+ *
+ *
+ *
+ * @param v_bw_u8 : The value of gyro bandwidth
+ * value | gyro bandwidth
+ * ----------|----------------
+ * 0x00 | BMI160_GYRO_OSR4_MODE
+ * 0x01 | BMI160_GYRO_OSR2_MODE
+ * 0x02 | BMI160_GYRO_NORMAL_MODE
+ * 0x03 | BMI160_GYRO_CIC_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_bw(u8 *v_bw_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro bandwidth*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_GYRO_CONFIG_BW__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_bw_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_CONFIG_BW);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * data of gyro from the register 0x42 bit 4 to 5
+ *
+ *
+ *
+ *
+ * @param v_bw_u8 : The value of gyro bandwidth
+ * value | gyro bandwidth
+ * ----------|----------------
+ * 0x00 | BMI160_GYRO_OSR4_MODE
+ * 0x01 | BMI160_GYRO_OSR2_MODE
+ * 0x02 | BMI160_GYRO_NORMAL_MODE
+ * 0x03 | BMI160_GYRO_CIC_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_bw(u8 v_bw_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_bw_u8 <= BMI160_MAX_GYRO_BW) {
+ /* write the gyro bandwidth*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_GYRO_CONFIG_BW__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_CONFIG_BW, v_bw_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_CONFIG_BW__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the range
+ * of gyro from the register 0x43 bit 0 to 2
+ *
+ * @param v_range_u8 : The value of gyro range
+ * value | range
+ * ----------|-------------------------------
+ * 0x00 | BMI160_GYRO_RANGE_2000_DEG_SEC
+ * 0x01 | BMI160_GYRO_RANGE_1000_DEG_SEC
+ * 0x02 | BMI160_GYRO_RANGE_500_DEG_SEC
+ * 0x03 | BMI160_GYRO_RANGE_250_DEG_SEC
+ * 0x04 | BMI160_GYRO_RANGE_125_DEG_SEC
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_range(u8 *v_range_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the gyro range */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_GYRO_RANGE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_range_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_RANGE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set the range
+ * of gyro from the register 0x43 bit 0 to 2
+ *
+ * @param v_range_u8 : The value of gyro range
+ * value | range
+ * ----------|-------------------------------
+ * 0x00 | BMI160_GYRO_RANGE_2000_DEG_SEC
+ * 0x01 | BMI160_GYRO_RANGE_1000_DEG_SEC
+ * 0x02 | BMI160_GYRO_RANGE_500_DEG_SEC
+ * 0x03 | BMI160_GYRO_RANGE_250_DEG_SEC
+ * 0x04 | BMI160_GYRO_RANGE_125_DEG_SEC
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_range(u8 v_range_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_range_u8 <= BMI160_MAX_GYRO_RANGE) {
+ /* write the gyro range value */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_GYRO_RANGE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_RANGE,
+ v_range_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_GYRO_RANGE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * output data rate of magnetometer from the register 0x44 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rat_u8e : The value of mag output data rate
+ * value | mag output data rate
+ * ---------|---------------------------
+ * 0x00 |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 |BMI160_MAG_OUTPUT_DATA_RATE_0_78HZ
+ * 0x02 |BMI160_MAG_OUTPUT_DATA_RATE_1_56HZ
+ * 0x03 |BMI160_MAG_OUTPUT_DATA_RATE_3_12HZ
+ * 0x04 |BMI160_MAG_OUTPUT_DATA_RATE_6_25HZ
+ * 0x05 |BMI160_MAG_OUTPUT_DATA_RATE_12_5HZ
+ * 0x06 |BMI160_MAG_OUTPUT_DATA_RATE_25HZ
+ * 0x07 |BMI160_MAG_OUTPUT_DATA_RATE_50HZ
+ * 0x08 |BMI160_MAG_OUTPUT_DATA_RATE_100HZ
+ * 0x09 |BMI160_MAG_OUTPUT_DATA_RATE_200HZ
+ * 0x0A |BMI160_MAG_OUTPUT_DATA_RATE_400HZ
+ * 0x0B |BMI160_MAG_OUTPUT_DATA_RATE_800HZ
+ * 0x0C |BMI160_MAG_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED0
+ * 0x0E |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED1
+ * 0x0F |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED2
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_output_data_rate(
+u8 *v_output_data_rat_u8e)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the mag data output rate*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_data_rat_u8e = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_CONFIG_OUTPUT_DATA_RATE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * output data rate of magnetometer from the register 0x44 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rat_u8e : The value of mag output data rate
+ * value | mag output data rate
+ * ---------|---------------------------
+ * 0x00 |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 |BMI160_MAG_OUTPUT_DATA_RATE_0_78HZ
+ * 0x02 |BMI160_MAG_OUTPUT_DATA_RATE_1_56HZ
+ * 0x03 |BMI160_MAG_OUTPUT_DATA_RATE_3_12HZ
+ * 0x04 |BMI160_MAG_OUTPUT_DATA_RATE_6_25HZ
+ * 0x05 |BMI160_MAG_OUTPUT_DATA_RATE_12_5HZ
+ * 0x06 |BMI160_MAG_OUTPUT_DATA_RATE_25HZ
+ * 0x07 |BMI160_MAG_OUTPUT_DATA_RATE_50HZ
+ * 0x08 |BMI160_MAG_OUTPUT_DATA_RATE_100HZ
+ * 0x09 |BMI160_MAG_OUTPUT_DATA_RATE_200HZ
+ * 0x0A |BMI160_MAG_OUTPUT_DATA_RATE_400HZ
+ * 0x0B |BMI160_MAG_OUTPUT_DATA_RATE_800HZ
+ * 0x0C |BMI160_MAG_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED0
+ * 0x0E |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED1
+ * 0x0F |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED2
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_output_data_rate(
+u8 v_output_data_rat_u8e)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* select the mag data output rate*/
+ if ((v_output_data_rat_u8e
+ <= BMI160_MAX_ACCEL_OUTPUT_DATA_RATE)
+ && (v_output_data_rat_u8e
+ != BMI160_OUTPUT_DATA_RATE0)
+ && (v_output_data_rat_u8e
+ != BMI160_OUTPUT_DATA_RATE6)
+ && (v_output_data_rat_u8e
+ != BMI160_OUTPUT_DATA_RATE7)) {
+ /* write the mag data output rate*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_CONFIG_OUTPUT_DATA_RATE,
+ v_output_data_rat_u8e);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_MAG_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to read Down sampling
+ * for gyro (2**downs_gyro) in the register 0x45 bit 0 to 2
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_gyro_u8 :The value of gyro fifo down
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_down_gyro(
+u8 *v_fifo_down_gyro_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the gyro fifo down*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_DOWN_GYRO__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_down_gyro_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_DOWN_GYRO);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to set Down sampling
+ * for gyro (2**downs_gyro) in the register 0x45 bit 0 to 2
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_gyro_u8 :The value of gyro fifo down
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_down_gyro(
+u8 v_fifo_down_gyro_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write the gyro fifo down*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_DOWN_GYRO__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_FIFO_DOWN_GYRO,
+ v_fifo_down_gyro_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_DOWN_GYRO__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read gyro fifo filter data
+ * from the register 0x45 bit 3
+ *
+ *
+ *
+ * @param v_gyro_fifo_filter_data_u8 :The value of gyro filter data
+ * value | gyro_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_fifo_filter_data(
+u8 *v_gyro_fifo_filter_data_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the gyro fifo filter data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_FILTER_GYRO__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_fifo_filter_data_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_FILTER_GYRO);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set gyro fifo filter data
+ * from the register 0x45 bit 3
+ *
+ *
+ *
+ * @param v_gyro_fifo_filter_data_u8 :The value of gyro filter data
+ * value | gyro_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_fifo_filter_data(
+u8 v_gyro_fifo_filter_data_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_gyro_fifo_filter_data_u8
+ <= BMI160_MAX_VALUE_FIFO_FILTER) {
+ /* write the gyro fifo filter data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_FILTER_GYRO__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_FIFO_FILTER_GYRO,
+ v_gyro_fifo_filter_data_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_FILTER_GYRO__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read Down sampling
+ * for accel (2*downs_accel) from the register 0x45 bit 4 to 6
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_u8 :The value of accel fifo down
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_down_accel(
+u8 *v_fifo_down_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel fifo down data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_DOWN_ACCEL__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_down_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_DOWN_ACCEL);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to set Down sampling
+ * for accel (2*downs_accel) from the register 0x45 bit 4 to 6
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_u8 :The value of accel fifo down
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_down_accel(
+u8 v_fifo_down_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write the accel fifo down data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_DOWN_ACCEL__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_DOWN_ACCEL, v_fifo_down_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_DOWN_ACCEL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read accel fifo filter data
+ * from the register 0x45 bit 7
+ *
+ *
+ *
+ * @param v_accel_fifo_filter_u8 :The value of accel filter data
+ * value | accel_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_fifo_filter_data(
+u8 *v_accel_fifo_filter_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel fifo filter data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_FILTER_ACCEL__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_fifo_filter_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_FILTER_ACCEL);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set accel fifo filter data
+ * from the register 0x45 bit 7
+ *
+ *
+ *
+ * @param v_accel_fifo_filter_u8 :The value of accel filter data
+ * value | accel_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_fifo_filter_data(
+u8 v_accel_fifo_filter_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_accel_fifo_filter_u8 <= BMI160_MAX_VALUE_FIFO_FILTER) {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_FILTER_ACCEL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ /* write accel fifo filter data */
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_FILTER_ACCEL,
+ v_accel_fifo_filter_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_FILTER_ACCEL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to Trigger an interrupt
+ * when FIFO contains water mark level from the register 0x46 bit 0 to 7
+ *
+ *
+ *
+ * @param v_fifo_wm_u8 : The value of fifo water mark level
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_wm(
+u8 *v_fifo_wm_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the fifo water mark level*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_WM__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_wm_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_WM);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to Trigger an interrupt
+ * when FIFO contains water mark level from the register 0x46 bit 0 to 7
+ *
+ *
+ *
+ * @param v_fifo_wm_u8 : The value of fifo water mark level
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_wm(
+u8 v_fifo_wm_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write the fifo water mark level*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_WM__REG,
+ &v_fifo_wm_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads fifo sensor time
+ * frame after the last valid data frame form the register 0x47 bit 1
+ *
+ *
+ *
+ *
+ * @param v_fifo_time_enable_u8 : The value of sensor time
+ * value | fifo sensor time
+ * ------------|-------------------------
+ * 0x00 | do not return sensortime frame
+ * 0x01 | return sensortime frame
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_time_enable(
+u8 *v_fifo_time_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the fifo sensor time*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_TIME_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_time_enable_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_TIME_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set fifo sensor time
+ * frame after the last valid data frame form the register 0x47 bit 1
+ *
+ *
+ *
+ *
+ * @param v_fifo_time_enable_u8 : The value of sensor time
+ * value | fifo sensor time
+ * ------------|-------------------------
+ * 0x00 | do not return sensortime frame
+ * 0x01 | return sensortime frame
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_time_enable(
+u8 v_fifo_time_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_fifo_time_enable_u8 <= BMI160_MAX_VALUE_FIFO_TIME) {
+ /* write the fifo sensor time*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_TIME_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_TIME_ENABLE,
+ v_fifo_time_enable_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_TIME_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads FIFO tag interrupt2 enable status
+ * from the resister 0x47 bit 2
+ *
+ * @param v_fifo_tag_intr2_u8 : The value of fifo tag interrupt
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_tag_intr2_enable(
+u8 *v_fifo_tag_intr2_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the fifo tag interrupt2*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_TAG_INTR2_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_tag_intr2_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_TAG_INTR2_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set FIFO tag interrupt2 enable status
+ * from the resister 0x47 bit 2
+ *
+ * @param v_fifo_tag_intr2_u8 : The value of fifo tag interrupt
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_tag_intr2_enable(
+u8 v_fifo_tag_intr2_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_fifo_tag_intr2_u8 <= BMI160_MAX_VALUE_FIFO_INTR) {
+ /* write the fifo tag interrupt2*/
+ com_rslt = bmi160_set_input_enable(1,
+ v_fifo_tag_intr2_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_TAG_INTR2_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_TAG_INTR2_ENABLE,
+ v_fifo_tag_intr2_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_TAG_INTR2_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API get FIFO tag interrupt1 enable status
+ * from the resister 0x47 bit 3
+ *
+ * @param v_fifo_tag_intr1_u8 :The value of fifo tag interrupt1
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_tag_intr1_enable(
+u8 *v_fifo_tag_intr1_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read fifo tag interrupt*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_TAG_INTR1_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_tag_intr1_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_TAG_INTR1_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set FIFO tag interrupt1 enable status
+ * from the resister 0x47 bit 3
+ *
+ * @param v_fifo_tag_intr1_u8 :The value of fifo tag interrupt1
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_tag_intr1_enable(
+u8 v_fifo_tag_intr1_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_fifo_tag_intr1_u8 <= BMI160_MAX_VALUE_FIFO_INTR) {
+ /* write the fifo tag interrupt*/
+ com_rslt = bmi160_set_input_enable(BMI160_INIT_VALUE,
+ v_fifo_tag_intr1_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_TAG_INTR1_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_TAG_INTR1_ENABLE,
+ v_fifo_tag_intr1_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_TAG_INTR1_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads FIFO frame
+ * header enable from the register 0x47 bit 4
+ *
+ * @param v_fifo_header_u8 :The value of fifo header
+ * value | fifo header
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_header_enable(
+u8 *v_fifo_header_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read fifo header */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_HEADER_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_header_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_HEADER_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set FIFO frame
+ * header enable from the register 0x47 bit 4
+ *
+ * @param v_fifo_header_u8 :The value of fifo header
+ * value | fifo header
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_header_enable(
+u8 v_fifo_header_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_fifo_header_u8 <= BMI160_MAX_VALUE_FIFO_HEADER) {
+ /* write the fifo header */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_HEADER_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_HEADER_ENABLE,
+ v_fifo_header_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_HEADER_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read stored
+ * magnetometer data in FIFO (all 3 axes) from the register 0x47 bit 5
+ *
+ * @param v_fifo_mag_u8 : The value of fifo mag enble
+ * value | fifo mag
+ * ----------|-------------------
+ * 0x00 | no magnetometer data is stored
+ * 0x01 | magnetometer data is stored
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_mag_enable(
+u8 *v_fifo_mag_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the fifo mag enable*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_MAG_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_mag_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_MAG_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set stored
+ * magnetometer data in FIFO (all 3 axes) from the register 0x47 bit 5
+ *
+ * @param v_fifo_mag_u8 : The value of fifo mag enble
+ * value | fifo mag
+ * ----------|-------------------
+ * 0x00 | no magnetometer data is stored
+ * 0x01 | magnetometer data is stored
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_mag_enable(
+u8 v_fifo_mag_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_fifo_mag_u8 <= BMI160_MAX_VALUE_FIFO_MAG) {
+ /* write the fifo mag enable*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_FIFO_MAG_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_MAG_ENABLE,
+ v_fifo_mag_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_FIFO_MAG_ENABLE__REG,
+ &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read stored
+ * accel data in FIFO (all 3 axes) from the register 0x47 bit 6
+ *
+ * @param v_fifo_accel_u8 : The value of fifo accel enble
+ * value | fifo accel
+ * ----------|-------------------
+ * 0x00 | no accel data is stored
+ * 0x01 | accel data is stored
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_accel_enable(
+u8 *v_fifo_accel_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel fifo enable*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_ACCEL_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_accel_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_ACCEL_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set stored
+ * accel data in FIFO (all 3 axes) from the register 0x47 bit 6
+ *
+ * @param v_fifo_accel_u8 : The value of fifo accel enble
+ * value | fifo accel
+ * ----------|-------------------
+ * 0x00 | no accel data is stored
+ * 0x01 | accel data is stored
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_accel_enable(
+u8 v_fifo_accel_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_fifo_accel_u8 <= BMI160_MAX_VALUE_FIFO_ACCEL) {
+ /* write the fifo mag enables*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_ACCEL_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_ACCEL_ENABLE, v_fifo_accel_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_ACCEL_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read stored
+ * gyro data in FIFO (all 3 axes) from the resister 0x47 bit 7
+ *
+ *
+ * @param v_fifo_gyro_u8 : The value of fifo gyro enble
+ * value | fifo gyro
+ * ----------|-------------------
+ * 0x00 | no gyro data is stored
+ * 0x01 | gyro data is stored
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_gyro_enable(
+u8 *v_fifo_gyro_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read fifo gyro enable */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_GYRO_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_gyro_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_GYRO_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set stored
+ * gyro data in FIFO (all 3 axes) from the resister 0x47 bit 7
+ *
+ *
+ * @param v_fifo_gyro_u8 : The value of fifo gyro enble
+ * value | fifo gyro
+ * ----------|-------------------
+ * 0x00 | no gyro data is stored
+ * 0x01 | gyro data is stored
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_gyro_enable(
+u8 v_fifo_gyro_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_fifo_gyro_u8 <= BMI160_MAX_VALUE_FIFO_GYRO) {
+ /* write fifo gyro enable*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_FIFO_GYRO_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FIFO_GYRO_ENABLE, v_fifo_gyro_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FIFO_GYRO_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * I2C device address of auxiliary mag from the register 0x4B bit 1 to 7
+ *
+ *
+ *
+ *
+ * @param v_i2c_device_addr_u8 : The value of mag I2C device address
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_i2c_device_addr(
+u8 *v_i2c_device_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the mag I2C device address*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_I2C_DEVICE_ADDR__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_i2c_device_addr_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_I2C_DEVICE_ADDR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * I2C device address of auxiliary mag from the register 0x4B bit 1 to 7
+ *
+ *
+ *
+ *
+ * @param v_i2c_device_addr_u8 : The value of mag I2C device address
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_i2c_device_addr(
+u8 v_i2c_device_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write the mag I2C device address*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_I2C_DEVICE_ADDR__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_I2C_DEVICE_ADDR,
+ v_i2c_device_addr_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_I2C_DEVICE_ADDR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * Burst data length (1,2,6,8 byte) from the register 0x4C bit 0 to 1
+ *
+ *
+ *
+ *
+ * @param v_mag_burst_u8 : The data of mag burst read lenth
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_burst(
+u8 *v_mag_burst_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read mag burst mode length*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_BURST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_burst_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_BURST);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * Burst data length (1,2,6,8 byte) from the register 0x4C bit 0 to 1
+ *
+ *
+ *
+ *
+ * @param v_mag_burst_u8 : The data of mag burst read lenth
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_burst(
+u8 v_mag_burst_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write mag burst mode length*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_BURST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_BURST, v_mag_burst_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_MAG_BURST__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * trigger-readout offset in units of 2.5 ms. If set to zero,
+ * the offset is maximum, i.e. after readout a trigger
+ * is issued immediately. from the register 0x4C bit 2 to 5
+ *
+ *
+ *
+ *
+ * @param v_mag_offset_u8 : The value of mag offset
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_offset(
+u8 *v_mag_offset_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_OFFSET__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_offset_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_OFFSET);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * trigger-readout offset in units of 2.5 ms. If set to zero,
+ * the offset is maximum, i.e. after readout a trigger
+ * is issued immediately. from the register 0x4C bit 2 to 5
+ *
+ *
+ *
+ *
+ * @param v_mag_offset_u8 : The value of mag offset
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_offset(
+u8 v_mag_offset_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_OFFSET__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_OFFSET, v_mag_offset_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_OFFSET__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * Enable register access on MAG_IF[2] or MAG_IF[3] writes.
+ * This implies that the DATA registers are not updated with
+ * magnetometer values. Accessing magnetometer requires
+ * the magnetometer in normal mode in PMU_STATUS.
+ * from the register 0x4C bit 7
+ *
+ *
+ *
+ * @param v_mag_manual_u8 : The value of mag manual enable
+ * value | mag manual
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_manual_enable(
+u8 *v_mag_manual_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read mag manual */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_MANUAL_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_manual_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_MANUAL_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * Enable register access on MAG_IF[2] or MAG_IF[3] writes.
+ * This implies that the DATA registers are not updated with
+ * magnetometer values. Accessing magnetometer requires
+ * the magnetometer in normal mode in PMU_STATUS.
+ * from the register 0x4C bit 7
+ *
+ *
+ *
+ * @param v_mag_manual_u8 : The value of mag manual enable
+ * value | mag manual
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_manual_enable(
+u8 v_mag_manual_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = BMI160_INIT_VALUE;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write the mag manual*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_MANUAL_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ if (com_rslt == SUCCESS) {
+ /* set the bit of mag manual enable*/
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_MAG_MANUAL_ENABLE, v_mag_manual_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_MAG_MANUAL_ENABLE__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ if (com_rslt == SUCCESS)
+ p_bmi160->mag_manual_enable = v_mag_manual_u8;
+ else
+ p_bmi160->mag_manual_enable = E_BMI160_COMM_RES;
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read data
+ * magnetometer address to read from the register 0x4D bit 0 to 7
+ * @brief It used to provide mag read address of auxiliary mag
+ *
+ *
+ *
+ *
+ * @param v_mag_read_addr_u8 : The value of address need to be read
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_read_addr(
+u8 *v_mag_read_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the written address*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_READ_ADDR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_read_addr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_READ_ADDR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * magnetometer write address from the register 0x4D bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_read_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_read_addr(
+u8 v_mag_read_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write the mag read address*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_READ_ADDR__REG, &v_mag_read_addr_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * magnetometer write address from the register 0x4E bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_write_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_write_addr(
+u8 *v_mag_write_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the address of last written */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_WRITE_ADDR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_write_addr_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_WRITE_ADDR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * magnetometer write address from the register 0x4E bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_write_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_write_addr(
+u8 v_mag_write_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write the data of mag address to write data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_WRITE_ADDR__REG, &v_mag_write_addr_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read magnetometer write data
+ * form the resister 0x4F bit 0 to 7
+ * @brief This writes the data will be wrote to mag
+ *
+ *
+ *
+ * @param v_mag_write_data_u8: The value of mag data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_write_data(
+u8 *v_mag_write_data_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_WRITE_DATA__REG, &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_write_data_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_WRITE_DATA);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set magnetometer write data
+ * form the resister 0x4F bit 0 to 7
+ * @brief This writes the data will be wrote to mag
+ *
+ *
+ *
+ * @param v_mag_write_data_u8: The value of mag data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_write_data(
+u8 v_mag_write_data_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt =
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_WRITE_DATA__REG, &v_mag_write_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * interrupt enable from the register 0x50 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_ANY_MOTION_X_ENABLE
+ * 1 | BMI160_ANY_MOTION_Y_ENABLE
+ * 2 | BMI160_ANY_MOTION_Z_ENABLE
+ * 3 | BMI160_DOUBLE_TAP_ENABLE
+ * 4 | BMI160_SINGLE_TAP_ENABLE
+ * 5 | BMI160_ORIENT_ENABLE
+ * 6 | BMI160_FLAT_ENABLE
+ *
+ * @param v_intr_enable_zero_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_enable_0(
+u8 v_enable_u8, u8 *v_intr_enable_zero_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* select interrupt to read*/
+ switch (v_enable_u8) {
+ case BMI160_ANY_MOTION_X_ENABLE:
+ /* read the any motion interrupt x data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE);
+ break;
+ case BMI160_ANY_MOTION_Y_ENABLE:
+ /* read the any motion interrupt y data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE);
+ break;
+ case BMI160_ANY_MOTION_Z_ENABLE:
+ /* read the any motion interrupt z data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE);
+ break;
+ case BMI160_DOUBLE_TAP_ENABLE:
+ /* read the double tap interrupt data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE);
+ break;
+ case BMI160_SINGLE_TAP_ENABLE:
+ /* read the single tap interrupt data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE);
+ break;
+ case BMI160_ORIENT_ENABLE:
+ /* read the orient interrupt data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_0_ORIENT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_ORIENT_ENABLE);
+ break;
+ case BMI160_FLAT_ENABLE:
+ /* read the flat interrupt data */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_0_FLAT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_FLAT_ENABLE);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * interrupt enable from the register 0x50 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_ANY_MOTION_X_ENABLE
+ * 1 | BMI160_ANY_MOTION_Y_ENABLE
+ * 2 | BMI160_ANY_MOTION_Z_ENABLE
+ * 3 | BMI160_DOUBLE_TAP_ENABLE
+ * 4 | BMI160_SINGLE_TAP_ENABLE
+ * 5 | BMI160_ORIENT_ENABLE
+ * 6 | BMI160_FLAT_ENABLE
+ *
+ * @param v_intr_enable_zero_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_enable_0(
+u8 v_enable_u8, u8 v_intr_enable_zero_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case BMI160_ANY_MOTION_X_ENABLE:
+ /* write any motion x*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_ANY_MOTION_Y_ENABLE:
+ /* write any motion y*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_ANY_MOTION_Z_ENABLE:
+ /* write any motion z*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_DOUBLE_TAP_ENABLE:
+ /* write double tap*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_SINGLE_TAP_ENABLE:
+ /* write single tap */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_ORIENT_ENABLE:
+ /* write orient interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_0_ORIENT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_ORIENT_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_ORIENT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_FLAT_ENABLE:
+ /* write flat interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_0_FLAT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_0_FLAT_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_0_FLAT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * interrupt enable byte1 from the register 0x51 bit 0 to 6
+ * @brief It read the high_g_x,high_g_y,high_g_z,low_g_enable
+ * data ready, fifo full and fifo water mark.
+ *
+ *
+ *
+ * @param v_enable_u8 : The value of interrupt enable
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_HIGH_G_X_ENABLE
+ * 1 | BMI160_HIGH_G_Y_ENABLE
+ * 2 | BMI160_HIGH_G_Z_ENABLE
+ * 3 | BMI160_LOW_G_ENABLE
+ * 4 | BMI160_DATA_RDY_ENABLE
+ * 5 | BMI160_FIFO_FULL_ENABLE
+ * 6 | BMI160_FIFO_WM_ENABLE
+ *
+ * @param v_intr_enable_1_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_enable_1(
+u8 v_enable_u8, u8 *v_intr_enable_1_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case BMI160_HIGH_G_X_ENABLE:
+ /* read high_g_x interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE);
+ break;
+ case BMI160_HIGH_G_Y_ENABLE:
+ /* read high_g_y interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE);
+ break;
+ case BMI160_HIGH_G_Z_ENABLE:
+ /* read high_g_z interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE);
+ break;
+ case BMI160_LOW_G_ENABLE:
+ /* read low_g interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE);
+ break;
+ case BMI160_DATA_RDY_ENABLE:
+ /* read data ready interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_DATA_RDY_ENABLE);
+ break;
+ case BMI160_FIFO_FULL_ENABLE:
+ /* read fifo full interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE);
+ break;
+ case BMI160_FIFO_WM_ENABLE:
+ /* read fifo water mark interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_FIFO_WM_ENABLE);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * interrupt enable byte1 from the register 0x51 bit 0 to 6
+ * @brief It read the high_g_x,high_g_y,high_g_z,low_g_enable
+ * data ready, fifo full and fifo water mark.
+ *
+ *
+ *
+ * @param v_enable_u8 : The value of interrupt enable
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_HIGH_G_X_ENABLE
+ * 1 | BMI160_HIGH_G_Y_ENABLE
+ * 2 | BMI160_HIGH_G_Z_ENABLE
+ * 3 | BMI160_LOW_G_ENABLE
+ * 4 | BMI160_DATA_RDY_ENABLE
+ * 5 | BMI160_FIFO_FULL_ENABLE
+ * 6 | BMI160_FIFO_WM_ENABLE
+ *
+ * @param v_intr_enable_1_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_enable_1(
+u8 v_enable_u8, u8 v_intr_enable_1_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case BMI160_HIGH_G_X_ENABLE:
+ /* write high_g_x interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_HIGH_G_Y_ENABLE:
+ /* write high_g_y interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_HIGH_G_Z_ENABLE:
+ /* write high_g_z interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_LOW_G_ENABLE:
+ /* write low_g interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_DATA_RDY_ENABLE:
+ /* write data ready interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_DATA_RDY_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_FIFO_FULL_ENABLE:
+ /* write fifo full interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_FIFO_WM_ENABLE:
+ /* write fifo water mark interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_1_FIFO_WM_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * interrupt enable byte2 from the register bit 0x52 bit 0 to 3
+ * @brief It reads no motion x,y and z
+ *
+ *
+ *
+ * @param v_enable_u8: The value of interrupt enable
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_NOMOTION_X_ENABLE
+ * 1 | BMI160_NOMOTION_Y_ENABLE
+ * 2 | BMI160_NOMOTION_Z_ENABLE
+ *
+ * @param v_intr_enable_2_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_enable_2(
+u8 v_enable_u8, u8 *v_intr_enable_2_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case BMI160_NOMOTION_X_ENABLE:
+ /* read no motion x */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_2_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE);
+ break;
+ case BMI160_NOMOTION_Y_ENABLE:
+ /* read no motion y */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_2_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE);
+ break;
+ case BMI160_NOMOTION_Z_ENABLE:
+ /* read no motion z */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_2_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * interrupt enable byte2 from the register bit 0x52 bit 0 to 3
+ * @brief It reads no motion x,y and z
+ *
+ *
+ *
+ * @param v_enable_u8: The value of interrupt enable
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_NOMOTION_X_ENABLE
+ * 1 | BMI160_NOMOTION_Y_ENABLE
+ * 2 | BMI160_NOMOTION_Z_ENABLE
+ *
+ * @param v_intr_enable_2_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_enable_2(
+u8 v_enable_u8, u8 v_intr_enable_2_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case BMI160_NOMOTION_X_ENABLE:
+ /* write no motion x */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE,
+ v_intr_enable_2_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_NOMOTION_Y_ENABLE:
+ /* write no motion y */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE,
+ v_intr_enable_2_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_NOMOTION_Z_ENABLE:
+ /* write no motion z */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE,
+ v_intr_enable_2_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to read
+ * interrupt enable step detector interrupt from
+ * the register bit 0x52 bit 3
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The value of step detector interrupt enable
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_step_detector_enable(
+u8 *v_step_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the step detector interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_step_intr_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to set
+ * interrupt enable step detector interrupt from
+ * the register bit 0x52 bit 3
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The value of step detector interrupt enable
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_step_detector_enable(
+u8 v_step_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE,
+ v_step_intr_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Configure trigger condition of interrupt1
+ * and interrupt2 pin from the register 0x53
+ * @brief interrupt1 - bit 0
+ * @brief interrupt2 - bit 4
+ *
+ * @param v_channel_u8: The value of edge trigger selection
+ * v_channel_u8 | Edge trigger
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_EDGE_CTRL
+ * 1 | BMI160_INTR2_EDGE_CTRL
+ *
+ * @param v_intr_edge_ctrl_u8 : The value of edge trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_EDGE
+ * 0x00 | BMI160_LEVEL
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_edge_ctrl(
+u8 v_channel_u8, u8 *v_intr_edge_ctrl_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case BMI160_INTR1_EDGE_CTRL:
+ /* read the edge trigger interrupt1*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_EDGE_CTRL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_edge_ctrl_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_EDGE_CTRL);
+ break;
+ case BMI160_INTR2_EDGE_CTRL:
+ /* read the edge trigger interrupt2*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_EDGE_CTRL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_edge_ctrl_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_EDGE_CTRL);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Configure trigger condition of interrupt1
+ * and interrupt2 pin from the register 0x53
+ * @brief interrupt1 - bit 0
+ * @brief interrupt2 - bit 4
+ *
+ * @param v_channel_u8: The value of edge trigger selection
+ * v_channel_u8 | Edge trigger
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_EDGE_CTRL
+ * 1 | BMI160_INTR2_EDGE_CTRL
+ *
+ * @param v_intr_edge_ctrl_u8 : The value of edge trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_EDGE
+ * 0x00 | BMI160_LEVEL
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_edge_ctrl(
+u8 v_channel_u8, u8 v_intr_edge_ctrl_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case BMI160_INTR1_EDGE_CTRL:
+ /* write the edge trigger interrupt1*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_EDGE_CTRL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_EDGE_CTRL,
+ v_intr_edge_ctrl_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_EDGE_CTRL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_EDGE_CTRL:
+ /* write the edge trigger interrupt2*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_EDGE_CTRL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_EDGE_CTRL,
+ v_intr_edge_ctrl_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_EDGE_CTRL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used for get the Configure level condition of interrupt1
+ * and interrupt2 pin form the register 0x53
+ * @brief interrupt1 - bit 1
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of level condition selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_LEVEL
+ * 1 | BMI160_INTR2_LEVEL
+ *
+ * @param v_intr_level_u8 : The value of level of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_LEVEL_HIGH
+ * 0x00 | BMI160_LEVEL_LOW
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_level(
+u8 v_channel_u8, u8 *v_intr_level_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case BMI160_INTR1_LEVEL:
+ /* read the interrupt1 level*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_LEVEL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_level_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_LEVEL);
+ break;
+ case BMI160_INTR2_LEVEL:
+ /* read the interrupt2 level*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_LEVEL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_level_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_LEVEL);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used for set the Configure level condition of interrupt1
+ * and interrupt2 pin form the register 0x53
+ * @brief interrupt1 - bit 1
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of level condition selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_LEVEL
+ * 1 | BMI160_INTR2_LEVEL
+ *
+ * @param v_intr_level_u8 : The value of level of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_LEVEL_HIGH
+ * 0x00 | BMI160_LEVEL_LOW
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_level(
+u8 v_channel_u8, u8 v_intr_level_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case BMI160_INTR1_LEVEL:
+ /* write the interrupt1 level*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_LEVEL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_LEVEL, v_intr_level_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_LEVEL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_LEVEL:
+ /* write the interrupt2 level*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_LEVEL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_LEVEL, v_intr_level_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_LEVEL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used to get configured output enable of interrupt1
+ * and interrupt2 from the register 0x53
+ * @brief interrupt1 - bit 2
+ * @brief interrupt2 - bit 6
+ *
+ *
+ * @param v_channel_u8: The value of output type enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_OUTPUT_TYPE
+ * 1 | BMI160_INTR2_OUTPUT_TYPE
+ *
+ * @param v_intr_output_type_u8 :
+ * The value of output type of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_OPEN_DRAIN
+ * 0x00 | BMI160_PUSH_PULL
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_output_type(
+u8 v_channel_u8, u8 *v_intr_output_type_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case BMI160_INTR1_OUTPUT_TYPE:
+ /* read the output type of interrupt1*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_OUTPUT_TYPE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_output_type_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_OUTPUT_TYPE);
+ break;
+ case BMI160_INTR2_OUTPUT_TYPE:
+ /* read the output type of interrupt2*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_OUTPUT_TYPE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_output_type_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_OUTPUT_TYPE);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used to set output enable of interrupt1
+ * and interrupt2 from the register 0x53
+ * @brief interrupt1 - bit 2
+ * @brief interrupt2 - bit 6
+ *
+ *
+ * @param v_channel_u8: The value of output type enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_OUTPUT_TYPE
+ * 1 | BMI160_INTR2_OUTPUT_TYPE
+ *
+ * @param v_intr_output_type_u8 :
+ * The value of output type of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_OPEN_DRAIN
+ * 0x00 | BMI160_PUSH_PULL
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_output_type(
+u8 v_channel_u8, u8 v_intr_output_type_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case BMI160_INTR1_OUTPUT_TYPE:
+ /* write the output type of interrupt1*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_OUTPUT_TYPE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_OUTPUT_TYPE,
+ v_intr_output_type_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_OUTPUT_TYPE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_OUTPUT_TYPE:
+ /* write the output type of interrupt2*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_OUTPUT_TYPE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_OUTPUT_TYPE,
+ v_intr_output_type_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_OUTPUT_TYPE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief API used to get the Output enable for interrupt1
+ * and interrupt1 pin from the register 0x53
+ * @brief interrupt1 - bit 3
+ * @brief interrupt2 - bit 7
+ *
+ * @param v_channel_u8: The value of output enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_OUTPUT_TYPE
+ * 1 | BMI160_INTR2_OUTPUT_TYPE
+ *
+ * @param v_output_enable_u8 :
+ * The value of output enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_INPUT
+ * 0x00 | BMI160_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_output_enable(
+u8 v_channel_u8, u8 *v_output_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case BMI160_INTR1_OUTPUT_ENABLE:
+ /* read the output enable of interrupt1*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_OUTPUT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_enable_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_OUTPUT_ENABLE);
+ break;
+ case BMI160_INTR2_OUTPUT_ENABLE:
+ /* read the output enable of interrupt2*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_OUTPUT_EN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_enable_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_OUTPUT_EN);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief API used to set the Output enable for interrupt1
+ * and interrupt1 pin from the register 0x53
+ * @brief interrupt1 - bit 3
+ * @brief interrupt2 - bit 7
+ *
+ * @param v_channel_u8: The value of output enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_OUTPUT_TYPE
+ * 1 | BMI160_INTR2_OUTPUT_TYPE
+ *
+ * @param v_output_enable_u8 :
+ * The value of output enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_INPUT
+ * 0x00 | BMI160_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_output_enable(
+u8 v_channel_u8, u8 v_output_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case BMI160_INTR1_OUTPUT_ENABLE:
+ /* write the output enable of interrupt1*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_OUTPUT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_OUTPUT_ENABLE,
+ v_output_enable_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_OUTPUT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_OUTPUT_ENABLE:
+ /* write the output enable of interrupt2*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_OUTPUT_EN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_OUTPUT_EN,
+ v_output_enable_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_OUTPUT_EN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+* @brief This API is used to get the latch duration
+* from the register 0x54 bit 0 to 3
+* @brief This latch selection is not applicable for data ready,
+* orientation and flat interrupts.
+*
+*
+*
+* @param v_latch_intr_u8 : The value of latch duration
+* Latch Duration | value
+* --------------------------------------|------------------
+* BMI160_LATCH_DUR_NONE | 0x00
+* BMI160_LATCH_DUR_312_5_MICRO_SEC | 0x01
+* BMI160_LATCH_DUR_625_MICRO_SEC | 0x02
+* BMI160_LATCH_DUR_1_25_MILLI_SEC | 0x03
+* BMI160_LATCH_DUR_2_5_MILLI_SEC | 0x04
+* BMI160_LATCH_DUR_5_MILLI_SEC | 0x05
+* BMI160_LATCH_DUR_10_MILLI_SEC | 0x06
+* BMI160_LATCH_DUR_20_MILLI_SEC | 0x07
+* BMI160_LATCH_DUR_40_MILLI_SEC | 0x08
+* BMI160_LATCH_DUR_80_MILLI_SEC | 0x09
+* BMI160_LATCH_DUR_160_MILLI_SEC | 0x0A
+* BMI160_LATCH_DUR_320_MILLI_SEC | 0x0B
+* BMI160_LATCH_DUR_640_MILLI_SEC | 0x0C
+* BMI160_LATCH_DUR_1_28_SEC | 0x0D
+* BMI160_LATCH_DUR_2_56_SEC | 0x0E
+* BMI160_LATCHED | 0x0F
+*
+*
+*
+* @return results of bus communication function
+* @retval 0 -> Success
+* @retval -1 -> Error
+*
+*
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_latch_intr(
+u8 *v_latch_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the latch duration value */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_LATCH__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_latch_intr_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LATCH);
+ }
+ return com_rslt;
+}
+/*!
+* @brief This API is used to set the latch duration
+* from the register 0x54 bit 0 to 3
+* @brief This latch selection is not applicable for data ready,
+* orientation and flat interrupts.
+*
+*
+*
+* @param v_latch_intr_u8 : The value of latch duration
+* Latch Duration | value
+* --------------------------------------|------------------
+* BMI160_LATCH_DUR_NONE | 0x00
+* BMI160_LATCH_DUR_312_5_MICRO_SEC | 0x01
+* BMI160_LATCH_DUR_625_MICRO_SEC | 0x02
+* BMI160_LATCH_DUR_1_25_MILLI_SEC | 0x03
+* BMI160_LATCH_DUR_2_5_MILLI_SEC | 0x04
+* BMI160_LATCH_DUR_5_MILLI_SEC | 0x05
+* BMI160_LATCH_DUR_10_MILLI_SEC | 0x06
+* BMI160_LATCH_DUR_20_MILLI_SEC | 0x07
+* BMI160_LATCH_DUR_40_MILLI_SEC | 0x08
+* BMI160_LATCH_DUR_80_MILLI_SEC | 0x09
+* BMI160_LATCH_DUR_160_MILLI_SEC | 0x0A
+* BMI160_LATCH_DUR_320_MILLI_SEC | 0x0B
+* BMI160_LATCH_DUR_640_MILLI_SEC | 0x0C
+* BMI160_LATCH_DUR_1_28_SEC | 0x0D
+* BMI160_LATCH_DUR_2_56_SEC | 0x0E
+* BMI160_LATCHED | 0x0F
+*
+*
+*
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+*
+*
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_latch_intr(u8 v_latch_intr_u8)
+{
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_latch_intr_u8 <= BMI160_MAX_LATCH_INTR) {
+ /* write the latch duration value */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_LATCH__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LATCH, v_latch_intr_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_LATCH__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used to get input enable for interrupt1
+ * and interrupt2 pin from the register 0x54
+ * @brief interrupt1 - bit 4
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of input enable selection
+ * v_channel_u8 | input selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_INPUT_ENABLE
+ * 1 | BMI160_INTR2_INPUT_ENABLE
+ *
+ * @param v_input_en_u8 :
+ * The value of input enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_INPUT
+ * 0x00 | BMI160_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_input_enable(
+u8 v_channel_u8, u8 *v_input_en_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read input enable of interrup1 and interrupt2*/
+ case BMI160_INTR1_INPUT_ENABLE:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_INPUT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_input_en_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_INPUT_ENABLE);
+ break;
+ case BMI160_INTR2_INPUT_ENABLE:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_INPUT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_input_en_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_INPUT_ENABLE);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used to set input enable for interrupt1
+ * and interrupt2 pin from the register 0x54
+ * @brief interrupt1 - bit 4
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of input enable selection
+ * v_channel_u8 | input selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_INPUT_ENABLE
+ * 1 | BMI160_INTR2_INPUT_ENABLE
+ *
+ * @param v_input_en_u8 :
+ * The value of input enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_INPUT
+ * 0x00 | BMI160_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_input_enable(
+u8 v_channel_u8, u8 v_input_en_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write input enable of interrup1 and interrupt2*/
+ case BMI160_INTR1_INPUT_ENABLE:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_INPUT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR1_INPUT_ENABLE, v_input_en_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR1_INPUT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_INPUT_ENABLE:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_INPUT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR2_INPUT_ENABLE, v_input_en_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR2_INPUT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief reads the Low g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 0 in the register 0x55
+ * @brief interrupt2 bit 0 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of low_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_LOW_G
+ * 1 | BMI160_INTR2_MAP_LOW_G
+ *
+ * @param v_intr_low_g_u8 : The value of low_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g(
+u8 v_channel_u8, u8 *v_intr_low_g_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the low_g interrupt */
+ case BMI160_INTR1_MAP_LOW_G:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_low_g_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_LOW_G);
+ break;
+ case BMI160_INTR2_MAP_LOW_G:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_low_g_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_LOW_G);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief set the Low g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 0 in the register 0x55
+ * @brief interrupt2 bit 0 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of low_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_LOW_G
+ * 1 | BMI160_INTR2_MAP_LOW_G
+ *
+ * @param v_intr_low_g_u8 : The value of low_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g(
+u8 v_channel_u8, u8 v_intr_low_g_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+u8 v_step_cnt_stat_u8 = BMI160_INIT_VALUE;
+u8 v_step_det_stat_u8 = BMI160_INIT_VALUE;
+
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* check the step detector interrupt enable status*/
+ com_rslt = bmi160_get_step_detector_enable(&v_step_det_stat_u8);
+ /* disable the step detector interrupt */
+ if (v_step_det_stat_u8 != BMI160_INIT_VALUE)
+ com_rslt += bmi160_set_step_detector_enable(BMI160_INIT_VALUE);
+ /* check the step counter interrupt enable status*/
+ com_rslt += bmi160_get_step_counter_enable(&v_step_cnt_stat_u8);
+ /* disable the step counter interrupt */
+ if (v_step_cnt_stat_u8 != BMI160_INIT_VALUE)
+ com_rslt += bmi160_set_step_counter_enable(
+ BMI160_INIT_VALUE);
+ switch (v_channel_u8) {
+ /* write the low_g interrupt*/
+ case BMI160_INTR1_MAP_LOW_G:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_LOW_G, v_intr_low_g_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_LOW_G:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_LOW_G, v_intr_low_g_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the HIGH g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 1 in the register 0x55
+ * @brief interrupt2 bit 1 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of high_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_HIGH_G
+ * 1 | BMI160_INTR2_MAP_HIGH_G
+ *
+ * @param v_intr_high_g_u8 : The value of high_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_high_g(
+u8 v_channel_u8, u8 *v_intr_high_g_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the high_g interrupt*/
+ switch (v_channel_u8) {
+ case BMI160_INTR1_MAP_HIGH_G:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_HIGH_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_high_g_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_HIGH_G);
+ break;
+ case BMI160_INTR2_MAP_HIGH_G:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_HIGH_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_high_g_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_HIGH_G);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the HIGH g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 1 in the register 0x55
+ * @brief interrupt2 bit 1 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of high_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_HIGH_G
+ * 1 | BMI160_INTR2_MAP_HIGH_G
+ *
+ * @param v_intr_high_g_u8 : The value of high_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_high_g(
+u8 v_channel_u8, u8 v_intr_high_g_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the high_g interrupt*/
+ case BMI160_INTR1_MAP_HIGH_G:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_HIGH_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_HIGH_G, v_intr_high_g_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_HIGH_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_HIGH_G:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_HIGH_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_HIGH_G, v_intr_high_g_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_HIGH_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the Any motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 2 in the register 0x55
+ * @brief interrupt2 bit 2 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of any motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_ANY_MOTION
+ * 1 | BMI160_INTR2_MAP_ANY_MOTION
+ *
+ * @param v_intr_any_motion_u8 : The value of any motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_any_motion(
+u8 v_channel_u8, u8 *v_intr_any_motion_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the any motion interrupt */
+ case BMI160_INTR1_MAP_ANY_MOTION:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_any_motion_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION);
+ break;
+ case BMI160_INTR2_MAP_ANY_MOTION:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_any_motion_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the Any motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 2 in the register 0x55
+ * @brief interrupt2 bit 2 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of any motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_ANY_MOTION
+ * 1 | BMI160_INTR2_MAP_ANY_MOTION
+ *
+ * @param v_intr_any_motion_u8 : The value of any motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_any_motion(
+u8 v_channel_u8, u8 v_intr_any_motion_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+u8 sig_mot_stat = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the status of significant motion interrupt */
+ com_rslt = bmi160_get_intr_significant_motion_select(&sig_mot_stat);
+ /* disable the significant motion interrupt */
+ if (sig_mot_stat != BMI160_INIT_VALUE)
+ com_rslt += bmi160_set_intr_significant_motion_select(
+ BMI160_INIT_VALUE);
+ switch (v_channel_u8) {
+ /* write the any motion interrupt */
+ case BMI160_INTR1_MAP_ANY_MOTION:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION,
+ v_intr_any_motion_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_ANY_MOTION:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION,
+ v_intr_any_motion_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the No motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 3 in the register 0x55
+ * @brief interrupt2 bit 3 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of no motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_NOMO
+ * 1 | BMI160_INTR2_MAP_NOMO
+ *
+ * @param v_intr_nomotion_u8 : The value of no motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_nomotion(
+u8 v_channel_u8, u8 *v_intr_nomotion_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the no motion interrupt*/
+ case BMI160_INTR1_MAP_NOMO:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_NOMOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_nomotion_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_NOMOTION);
+ break;
+ case BMI160_INTR2_MAP_NOMO:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_NOMOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_nomotion_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_NOMOTION);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the No motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 3 in the register 0x55
+ * @brief interrupt2 bit 3 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of no motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_NOMO
+ * 1 | BMI160_INTR2_MAP_NOMO
+ *
+ * @param v_intr_nomotion_u8 : The value of no motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_nomotion(
+u8 v_channel_u8, u8 v_intr_nomotion_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the no motion interrupt*/
+ case BMI160_INTR1_MAP_NOMO:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_NOMOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_NOMOTION,
+ v_intr_nomotion_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_NOMOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_NOMO:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_NOMOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_NOMOTION,
+ v_intr_nomotion_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_NOMOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the Double Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 4 in the register 0x55
+ * @brief interrupt2 bit 4 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of double tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_DOUBLE_TAP
+ * 1 | BMI160_INTR2_MAP_DOUBLE_TAP
+ *
+ * @param v_intr_double_tap_u8 : The value of double tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_double_tap(
+u8 v_channel_u8, u8 *v_intr_double_tap_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case BMI160_INTR1_MAP_DOUBLE_TAP:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_double_tap_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_DOUBLE_TAP);
+ break;
+ case BMI160_INTR2_MAP_DOUBLE_TAP:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_double_tap_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_DOUBLE_TAP);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the Double Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 4 in the register 0x55
+ * @brief interrupt2 bit 4 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of double tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_DOUBLE_TAP
+ * 1 | BMI160_INTR2_MAP_DOUBLE_TAP
+ *
+ * @param v_intr_double_tap_u8 : The value of double tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_double_tap(
+u8 v_channel_u8, u8 v_intr_double_tap_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* set the double tap interrupt */
+ case BMI160_INTR1_MAP_DOUBLE_TAP:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_DOUBLE_TAP,
+ v_intr_double_tap_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_DOUBLE_TAP:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_DOUBLE_TAP,
+ v_intr_double_tap_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the Single Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 5 in the register 0x55
+ * @brief interrupt2 bit 5 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of single tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_SINGLE_TAP
+ * 1 | BMI160_INTR2_MAP_SINGLE_TAP
+ *
+ * @param v_intr_single_tap_u8 : The value of single tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_single_tap(
+u8 v_channel_u8, u8 *v_intr_single_tap_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* reads the single tap interrupt*/
+ case BMI160_INTR1_MAP_SINGLE_TAP:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_SINGLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_single_tap_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_SINGLE_TAP);
+ break;
+ case BMI160_INTR2_MAP_SINGLE_TAP:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_SINGLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_single_tap_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_SINGLE_TAP);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the Single Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 5 in the register 0x55
+ * @brief interrupt2 bit 5 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of single tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_SINGLE_TAP
+ * 1 | BMI160_INTR2_MAP_SINGLE_TAP
+ *
+ * @param v_intr_single_tap_u8 : The value of single tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_single_tap(
+u8 v_channel_u8, u8 v_intr_single_tap_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the single tap interrupt */
+ case BMI160_INTR1_MAP_SINGLE_TAP:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_SINGLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_SINGLE_TAP,
+ v_intr_single_tap_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_SINGLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_SINGLE_TAP:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_SINGLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_SINGLE_TAP,
+ v_intr_single_tap_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_SINGLE_TAP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the Orient interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 6 in the register 0x55
+ * @brief interrupt2 bit 6 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of orient interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_ORIENT
+ * 1 | BMI160_INTR2_MAP_ORIENT
+ *
+ * @param v_intr_orient_u8 : The value of orient enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient(
+u8 v_channel_u8, u8 *v_intr_orient_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the orientation interrupt*/
+ case BMI160_INTR1_MAP_ORIENT:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_ORIENT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_orient_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_ORIENT);
+ break;
+ case BMI160_INTR2_MAP_ORIENT:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_ORIENT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_orient_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_ORIENT);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the Orient interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 6 in the register 0x55
+ * @brief interrupt2 bit 6 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of orient interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_ORIENT
+ * 1 | BMI160_INTR2_MAP_ORIENT
+ *
+ * @param v_intr_orient_u8 : The value of orient enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient(
+u8 v_channel_u8, u8 v_intr_orient_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the orientation interrupt*/
+ case BMI160_INTR1_MAP_ORIENT:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_ORIENT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_ORIENT, v_intr_orient_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_ORIENT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_ORIENT:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_ORIENT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_ORIENT, v_intr_orient_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_ORIENT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief Reads the Flat interrupt
+ * mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 7 in the register 0x55
+ * @brief interrupt2 bit 7 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of flat interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FLAT
+ * 1 | BMI160_INTR2_MAP_FLAT
+ *
+ * @param v_intr_flat_u8 : The value of flat enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_flat(
+u8 v_channel_u8, u8 *v_intr_flat_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the flat interrupt*/
+ case BMI160_INTR1_MAP_FLAT:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_FLAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_flat_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_FLAT);
+ break;
+ case BMI160_INTR2_MAP_FLAT:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_FLAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_flat_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_FLAT);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief Write the Flat interrupt
+ * mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 7 in the register 0x55
+ * @brief interrupt2 bit 7 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of flat interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FLAT
+ * 1 | BMI160_INTR2_MAP_FLAT
+ *
+ * @param v_intr_flat_u8 : The value of flat enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_flat(
+u8 v_channel_u8, u8 v_intr_flat_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the flat interrupt */
+ case BMI160_INTR1_MAP_FLAT:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_0_INTR1_FLAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_0_INTR1_FLAT,
+ v_intr_flat_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_MAP_0_INTR1_FLAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_FLAT:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_2_INTR2_FLAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_2_INTR2_FLAT,
+ v_intr_flat_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_MAP_2_INTR2_FLAT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Reads PMU trigger interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 0 and 4
+ * @brief interrupt1 bit 0 in the register 0x56
+ * @brief interrupt2 bit 4 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of pmu trigger selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_PMUTRIG
+ * 1 | BMI160_INTR2_MAP_PMUTRIG
+ *
+ * @param v_intr_pmu_trig_u8 : The value of pmu trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_pmu_trig(
+u8 v_channel_u8, u8 *v_intr_pmu_trig_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the pmu trigger interrupt*/
+ case BMI160_INTR1_MAP_PMUTRIG:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_PMU_TRIG__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_pmu_trig_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR1_PMU_TRIG);
+ break;
+ case BMI160_INTR2_MAP_PMUTRIG:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_PMU_TRIG__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_pmu_trig_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR2_PMU_TRIG);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write PMU trigger interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 0 and 4
+ * @brief interrupt1 bit 0 in the register 0x56
+ * @brief interrupt2 bit 4 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of pmu trigger selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_PMUTRIG
+ * 1 | BMI160_INTR2_MAP_PMUTRIG
+ *
+ * @param v_intr_pmu_trig_u8 : The value of pmu trigger enable
+ * value | trigger enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_pmu_trig(
+u8 v_channel_u8, u8 v_intr_pmu_trig_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the pmu trigger interrupt */
+ case BMI160_INTR1_MAP_PMUTRIG:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_PMU_TRIG__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR1_PMU_TRIG,
+ v_intr_pmu_trig_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_PMU_TRIG__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_PMUTRIG:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_PMU_TRIG__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR2_PMU_TRIG,
+ v_intr_pmu_trig_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_PMU_TRIG__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads FIFO Full interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 5 and 1
+ * @brief interrupt1 bit 5 in the register 0x56
+ * @brief interrupt2 bit 1 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo full interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FIFO_FULL
+ * 1 | BMI160_INTR2_MAP_FIFO_FULL
+ *
+ * @param v_intr_fifo_full_u8 : The value of fifo full interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_fifo_full(
+u8 v_channel_u8, u8 *v_intr_fifo_full_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the fifo full interrupt */
+ case BMI160_INTR1_MAP_FIFO_FULL:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_FIFO_FULL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_fifo_full_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR1_FIFO_FULL);
+ break;
+ case BMI160_INTR2_MAP_FIFO_FULL:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_FIFO_FULL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_fifo_full_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR2_FIFO_FULL);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write FIFO Full interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 5 and 1
+ * @brief interrupt1 bit 5 in the register 0x56
+ * @brief interrupt2 bit 1 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo full interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FIFO_FULL
+ * 1 | BMI160_INTR2_MAP_FIFO_FULL
+ *
+ * @param v_intr_fifo_full_u8 : The value of fifo full interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_fifo_full(
+u8 v_channel_u8, u8 v_intr_fifo_full_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the fifo full interrupt */
+ case BMI160_INTR1_MAP_FIFO_FULL:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_FIFO_FULL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR1_FIFO_FULL,
+ v_intr_fifo_full_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_MAP_1_INTR1_FIFO_FULL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_FIFO_FULL:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_FIFO_FULL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR2_FIFO_FULL,
+ v_intr_fifo_full_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_MAP_1_INTR2_FIFO_FULL__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Reads FIFO Watermark interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 6 and 2
+ * @brief interrupt1 bit 6 in the register 0x56
+ * @brief interrupt2 bit 2 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo Watermark interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FIFO_WM
+ * 1 | BMI160_INTR2_MAP_FIFO_WM
+ *
+ * @param v_intr_fifo_wm_u8 : The value of fifo Watermark interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_fifo_wm(
+u8 v_channel_u8, u8 *v_intr_fifo_wm_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the fifo water mark interrupt */
+ case BMI160_INTR1_MAP_FIFO_WM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_FIFO_WM__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_fifo_wm_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR1_FIFO_WM);
+ break;
+ case BMI160_INTR2_MAP_FIFO_WM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_FIFO_WM__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_fifo_wm_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR2_FIFO_WM);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write FIFO Watermark interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 6 and 2
+ * @brief interrupt1 bit 6 in the register 0x56
+ * @brief interrupt2 bit 2 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo Watermark interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FIFO_WM
+ * 1 | BMI160_INTR2_MAP_FIFO_WM
+ *
+ * @param v_intr_fifo_wm_u8 : The value of fifo Watermark interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_fifo_wm(
+u8 v_channel_u8, u8 v_intr_fifo_wm_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the fifo water mark interrupt */
+ case BMI160_INTR1_MAP_FIFO_WM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_FIFO_WM__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR1_FIFO_WM,
+ v_intr_fifo_wm_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_MAP_1_INTR1_FIFO_WM__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_FIFO_WM:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_FIFO_WM__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR2_FIFO_WM,
+ v_intr_fifo_wm_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr,
+ BMI160_USER_INTR_MAP_1_INTR2_FIFO_WM__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Reads Data Ready interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56
+ * @brief interrupt1 bit 7 in the register 0x56
+ * @brief interrupt2 bit 3 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of data ready interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_DATA_RDY
+ * 1 | BMI160_INTR2_MAP_DATA_RDY
+ *
+ * @param v_intr_data_rdy_u8 : The value of data ready interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_data_rdy(
+u8 v_channel_u8, u8 *v_intr_data_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /*Read Data Ready interrupt*/
+ case BMI160_INTR1_MAP_DATA_RDY:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_DATA_RDY__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_data_rdy_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR1_DATA_RDY);
+ break;
+ case BMI160_INTR2_MAP_DATA_RDY:
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_DATA_RDY__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_data_rdy_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR2_DATA_RDY);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write Data Ready interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56
+ * @brief interrupt1 bit 7 in the register 0x56
+ * @brief interrupt2 bit 3 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of data ready interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_DATA_RDY
+ * 1 | BMI160_INTR2_MAP_DATA_RDY
+ *
+ * @param v_intr_data_rdy_u8 : The value of data ready interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_data_rdy(
+u8 v_channel_u8, u8 v_intr_data_rdy_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /*Write Data Ready interrupt*/
+ case BMI160_INTR1_MAP_DATA_RDY:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_DATA_RDY__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR1_DATA_RDY,
+ v_intr_data_rdy_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR1_DATA_RDY__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case BMI160_INTR2_MAP_DATA_RDY:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_DATA_RDY__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MAP_1_INTR2_DATA_RDY,
+ v_intr_data_rdy_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(p_bmi160->
+ dev_addr, BMI160_USER_INTR_MAP_1_INTR2_DATA_RDY__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API reads data source for the interrupt
+ * engine for the single and double tap interrupts from the register
+ * 0x58 bit 3
+ *
+ *
+ * @param v_tap_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_source(u8 *v_tap_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the tap source interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_DATA_0_INTR_TAP_SOURCE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_source_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_DATA_0_INTR_TAP_SOURCE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write data source for the interrupt
+ * engine for the single and double tap interrupts from the register
+ * 0x58 bit 3
+ *
+ *
+ * @param v_tap_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_source(
+u8 v_tap_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_tap_source_u8 <= BMI160_MAX_VALUE_SOURCE_INTR) {
+ /* write the tap source interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_DATA_0_INTR_TAP_SOURCE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_DATA_0_INTR_TAP_SOURCE,
+ v_tap_source_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_DATA_0_INTR_TAP_SOURCE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API Reads Data source for the
+ * interrupt engine for the low and high g interrupts
+ * from the register 0x58 bit 7
+ *
+ * @param v_low_high_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_high_source(
+u8 *v_low_high_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the high_low_g source interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_high_source_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Data source for the
+ * interrupt engine for the low and high g interrupts
+ * from the register 0x58 bit 7
+ *
+ * @param v_low_high_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_high_source(
+u8 v_low_high_source_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_low_high_source_u8 <= BMI160_MAX_VALUE_SOURCE_INTR) {
+ /* write the high_low_g source interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE,
+ v_low_high_source_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API reads Data source for the
+ * interrupt engine for the nomotion and anymotion interrupts
+ * from the register 0x59 bit 7
+ *
+ * @param v_motion_source_u8 :
+ * The value of the any/no motion interrupt source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_motion_source(
+u8 *v_motion_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the any/no motion interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_DATA_1_INTR_MOTION_SOURCE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_motion_source_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_DATA_1_INTR_MOTION_SOURCE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Data source for the
+ * interrupt engine for the nomotion and anymotion interrupts
+ * from the register 0x59 bit 7
+ *
+ * @param v_motion_source_u8 :
+ * The value of the any/no motion interrupt source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_motion_source(
+u8 v_motion_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_motion_source_u8 <= BMI160_MAX_VALUE_SOURCE_INTR) {
+ /* write the any/no motion interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_DATA_1_INTR_MOTION_SOURCE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_DATA_1_INTR_MOTION_SOURCE,
+ v_motion_source_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_DATA_1_INTR_MOTION_SOURCE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to read the low_g duration from register
+ * 0x5A bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_durn_u8 : The value of low_g duration
+ *
+ * @note Low_g duration trigger trigger delay according to
+ * "(v_low_g_durn_u8 * 2.5)ms" in a range from 2.5ms to 640ms.
+ * the default corresponds delay is 20ms
+ * @note When low_g data source of interrupt is unfiltered
+ * the sensor must not be in low power mode
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g_durn(
+u8 *v_low_g_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the low_g interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_g_durn_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_0_INTR_LOW_DURN);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to write the low_g duration from register
+ * 0x5A bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_durn_u8 : The value of low_g duration
+ *
+ * @note Low_g duration trigger trigger delay according to
+ * "(v_low_g_durn_u8 * 2.5)ms" in a range from 2.5ms to 640ms.
+ * the default corresponds delay is 20ms
+ * @note When low_g data source of interrupt is unfiltered
+ * the sensor must not be in low power mode
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g_durn(u8 v_low_g_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write the low_g interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__REG,
+ &v_low_g_durn_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read Threshold
+ * definition for the low-g interrupt from the register 0x5B bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_thres_u8 : The value of low_g threshold
+ *
+ * @note Low_g interrupt trigger threshold according to
+ * (v_low_g_thres_u8 * 7.81)mg for v_low_g_thres_u8 > 0
+ * 3.91 mg for v_low_g_thres_u8 = 0
+ * The threshold range is form 3.91mg to 2.000mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g_thres(
+u8 *v_low_g_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read low_g threshold */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_g_thres_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_1_INTR_LOW_THRES);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write Threshold
+ * definition for the low-g interrupt from the register 0x5B bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_thres_u8 : The value of low_g threshold
+ *
+ * @note Low_g interrupt trigger threshold according to
+ * (v_low_g_thres_u8 * 7.81)mg for v_low_g_thres_u8 > 0
+ * 3.91 mg for v_low_g_thres_u8 = 0
+ * The threshold range is form 3.91mg to 2.000mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g_thres(
+u8 v_low_g_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write low_g threshold */
+ com_rslt = p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__REG,
+ &v_low_g_thres_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API Reads Low-g interrupt hysteresis
+ * from the register 0x5C bit 0 to 1
+ *
+ * @param v_low_hyst_u8 :The value of low_g hysteresis
+ *
+ * @note Low_g hysteresis calculated by v_low_hyst_u8*125 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g_hyst(
+u8 *v_low_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read low_g hysteresis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_hyst_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Low-g interrupt hysteresis
+ * from the register 0x5C bit 0 to 1
+ *
+ * @param v_low_hyst_u8 :The value of low_g hysteresis
+ *
+ * @note Low_g hysteresis calculated by v_low_hyst_u8*125 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g_hyst(
+u8 v_low_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write low_g hysteresis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST,
+ v_low_hyst_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads Low-g interrupt mode
+ * from the register 0x5C bit 2
+ *
+ * @param v_low_g_mode_u8 : The value of low_g mode
+ * Value | Description
+ * ----------|-----------------
+ * 0 | single-axis
+ * 1 | axis-summing
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g_mode(u8 *v_low_g_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /*read Low-g interrupt mode*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_g_mode_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Low-g interrupt mode
+ * from the register 0x5C bit 2
+ *
+ * @param v_low_g_mode_u8 : The value of low_g mode
+ * Value | Description
+ * ----------|-----------------
+ * 0 | single-axis
+ * 1 | axis-summing
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g_mode(
+u8 v_low_g_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_low_g_mode_u8 <= BMI160_MAX_VALUE_LOW_G_MODE) {
+ /*write Low-g interrupt mode*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE,
+ v_low_g_mode_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads High-g interrupt hysteresis
+ * from the register 0x5C bit 6 and 7
+ *
+ * @param v_high_g_hyst_u8 : The value of high hysteresis
+ *
+ * @note High_g hysteresis changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g hysteresis
+ * ----------------|---------------------
+ * 2g | high_hy*125 mg
+ * 4g | high_hy*250 mg
+ * 8g | high_hy*500 mg
+ * 16g | high_hy*1000 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_high_g_hyst(
+u8 *v_high_g_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read high_g hysteresis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_hyst_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write High-g interrupt hysteresis
+ * from the register 0x5C bit 6 and 7
+ *
+ * @param v_high_g_hyst_u8 : The value of high hysteresis
+ *
+ * @note High_g hysteresis changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g hysteresis
+ * ----------------|---------------------
+ * 2g | high_hy*125 mg
+ * 4g | high_hy*250 mg
+ * 8g | high_hy*500 mg
+ * 16g | high_hy*1000 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_high_g_hyst(
+u8 v_high_g_hyst_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write high_g hysteresis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST,
+ v_high_g_hyst_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read Delay
+ * time definition for the high-g interrupt from the register
+ * 0x5D bit 0 to 7
+ *
+ *
+ *
+ * @param v_high_g_durn_u8 : The value of high duration
+ *
+ * @note High_g interrupt delay triggered according to
+ * v_high_g_durn_u8 * 2.5ms in a range from 2.5ms to 640ms
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_high_g_durn(
+u8 *v_high_g_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read high_g duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_durn_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write Delay
+ * time definition for the high-g interrupt from the register
+ * 0x5D bit 0 to 7
+ *
+ *
+ *
+ * @param v_high_g_durn_u8 : The value of high duration
+ *
+ * @note High_g interrupt delay triggered according to
+ * v_high_g_durn_u8 * 2.5ms in a range from 2.5ms to 640ms
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_high_g_durn(
+u8 v_high_g_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write high_g duration*/
+ com_rslt = p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__REG,
+ &v_high_g_durn_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read Threshold
+ * definition for the high-g interrupt from the register 0x5E 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_high_g_thres_u8 : Pointer holding the value of Threshold
+ * @note High_g threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | v_high_g_thres_u8*7.81 mg
+ * 4g | v_high_g_thres_u8*15.63 mg
+ * 8g | v_high_g_thres_u8*31.25 mg
+ * 16g | v_high_g_thres_u8*62.5 mg
+ * @note when v_high_g_thres_u8 = 0
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | 3.91 mg
+ * 4g | 7.81 mg
+ * 8g | 15.63 mg
+ * 16g | 31.25 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_high_g_thres(
+u8 *v_high_g_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_thres_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write Threshold
+ * definition for the high-g interrupt from the register 0x5E 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_high_g_thres_u8 : Pointer holding the value of Threshold
+ * @note High_g threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | v_high_g_thres_u8*7.81 mg
+ * 4g | v_high_g_thres_u8*15.63 mg
+ * 8g | v_high_g_thres_u8*31.25 mg
+ * 16g | v_high_g_thres_u8*62.5 mg
+ * @note when v_high_g_thres_u8 = 0
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | 3.91 mg
+ * 4g | 7.81 mg
+ * 8g | 15.63 mg
+ * 16g | 31.25 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_high_g_thres(
+u8 v_high_g_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ com_rslt = p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__REG,
+ &v_high_g_thres_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads any motion duration
+ * from the register 0x5F bit 0 and 1
+ *
+ * @param v_any_motion_durn_u8 : The value of any motion duration
+ *
+ * @note Any motion duration can be calculated by "v_any_motion_durn_u8 + 1"
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_any_motion_durn(
+u8 *v_any_motion_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read any motion duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_durn_u8 = BMI160_GET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write any motion duration
+ * from the register 0x5F bit 0 and 1
+ *
+ * @param v_any_motion_durn_u8 : The value of any motion duration
+ *
+ * @note Any motion duration can be calculated by "v_any_motion_durn_u8 + 1"
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_any_motion_durn(
+u8 v_any_motion_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write any motion duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN,
+ v_any_motion_durn_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read Slow/no-motion
+ * interrupt trigger delay duration from the register 0x5F bit 2 to 7
+ *
+ * @param v_slow_no_motion_u8 :The value of slow no motion duration
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * @note v_slow_no_motion_u8(5:4)=0b00 ->
+ * [v_slow_no_motion_u8(3:0) + 1] * 1.28s (1.28s-20.48s)
+ * @note v_slow_no_motion_u8(5:4)=1 ->
+ * [v_slow_no_motion_u8(3:0)+5] * 5.12s (25.6s-102.4s)
+ * @note v_slow_no_motion_u8(5)='1' ->
+ * [(v_slow_no_motion_u8:0)+11] * 10.24s (112.64s-430.08s);
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_slow_no_motion_durn(
+u8 *v_slow_no_motion_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read slow no motion duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_slow_no_motion_u8 = BMI160_GET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN);
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API write Slow/no-motion
+ * interrupt trigger delay duration from the register 0x5F bit 2 to 7
+ *
+ * @param v_slow_no_motion_u8 :The value of slow no motion duration
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * @note v_slow_no_motion_u8(5:4)=0b00 ->
+ * [v_slow_no_motion_u8(3:0) + 1] * 1.28s (1.28s-20.48s)
+ * @note v_slow_no_motion_u8(5:4)=1 ->
+ * [v_slow_no_motion_u8(3:0)+5] * 5.12s (25.6s-102.4s)
+ * @note v_slow_no_motion_u8(5)='1' ->
+ * [(v_slow_no_motion_u8:0)+11] * 10.24s (112.64s-430.08s);
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_slow_no_motion_durn(
+u8 v_slow_no_motion_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write slow no motion duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN,
+ v_slow_no_motion_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read threshold
+ * definition for the any-motion interrupt
+ * from the register 0x60 bit 0 to 7
+ *
+ *
+ * @param v_any_motion_thres_u8 : The value of any motion threshold
+ *
+ * @note any motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | v_any_motion_thres_u8*3.91 mg
+ * 4g | v_any_motion_thres_u8*7.81 mg
+ * 8g | v_any_motion_thres_u8*15.63 mg
+ * 16g | v_any_motion_thres_u8*31.25 mg
+ * @note when v_any_motion_thres_u8 = 0
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_any_motion_thres(
+u8 *v_any_motion_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read any motion threshold*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_thres_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write threshold
+ * definition for the any-motion interrupt
+ * from the register 0x60 bit 0 to 7
+ *
+ *
+ * @param v_any_motion_thres_u8 : The value of any motion threshold
+ *
+ * @note any motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | v_any_motion_thres_u8*3.91 mg
+ * 4g | v_any_motion_thres_u8*7.81 mg
+ * 8g | v_any_motion_thres_u8*15.63 mg
+ * 16g | v_any_motion_thres_u8*31.25 mg
+ * @note when v_any_motion_thres_u8 = 0
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_any_motion_thres(
+u8 v_any_motion_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write any motion threshold*/
+ com_rslt = p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__REG,
+ &v_any_motion_thres_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to read threshold
+ * for the slow/no-motion interrupt
+ * from the register 0x61 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_slow_no_motion_thres_u8 : The value of slow no motion threshold
+ * @note slow no motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | v_slow_no_motion_thres_u8*3.91 mg
+ * 4g | v_slow_no_motion_thres_u8*7.81 mg
+ * 8g | v_slow_no_motion_thres_u8*15.63 mg
+ * 16g | v_slow_no_motion_thres_u8*31.25 mg
+ * @note when v_slow_no_motion_thres_u8 = 0
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_slow_no_motion_thres(
+u8 *v_slow_no_motion_thres_u8)
+{
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read slow no motion threshold*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_slow_no_motion_thres_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES);
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to write threshold
+ * for the slow/no-motion interrupt
+ * from the register 0x61 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_slow_no_motion_thres_u8 : The value of slow no motion threshold
+ * @note slow no motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | v_slow_no_motion_thres_u8*3.91 mg
+ * 4g | v_slow_no_motion_thres_u8*7.81 mg
+ * 8g | v_slow_no_motion_thres_u8*15.63 mg
+ * 16g | v_slow_no_motion_thres_u8*31.25 mg
+ * @note when v_slow_no_motion_thres_u8 = 0
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_slow_no_motion_thres(
+u8 v_slow_no_motion_thres_u8)
+{
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write slow no motion threshold*/
+ com_rslt = p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__REG,
+ &v_slow_no_motion_thres_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to read
+ * the slow/no-motion selection from the register 0x62 bit 0
+ *
+ *
+ *
+ *
+ * @param v_intr_slow_no_motion_select_u8 :
+ * The value of slow/no-motion select
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SLOW_MOTION
+ * 0x01 | NO_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_slow_no_motion_select(
+u8 *v_intr_slow_no_motion_select_u8)
+{
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read slow no motion select*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_slow_no_motion_select_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT);
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to write
+ * the slow/no-motion selection from the register 0x62 bit 0
+ *
+ *
+ *
+ *
+ * @param v_intr_slow_no_motion_select_u8 :
+ * The value of slow/no-motion select
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SLOW_MOTION
+ * 0x01 | NO_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_slow_no_motion_select(
+u8 v_intr_slow_no_motion_select_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+} else {
+if (v_intr_slow_no_motion_select_u8 <= BMI160_MAX_VALUE_NO_MOTION) {
+ /* write slow no motion select*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT,
+ v_intr_slow_no_motion_select_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+} else {
+com_rslt = E_BMI160_OUT_OF_RANGE;
+}
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to select
+ * the significant or any motion interrupt from the register 0x62 bit 1
+ *
+ *
+ *
+ *
+ * @param v_intr_significant_motion_select_u8 :
+ * the value of significant or any motion interrupt selection
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | ANY_MOTION
+ * 0x01 | SIGNIFICANT_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_significant_motion_select(
+u8 *v_intr_significant_motion_select_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the significant or any motion interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_SIGNIFICATION_MOTION_SELECT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_significant_motion_select_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_SIGNIFICATION_MOTION_SELECT);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to write, select
+ * the significant or any motion interrupt from the register 0x62 bit 1
+ *
+ *
+ *
+ *
+ * @param v_intr_significant_motion_select_u8 :
+ * the value of significant or any motion interrupt selection
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | ANY_MOTION
+ * 0x01 | SIGNIFICANT_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_significant_motion_select(
+u8 v_intr_significant_motion_select_u8)
+{
+/* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_intr_significant_motion_select_u8 <=
+ BMI160_MAX_VALUE_SIGNIFICANT_MOTION) {
+ /* write the significant or any motion interrupt*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_SIGNIFICATION_MOTION_SELECT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_SIGNIFICATION_MOTION_SELECT,
+ v_intr_significant_motion_select_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_SIGNIFICATION_MOTION_SELECT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to read
+ * the significant skip time from the register 0x62 bit 2 and 3
+ *
+ *
+ *
+ *
+ * @param v_int_sig_mot_skip_u8 : the value of significant skip time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | skip time 1.5 seconds
+ * 0x01 | skip time 3 seconds
+ * 0x02 | skip time 6 seconds
+ * 0x03 | skip time 12 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_significant_motion_skip(
+u8 *v_int_sig_mot_skip_u8)
+{
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read significant skip time*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_SKIP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_int_sig_mot_skip_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_SKIP);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to write
+ * the significant skip time from the register 0x62 bit 2 and 3
+ *
+ *
+ *
+ *
+ * @param v_int_sig_mot_skip_u8 : the value of significant skip time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | skip time 1.5 seconds
+ * 0x01 | skip time 3 seconds
+ * 0x02 | skip time 6 seconds
+ * 0x03 | skip time 12 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_significant_motion_skip(
+u8 v_int_sig_mot_skip_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_int_sig_mot_skip_u8 <= BMI160_MAX_UNDER_SIG_MOTION) {
+ /* write significant skip time*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_SKIP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_SKIP,
+ v_int_sig_mot_skip_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_SKIP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to read
+ * the significant proof time from the register 0x62 bit 4 and 5
+ *
+ *
+ *
+ *
+ * @param v_significant_motion_proof_u8 :
+ * the value of significant proof time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | proof time 0.25 seconds
+ * 0x01 | proof time 0.5 seconds
+ * 0x02 | proof time 1 seconds
+ * 0x03 | proof time 2 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_significant_motion_proof(
+u8 *v_significant_motion_proof_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read significant proof time */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_PROOF__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_significant_motion_proof_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_PROOF);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to write
+ * the significant proof time from the register 0x62 bit 4 and 5
+ *
+ *
+ *
+ *
+ * @param v_significant_motion_proof_u8 :
+ * the value of significant proof time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | proof time 0.25 seconds
+ * 0x01 | proof time 0.5 seconds
+ * 0x02 | proof time 1 seconds
+ * 0x03 | proof time 2 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_significant_motion_proof(
+u8 v_significant_motion_proof_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_significant_motion_proof_u8
+ <= BMI160_MAX_UNDER_SIG_MOTION) {
+ /* write significant proof time */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_PROOF__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_PROOF,
+ v_significant_motion_proof_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_SIGNIFICANT_MOTION_PROOF__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the tap duration
+ * from the register 0x63 bit 0 to 2
+ *
+ *
+ *
+ * @param v_tap_durn_u8 : The value of tap duration
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_DURN_50MS
+ * 0x01 | BMI160_TAP_DURN_100MS
+ * 0x03 | BMI160_TAP_DURN_150MS
+ * 0x04 | BMI160_TAP_DURN_200MS
+ * 0x05 | BMI160_TAP_DURN_250MS
+ * 0x06 | BMI160_TAP_DURN_375MS
+ * 0x07 | BMI160_TAP_DURN_700MS
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_durn(
+u8 *v_tap_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read tap duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_durn_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_DURN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write the tap duration
+ * from the register 0x63 bit 0 to 2
+ *
+ *
+ *
+ * @param v_tap_durn_u8 : The value of tap duration
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_DURN_50MS
+ * 0x01 | BMI160_TAP_DURN_100MS
+ * 0x03 | BMI160_TAP_DURN_150MS
+ * 0x04 | BMI160_TAP_DURN_200MS
+ * 0x05 | BMI160_TAP_DURN_250MS
+ * 0x06 | BMI160_TAP_DURN_375MS
+ * 0x07 | BMI160_TAP_DURN_700MS
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_durn(
+u8 v_tap_durn_u8)
+{
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_tap_durn_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_tap_durn_u8 <= BMI160_MAX_TAP_TURN) {
+ switch (v_tap_durn_u8) {
+ case BMI160_TAP_DURN_50MS:
+ v_data_tap_durn_u8 = BMI160_TAP_DURN_50MS;
+ break;
+ case BMI160_TAP_DURN_100MS:
+ v_data_tap_durn_u8 = BMI160_TAP_DURN_100MS;
+ break;
+ case BMI160_TAP_DURN_150MS:
+ v_data_tap_durn_u8 = BMI160_TAP_DURN_150MS;
+ break;
+ case BMI160_TAP_DURN_200MS:
+ v_data_tap_durn_u8 = BMI160_TAP_DURN_200MS;
+ break;
+ case BMI160_TAP_DURN_250MS:
+ v_data_tap_durn_u8 = BMI160_TAP_DURN_250MS;
+ break;
+ case BMI160_TAP_DURN_375MS:
+ v_data_tap_durn_u8 = BMI160_TAP_DURN_375MS;
+ break;
+ case BMI160_TAP_DURN_500MS:
+ v_data_tap_durn_u8 = BMI160_TAP_DURN_500MS;
+ break;
+ case BMI160_TAP_DURN_700MS:
+ v_data_tap_durn_u8 = BMI160_TAP_DURN_700MS;
+ break;
+ default:
+ break;
+ }
+ /* write tap duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_DURN,
+ v_data_tap_durn_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_DURN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read the
+ * tap shock duration from the register 0x63 bit 2
+ *
+ * @param v_tap_shock_u8 :The value of tap shock
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_SHOCK_50MS
+ * 0x01 | BMI160_TAP_SHOCK_75MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_shock(
+u8 *v_tap_shock_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read tap shock duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_SHOCK__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_shock_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_SHOCK);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write the
+ * tap shock duration from the register 0x63 bit 2
+ *
+ * @param v_tap_shock_u8 :The value of tap shock
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_SHOCK_50MS
+ * 0x01 | BMI160_TAP_SHOCK_75MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_shock(u8 v_tap_shock_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_tap_shock_u8 <= BMI160_MAX_VALUE_TAP_SHOCK) {
+ /* write tap shock duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_SHOCK__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_SHOCK,
+ v_tap_shock_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_SHOCK__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read
+ * tap quiet duration from the register 0x63 bit 7
+ *
+ *
+ * @param v_tap_quiet_u8 : The value of tap quiet
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_QUIET_30MS
+ * 0x01 | BMI160_TAP_QUIET_20MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_quiet(
+u8 *v_tap_quiet_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read tap quiet duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_QUIET__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_quiet_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_QUIET);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write
+ * tap quiet duration from the register 0x63 bit 7
+ *
+ *
+ * @param v_tap_quiet_u8 : The value of tap quiet
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_QUIET_30MS
+ * 0x01 | BMI160_TAP_QUIET_20MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_quiet(u8 v_tap_quiet_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_tap_quiet_u8 <= BMI160_MAX_VALUE_TAP_QUIET) {
+ /* write tap quiet duration*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_QUIET__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_QUIET,
+ v_tap_quiet_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_0_INTR_TAP_QUIET__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read Threshold of the
+ * single/double tap interrupt from the register 0x64 bit 0 to 4
+ *
+ *
+ * @param v_tap_thres_u8 : The value of single/double tap threshold
+ *
+ * @note single/double tap threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | single/double tap threshold
+ * ----------------|---------------------
+ * 2g | ((v_tap_thres_u8 + 1) * 62.5)mg
+ * 4g | ((v_tap_thres_u8 + 1) * 125)mg
+ * 8g | ((v_tap_thres_u8 + 1) * 250)mg
+ * 16g | ((v_tap_thres_u8 + 1) * 500)mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_thres(
+u8 *v_tap_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read tap threshold*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_1_INTR_TAP_THRES__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_thres_u8 = BMI160_GET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_TAP_1_INTR_TAP_THRES);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Threshold of the
+ * single/double tap interrupt from the register 0x64 bit 0 to 4
+ *
+ *
+ * @param v_tap_thres_u8 : The value of single/double tap threshold
+ *
+ * @note single/double tap threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | single/double tap threshold
+ * ----------------|---------------------
+ * 2g | ((v_tap_thres_u8 + 1) * 62.5)mg
+ * 4g | ((v_tap_thres_u8 + 1) * 125)mg
+ * 8g | ((v_tap_thres_u8 + 1) * 250)mg
+ * 16g | ((v_tap_thres_u8 + 1) * 500)mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_thres(
+u8 v_tap_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write tap threshold*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_1_INTR_TAP_THRES__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_TAP_1_INTR_TAP_THRES,
+ v_tap_thres_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_TAP_1_INTR_TAP_THRES__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read the threshold for orientation interrupt
+ * from the register 0x65 bit 0 and 1
+ *
+ * @param v_orient_mode_u8 : The value of threshold for orientation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | symmetrical
+ * 0x01 | high-asymmetrical
+ * 0x02 | low-asymmetrical
+ * 0x03 | symmetrical
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_mode(
+u8 *v_orient_mode_u8)
+{
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read orientation threshold*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mode_u8 = BMI160_GET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_MODE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write the threshold for orientation interrupt
+ * from the register 0x65 bit 0 and 1
+ *
+ * @param v_orient_mode_u8 : The value of threshold for orientation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | symmetrical
+ * 0x01 | high-asymmetrical
+ * 0x02 | low-asymmetrical
+ * 0x03 | symmetrical
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_mode(
+u8 v_orient_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_orient_mode_u8 <= BMI160_MAX_ORIENT_MODE) {
+ /* write orientation threshold*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_MODE,
+ v_orient_mode_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read the orient blocking mode
+ * that is used for the generation of the orientation interrupt.
+ * from the register 0x65 bit 2 and 3
+ *
+ * @param v_orient_blocking_u8 : The value of orient blocking mode
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | No blocking
+ * 0x01 | Theta blocking or acceleration in any axis > 1.5g
+ * 0x02 | Theta blocking or acceleration slope in any axis >
+ * - | 0.2g or acceleration in any axis > 1.5g
+ * 0x03 | Theta blocking or acceleration slope in any axis >
+ * - | 0.4g or acceleration in any axis >
+ * - | 1.5g and value of orient is not stable
+ * - | for at least 100 ms
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_blocking(
+u8 *v_orient_blocking_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read orient blocking mode*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_blocking_u8 = BMI160_GET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write the orient blocking mode
+ * that is used for the generation of the orientation interrupt.
+ * from the register 0x65 bit 2 and 3
+ *
+ * @param v_orient_blocking_u8 : The value of orient blocking mode
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | No blocking
+ * 0x01 | Theta blocking or acceleration in any axis > 1.5g
+ * 0x02 | Theta blocking or acceleration slope in any axis >
+ * - | 0.2g or acceleration in any axis > 1.5g
+ * 0x03 | Theta blocking or acceleration slope in any axis >
+ * - | 0.4g or acceleration in any axis >
+ * - | 1.5g and value of orient is not stable
+ * - | for at least 100 ms
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_blocking(
+u8 v_orient_blocking_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_orient_blocking_u8 <= BMI160_MAX_ORIENT_BLOCKING) {
+ /* write orient blocking mode*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING,
+ v_orient_blocking_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API read Orient interrupt
+ * hysteresis, from the register 0x64 bit 4 to 7
+ *
+ *
+ *
+ * @param v_orient_hyst_u8 : The value of orient hysteresis
+ *
+ * @note 1 LSB corresponds to 62.5 mg,
+ * irrespective of the selected accel range
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_hyst(
+u8 *v_orient_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read orient hysteresis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_hyst_u8 = BMI160_GET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_HYST);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Orient interrupt
+ * hysteresis, from the register 0x64 bit 4 to 7
+ *
+ *
+ *
+ * @param v_orient_hyst_u8 : The value of orient hysteresis
+ *
+ * @note 1 LSB corresponds to 62.5 mg,
+ * irrespective of the selected accel range
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_hyst(
+u8 v_orient_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write orient hysteresis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_HYST,
+ v_orient_hyst_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read Orient
+ * blocking angle (0 to 44.8) from the register 0x66 bit 0 to 5
+ *
+ * @param v_orient_theta_u8 : The value of Orient blocking angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_theta(
+u8 *v_orient_theta_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read Orient blocking angle*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_theta_u8 = BMI160_GET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_THETA);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Orient
+ * blocking angle (0 to 44.8) from the register 0x66 bit 0 to 5
+ *
+ * @param v_orient_theta_u8 : The value of Orient blocking angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_theta(
+u8 v_orient_theta_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_orient_theta_u8 <= BMI160_MAX_ORIENT_THETA) {
+ /* write Orient blocking angle*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_THETA,
+ v_orient_theta_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API read orient change
+ * of up/down bit from the register 0x66 bit 6
+ *
+ * @param v_orient_ud_u8 : The value of orient change of up/down
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | Is ignored
+ * 0x01 | Generates orientation interrupt
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_ud_enable(
+u8 *v_orient_ud_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read orient up/down enable*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_ud_u8 = BMI160_GET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write orient change
+ * of up/down bit from the register 0x66 bit 6
+ *
+ * @param v_orient_ud_u8 : The value of orient change of up/down
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | Is ignored
+ * 0x01 | Generates orientation interrupt
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_ud_enable(
+u8 v_orient_ud_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_orient_ud_u8 <= BMI160_MAX_VALUE_ORIENT_UD) {
+ /* write orient up/down enable */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE,
+ v_orient_ud_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API read orientation axes changes
+ * from the register 0x66 bit 7
+ *
+ * @param v_orient_axes_u8 : The value of orient axes assignment
+ * value | Behaviour | Name
+ * ----------|--------------------|------
+ * 0x00 | x = x, y = y, z = z|orient_ax_noex
+ * 0x01 | x = y, y = z, z = x|orient_ax_ex
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_axes_enable(
+u8 *v_orient_axes_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read orientation axes changes */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_axes_u8 = BMI160_GET_BITSLICE
+ (v_data_u8,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write orientation axes changes
+ * from the register 0x66 bit 7
+ *
+ * @param v_orient_axes_u8 : The value of orient axes assignment
+ * value | Behaviour | Name
+ * ----------|--------------------|------
+ * 0x00 | x = x, y = y, z = z|orient_ax_noex
+ * 0x01 | x = y, y = z, z = x|orient_ax_ex
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_axes_enable(
+u8 v_orient_axes_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_orient_axes_u8 <= BMI160_MAX_VALUE_ORIENT_AXES) {
+ /*write orientation axes changes */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX,
+ v_orient_axes_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API read Flat angle (0 to 44.8) for flat interrupt
+ * from the register 0x67 bit 0 to 5
+ *
+ * @param v_flat_theta_u8 : The value of flat angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_flat_theta(
+u8 *v_flat_theta_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read Flat angle*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_FLAT_0_INTR_FLAT_THETA__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_theta_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_FLAT_0_INTR_FLAT_THETA);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Flat angle (0 to 44.8) for flat interrupt
+ * from the register 0x67 bit 0 to 5
+ *
+ * @param v_flat_theta_u8 : The value of flat angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_flat_theta(
+u8 v_flat_theta_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_flat_theta_u8 <= BMI160_MAX_FLAT_THETA) {
+ /* write Flat angle */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_FLAT_0_INTR_FLAT_THETA__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_FLAT_0_INTR_FLAT_THETA,
+ v_flat_theta_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_FLAT_0_INTR_FLAT_THETA__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read Flat interrupt hold time;
+ * from the register 0x68 bit 4 and 5
+ *
+ * @param v_flat_hold_u8 : The value of flat hold time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | 0ms
+ * 0x01 | 512ms
+ * 0x01 | 1024ms
+ * 0x01 | 2048ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_flat_hold(
+u8 *v_flat_hold_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read flat hold time*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HOLD__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_hold_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HOLD);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Flat interrupt hold time;
+ * from the register 0x68 bit 4 and 5
+ *
+ * @param v_flat_hold_u8 : The value of flat hold time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | 0ms
+ * 0x01 | 512ms
+ * 0x01 | 1024ms
+ * 0x01 | 2048ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_flat_hold(
+u8 v_flat_hold_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_flat_hold_u8 <= BMI160_MAX_FLAT_HOLD) {
+ /* write flat hold time*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HOLD__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HOLD,
+ v_flat_hold_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HOLD__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read flat interrupt hysteresis
+ * from the register 0x68 bit 0 to 3
+ *
+ * @param v_flat_hyst_u8 : The value of flat hysteresis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_flat_hyst(
+u8 *v_flat_hyst_u8)
+{
+ /* variable used to return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the flat hysteresis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_hyst_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HYST);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write flat interrupt hysteresis
+ * from the register 0x68 bit 0 to 3
+ *
+ * @param v_flat_hyst_u8 : The value of flat hysteresis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_flat_hyst(
+u8 v_flat_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_flat_hyst_u8 <= BMI160_MAX_FLAT_HYST) {
+ /* read the flat hysteresis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HYST,
+ v_flat_hyst_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_INTR_FLAT_1_INTR_FLAT_HYST__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read accel offset compensation
+ * target value for z-axis from the register 0x69 bit 0 and 1
+ *
+ * @param v_foc_accel_z_u8 : the value of accel offset compensation z axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_accel_z(u8 *v_foc_accel_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel offset compensation for z axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_accel_z_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_ACCEL_Z);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write accel offset compensation
+ * target value for z-axis from the register 0x69 bit 0 and 1
+ *
+ * @param v_foc_accel_z_u8 : the value of accel offset compensation z axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_foc_accel_z(
+u8 v_foc_accel_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write the accel offset compensation for z axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_ACCEL_Z,
+ v_foc_accel_z_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel offset compensation
+ * target value for y-axis
+ * from the register 0x69 bit 2 and 3
+ *
+ * @param v_foc_accel_y_u8 : the value of accel offset compensation y axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_accel_y(u8 *v_foc_accel_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel offset compensation for y axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_accel_y_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_ACCEL_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel offset compensation
+ * target value for y-axis
+ * from the register 0x69 bit 2 and 3
+ *
+ * @param v_foc_accel_y_u8 : the value of accel offset compensation y axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x02 | -1g
+ * 0x03 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_foc_accel_y(u8 v_foc_accel_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_foc_accel_y_u8 <= BMI160_MAX_ACCEL_FOC) {
+ /* write the accel offset compensation for y axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_ACCEL_Y,
+ v_foc_accel_y_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel offset compensation
+ * target value for x-axis is
+ * from the register 0x69 bit 4 and 5
+ *
+ * @param v_foc_accel_x_u8 : the value of accel offset compensation x axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x02 | -1g
+ * 0x03 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_accel_x(u8 *v_foc_accel_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the accel offset compensation for x axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_accel_x_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_ACCEL_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel offset compensation
+ * target value for x-axis is
+ * from the register 0x69 bit 4 and 5
+ *
+ * @param v_foc_accel_x_u8 : the value of accel offset compensation x axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_foc_accel_x(u8 v_foc_accel_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_foc_accel_x_u8 <= BMI160_MAX_ACCEL_FOC) {
+ /* write the accel offset compensation for x axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_ACCEL_X,
+ v_foc_accel_x_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API writes accel fast offset compensation
+ * from the register 0x69 bit 0 to 5
+ * @brief This API writes each axis individually
+ * FOC_X_AXIS - bit 4 and 5
+ * FOC_Y_AXIS - bit 2 and 3
+ * FOC_Z_AXIS - bit 0 and 1
+ *
+ * @param v_foc_accel_u8: The value of accel offset compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_axis_u8: The value of accel offset axis selection
+ * value | axis
+ * ----------|-------------------
+ * 0 | FOC_X_AXIS
+ * 1 | FOC_Y_AXIS
+ * 2 | FOC_Z_AXIS
+ *
+ * @param v_accel_offset_s8: The accel offset value
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_foc_trigger(u8 v_axis_u8,
+u8 v_foc_accel_u8, s8 *v_accel_offset_s8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+s8 v_status_s8 = SUCCESS;
+u8 v_timeout_u8 = BMI160_INIT_VALUE;
+s8 v_foc_accel_offset_x_s8 = BMI160_INIT_VALUE;
+s8 v_foc_accel_offset_y_s8 = BMI160_INIT_VALUE;
+s8 v_foc_accel_offset_z_s8 = BMI160_INIT_VALUE;
+u8 focstatus = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+} else {
+ v_status_s8 = bmi160_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ switch (v_axis_u8) {
+ case FOC_X_AXIS:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_ACCEL_X,
+ v_foc_accel_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the
+ FOC need to write
+ 0x03 in the register 0x7e*/
+ com_rslt +=
+ bmi160_set_command_register(
+ START_FOC_ACCEL_GYRO);
+
+ com_rslt +=
+ bmi160_get_foc_rdy(&focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ BMI160_MAXIMUM_TIMEOUT)) {
+ p_bmi160->delay_msec(
+ BMI160_DELAY_SETTLING_TIME);
+ com_rslt = bmi160_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == BMI160_FOC_STAT_HIGH)) {
+ com_rslt +=
+ bmi160_get_accel_offset_compensation_xaxis(
+ &v_foc_accel_offset_x_s8);
+ *v_accel_offset_s8 =
+ v_foc_accel_offset_x_s8;
+ }
+ break;
+ case FOC_Y_AXIS:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_ACCEL_Y,
+ v_foc_accel_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the FOC
+ need to write 0x03
+ in the register 0x7e*/
+ com_rslt +=
+ bmi160_set_command_register(
+ START_FOC_ACCEL_GYRO);
+
+ com_rslt +=
+ bmi160_get_foc_rdy(&focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ BMI160_MAXIMUM_TIMEOUT)) {
+ p_bmi160->delay_msec(
+ BMI160_DELAY_SETTLING_TIME);
+ com_rslt = bmi160_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == BMI160_FOC_STAT_HIGH)) {
+ com_rslt +=
+ bmi160_get_accel_offset_compensation_yaxis(
+ &v_foc_accel_offset_y_s8);
+ *v_accel_offset_s8 =
+ v_foc_accel_offset_y_s8;
+ }
+ break;
+ case FOC_Z_AXIS:
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_ACCEL_Z,
+ v_foc_accel_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the FOC need to write
+ 0x03 in the register 0x7e*/
+ com_rslt +=
+ bmi160_set_command_register(
+ START_FOC_ACCEL_GYRO);
+
+ com_rslt +=
+ bmi160_get_foc_rdy(&focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ BMI160_MAXIMUM_TIMEOUT)) {
+ p_bmi160->delay_msec(
+ BMI160_DELAY_SETTLING_TIME);
+ com_rslt = bmi160_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == BMI160_FOC_STAT_HIGH)) {
+ com_rslt +=
+ bmi160_get_accel_offset_compensation_zaxis(
+ &v_foc_accel_offset_z_s8);
+ *v_accel_offset_s8 =
+ v_foc_accel_offset_z_s8;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API write fast accel offset compensation
+ * it writes all axis together.To the register 0x69 bit 0 to 5
+ * FOC_X_AXIS - bit 4 and 5
+ * FOC_Y_AXIS - bit 2 and 3
+ * FOC_Z_AXIS - bit 0 and 1
+ *
+ * @param v_foc_accel_x_u8: The value of accel offset x compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_foc_accel_y_u8: The value of accel offset y compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_foc_accel_z_u8: The value of accel offset z compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_accel_off_x_s8: The value of accel offset x axis
+ * @param v_accel_off_y_s8: The value of accel offset y axis
+ * @param v_accel_off_z_s8: The value of accel offset z axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_accel_foc_trigger_xyz(u8 v_foc_accel_x_u8,
+u8 v_foc_accel_y_u8, u8 v_foc_accel_z_u8, s8 *v_accel_off_x_s8,
+s8 *v_accel_off_y_s8, s8 *v_accel_off_z_s8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 focx = BMI160_INIT_VALUE;
+u8 focy = BMI160_INIT_VALUE;
+u8 focz = BMI160_INIT_VALUE;
+s8 v_foc_accel_offset_x_s8 = BMI160_INIT_VALUE;
+s8 v_foc_accel_offset_y_s8 = BMI160_INIT_VALUE;
+s8 v_foc_accel_offset_z_s8 = BMI160_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+u8 v_timeout_u8 = BMI160_INIT_VALUE;
+u8 focstatus = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ v_status_s8 = bmi160_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ /* foc x axis*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_X__REG,
+ &focx, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ focx = BMI160_SET_BITSLICE(focx,
+ BMI160_USER_FOC_ACCEL_X,
+ v_foc_accel_x_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_X__REG,
+ &focx, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* foc y axis*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Y__REG,
+ &focy, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ focy = BMI160_SET_BITSLICE(focy,
+ BMI160_USER_FOC_ACCEL_Y,
+ v_foc_accel_y_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Y__REG,
+ &focy, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* foc z axis*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Z__REG,
+ &focz, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ focz = BMI160_SET_BITSLICE(focz,
+ BMI160_USER_FOC_ACCEL_Z,
+ v_foc_accel_z_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_ACCEL_Z__REG,
+ &focz, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the FOC need to
+ write 0x03 in the register 0x7e*/
+ com_rslt += bmi160_set_command_register(
+ START_FOC_ACCEL_GYRO);
+
+ com_rslt += bmi160_get_foc_rdy(
+ &focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ BMI160_MAXIMUM_TIMEOUT)) {
+ p_bmi160->delay_msec(
+ BMI160_DELAY_SETTLING_TIME);
+ com_rslt = bmi160_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == BMI160_GEN_READ_WRITE_DATA_LENGTH)) {
+ com_rslt +=
+ bmi160_get_accel_offset_compensation_xaxis(
+ &v_foc_accel_offset_x_s8);
+ *v_accel_off_x_s8 =
+ v_foc_accel_offset_x_s8;
+ com_rslt +=
+ bmi160_get_accel_offset_compensation_yaxis(
+ &v_foc_accel_offset_y_s8);
+ *v_accel_off_y_s8 =
+ v_foc_accel_offset_y_s8;
+ com_rslt +=
+ bmi160_get_accel_offset_compensation_zaxis(
+ &v_foc_accel_offset_z_s8);
+ *v_accel_off_z_s8 =
+ v_foc_accel_offset_z_s8;
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API read gyro fast offset enable
+ * from the register 0x69 bit 6
+ *
+ * @param v_foc_gyro_u8 : The value of gyro fast offset enable
+ * value | Description
+ * ----------|-------------
+ * 0 | fast offset compensation disabled
+ * 1 | fast offset compensation enabled
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_gyro_enable(
+u8 *v_foc_gyro_u8)
+{
+ /* used for return the status of bus communication */
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the gyro fast offset enable*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_FOC_GYRO_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_gyro_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_GYRO_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro fast offset enable
+ * from the register 0x69 bit 6
+ *
+ * @param v_foc_gyro_u8 : The value of gyro fast offset enable
+ * value | Description
+ * ----------|-------------
+ * 0 | fast offset compensation disabled
+ * 1 | fast offset compensation enabled
+ *
+ * @param v_gyro_off_x_s16 : The value of gyro fast offset x axis data
+ * @param v_gyro_off_y_s16 : The value of gyro fast offset y axis data
+ * @param v_gyro_off_z_s16 : The value of gyro fast offset z axis data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_foc_gyro_enable(
+u8 v_foc_gyro_u8, s16 *v_gyro_off_x_s16,
+s16 *v_gyro_off_y_s16, s16 *v_gyro_off_z_s16)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+u8 v_timeout_u8 = BMI160_INIT_VALUE;
+s16 offsetx = BMI160_INIT_VALUE;
+s16 offsety = BMI160_INIT_VALUE;
+s16 offsetz = BMI160_INIT_VALUE;
+u8 focstatus = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ v_status_s8 = bmi160_set_gyro_offset_enable(
+ GYRO_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_FOC_GYRO_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_FOC_GYRO_ENABLE,
+ v_foc_gyro_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_FOC_GYRO_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the FOC need to write 0x03
+ in the register 0x7e*/
+ com_rslt += bmi160_set_command_register
+ (START_FOC_ACCEL_GYRO);
+
+ com_rslt += bmi160_get_foc_rdy(&focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != BMI160_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ BMI160_MAXIMUM_TIMEOUT)) {
+ p_bmi160->delay_msec(
+ BMI160_DELAY_SETTLING_TIME);
+ com_rslt = bmi160_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == BMI160_FOC_STAT_HIGH)) {
+ com_rslt +=
+ bmi160_get_gyro_offset_compensation_xaxis
+ (&offsetx);
+ *v_gyro_off_x_s16 = offsetx;
+
+ com_rslt +=
+ bmi160_get_gyro_offset_compensation_yaxis
+ (&offsety);
+ *v_gyro_off_y_s16 = offsety;
+
+ com_rslt +=
+ bmi160_get_gyro_offset_compensation_zaxis(
+ &offsetz);
+ *v_gyro_off_z_s16 = offsetz;
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API read NVM program enable
+ * from the register 0x6A bit 1
+ *
+ * @param v_nvm_prog_u8 : The value of NVM program enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_nvm_prog_enable(
+u8 *v_nvm_prog_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read NVM program*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_CONFIG_NVM_PROG_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_nvm_prog_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_CONFIG_NVM_PROG_ENABLE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write NVM program enable
+ * from the register 0x6A bit 1
+ *
+ * @param v_nvm_prog_u8 : The value of NVM program enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_nvm_prog_enable(
+u8 v_nvm_prog_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_nvm_prog_u8 <= BMI160_MAX_VALUE_NVM_PROG) {
+ /* write the NVM program*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_CONFIG_NVM_PROG_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_CONFIG_NVM_PROG_ENABLE,
+ v_nvm_prog_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_CONFIG_NVM_PROG_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read to configure SPI
+ * Interface Mode for primary and OIS interface
+ * from the register 0x6B bit 0
+ *
+ * @param v_spi3_u8 : The value of SPI mode selection
+ * Value | Description
+ * --------|-------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_spi3(
+u8 *v_spi3_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read SPI mode*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_SPI3__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_spi3_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_IF_CONFIG_SPI3);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write to configure SPI
+ * Interface Mode for primary and OIS interface
+ * from the register 0x6B bit 0
+ *
+ * @param v_spi3_u8 : The value of SPI mode selection
+ * Value | Description
+ * --------|-------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_spi3(
+u8 v_spi3_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_spi3_u8 <= BMI160_MAX_VALUE_SPI3) {
+ /* write SPI mode*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_SPI3__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_IF_CONFIG_SPI3,
+ v_spi3_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_SPI3__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read I2C Watchdog timer
+ * from the register 0x70 bit 1
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watch dog timer
+ * Value | Description
+ * --------|-------------
+ * 0 | I2C watchdog v_timeout_u8 after 1 ms
+ * 1 | I2C watchdog v_timeout_u8 after 50 ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_i2c_wdt_select(
+u8 *v_i2c_wdt_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read I2C watch dog timer */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_I2C_WDT_SELECT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_i2c_wdt_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_IF_CONFIG_I2C_WDT_SELECT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write I2C Watchdog timer
+ * from the register 0x70 bit 1
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watch dog timer
+ * Value | Description
+ * --------|-------------
+ * 0 | I2C watchdog v_timeout_u8 after 1 ms
+ * 1 | I2C watchdog v_timeout_u8 after 50 ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_i2c_wdt_select(
+u8 v_i2c_wdt_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_i2c_wdt_u8 <= BMI160_MAX_VALUE_I2C_WDT) {
+ /* write I2C watch dog timer */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_I2C_WDT_SELECT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_IF_CONFIG_I2C_WDT_SELECT,
+ v_i2c_wdt_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_I2C_WDT_SELECT__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read I2C watchdog enable
+ * from the register 0x70 bit 2
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watchdog enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_i2c_wdt_enable(
+u8 *v_i2c_wdt_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read i2c watch dog eneble */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_I2C_WDT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_i2c_wdt_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_IF_CONFIG_I2C_WDT_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write I2C watchdog enable
+ * from the register 0x70 bit 2
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watchdog enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_i2c_wdt_enable(
+u8 v_i2c_wdt_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_i2c_wdt_u8 <= BMI160_MAX_VALUE_I2C_WDT) {
+ /* write i2c watch dog eneble */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_I2C_WDT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_IF_CONFIG_I2C_WDT_ENABLE,
+ v_i2c_wdt_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_I2C_WDT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read I2C interface configuration(if) moe
+ * from the register 0x6B bit 4 and 5
+ *
+ * @param v_if_mode_u8 : The value of interface configuration mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Primary interface:autoconfig / secondary interface:off
+ * 0x01 | Primary interface:I2C / secondary interface:OIS
+ * 0x02 | Primary interface:autoconfig/secondary interface:Magnetometer
+ * 0x03 | Reserved
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_if_mode(
+u8 *v_if_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read if mode*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_IF_MODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_if_mode_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_IF_CONFIG_IF_MODE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write I2C interface configuration(if) moe
+ * from the register 0x6B bit 4 and 5
+ *
+ * @param v_if_mode_u8 : The value of interface configuration mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Primary interface:autoconfig / secondary interface:off
+ * 0x01 | Primary interface:I2C / secondary interface:OIS
+ * 0x02 | Primary interface:autoconfig/secondary interface:Magnetometer
+ * 0x03 | Reserved
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_if_mode(
+u8 v_if_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_if_mode_u8 <= BMI160_MAX_IF_MODE) {
+ /* write if mode*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_IF_MODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_IF_CONFIG_IF_MODE,
+ v_if_mode_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_IF_CONFIG_IF_MODE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro sleep trigger
+ * from the register 0x6C bit 0 to 2
+ *
+ * @param v_gyro_sleep_trigger_u8 : The value of gyro sleep trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | nomotion: no / Not INT1 pin: no / INT2 pin: no
+ * 0x01 | nomotion: no / Not INT1 pin: no / INT2 pin: yes
+ * 0x02 | nomotion: no / Not INT1 pin: yes / INT2 pin: no
+ * 0x03 | nomotion: no / Not INT1 pin: yes / INT2 pin: yes
+ * 0x04 | nomotion: yes / Not INT1 pin: no / INT2 pin: no
+ * 0x05 | anymotion: yes / Not INT1 pin: no / INT2 pin: yes
+ * 0x06 | anymotion: yes / Not INT1 pin: yes / INT2 pin: no
+ * 0x07 | anymotion: yes / Not INT1 pin: yes / INT2 pin: yes
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_sleep_trigger(
+u8 *v_gyro_sleep_trigger_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro sleep trigger */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_SLEEP_TRIGGER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_sleep_trigger_u8 =
+ BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_SLEEP_TRIGGER);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro sleep trigger
+ * from the register 0x6C bit 0 to 2
+ *
+ * @param v_gyro_sleep_trigger_u8 : The value of gyro sleep trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | nomotion: no / Not INT1 pin: no / INT2 pin: no
+ * 0x01 | nomotion: no / Not INT1 pin: no / INT2 pin: yes
+ * 0x02 | nomotion: no / Not INT1 pin: yes / INT2 pin: no
+ * 0x03 | nomotion: no / Not INT1 pin: yes / INT2 pin: yes
+ * 0x04 | nomotion: yes / Not INT1 pin: no / INT2 pin: no
+ * 0x05 | anymotion: yes / Not INT1 pin: no / INT2 pin: yes
+ * 0x06 | anymotion: yes / Not INT1 pin: yes / INT2 pin: no
+ * 0x07 | anymotion: yes / Not INT1 pin: yes / INT2 pin: yes
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_sleep_trigger(
+u8 v_gyro_sleep_trigger_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_gyro_sleep_trigger_u8 <= BMI160_MAX_GYRO_SLEEP_TIGGER) {
+ /* write gyro sleep trigger */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_SLEEP_TRIGGER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_SLEEP_TRIGGER,
+ v_gyro_sleep_trigger_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_SLEEP_TRIGGER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro wakeup trigger
+ * from the register 0x6C bit 3 and 4
+ *
+ * @param v_gyro_wakeup_trigger_u8 : The value of gyro wakeup trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | anymotion: no / INT1 pin: no
+ * 0x01 | anymotion: no / INT1 pin: yes
+ * 0x02 | anymotion: yes / INT1 pin: no
+ * 0x03 | anymotion: yes / INT1 pin: yes
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_wakeup_trigger(
+u8 *v_gyro_wakeup_trigger_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro wakeup trigger */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_WAKEUP_TRIGGER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_wakeup_trigger_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_GYRO_WAKEUP_TRIGGER);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro wakeup trigger
+ * from the register 0x6C bit 3 and 4
+ *
+ * @param v_gyro_wakeup_trigger_u8 : The value of gyro wakeup trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | anymotion: no / INT1 pin: no
+ * 0x01 | anymotion: no / INT1 pin: yes
+ * 0x02 | anymotion: yes / INT1 pin: no
+ * 0x03 | anymotion: yes / INT1 pin: yes
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_wakeup_trigger(
+u8 v_gyro_wakeup_trigger_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_gyro_wakeup_trigger_u8
+ <= BMI160_MAX_GYRO_WAKEUP_TRIGGER) {
+ /* write gyro wakeup trigger */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_WAKEUP_TRIGGER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_WAKEUP_TRIGGER,
+ v_gyro_wakeup_trigger_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_WAKEUP_TRIGGER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read Target state for gyro sleep mode
+ * from the register 0x6C bit 5
+ *
+ * @param v_gyro_sleep_state_u8 : The value of gyro sleep mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Sleep transition to fast wake up state
+ * 0x01 | Sleep transition to suspend state
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_sleep_state(
+u8 *v_gyro_sleep_state_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro sleep state*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_SLEEP_STATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_sleep_state_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_GYRO_SLEEP_STATE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Target state for gyro sleep mode
+ * from the register 0x6C bit 5
+ *
+ * @param v_gyro_sleep_state_u8 : The value of gyro sleep mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Sleep transition to fast wake up state
+ * 0x01 | Sleep transition to suspend state
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_sleep_state(
+u8 v_gyro_sleep_state_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_gyro_sleep_state_u8 <= BMI160_MAX_VALUE_SLEEP_STATE) {
+ /* write gyro sleep state*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_SLEEP_STATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_SLEEP_STATE,
+ v_gyro_sleep_state_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_SLEEP_STATE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro wakeup interrupt
+ * from the register 0x6C bit 6
+ *
+ * @param v_gyro_wakeup_intr_u8 : The valeu of gyro wakeup interrupt
+ * Value | Description
+ * --------|-------------
+ * 0x00 | DISABLE
+ * 0x01 | ENABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_wakeup_intr(
+u8 *v_gyro_wakeup_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro wakeup interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_WAKEUP_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_wakeup_intr_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_GYRO_WAKEUP_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro wakeup interrupt
+ * from the register 0x6C bit 6
+ *
+ * @param v_gyro_wakeup_intr_u8 : The valeu of gyro wakeup interrupt
+ * Value | Description
+ * --------|-------------
+ * 0x00 | DISABLE
+ * 0x01 | ENABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_wakeup_intr(
+u8 v_gyro_wakeup_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_gyro_wakeup_intr_u8 <= BMI160_MAX_VALUE_WAKEUP_INTR) {
+ /* write gyro wakeup interrupt */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_WAKEUP_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_WAKEUP_INTR,
+ v_gyro_wakeup_intr_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_WAKEUP_INTR__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel select axis to be self-test
+ *
+ * @param v_accel_selftest_axis_u8 :
+ * The value of accel self test axis selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | disabled
+ * 0x01 | x-axis
+ * 0x02 | y-axis
+ * 0x03 | z-axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_selftest_axis(
+u8 *v_accel_selftest_axis_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read accel self test axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_SELFTEST_AXIS__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_selftest_axis_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_ACCEL_SELFTEST_AXIS);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel select axis to be self-test
+ *
+ * @param v_accel_selftest_axis_u8 :
+ * The value of accel self test axis selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | disabled
+ * 0x01 | x-axis
+ * 0x02 | y-axis
+ * 0x03 | z-axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_selftest_axis(
+u8 v_accel_selftest_axis_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_accel_selftest_axis_u8
+ <= BMI160_MAX_ACCEL_SELFTEST_AXIS) {
+ /* write accel self test axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_SELFTEST_AXIS__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_SELFTEST_AXIS,
+ v_accel_selftest_axis_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_SELFTEST_AXIS__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel self test axis sign
+ * from the register 0x6D bit 2
+ *
+ * @param v_accel_selftest_sign_u8: The value of accel self test axis sign
+ * Value | Description
+ * --------|-------------
+ * 0x00 | negative
+ * 0x01 | positive
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_selftest_sign(
+u8 *v_accel_selftest_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read accel self test axis sign*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_SELFTEST_SIGN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_selftest_sign_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_ACCEL_SELFTEST_SIGN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel self test axis sign
+ * from the register 0x6D bit 2
+ *
+ * @param v_accel_selftest_sign_u8: The value of accel self test axis sign
+ * Value | Description
+ * --------|-------------
+ * 0x00 | negative
+ * 0x01 | positive
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_selftest_sign(
+u8 v_accel_selftest_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_accel_selftest_sign_u8 <=
+ BMI160_MAX_VALUE_SELFTEST_SIGN) {
+ /* write accel self test axis sign*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_SELFTEST_SIGN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_ACCEL_SELFTEST_SIGN,
+ v_accel_selftest_sign_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_ACCEL_SELFTEST_SIGN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel self test amplitude
+ * from the register 0x6D bit 3
+ * select amplitude of the selftest deflection:
+ *
+ * @param v_accel_selftest_amp_u8 : The value of accel self test amplitude
+ * Value | Description
+ * --------|-------------
+ * 0x00 | LOW
+ * 0x01 | HIGH
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_selftest_amp(
+u8 *v_accel_selftest_amp_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read self test amplitude*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_SELFTEST_AMP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_selftest_amp_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_SELFTEST_AMP);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel self test amplitude
+ * from the register 0x6D bit 3
+ * select amplitude of the selftest deflection:
+ *
+ * @param v_accel_selftest_amp_u8 : The value of accel self test amplitude
+ * Value | Description
+ * --------|-------------
+ * 0x00 | LOW
+ * 0x01 | HIGH
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_selftest_amp(
+u8 v_accel_selftest_amp_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_accel_selftest_amp_u8 <=
+ BMI160_MAX_VALUE_SELFTEST_AMP) {
+ /* write self test amplitude*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_SELFTEST_AMP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_SELFTEST_AMP,
+ v_accel_selftest_amp_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_SELFTEST_AMP__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro self test trigger
+ *
+ * @param v_gyro_selftest_start_u8: The value of gyro self test start
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_selftest_start(
+u8 *v_gyro_selftest_start_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro self test start */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_SELFTEST_START__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_selftest_start_u8 = BMI160_GET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_GYRO_SELFTEST_START);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro self test trigger
+ *
+ * @param v_gyro_selftest_start_u8: The value of gyro self test start
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_selftest_start(
+u8 v_gyro_selftest_start_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_gyro_selftest_start_u8 <=
+ BMI160_MAX_VALUE_SELFTEST_START) {
+ /* write gyro self test start */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_SELFTEST_START__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_GYRO_SELFTEST_START,
+ v_gyro_selftest_start_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_GYRO_SELFTEST_START__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read primary interface selection I2C or SPI
+ * from the register 0x70 bit 0
+ *
+ * @param v_spi_enable_u8: The value of Interface selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | I2C Enable
+ * 0x01 | I2C DISBALE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_spi_enable(u8 *v_spi_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read interface section*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_NV_CONFIG_SPI_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_spi_enable_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_NV_CONFIG_SPI_ENABLE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write primary interface selection I2C or SPI
+ * from the register 0x70 bit 0
+ *
+ * @param v_spi_enable_u8: The value of Interface selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | I2C Enable
+ * 0x01 | I2C DISBALE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_spi_enable(u8 v_spi_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write interface section*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_NV_CONFIG_SPI_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_NV_CONFIG_SPI_ENABLE,
+ v_spi_enable_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_NV_CONFIG_SPI_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read the spare zero
+ * form register 0x70 bit 3
+ *
+ *
+ * @param v_spare0_trim_u8: The value of spare zero
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_spare0_trim(u8 *v_spare0_trim_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read spare zero*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_NV_CONFIG_SPARE0__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_spare0_trim_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_NV_CONFIG_SPARE0);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write the spare zero
+ * form register 0x70 bit 3
+ *
+ *
+ * @param v_spare0_trim_u8: The value of spare zero
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_spare0_trim(u8 v_spare0_trim_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write spare zero*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_NV_CONFIG_SPARE0__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_NV_CONFIG_SPARE0,
+ v_spare0_trim_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_NV_CONFIG_SPARE0__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read the NVM counter
+ * form register 0x70 bit 4 to 7
+ *
+ *
+ * @param v_nvm_counter_u8: The value of NVM counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_nvm_counter(u8 *v_nvm_counter_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read NVM counter*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_NV_CONFIG_NVM_COUNTER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_nvm_counter_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_NV_CONFIG_NVM_COUNTER);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write the NVM counter
+ * form register 0x70 bit 4 to 7
+ *
+ *
+ * @param v_nvm_counter_u8: The value of NVM counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_nvm_counter(
+u8 v_nvm_counter_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write NVM counter*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_NV_CONFIG_NVM_COUNTER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_NV_CONFIG_NVM_COUNTER,
+ v_nvm_counter_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_NV_CONFIG_NVM_COUNTER__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel manual offset compensation of x axis
+ * from the register 0x71 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_x_s8:
+ * The value of accel manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_offset_compensation_xaxis(
+s8 *v_accel_off_x_s8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read accel manual offset compensation of x axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_0_ACCEL_OFF_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_off_x_s8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_OFFSET_0_ACCEL_OFF_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel manual offset compensation of x axis
+ * from the register 0x71 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_x_s8:
+ * The value of accel manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_offset_compensation_xaxis(
+s8 v_accel_off_x_s8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* enable accel offset */
+ v_status_s8 = bmi160_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ /* write accel manual offset compensation of x axis*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_0_ACCEL_OFF_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_OFFSET_0_ACCEL_OFF_X,
+ v_accel_off_x_s8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_0_ACCEL_OFF_X__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel manual offset compensation of y axis
+ * from the register 0x72 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_y_s8:
+ * The value of accel manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_offset_compensation_yaxis(
+s8 *v_accel_off_y_s8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read accel manual offset compensation of y axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_1_ACCEL_OFF_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_off_y_s8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_OFFSET_1_ACCEL_OFF_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel manual offset compensation of y axis
+ * from the register 0x72 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_y_s8:
+ * The value of accel manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_offset_compensation_yaxis(
+s8 v_accel_off_y_s8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* enable accel offset */
+ v_status_s8 = bmi160_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ /* write accel manual offset compensation of y axis*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_1_ACCEL_OFF_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(
+ v_data_u8,
+ BMI160_USER_OFFSET_1_ACCEL_OFF_Y,
+ v_accel_off_y_s8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_1_ACCEL_OFF_Y__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel manual offset compensation of z axis
+ * from the register 0x73 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_z_s8:
+ * The value of accel manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_offset_compensation_zaxis(
+s8 *v_accel_off_z_s8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read accel manual offset compensation of z axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_2_ACCEL_OFF_Z__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_off_z_s8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_OFFSET_2_ACCEL_OFF_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel manual offset compensation of z axis
+ * from the register 0x73 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_z_s8:
+ * The value of accel manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_offset_compensation_zaxis(
+s8 v_accel_off_z_s8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ u8 v_status_s8 = SUCCESS;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* enable accel offset */
+ v_status_s8 = bmi160_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ /* write accel manual offset
+ compensation of z axis*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_2_ACCEL_OFF_Z__REG,
+ &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_OFFSET_2_ACCEL_OFF_Z,
+ v_accel_off_z_s8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_2_ACCEL_OFF_Z__REG,
+ &v_data_u8,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro manual offset compensation of x axis
+ * from the register 0x74 bit 0 to 7 and 0x77 bit 0 and 1
+ *
+ *
+ *
+ * @param v_gyro_off_x_s16:
+ * The value of gyro manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_offset_compensation_xaxis(
+s16 *v_gyro_off_x_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data1_u8r = BMI160_INIT_VALUE;
+ u8 v_data2_u8r = BMI160_INIT_VALUE;
+ s16 v_data3_u8r, v_data4_u8r = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro offset x*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_3_GYRO_OFF_X__REG,
+ &v_data1_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data1_u8r = BMI160_GET_BITSLICE(v_data1_u8r,
+ BMI160_USER_OFFSET_3_GYRO_OFF_X);
+ com_rslt += p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_X__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data2_u8r = BMI160_GET_BITSLICE(v_data2_u8r,
+ BMI160_USER_OFFSET_6_GYRO_OFF_X);
+ v_data3_u8r = v_data2_u8r
+ << BMI160_SHIFT_BIT_POSITION_BY_14_BITS;
+ v_data4_u8r = v_data1_u8r
+ << BMI160_SHIFT_BIT_POSITION_BY_06_BITS;
+ v_data3_u8r = v_data3_u8r | v_data4_u8r;
+ *v_gyro_off_x_s16 = v_data3_u8r
+ >> BMI160_SHIFT_BIT_POSITION_BY_06_BITS;
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro manual offset compensation of x axis
+ * from the register 0x74 bit 0 to 7 and 0x77 bit 0 and 1
+ *
+ *
+ *
+ * @param v_gyro_off_x_s16:
+ * The value of gyro manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_offset_compensation_xaxis(
+s16 v_gyro_off_x_s16)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data1_u8r, v_data2_u8r = BMI160_INIT_VALUE;
+u16 v_data3_u8r = BMI160_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write gyro offset x*/
+ v_status_s8 = bmi160_set_gyro_offset_enable(
+ GYRO_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_3_GYRO_OFF_X__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data1_u8r =
+ ((s8) (v_gyro_off_x_s16 &
+ BMI160_GYRO_MANUAL_OFFSET_0_7));
+ v_data2_u8r = BMI160_SET_BITSLICE(
+ v_data2_u8r,
+ BMI160_USER_OFFSET_3_GYRO_OFF_X,
+ v_data1_u8r);
+ /* write 0x74 bit 0 to 7*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_3_GYRO_OFF_X__REG,
+ &v_data2_u8r,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ com_rslt += p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_X__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u8r =
+ (u16) (v_gyro_off_x_s16 &
+ BMI160_GYRO_MANUAL_OFFSET_8_9);
+ v_data1_u8r = (u8)(v_data3_u8r
+ >> BMI160_SHIFT_BIT_POSITION_BY_08_BITS);
+ v_data2_u8r = BMI160_SET_BITSLICE(
+ v_data2_u8r,
+ BMI160_USER_OFFSET_6_GYRO_OFF_X,
+ v_data1_u8r);
+ /* write 0x77 bit 0 and 1*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_X__REG,
+ &v_data2_u8r,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ return ERROR;
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API read gyro manual offset compensation of y axis
+ * from the register 0x75 bit 0 to 7 and 0x77 bit 2 and 3
+ *
+ *
+ *
+ * @param v_gyro_off_y_s16:
+ * The value of gyro manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_offset_compensation_yaxis(
+s16 *v_gyro_off_y_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data1_u8r = BMI160_INIT_VALUE;
+ u8 v_data2_u8r = BMI160_INIT_VALUE;
+ s16 v_data3_u8r, v_data4_u8r = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro offset y*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_4_GYRO_OFF_Y__REG,
+ &v_data1_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data1_u8r = BMI160_GET_BITSLICE(v_data1_u8r,
+ BMI160_USER_OFFSET_4_GYRO_OFF_Y);
+ com_rslt += p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Y__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data2_u8r = BMI160_GET_BITSLICE(v_data2_u8r,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Y);
+ v_data3_u8r = v_data2_u8r
+ << BMI160_SHIFT_BIT_POSITION_BY_14_BITS;
+ v_data4_u8r = v_data1_u8r
+ << BMI160_SHIFT_BIT_POSITION_BY_06_BITS;
+ v_data3_u8r = v_data3_u8r | v_data4_u8r;
+ *v_gyro_off_y_s16 = v_data3_u8r
+ >> BMI160_SHIFT_BIT_POSITION_BY_06_BITS;
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro manual offset compensation of y axis
+ * from the register 0x75 bit 0 to 7 and 0x77 bit 2 and 3
+ *
+ *
+ *
+ * @param v_gyro_off_y_s16:
+ * The value of gyro manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_offset_compensation_yaxis(
+s16 v_gyro_off_y_s16)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data1_u8r, v_data2_u8r = BMI160_INIT_VALUE;
+u16 v_data3_u8r = BMI160_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* enable gyro offset bit */
+ v_status_s8 = bmi160_set_gyro_offset_enable(
+ GYRO_OFFSET_ENABLE);
+ /* write gyro offset y*/
+ if (v_status_s8 == SUCCESS) {
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_4_GYRO_OFF_Y__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data1_u8r =
+ ((s8) (v_gyro_off_y_s16 &
+ BMI160_GYRO_MANUAL_OFFSET_0_7));
+ v_data2_u8r = BMI160_SET_BITSLICE(
+ v_data2_u8r,
+ BMI160_USER_OFFSET_4_GYRO_OFF_Y,
+ v_data1_u8r);
+ /* write 0x75 bit 0 to 7*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_4_GYRO_OFF_Y__REG,
+ &v_data2_u8r,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ com_rslt += p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Y__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u8r =
+ (u16) (v_gyro_off_y_s16 &
+ BMI160_GYRO_MANUAL_OFFSET_8_9);
+ v_data1_u8r = (u8)(v_data3_u8r
+ >> BMI160_SHIFT_BIT_POSITION_BY_08_BITS);
+ v_data2_u8r = BMI160_SET_BITSLICE(
+ v_data2_u8r,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Y,
+ v_data1_u8r);
+ /* write 0x77 bit 2 and 3*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Y__REG,
+ &v_data2_u8r,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ return ERROR;
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API read gyro manual offset compensation of z axis
+ * from the register 0x76 bit 0 to 7 and 0x77 bit 4 and 5
+ *
+ *
+ *
+ * @param v_gyro_off_z_s16:
+ * The value of gyro manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_offset_compensation_zaxis(
+s16 *v_gyro_off_z_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data1_u8r = BMI160_INIT_VALUE;
+ u8 v_data2_u8r = BMI160_INIT_VALUE;
+ s16 v_data3_u8r, v_data4_u8r = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro manual offset z axis*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_5_GYRO_OFF_Z__REG,
+ &v_data1_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data1_u8r = BMI160_GET_BITSLICE
+ (v_data1_u8r,
+ BMI160_USER_OFFSET_5_GYRO_OFF_Z);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Z__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data2_u8r = BMI160_GET_BITSLICE(
+ v_data2_u8r,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Z);
+ v_data3_u8r = v_data2_u8r
+ << BMI160_SHIFT_BIT_POSITION_BY_14_BITS;
+ v_data4_u8r = v_data1_u8r
+ << BMI160_SHIFT_BIT_POSITION_BY_06_BITS;
+ v_data3_u8r = v_data3_u8r | v_data4_u8r;
+ *v_gyro_off_z_s16 = v_data3_u8r
+ >> BMI160_SHIFT_BIT_POSITION_BY_06_BITS;
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro manual offset compensation of z axis
+ * from the register 0x76 bit 0 to 7 and 0x77 bit 4 and 5
+ *
+ *
+ *
+ * @param v_gyro_off_z_s16:
+ * The value of gyro manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_offset_compensation_zaxis(
+s16 v_gyro_off_z_s16)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data1_u8r, v_data2_u8r = BMI160_INIT_VALUE;
+u16 v_data3_u8r = BMI160_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* enable gyro offset*/
+ v_status_s8 = bmi160_set_gyro_offset_enable(
+ GYRO_OFFSET_ENABLE);
+ /* write gyro manual offset z axis*/
+ if (v_status_s8 == SUCCESS) {
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_5_GYRO_OFF_Z__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data1_u8r =
+ ((u8) (v_gyro_off_z_s16 &
+ BMI160_GYRO_MANUAL_OFFSET_0_7));
+ v_data2_u8r = BMI160_SET_BITSLICE(
+ v_data2_u8r,
+ BMI160_USER_OFFSET_5_GYRO_OFF_Z,
+ v_data1_u8r);
+ /* write 0x76 bit 0 to 7*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_5_GYRO_OFF_Z__REG,
+ &v_data2_u8r,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ com_rslt += p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Z__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u8r =
+ (u16) (v_gyro_off_z_s16 &
+ BMI160_GYRO_MANUAL_OFFSET_8_9);
+ v_data1_u8r = (u8)(v_data3_u8r
+ >> BMI160_SHIFT_BIT_POSITION_BY_08_BITS);
+ v_data2_u8r = BMI160_SET_BITSLICE(
+ v_data2_u8r,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Z,
+ v_data1_u8r);
+ /* write 0x77 bit 4 and 5*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_Z__REG,
+ &v_data2_u8r,
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ return ERROR;
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API read the accel offset enable bit
+ * from the register 0x77 bit 6
+ *
+ *
+ *
+ * @param v_accel_off_enable_u8: The value of accel offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_offset_enable(
+u8 *v_accel_off_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read accel offset enable */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_ACCEL_OFF_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_off_enable_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_OFFSET_6_ACCEL_OFF_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write the accel offset enable bit
+ * from the register 0x77 bit 6
+ *
+ *
+ *
+ * @param v_accel_off_enable_u8: The value of accel offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_offset_enable(
+u8 v_accel_off_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write accel offset enable */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_ACCEL_OFF_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_OFFSET_6_ACCEL_OFF_ENABLE,
+ v_accel_off_enable_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_ACCEL_OFF_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read the accel offset enable bit
+ * from the register 0x77 bit 7
+ *
+ *
+ *
+ * @param v_gyro_off_enable_u8: The value of gyro offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_offset_enable(
+u8 *v_gyro_off_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read gyro offset*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_EN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_off_enable_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_OFFSET_6_GYRO_OFF_EN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write the accel offset enable bit
+ * from the register 0x77 bit 7
+ *
+ *
+ *
+ * @param v_gyro_off_enable_u8: The value of gyro offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_offset_enable(
+u8 v_gyro_off_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write gyro offset*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_EN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_OFFSET_6_GYRO_OFF_EN,
+ v_gyro_off_enable_u8);
+ com_rslt += p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_OFFSET_6_GYRO_OFF_EN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads step counter value
+ * form the register 0x78 and 0x79
+ *
+ *
+ *
+ *
+ * @param v_step_cnt_s16 : The value of step counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_step_count(u16 *v_step_cnt_s16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* array having the step counter LSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 a_data_u8r[BMI160_STEP_COUNT_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read step counter */
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STEP_COUNT_LSB__REG,
+ a_data_u8r, BMI160_STEP_COUNTER_LENGTH);
+
+ *v_step_cnt_s16 = (s16)
+ ((((s32)((s8)a_data_u8r[BMI160_STEP_COUNT_MSB_BYTE]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[BMI160_STEP_COUNT_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API Reads
+ * step counter configuration
+ * from the register 0x7A bit 0 to 7
+ * and from the register 0x7B bit 0 to 2 and 4 to 7
+ *
+ *
+ * @param v_step_config_u16 : The value of step configuration
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_step_config(
+u16 *v_step_config_u16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data1_u8r = BMI160_INIT_VALUE;
+ u8 v_data2_u8r = BMI160_INIT_VALUE;
+ u16 v_data3_u8r = BMI160_INIT_VALUE;
+ /* Read the 0 to 7 bit*/
+ com_rslt =
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_ZERO__REG,
+ &v_data1_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* Read the 8 to 10 bit*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_ONE_CNF1__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data2_u8r = BMI160_GET_BITSLICE(v_data2_u8r,
+ BMI160_USER_STEP_CONFIG_ONE_CNF1);
+ v_data3_u8r = ((u16)((((u32)
+ ((u8)v_data2_u8r))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | (v_data1_u8r)));
+ /* Read the 11 to 14 bit*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_ONE_CNF2__REG,
+ &v_data1_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data1_u8r = BMI160_GET_BITSLICE(v_data1_u8r,
+ BMI160_USER_STEP_CONFIG_ONE_CNF2);
+ *v_step_config_u16 = ((u16)((((u32)
+ ((u8)v_data1_u8r))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | (v_data3_u8r)));
+
+ return com_rslt;
+}
+ /*!
+ * @brief This API write
+ * step counter configuration
+ * from the register 0x7A bit 0 to 7
+ * and from the register 0x7B bit 0 to 2 and 4 to 7
+ *
+ *
+ * @param v_step_config_u16 :
+ * the value of Enable step configuration
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_step_config(
+u16 v_step_config_u16)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data1_u8r = BMI160_INIT_VALUE;
+ u8 v_data2_u8r = BMI160_INIT_VALUE;
+ u16 v_data3_u16 = BMI160_INIT_VALUE;
+
+ /* write the 0 to 7 bit*/
+ v_data1_u8r = (u8)(v_step_config_u16 &
+ BMI160_STEP_CONFIG_0_7);
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_ZERO__REG,
+ &v_data1_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* write the 8 to 10 bit*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_ONE_CNF1__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u16 = (u16) (v_step_config_u16 &
+ BMI160_STEP_CONFIG_8_10);
+ v_data1_u8r = (u8)(v_data3_u16
+ >> BMI160_SHIFT_BIT_POSITION_BY_08_BITS);
+ v_data2_u8r = BMI160_SET_BITSLICE(v_data2_u8r,
+ BMI160_USER_STEP_CONFIG_ONE_CNF1, v_data1_u8r);
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_ONE_CNF1__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ /* write the 11 to 14 bit*/
+ com_rslt += p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_ONE_CNF2__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u16 = (u16) (v_step_config_u16 &
+ BMI160_STEP_CONFIG_11_14);
+ v_data1_u8r = (u8)(v_data3_u16
+ >> BMI160_SHIFT_BIT_POSITION_BY_12_BITS);
+ v_data2_u8r = BMI160_SET_BITSLICE(v_data2_u8r,
+ BMI160_USER_STEP_CONFIG_ONE_CNF2, v_data1_u8r);
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_ONE_CNF2__REG,
+ &v_data2_u8r, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ return com_rslt;
+}
+ /*!
+ * @brief This API read enable step counter
+ * from the register 0x7B bit 3
+ *
+ *
+ * @param v_step_counter_u8 : The value of step counter enable
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_step_counter_enable(
+u8 *v_step_counter_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the step counter */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_step_counter_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write enable step counter
+ * from the register 0x7B bit 3
+ *
+ *
+ * @param v_step_counter_u8 : The value of step counter enable
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_step_counter_enable(u8 v_step_counter_u8)
+{
+/* variable used for return the status of communication result*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+/* check the p_bmi160 structure as NULL*/
+if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+} else {
+ if (v_step_counter_u8 <= BMI160_MAX_GYRO_STEP_COUNTER) {
+ /* write the step counter */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE,
+ v_step_counter_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+}
+ return com_rslt;
+}
+ /*!
+ * @brief This API set Step counter modes
+ *
+ *
+ * @param v_step_mode_u8 : The value of step counter mode
+ * value | mode
+ * ----------|-----------
+ * 0 | BMI160_STEP_NORMAL_MODE
+ * 1 | BMI160_STEP_SENSITIVE_MODE
+ * 2 | BMI160_STEP_ROBUST_MODE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_step_mode(u8 v_step_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+
+ switch (v_step_mode_u8) {
+ case BMI160_STEP_NORMAL_MODE:
+ com_rslt = bmi160_set_step_config(
+ STEP_CONFIG_NORMAL);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ case BMI160_STEP_SENSITIVE_MODE:
+ com_rslt = bmi160_set_step_config(
+ STEP_CONFIG_SENSITIVE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ case BMI160_STEP_ROBUST_MODE:
+ com_rslt = bmi160_set_step_config(
+ STEP_CONFIG_ROBUST);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+
+ return com_rslt;
+}
+/*!
+ * @brief This API used to trigger the signification motion
+ * interrupt
+ *
+ *
+ * @param v_significant_u8 : The value of interrupt selection
+ * value | interrupt
+ * ----------|-----------
+ * 0 | BMI160_MAP_INTR1
+ * 1 | BMI160_MAP_INTR2
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_map_significant_motion_intr(
+u8 v_significant_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_sig_motion_u8 = BMI160_INIT_VALUE;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ u8 v_any_motion_intr1_stat_u8 = BMI160_ENABLE_ANY_MOTION_INTR1;
+ u8 v_any_motion_intr2_stat_u8 = BMI160_ENABLE_ANY_MOTION_INTR2;
+ u8 v_any_motion_axis_stat_u8 = BMI160_ENABLE_ANY_MOTION_AXIS;
+ /* enable the significant motion interrupt */
+ com_rslt = bmi160_get_intr_significant_motion_select(&v_sig_motion_u8);
+ if (v_sig_motion_u8 != BMI160_SIG_MOTION_STAT_HIGH)
+ com_rslt += bmi160_set_intr_significant_motion_select(
+ BMI160_SIG_MOTION_INTR_ENABLE);
+ switch (v_significant_u8) {
+ case BMI160_MAP_INTR1:
+ /* interrupt */
+ com_rslt += bmi160_read_reg(
+ BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_any_motion_intr1_stat_u8;
+ /* map the signification interrupt to any-motion interrupt1*/
+ com_rslt += bmi160_write_reg(
+ BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* axis*/
+ com_rslt = bmi160_read_reg(BMI160_USER_INTR_ENABLE_0_ADDR,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_any_motion_axis_stat_u8;
+ com_rslt += bmi160_write_reg(
+ BMI160_USER_INTR_ENABLE_0_ADDR,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+
+ case BMI160_MAP_INTR2:
+ /* map the signification interrupt to any-motion interrupt2*/
+ com_rslt += bmi160_read_reg(
+ BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_any_motion_intr2_stat_u8;
+ com_rslt += bmi160_write_reg(
+ BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* axis*/
+ com_rslt = bmi160_read_reg(BMI160_USER_INTR_ENABLE_0_ADDR,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_any_motion_axis_stat_u8;
+ com_rslt += bmi160_write_reg(
+ BMI160_USER_INTR_ENABLE_0_ADDR,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API used to trigger the step detector
+ * interrupt
+ *
+ *
+ * @param v_step_detector_u8 : The value of interrupt selection
+ * value | interrupt
+ * ----------|-----------
+ * 0 | BMI160_MAP_INTR1
+ * 1 | BMI160_MAP_INTR2
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_map_step_detector_intr(
+u8 v_step_detector_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_step_det_u8 = BMI160_INIT_VALUE;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ u8 v_low_g_intr_u81_stat_u8 = BMI160_LOW_G_INTR_STAT;
+ u8 v_low_g_intr_u82_stat_u8 = BMI160_LOW_G_INTR_STAT;
+ u8 v_low_g_enable_u8 = BMI160_ENABLE_LOW_G;
+ /* read the v_status_s8 of step detector interrupt*/
+ com_rslt = bmi160_get_step_detector_enable(&v_step_det_u8);
+ if (v_step_det_u8 != BMI160_STEP_DET_STAT_HIGH)
+ com_rslt += bmi160_set_step_detector_enable(
+ BMI160_STEP_DETECT_INTR_ENABLE);
+ switch (v_step_detector_u8) {
+ case BMI160_MAP_INTR1:
+ com_rslt += bmi160_read_reg(
+ BMI160_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_low_g_intr_u81_stat_u8;
+ /* map the step detector interrupt
+ to Low-g interrupt 1*/
+ com_rslt += bmi160_write_reg(
+ BMI160_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* Enable the Low-g interrupt*/
+ com_rslt = bmi160_read_reg(
+ BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_low_g_enable_u8;
+ com_rslt += bmi160_write_reg(
+ BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ case BMI160_MAP_INTR2:
+ /* map the step detector interrupt
+ to Low-g interrupt 1*/
+ com_rslt += bmi160_read_reg(
+ BMI160_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_low_g_intr_u82_stat_u8;
+
+ com_rslt += bmi160_write_reg(
+ BMI160_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* Enable the Low-g interrupt*/
+ com_rslt = bmi160_read_reg(
+ BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_low_g_enable_u8;
+ com_rslt += bmi160_write_reg(
+ BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API used to clear the step counter interrupt
+ * interrupt
+ *
+ *
+ * @param : None
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_clear_step_counter(void)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* clear the step counter*/
+ com_rslt = bmi160_set_command_register(RESET_STEP_COUNTER);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+
+}
+ /*!
+ * @brief This API writes value to the register 0x7E bit 0 to 7
+ *
+ *
+ * @param v_command_reg_u8 : The value to write command register
+ * value | Description
+ * ---------|--------------------------------------------------------
+ * 0x00 | Reserved
+ * 0x03 | Starts fast offset calibration for the accel and gyro
+ * 0x10 | Sets the PMU mode for the Accelerometer to suspend
+ * 0x11 | Sets the PMU mode for the Accelerometer to normal
+ * 0x12 | Sets the PMU mode for the Accelerometer Lowpower
+ * 0x14 | Sets the PMU mode for the Gyroscope to suspend
+ * 0x15 | Sets the PMU mode for the Gyroscope to normal
+ * 0x16 | Reserved
+ * 0x17 | Sets the PMU mode for the Gyroscope to fast start-up
+ * 0x18 | Sets the PMU mode for the Magnetometer to suspend
+ * 0x19 | Sets the PMU mode for the Magnetometer to normal
+ * 0x1A | Sets the PMU mode for the Magnetometer to Lowpower
+ * 0xB0 | Clears all data in the FIFO
+ * 0xB1 | Resets the interrupt engine
+ * 0xB2 | step_cnt_clr Clears the step counter
+ * 0xB6 | Triggers a reset
+ * 0x37 | See extmode_en_last
+ * 0x9A | See extmode_en_last
+ * 0xC0 | Enable the extended mode
+ * 0xC4 | Erase NVM cell
+ * 0xC8 | Load NVM cell
+ * 0xF0 | Reset acceleration data path
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_command_register(u8 v_command_reg_u8)
+{
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write command register */
+ com_rslt = p_bmi160->BMI160_BUS_WRITE_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_CMD_COMMANDS__REG,
+ &v_command_reg_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read target page from the register 0x7F bit 4 and 5
+ *
+ * @param v_target_page_u8: The value of target page
+ * value | page
+ * ---------|-----------
+ * 0 | User data/configure page
+ * 1 | Chip level trim/test page
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_target_page(u8 *v_target_page_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the page*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_CMD_TARGET_PAGE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_target_page_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_CMD_TARGET_PAGE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write target page from the register 0x7F bit 4 and 5
+ *
+ * @param v_target_page_u8: The value of target page
+ * value | page
+ * ---------|-----------
+ * 0 | User data/configure page
+ * 1 | Chip level trim/test page
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_target_page(u8 v_target_page_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_target_page_u8 <= BMI160_MAX_TARGET_PAGE) {
+ /* write the page*/
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_CMD_TARGET_PAGE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_CMD_TARGET_PAGE,
+ v_target_page_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_CMD_TARGET_PAGE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read page enable from the register 0x7F bit 7
+ *
+ *
+ *
+ * @param v_page_enable_u8: The value of page enable
+ * value | page
+ * ---------|-----------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_paging_enable(u8 *v_page_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the page enable */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_CMD_PAGING_EN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_page_enable_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_CMD_PAGING_EN);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write page enable from the register 0x7F bit 7
+ *
+ *
+ *
+ * @param v_page_enable_u8: The value of page enable
+ * value | page
+ * ---------|-----------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_paging_enable(
+u8 v_page_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ if (v_page_enable_u8 <= BMI160_MAX_VALUE_PAGE) {
+ /* write the page enable */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_CMD_PAGING_EN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_CMD_PAGING_EN,
+ v_page_enable_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_CMD_PAGING_EN__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read
+ * pull up configuration from the register 0X85 bit 4 an 5
+ *
+ *
+ *
+ * @param v_control_pullup_u8: The value of pull up register
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_pullup_configuration(
+u8 *v_control_pullup_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read pull up value */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC(
+ p_bmi160->dev_addr,
+ BMI160_COM_C_TRIM_FIVE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ *v_control_pullup_u8 = BMI160_GET_BITSLICE(v_data_u8,
+ BMI160_COM_C_TRIM_FIVE);
+ }
+ return com_rslt;
+
+}
+ /*!
+ * @brief This API write
+ * pull up configuration from the register 0X85 bit 4 an 5
+ *
+ *
+ *
+ * @param v_control_pullup_u8: The value of pull up register
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_pullup_configuration(
+u8 v_control_pullup_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* write pull up value */
+ com_rslt = p_bmi160->BMI160_BUS_READ_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_COM_C_TRIM_FIVE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ BMI160_SET_BITSLICE(v_data_u8,
+ BMI160_COM_C_TRIM_FIVE,
+ v_control_pullup_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_WRITE_FUNC
+ (p_bmi160->dev_addr,
+ BMI160_COM_C_TRIM_FIVE__REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+
+/*!
+ * @brief This function used for read the compensated value of mag
+ * Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_compensate_xyz(
+struct bmi160_mag_xyz_s32_t *mag_comp_xyz)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ struct bmi160_mag_xyzr_t mag_xyzr;
+ com_rslt = bmi160_read_mag_xyzr(&mag_xyzr);
+ if (com_rslt)
+ return com_rslt;
+ /* Compensation for X axis */
+ mag_comp_xyz->x = bmi160_bmm150_mag_compensate_X(
+ mag_xyzr.x, mag_xyzr.r);
+
+ /* Compensation for Y axis */
+ mag_comp_xyz->y = bmi160_bmm150_mag_compensate_Y(
+ mag_xyzr.y, mag_xyzr.r);
+
+ /* Compensation for Z axis */
+ mag_comp_xyz->z = bmi160_bmm150_mag_compensate_Z(
+ mag_xyzr.z, mag_xyzr.r);
+
+ return com_rslt;
+}
+
+/*!
+ * @brief This function used for read the compensated value of mag
+ * Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_compensate_xyz_raw(
+struct bmi160_mag_xyz_s32_t *mag_comp_xyz, struct bmi160_mag_xyzr_t mag_xyzr)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+
+ /* Compensation for X axis */
+ mag_comp_xyz->x = bmi160_bmm150_mag_compensate_X(
+ mag_xyzr.x, mag_xyzr.r);
+
+ /* Compensation for Y axis */
+ mag_comp_xyz->y = bmi160_bmm150_mag_compensate_Y(
+ mag_xyzr.y, mag_xyzr.r);
+
+ /* Compensation for Z axis */
+ mag_comp_xyz->z = bmi160_bmm150_mag_compensate_Z(
+ mag_xyzr.z, mag_xyzr.r);
+
+ return com_rslt;
+}
+/*!
+ * @brief This API used to get the compensated BMM150-X data
+ * the out put of X as s32
+ * Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_x_s16 : The value of mag raw X data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 bmi160_bmm150_mag_compensate_X(s16 v_mag_data_x_s16, u16 v_data_r_u16)
+{
+s32 inter_retval = BMI160_INIT_VALUE;
+/* no overflow */
+if (v_mag_data_x_s16 != BMI160_MAG_FLIP_OVERFLOW_ADCVAL) {
+ if ((v_data_r_u16 != 0)
+ && (mag_trim.dig_xyz1 != 0)) {
+ inter_retval = ((s32)(((u16)
+ ((((s32)mag_trim.dig_xyz1)
+ << BMI160_SHIFT_BIT_POSITION_BY_14_BITS)/
+ (v_data_r_u16 != 0 ?
+ v_data_r_u16 : mag_trim.dig_xyz1))) -
+ ((u16)0x4000)));
+ } else {
+ inter_retval = BMI160_MAG_OVERFLOW_OUTPUT;
+ return inter_retval;
+ }
+ inter_retval = ((s32)((((s32)v_mag_data_x_s16) *
+ ((((((((s32)mag_trim.dig_xy2) *
+ ((((s32)inter_retval) *
+ ((s32)inter_retval))
+ >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS)) +
+ (((s32)inter_retval) *
+ ((s32)(((s16)mag_trim.dig_xy1)
+ << BMI160_SHIFT_BIT_POSITION_BY_07_BITS))))
+ >> BMI160_SHIFT_BIT_POSITION_BY_09_BITS) +
+ ((s32)0x100000)) *
+ ((s32)(((s16)mag_trim.dig_x2) +
+ ((s16)0xA0))))
+ >> BMI160_SHIFT_BIT_POSITION_BY_12_BITS))
+ >> BMI160_SHIFT_BIT_POSITION_BY_13_BITS)) +
+ (((s16)mag_trim.dig_x1)
+ << BMI160_SHIFT_BIT_POSITION_BY_03_BITS);
+ /* check the overflow output */
+ if (inter_retval == (s32)BMI160_MAG_OVERFLOW_OUTPUT)
+ inter_retval = BMI160_MAG_OVERFLOW_OUTPUT_S32;
+} else {
+ /* overflow */
+ inter_retval = BMI160_MAG_OVERFLOW_OUTPUT;
+}
+return inter_retval;
+}
+/*!
+ * @brief This API used to get the compensated BMM150-Y data
+ * the out put of Y as s32
+ * Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_y_s16 : The value of mag raw Y data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated Y data value output as s32
+ */
+s32 bmi160_bmm150_mag_compensate_Y(s16 v_mag_data_y_s16, u16 v_data_r_u16)
+{
+s32 inter_retval = BMI160_INIT_VALUE;
+/* no overflow */
+if (v_mag_data_y_s16 != BMI160_MAG_FLIP_OVERFLOW_ADCVAL) {
+ if ((v_data_r_u16 != 0)
+ && (mag_trim.dig_xyz1 != 0)) {
+ inter_retval = ((s32)(((u16)(((
+ (s32)mag_trim.dig_xyz1)
+ << BMI160_SHIFT_BIT_POSITION_BY_14_BITS) /
+ (v_data_r_u16 != 0 ?
+ v_data_r_u16 : mag_trim.dig_xyz1))) -
+ ((u16)0x4000)));
+ } else {
+ inter_retval = BMI160_MAG_OVERFLOW_OUTPUT;
+ return inter_retval;
+ }
+ inter_retval = ((s32)((((s32)v_mag_data_y_s16) * ((((((((s32)
+ mag_trim.dig_xy2) * ((((s32) inter_retval) *
+ ((s32)inter_retval)) >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS))
+ + (((s32)inter_retval) *
+ ((s32)(((s16)mag_trim.dig_xy1)
+ << BMI160_SHIFT_BIT_POSITION_BY_07_BITS))))
+ >> BMI160_SHIFT_BIT_POSITION_BY_09_BITS) +
+ ((s32)0x100000))
+ * ((s32)(((s16)mag_trim.dig_y2)
+ + ((s16)0xA0))))
+ >> BMI160_SHIFT_BIT_POSITION_BY_12_BITS))
+ >> BMI160_SHIFT_BIT_POSITION_BY_13_BITS)) +
+ (((s16)mag_trim.dig_y1)
+ << BMI160_SHIFT_BIT_POSITION_BY_03_BITS);
+ /* check the overflow output */
+ if (inter_retval == (s32)BMI160_MAG_OVERFLOW_OUTPUT)
+ inter_retval = BMI160_MAG_OVERFLOW_OUTPUT_S32;
+} else {
+ /* overflow */
+ inter_retval = BMI160_MAG_OVERFLOW_OUTPUT;
+}
+return inter_retval;
+}
+/*!
+ * @brief This API used to get the compensated BMM150-Z data
+ * the out put of Z as s32
+ * Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_z_s16 : The value of mag raw Z data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated Z data value output as s32
+ */
+s32 bmi160_bmm150_mag_compensate_Z(s16 v_mag_data_z_s16, u16 v_data_r_u16)
+{
+ s32 retval = BMI160_INIT_VALUE;
+
+ if (v_mag_data_z_s16 != BMI160_MAG_HALL_OVERFLOW_ADCVAL) {
+ if ((v_data_r_u16 != 0)
+ && (mag_trim.dig_z2 != 0)
+ /* && (mag_trim.dig_z3 != 0)*/
+ && (mag_trim.dig_z1 != 0)
+ && (mag_trim.dig_xyz1 != 0)) {
+ retval = (((((s32)(v_mag_data_z_s16 - mag_trim.dig_z4))
+ << BMI160_SHIFT_BIT_POSITION_BY_15_BITS) -
+ ((((s32)mag_trim.dig_z3) *
+ ((s32)(((s16)v_data_r_u16) -
+ ((s16)mag_trim.dig_xyz1))))
+ >> BMI160_SHIFT_BIT_POSITION_BY_02_BITS))/
+ (mag_trim.dig_z2 +
+ ((s16)(((((s32)mag_trim.dig_z1) *
+ ((((s16)v_data_r_u16)
+ << BMI160_SHIFT_BIT_POSITION_BY_01_BIT))) +
+ (1 << BMI160_SHIFT_BIT_POSITION_BY_15_BITS))
+ >> BMI160_SHIFT_BIT_POSITION_BY_16_BITS))));
+ }
+ } else {
+ retval = BMI160_MAG_OVERFLOW_OUTPUT;
+ }
+ return retval;
+}
+ /*!
+ * @brief This function used for initialize the bmm150 sensor
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_interface_init(void)
+{
+ /* This variable used for provide the communication
+ results*/
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = BMI160_INIT_VALUE;
+ u8 v_pull_value_u8 = BMI160_INIT_VALUE;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ /* accel operation mode to normal*/
+ com_rslt = bmi160_set_command_register(ACCEL_MODE_NORMAL);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* write the mag power mode as NORMAL*/
+ com_rslt += bmi160_set_mag_interface_normal();
+
+ /* register 0x7E write the 0x37, 0x9A and 0x30*/
+ com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_ONE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_TWO);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_THREE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /*switch the page1*/
+ com_rslt += bmi160_set_target_page(BMI160_WRITE_TARGET_PAGE1);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_target_page(&v_data_u8);
+ com_rslt += bmi160_set_paging_enable(BMI160_WRITE_ENABLE_PAGE1);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_paging_enable(&v_data_u8);
+ /* enable the pullup configuration from
+ the register 0x05 bit 4 and 5 as 10*/
+ bmi160_get_pullup_configuration(&v_pull_value_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ v_pull_value_u8 = v_pull_value_u8 | BMI160_PULL_UP_DATA;
+ com_rslt += bmi160_set_pullup_configuration(v_pull_value_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /*switch the page0*/
+ com_rslt += bmi160_set_target_page(BMI160_WRITE_TARGET_PAGE0);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_target_page(&v_data_u8);
+ /* Write the BMM150 i2c address*/
+ com_rslt += bmi160_set_i2c_device_addr(BMI160_AUX_BMM150_I2C_ADDRESS);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* enable the mag interface to manual mode*/
+ com_rslt += bmi160_set_mag_manual_enable(BMI160_MANUAL_ENABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_mag_manual_enable(&v_data_u8);
+ /*Enable the MAG interface */
+ com_rslt += bmi160_set_if_mode(BMI160_ENABLE_MAG_IF_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_if_mode(&v_data_u8);
+ /* Mag normal mode*/
+ com_rslt += bmi160_bmm150_mag_wakeup();
+ printk(KERN_INFO "com_rslt:%d, <%s><%d>\n",
+ com_rslt, __func__, __LINE__);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* Read the BMM150 device id is 0x32*/
+ /*com_rslt += bmi160_set_mag_read_addr(BMI160_BMM150_CHIP_ID);*/
+ /*p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);*/
+ /*com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);*/
+ /**v_chip_id_u8 = v_data_u8;*/
+ /*p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);*/
+ /* write the power mode register*/
+ com_rslt += bmi160_set_mag_write_data(BMI160_BMM_POWER_MODE_REG);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /*write 0x4C register to write set power mode to normal*/
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_POWE_MODE_REG);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* read the mag trim values*/
+ com_rslt += bmi160_read_bmm150_mag_trim();
+ printk(KERN_INFO "com_rslt:%d, <%s><%d>\n",
+ com_rslt, __func__, __LINE__);
+ /* To avoid the auto mode enable when manual mode operation running*/
+ V_bmm150_maual_auto_condition_u8 = BMI160_MANUAL_ENABLE;
+ /* write the XY and Z repetitions*/
+ com_rslt += bmi160_set_bmm150_mag_presetmode(
+ BMI160_MAG_PRESETMODE_REGULAR);
+ printk(KERN_INFO "com_rslt:%d, <%s><%d>\n",
+ com_rslt, __func__, __LINE__);
+ /* To avoid the auto mode enable when manual mode operation running*/
+ V_bmm150_maual_auto_condition_u8 = BMI160_MANUAL_DISABLE;
+ /* Set the power mode of mag as force mode*/
+ /* The data have to write for the register
+ It write the value in the register 0x4F */
+ com_rslt += bmi160_set_mag_write_data(BMI160_BMM150_FORCE_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ printk(KERN_INFO "com_rslt:%d, <%s><%d>\n",
+ com_rslt, __func__, __LINE__);
+ /* write into power mode register*/
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_POWE_MODE_REG);
+ /* write the mag v_data_bw_u8 as 25Hz*/
+ com_rslt += bmi160_set_mag_output_data_rate(
+ BMI160_MAG_OUTPUT_DATA_RATE_25HZ);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ /* When mag interface is auto mode - The mag read address
+ starts the register 0x42*/
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_BMM150_DATA_REG);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* enable mag interface to auto mode*/
+ com_rslt += bmi160_set_mag_manual_enable(BMI160_MANUAL_DISABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_mag_manual_enable(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for set the mag power control
+ * bit enable
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_wakeup(void)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = BMI160_INIT_VALUE;
+ u8 v_try_times_u8 = BMI160_BMM150_MAX_RETRY_WAKEUP;
+ u8 v_power_control_bit_u8 = BMI160_INIT_VALUE;
+ u8 i = BMI160_INIT_VALUE;
+
+ for (i = BMI160_INIT_VALUE; i < v_try_times_u8; i++) {
+ com_rslt = bmi160_set_mag_write_data(BMI160_BMM150_POWER_ON);
+ p_bmi160->delay_msec(BMI160_BMM150_WAKEUP_DELAY1);
+ /*write 0x4B register to enable power control bit*/
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_POWE_CONTROL_REG);
+ p_bmi160->delay_msec(BMI160_BMM150_WAKEUP_DELAY2);
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_BMM150_POWE_CONTROL_REG);
+ /* 0x04 is secondary read mag x lsb register */
+ p_bmi160->delay_msec(BMI160_BMM150_WAKEUP_DELAY3);
+ com_rslt += bmi160_read_reg(BMI160_USER_DATA_0_ADDR,
+ &v_power_control_bit_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ v_power_control_bit_u8 = BMI160_BMM150_SET_POWER_CONTROL
+ & v_power_control_bit_u8;
+ if (v_power_control_bit_u8 == BMI160_BMM150_POWER_ON)
+ break;
+ }
+ com_rslt = (i >= v_try_times_u8) ?
+ BMI160_BMM150_POWER_ON_FAIL : BMI160_BMM150_POWER_ON_SUCCESS;
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for set the magnetometer
+ * power mode.
+ * @note
+ * Before set the mag power mode
+ * make sure the following two point is addressed
+ * Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ *
+ * @param v_mag_sec_if_pow_mode_u8 : The value of mag power mode
+ * value | mode
+ * ----------|------------
+ * 0 | BMI160_MAG_FORCE_MODE
+ * 1 | BMI160_MAG_SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_bmm150_mag_and_secondary_if_power_mode(
+u8 v_mag_sec_if_pow_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = BMI160_INIT_VALUE;
+ /* set the accel power mode to NORMAL*/
+ com_rslt = bmi160_set_command_register(ACCEL_MODE_NORMAL);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ /* set mag interface manual mode*/
+ if (p_bmi160->mag_manual_enable != BMI160_MANUAL_ENABLE) {
+ com_rslt += bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_ENABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+
+ switch (v_mag_sec_if_pow_mode_u8) {
+ case BMI160_MAG_FORCE_MODE:
+ /* set the secondary mag power mode as NORMAL*/
+ com_rslt += bmi160_set_mag_interface_normal();
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ /* set the mag power mode as FORCE mode*/
+ com_rslt += bmi160_bmm150_mag_set_power_mode(FORCE_MODE);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ case BMI160_MAG_SUSPEND_MODE:
+ /* set the mag power mode as SUSPEND mode*/
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ com_rslt += bmi160_bmm150_mag_set_power_mode(SUSPEND_MODE);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* set the secondary mag power mode as SUSPEND*/
+ com_rslt += bmi160_set_command_register(MAG_MODE_SUSPEND);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ if (p_bmi160->mag_manual_enable == BMI160_MANUAL_ENABLE) {
+ /* set mag interface auto mode*/
+ com_rslt += bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_DISABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ return com_rslt;
+}
+/*!
+ * @brief This function used for set the magnetometer
+ * power mode.
+ * @note
+ * Before set the mag power mode
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @param v_mag_pow_mode_u8 : The value of mag power mode
+ * value | mode
+ * ----------|------------
+ * 0 | FORCE_MODE
+ * 1 | SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_set_power_mode(
+u8 v_mag_pow_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = BMI160_INIT_VALUE;
+ u8 manual_enable_status = 0;
+ /* set mag interface manual mode*/
+ if (p_bmi160->mag_manual_enable != BMI160_MANUAL_ENABLE) {
+ com_rslt = bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_ENABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_get_mag_manual_enable(&manual_enable_status);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ printk(KERN_INFO "1com_rslt:%d, manual:%d, manual_read:%d\n",
+ com_rslt, p_bmi160->mag_manual_enable, manual_enable_status);
+ }
+ printk(KERN_INFO "2com_rslt:%d, manual:%d, manual_read:%d\n",
+ com_rslt, p_bmi160->mag_manual_enable, manual_enable_status);
+
+ switch (v_mag_pow_mode_u8) {
+ case FORCE_MODE:
+ /* Set the power control bit enabled */
+ com_rslt = bmi160_bmm150_mag_wakeup();
+ /* write the mag power mode as FORCE mode*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_BMM150_FORCE_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_POWE_MODE_REG);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* To avoid the auto mode enable when manual
+ mode operation running*/
+ V_bmm150_maual_auto_condition_u8 = BMI160_MANUAL_ENABLE;
+ /* set the preset mode */
+ com_rslt += bmi160_set_bmm150_mag_presetmode(
+ BMI160_MAG_PRESETMODE_REGULAR);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* To avoid the auto mode enable when manual
+ mode operation running*/
+ V_bmm150_maual_auto_condition_u8 = BMI160_MANUAL_DISABLE;
+ /* set the mag read address to data registers*/
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_BMM150_DATA_REG);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ case SUSPEND_MODE:
+ printk(KERN_INFO "3com_rslt:%d, manual:%d, read_manual:%d\n",
+ com_rslt, p_bmi160->mag_manual_enable, manual_enable_status);
+ /* Set the power mode of mag as suspend mode*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_BMM150_POWER_OFF);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_POWE_CONTROL_REG);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ printk(KERN_INFO "4com_rslt:%d, manual:%d, manual_read:%d\n",
+ com_rslt, p_bmi160->mag_manual_enable, manual_enable_status);
+ /* set mag interface auto mode*/
+ if (p_bmi160->mag_manual_enable == BMI160_MANUAL_ENABLE) {
+ com_rslt += bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_DISABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_get_mag_manual_enable(&manual_enable_status);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "5com_rslt:%d, manual:%d, manual_read:%d\n",
+ com_rslt, p_bmi160->mag_manual_enable, manual_enable_status);
+ return com_rslt;
+}
+/*!
+ * @brief This API used to set the pre-set modes of bmm150
+ * The pre-set mode setting is depend on data rate and xy and z repetitions
+ *
+ * @note
+ * Before set the mag preset mode
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_mode_u8: The value of pre-set mode selection value
+ * value | pre_set mode
+ * ----------|------------
+ * 1 | BMI160_MAG_PRESETMODE_LOWPOWER
+ * 2 | BMI160_MAG_PRESETMODE_REGULAR
+ * 3 | BMI160_MAG_PRESETMODE_HIGHACCURACY
+ * 4 | BMI160_MAG_PRESETMODE_ENHANCED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_bmm150_mag_presetmode(u8 v_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ switch (v_mode_u8) {
+ case BMI160_MAG_PRESETMODE_LOWPOWER:
+ /* write the XY and Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt = bmi160_set_mag_write_data(
+ BMI160_MAG_LOWPOWER_REPXY);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_XY_REP);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* write the Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_MAG_LOWPOWER_REPZ);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_Z_REP);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* set the mag v_data_u8 rate as 10 to the register 0x4C*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_MAG_LOWPOWER_DR);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_POWE_MODE_REG);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ case BMI160_MAG_PRESETMODE_REGULAR:
+ /* write the XY and Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt = bmi160_set_mag_write_data(
+ BMI160_MAG_REGULAR_REPXY);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_XY_REP);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* write the Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_MAG_REGULAR_REPZ);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_Z_REP);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* set the mag v_data_u8 rate as 10 to the register 0x4C*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_MAG_REGULAR_DR);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_POWE_MODE_REG);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ case BMI160_MAG_PRESETMODE_HIGHACCURACY:
+ /* write the XY and Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt = bmi160_set_mag_write_data(
+ BMI160_MAG_HIGHACCURACY_REPXY);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_XY_REP);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* write the Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_MAG_HIGHACCURACY_REPZ);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_Z_REP);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* set the mag v_data_u8 rate as 20 to the register 0x4C*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_MAG_HIGHACCURACY_DR);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_POWE_MODE_REG);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ case BMI160_MAG_PRESETMODE_ENHANCED:
+ /* write the XY and Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt = bmi160_set_mag_write_data(
+ BMI160_MAG_ENHANCED_REPXY);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_XY_REP);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* write the Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_MAG_ENHANCED_REPZ);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_Z_REP);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* set the mag v_data_u8 rate as 10 to the register 0x4C*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_MAG_ENHANCED_DR);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_BMM150_POWE_MODE_REG);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for read the trim values of magnetometer
+ *
+ * @note
+ * Before reading the mag trimming values
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_bmm150_mag_trim(void)
+{
+ /* This variable used for provide the communication
+ results*/
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array holding the bmm150 trim data
+ */
+ u8 v_data_u8[BMI160_MAG_TRIM_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE};
+ /* read dig_x1 value */
+ com_rslt = bmi160_set_mag_read_addr(
+ BMI160_MAG_DIG_X1);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_X1],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_x1 = v_data_u8[BMI160_BMM150_DIG_X1];
+ /* read dig_y1 value */
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_MAG_DIG_Y1);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_Y1],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_y1 = v_data_u8[BMI160_BMM150_DIG_Y1];
+
+ /* read dig_x2 value */
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_MAG_DIG_X2);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_X2],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_x2 = v_data_u8[BMI160_BMM150_DIG_X2];
+ /* read dig_y2 value */
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_MAG_DIG_Y2);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_Y3],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_y2 = v_data_u8[BMI160_BMM150_DIG_Y3];
+
+ /* read dig_xy1 value */
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_MAG_DIG_XY1);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_XY1],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_xy1 = v_data_u8[BMI160_BMM150_DIG_XY1];
+ /* read dig_xy2 value */
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_MAG_DIG_XY2);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 ls register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_XY2],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_xy2 = v_data_u8[BMI160_BMM150_DIG_XY2];
+
+ /* read dig_z1 lsb value */
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_MAG_DIG_Z1_LSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_Z1_LSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* read dig_z1 msb value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_MAG_DIG_Z1_MSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_Z1_MSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_z1 =
+ (u16)((((u32)((u8)v_data_u8[BMI160_BMM150_DIG_Z1_MSB]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_BMM150_DIG_Z1_LSB]));
+
+ /* read dig_z2 lsb value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_MAG_DIG_Z2_LSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_Z2_LSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* read dig_z2 msb value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_MAG_DIG_Z2_MSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_Z2_MSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_z2 =
+ (s16)((((s32)((s8)v_data_u8[BMI160_BMM150_DIG_Z2_MSB]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_BMM150_DIG_Z2_LSB]));
+
+ /* read dig_z3 lsb value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_MAG_DIG_Z3_LSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_DIG_Z3_LSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* read dig_z3 msb value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_MAG_DIG_Z3_MSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_DIG_Z3_MSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_z3 =
+ (s16)((((s32)((s8)v_data_u8[BMI160_BMM150_DIG_DIG_Z3_MSB]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_BMM150_DIG_DIG_Z3_LSB]));
+
+ /* read dig_z4 lsb value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_MAG_DIG_Z4_LSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_DIG_Z4_LSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* read dig_z4 msb value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_MAG_DIG_Z4_MSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_DIG_Z4_MSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_z4 =
+ (s16)((((s32)((s8)v_data_u8[BMI160_BMM150_DIG_DIG_Z4_MSB]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_BMM150_DIG_DIG_Z4_LSB]));
+
+ /* read dig_xyz1 lsb value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_MAG_DIG_XYZ1_LSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_DIG_XYZ1_LSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* read dig_xyz1 msb value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_MAG_DIG_XYZ1_MSB);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[BMI160_BMM150_DIG_DIG_XYZ1_MSB],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ mag_trim.dig_xyz1 =
+ (u16)((((u32)((u8)v_data_u8[BMI160_BMM150_DIG_DIG_XYZ1_MSB]))
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[BMI160_BMM150_DIG_DIG_XYZ1_LSB]));
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for initialize
+ * the AKM09911 and AKM09912 sensor
+ *
+ *
+ * @param v_akm_i2c_address_u8: The value of device address
+ * AKM sensor | Slave address
+ * --------------|---------------------
+ * AKM09911 | AKM09911_I2C_ADDR_1
+ * - | and AKM09911_I2C_ADDR_2
+ * AKM09912 | AKM09912_I2C_ADDR_1
+ * - | AKM09912_I2C_ADDR_2
+ * - | AKM09912_I2C_ADDR_3
+ * - | AKM09912_I2C_ADDR_4
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm_mag_interface_init(
+u8 v_akm_i2c_address_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_pull_value_u8 = BMI160_INIT_VALUE;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ u8 v_akm_chip_id_u8 = BMI160_INIT_VALUE;
+ /* accel operation mode to normal*/
+ com_rslt = bmi160_set_command_register(ACCEL_MODE_NORMAL);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_command_register(MAG_MODE_NORMAL);
+ p_bmi160->delay_msec(BMI160_AKM_INIT_DELAY);
+ bmi160_get_mag_power_mode_stat(&v_data_u8);
+ /* register 0x7E write the 0x37, 0x9A and 0x30*/
+ com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_ONE);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_TWO);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_THREE);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /*switch the page1*/
+ com_rslt += bmi160_set_target_page(BMI160_WRITE_TARGET_PAGE1);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_target_page(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_paging_enable(BMI160_WRITE_ENABLE_PAGE1);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_paging_enable(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* enable the pullup configuration from
+ the register 0x05 bit 4 and 5 to 10*/
+ bmi160_get_pullup_configuration(&v_pull_value_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ v_pull_value_u8 = v_pull_value_u8 | BMI160_PULL_UP_DATA;
+ com_rslt += bmi160_set_pullup_configuration(v_pull_value_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ /*switch the page0*/
+ com_rslt += bmi160_set_target_page(BMI160_WRITE_TARGET_PAGE0);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_target_page(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* Write the AKM09911 0r AKM09912 i2c address*/
+ com_rslt += bmi160_set_i2c_device_addr(v_akm_i2c_address_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* enable the mag interface to manual mode*/
+ com_rslt += bmi160_set_mag_manual_enable(BMI160_MANUAL_ENABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_mag_manual_enable(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /*Enable the MAG interface */
+ com_rslt += bmi160_set_if_mode(BMI160_ENABLE_MAG_IF_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_if_mode(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ /* Set the AKM Fuse ROM mode */
+ /* Set value for fuse ROM mode*/
+ com_rslt += bmi160_set_mag_write_data(AKM_FUSE_ROM_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* AKM mode address is 0x31*/
+ com_rslt += bmi160_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Read the Fuse ROM v_data_u8 from registers
+ 0x60,0x61 and 0x62*/
+ /* ASAX v_data_u8 */
+ com_rslt += bmi160_read_bst_akm_sensitivity_data();
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* read the device id of the AKM sensor
+ if device id is 0x05 - AKM09911
+ if device id is 0x04 - AKM09912*/
+ com_rslt += bmi160_set_mag_read_addr(AKM09912_CHIP_ID_REG);
+ /* 0x04 is mag_x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_akm_chip_id_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ printk(KERN_INFO "bmi160,addr:0x%x, akm_chip_id:0x%x",
+ v_akm_i2c_address_u8, v_akm_chip_id_u8);
+ /* Set value power down mode mode*/
+ com_rslt += bmi160_set_mag_write_data(AKM_POWER_DOWN_MODE_DATA);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* AKM mode address is 0x31*/
+ com_rslt += bmi160_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Set AKM Force mode*/
+ com_rslt += bmi160_set_mag_write_data(
+ AKM_SINGLE_MEASUREMENT_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* AKM mode address is 0x31*/
+ com_rslt += bmi160_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Set the AKM read xyz v_data_u8 address*/
+ com_rslt += bmi160_set_mag_read_addr(AKM_DATA_REGISTER);
+ /* write the mag v_data_bw_u8 as 25Hz*/
+ com_rslt += bmi160_set_mag_output_data_rate(
+ BMI160_MAG_OUTPUT_DATA_RATE_25HZ);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* Enable mag interface to auto mode*/
+ com_rslt += bmi160_set_mag_manual_enable(BMI160_MANUAL_DISABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_mag_manual_enable(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for read the sensitivity data of
+ * AKM09911 and AKM09912
+ *
+ * @note Before reading the mag sensitivity values
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_bst_akm_sensitivity_data(void)
+{
+ /* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array holding the sensitivity ax,ay and az data*/
+ u8 v_data_u8[BMI160_AKM_SENSITIVITY_DATA_SIZE] = {
+ BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* read asax value */
+ com_rslt = bmi160_set_mag_read_addr(BMI160_BST_AKM_ASAX);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[AKM_ASAX],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ akm_asa_data.asax = v_data_u8[AKM_ASAX];
+ /* read asay value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_BST_AKM_ASAY);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[AKM_ASAY],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ akm_asa_data.asay = v_data_u8[AKM_ASAY];
+ /* read asaz value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_BST_AKM_ASAZ);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[AKM_ASAZ],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ akm_asa_data.asaz = v_data_u8[AKM_ASAZ];
+
+ return com_rslt;
+}
+/*!
+ * @brief This API used to get the compensated X data
+ * of AKM09911 the out put of X as s32
+ * @note Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_x_s16 : The value of X data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09911_compensate_X(s16 v_bst_akm_x_s16)
+{
+ /*Return value of AKM x compensated v_data_u8*/
+ s32 retval = BMI160_INIT_VALUE;
+ /* Convert raw v_data_u8 into compensated v_data_u8*/
+ retval = (v_bst_akm_x_s16 *
+ ((akm_asa_data.asax/AKM09911_SENSITIVITY_DIV) +
+ BMI160_GEN_READ_WRITE_DATA_LENGTH));
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated Y data
+ * of AKM09911 the out put of Y as s32
+ * @note Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_y_s16 : The value of Y data
+ *
+ * @return results of compensated Y data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09911_compensate_Y(s16 v_bst_akm_y_s16)
+{
+ /*Return value of AKM y compensated v_data_u8*/
+ s32 retval = BMI160_INIT_VALUE;
+ /* Convert raw v_data_u8 into compensated v_data_u8*/
+ retval = (v_bst_akm_y_s16 *
+ ((akm_asa_data.asay/AKM09911_SENSITIVITY_DIV) +
+ BMI160_GEN_READ_WRITE_DATA_LENGTH));
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated Z data
+ * of AKM09911 the out put of Z as s32
+ * @note Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_z_s16 : The value of Z data
+ *
+ * @return results of compensated Z data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09911_compensate_Z(s16 v_bst_akm_z_s16)
+{
+ /*Return value of AKM z compensated v_data_u8*/
+ s32 retval = BMI160_INIT_VALUE;
+ /* Convert raw v_data_u8 into compensated v_data_u8*/
+ retval = (v_bst_akm_z_s16 *
+ ((akm_asa_data.asaz/AKM09911_SENSITIVITY_DIV) +
+ BMI160_GEN_READ_WRITE_DATA_LENGTH));
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated X data
+ * of AKM09912 the out put of X as s32
+ * @note Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_x_s16 : The value of X data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09912_compensate_X(s16 v_bst_akm_x_s16)
+{
+ /*Return value of AKM x compensated data*/
+ s32 retval = BMI160_INIT_VALUE;
+ /* Convert raw data into compensated data*/
+ retval = v_bst_akm_x_s16 *
+ (akm_asa_data.asax + AKM09912_SENSITIVITY)
+ / AKM09912_SENSITIVITY_DIV;
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated Y data
+ * of AKM09912 the out put of Y as s32
+ * @note Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_y_s16 : The value of Y data
+ *
+ * @return results of compensated Y data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09912_compensate_Y(s16 v_bst_akm_y_s16)
+{
+ /*Return value of AKM y compensated data*/
+ s32 retval = BMI160_INIT_VALUE;
+ /* Convert raw data into compensated data*/
+ retval = v_bst_akm_y_s16 *
+ (akm_asa_data.asax + AKM09912_SENSITIVITY)
+ / AKM09912_SENSITIVITY_DIV;
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated Z data
+ * of AKM09912 the out put of Z as s32
+ * @note Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_z_s16 : The value of Z data
+ *
+ * @return results of compensated Z data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09912_compensate_Z(s16 v_bst_akm_z_s16)
+{
+ /*Return value of AKM z compensated data*/
+ s32 retval = BMI160_INIT_VALUE;
+ /* Convert raw data into compensated data*/
+ retval = v_bst_akm_z_s16 *
+ (akm_asa_data.asax + AKM09912_SENSITIVITY)
+ / AKM09912_SENSITIVITY_DIV;
+ return retval;
+}
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09911
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm09911_compensate_xyz(
+struct bmi160_mag_xyz_s32_t *bst_akm_xyz)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ struct bmi160_mag_t mag_xyz;
+
+ com_rslt = bmi160_read_mag_xyz(&mag_xyz, BST_AKM);
+ /* Compensation for X axis */
+ bst_akm_xyz->x = bmi160_bst_akm09911_compensate_X(mag_xyz.x);
+
+ /* Compensation for Y axis */
+ bst_akm_xyz->y = bmi160_bst_akm09911_compensate_Y(mag_xyz.y);
+
+ /* Compensation for Z axis */
+ bst_akm_xyz->z = bmi160_bst_akm09911_compensate_Z(mag_xyz.z);
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09912
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm09912_compensate_xyz(
+struct bmi160_mag_xyz_s32_t *bst_akm_xyz)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ struct bmi160_mag_t mag_xyz;
+
+ com_rslt = bmi160_read_mag_xyz(&mag_xyz, BST_AKM);
+ printk(KERN_INFO "akm09912_raw_x:%d, %d, %d, <%s>,<%d>",
+ mag_xyz.x, mag_xyz.y, mag_xyz.z, __func__, __LINE__);
+ /* Compensation for X axis */
+ bst_akm_xyz->x = bmi160_bst_akm09912_compensate_X(mag_xyz.x);
+
+ /* Compensation for Y axis */
+ bst_akm_xyz->y = bmi160_bst_akm09912_compensate_Y(mag_xyz.y);
+
+ /* Compensation for Z axis */
+ bst_akm_xyz->z = bmi160_bst_akm09912_compensate_Z(mag_xyz.z);
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09912
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm09912_compensate_xyz_raw(
+struct bmi160_mag_xyz_s32_t *bst_akm_xyz)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Compensation for X axis */
+ bst_akm_xyz->x = bmi160_bst_akm09912_compensate_X(bst_akm_xyz->x);
+
+ /* Compensation for Y axis */
+ bst_akm_xyz->y = bmi160_bst_akm09912_compensate_Y(bst_akm_xyz->y);
+
+ /* Compensation for Z axis */
+ bst_akm_xyz->z = bmi160_bst_akm09912_compensate_Z(bst_akm_xyz->z);
+
+ return com_rslt;
+}
+/*!
+ * @brief This function used for set the AKM09911 and AKM09912
+ * power mode.
+ * @note Before set the AKM power mode
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @param v_akm_pow_mode_u8 : The value of akm power mode
+ * value | Description
+ * ---------|--------------------
+ * 0 | AKM_POWER_DOWN_MODE
+ * 1 | AKM_SINGLE_MEAS_MODE
+ * 2 | FUSE_ROM_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm_set_powermode(
+u8 v_akm_pow_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = BMI160_INIT_VALUE;
+ /* set mag interface manual mode*/
+ if (p_bmi160->mag_manual_enable != BMI160_MANUAL_ENABLE) {
+ com_rslt = bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_ENABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__);
+ switch (v_akm_pow_mode_u8) {
+ case AKM_POWER_DOWN_MODE:
+ /* Set the power mode of AKM as power down mode*/
+ com_rslt += bmi160_set_mag_write_data(AKM_POWER_DOWN_MODE_DATA);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ case AKM_SINGLE_MEAS_MODE:
+ /* Set the power mode of AKM as
+ single measurement mode*/
+ com_rslt += bmi160_set_mag_write_data
+ (AKM_SINGLE_MEASUREMENT_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_read_addr(AKM_DATA_REGISTER);
+ break;
+ case FUSE_ROM_MODE:
+ /* Set the power mode of AKM as
+ Fuse ROM mode*/
+ com_rslt += bmi160_set_mag_write_data(AKM_FUSE_ROM_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Sensitivity v_data_u8 */
+ com_rslt += bmi160_read_bst_akm_sensitivity_data();
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* power down mode*/
+ com_rslt += bmi160_set_mag_write_data(AKM_POWER_DOWN_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ /* set mag interface auto mode*/
+ if (p_bmi160->mag_manual_enable == BMI160_MANUAL_ENABLE) {
+ com_rslt += bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_DISABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_bmi160->mag_manual_enable, __func__, __LINE__);
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for set the magnetometer
+ * power mode of AKM09911 and AKM09912
+ * @note Before set the mag power mode
+ * make sure the following two point is addressed
+ * Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ *
+ * @param v_mag_sec_if_pow_mode_u8 : The value of secondary if power mode
+ * value | Description
+ * ---------|--------------------
+ * 0 | BMI160_MAG_FORCE_MODE
+ * 1 | BMI160_MAG_SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_bst_akm_and_secondary_if_powermode(
+u8 v_mag_sec_if_pow_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* accel operation mode to normal*/
+ com_rslt = bmi160_set_command_register(ACCEL_MODE_NORMAL);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* set mag interface manual mode*/
+ if (p_bmi160->mag_manual_enable != BMI160_MANUAL_ENABLE) {
+ com_rslt = bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_ENABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_ERR "com_rslt:%d, manual:%d,after setacc normal mode\n",
+ com_rslt, p_bmi160->mag_manual_enable);
+ switch (v_mag_sec_if_pow_mode_u8) {
+ case BMI160_MAG_FORCE_MODE:
+ /* set the secondary mag power mode as NORMAL*/
+ com_rslt += bmi160_set_mag_interface_normal();
+ /* set the akm power mode as single measurement mode*/
+ com_rslt += bmi160_bst_akm_set_powermode(AKM_SINGLE_MEAS_MODE);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_read_addr(AKM_DATA_REGISTER);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ break;
+ case BMI160_MAG_SUSPEND_MODE:
+ /* set the akm power mode as power down mode*/
+ com_rslt += bmi160_bst_akm_set_powermode(AKM_POWER_DOWN_MODE);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* set the secondary mag power mode as SUSPEND*/
+ com_rslt += bmi160_set_command_register(MAG_MODE_SUSPEND);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_BMI160_OUT_OF_RANGE;
+ break;
+ }
+ /* set mag interface auto mode*/
+ if (p_bmi160->mag_manual_enable == BMI160_MANUAL_ENABLE)
+ com_rslt += bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_DISABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ return com_rslt;
+}
+/*!
+ * @brief This function used for read the YAMAH-YAS532 init
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas532_mag_interface_init(
+void)
+{
+ /* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ u8 v_pull_value_u8 = BMI160_INIT_VALUE;
+ u8 v_data_u8 = BMI160_INIT_VALUE;
+ u8 i = BMI160_INIT_VALUE;
+ /* accel operation mode to normal*/
+ com_rslt = bmi160_set_command_register(ACCEL_MODE_NORMAL);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* write mag power mode as NORMAL*/
+ com_rslt += bmi160_set_mag_interface_normal();
+ /* register 0x7E write the 0x37, 0x9A and 0x30*/
+ com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_ONE);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_TWO);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_THREE);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /*switch the page1*/
+ com_rslt += bmi160_set_target_page(BMI160_WRITE_TARGET_PAGE1);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_target_page(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_paging_enable(BMI160_WRITE_ENABLE_PAGE1);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_paging_enable(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* enable the pullup configuration from
+ the register 0x05 bit 4 and 5 as 10*/
+ bmi160_get_pullup_configuration(&v_pull_value_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ v_pull_value_u8 = v_pull_value_u8 | BMI160_PULL_UP_DATA;
+ com_rslt += bmi160_set_pullup_configuration(v_pull_value_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /*switch the page0*/
+ com_rslt += bmi160_set_target_page(BMI160_WRITE_TARGET_PAGE0);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_target_page(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* Write the YAS532 i2c address*/
+ com_rslt += bmi160_set_i2c_device_addr(BMI160_AUX_YAS532_I2C_ADDRESS);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* enable the mag interface to manual mode*/
+ com_rslt += bmi160_set_mag_manual_enable(BMI160_MANUAL_ENABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_mag_manual_enable(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /*Enable the MAG interface */
+ com_rslt += bmi160_set_if_mode(BMI160_ENABLE_MAG_IF_MODE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_if_mode(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ v_data_u8 = BMI160_MANUAL_DISABLE;
+ /* Read the YAS532 device id is 0x02*/
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS_DEVICE_ID_REG);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* Read the YAS532 calibration data*/
+ com_rslt += bmi160_bst_yamaha_yas532_calib_values();
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Assign the data acquisition mode*/
+ yas532_data.measure_state = YAS532_MAG_STATE_INIT_COIL;
+ /* Set the default offset as invalid offset*/
+ set_vector(yas532_data.v_hard_offset_s8, INVALID_OFFSET);
+ /* set the transform to zero */
+ yas532_data.transform = BMI160_NULL;
+ /* Assign overflow as zero*/
+ yas532_data.overflow = 0;
+ #if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+ yas532_data.temp_data.num =
+ yas532_data.temp_data.idx = 0;
+ #endif
+ /* Assign the coef value*/
+ for (i = 0; i < 3; i++) {
+ yas532_data.coef[i] = yas532_version_ac_coef[i];
+ yas532_data.last_raw[i] = 0;
+ }
+ yas532_data.last_raw[3] = 0;
+ /* Set the initial values of yas532*/
+ com_rslt += bmi160_bst_yas532_set_initial_values();
+ /* write the mag v_data_bw_u8 as 25Hz*/
+ com_rslt += bmi160_set_mag_output_data_rate(
+ BMI160_MAG_OUTPUT_DATA_RATE_25HZ);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* Enable mag interface to auto mode*/
+ com_rslt += bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_DISABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ bmi160_get_mag_manual_enable(&v_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+}
+/*!
+ * @brief This function used to set the YAS532 initial values
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_set_initial_values(void)
+{
+/* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* write testr1 as 0x00*/
+ com_rslt = bmi160_set_mag_write_data(
+ BMI160_YAS532_WRITE_TESTR1);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(BMI160_YAS532_TESTR1);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write testr2 as 0x00*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_YAS532_WRITE_TESTR2);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(BMI160_YAS532_TESTR2);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write Rcoil as 0x00*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_YAS532_WRITE_RCOIL);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(BMI160_YAS532_RCOIL);
+ p_bmi160->delay_msec(BMI160_YAS532_SET_INITIAL_VALUE_DELAY);
+ /* check the valid offset*/
+ if (is_valid_offset(yas532_data.v_hard_offset_s8)) {
+ com_rslt += bmi160_bst_yas532_set_offset(
+ yas532_data.v_hard_offset_s8);
+ yas532_data.measure_state = YAS532_MAG_STATE_NORMAL;
+ } else {
+ /* set the default offset as invalid offset*/
+ set_vector(yas532_data.v_hard_offset_s8, INVALID_OFFSET);
+ /*Set the default measure state for offset correction*/
+ yas532_data.measure_state = YAS532_MAG_STATE_MEASURE_OFFSET;
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This function used for YAS532 offset correction
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_magnetic_measure_set_offset(
+void)
+{
+ /* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* used for offset value set to the offset register*/
+ s8 v_hard_offset_s8[BMI160_HARD_OFFSET_DATA_SIZE] = {
+ BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* offset correction factors*/
+ static const u8 v_correct_u8[BMI160_YAS_CORRECT_DATA_SIZE] = {
+ 16, 8, 4, 2, 1};
+ /* used for the temperature */
+ u16 v_temp_u16 = BMI160_INIT_VALUE;
+ /* used for the xy1y2 read*/
+ u16 v_xy1y2_u16[BMI160_YAS_XY1Y2_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* local flag for assign the values*/
+ s32 v_flag_s32[BMI160_YAS_FLAG_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ u8 i, j, v_busy_u8, v_overflow_u8 = BMI160_INIT_VALUE;
+
+ for (i = 0; i < 5; i++) {
+ /* set the offset values*/
+ com_rslt = bmi160_bst_yas532_set_offset(v_hard_offset_s8);
+ /* read the sensor data*/
+ com_rslt += bmi160_bst_yas532_normal_measurement_data(
+ BMI160_YAS532_ACQ_START, &v_busy_u8, &v_temp_u16,
+ v_xy1y2_u16, &v_overflow_u8);
+ /* check the sensor busy status*/
+ if (v_busy_u8)
+ return E_BMI160_BUSY;
+ /* calculate the magnetic correction with
+ offset and assign the values
+ to the offset register */
+ for (j = 0; j < 3; j++) {
+ if (YAS532_DATA_CENTER == v_xy1y2_u16[j])
+ v_flag_s32[j] = 0;
+ if (YAS532_DATA_CENTER < v_xy1y2_u16[j])
+ v_flag_s32[j] = 1;
+ if (v_xy1y2_u16[j] < YAS532_DATA_CENTER)
+ v_flag_s32[j] = -1;
+ }
+ for (j = 0; j < 3; j++) {
+ if (v_flag_s32[j])
+ v_hard_offset_s8[j] = (s8)(v_hard_offset_s8[j]
+ + v_flag_s32[j] * v_correct_u8[i]);
+ }
+ }
+ /* set the offset */
+ com_rslt += bmi160_bst_yas532_set_offset(v_hard_offset_s8);
+ return com_rslt;
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS532 calibration data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas532_calib_values(void)
+{
+ /* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array holding the YAS532 calibration values */
+ u8 v_data_u8[BMI160_YAS532_CALIB_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* Read the DX value */
+ com_rslt = bmi160_set_mag_read_addr(BMI160_YAS532_CALIB_CX);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[0], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ yas532_data.calib_yas532.cx = (s32)((v_data_u8[0]
+ * 10) - 1280);
+ /* Read the DY1 value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB_CY1);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[1], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ yas532_data.calib_yas532.cy1 =
+ (s32)((v_data_u8[1] * 10) - 1280);
+ /* Read the DY2 value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB_CY2);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[2], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ yas532_data.calib_yas532.cy2 =
+ (s32)((v_data_u8[2] * 10) - 1280);
+ /* Read the D2 and D3 value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB1);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[3], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ yas532_data.calib_yas532.a2 =
+ (s32)(((v_data_u8[3] >>
+ BMI160_SHIFT_BIT_POSITION_BY_02_BITS)
+ & 0x03F) - 32);
+ /* Read the D3 and D4 value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB2);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[4], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a3*/
+ yas532_data.calib_yas532.a3 = (s32)((((v_data_u8[3] <<
+ BMI160_SHIFT_BIT_POSITION_BY_02_BITS) & 0x0C) |
+ ((v_data_u8[4]
+ >> BMI160_SHIFT_BIT_POSITION_BY_06_BITS)
+ & 0x03)) - 8);
+ /* calculate a4*/
+ yas532_data.calib_yas532.a4 = (s32)((v_data_u8[4]
+ & 0x3F) - 32);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* Read the D5 and D6 value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB3);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[5], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a5*/
+ yas532_data.calib_yas532.a5 =
+ (s32)(((v_data_u8[5]
+ >> BMI160_SHIFT_BIT_POSITION_BY_02_BITS)
+ & 0x3F) + 38);
+ /* Read the D6 and D7 value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB4);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[6], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a6*/
+ yas532_data.calib_yas532.a6 =
+ (s32)((((v_data_u8[5]
+ << BMI160_SHIFT_BIT_POSITION_BY_04_BITS)
+ & 0x30) | ((v_data_u8[6] >>
+ BMI160_SHIFT_BIT_POSITION_BY_04_BITS)
+ & 0x0F)) - 32);
+ /* Read the D7 and D8 value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB5);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[7], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a7*/
+ yas532_data.calib_yas532.a7 = (s32)((((v_data_u8[6]
+ << BMI160_SHIFT_BIT_POSITION_BY_03_BITS)
+ & 0x78) |
+ ((v_data_u8[7]
+ >> BMI160_SHIFT_BIT_POSITION_BY_05_BITS) &
+ 0x07)) - 64);
+ /* Read the D8 and D9 value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CLAIB6);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[8], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a8*/
+ yas532_data.calib_yas532.a8 = (s32)((((v_data_u8[7] <<
+ BMI160_GEN_READ_WRITE_DATA_LENGTH) & 0x3E) |
+ ((v_data_u8[8] >>
+ BMI160_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01)) -
+ 32);
+
+ /* Read the D8 and D9 value */
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB7);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[9], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a9*/
+ yas532_data.calib_yas532.a9 = (s32)(((v_data_u8[8] <<
+ BMI160_GEN_READ_WRITE_DATA_LENGTH) & 0xFE) |
+ ((v_data_u8[9] >>
+ BMI160_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01));
+ /* calculate k*/
+ yas532_data.calib_yas532.k = (s32)((v_data_u8[9] >>
+ BMI160_SHIFT_BIT_POSITION_BY_02_BITS) & 0x1F);
+ /* Read the value from register 0x9A*/
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB8);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[10],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* Read the value from register 0x9B*/
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIIB9);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[11],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* Read the value from register 0x9C*/
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB10);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[12],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* Read the value from register 0x9D*/
+ com_rslt += bmi160_set_mag_read_addr(BMI160_YAS532_CALIB11);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+ &v_data_u8[13],
+ BMI160_GEN_READ_WRITE_DATA_LENGTH);
+ /* Calculate the fxy1y2 and rxy1y1*/
+ yas532_data.calib_yas532.fxy1y2[0] =
+ (u8)(((v_data_u8[10]
+ & 0x01)
+ << BMI160_SHIFT_BIT_POSITION_BY_01_BIT)
+ | ((v_data_u8[11] >>
+ BMI160_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01));
+ yas532_data.calib_yas532.rxy1y2[0] =
+ ((s8)(((v_data_u8[10]
+ >> BMI160_SHIFT_BIT_POSITION_BY_01_BIT) & 0x3F)
+ << BMI160_SHIFT_BIT_POSITION_BY_02_BITS))
+ >> BMI160_SHIFT_BIT_POSITION_BY_02_BITS;
+ yas532_data.calib_yas532.fxy1y2[1] =
+ (u8)(((v_data_u8[11] & 0x01)
+ << BMI160_SHIFT_BIT_POSITION_BY_01_BIT)
+ | ((v_data_u8[12] >>
+ BMI160_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01));
+ yas532_data.calib_yas532.rxy1y2[1] =
+ ((s8)(((v_data_u8[11]
+ >> BMI160_SHIFT_BIT_POSITION_BY_01_BIT) & 0x3F)
+ << BMI160_SHIFT_BIT_POSITION_BY_02_BITS))
+ >> BMI160_SHIFT_BIT_POSITION_BY_02_BITS;
+ yas532_data.calib_yas532.fxy1y2[2] =
+ (u8)(((v_data_u8[12] & 0x01)
+ << BMI160_SHIFT_BIT_POSITION_BY_01_BIT)
+ | ((v_data_u8[13]
+ >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01));
+ yas532_data.calib_yas532.rxy1y2[2] =
+ ((s8)(((v_data_u8[12]
+ >> BMI160_SHIFT_BIT_POSITION_BY_01_BIT) & 0x3F)
+ << BMI160_SHIFT_BIT_POSITION_BY_02_BITS))
+ >> BMI160_SHIFT_BIT_POSITION_BY_02_BITS;
+
+ return com_rslt;
+}
+/*!
+ * @brief This function used for calculate the
+ * YAS532 read the linear data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_xy1y2_to_linear(
+u16 *v_xy1y2_u16, s32 *xy1y2_linear)
+{
+ /* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = SUCCESS;
+ static const u16 v_calib_data[] = {
+ 3721, 3971, 4221, 4471};
+ u8 i = BMI160_INIT_VALUE;
+
+ for (i = 0; i < 3; i++)
+ xy1y2_linear[i] = v_xy1y2_u16[i] -
+ v_calib_data[yas532_data.calib_yas532.fxy1y2[i]]
+ + (yas532_data.v_hard_offset_s8[i] -
+ yas532_data.calib_yas532.rxy1y2[i])
+ * yas532_data.coef[i];
+ return com_rslt;
+}
+/*!
+ * @brief This function used for read the YAS532 sensor data
+ * @param v_acquisition_command_u8: used to set the data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ * @param v_busy_u8 : used to get the busy flay for sensor data read
+ * @param v_temp_u16 : used to get the temperature data
+ * @param v_xy1y2_u16 : used to get the sensor xy1y2 data
+ * @param v_overflow_u8 : used to get the overflow data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_normal_measurement_data(
+u8 v_acquisition_command_u8, u8 *v_busy_u8,
+u16 *v_temp_u16, u16 *v_xy1y2_u16, u8 *v_overflow_u8)
+{
+ /* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = BMI160_INIT_VALUE;
+ /* Array holding the YAS532 xyy1 data*/
+ u8 v_data_u8[BMI160_YAS_XY1Y2T_DATA_SIZE] = {
+ BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ u8 i = BMI160_INIT_VALUE;
+ /* check the p_bmi160 structure as NULL*/
+ if (p_bmi160 == BMI160_NULL) {
+ return E_BMI160_NULL_PTR;
+ } else {
+ /* read the sensor data */
+ com_rslt = bmi160_bst_yas532_acquisition_command_register(
+ v_acquisition_command_u8);
+ com_rslt +=
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_MAG_X_LSB__REG,
+ v_data_u8, BMI160_MAG_YAS_DATA_LENGTH);
+ /* read the xyy1 data*/
+ *v_busy_u8 =
+ ((v_data_u8[0]
+ >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01);
+ *v_temp_u16 =
+ (u16)((((s32)v_data_u8[0]
+ << BMI160_SHIFT_BIT_POSITION_BY_03_BITS)
+ & 0x3F8) | ((v_data_u8[1]
+ >> BMI160_SHIFT_BIT_POSITION_BY_05_BITS) & 0x07));
+ v_xy1y2_u16[0] =
+ (u16)((((s32)v_data_u8[2]
+ << BMI160_SHIFT_BIT_POSITION_BY_06_BITS) & 0x1FC0)
+ | ((v_data_u8[3] >>
+ BMI160_SHIFT_BIT_POSITION_BY_02_BITS) & 0x3F));
+ v_xy1y2_u16[1] =
+ (u16)((((s32)v_data_u8[4]
+ << BMI160_SHIFT_BIT_POSITION_BY_06_BITS)
+ & 0x1FC0)
+ | ((v_data_u8[5]
+ >> BMI160_SHIFT_BIT_POSITION_BY_02_BITS) & 0x3F));
+ v_xy1y2_u16[2] =
+ (u16)((((s32)v_data_u8[6]
+ << BMI160_SHIFT_BIT_POSITION_BY_06_BITS)
+ & 0x1FC0)
+ | ((v_data_u8[7]
+ >> BMI160_SHIFT_BIT_POSITION_BY_02_BITS) & 0x3F));
+ *v_overflow_u8 = 0;
+ for (i = 0; i < 3; i++) {
+ if (v_xy1y2_u16[i] == YAS532_DATA_OVERFLOW)
+ *v_overflow_u8 |= (1 << (i * 2));
+ if (v_xy1y2_u16[i] == YAS532_DATA_UNDERFLOW)
+ *v_overflow_u8 |= (1 << (i * 2 + 1));
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This function used for YAS532 sensor data
+ * @param v_acquisition_command_u8 : the value of CMDR
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ * @param xyz_data : the vector xyz output
+ * @param v_overflow_s8 : the value of overflow
+ * @param v_temp_correction_u8 : the value of temperate correction enable
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_measurement_xyz_data(
+struct yas532_vector *xyz_data, u8 *v_overflow_s8, u8 v_temp_correction_u8,
+u8 v_acquisition_command_u8)
+{
+ /* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = BMI160_INIT_VALUE;
+ /* Array holding the linear calculation output*/
+ s32 v_xy1y2_linear_s32[BMI160_YAS_XY1Y2_DATA_SIZE] = {
+ BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* Array holding the temperature data */
+ s32 v_xyz_tmp_s32[BMI160_YAS_TEMP_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ s32 tmp = BMI160_INIT_VALUE;
+ s32 sx, sy1, sy2, sy, sz = BMI160_INIT_VALUE;
+ u8 i, v_busy_u8 = BMI160_INIT_VALUE;
+ u16 v_temp_u16 = BMI160_INIT_VALUE;
+ /* Array holding the xyy1 sensor raw data*/
+ u16 v_xy1y2_u16[BMI160_YAS_XY1Y2_DATA_SIZE] = {BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ #if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+ s32 sum = BMI160_INIT_VALUE;
+ #endif
+ *v_overflow_s8 = BMI160_INIT_VALUE;
+ switch (yas532_data.measure_state) {
+ case YAS532_MAG_STATE_INIT_COIL:
+ if (p_bmi160->mag_manual_enable != BMI160_MANUAL_ENABLE)
+ com_rslt = bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_ENABLE);
+ /* write Rcoil*/
+ com_rslt += bmi160_set_mag_write_data(
+ BMI160_YAS_DISABLE_RCOIL);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(BMI160_YAS532_RCOIL);
+ p_bmi160->delay_msec(BMI160_YAS532_MEASUREMENT_DELAY);
+ if (!yas532_data.overflow && is_valid_offset(
+ yas532_data.v_hard_offset_s8))
+ yas532_data.measure_state = 0;
+ break;
+ case YAS532_MAG_STATE_MEASURE_OFFSET:
+ com_rslt = bmi160_bst_yas532_magnetic_measure_set_offset();
+ yas532_data.measure_state = 0;
+ break;
+ default:
+ break;
+ }
+ /* Read sensor data*/
+ com_rslt += bmi160_bst_yas532_normal_measurement_data(
+ v_acquisition_command_u8, &v_busy_u8, &v_temp_u16,
+ v_xy1y2_u16, v_overflow_s8);
+ /* Calculate the linear data*/
+ com_rslt += bmi160_bst_yas532_xy1y2_to_linear(v_xy1y2_u16,
+ v_xy1y2_linear_s32);
+ /* Calculate temperature correction */
+ #if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+ yas532_data.temp_data.log[yas532_data.temp_data.idx++] =
+ v_temp_u16;
+ if (YAS532_MAG_TEMPERATURE_LOG <= yas532_data.temp_data.idx)
+ yas532_data.temp_data.idx = 0;
+ yas532_data.temp_data.num++;
+ if (YAS532_MAG_TEMPERATURE_LOG <= yas532_data.temp_data.num)
+ yas532_data.temp_data.num = YAS532_MAG_TEMPERATURE_LOG;
+ for (i = 0; i < yas532_data.temp_data.num; i++)
+ sum += yas532_data.temp_data.log[i];
+ tmp = sum * 10 / yas532_data.temp_data.num
+ - YAS532_TEMP20DEGREE_TYPICAL * 10;
+ #else
+ tmp = (v_temp_u16 - YAS532_TEMP20DEGREE_TYPICAL)
+ * 10;
+ #endif
+ sx = v_xy1y2_linear_s32[0];
+ sy1 = v_xy1y2_linear_s32[1];
+ sy2 = v_xy1y2_linear_s32[2];
+ /* Temperature correction */
+ if (v_temp_correction_u8) {
+ sx -= (yas532_data.calib_yas532.cx * tmp)
+ / 1000;
+ sy1 -= (yas532_data.calib_yas532.cy1 * tmp)
+ / 1000;
+ sy2 -= (yas532_data.calib_yas532.cy2 * tmp)
+ / 1000;
+ }
+ sy = sy1 - sy2;
+ sz = -sy1 - sy2;
+
+ xyz_data->yas532_vector_xyz[0] = yas532_data.calib_yas532.k *
+ ((100 * sx + yas532_data.calib_yas532.a2 * sy +
+ yas532_data.calib_yas532.a3 * sz) / 10);
+ xyz_data->yas532_vector_xyz[1] = yas532_data.calib_yas532.k *
+ ((yas532_data.calib_yas532.a4 * sx + yas532_data.calib_yas532.a5 * sy +
+ yas532_data.calib_yas532.a6 * sz) / 10);
+ xyz_data->yas532_vector_xyz[2] = yas532_data.calib_yas532.k *
+ ((yas532_data.calib_yas532.a7 * sx + yas532_data.calib_yas532.a8 * sy +
+ yas532_data.calib_yas532.a9 * sz) / 10);
+ if (yas532_data.transform != BMI160_NULL) {
+ for (i = 0; i < 3; i++) {
+ v_xyz_tmp_s32[i] = yas532_data.transform[i
+ * 3] *
+ xyz_data->yas532_vector_xyz[0]
+ + yas532_data.transform[i * 3 + 1] *
+ xyz_data->yas532_vector_xyz[1]
+ + yas532_data.transform[i * 3 + 2] *
+ xyz_data->yas532_vector_xyz[2];
+ }
+ set_vector(xyz_data->yas532_vector_xyz, v_xyz_tmp_s32);
+ }
+ for (i = 0; i < 3; i++) {
+ xyz_data->yas532_vector_xyz[i] -=
+ xyz_data->yas532_vector_xyz[i] % 10;
+ if (*v_overflow_s8 & (1
+ << (i * 2)))
+ xyz_data->yas532_vector_xyz[i] +=
+ 1; /* set overflow */
+ if (*v_overflow_s8 & (1 <<
+ (i * 2 + 1)))
+ xyz_data->yas532_vector_xyz[i] += 2; /* set underflow */
+ }
+
+
+if (v_busy_u8)
+ return com_rslt;
+ if (0 < *v_overflow_s8) {
+ if (!yas532_data.overflow)
+ yas532_data.overflow = 1;
+ yas532_data.measure_state = YAS532_MAG_STATE_INIT_COIL;
+ } else
+ yas532_data.overflow = 0;
+ for (i = 0; i < 3; i++)
+ yas532_data.last_raw[i] = v_xy1y2_u16[i];
+ yas532_data.last_raw[i] = v_temp_u16;
+ return com_rslt;
+}
+/*!
+ * @brief This function used for YAS532 write data acquisition
+ * command register write
+ * @param v_command_reg_data_u8 : the value of data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_acquisition_command_register(
+u8 v_command_reg_data_u8)
+{
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+
+ if (p_bmi160->mag_manual_enable != BMI160_MANUAL_ENABLE)
+ com_rslt = bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_ENABLE);
+
+ com_rslt = bmi160_set_mag_write_data(v_command_reg_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* YAMAHA YAS532-0x82*/
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_YAS532_COMMAND_REGISTER);
+ p_bmi160->delay_msec(BMI160_YAS_ACQ_COMMAND_DELAY);
+ com_rslt += bmi160_set_mag_read_addr(
+ BMI160_YAS532_DATA_REGISTER);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ if (p_bmi160->mag_manual_enable == BMI160_MANUAL_ENABLE)
+ com_rslt += bmi160_set_mag_manual_enable(BMI160_MANUAL_DISABLE);
+
+ return com_rslt;
+
+}
+/*!
+ * @brief This function used write offset of YAS532
+ *
+ * @param p_offset_s8 : The value of offset to write
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_set_offset(
+const s8 *p_offset_s8)
+{
+ /* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+
+ if (p_bmi160->mag_manual_enable != BMI160_MANUAL_ENABLE)
+ com_rslt = bmi160_set_mag_manual_enable(BMI160_MANUAL_ENABLE);
+ p_bmi160->delay_msec(BMI160_YAS532_OFFSET_DELAY);
+
+ /* Write offset X data*/
+ com_rslt = bmi160_set_mag_write_data(p_offset_s8[0]);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* YAS532 offset x write*/
+ com_rslt += bmi160_set_mag_write_addr(BMI160_YAS532_OFFSET_X);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ /* Write offset Y data*/
+ com_rslt = bmi160_set_mag_write_data(p_offset_s8[1]);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* YAS532 offset y write*/
+ com_rslt += bmi160_set_mag_write_addr(BMI160_YAS532_OFFSET_Y);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ /* Write offset Z data*/
+ com_rslt = bmi160_set_mag_write_data(p_offset_s8[2]);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* YAS532 offset z write*/
+ com_rslt += bmi160_set_mag_write_addr(BMI160_YAS532_OFFSET_Z);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ set_vector(yas532_data.v_hard_offset_s8, p_offset_s8);
+
+ if (p_bmi160->mag_manual_enable == BMI160_MANUAL_ENABLE)
+ com_rslt = bmi160_set_mag_manual_enable(BMI160_MANUAL_DISABLE);
+ return com_rslt;
+}
+/*!
+ * @brief This function used to init the YAMAH-YAS537
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas537_mag_interface_init(
+void)
+{
+/* This variable used for provide the communication
+results*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+u8 v_pull_value_u8 = BMI160_INIT_VALUE;
+u8 v_data_u8 = BMI160_INIT_VALUE;
+u8 i = BMI160_INIT_VALUE;
+/* accel operation mode to normal*/
+com_rslt = bmi160_set_command_register(ACCEL_MODE_NORMAL);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* write mag power mode as NORMAL*/
+com_rslt += bmi160_set_mag_interface_normal();
+/* register 0x7E write the 0x37, 0x9A and 0x30*/
+com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_ONE);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_TWO);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+com_rslt += bmi160_set_command_register(BMI160_COMMAND_REG_THREE);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/*switch the page1*/
+com_rslt += bmi160_set_target_page(BMI160_WRITE_TARGET_PAGE1);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+bmi160_get_target_page(&v_data_u8);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+com_rslt += bmi160_set_paging_enable(BMI160_WRITE_ENABLE_PAGE1);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+bmi160_get_paging_enable(&v_data_u8);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* enable the pullup configuration from
+the register 0x05 bit 4 and 5 as 10*/
+bmi160_get_pullup_configuration(&v_pull_value_u8);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+v_pull_value_u8 = v_pull_value_u8 | BMI160_PULL_UP_DATA;
+com_rslt += bmi160_set_pullup_configuration(v_pull_value_u8);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/*switch the page0*/
+com_rslt += bmi160_set_target_page(BMI160_WRITE_TARGET_PAGE0);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+bmi160_get_target_page(&v_data_u8);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* Write the YAS532 i2c address*/
+com_rslt += bmi160_set_i2c_device_addr(BMI160_YAS537_I2C_ADDRESS);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* enable the mag interface to manual mode*/
+com_rslt += bmi160_set_mag_manual_enable(BMI160_MANUAL_ENABLE);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+bmi160_get_mag_manual_enable(&v_data_u8);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/*Enable the MAG interface */
+com_rslt += bmi160_set_if_mode(BMI160_ENABLE_MAG_IF_MODE);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+bmi160_get_if_mode(&v_data_u8);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+v_data_u8 = BMI160_MANUAL_DISABLE;
+/* Read the YAS537 device id*/
+com_rslt += bmi160_set_mag_read_addr(BMI160_YAS_DEVICE_ID_REG);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&v_data_u8, BMI160_GEN_READ_WRITE_DATA_LENGTH);
+yas537_data.dev_id = v_data_u8;
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* Read the YAS532 calibration data*/
+com_rslt +=
+bmi160_bst_yamaha_yas537_calib_values(
+BMI160_GEN_READ_WRITE_DATA_LENGTH);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* set the mode to NORMAL*/
+yas537_data.measure_state = YAS537_MAG_STATE_NORMAL;
+/* set the transform to zero */
+yas537_data.transform = BMI160_NULL;
+yas537_data.average = 32;
+for (i = 0; i < 3; i++) {
+ yas537_data.hard_offset[i] = -128;
+ yas537_data.last_after_rcoil[i] = 0;
+}
+for (i = 0; i < 4; i++)
+ yas537_data.last_raw[i] = 0;
+/* write the mag bandwidth as 25Hz*/
+com_rslt += bmi160_set_mag_output_data_rate(
+BMI160_MAG_OUTPUT_DATA_RATE_25HZ);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* Enable mag interface to auto mode*/
+com_rslt += bmi160_set_mag_manual_enable(
+BMI160_MANUAL_DISABLE);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+bmi160_get_mag_manual_enable(&v_data_u8);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+return com_rslt;
+}
+/*!
+* @brief This function used for read the
+* YAMAHA YAS537 calibration data
+*
+*
+* @param v_rcoil_u8 : The value of r coil
+*
+*
+* @return results of bus communication function
+* @retval 0 -> Success
+* @retval -1 -> Error
+*
+*
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas537_calib_values(
+u8 v_rcoil_u8)
+{
+/* This variable used for provide the communication
+results*/
+BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+/* Array holding the YAS532 calibration values */
+u8 a_data_u8[BMI160_YAS537_CALIB_DATA_SIZE] = {
+BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+};
+static const u8 v_avrr_u8[] = {0x50, 0x60, 0x70};
+u8 v_cal_valid_u8 = BMI160_INIT_VALUE, i;
+/* write soft reset as 0x02*/
+com_rslt = bmi160_set_mag_write_data(
+YAS537_SRSTR_DATA);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+com_rslt += bmi160_set_mag_write_addr(YAS537_REG_SRSTR);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* Read the DX value */
+com_rslt = bmi160_set_mag_read_addr(YAS537_REG_CALR_C0);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[0], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the DY1 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_C1);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[1], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the DY2 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_C2);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[2], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D2 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_C3);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[3], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D3 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_C4);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[4], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D4 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_C5);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[5], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D5 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_C6);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[6], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D6 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_C7);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[7], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D7 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_C8);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[8], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D8 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_C9);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[9], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D9 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_CA);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[10], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the RX value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_CB);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[11], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the RY1 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_CC);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[12], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the RY2 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_CD);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[13], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the RY2 value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_CE);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[14], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the CHF value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_CF);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[15], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the VER value */
+com_rslt += bmi160_set_mag_read_addr(YAS537_REG_CALR_DO);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += bmi160_read_reg(BMI160_MAG_DATA_READ_REG,
+&a_data_u8[16], BMI160_GEN_READ_WRITE_DATA_LENGTH);
+/* get the calib ver*/
+yas537_data.calib_yas537.ver =
+(a_data_u8[16] >> BMI160_SHIFT_BIT_POSITION_BY_06_BITS);
+for (i = 0; i < 17; i++) {
+ if (((i < 16 && a_data_u8[i]) != 0))
+ v_cal_valid_u8 = 1;
+ if ((i < 16 &&
+ (a_data_u8[i] & 0x3F)) != 0)
+ v_cal_valid_u8 = 1;
+}
+if (!v_cal_valid_u8)
+ return ERROR;
+if (yas537_data.calib_yas537.ver == 0) {
+ for (i = 0; i < 17; i++) {
+ if (i < 12) {
+ /* write offset*/
+ com_rslt += bmi160_set_mag_write_data(
+ a_data_u8[i]);
+ p_bmi160->delay_msec(
+ BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ YAS537_REG_MTCR + i);
+ p_bmi160->delay_msec(
+ BMI160_GEN_READ_WRITE_DELAY);
+ } else if (i < 15) {
+ /* write offset correction*/
+ com_rslt += bmi160_set_mag_write_data(
+ a_data_u8[i]);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr((
+ (YAS537_REG_OXR + i) - 12));
+ p_bmi160->delay_msec(
+ BMI160_GEN_READ_WRITE_DELAY);
+ yas537_data.hard_offset[i - 12]
+ = a_data_u8[i];
+ } else {
+ /* write offset correction*/
+ com_rslt += bmi160_set_mag_write_data(
+ a_data_u8[i]);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr((
+ (YAS537_REG_OXR + i) - 11));
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ }
+
+}
+} else if (yas537_data.calib_yas537.ver == 1) {
+ for (i = 0; i < 3; i++) {
+ /* write offset*/
+ com_rslt += bmi160_set_mag_write_data(
+ a_data_u8[i]);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ YAS537_REG_MTCR + i);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ if (com_rslt == SUCCESS) {
+ /* write offset*/
+ com_rslt += bmi160_set_mag_write_data(
+ a_data_u8[i + 12]);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ YAS537_REG_OXR + i);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ yas537_data.hard_offset[i] =
+ a_data_u8[i + 12];
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+ /* write offset*/
+ com_rslt += bmi160_set_mag_write_data(
+ ((a_data_u8[i] & 0xE0) | 0x10));
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(
+ YAS537_REG_MTCR + i);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write offset*/
+ com_rslt += bmi160_set_mag_write_data(
+ ((a_data_u8[15]
+ >> BMI160_SHIFT_BIT_POSITION_BY_03_BITS)
+ & 0x1E));
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(YAS537_REG_HCKR);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write offset*/
+ com_rslt += bmi160_set_mag_write_data(
+ ((a_data_u8[15] << 1) & 0x1E));
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(YAS537_REG_LCKR);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write offset*/
+ com_rslt += bmi160_set_mag_write_data(
+ (a_data_u8[16] & 0x3F));
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(YAS537_REG_OCR);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+
+ /* Assign the calibration values*/
+ /* a2 */
+ yas537_data.calib_yas537.a2 =
+ ((((a_data_u8[3]
+ << BMI160_SHIFT_BIT_POSITION_BY_02_BITS)
+ & 0x7C)
+ | (a_data_u8[4]
+ >> BMI160_SHIFT_BIT_POSITION_BY_06_BITS)) - 64);
+ /* a3 */
+ yas537_data.calib_yas537.a3 =
+ ((((a_data_u8[4] << BMI160_SHIFT_BIT_POSITION_BY_01_BIT)
+ & 0x7E)
+ | (a_data_u8[5]
+ >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS)) - 64);
+ /* a4 */
+ yas537_data.calib_yas537.a4 =
+ ((((a_data_u8[5]
+ << BMI160_SHIFT_BIT_POSITION_BY_01_BIT)
+ & 0xFE)
+ | (a_data_u8[6]
+ >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS))
+ - 128);
+ /* a5 */
+ yas537_data.calib_yas537.a5 =
+ ((((a_data_u8[6]
+ << BMI160_SHIFT_BIT_POSITION_BY_02_BITS)
+ & 0x1FC)
+ | (a_data_u8[7]
+ >> BMI160_SHIFT_BIT_POSITION_BY_06_BITS))
+ - 112);
+ /* a6 */
+ yas537_data.calib_yas537.a6 =
+ ((((a_data_u8[7]
+ << BMI160_SHIFT_BIT_POSITION_BY_01_BIT)
+ & 0x7E)
+ | (a_data_u8[8]
+ >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS)) - 64);
+ /* a7 */
+ yas537_data.calib_yas537.a7 =
+ ((((a_data_u8[8]
+ << BMI160_SHIFT_BIT_POSITION_BY_01_BIT)
+ & 0xFE)
+ | (a_data_u8[9]
+ >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS))
+ - 128);
+ /* a8 */
+ yas537_data.calib_yas537.a8 = ((a_data_u8[9] &
+ 0x7F) - 64);
+ /* a9 */
+ yas537_data.calib_yas537.a9 = ((((a_data_u8[10]
+ << BMI160_SHIFT_BIT_POSITION_BY_01_BIT) & 0x1FE)
+ | (a_data_u8[11]
+ >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS))
+ - 112);
+ /* k */
+ yas537_data.calib_yas537.k = (
+ a_data_u8[11] & 0x7F);
+ } else {
+ return ERROR;
+ }
+/* write A/D converter*/
+com_rslt += bmi160_set_mag_write_data(
+YAS537_WRITE_A_D_CONVERTER);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+com_rslt += bmi160_set_mag_write_addr(YAS537_REG_ADCCALR);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* write A/D converter second register*/
+com_rslt += bmi160_set_mag_write_data(
+YAS537_WRITE_A_D_CONVERTER2);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+com_rslt += bmi160_set_mag_write_addr(YAS537_REG_ADCCALR_ONE);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* write temperature calibration register*/
+com_rslt += bmi160_set_mag_write_data(YAS537_WRITE_TEMP_CALIB);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+com_rslt += bmi160_set_mag_write_addr(YAS537_REG_TRMR);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* write average filter register*/
+com_rslt += bmi160_set_mag_write_data(
+v_avrr_u8[yas537_data.average]);
+p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+com_rslt += bmi160_set_mag_write_addr(YAS537_REG_AVRR);
+p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+if (v_rcoil_u8) {
+ /* write average; filter register*/
+ com_rslt += bmi160_set_mag_write_data(
+ YAS537_WRITE_FILTER);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(YAS537_REG_CONFR);
+ p_bmi160->delay_msec(
+ BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+}
+
+return com_rslt;
+
+}
+/*!
+ * @brief This function used for YAS537 write data acquisition
+ * command register write
+ * @param v_command_reg_data_u8 : the value of data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas537_acquisition_command_register(
+u8 v_command_reg_data_u8)
+{
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+
+ if (p_bmi160->mag_manual_enable != BMI160_MANUAL_ENABLE)
+ com_rslt = bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_ENABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ com_rslt = bmi160_set_mag_write_data(v_command_reg_data_u8);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ /* YAMAHA YAS532-0x82*/
+ com_rslt += bmi160_set_mag_write_addr(
+ BMI160_REG_YAS537_CMDR);
+ /* set the mode to RECORD*/
+ yas537_data.measure_state = YAS537_MAG_STATE_RECORD_DATA;
+ p_bmi160->delay_msec(BMI160_YAS_ACQ_COMMAND_DELAY);
+ com_rslt += bmi160_set_mag_read_addr(
+ YAS537_REG_TEMPERATURE_0);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ if (p_bmi160->mag_manual_enable == BMI160_MANUAL_ENABLE)
+ com_rslt += bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_DISABLE);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param xy1y2: The value of raw xy1y2 data
+ * @param xyz: The value of xyz data
+ *
+ *
+ * @return None
+ *
+ *
+ */
+static void xy1y2_to_xyz(u16 *xy1y2, s32 *xyz)
+{
+ xyz[0] = ((xy1y2[0] - 8192)
+ * 300);
+ xyz[1] = (((xy1y2[1] - xy1y2[2])
+ * 1732) / 10);
+ xyz[2] = (((-xy1y2[2] - xy1y2[2])
+ + 16384) * 300);
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_coil_stat_u8: The value of R coil status
+ * @param v_busy_u8: The value of busy status
+ * @param v_temperature_u16: The value of temperature
+ * @param xy1y2: The value of raw xy1y2 data
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas537_read_xy1y2_data(
+u8 *v_coil_stat_u8, u8 *v_busy_u8,
+u16 *v_temperature_u16, u16 *xy1y2, u8 *v_ouflow_u8)
+{
+ /* This variable used for provide the communication
+ results*/
+ BMI160_RETURN_FUNCTION_TYPE com_rslt = E_BMI160_COMM_RES;
+ /* Array holding the YAS532 calibration values */
+ u8 a_data_u8[BMI160_YAS_XY1Y2T_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE,
+ };
+ u8 i = BMI160_INIT_VALUE;
+ s32 a_h_s32[BMI160_YAS_H_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ s32 a_s_s32[BMI160_YAS_S_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ /* set command register*/
+ com_rslt = bmi160_bst_yas537_acquisition_command_register(
+ YAS537_SET_COMMAND_REGISTER);
+ /* read the yas537 sensor data of xy1y2*/
+ com_rslt +=
+ p_bmi160->BMI160_BUS_READ_FUNC(p_bmi160->dev_addr,
+ BMI160_USER_DATA_MAG_X_LSB__REG,
+ a_data_u8, BMI160_MAG_YAS_DATA_LENGTH);
+ /* read the busy flag*/
+ *v_busy_u8 = a_data_u8[2]
+ >> BMI160_SHIFT_BIT_POSITION_BY_07_BITS;
+ /* read the coil status*/
+ *v_coil_stat_u8 =
+ ((a_data_u8[2] >>
+ BMI160_SHIFT_BIT_POSITION_BY_06_BITS) & 0X01);
+ /* read temperature data*/
+ *v_temperature_u16 = (u16)((a_data_u8[0]
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | a_data_u8[1]);
+ /* read x data*/
+ xy1y2[0] = (u16)(((a_data_u8[2] &
+ 0x3F)
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8[3]));
+ /* read y1 data*/
+ xy1y2[1] = (u16)((a_data_u8[4]
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | a_data_u8[5]);
+ /* read y2 data*/
+ xy1y2[2] = (u16)((a_data_u8[6]
+ << BMI160_SHIFT_BIT_POSITION_BY_08_BITS)
+ | a_data_u8[7]);
+ for (i = 0; i < 3; i++)
+ yas537_data.last_raw[i] = xy1y2[i];
+ yas537_data.last_raw[i] = *v_temperature_u16;
+ if (yas537_data.calib_yas537.ver == 1) {
+ for (i = 0; i < 3; i++)
+ a_s_s32[i] = xy1y2[i] - 8192;
+ /* read hx*/
+ a_h_s32[0] = ((yas537_data.calib_yas537.k * (
+ (128 * a_s_s32[0]) +
+ (yas537_data.calib_yas537.a2 * a_s_s32[1]) +
+ (yas537_data.calib_yas537.a3 * a_s_s32[2])))
+ / (8192));
+ /* read hy1*/
+ a_h_s32[1] = ((yas537_data.calib_yas537.k * (
+ (yas537_data.calib_yas537.a4 * a_s_s32[0]) +
+ (yas537_data.calib_yas537.a5 * a_s_s32[1]) +
+ (yas537_data.calib_yas537.a6 * a_s_s32[2])))
+ / (8192));
+ /* read hy2*/
+ a_h_s32[2] = ((yas537_data.calib_yas537.k * (
+ (yas537_data.calib_yas537.a7 * a_s_s32[0]) +
+ (yas537_data.calib_yas537.a8 * a_s_s32[1]) +
+ (yas537_data.calib_yas537.a9 * a_s_s32[2])))
+ / (8192));
+
+ for (i = 0; i < 3; i++) {
+ if (a_h_s32[i] < -8192)
+ a_h_s32[i] = -8192;
+
+ if (8192 < a_h_s32[i])
+ a_h_s32[i] = 8192;
+
+ xy1y2[i] = a_h_s32[i] + 8192;
+
+ }
+ }
+ *v_ouflow_u8 = 0;
+ for (i = 0; i < 3; i++) {
+ if (YAS537_DATA_OVERFLOW <= xy1y2[i])
+ *v_ouflow_u8 |= (1 << (i * 2));
+ if (xy1y2[i] == YAS537_DATA_UNDERFLOW)
+ *v_ouflow_u8 |= (1 << (i * 2 + 1));
+ }
+
+ return com_rslt;
+
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+static BMI160_RETURN_FUNCTION_TYPE invalid_magnetic_field(
+u16 *v_cur_u16, u16 *v_last_u16)
+{
+ s16 invalid_thresh[] = {1500, 1500, 1500};
+ u8 i = BMI160_INIT_VALUE;
+
+ for (i = 0; i < 3; i++)
+ if (invalid_thresh[i] < ABS(v_cur_u16[i] - v_last_u16[i]))
+ return 1;
+ return 0;
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas537_measure_xyz_data(
+u8 *v_ouflow_u8, struct yas_vector *vector_xyz)
+{
+ s32 a_xyz_tmp_s32[BMI160_YAS_TEMP_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ u8 i = BMI160_INIT_VALUE;
+ s8 com_rslt = BMI160_INIT_VALUE;
+ u8 v_busy_u8 = BMI160_INIT_VALUE;
+ u8 v_rcoil_u8 = BMI160_INIT_VALUE;
+ u16 v_temperature_u16 = BMI160_INIT_VALUE;
+ u16 a_xy1y2_u16[BMI160_YAS_XY1Y2_DATA_SIZE] = {
+ BMI160_INIT_VALUE, BMI160_INIT_VALUE, BMI160_INIT_VALUE};
+ *v_ouflow_u8 = 0;
+ /* read the yas537 xy1y2 data*/
+ com_rslt = bmi160_bst_yamaha_yas537_read_xy1y2_data(
+ &v_rcoil_u8, &v_busy_u8,
+ &v_temperature_u16, a_xy1y2_u16, v_ouflow_u8);
+ /* linear calculation*/
+ xy1y2_to_xyz(a_xy1y2_u16, vector_xyz->yas537_vector_xyz);
+ if (yas537_data.transform != BMI160_NULL) {
+ for (i = 0; i < 3; i++) {
+ a_xyz_tmp_s32[i] = ((
+ yas537_data.transform[i + 3]
+ * vector_xyz->yas537_vector_xyz[0])
+ + (yas537_data.transform[
+ i * 3 + 1]
+ * vector_xyz->yas537_vector_xyz[1])
+ + (yas537_data.transform[
+ i * 3 + 2]
+ * vector_xyz->yas537_vector_xyz[2]));
+ }
+ yas537_set_vector(
+ vector_xyz->yas537_vector_xyz, a_xyz_tmp_s32);
+ }
+ for (i = 0; i < 3; i++) {
+ vector_xyz->yas537_vector_xyz[i] -=
+ vector_xyz->yas537_vector_xyz[i] % 10;
+ if (*v_ouflow_u8 & (1 <<
+ (i * 2)))
+ vector_xyz->yas537_vector_xyz[i] +=
+ 1; /* set overflow */
+ if (*v_ouflow_u8 & (1 << (i * 2 + 1)))
+ /* set underflow */
+ vector_xyz->yas537_vector_xyz[i] += 2;
+ }
+ if (v_busy_u8)
+ return ERROR;
+ switch (yas537_data.measure_state) {
+ case YAS537_MAG_STATE_INIT_COIL:
+ if (p_bmi160->mag_manual_enable != BMI160_MANUAL_ENABLE)
+ com_rslt = bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_ENABLE);
+ com_rslt += bmi160_set_mag_write_data(YAS537_WRITE_CONFR);
+ p_bmi160->delay_msec(BMI160_GEN_READ_WRITE_DELAY);
+ com_rslt += bmi160_set_mag_write_addr(YAS537_REG_CONFR);
+ p_bmi160->delay_msec(BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ yas537_data.measure_state = YAS537_MAG_STATE_RECORD_DATA;
+ if (p_bmi160->mag_manual_enable == BMI160_MANUAL_ENABLE)
+ com_rslt = bmi160_set_mag_manual_enable(
+ BMI160_MANUAL_DISABLE);
+ break;
+ case YAS537_MAG_STATE_RECORD_DATA:
+ if (v_rcoil_u8)
+ break;
+ yas537_set_vector(yas537_data.last_after_rcoil, a_xy1y2_u16);
+ yas537_data.measure_state = YAS537_MAG_STATE_NORMAL;
+ break;
+ case YAS537_MAG_STATE_NORMAL:
+ if (BMI160_INIT_VALUE < v_ouflow_u8
+ || invalid_magnetic_field(a_xy1y2_u16,
+ yas537_data.last_after_rcoil)) {
+ yas537_data.measure_state = YAS537_MAG_STATE_INIT_COIL;
+ for (i = 0; i < 3; i++) {
+ if (!*v_ouflow_u8)
+ vector_xyz->yas537_vector_xyz[i] += 3;
+ }
+ }
+ break;
+ }
+
+ return com_rslt;
+}
+/*!
+ * @brief This function used for reading
+ * bmi160_t structure
+ *
+ * @return the reference and values of bmi160_t
+ *
+ *
+*/
+struct bmi160_t *bmi160_get_ptr(void)
+{
+ return p_bmi160;
+}
diff --git a/drivers/input/sensors/bmi160/bmi160.h b/drivers/input/sensors/bmi160/bmi160.h
new file mode 100644
index 000000000000..bc94a354fcbb
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bmi160.h
@@ -0,0 +1,11814 @@
+/*
+****************************************************************************
+* Copyright (C) 2014 Bosch Sensortec GmbH
+*
+* bmi160.h
+* Date : 2015/04/02
+* @id 836294d
+* Revision : 2.0.9 $
+* @brief
+* The head file of BMI160API
+*
+****************************************************************************
+*
+* \section Disclaimer
+*
+* Common:
+* Bosch Sensortec products are developed for the consumer goods industry.
+* They may only be used within the parameters of the respective valid
+* product data sheet. Bosch Sensortec products are provided with the
+* express understanding that there is no warranty of fitness for a
+* particular purpose.They are not fit for use in life-sustaining,
+* safety or security sensitive systems or any system or device
+* that may lead to bodily harm or property damage if the system
+* or device malfunctions. In addition,Bosch Sensortec products are
+* not fit for use in products which interact with motor vehicle systems.
+* The resale and or use of products are at the purchasers own risk and
+* his own responsibility. The examination of fitness for the intended use
+* is the sole responsibility of the Purchaser.
+*
+* The purchaser shall indemnify Bosch Sensortec from all third party
+* claims, including any claims for incidental, or consequential damages,
+* arising from any product use not covered by the parameters of
+* the respective valid product data sheet or not approved by
+* Bosch Sensortec and reimburse Bosch Sensortec for all costs in
+* connection with such claims.
+*
+* The purchaser must monitor the market for the purchased products,
+* particularly with regard to product safety and inform Bosch Sensortec
+* without delay of all security relevant incidents.
+*
+* Engineering Samples are marked with an asterisk (*) or (e).
+* Samples may vary from the valid technical specifications of the product
+* series. They are therefore not intended or fit for resale to third
+* parties or for use in end products. Their sole purpose is internal
+* client testing. The testing of an engineering sample may in no way
+* replace the testing of a product series. Bosch Sensortec assumes
+* no liability for the use of engineering samples.
+* By accepting the engineering samples, the Purchaser agrees to indemnify
+* Bosch Sensortec from all claims arising from the use of engineering
+* samples.
+*
+* Special:
+* This software module (hereinafter called "Software") and any information
+* on application-sheets (hereinafter called "Information") is provided
+* free of charge for the sole purpose to support your application work.
+* The Software and Information is subject to the following
+* terms and conditions:
+*
+* The Software is specifically designed for the exclusive use for
+* Bosch Sensortec products by personnel who have special experience
+* and training. Do not use this Software if you do not have the
+* proper experience or training.
+*
+* This Software package is provided `` as is `` and without any expressed
+* or implied warranties,including without limitation, the implied warranties
+* of merchantability and fitness for a particular purpose.
+*
+* Bosch Sensortec and their representatives and agents deny any liability
+* for the functional impairment
+* of this Software in terms of fitness, performance and safety.
+* Bosch Sensortec and their representatives and agents shall not be liable
+* for any direct or indirect damages or injury, except as
+* otherwise stipulated in mandatory applicable law.
+*
+* The Information provided is believed to be accurate and reliable.
+* Bosch Sensortec assumes no responsibility for the consequences of use
+* of such Information nor for any infringement of patents or
+* other rights of third parties which may result from its use.
+* No license is granted by implication or otherwise under any patent or
+* patent rights of Bosch. Specifications mentioned in the Information are
+* subject to change without notice.
+**************************************************************************/
+/*! \file bmi160.h
+ \brief BMI160 Sensor Driver Support Header File */
+/* user defined code to be added here ... */
+#ifndef __BMI160_H__
+#define __BMI160_H__
+
+/*!
+* @brief The following definition uses for define the data types
+*
+* @note While porting the API please consider the following
+* @note Please check the version of C standard
+* @note Are you using Linux platform
+*/
+
+/*!
+* @brief For the Linux platform support
+* Please use the types.h for your data types definitions
+*/
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+#else /* ! __KERNEL__ */
+/**********************************************************
+* These definition uses for define the C
+* standard version data types
+***********************************************************/
+# if !defined(__STDC_VERSION__)
+
+/************************************************
+ * compiler is C11 C standard
+************************************************/
+#if (__STDC_VERSION__ == 201112L)
+
+/************************************************/
+#include <stdint.h>
+/************************************************/
+
+/*unsigned integer types*/
+#define u8 uint8_t
+#define u16 uint16_t
+#define u32 uint32_t
+#define u64 uint64_t
+
+/*signed integer types*/
+#define s8 int8_t
+#define s16 int16_t
+#define s32 int32_t
+#define s64 int64_t
+/************************************************
+ * compiler is C99 C standard
+************************************************/
+
+#elif (__STDC_VERSION__ == 199901L)
+
+/* stdint.h is a C99 supported c library.
+which is used to fixed the integer size*/
+/************************************************/
+#include <stdint.h>
+/************************************************/
+
+/*unsigned integer types*/
+#define u8 uint8_t
+#define u16 uint16_t
+#define u32 uint32_t
+#define u64 uint64_t
+
+/*signed integer types*/
+#define s8 int8_t
+#define s16 int16_t
+#define s32 int32_t
+#define s64 int64_t
+/************************************************
+ * compiler is C89 or other C standard
+************************************************/
+#else /* !defined(__STDC_VERSION__) */
+/* By default it is defined as 32 bit machine configuration*/
+/* define the definition based on your machine configuration*/
+/* define the data types based on your
+ machine/compiler/controller configuration*/
+#define MACHINE_32_BIT
+
+/* If your machine support 16 bit
+define the MACHINE_16_BIT*/
+#ifdef MACHINE_16_BIT
+#include <limits.h>
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed long int
+
+#if defined(LONG_MAX) && LONG_MAX == 0x7fffffffffffffffL
+#define s64 long int
+#define u64 unsigned long int
+#elif defined(LLONG_MAX) && (LLONG_MAX == 0x7fffffffffffffffLL)
+#define s64 long long int
+#define u64 unsigned long long int
+#else
+#warning Either the correct data type for signed 64 bit integer \
+could not be found, or 64 bit integers are not supported in your environment.
+#warning If 64 bit integers are supported on your platform, \
+please set s64 manually.
+#endif
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned long int
+
+/* If your machine support 32 bit
+define the MACHINE_32_BIT*/
+#elif defined MACHINE_32_BIT
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed int
+#define s64 signed long long int
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned int
+#define u64 unsigned long long int
+
+/* If your machine support 64 bit
+define the MACHINE_64_BIT*/
+#elif defined MACHINE_64_BIT
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed int
+#define s64 signed long int
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned int
+#define u64 unsigned long int
+
+#else
+#warning The data types defined above which not supported \
+define the data types manually
+#endif
+#endif
+
+/*** This else will execute for the compilers
+ * which are not supported the C standards
+ * Like C89/C99/C11***/
+#else
+/* By default it is defined as 32 bit machine configuration*/
+/* define the definition based on your machine configuration*/
+/* define the data types based on your
+ machine/compiler/controller configuration*/
+#define MACHINE_32_BIT
+
+/* If your machine support 16 bit
+define the MACHINE_16_BIT*/
+#ifdef MACHINE_16_BIT
+#include <limits.h>
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed long int
+
+#if defined(LONG_MAX) && LONG_MAX == 0x7fffffffffffffffL
+#define s64 long int
+#define u64 unsigned long int
+#elif defined(LLONG_MAX) && (LLONG_MAX == 0x7fffffffffffffffLL)
+#define s64 long long int
+#define u64 unsigned long long int
+#else
+#warning Either the correct data type for signed 64 bit integer \
+could not be found, or 64 bit integers are not supported in your environment.
+#warning If 64 bit integers are supported on your platform, \
+please set s64 manually.
+#endif
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned long int
+
+/* If your machine support 32 bit
+define the MACHINE_32_BIT*/
+#elif defined MACHINE_32_BIT
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed int
+#define s64 signed long long int
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned int
+#define u64 unsigned long long int
+
+/* If your machine support 64 bit
+define the MACHINE_64_BIT*/
+#elif defined MACHINE_64_BIT
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed int
+#define s64 signed long int
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned int
+#define u64 unsigned long int
+
+#else
+#warning The data types defined above which not supported \
+define the data types manually
+#endif
+#endif
+#endif
+/***************************************************************/
+/**\name BUS READ AND WRITE FUNCTION POINTERS */
+/***************************************************************/
+/*!
+ @brief Define the calling convention of YOUR bus communication routine.
+ @note This includes types of parameters. This example shows the
+ configuration for an SPI bus link.
+
+ If your communication function looks like this:
+
+ write_my_bus_xy(u8 device_addr, u8 register_addr,
+ u8 * data, u8 length);
+
+ The BMI160_WR_FUNC_PTR would equal:
+
+ BMI160_WR_FUNC_PTR s8 (* bus_write)(u8,
+ u8, u8 *, u8)
+
+ Parameters can be mixed as needed refer to the
+ @ref BMI160_BUS_WRITE_FUNC macro.
+
+
+*/
+#define BMI160_WR_FUNC_PTR s8 (*bus_write)(u8, u8,\
+u8 *, u8)
+/**< link macro between API function calls and bus write function
+ @note The bus write function can change since this is a
+ system dependant issue.
+
+ If the bus_write parameter calling order is like: reg_addr,
+ reg_data, wr_len it would be as it is here.
+
+ If the parameters are differently ordered or your communication
+ function like I2C need to know the device address,
+ you can change this macro accordingly.
+
+
+ BMI160_BUS_WRITE_FUNC(dev_addr, reg_addr, reg_data, wr_len)\
+ bus_write(dev_addr, reg_addr, reg_data, wr_len)
+
+ This macro lets all API functions call YOUR communication routine in a
+ way that equals your definition in the
+ @ref BMI160_WR_FUNC_PTR definition.
+
+*/
+#define BMI160_BUS_WRITE_FUNC(dev_addr, reg_addr, reg_data, wr_len)\
+ bus_write(dev_addr, reg_addr, reg_data, wr_len)
+
+/**< Define the calling convention of YOUR bus communication routine.
+ @note This includes types of parameters. This example shows the
+ configuration for an SPI bus link.
+
+ If your communication function looks like this:
+
+ read_my_bus_xy(u8 device_addr, u8 register_addr,
+ u8 * data, u8 length);
+
+ The BMI160_RD_FUNC_PTR would equal:
+
+ BMI160_RD_FUNC_PTR s8 (* bus_read)(u8,
+ u8, u8 *, u8)
+
+ Parameters can be mixed as needed refer to the
+ refer BMI160_BUS_READ_FUNC macro.
+
+*/
+#define BMI160_SPI_RD_MASK (0x80) /* for spi read transactions on SPI the
+ MSB has to be set */
+#define BMI160_RD_FUNC_PTR s8 (*bus_read)(u8,\
+ u8, u8 *, u8)
+
+#define BMI160_BRD_FUNC_PTR s8 \
+(*burst_read)(u8, u8, u8 *, u32)
+
+/**< link macro between API function calls and bus read function
+ @note The bus write function can change since this is a
+ system dependant issue.
+
+ If the bus_read parameter calling order is like: reg_addr,
+ reg_data, wr_len it would be as it is here.
+
+ If the parameters are differently ordered or your communication
+ function like I2C need to know the device address,
+ you can change this macro accordingly.
+
+
+ BMI160_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, wr_len)\
+ bus_read(dev_addr, reg_addr, reg_data, wr_len)
+
+ This macro lets all API functions call YOUR communication routine in a
+ way that equals your definition in the
+ refer BMI160_WR_FUNC_PTR definition.
+
+ @note: this macro also includes the "MSB='1'
+ for reading BMI160 addresses.
+
+*/
+#define BMI160_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, r_len)\
+ bus_read(dev_addr, reg_addr, reg_data, r_len)
+
+#define BMI160_BURST_READ_FUNC(device_addr, \
+register_addr, register_data, rd_len)\
+burst_read(device_addr, register_addr, register_data, rd_len)
+
+
+#define BMI160_MDELAY_DATA_TYPE u32
+
+/***************************************************************/
+/**\name BUS READ AND WRITE FUNCTION POINTERS */
+/***************************************************************/
+#define BMI160_I2C_ADDR1 0x68 /**< I2C Address needs to be changed */
+#define BMI160_I2C_ADDR2 0x69 /**< I2C Address needs to be changed */
+#define BMI160_AUX_BMM150_I2C_ADDRESS (0x10)
+#define BMI160_AUX_YAS532_I2C_ADDRESS (0x2E)
+/**< I2C address of YAS532*/
+#define BMI160_AKM09911_I2C_ADDRESS 0x0C/**< I2C address of AKM09911*/
+/**< I2C address of AKM09911*/
+#define BMI160_AUX_AKM09911_I2C_ADDR_2 (0x0D)
+/**< I2C address of AKM09911*/
+#define BMI160_AUX_AKM09912_I2C_ADDR_1 (0x0C)
+/**< I2C address of AKM09912*/
+#define BMI160_AUX_AKM09912_I2C_ADDR_2 (0x0D)
+/**< I2C address of AKM09912*/
+#define BMI160_AUX_AKM09912_I2C_ADDR_3 (0x0E)
+/**< I2C address of AKM09912*/
+#define BMI160_AKM09912_I2C_ADDRESS 0x0F/**< I2C address of akm09912*/
+
+#define BMI160_YAS532_I2C_ADDRESS 0x2E/**< I2C address of YAS532*/
+/*******************************************/
+/**\name CONSTANTS */
+/******************************************/
+#define BMI160_INIT_VALUE (0)
+#define BMI160_GEN_READ_WRITE_DATA_LENGTH (1)
+#define BMI160_MAXIMUM_TIMEOUT (10)
+/* output data rate condition check*/
+#define BMI160_OUTPUT_DATA_RATE0 (0)
+#define BMI160_OUTPUT_DATA_RATE1 (1)
+#define BMI160_OUTPUT_DATA_RATE2 (2)
+#define BMI160_OUTPUT_DATA_RATE3 (3)
+#define BMI160_OUTPUT_DATA_RATE4 (4)
+#define BMI160_OUTPUT_DATA_RATE5 (5)
+#define BMI160_OUTPUT_DATA_RATE6 (14)
+#define BMI160_OUTPUT_DATA_RATE7 (15)
+/* accel range check*/
+#define BMI160_ACCEL_RANGE0 (3)
+#define BMI160_ACCEL_RANGE1 (5)
+#define BMI160_ACCEL_RANGE3 (8)
+#define BMI160_ACCEL_RANGE4 (12)
+/* check the status of registers*/
+#define BMI160_FOC_STAT_HIGH (1)
+#define BMI160_SIG_MOTION_STAT_HIGH (1)
+#define BMI160_STEP_DET_STAT_HIGH (1)
+
+/*condition check for reading and writing data*/
+#define BMI160_MAX_VALUE_SIGNIFICANT_MOTION (1)
+#define BMI160_MAX_VALUE_FIFO_FILTER (1)
+#define BMI160_MAX_VALUE_FIFO_TIME (1)
+#define BMI160_MAX_VALUE_FIFO_INTR (1)
+#define BMI160_MAX_VALUE_FIFO_HEADER (1)
+#define BMI160_MAX_VALUE_FIFO_MAG (1)
+#define BMI160_MAX_VALUE_FIFO_ACCEL (1)
+#define BMI160_MAX_VALUE_FIFO_GYRO (1)
+#define BMI160_MAX_VALUE_SOURCE_INTR (1)
+#define BMI160_MAX_VALUE_LOW_G_MODE (1)
+#define BMI160_MAX_VALUE_NO_MOTION (1)
+#define BMI160_MAX_VALUE_TAP_SHOCK (1)
+#define BMI160_MAX_VALUE_TAP_QUIET (1)
+#define BMI160_MAX_VALUE_ORIENT_UD (1)
+#define BMI160_MAX_VALUE_ORIENT_AXES (1)
+#define BMI160_MAX_VALUE_NVM_PROG (1)
+#define BMI160_MAX_VALUE_SPI3 (1)
+#define BMI160_MAX_VALUE_PAGE (1)
+#define BMI160_MAX_VALUE_I2C_WDT (1)
+#define BMI160_MAX_VALUE_SLEEP_STATE (1)
+#define BMI160_MAX_VALUE_WAKEUP_INTR (1)
+#define BMI160_MAX_VALUE_SELFTEST_SIGN (1)
+#define BMI160_MAX_VALUE_SELFTEST_AMP (1)
+#define BMI160_MAX_VALUE_SELFTEST_START (1)
+#define BMI160_MAX_GYRO_WAKEUP_TRIGGER (3)
+#define BMI160_MAX_ACCEL_SELFTEST_AXIS (3)
+#define BMI160_MAX_GYRO_STEP_COUNTER (1)
+#define BMI160_MAX_GYRO_BW (3)
+#define BMI160_MAX_ACCEL_BW (7)
+#define BMI160_MAX_ORIENT_MODE (3)
+#define BMI160_MAX_ORIENT_BLOCKING (3)
+#define BMI160_MAX_FLAT_HOLD (3)
+#define BMI160_MAX_ACCEL_FOC (3)
+#define BMI160_MAX_IF_MODE (3)
+#define BMI160_MAX_TARGET_PAGE (3)
+#define BMI160_MAX_GYRO_RANGE (4)
+#define BMI160_MAX_GYRO_SLEEP_TIGGER (7)
+#define BMI160_MAX_TAP_TURN (7)
+#define BMI160_MAX_UNDER_SAMPLING (1)
+#define BMI160_MAX_UNDER_SIG_MOTION (3)
+#define BMI160_MAX_ACCEL_OUTPUT_DATA_RATE (12)
+#define BMI160_MAX_LATCH_INTR (15)
+#define BMI160_MAX_FLAT_HYST (15)
+#define BMI160_MAX_ORIENT_THETA (63)
+#define BMI160_MAX_FLAT_THETA (63)
+
+/* FIFO index definitions*/
+#define BMI160_FIFO_X_LSB_DATA (0)
+#define BMI160_FIFO_X_MSB_DATA (1)
+#define BMI160_FIFO_Y_LSB_DATA (2)
+#define BMI160_FIFO_Y_MSB_DATA (3)
+#define BMI160_FIFO_Z_LSB_DATA (4)
+#define BMI160_FIFO_Z_MSB_DATA (5)
+#define BMI160_FIFO_R_LSB_DATA (6)
+#define BMI160_FIFO_R_MSB_DATA (7)
+/* FIFO gyro definition*/
+#define BMI160_GA_FIFO_G_X_LSB (0)
+#define BMI160_GA_FIFO_G_X_MSB (1)
+#define BMI160_GA_FIFO_G_Y_LSB (2)
+#define BMI160_GA_FIFO_G_Y_MSB (3)
+#define BMI160_GA_FIFO_G_Z_LSB (4)
+#define BMI160_GA_FIFO_G_Z_MSB (5)
+#define BMI160_GA_FIFO_A_X_LSB (6)
+#define BMI160_GA_FIFO_A_X_MSB (7)
+#define BMI160_GA_FIFO_A_Y_LSB (8)
+#define BMI160_GA_FIFO_A_Y_MSB (9)
+#define BMI160_GA_FIFO_A_Z_LSB (10)
+#define BMI160_GA_FIFO_A_Z_MSB (11)
+/* FIFO mag/gyro/accel definition*/
+#define BMI160_MGA_FIFO_M_X_LSB (0)
+#define BMI160_MGA_FIFO_M_X_MSB (1)
+#define BMI160_MGA_FIFO_M_Y_LSB (2)
+#define BMI160_MGA_FIFO_M_Y_MSB (3)
+#define BMI160_MGA_FIFO_M_Z_LSB (4)
+#define BMI160_MGA_FIFO_M_Z_MSB (5)
+#define BMI160_MGA_FIFO_M_R_LSB (6)
+#define BMI160_MGA_FIFO_M_R_MSB (7)
+#define BMI160_MGA_FIFO_G_X_LSB (8)
+#define BMI160_MGA_FIFO_G_X_MSB (9)
+#define BMI160_MGA_FIFO_G_Y_LSB (10)
+#define BMI160_MGA_FIFO_G_Y_MSB (11)
+#define BMI160_MGA_FIFO_G_Z_LSB (12)
+#define BMI160_MGA_FIFO_G_Z_MSB (13)
+#define BMI160_MGA_FIFO_A_X_LSB (14)
+#define BMI160_MGA_FIFO_A_X_MSB (15)
+#define BMI160_MGA_FIFO_A_Y_LSB (16)
+#define BMI160_MGA_FIFO_A_Y_MSB (17)
+#define BMI160_MGA_FIFO_A_Z_LSB (18)
+#define BMI160_MGA_FIFO_A_Z_MSB (19)
+/* FIFO mag definition*/
+#define BMI160_MA_FIFO_M_X_LSB (0)
+#define BMI160_MA_FIFO_M_X_MSB (1)
+#define BMI160_MA_FIFO_M_Y_LSB (2)
+#define BMI160_MA_FIFO_M_Y_MSB (3)
+#define BMI160_MA_FIFO_M_Z_LSB (4)
+#define BMI160_MA_FIFO_M_Z_MSB (5)
+#define BMI160_MA_FIFO_M_R_LSB (6)
+#define BMI160_MA_FIFO_M_R_MSB (7)
+#define BMI160_MA_FIFO_A_X_LSB (8)
+#define BMI160_MA_FIFO_A_X_MSB (9)
+#define BMI160_MA_FIFO_A_Y_LSB (10)
+#define BMI160_MA_FIFO_A_Y_MSB (11)
+#define BMI160_MA_FIFO_A_Z_LSB (12)
+#define BMI160_MA_FIFO_A_Z_MSB (13)
+/* FIFO mag/gyro definition*/
+#define BMI160_MG_FIFO_M_X_LSB (0)
+#define BMI160_MG_FIFO_M_X_MSB (1)
+#define BMI160_MG_FIFO_M_Y_LSB (2)
+#define BMI160_MG_FIFO_M_Y_MSB (3)
+#define BMI160_MG_FIFO_M_Z_LSB (4)
+#define BMI160_MG_FIFO_M_Z_MSB (5)
+#define BMI160_MG_FIFO_M_R_LSB (6)
+#define BMI160_MG_FIFO_M_R_MSB (7)
+#define BMI160_MG_FIFO_G_X_LSB (8)
+#define BMI160_MG_FIFO_G_X_MSB (9)
+#define BMI160_MG_FIFO_G_Y_LSB (10)
+#define BMI160_MG_FIFO_G_Y_MSB (11)
+#define BMI160_MG_FIFO_G_Z_LSB (12)
+#define BMI160_MG_FIFO_G_Z_MSB (13)
+/* FIFO length definitions*/
+#define BMI160_FIFO_SENSOR_TIME_LSB (0)
+#define BMI160_FIFO_SENSOR_TIME_XLSB (1)
+#define BMI160_FIFO_SENSOR_TIME_MSB (2)
+#define BMI160_FIFO_SENSOR_TIME_LENGTH (3)
+#define BMI160_FIFO_A_LENGTH (6)
+#define BMI160_FIFO_G_LENGTH (6)
+#define BMI160_FIFO_M_LENGTH (8)
+#define BMI160_FIFO_AG_LENGTH (12)
+#define BMI160_FIFO_AMG_LENGTH (20)
+#define BMI160_FIFO_MA_OR_MG_LENGTH (14)
+
+/* bus read and write length for mag, accel and gyro*/
+#define BMI160_MAG_X_DATA_LENGTH (2)
+#define BMI160_MAG_Y_DATA_LENGTH (2)
+#define BMI160_MAG_Z_DATA_LENGTH (2)
+#define BMI160_MAG_R_DATA_LENGTH (2)
+#define BMI160_MAG_XYZ_DATA_LENGTH (6)
+#define BMI160_MAG_XYZR_DATA_LENGTH (8)
+#define BMI160_MAG_YAS_DATA_LENGTH (8)
+#define BMI160_GYRO_DATA_LENGTH (2)
+#define BMI160_GYRO_XYZ_DATA_LENGTH (6)
+#define BMI160_ACCEL_DATA_LENGTH (2)
+#define BMI160_ACCEL_XYZ_DATA_LENGTH (6)
+#define BMI160_TEMP_DATA_LENGTH (2)
+#define BMI160_FIFO_DATA_LENGTH (2)
+#define BMI160_STEP_COUNTER_LENGTH (2)
+#define BMI160_SENSOR_TIME_LENGTH (3)
+
+/* Delay definitions*/
+#define BMI160_SEC_INTERFACE_GEN_READ_WRITE_DELAY (5)
+#define BMI160_BMM150_WAKEUP_DELAY1 (2)
+#define BMI160_BMM150_WAKEUP_DELAY2 (3)
+#define BMI160_BMM150_WAKEUP_DELAY3 (1)
+#define BMI160_YAS532_OFFSET_DELAY (2)
+#define BMI160_GEN_READ_WRITE_DELAY (1)
+#define BMI160_YAS532_MEASUREMENT_DELAY (25)
+#define BMI160_YAS_ACQ_COMMAND_DELAY (50)
+#define BMI160_YAS532_SET_INITIAL_VALUE_DELAY (200)
+#define BMI160_AKM_INIT_DELAY (60)
+/****************************************************/
+/**\name ARRAY SIZE DEFINITIONS */
+/***************************************************/
+#define BMI160_ACCEL_X_DATA_SIZE (2)
+#define BMI160_ACCEL_Y_DATA_SIZE (2)
+#define BMI160_ACCEL_Z_DATA_SIZE (2)
+#define BMI160_ACCEL_XYZ_DATA_SIZE (6)
+
+#define BMI160_GYRO_X_DATA_SIZE (2)
+#define BMI160_GYRO_Y_DATA_SIZE (2)
+#define BMI160_GYRO_Z_DATA_SIZE (2)
+#define BMI160_GYRO_XYZ_DATA_SIZE (6)
+
+#define BMI160_MAG_X_DATA_SIZE (2)
+#define BMI160_MAG_Y_DATA_SIZE (2)
+#define BMI160_MAG_Z_DATA_SIZE (2)
+#define BMI160_MAG_R_DATA_SIZE (2)
+#define BMI160_MAG_XYZ_DATA_SIZE (6)
+#define BMI160_MAG_XYZR_DATA_SIZE (8)
+#define BMI160_MAG_TRIM_DATA_SIZE (16)
+
+
+#define BMI160_TEMP_DATA_SIZE (2)
+#define BMI160_FIFO_DATA_SIZE (2)
+#define BMI160_STEP_COUNT_DATA_SIZE (2)
+
+#define BMI160_SENSOR_TIME_DATA_SIZE (3)
+#define BMI160_AKM_SENSITIVITY_DATA_SIZE (3)
+#define BMI160_HARD_OFFSET_DATA_SIZE (3)
+#define BMI160_YAS_XY1Y2_DATA_SIZE (3)
+#define BMI160_YAS_FLAG_DATA_SIZE (3)
+#define BMI160_YAS_TEMP_DATA_SIZE (3)
+#define BMI160_YAS_H_DATA_SIZE (3)
+#define BMI160_YAS_S_DATA_SIZE (3)
+#define BMI160_YAS_CORRECT_DATA_SIZE (5)
+#define BMI160_YAS_XY1Y2T_DATA_SIZE (8)
+#define BMI160_YAS537_CALIB_DATA_SIZE (17)
+#define BMI160_YAS532_CALIB_DATA_SIZE (14)
+/****************************************************/
+/**\name ARRAY PARAMETER DEFINITIONS */
+/***************************************************/
+#define BMI160_SENSOR_TIME_MSB_BYTE (2)
+#define BMI160_SENSOR_TIME_XLSB_BYTE (1)
+#define BMI160_SENSOR_TIME_LSB_BYTE (0)
+
+#define BMI160_MAG_X_LSB_BYTE (0)
+#define BMI160_MAG_X_MSB_BYTE (1)
+#define BMI160_MAG_Y_LSB_BYTE (0)
+#define BMI160_MAG_Y_MSB_BYTE (1)
+#define BMI160_MAG_Z_LSB_BYTE (0)
+#define BMI160_MAG_Z_MSB_BYTE (1)
+#define BMI160_MAG_R_LSB_BYTE (0)
+#define BMI160_MAG_R_MSB_BYTE (1)
+#define BMI160_DATA_FRAME_MAG_X_LSB_BYTE (0)
+#define BMI160_DATA_FRAME_MAG_X_MSB_BYTE (1)
+#define BMI160_DATA_FRAME_MAG_Y_LSB_BYTE (2)
+#define BMI160_DATA_FRAME_MAG_Y_MSB_BYTE (3)
+#define BMI160_DATA_FRAME_MAG_Z_LSB_BYTE (4)
+#define BMI160_DATA_FRAME_MAG_Z_MSB_BYTE (5)
+#define BMI160_DATA_FRAME_MAG_R_LSB_BYTE (6)
+#define BMI160_DATA_FRAME_MAG_R_MSB_BYTE (7)
+
+#define BMI160_GYRO_X_LSB_BYTE (0)
+#define BMI160_GYRO_X_MSB_BYTE (1)
+#define BMI160_GYRO_Y_LSB_BYTE (0)
+#define BMI160_GYRO_Y_MSB_BYTE (1)
+#define BMI160_GYRO_Z_LSB_BYTE (0)
+#define BMI160_GYRO_Z_MSB_BYTE (1)
+#define BMI160_DATA_FRAME_GYRO_X_LSB_BYTE (0)
+#define BMI160_DATA_FRAME_GYRO_X_MSB_BYTE (1)
+#define BMI160_DATA_FRAME_GYRO_Y_LSB_BYTE (2)
+#define BMI160_DATA_FRAME_GYRO_Y_MSB_BYTE (3)
+#define BMI160_DATA_FRAME_GYRO_Z_LSB_BYTE (4)
+#define BMI160_DATA_FRAME_GYRO_Z_MSB_BYTE (5)
+
+#define BMI160_ACCEL_X_LSB_BYTE (0)
+#define BMI160_ACCEL_X_MSB_BYTE (1)
+#define BMI160_ACCEL_Y_LSB_BYTE (0)
+#define BMI160_ACCEL_Y_MSB_BYTE (1)
+#define BMI160_ACCEL_Z_LSB_BYTE (0)
+#define BMI160_ACCEL_Z_MSB_BYTE (1)
+#define BMI160_DATA_FRAME_ACCEL_X_LSB_BYTE (0)
+#define BMI160_DATA_FRAME_ACCEL_X_MSB_BYTE (1)
+#define BMI160_DATA_FRAME_ACCEL_Y_LSB_BYTE (2)
+#define BMI160_DATA_FRAME_ACCEL_Y_MSB_BYTE (3)
+#define BMI160_DATA_FRAME_ACCEL_Z_LSB_BYTE (4)
+#define BMI160_DATA_FRAME_ACCEL_Z_MSB_BYTE (5)
+
+#define BMI160_TEMP_LSB_BYTE (0)
+#define BMI160_TEMP_MSB_BYTE (1)
+
+#define BMI160_FIFO_LENGTH_LSB_BYTE (0)
+#define BMI160_FIFO_LENGTH_MSB_BYTE (1)
+
+#define BMI160_STEP_COUNT_LSB_BYTE (0)
+#define BMI160_STEP_COUNT_MSB_BYTE (1)
+/****************************************************/
+/**\name ERROR CODES */
+/***************************************************/
+
+#define E_BMI160_NULL_PTR ((s8)-127)
+#define E_BMI160_COMM_RES ((s8)-1)
+#define E_BMI160_OUT_OF_RANGE ((s8)-2)
+#define E_BMI160_BUSY ((s8)-3)
+#define SUCCESS ((u8)0)
+#define ERROR ((s8)-1)
+
+/* Constants */
+#define BMI160_NULL (0)
+#define BMI160_DELAY_SETTLING_TIME (5)
+/*This refers BMI160 return type as s8 */
+#define BMI160_RETURN_FUNCTION_TYPE s8
+/****************************************************/
+/**\name REGISTER DEFINITIONS */
+/***************************************************/
+/*******************/
+/**\name CHIP ID */
+/*******************/
+#define BMI160_USER_CHIP_ID_ADDR (0x00)
+/*******************/
+/**\name ERROR STATUS */
+/*******************/
+#define BMI160_USER_ERROR_ADDR (0X02)
+/*******************/
+/**\name POWER MODE STATUS */
+/*******************/
+#define BMI160_USER_PMU_STAT_ADDR (0X03)
+/*******************/
+/**\name MAG DATA REGISTERS */
+/*******************/
+#define BMI160_USER_DATA_0_ADDR (0X04)
+#define BMI160_USER_DATA_1_ADDR (0X05)
+#define BMI160_USER_DATA_2_ADDR (0X06)
+#define BMI160_USER_DATA_3_ADDR (0X07)
+#define BMI160_USER_DATA_4_ADDR (0X08)
+#define BMI160_USER_DATA_5_ADDR (0X09)
+#define BMI160_USER_DATA_6_ADDR (0X0A)
+#define BMI160_USER_DATA_7_ADDR (0X0B)
+/*******************/
+/**\name GYRO DATA REGISTERS */
+/*******************/
+#define BMI160_USER_DATA_8_ADDR (0X0C)
+#define BMI160_USER_DATA_9_ADDR (0X0D)
+#define BMI160_USER_DATA_10_ADDR (0X0E)
+#define BMI160_USER_DATA_11_ADDR (0X0F)
+#define BMI160_USER_DATA_12_ADDR (0X10)
+#define BMI160_USER_DATA_13_ADDR (0X11)
+#define BMI160_USER_DATA_14_ADDR (0X12)
+#define BMI160_USER_DATA_15_ADDR (0X13)
+/*******************/
+/**\name ACCEL DATA REGISTERS */
+/*******************/
+#define BMI160_USER_DATA_16_ADDR (0X14)
+#define BMI160_USER_DATA_17_ADDR (0X15)
+#define BMI160_USER_DATA_18_ADDR (0X16)
+#define BMI160_USER_DATA_19_ADDR (0X17)
+/*******************/
+/**\name SENSOR TIME REGISTERS */
+/*******************/
+#define BMI160_USER_SENSORTIME_0_ADDR (0X18)
+#define BMI160_USER_SENSORTIME_1_ADDR (0X19)
+#define BMI160_USER_SENSORTIME_2_ADDR (0X1A)
+/*******************/
+/**\name STATUS REGISTER FOR SENSOR STATUS FLAG */
+/*******************/
+#define BMI160_USER_STAT_ADDR (0X1B)
+/*******************/
+/**\name INTERRUPY STATUS REGISTERS */
+/*******************/
+#define BMI160_USER_INTR_STAT_0_ADDR (0X1C)
+#define BMI160_USER_INTR_STAT_1_ADDR (0X1D)
+#define BMI160_USER_INTR_STAT_2_ADDR (0X1E)
+#define BMI160_USER_INTR_STAT_3_ADDR (0X1F)
+/*******************/
+/**\name TEMPERATURE REGISTERS */
+/*******************/
+#define BMI160_USER_TEMPERATURE_0_ADDR (0X20)
+#define BMI160_USER_TEMPERATURE_1_ADDR (0X21)
+/*******************/
+/**\name FIFO REGISTERS */
+/*******************/
+#define BMI160_USER_FIFO_LENGTH_0_ADDR (0X22)
+#define BMI160_USER_FIFO_LENGTH_1_ADDR (0X23)
+#define BMI160_USER_FIFO_DATA_ADDR (0X24)
+/***************************************************/
+/**\name ACCEL CONFIG REGISTERS FOR ODR, BANDWIDTH AND UNDERSAMPLING*/
+/******************************************************/
+#define BMI160_USER_ACCEL_CONFIG_ADDR (0X40)
+/*******************/
+/**\name ACCEL RANGE */
+/*******************/
+#define BMI160_USER_ACCEL_RANGE_ADDR (0X41)
+/***************************************************/
+/**\name GYRO CONFIG REGISTERS FOR ODR AND BANDWIDTH */
+/******************************************************/
+#define BMI160_USER_GYRO_CONFIG_ADDR (0X42)
+/*******************/
+/**\name GYRO RANGE */
+/*******************/
+#define BMI160_USER_GYRO_RANGE_ADDR (0X43)
+/***************************************************/
+/**\name MAG CONFIG REGISTERS FOR ODR*/
+/******************************************************/
+#define BMI160_USER_MAG_CONFIG_ADDR (0X44)
+/***************************************************/
+/**\name REGISTER FOR GYRO AND ACCEL DOWNSAMPLING RATES FOR FIFO*/
+/******************************************************/
+#define BMI160_USER_FIFO_DOWN_ADDR (0X45)
+/***************************************************/
+/**\name FIFO CONFIG REGISTERS*/
+/******************************************************/
+#define BMI160_USER_FIFO_CONFIG_0_ADDR (0X46)
+#define BMI160_USER_FIFO_CONFIG_1_ADDR (0X47)
+/***************************************************/
+/**\name MAG INTERFACE REGISTERS*/
+/******************************************************/
+#define BMI160_USER_MAG_IF_0_ADDR (0X4B)
+#define BMI160_USER_MAG_IF_1_ADDR (0X4C)
+#define BMI160_USER_MAG_IF_2_ADDR (0X4D)
+#define BMI160_USER_MAG_IF_3_ADDR (0X4E)
+#define BMI160_USER_MAG_IF_4_ADDR (0X4F)
+/***************************************************/
+/**\name INTERRUPT ENABLE REGISTERS*/
+/******************************************************/
+#define BMI160_USER_INTR_ENABLE_0_ADDR (0X50)
+#define BMI160_USER_INTR_ENABLE_1_ADDR (0X51)
+#define BMI160_USER_INTR_ENABLE_2_ADDR (0X52)
+#define BMI160_USER_INTR_OUT_CTRL_ADDR (0X53)
+/***************************************************/
+/**\name LATCH DURATION REGISTERS*/
+/******************************************************/
+#define BMI160_USER_INTR_LATCH_ADDR (0X54)
+/***************************************************/
+/**\name MAP INTERRUPT 1 and 2 REGISTERS*/
+/******************************************************/
+#define BMI160_USER_INTR_MAP_0_ADDR (0X55)
+#define BMI160_USER_INTR_MAP_1_ADDR (0X56)
+#define BMI160_USER_INTR_MAP_2_ADDR (0X57)
+/***************************************************/
+/**\name DATA SOURCE REGISTERS*/
+/******************************************************/
+#define BMI160_USER_INTR_DATA_0_ADDR (0X58)
+#define BMI160_USER_INTR_DATA_1_ADDR (0X59)
+/***************************************************/
+/**\name
+INTERRUPT THRESHOLD, HYSTERESIS, DURATION, MODE CONFIGURATION REGISTERS*/
+/******************************************************/
+#define BMI160_USER_INTR_LOWHIGH_0_ADDR (0X5A)
+#define BMI160_USER_INTR_LOWHIGH_1_ADDR (0X5B)
+#define BMI160_USER_INTR_LOWHIGH_2_ADDR (0X5C)
+#define BMI160_USER_INTR_LOWHIGH_3_ADDR (0X5D)
+#define BMI160_USER_INTR_LOWHIGH_4_ADDR (0X5E)
+#define BMI160_USER_INTR_MOTION_0_ADDR (0X5F)
+#define BMI160_USER_INTR_MOTION_1_ADDR (0X60)
+#define BMI160_USER_INTR_MOTION_2_ADDR (0X61)
+#define BMI160_USER_INTR_MOTION_3_ADDR (0X62)
+#define BMI160_USER_INTR_TAP_0_ADDR (0X63)
+#define BMI160_USER_INTR_TAP_1_ADDR (0X64)
+#define BMI160_USER_INTR_ORIENT_0_ADDR (0X65)
+#define BMI160_USER_INTR_ORIENT_1_ADDR (0X66)
+#define BMI160_USER_INTR_FLAT_0_ADDR (0X67)
+#define BMI160_USER_INTR_FLAT_1_ADDR (0X68)
+/***************************************************/
+/**\name FAST OFFSET CONFIGURATION REGISTER*/
+/******************************************************/
+#define BMI160_USER_FOC_CONFIG_ADDR (0X69)
+/***************************************************/
+/**\name MISCELLANEOUS CONFIGURATION REGISTER*/
+/******************************************************/
+#define BMI160_USER_CONFIG_ADDR (0X6A)
+/***************************************************/
+/**\name SERIAL INTERFACE SETTINGS REGISTER*/
+/******************************************************/
+#define BMI160_USER_IF_CONFIG_ADDR (0X6B)
+/***************************************************/
+/**\name GYRO POWER MODE TRIGGER REGISTER */
+/******************************************************/
+#define BMI160_USER_PMU_TRIGGER_ADDR (0X6C)
+/***************************************************/
+/**\name SELF_TEST REGISTER*/
+/******************************************************/
+#define BMI160_USER_SELF_TEST_ADDR (0X6D)
+/***************************************************/
+/**\name SPI,I2C SELECTION REGISTER*/
+/******************************************************/
+#define BMI160_USER_NV_CONFIG_ADDR (0x70)
+/***************************************************/
+/**\name ACCEL AND GYRO OFFSET REGISTERS*/
+/******************************************************/
+#define BMI160_USER_OFFSET_0_ADDR (0X71)
+#define BMI160_USER_OFFSET_1_ADDR (0X72)
+#define BMI160_USER_OFFSET_2_ADDR (0X73)
+#define BMI160_USER_OFFSET_3_ADDR (0X74)
+#define BMI160_USER_OFFSET_4_ADDR (0X75)
+#define BMI160_USER_OFFSET_5_ADDR (0X76)
+#define BMI160_USER_OFFSET_6_ADDR (0X77)
+/***************************************************/
+/**\name STEP COUNTER INTERRUPT REGISTERS*/
+/******************************************************/
+#define BMI160_USER_STEP_COUNT_0_ADDR (0X78)
+#define BMI160_USER_STEP_COUNT_1_ADDR (0X79)
+/***************************************************/
+/**\name STEP COUNTER CONFIGURATION REGISTERS*/
+/******************************************************/
+#define BMI160_USER_STEP_CONFIG_0_ADDR (0X7A)
+#define BMI160_USER_STEP_CONFIG_1_ADDR (0X7B)
+/***************************************************/
+/**\name COMMAND REGISTER*/
+/******************************************************/
+#define BMI160_CMD_COMMANDS_ADDR (0X7E)
+/***************************************************/
+/**\name PAGE REGISTERS*/
+/******************************************************/
+#define BMI160_CMD_EXT_MODE_ADDR (0X7F)
+#define BMI160_COM_C_TRIM_FIVE_ADDR (0X05)
+
+/****************************************************/
+/**\name SHIFT VALUE DEFINITION */
+/***************************************************/
+#define BMI160_SHIFT_BIT_POSITION_BY_01_BIT (1)
+#define BMI160_SHIFT_BIT_POSITION_BY_02_BITS (2)
+#define BMI160_SHIFT_BIT_POSITION_BY_03_BITS (3)
+#define BMI160_SHIFT_BIT_POSITION_BY_04_BITS (4)
+#define BMI160_SHIFT_BIT_POSITION_BY_05_BITS (5)
+#define BMI160_SHIFT_BIT_POSITION_BY_06_BITS (6)
+#define BMI160_SHIFT_BIT_POSITION_BY_07_BITS (7)
+#define BMI160_SHIFT_BIT_POSITION_BY_08_BITS (8)
+#define BMI160_SHIFT_BIT_POSITION_BY_09_BITS (9)
+#define BMI160_SHIFT_BIT_POSITION_BY_12_BITS (12)
+#define BMI160_SHIFT_BIT_POSITION_BY_13_BITS (13)
+#define BMI160_SHIFT_BIT_POSITION_BY_14_BITS (14)
+#define BMI160_SHIFT_BIT_POSITION_BY_15_BITS (15)
+#define BMI160_SHIFT_BIT_POSITION_BY_16_BITS (16)
+
+/****************************************************/
+/**\name DEFINITIONS USED FOR YAMAHA-YAS532 */
+/***************************************************/
+#define YAS532_MAG_STATE_NORMAL (0)
+#define YAS532_MAG_STATE_INIT_COIL (1)
+#define YAS532_MAG_STATE_MEASURE_OFFSET (2)
+#define YAS532_MAG_INITCOIL_TIMEOUT (1000)
+#define YAS532_MAG_NOTRANS_POSITION (3)
+#define YAS532_DEFAULT_SENSOR_DELAY (50)
+#define YAS532_DATA_OVERFLOW (8190)
+#define YAS532_DATA_UNDERFLOW (0)
+#define YAS532_MAG_LOG (20)
+#define YAS532_MAG_TEMPERATURE_LOG (10)
+#define YAS532_TEMP20DEGREE_TYPICAL (390)
+#define YAS532_VERSION_AC_COEF_X (850)
+#define YAS532_VERSION_AC_COEF_Y1 (750)
+#define YAS532_VERSION_AC_COEF_Y2 (750)
+#define YAS532_DATA_CENTER (4096)
+/****************************************************/
+/**\name YAMAHA-YAS532 OFFSET DEFINITION */
+/***************************************************/
+static const s8 INVALID_OFFSET[] = {0x7f, 0x7f, 0x7f};
+#define set_vector(to, from) \
+ {int _l; for (_l = 0; _l < 3; _l++) (to)[_l] = (from)[_l]; }
+#define is_valid_offset(a) \
+ (((a)[0] <= 31) && ((a)[1] <= 31) && ((a)[2] <= 31) \
+ && (-31 <= (a)[0]) && (-31 <= (a)[1]) && (-31 <= (a)[2]))
+
+/**************************************************/
+/**\name YAS532 CALIB DATA DEFINITIONS */
+/*************************************************/
+
+
+/* register address of YAS532*/
+#define BMI160_YAS532_TESTR1 (0x88)
+#define BMI160_YAS532_TESTR2 (0x89)
+#define BMI160_YAS532_RCOIL (0x81)
+#define BMI160_YAS532_COMMAND_REGISTER (0x82)
+#define BMI160_YAS532_DATA_REGISTER (0xB0)
+/* calib data register definition*/
+#define BMI160_YAS532_CALIB_CX (0x90)
+#define BMI160_YAS532_CALIB_CY1 (0x91)
+#define BMI160_YAS532_CALIB_CY2 (0x92)
+#define BMI160_YAS532_CALIB1 (0x93)
+#define BMI160_YAS532_CALIB2 (0x94)
+#define BMI160_YAS532_CALIB3 (0x95)
+#define BMI160_YAS532_CALIB4 (0x96)
+#define BMI160_YAS532_CALIB5 (0x97)
+#define BMI160_YAS532_CLAIB6 (0x98)
+#define BMI160_YAS532_CALIB7 (0x99)
+#define BMI160_YAS532_CALIB8 (0x9A)
+#define BMI160_YAS532_CALIIB9 (0x9B)
+#define BMI160_YAS532_CALIB10 (0x9C)
+#define BMI160_YAS532_CALIB11 (0x9D)
+/* offset definition */
+#define BMI160_YAS532_OFFSET_X (0x85)
+#define BMI160_YAS532_OFFSET_Y (0x86)
+#define BMI160_YAS532_OFFSET_Z (0x87)
+/* data to write register for yas532*/
+#define BMI160_YAS532_WRITE_TESTR1 (0x00)
+#define BMI160_YAS532_WRITE_TESTR2 (0x00)
+#define BMI160_YAS532_WRITE_RCOIL (0x00)
+/**************************************************/
+/**\name YAS537 DEFINITION */
+/*************************************************/
+
+#define YAS537_SRSTR_DATA (0x02)
+#define YAS537_WRITE_A_D_CONVERTER (0x03)
+#define YAS537_WRITE_A_D_CONVERTER2 (0xF8)
+#define YAS537_WRITE_FILTER (0x08)
+#define YAS537_WRITE_CONFR (0x08)
+#define YAS537_WRITE_TEMP_CALIB (0xFF)
+#define YAS537_SET_COMMAND_REGISTER (0x01)
+
+/**************************************************/
+/**\name YAS537 REGISTER DEFINITION */
+/*************************************************/
+#define YAS537_REG_SRSTR (0x90)
+#define YAS537_REG_CALR_C0 (0xC0)
+#define YAS537_REG_CALR_C1 (0xC1)
+#define YAS537_REG_CALR_C2 (0xC2)
+#define YAS537_REG_CALR_C3 (0xC3)
+#define YAS537_REG_CALR_C4 (0xC4)
+#define YAS537_REG_CALR_C5 (0xC5)
+#define YAS537_REG_CALR_C6 (0xC6)
+#define YAS537_REG_CALR_C7 (0xC7)
+#define YAS537_REG_CALR_C8 (0xC8)
+#define YAS537_REG_CALR_C9 (0xC9)
+#define YAS537_REG_CALR_CA (0xCA)
+#define YAS537_REG_CALR_CB (0xCB)
+#define YAS537_REG_CALR_CC (0xCC)
+#define YAS537_REG_CALR_CD (0xCD)
+#define YAS537_REG_CALR_CE (0xCE)
+#define YAS537_REG_CALR_CF (0xCF)
+#define YAS537_REG_CALR_DO (0xD0)
+#define YAS537_REG_MTCR (0x93)
+#define YAS537_REG_CONFR (0x82)
+#define BMI160_REG_YAS537_CMDR (0x81)
+#define YAS537_REG_OXR (0x84)
+#define YAS537_REG_AVRR (0x87)
+#define YAS537_REG_HCKR (0x88)
+#define YAS537_REG_LCKR (0x89)
+#define YAS537_REG_ADCCALR (0x91)
+#define YAS537_REG_ADCCALR_ONE (0x92)
+#define YAS537_REG_OCR (0x9E)
+#define YAS537_REG_TRMR (0x9F)
+#define YAS537_REG_TEMPERATURE_0 (0xB0)
+#define YAS537_REG_TEMPERATURE_1 (0xB1)
+#define YAS537_REG_DATA_X_0 (0xB2)
+#define YAS537_REG_DATA_X_1 (0xB3)
+#define YAS537_REG_DATA_Y1_0 (0xB4)
+#define YAS537_REG_DATA_Y1_1 (0xB5)
+#define YAS537_REG_DATA_Y2_0 (0xB6)
+#define YAS537_REG_DATA_Y2_1 (0xB7)
+#define YAS537_MAG_STATE_NORMAL (0)
+#define YAS537_MAG_STATE_INIT_COIL (1)
+#define YAS537_MAG_STATE_RECORD_DATA (2)
+#define YAS537_DATA_UNDERFLOW (0)
+#define YAS537_DATA_OVERFLOW (16383)
+/****************************************************/
+/**\name YAS537_set vector */
+/***************************************************/
+#define yas537_set_vector(to, from) \
+ {int _l; for (_l = 0; _l < 3; _l++) (to)[_l] = (from)[_l]; }
+
+#ifndef ABS
+#define ABS(a) ((a) > 0 ? (a) : -(a)) /*!< Absolute value */
+#endif
+/****************************************************/
+/**\name AKM09911 AND AKM09912 DEFINITION */
+/***************************************************/
+#define AKM09912_SENSITIVITY_DIV (256)
+#define AKM09912_SENSITIVITY (128)
+#define AKM09911_SENSITIVITY_DIV (128)
+#define AKM_ASAX (0)
+#define AKM_ASAY (1)
+#define AKM_ASAZ (2)
+#define AKM_POWER_DOWN_MODE_DATA (0x00)
+#define AKM_FUSE_ROM_MODE (0x1F)
+#define AKM_POWER_MODE_REG (0x31)
+#define AKM_SINGLE_MEASUREMENT_MODE (0x01)
+#define AKM_DATA_REGISTER (0x11)
+/*! AKM09912 Register definition */
+#define AKM09912_CHIP_ID_REG (0x01)
+/****************************************************/
+/**\name BMM150 DEFINITION */
+/***************************************************/
+#define BMI160_BMM150_SET_POWER_CONTROL (0x01)
+#define BMI160_BMM150_MAX_RETRY_WAKEUP (5)
+#define BMI160_BMM150_POWER_ON (0x01)
+#define BMI160_BMM150_POWER_OFF (0x00)
+#define BMI160_BMM150_FORCE_MODE (0x02)
+#define BMI160_BMM150_POWER_ON_SUCCESS (0)
+#define BMI160_BMM150_POWER_ON_FAIL ((s8)-1)
+
+#define BMI160_BMM150_DIG_X1 (0)
+#define BMI160_BMM150_DIG_Y1 (1)
+#define BMI160_BMM150_DIG_X2 (2)
+#define BMI160_BMM150_DIG_Y3 (3)
+#define BMI160_BMM150_DIG_XY1 (4)
+#define BMI160_BMM150_DIG_XY2 (5)
+#define BMI160_BMM150_DIG_Z1_LSB (6)
+#define BMI160_BMM150_DIG_Z1_MSB (7)
+#define BMI160_BMM150_DIG_Z2_LSB (8)
+#define BMI160_BMM150_DIG_Z2_MSB (9)
+#define BMI160_BMM150_DIG_DIG_Z3_LSB (10)
+#define BMI160_BMM150_DIG_DIG_Z3_MSB (11)
+#define BMI160_BMM150_DIG_DIG_Z4_LSB (12)
+#define BMI160_BMM150_DIG_DIG_Z4_MSB (13)
+#define BMI160_BMM150_DIG_DIG_XYZ1_LSB (14)
+#define BMI160_BMM150_DIG_DIG_XYZ1_MSB (15)
+
+/**************************************************************/
+/**\name STRUCTURE DEFINITIONS */
+/**************************************************************/
+/*!
+* @brief bmi160 structure
+* This structure holds all relevant information about bmi160
+*/
+struct bmi160_t {
+u8 chip_id;/**< chip id of BMI160 */
+u8 dev_addr;/**< device address of BMI160 */
+s8 mag_manual_enable;/**< used for check the mag manual/auto mode status */
+BMI160_WR_FUNC_PTR;/**< bus write function pointer */
+BMI160_RD_FUNC_PTR;/**< bus read function pointer */
+BMI160_BRD_FUNC_PTR;/**< burst write function pointer */
+void (*delay_msec)(BMI160_MDELAY_DATA_TYPE);/**< delay function pointer */
+};
+/*!
+ * @brief Structure containing bmm150 and akm09911
+ * magnetometer values for x,y and
+ * z-axis in s16
+ */
+struct bmi160_mag_t {
+s16 x;/**< BMM150 and AKM09911 and AKM09912 X raw data*/
+s16 y;/**< BMM150 and AKM09911 and AKM09912 Y raw data*/
+s16 z;/**< BMM150 and AKM09911 and AKM09912 Z raw data*/
+};
+/*!
+ * @brief Structure containing bmm150 xyz data and temperature
+ */
+struct bmi160_mag_xyzr_t {
+s16 x;/**< BMM150 X raw data*/
+s16 y;/**< BMM150 Y raw data*/
+s16 z;/**<BMM150 Z raw data*/
+u16 r;/**<BMM150 R raw data*/
+};
+/*!
+ * @brief Structure containing gyro xyz data
+ */
+struct bmi160_gyro_t {
+s16 x;/**<gyro X data*/
+s16 y;/**<gyro Y data*/
+s16 z;/**<gyro Z data*/
+};
+/*!
+ * @brief Structure containing accel xyz data
+ */
+struct bmi160_accel_t {
+s16 x;/**<accel X data*/
+s16 y;/**<accel Y data*/
+s16 z;/**<accel Z data*/
+};
+/*!
+ * @brief Structure bmm150 mag compensated data with s32 output
+ */
+struct bmi160_mag_xyz_s32_t {
+s16 x;/**<BMM150 X compensated data*/
+s16 y;/**<BMM150 Y compensated data*/
+s16 z;/**<BMM150 Z compensated data*/
+};
+/*!
+ * @brief Structure bmm150 mag trim data
+ */
+struct trim_data_t {
+s8 dig_x1;/**<BMM150 trim x1 data*/
+s8 dig_y1;/**<BMM150 trim y1 data*/
+
+s8 dig_x2;/**<BMM150 trim x2 data*/
+s8 dig_y2;/**<BMM150 trim y2 data*/
+
+u16 dig_z1;/**<BMM150 trim z1 data*/
+s16 dig_z2;/**<BMM150 trim z2 data*/
+s16 dig_z3;/**<BMM150 trim z3 data*/
+s16 dig_z4;/**<BMM150 trim z4 data*/
+
+u8 dig_xy1;/**<BMM150 trim xy1 data*/
+s8 dig_xy2;/**<BMM150 trim xy2 data*/
+
+u16 dig_xyz1;/**<BMM150 trim xyz1 data*/
+};
+
+/*!
+* @brief Structure for reading AKM compensating data
+*/
+struct bst_akm_sensitivity_data_t {
+u8 asax;/**<AKM09911 and AKM09912 X sensitivity data*/
+u8 asay;/**<AKM09911 and AKM09912 Y sensitivity data*/
+u8 asaz;/**<AKM09911 and AKM09912 Z sensitivity data*/
+};
+/*!
+* @brief YAMAHA-YAS532 struct
+* Calibration YAS532 data struct
+*/
+struct bst_yas532_calib_data_t {
+s32 cx;/**<YAS532 calib cx data */
+s32 cy1;/**<YAS532 calib cy1 data */
+s32 cy2;/**<YAS532 calib cy2 data */
+s32 a2;/**<YAS532 calib a2 data */
+s32 a3;/**<YAS532 calib a3 data */
+s32 a4;/**<YAS532 calib a4 data */
+s32 a5;/**<YAS532 calib a5 data */
+s32 a6;/**<YAS532 calib a6 data */
+s32 a7;/**<YAS532 calib a7 data */
+s32 a8;/**<YAS532 calib a8 data */
+s32 a9;/**<YAS532 calib a9 data */
+s32 k;/**<YAS532 calib k data */
+s8 rxy1y2[3];/**<YAS532 calib rxy1y2 data */
+u8 fxy1y2[3];/**<YAS532 calib fxy1y2 data */
+};
+/*!
+* @brief YAS532 Temperature structure
+*/
+#if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+struct yas_temp_filter_t {
+u16 log[YAS532_MAG_TEMPERATURE_LOG];/**<YAS532 temp log array */
+u8 num;/**< used for increment the index */
+u8 idx;/**< used for increment the index */
+};
+#endif
+/*!
+* @brief YAS532 sensor initialization
+*/
+struct yas532_t {
+struct bst_yas532_calib_data_t calib_yas532;/**< calib data */
+s8 measure_state;/**< update measure state */
+s8 v_hard_offset_s8[3];/**< offset write array*/
+s32 coef[3];/**< co efficient data */
+s8 overflow;/**< over flow condition check */
+u8 dev_id;/**< device id information */
+const s8 *transform;/**< transform condition check */
+#if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+struct yas_temp_filter_t temp_data;/**< temp data */
+#endif
+u16 last_raw[4];/**< raw data */
+};
+/*!
+* @brief Used for reading the YAS532 XYZ data
+*/
+struct yas532_vector {
+s32 yas532_vector_xyz[3];/**< YAS532 compensated xyz data*/
+};
+/**
+ * @struct yas_vector
+ * @brief Stores the sensor data
+ */
+struct yas_vector {
+ s32 yas537_vector_xyz[3]; /*!< vector data */
+};
+/*!
+* @brief YAMAHA-YAS532 struct
+* Calibration YAS532 data struct
+*/
+struct bst_yas537_calib_data_t {
+s8 a2;/**<YAS532 calib a2 data */
+s8 a3;/**<YAS532 calib a3 data */
+s8 a4;/**<YAS532 calib a4 data */
+s16 a5;/**<YAS532 calib a5 data */
+s8 a6;/**<YAS532 calib a6 data */
+s8 a7;/**<YAS532 calib a7 data */
+s8 a8;/**<YAS532 calib a8 data */
+s16 a9;/**<YAS532 calib a9 data */
+u8 k;/**<YAS532 calib k data */
+u8 ver;/**<YAS532 calib ver data*/
+};
+/*!
+* @brief YAS537 sensor initialization
+*/
+struct yas537_t {
+struct bst_yas537_calib_data_t calib_yas537;/**< calib data */
+s8 measure_state;/**< update measure state */
+s8 hard_offset[3];/**< offset write array*/
+u16 last_after_rcoil[3];/**< rcoil write array*/
+s32 coef[3];/**< co efficient data */
+s8 overflow;/**< over flow condition check */
+u8 dev_id;/**< device id information */
+u8 average;/**<average selection for offset configuration*/
+const s8 *transform;/**< transform condition check */
+u16 last_raw[4];/**< raw data */
+struct yas_vector xyz; /*!< X, Y, Z measurement data of the sensor */
+};
+/**************************************************************/
+/**\name USER DATA REGISTERS DEFINITION START */
+/**************************************************************/
+
+/**************************************************************/
+/**\name CHIP ID LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Chip ID Description - Reg Addr --> (0x00), Bit --> 0...7 */
+#define BMI160_USER_CHIP_ID__POS (0)
+#define BMI160_USER_CHIP_ID__MSK (0xFF)
+#define BMI160_USER_CHIP_ID__LEN (8)
+#define BMI160_USER_CHIP_ID__REG (BMI160_USER_CHIP_ID_ADDR)
+/**************************************************************/
+/**\name ERROR STATUS LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Error Description - Reg Addr --> (0x02), Bit --> 0 */
+#define BMI160_USER_ERR_STAT__POS (0)
+#define BMI160_USER_ERR_STAT__LEN (8)
+#define BMI160_USER_ERR_STAT__MSK (0xFF)
+#define BMI160_USER_ERR_STAT__REG (BMI160_USER_ERROR_ADDR)
+
+#define BMI160_USER_FATAL_ERR__POS (0)
+#define BMI160_USER_FATAL_ERR__LEN (1)
+#define BMI160_USER_FATAL_ERR__MSK (0x01)
+#define BMI160_USER_FATAL_ERR__REG (BMI160_USER_ERROR_ADDR)
+
+/* Error Description - Reg Addr --> (0x02), Bit --> 1...4 */
+#define BMI160_USER_ERR_CODE__POS (1)
+#define BMI160_USER_ERR_CODE__LEN (4)
+#define BMI160_USER_ERR_CODE__MSK (0x1E)
+#define BMI160_USER_ERR_CODE__REG (BMI160_USER_ERROR_ADDR)
+
+/* Error Description - Reg Addr --> (0x02), Bit --> 5 */
+#define BMI160_USER_I2C_FAIL_ERR__POS (5)
+#define BMI160_USER_I2C_FAIL_ERR__LEN (1)
+#define BMI160_USER_I2C_FAIL_ERR__MSK (0x20)
+#define BMI160_USER_I2C_FAIL_ERR__REG (BMI160_USER_ERROR_ADDR)
+
+/* Error Description - Reg Addr --> (0x02), Bit --> 6 */
+#define BMI160_USER_DROP_CMD_ERR__POS (6)
+#define BMI160_USER_DROP_CMD_ERR__LEN (1)
+#define BMI160_USER_DROP_CMD_ERR__MSK (0x40)
+#define BMI160_USER_DROP_CMD_ERR__REG (BMI160_USER_ERROR_ADDR)
+/**************************************************************/
+/**\name MAG DATA READY LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Error Description - Reg Addr --> (0x02), Bit --> 7 */
+#define BMI160_USER_MAG_DADA_RDY_ERR__POS (7)
+#define BMI160_USER_MAG_DADA_RDY_ERR__LEN (1)
+#define BMI160_USER_MAG_DADA_RDY_ERR__MSK (0x80)
+#define BMI160_USER_MAG_DADA_RDY_ERR__REG (BMI160_USER_ERROR_ADDR)
+/**************************************************************/
+/**\name MAG POWER MODE LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* PMU_Status Description of MAG - Reg Addr --> (0x03), Bit --> 1..0 */
+#define BMI160_USER_MAG_POWER_MODE_STAT__POS (0)
+#define BMI160_USER_MAG_POWER_MODE_STAT__LEN (2)
+#define BMI160_USER_MAG_POWER_MODE_STAT__MSK (0x03)
+#define BMI160_USER_MAG_POWER_MODE_STAT__REG \
+(BMI160_USER_PMU_STAT_ADDR)
+/**************************************************************/
+/**\name GYRO POWER MODE LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* PMU_Status Description of GYRO - Reg Addr --> (0x03), Bit --> 3...2 */
+#define BMI160_USER_GYRO_POWER_MODE_STAT__POS (2)
+#define BMI160_USER_GYRO_POWER_MODE_STAT__LEN (2)
+#define BMI160_USER_GYRO_POWER_MODE_STAT__MSK (0x0C)
+#define BMI160_USER_GYRO_POWER_MODE_STAT__REG \
+(BMI160_USER_PMU_STAT_ADDR)
+/**************************************************************/
+/**\name ACCEL POWER MODE LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* PMU_Status Description of ACCEL - Reg Addr --> (0x03), Bit --> 5...4 */
+#define BMI160_USER_ACCEL_POWER_MODE_STAT__POS (4)
+#define BMI160_USER_ACCEL_POWER_MODE_STAT__LEN (2)
+#define BMI160_USER_ACCEL_POWER_MODE_STAT__MSK (0x30)
+#define BMI160_USER_ACCEL_POWER_MODE_STAT__REG \
+(BMI160_USER_PMU_STAT_ADDR)
+/**************************************************************/
+/**\name MAG DATA XYZ LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Mag_X(LSB) Description - Reg Addr --> (0x04), Bit --> 0...7 */
+#define BMI160_USER_DATA_0_MAG_X_LSB__POS (0)
+#define BMI160_USER_DATA_0_MAG_X_LSB__LEN (8)
+#define BMI160_USER_DATA_0_MAG_X_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_0_MAG_X_LSB__REG (BMI160_USER_DATA_0_ADDR)
+
+/* Mag_X(LSB) Description - Reg Addr --> (0x04), Bit --> 3...7 */
+#define BMI160_USER_DATA_MAG_X_LSB__POS (3)
+#define BMI160_USER_DATA_MAG_X_LSB__LEN (5)
+#define BMI160_USER_DATA_MAG_X_LSB__MSK (0xF8)
+#define BMI160_USER_DATA_MAG_X_LSB__REG (BMI160_USER_DATA_0_ADDR)
+
+/* Mag_X(MSB) Description - Reg Addr --> (0x05), Bit --> 0...7 */
+#define BMI160_USER_DATA_1_MAG_X_MSB__POS (0)
+#define BMI160_USER_DATA_1_MAG_X_MSB__LEN (8)
+#define BMI160_USER_DATA_1_MAG_X_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_1_MAG_X_MSB__REG (BMI160_USER_DATA_1_ADDR)
+
+/* Mag_Y(LSB) Description - Reg Addr --> (0x06), Bit --> 0...7 */
+#define BMI160_USER_DATA_2_MAG_Y_LSB__POS (0)
+#define BMI160_USER_DATA_2_MAG_Y_LSB__LEN (8)
+#define BMI160_USER_DATA_2_MAG_Y_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_2_MAG_Y_LSB__REG (BMI160_USER_DATA_2_ADDR)
+
+/* Mag_Y(LSB) Description - Reg Addr --> (0x06), Bit --> 3...7 */
+#define BMI160_USER_DATA_MAG_Y_LSB__POS (3)
+#define BMI160_USER_DATA_MAG_Y_LSB__LEN (5)
+#define BMI160_USER_DATA_MAG_Y_LSB__MSK (0xF8)
+#define BMI160_USER_DATA_MAG_Y_LSB__REG (BMI160_USER_DATA_2_ADDR)
+
+/* Mag_Y(MSB) Description - Reg Addr --> (0x07), Bit --> 0...7 */
+#define BMI160_USER_DATA_3_MAG_Y_MSB__POS (0)
+#define BMI160_USER_DATA_3_MAG_Y_MSB__LEN (8)
+#define BMI160_USER_DATA_3_MAG_Y_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_3_MAG_Y_MSB__REG (BMI160_USER_DATA_3_ADDR)
+
+/* Mag_Z(LSB) Description - Reg Addr --> (0x08), Bit --> 0...7 */
+#define BMI160_USER_DATA_4_MAG_Z_LSB__POS (0)
+#define BMI160_USER_DATA_4_MAG_Z_LSB__LEN (8)
+#define BMI160_USER_DATA_4_MAG_Z_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_4_MAG_Z_LSB__REG (BMI160_USER_DATA_4_ADDR)
+
+/* Mag_X(LSB) Description - Reg Addr --> (0x08), Bit --> 3...7 */
+#define BMI160_USER_DATA_MAG_Z_LSB__POS (1)
+#define BMI160_USER_DATA_MAG_Z_LSB__LEN (7)
+#define BMI160_USER_DATA_MAG_Z_LSB__MSK (0xFE)
+#define BMI160_USER_DATA_MAG_Z_LSB__REG (BMI160_USER_DATA_4_ADDR)
+
+/* Mag_Z(MSB) Description - Reg Addr --> (0x09), Bit --> 0...7 */
+#define BMI160_USER_DATA_5_MAG_Z_MSB__POS (0)
+#define BMI160_USER_DATA_5_MAG_Z_MSB__LEN (8)
+#define BMI160_USER_DATA_5_MAG_Z_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_5_MAG_Z_MSB__REG (BMI160_USER_DATA_5_ADDR)
+
+/* RHALL(LSB) Description - Reg Addr --> (0x0A), Bit --> 0...7 */
+#define BMI160_USER_DATA_6_RHALL_LSB__POS (0)
+#define BMI160_USER_DATA_6_RHALL_LSB__LEN (8)
+#define BMI160_USER_DATA_6_RHALL_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_6_RHALL_LSB__REG (BMI160_USER_DATA_6_ADDR)
+
+/* Mag_R(LSB) Description - Reg Addr --> (0x0A), Bit --> 3...7 */
+#define BMI160_USER_DATA_MAG_R_LSB__POS (2)
+#define BMI160_USER_DATA_MAG_R_LSB__LEN (6)
+#define BMI160_USER_DATA_MAG_R_LSB__MSK (0xFC)
+#define BMI160_USER_DATA_MAG_R_LSB__REG (BMI160_USER_DATA_6_ADDR)
+
+/* RHALL(MSB) Description - Reg Addr --> (0x0B), Bit --> 0...7 */
+#define BMI160_USER_DATA_7_RHALL_MSB__POS (0)
+#define BMI160_USER_DATA_7_RHALL_MSB__LEN (8)
+#define BMI160_USER_DATA_7_RHALL_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_7_RHALL_MSB__REG (BMI160_USER_DATA_7_ADDR)
+/**************************************************************/
+/**\name GYRO DATA XYZ LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* GYR_X (LSB) Description - Reg Addr --> (0x0C), Bit --> 0...7 */
+#define BMI160_USER_DATA_8_GYRO_X_LSB__POS (0)
+#define BMI160_USER_DATA_8_GYRO_X_LSB__LEN (8)
+#define BMI160_USER_DATA_8_GYRO_X_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_8_GYRO_X_LSB__REG (BMI160_USER_DATA_8_ADDR)
+
+/* GYR_X (MSB) Description - Reg Addr --> (0x0D), Bit --> 0...7 */
+#define BMI160_USER_DATA_9_GYRO_X_MSB__POS (0)
+#define BMI160_USER_DATA_9_GYRO_X_MSB__LEN (8)
+#define BMI160_USER_DATA_9_GYRO_X_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_9_GYRO_X_MSB__REG (BMI160_USER_DATA_9_ADDR)
+
+/* GYR_Y (LSB) Description - Reg Addr --> 0x0E, Bit --> 0...7 */
+#define BMI160_USER_DATA_10_GYRO_Y_LSB__POS (0)
+#define BMI160_USER_DATA_10_GYRO_Y_LSB__LEN (8)
+#define BMI160_USER_DATA_10_GYRO_Y_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_10_GYRO_Y_LSB__REG (BMI160_USER_DATA_10_ADDR)
+
+/* GYR_Y (MSB) Description - Reg Addr --> (0x0F), Bit --> 0...7 */
+#define BMI160_USER_DATA_11_GYRO_Y_MSB__POS (0)
+#define BMI160_USER_DATA_11_GYRO_Y_MSB__LEN (8)
+#define BMI160_USER_DATA_11_GYRO_Y_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_11_GYRO_Y_MSB__REG (BMI160_USER_DATA_11_ADDR)
+
+/* GYR_Z (LSB) Description - Reg Addr --> (0x10), Bit --> 0...7 */
+#define BMI160_USER_DATA_12_GYRO_Z_LSB__POS (0)
+#define BMI160_USER_DATA_12_GYRO_Z_LSB__LEN (8)
+#define BMI160_USER_DATA_12_GYRO_Z_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_12_GYRO_Z_LSB__REG (BMI160_USER_DATA_12_ADDR)
+
+/* GYR_Z (MSB) Description - Reg Addr --> (0x11), Bit --> 0...7 */
+#define BMI160_USER_DATA_13_GYRO_Z_MSB__POS (0)
+#define BMI160_USER_DATA_13_GYRO_Z_MSB__LEN (8)
+#define BMI160_USER_DATA_13_GYRO_Z_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_13_GYRO_Z_MSB__REG (BMI160_USER_DATA_13_ADDR)
+/**************************************************************/
+/**\name ACCEL DATA XYZ LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* ACC_X (LSB) Description - Reg Addr --> (0x12), Bit --> 0...7 */
+#define BMI160_USER_DATA_14_ACCEL_X_LSB__POS (0)
+#define BMI160_USER_DATA_14_ACCEL_X_LSB__LEN (8)
+#define BMI160_USER_DATA_14_ACCEL_X_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_14_ACCEL_X_LSB__REG (BMI160_USER_DATA_14_ADDR)
+
+/* ACC_X (MSB) Description - Reg Addr --> 0x13, Bit --> 0...7 */
+#define BMI160_USER_DATA_15_ACCEL_X_MSB__POS (0)
+#define BMI160_USER_DATA_15_ACCEL_X_MSB__LEN (8)
+#define BMI160_USER_DATA_15_ACCEL_X_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_15_ACCEL_X_MSB__REG (BMI160_USER_DATA_15_ADDR)
+
+/* ACC_Y (LSB) Description - Reg Addr --> (0x14), Bit --> 0...7 */
+#define BMI160_USER_DATA_16_ACCEL_Y_LSB__POS (0)
+#define BMI160_USER_DATA_16_ACCEL_Y_LSB__LEN (8)
+#define BMI160_USER_DATA_16_ACCEL_Y_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_16_ACCEL_Y_LSB__REG (BMI160_USER_DATA_16_ADDR)
+
+/* ACC_Y (MSB) Description - Reg Addr --> (0x15), Bit --> 0...7 */
+#define BMI160_USER_DATA_17_ACCEL_Y_MSB__POS (0)
+#define BMI160_USER_DATA_17_ACCEL_Y_MSB__LEN (8)
+#define BMI160_USER_DATA_17_ACCEL_Y_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_17_ACCEL_Y_MSB__REG (BMI160_USER_DATA_17_ADDR)
+
+/* ACC_Z (LSB) Description - Reg Addr --> 0x16, Bit --> 0...7 */
+#define BMI160_USER_DATA_18_ACCEL_Z_LSB__POS (0)
+#define BMI160_USER_DATA_18_ACCEL_Z_LSB__LEN (8)
+#define BMI160_USER_DATA_18_ACCEL_Z_LSB__MSK (0xFF)
+#define BMI160_USER_DATA_18_ACCEL_Z_LSB__REG (BMI160_USER_DATA_18_ADDR)
+
+/* ACC_Z (MSB) Description - Reg Addr --> (0x17), Bit --> 0...7 */
+#define BMI160_USER_DATA_19_ACCEL_Z_MSB__POS (0)
+#define BMI160_USER_DATA_19_ACCEL_Z_MSB__LEN (8)
+#define BMI160_USER_DATA_19_ACCEL_Z_MSB__MSK (0xFF)
+#define BMI160_USER_DATA_19_ACCEL_Z_MSB__REG (BMI160_USER_DATA_19_ADDR)
+/**************************************************************/
+/**\name SENSOR TIME LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* SENSORTIME_0 (LSB) Description - Reg Addr --> (0x18), Bit --> 0...7 */
+#define BMI160_USER_SENSORTIME_0_SENSOR_TIME_LSB__POS (0)
+#define BMI160_USER_SENSORTIME_0_SENSOR_TIME_LSB__LEN (8)
+#define BMI160_USER_SENSORTIME_0_SENSOR_TIME_LSB__MSK (0xFF)
+#define BMI160_USER_SENSORTIME_0_SENSOR_TIME_LSB__REG \
+ (BMI160_USER_SENSORTIME_0_ADDR)
+
+/* SENSORTIME_1 (MSB) Description - Reg Addr --> (0x19), Bit --> 0...7 */
+#define BMI160_USER_SENSORTIME_1_SENSOR_TIME_MSB__POS (0)
+#define BMI160_USER_SENSORTIME_1_SENSOR_TIME_MSB__LEN (8)
+#define BMI160_USER_SENSORTIME_1_SENSOR_TIME_MSB__MSK (0xFF)
+#define BMI160_USER_SENSORTIME_1_SENSOR_TIME_MSB__REG \
+ (BMI160_USER_SENSORTIME_1_ADDR)
+
+/* SENSORTIME_2 (MSB) Description - Reg Addr --> (0x1A), Bit --> 0...7 */
+#define BMI160_USER_SENSORTIME_2_SENSOR_TIME_MSB__POS (0)
+#define BMI160_USER_SENSORTIME_2_SENSOR_TIME_MSB__LEN (8)
+#define BMI160_USER_SENSORTIME_2_SENSOR_TIME_MSB__MSK (0xFF)
+#define BMI160_USER_SENSORTIME_2_SENSOR_TIME_MSB__REG \
+ (BMI160_USER_SENSORTIME_2_ADDR)
+/**************************************************************/
+/**\name GYRO SELF TEST LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 1 */
+#define BMI160_USER_STAT_GYRO_SELFTEST_OK__POS (1)
+#define BMI160_USER_STAT_GYRO_SELFTEST_OK__LEN (1)
+#define BMI160_USER_STAT_GYRO_SELFTEST_OK__MSK (0x02)
+#define BMI160_USER_STAT_GYRO_SELFTEST_OK__REG \
+ (BMI160_USER_STAT_ADDR)
+/**************************************************************/
+/**\name MAG MANUAL OPERATION LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 2 */
+#define BMI160_USER_STAT_MAG_MANUAL_OPERATION__POS (2)
+#define BMI160_USER_STAT_MAG_MANUAL_OPERATION__LEN (1)
+#define BMI160_USER_STAT_MAG_MANUAL_OPERATION__MSK (0x04)
+#define BMI160_USER_STAT_MAG_MANUAL_OPERATION__REG \
+ (BMI160_USER_STAT_ADDR)
+/**************************************************************/
+/**\name FOC STATUS LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 3 */
+#define BMI160_USER_STAT_FOC_RDY__POS (3)
+#define BMI160_USER_STAT_FOC_RDY__LEN (1)
+#define BMI160_USER_STAT_FOC_RDY__MSK (0x08)
+#define BMI160_USER_STAT_FOC_RDY__REG (BMI160_USER_STAT_ADDR)
+/**************************************************************/
+/**\name NVM READY LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 4 */
+#define BMI160_USER_STAT_NVM_RDY__POS (4)
+#define BMI160_USER_STAT_NVM_RDY__LEN (1)
+#define BMI160_USER_STAT_NVM_RDY__MSK (0x10)
+#define BMI160_USER_STAT_NVM_RDY__REG (BMI160_USER_STAT_ADDR)
+/**************************************************************/
+/**\name DATA READY LENGTH, POSITION AND MASK FOR ACCEL, MAG AND GYRO*/
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 5 */
+#define BMI160_USER_STAT_DATA_RDY_MAG__POS (5)
+#define BMI160_USER_STAT_DATA_RDY_MAG__LEN (1)
+#define BMI160_USER_STAT_DATA_RDY_MAG__MSK (0x20)
+#define BMI160_USER_STAT_DATA_RDY_MAG__REG (BMI160_USER_STAT_ADDR)
+
+/* Status Description - Reg Addr --> 0x1B, Bit --> 6 */
+#define BMI160_USER_STAT_DATA_RDY_GYRO__POS (6)
+#define BMI160_USER_STAT_DATA_RDY_GYRO__LEN (1)
+#define BMI160_USER_STAT_DATA_RDY_GYRO__MSK (0x40)
+#define BMI160_USER_STAT_DATA_RDY_GYRO__REG (BMI160_USER_STAT_ADDR)
+
+/* Status Description - Reg Addr --> 0x1B, Bit --> 7 */
+#define BMI160_USER_STAT_DATA_RDY_ACCEL__POS (7)
+#define BMI160_USER_STAT_DATA_RDY_ACCEL__LEN (1)
+#define BMI160_USER_STAT_DATA_RDY_ACCEL__MSK (0x80)
+#define BMI160_USER_STAT_DATA_RDY_ACCEL__REG (BMI160_USER_STAT_ADDR)
+/**************************************************************/
+/**\name INTERRUPT STATUS LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 0 */
+#define BMI160_USER_INTR_STAT_0_STEP_INTR__POS (0)
+#define BMI160_USER_INTR_STAT_0_STEP_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_0_STEP_INTR__MSK (0x01)
+#define BMI160_USER_INTR_STAT_0_STEP_INTR__REG \
+ (BMI160_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name SIGNIFICANT INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 1 */
+#define BMI160_USER_INTR_STAT_0_SIGNIFICANT_INTR__POS (1)
+#define BMI160_USER_INTR_STAT_0_SIGNIFICANT_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_0_SIGNIFICANT_INTR__MSK (0x02)
+#define BMI160_USER_INTR_STAT_0_SIGNIFICANT_INTR__REG \
+ (BMI160_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name ANY_MOTION INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 2 */
+#define BMI160_USER_INTR_STAT_0_ANY_MOTION__POS (2)
+#define BMI160_USER_INTR_STAT_0_ANY_MOTION__LEN (1)
+#define BMI160_USER_INTR_STAT_0_ANY_MOTION__MSK (0x04)
+#define BMI160_USER_INTR_STAT_0_ANY_MOTION__REG \
+ (BMI160_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name PMU TRIGGER INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 3 */
+#define BMI160_USER_INTR_STAT_0_PMU_TRIGGER__POS 3
+#define BMI160_USER_INTR_STAT_0_PMU_TRIGGER__LEN (1)
+#define BMI160_USER_INTR_STAT_0_PMU_TRIGGER__MSK (0x08)
+#define BMI160_USER_INTR_STAT_0_PMU_TRIGGER__REG \
+ (BMI160_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name DOUBLE TAP INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 4 */
+#define BMI160_USER_INTR_STAT_0_DOUBLE_TAP_INTR__POS 4
+#define BMI160_USER_INTR_STAT_0_DOUBLE_TAP_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_0_DOUBLE_TAP_INTR__MSK (0x10)
+#define BMI160_USER_INTR_STAT_0_DOUBLE_TAP_INTR__REG \
+ (BMI160_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name SINGLE TAP INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 5 */
+#define BMI160_USER_INTR_STAT_0_SINGLE_TAP_INTR__POS 5
+#define BMI160_USER_INTR_STAT_0_SINGLE_TAP_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_0_SINGLE_TAP_INTR__MSK (0x20)
+#define BMI160_USER_INTR_STAT_0_SINGLE_TAP_INTR__REG \
+ (BMI160_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name ORIENT INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 6 */
+#define BMI160_USER_INTR_STAT_0_ORIENT__POS (6)
+#define BMI160_USER_INTR_STAT_0_ORIENT__LEN (1)
+#define BMI160_USER_INTR_STAT_0_ORIENT__MSK (0x40)
+#define BMI160_USER_INTR_STAT_0_ORIENT__REG \
+ (BMI160_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name FLAT INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 7 */
+#define BMI160_USER_INTR_STAT_0_FLAT__POS (7)
+#define BMI160_USER_INTR_STAT_0_FLAT__LEN (1)
+#define BMI160_USER_INTR_STAT_0_FLAT__MSK (0x80)
+#define BMI160_USER_INTR_STAT_0_FLAT__REG \
+ (BMI160_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name HIGH_G INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 2 */
+#define BMI160_USER_INTR_STAT_1_HIGH_G_INTR__POS (2)
+#define BMI160_USER_INTR_STAT_1_HIGH_G_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_1_HIGH_G_INTR__MSK (0x04)
+#define BMI160_USER_INTR_STAT_1_HIGH_G_INTR__REG \
+ (BMI160_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name LOW_G INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 3 */
+#define BMI160_USER_INTR_STAT_1_LOW_G_INTR__POS (3)
+#define BMI160_USER_INTR_STAT_1_LOW_G_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_1_LOW_G_INTR__MSK (0x08)
+#define BMI160_USER_INTR_STAT_1_LOW_G_INTR__REG \
+ (BMI160_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name DATA READY INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 4 */
+#define BMI160_USER_INTR_STAT_1_DATA_RDY_INTR__POS (4)
+#define BMI160_USER_INTR_STAT_1_DATA_RDY_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_1_DATA_RDY_INTR__MSK (0x10)
+#define BMI160_USER_INTR_STAT_1_DATA_RDY_INTR__REG \
+ (BMI160_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name FIFO FULL INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 5 */
+#define BMI160_USER_INTR_STAT_1_FIFO_FULL_INTR__POS (5)
+#define BMI160_USER_INTR_STAT_1_FIFO_FULL_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_1_FIFO_FULL_INTR__MSK (0x20)
+#define BMI160_USER_INTR_STAT_1_FIFO_FULL_INTR__REG \
+ (BMI160_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name FIFO WATERMARK INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 6 */
+#define BMI160_USER_INTR_STAT_1_FIFO_WM_INTR__POS (6)
+#define BMI160_USER_INTR_STAT_1_FIFO_WM_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_1_FIFO_WM_INTR__MSK (0x40)
+#define BMI160_USER_INTR_STAT_1_FIFO_WM_INTR__REG \
+ (BMI160_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name NO MOTION INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 7 */
+#define BMI160_USER_INTR_STAT_1_NOMOTION_INTR__POS (7)
+#define BMI160_USER_INTR_STAT_1_NOMOTION_INTR__LEN (1)
+#define BMI160_USER_INTR_STAT_1_NOMOTION_INTR__MSK (0x80)
+#define BMI160_USER_INTR_STAT_1_NOMOTION_INTR__REG \
+ (BMI160_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name ANY MOTION-XYZ AXIS INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 0 */
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__POS (0)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__LEN (1)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__MSK (0x01)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__REG \
+ (BMI160_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 1 */
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__POS (1)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__LEN (1)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__MSK (0x02)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__REG \
+ (BMI160_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 2 */
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__POS (2)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__LEN (1)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__MSK (0x04)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__REG \
+ (BMI160_USER_INTR_STAT_2_ADDR)
+/**************************************************************/
+/**\name ANY MOTION SIGN LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 3 */
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_SIGN__POS (3)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_SIGN__LEN (1)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_SIGN__MSK (0x08)
+#define BMI160_USER_INTR_STAT_2_ANY_MOTION_SIGN__REG \
+ (BMI160_USER_INTR_STAT_2_ADDR)
+/**************************************************************/
+/**\name TAP_XYZ AND SIGN LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 4 */
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_X__POS (4)
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_X__LEN (1)
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_X__MSK (0x10)
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_X__REG \
+ (BMI160_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 5 */
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_Y__POS (5)
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_Y__LEN (1)
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_Y__MSK (0x20)
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_Y__REG \
+ (BMI160_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 6 */
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_Z__POS (6)
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_Z__LEN (1)
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_Z__MSK (0x40)
+#define BMI160_USER_INTR_STAT_2_TAP_FIRST_Z__REG \
+ (BMI160_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 7 */
+#define BMI160_USER_INTR_STAT_2_TAP_SIGN__POS (7)
+#define BMI160_USER_INTR_STAT_2_TAP_SIGN__LEN (1)
+#define BMI160_USER_INTR_STAT_2_TAP_SIGN__MSK (0x80)
+#define BMI160_USER_INTR_STAT_2_TAP_SIGN__REG \
+ (BMI160_USER_INTR_STAT_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT SATAUS FOR WHOLE 0x1E LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 0...7 */
+#define BMI160_USER_INTR_STAT_2__POS (0)
+#define BMI160_USER_INTR_STAT_2__LEN (8)
+#define BMI160_USER_INTR_STAT_2__MSK (0xFF)
+#define BMI160_USER_INTR_STAT_2__REG \
+ (BMI160_USER_INTR_STAT_2_ADDR)
+/**************************************************************/
+/**\name HIGH_G-XYZ AND SIGN LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 0 */
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_X__POS (0)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_X__LEN (1)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_X__MSK (0x01)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_X__REG \
+ (BMI160_USER_INTR_STAT_3_ADDR)
+
+/* Int_Status_3 Description - Reg Addr --> 0x1E, Bit --> 1 */
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Y__POS (1)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Y__LEN (1)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Y__MSK (0x02)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Y__REG \
+ (BMI160_USER_INTR_STAT_3_ADDR)
+
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 2 */
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Z__POS (2)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Z__LEN (1)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Z__MSK (0x04)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_FIRST_Z__REG \
+ (BMI160_USER_INTR_STAT_3_ADDR)
+
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 3 */
+#define BMI160_USER_INTR_STAT_3_HIGH_G_SIGN__POS (3)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_SIGN__LEN (1)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_SIGN__MSK (0x08)
+#define BMI160_USER_INTR_STAT_3_HIGH_G_SIGN__REG \
+ (BMI160_USER_INTR_STAT_3_ADDR)
+/**************************************************************/
+/**\name ORIENT XY and Z AXIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 4...5 */
+#define BMI160_USER_INTR_STAT_3_ORIENT_XY__POS (4)
+#define BMI160_USER_INTR_STAT_3_ORIENT_XY__LEN (2)
+#define BMI160_USER_INTR_STAT_3_ORIENT_XY__MSK (0x30)
+#define BMI160_USER_INTR_STAT_3_ORIENT_XY__REG \
+ (BMI160_USER_INTR_STAT_3_ADDR)
+
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 6 */
+#define BMI160_USER_INTR_STAT_3_ORIENT_Z__POS (6)
+#define BMI160_USER_INTR_STAT_3_ORIENT_Z__LEN (1)
+#define BMI160_USER_INTR_STAT_3_ORIENT_Z__MSK (0x40)
+#define BMI160_USER_INTR_STAT_3_ORIENT_Z__REG \
+ (BMI160_USER_INTR_STAT_3_ADDR)
+/**************************************************************/
+/**\name FLAT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 7 */
+#define BMI160_USER_INTR_STAT_3_FLAT__POS (7)
+#define BMI160_USER_INTR_STAT_3_FLAT__LEN (1)
+#define BMI160_USER_INTR_STAT_3_FLAT__MSK (0x80)
+#define BMI160_USER_INTR_STAT_3_FLAT__REG \
+ (BMI160_USER_INTR_STAT_3_ADDR)
+/**************************************************************/
+/**\name (0x1F) LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 0...7 */
+#define BMI160_USER_INTR_STAT_3__POS (0)
+#define BMI160_USER_INTR_STAT_3__LEN (8)
+#define BMI160_USER_INTR_STAT_3__MSK (0xFF)
+#define BMI160_USER_INTR_STAT_3__REG \
+ (BMI160_USER_INTR_STAT_3_ADDR)
+/**************************************************************/
+/**\name TEMPERATURE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Temperature Description - LSB Reg Addr --> (0x20), Bit --> 0...7 */
+#define BMI160_USER_TEMP_LSB_VALUE__POS (0)
+#define BMI160_USER_TEMP_LSB_VALUE__LEN (8)
+#define BMI160_USER_TEMP_LSB_VALUE__MSK (0xFF)
+#define BMI160_USER_TEMP_LSB_VALUE__REG \
+ (BMI160_USER_TEMPERATURE_0_ADDR)
+
+/* Temperature Description - LSB Reg Addr --> 0x21, Bit --> 0...7 */
+#define BMI160_USER_TEMP_MSB_VALUE__POS (0)
+#define BMI160_USER_TEMP_MSB_VALUE__LEN (8)
+#define BMI160_USER_TEMP_MSB_VALUE__MSK (0xFF)
+#define BMI160_USER_TEMP_MSB_VALUE__REG \
+ (BMI160_USER_TEMPERATURE_1_ADDR)
+/**************************************************************/
+/**\name FIFO BYTE COUNTER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Length0 Description - Reg Addr --> 0x22, Bit --> 0...7 */
+#define BMI160_USER_FIFO_BYTE_COUNTER_LSB__POS (0)
+#define BMI160_USER_FIFO_BYTE_COUNTER_LSB__LEN (8)
+#define BMI160_USER_FIFO_BYTE_COUNTER_LSB__MSK (0xFF)
+#define BMI160_USER_FIFO_BYTE_COUNTER_LSB__REG \
+ (BMI160_USER_FIFO_LENGTH_0_ADDR)
+
+/*Fifo_Length1 Description - Reg Addr --> 0x23, Bit --> 0...2 */
+#define BMI160_USER_FIFO_BYTE_COUNTER_MSB__POS (0)
+#define BMI160_USER_FIFO_BYTE_COUNTER_MSB__LEN 3
+#define BMI160_USER_FIFO_BYTE_COUNTER_MSB__MSK (0x07)
+#define BMI160_USER_FIFO_BYTE_COUNTER_MSB__REG \
+ (BMI160_USER_FIFO_LENGTH_1_ADDR)
+
+/**************************************************************/
+/**\name FIFO DATA LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Data Description - Reg Addr --> 0x24, Bit --> 0...7 */
+#define BMI160_USER_FIFO_DATA__POS (0)
+#define BMI160_USER_FIFO_DATA__LEN (8)
+#define BMI160_USER_FIFO_DATA__MSK (0xFF)
+#define BMI160_USER_FIFO_DATA__REG (BMI160_USER_FIFO_DATA_ADDR)
+
+/**************************************************************/
+/**\name ACCEL CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Acc_Conf Description - Reg Addr --> (0x40), Bit --> 0...3 */
+#define BMI160_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__POS (0)
+#define BMI160_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__LEN (4)
+#define BMI160_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__MSK (0x0F)
+#define BMI160_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__REG \
+(BMI160_USER_ACCEL_CONFIG_ADDR)
+
+/* Acc_Conf Description - Reg Addr --> (0x40), Bit --> 4...6 */
+#define BMI160_USER_ACCEL_CONFIG_ACCEL_BW__POS (4)
+#define BMI160_USER_ACCEL_CONFIG_ACCEL_BW__LEN (3)
+#define BMI160_USER_ACCEL_CONFIG_ACCEL_BW__MSK (0x70)
+#define BMI160_USER_ACCEL_CONFIG_ACCEL_BW__REG (BMI160_USER_ACCEL_CONFIG_ADDR)
+
+/* Acc_Conf Description - Reg Addr --> (0x40), Bit --> 7 */
+#define BMI160_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__POS (7)
+#define BMI160_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__LEN (1)
+#define BMI160_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__MSK (0x80)
+#define BMI160_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__REG \
+(BMI160_USER_ACCEL_CONFIG_ADDR)
+
+/* Acc_Range Description - Reg Addr --> 0x41, Bit --> 0...3 */
+#define BMI160_USER_ACCEL_RANGE__POS (0)
+#define BMI160_USER_ACCEL_RANGE__LEN (4)
+#define BMI160_USER_ACCEL_RANGE__MSK (0x0F)
+#define BMI160_USER_ACCEL_RANGE__REG \
+(BMI160_USER_ACCEL_RANGE_ADDR)
+/**************************************************************/
+/**\name GYRO CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Gyro_Conf Description - Reg Addr --> (0x42), Bit --> 0...3 */
+#define BMI160_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__POS (0)
+#define BMI160_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__LEN (4)
+#define BMI160_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__MSK (0x0F)
+#define BMI160_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__REG \
+(BMI160_USER_GYRO_CONFIG_ADDR)
+
+/* Gyro_Conf Description - Reg Addr --> (0x42), Bit --> 4...5 */
+#define BMI160_USER_GYRO_CONFIG_BW__POS (4)
+#define BMI160_USER_GYRO_CONFIG_BW__LEN (2)
+#define BMI160_USER_GYRO_CONFIG_BW__MSK (0x30)
+#define BMI160_USER_GYRO_CONFIG_BW__REG \
+(BMI160_USER_GYRO_CONFIG_ADDR)
+
+/* Gyr_Range Description - Reg Addr --> 0x43, Bit --> 0...2 */
+#define BMI160_USER_GYRO_RANGE__POS (0)
+#define BMI160_USER_GYRO_RANGE__LEN (3)
+#define BMI160_USER_GYRO_RANGE__MSK (0x07)
+#define BMI160_USER_GYRO_RANGE__REG (BMI160_USER_GYRO_RANGE_ADDR)
+/**************************************************************/
+/**\name MAG CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Mag_Conf Description - Reg Addr --> (0x44), Bit --> 0...3 */
+#define BMI160_USER_MAG_CONFIG_OUTPUT_DATA_RATE__POS (0)
+#define BMI160_USER_MAG_CONFIG_OUTPUT_DATA_RATE__LEN (4)
+#define BMI160_USER_MAG_CONFIG_OUTPUT_DATA_RATE__MSK (0x0F)
+#define BMI160_USER_MAG_CONFIG_OUTPUT_DATA_RATE__REG \
+(BMI160_USER_MAG_CONFIG_ADDR)
+/**************************************************************/
+/**\name FIFO DOWNS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Downs Description - Reg Addr --> 0x45, Bit --> 0...2 */
+#define BMI160_USER_FIFO_DOWN_GYRO__POS (0)
+#define BMI160_USER_FIFO_DOWN_GYRO__LEN (3)
+#define BMI160_USER_FIFO_DOWN_GYRO__MSK (0x07)
+#define BMI160_USER_FIFO_DOWN_GYRO__REG (BMI160_USER_FIFO_DOWN_ADDR)
+/**************************************************************/
+/**\name FIFO FILTER FOR ACCEL AND GYRO LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_filt Description - Reg Addr --> 0x45, Bit --> 3 */
+#define BMI160_USER_FIFO_FILTER_GYRO__POS (3)
+#define BMI160_USER_FIFO_FILTER_GYRO__LEN (1)
+#define BMI160_USER_FIFO_FILTER_GYRO__MSK (0x08)
+#define BMI160_USER_FIFO_FILTER_GYRO__REG (BMI160_USER_FIFO_DOWN_ADDR)
+
+/* Fifo_Downs Description - Reg Addr --> 0x45, Bit --> 4...6 */
+#define BMI160_USER_FIFO_DOWN_ACCEL__POS (4)
+#define BMI160_USER_FIFO_DOWN_ACCEL__LEN (3)
+#define BMI160_USER_FIFO_DOWN_ACCEL__MSK (0x70)
+#define BMI160_USER_FIFO_DOWN_ACCEL__REG (BMI160_USER_FIFO_DOWN_ADDR)
+
+/* Fifo_FILT Description - Reg Addr --> 0x45, Bit --> 7 */
+#define BMI160_USER_FIFO_FILTER_ACCEL__POS (7)
+#define BMI160_USER_FIFO_FILTER_ACCEL__LEN (1)
+#define BMI160_USER_FIFO_FILTER_ACCEL__MSK (0x80)
+#define BMI160_USER_FIFO_FILTER_ACCEL__REG (BMI160_USER_FIFO_DOWN_ADDR)
+/**************************************************************/
+/**\name FIFO WATER MARK LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_0 Description - Reg Addr --> 0x46, Bit --> 0...7 */
+#define BMI160_USER_FIFO_WM__POS (0)
+#define BMI160_USER_FIFO_WM__LEN (8)
+#define BMI160_USER_FIFO_WM__MSK (0xFF)
+#define BMI160_USER_FIFO_WM__REG (BMI160_USER_FIFO_CONFIG_0_ADDR)
+/**************************************************************/
+/**\name FIFO TIME LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 1 */
+#define BMI160_USER_FIFO_TIME_ENABLE__POS (1)
+#define BMI160_USER_FIFO_TIME_ENABLE__LEN (1)
+#define BMI160_USER_FIFO_TIME_ENABLE__MSK (0x02)
+#define BMI160_USER_FIFO_TIME_ENABLE__REG (BMI160_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO TAG INTERRUPT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 2 */
+#define BMI160_USER_FIFO_TAG_INTR2_ENABLE__POS (2)
+#define BMI160_USER_FIFO_TAG_INTR2_ENABLE__LEN (1)
+#define BMI160_USER_FIFO_TAG_INTR2_ENABLE__MSK (0x04)
+#define BMI160_USER_FIFO_TAG_INTR2_ENABLE__REG (BMI160_USER_FIFO_CONFIG_1_ADDR)
+
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 3 */
+#define BMI160_USER_FIFO_TAG_INTR1_ENABLE__POS (3)
+#define BMI160_USER_FIFO_TAG_INTR1_ENABLE__LEN (1)
+#define BMI160_USER_FIFO_TAG_INTR1_ENABLE__MSK (0x08)
+#define BMI160_USER_FIFO_TAG_INTR1_ENABLE__REG (BMI160_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO HEADER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 4 */
+#define BMI160_USER_FIFO_HEADER_ENABLE__POS (4)
+#define BMI160_USER_FIFO_HEADER_ENABLE__LEN (1)
+#define BMI160_USER_FIFO_HEADER_ENABLE__MSK (0x10)
+#define BMI160_USER_FIFO_HEADER_ENABLE__REG \
+(BMI160_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO MAG ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 5 */
+#define BMI160_USER_FIFO_MAG_ENABLE__POS (5)
+#define BMI160_USER_FIFO_MAG_ENABLE__LEN (1)
+#define BMI160_USER_FIFO_MAG_ENABLE__MSK (0x20)
+#define BMI160_USER_FIFO_MAG_ENABLE__REG \
+(BMI160_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO ACCEL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 6 */
+#define BMI160_USER_FIFO_ACCEL_ENABLE__POS (6)
+#define BMI160_USER_FIFO_ACCEL_ENABLE__LEN (1)
+#define BMI160_USER_FIFO_ACCEL_ENABLE__MSK (0x40)
+#define BMI160_USER_FIFO_ACCEL_ENABLE__REG \
+(BMI160_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO GYRO ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 7 */
+#define BMI160_USER_FIFO_GYRO_ENABLE__POS (7)
+#define BMI160_USER_FIFO_GYRO_ENABLE__LEN (1)
+#define BMI160_USER_FIFO_GYRO_ENABLE__MSK (0x80)
+#define BMI160_USER_FIFO_GYRO_ENABLE__REG \
+(BMI160_USER_FIFO_CONFIG_1_ADDR)
+
+/**************************************************************/
+/**\name MAG I2C ADDRESS SELECTION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+
+/* Mag_IF_0 Description - Reg Addr --> 0x4b, Bit --> 1...7 */
+#define BMI160_USER_I2C_DEVICE_ADDR__POS (1)
+#define BMI160_USER_I2C_DEVICE_ADDR__LEN (7)
+#define BMI160_USER_I2C_DEVICE_ADDR__MSK (0xFE)
+#define BMI160_USER_I2C_DEVICE_ADDR__REG (BMI160_USER_MAG_IF_0_ADDR)
+/**************************************************************/
+/**\name MAG CONFIGURATION FOR SECONDARY
+ INTERFACE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Mag_IF_1 Description - Reg Addr --> 0x4c, Bit --> 0...1 */
+#define BMI160_USER_MAG_BURST__POS (0)
+#define BMI160_USER_MAG_BURST__LEN (2)
+#define BMI160_USER_MAG_BURST__MSK (0x03)
+#define BMI160_USER_MAG_BURST__REG (BMI160_USER_MAG_IF_1_ADDR)
+
+/* Mag_IF_1 Description - Reg Addr --> 0x4c, Bit --> 2...5 */
+#define BMI160_USER_MAG_OFFSET__POS (2)
+#define BMI160_USER_MAG_OFFSET__LEN (4)
+#define BMI160_USER_MAG_OFFSET__MSK (0x3C)
+#define BMI160_USER_MAG_OFFSET__REG (BMI160_USER_MAG_IF_1_ADDR)
+
+/* Mag_IF_1 Description - Reg Addr --> 0x4c, Bit --> 7 */
+#define BMI160_USER_MAG_MANUAL_ENABLE__POS (7)
+#define BMI160_USER_MAG_MANUAL_ENABLE__LEN (1)
+#define BMI160_USER_MAG_MANUAL_ENABLE__MSK (0x80)
+#define BMI160_USER_MAG_MANUAL_ENABLE__REG \
+(BMI160_USER_MAG_IF_1_ADDR)
+
+/* Mag_IF_2 Description - Reg Addr --> 0x4d, Bit -->0... 7 */
+#define BMI160_USER_READ_ADDR__POS (0)
+#define BMI160_USER_READ_ADDR__LEN (8)
+#define BMI160_USER_READ_ADDR__MSK (0xFF)
+#define BMI160_USER_READ_ADDR__REG (BMI160_USER_MAG_IF_2_ADDR)
+
+/* Mag_IF_3 Description - Reg Addr --> 0x4e, Bit -->0... 7 */
+#define BMI160_USER_WRITE_ADDR__POS (0)
+#define BMI160_USER_WRITE_ADDR__LEN (8)
+#define BMI160_USER_WRITE_ADDR__MSK (0xFF)
+#define BMI160_USER_WRITE_ADDR__REG (BMI160_USER_MAG_IF_3_ADDR)
+
+/* Mag_IF_4 Description - Reg Addr --> 0x4f, Bit -->0... 7 */
+#define BMI160_USER_WRITE_DATA__POS (0)
+#define BMI160_USER_WRITE_DATA__LEN (8)
+#define BMI160_USER_WRITE_DATA__MSK (0xFF)
+#define BMI160_USER_WRITE_DATA__REG (BMI160_USER_MAG_IF_4_ADDR)
+/**************************************************************/
+/**\name ANY MOTION XYZ AXIS ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->0 */
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__POS (0)
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__MSK (0x01)
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_0_ADDR)
+
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->1 */
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__POS (1)
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__MSK (0x02)
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_0_ADDR)
+
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->2 */
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__POS (2)
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__MSK (0x04)
+#define BMI160_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name DOUBLE TAP ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->4 */
+#define BMI160_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__POS (4)
+#define BMI160_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__MSK (0x10)
+#define BMI160_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name SINGLE TAP ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->5 */
+#define BMI160_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__POS (5)
+#define BMI160_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__MSK (0x20)
+#define BMI160_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name ORIENT ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->6 */
+#define BMI160_USER_INTR_ENABLE_0_ORIENT_ENABLE__POS (6)
+#define BMI160_USER_INTR_ENABLE_0_ORIENT_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_0_ORIENT_ENABLE__MSK (0x40)
+#define BMI160_USER_INTR_ENABLE_0_ORIENT_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name FLAT ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->7 */
+#define BMI160_USER_INTR_ENABLE_0_FLAT_ENABLE__POS (7)
+#define BMI160_USER_INTR_ENABLE_0_FLAT_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_0_FLAT_ENABLE__MSK (0x80)
+#define BMI160_USER_INTR_ENABLE_0_FLAT_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name HIGH_G XYZ ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->0 */
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__POS (0)
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__MSK (0x01)
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_1_ADDR)
+
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->1 */
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__POS (1)
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__MSK (0x02)
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_1_ADDR)
+
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->2 */
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__POS (2)
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__MSK (0x04)
+#define BMI160_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_1_ADDR)
+/**************************************************************/
+/**\name LOW_G ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->3 */
+#define BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__POS (3)
+#define BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__MSK (0x08)
+#define BMI160_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_1_ADDR)
+/**************************************************************/
+/**\name DATA READY ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->4 */
+#define BMI160_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__POS (4)
+#define BMI160_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__MSK (0x10)
+#define BMI160_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_1_ADDR)
+/**************************************************************/
+/**\name FIFO FULL AND WATER MARK ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->5 */
+#define BMI160_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__POS (5)
+#define BMI160_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__MSK (0x20)
+#define BMI160_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_1_ADDR)
+
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->6 */
+#define BMI160_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__POS (6)
+#define BMI160_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__MSK (0x40)
+#define BMI160_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_1_ADDR)
+/**************************************************************/
+/**\name NO MOTION XYZ ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_2 Description - Reg Addr --> (0x52), Bit -->0 */
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__POS (0)
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__MSK (0x01)
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_2_ADDR)
+
+/* Int_En_2 Description - Reg Addr --> (0x52), Bit -->1 */
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__POS (1)
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__MSK (0x02)
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_2_ADDR)
+
+/* Int_En_2 Description - Reg Addr --> (0x52), Bit -->2 */
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__POS (2)
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__MSK (0x04)
+#define BMI160_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_2_ADDR)
+/**************************************************************/
+/**\name STEP DETECTOR ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_2 Description - Reg Addr --> (0x52), Bit -->3 */
+#define BMI160_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__POS (3)
+#define BMI160_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__MSK (0x08)
+#define BMI160_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__REG \
+(BMI160_USER_INTR_ENABLE_2_ADDR)
+/**************************************************************/
+/**\name EDGE CONTROL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->0 */
+#define BMI160_USER_INTR1_EDGE_CTRL__POS (0)
+#define BMI160_USER_INTR1_EDGE_CTRL__LEN (1)
+#define BMI160_USER_INTR1_EDGE_CTRL__MSK (0x01)
+#define BMI160_USER_INTR1_EDGE_CTRL__REG \
+(BMI160_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name LEVEL CONTROL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->1 */
+#define BMI160_USER_INTR1_LEVEL__POS (1)
+#define BMI160_USER_INTR1_LEVEL__LEN (1)
+#define BMI160_USER_INTR1_LEVEL__MSK (0x02)
+#define BMI160_USER_INTR1_LEVEL__REG \
+(BMI160_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name OUTPUT TYPE ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->2 */
+#define BMI160_USER_INTR1_OUTPUT_TYPE__POS (2)
+#define BMI160_USER_INTR1_OUTPUT_TYPE__LEN (1)
+#define BMI160_USER_INTR1_OUTPUT_TYPE__MSK (0x04)
+#define BMI160_USER_INTR1_OUTPUT_TYPE__REG \
+(BMI160_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name OUTPUT TYPE ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->3 */
+#define BMI160_USER_INTR1_OUTPUT_ENABLE__POS (3)
+#define BMI160_USER_INTR1_OUTPUT_ENABLE__LEN (1)
+#define BMI160_USER_INTR1_OUTPUT_ENABLE__MSK (0x08)
+#define BMI160_USER_INTR1_OUTPUT_ENABLE__REG \
+(BMI160_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name EDGE CONTROL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->4 */
+#define BMI160_USER_INTR2_EDGE_CTRL__POS (4)
+#define BMI160_USER_INTR2_EDGE_CTRL__LEN (1)
+#define BMI160_USER_INTR2_EDGE_CTRL__MSK (0x10)
+#define BMI160_USER_INTR2_EDGE_CTRL__REG \
+(BMI160_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name LEVEL CONTROL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->5 */
+#define BMI160_USER_INTR2_LEVEL__POS (5)
+#define BMI160_USER_INTR2_LEVEL__LEN (1)
+#define BMI160_USER_INTR2_LEVEL__MSK (0x20)
+#define BMI160_USER_INTR2_LEVEL__REG \
+(BMI160_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name OUTPUT TYPE ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->6 */
+#define BMI160_USER_INTR2_OUTPUT_TYPE__POS (6)
+#define BMI160_USER_INTR2_OUTPUT_TYPE__LEN (1)
+#define BMI160_USER_INTR2_OUTPUT_TYPE__MSK (0x40)
+#define BMI160_USER_INTR2_OUTPUT_TYPE__REG \
+(BMI160_USER_INTR_OUT_CTRL_ADDR)
+
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->7 */
+#define BMI160_USER_INTR2_OUTPUT_EN__POS (7)
+#define BMI160_USER_INTR2_OUTPUT_EN__LEN (1)
+#define BMI160_USER_INTR2_OUTPUT_EN__MSK (0x80)
+#define BMI160_USER_INTR2_OUTPUT_EN__REG \
+(BMI160_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name LATCH INTERRUPT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Latch Description - Reg Addr --> 0x54, Bit -->0...3 */
+#define BMI160_USER_INTR_LATCH__POS (0)
+#define BMI160_USER_INTR_LATCH__LEN (4)
+#define BMI160_USER_INTR_LATCH__MSK (0x0F)
+#define BMI160_USER_INTR_LATCH__REG (BMI160_USER_INTR_LATCH_ADDR)
+/**************************************************************/
+/**\name INPUT ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Latch Description - Reg Addr --> 0x54, Bit -->4 */
+#define BMI160_USER_INTR1_INPUT_ENABLE__POS (4)
+#define BMI160_USER_INTR1_INPUT_ENABLE__LEN (1)
+#define BMI160_USER_INTR1_INPUT_ENABLE__MSK (0x10)
+#define BMI160_USER_INTR1_INPUT_ENABLE__REG \
+(BMI160_USER_INTR_LATCH_ADDR)
+
+/* Int_Latch Description - Reg Addr --> 0x54, Bit -->5*/
+#define BMI160_USER_INTR2_INPUT_ENABLE__POS (5)
+#define BMI160_USER_INTR2_INPUT_ENABLE__LEN (1)
+#define BMI160_USER_INTR2_INPUT_ENABLE__MSK (0x20)
+#define BMI160_USER_INTR2_INPUT_ENABLE__REG \
+(BMI160_USER_INTR_LATCH_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF LOW_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->0 */
+#define BMI160_USER_INTR_MAP_0_INTR1_LOW_G__POS (0)
+#define BMI160_USER_INTR_MAP_0_INTR1_LOW_G__LEN (1)
+#define BMI160_USER_INTR_MAP_0_INTR1_LOW_G__MSK (0x01)
+#define BMI160_USER_INTR_MAP_0_INTR1_LOW_G__REG (BMI160_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF HIGH_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->1 */
+#define BMI160_USER_INTR_MAP_0_INTR1_HIGH_G__POS (1)
+#define BMI160_USER_INTR_MAP_0_INTR1_HIGH_G__LEN (1)
+#define BMI160_USER_INTR_MAP_0_INTR1_HIGH_G__MSK (0x02)
+#define BMI160_USER_INTR_MAP_0_INTR1_HIGH_G__REG \
+(BMI160_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT MAPPIONG OF ANY MOTION_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->2 */
+#define BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION__POS (2)
+#define BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION__LEN (1)
+#define BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION__MSK (0x04)
+#define BMI160_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG \
+(BMI160_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF NO MOTION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->3 */
+#define BMI160_USER_INTR_MAP_0_INTR1_NOMOTION__POS (3)
+#define BMI160_USER_INTR_MAP_0_INTR1_NOMOTION__LEN (1)
+#define BMI160_USER_INTR_MAP_0_INTR1_NOMOTION__MSK (0x08)
+#define BMI160_USER_INTR_MAP_0_INTR1_NOMOTION__REG (BMI160_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF DOUBLE TAP LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->4 */
+#define BMI160_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__POS (4)
+#define BMI160_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__LEN (1)
+#define BMI160_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__MSK (0x10)
+#define BMI160_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__REG \
+(BMI160_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF SINGLE TAP LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->5 */
+#define BMI160_USER_INTR_MAP_0_INTR1_SINGLE_TAP__POS (5)
+#define BMI160_USER_INTR_MAP_0_INTR1_SINGLE_TAP__LEN (1)
+#define BMI160_USER_INTR_MAP_0_INTR1_SINGLE_TAP__MSK (0x20)
+#define BMI160_USER_INTR_MAP_0_INTR1_SINGLE_TAP__REG \
+(BMI160_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF ORIENT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->6 */
+#define BMI160_USER_INTR_MAP_0_INTR1_ORIENT__POS (6)
+#define BMI160_USER_INTR_MAP_0_INTR1_ORIENT__LEN (1)
+#define BMI160_USER_INTR_MAP_0_INTR1_ORIENT__MSK (0x40)
+#define BMI160_USER_INTR_MAP_0_INTR1_ORIENT__REG \
+(BMI160_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT MAPPIONG OF FLAT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x56, Bit -->7 */
+#define BMI160_USER_INTR_MAP_0_INTR1_FLAT__POS (7)
+#define BMI160_USER_INTR_MAP_0_INTR1_FLAT__LEN (1)
+#define BMI160_USER_INTR_MAP_0_INTR1_FLAT__MSK (0x80)
+#define BMI160_USER_INTR_MAP_0_INTR1_FLAT__REG (BMI160_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF PMU TRIGGER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->0 */
+#define BMI160_USER_INTR_MAP_1_INTR2_PMU_TRIG__POS (0)
+#define BMI160_USER_INTR_MAP_1_INTR2_PMU_TRIG__LEN (1)
+#define BMI160_USER_INTR_MAP_1_INTR2_PMU_TRIG__MSK (0x01)
+#define BMI160_USER_INTR_MAP_1_INTR2_PMU_TRIG__REG (BMI160_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF FIFO FULL AND
+ WATER MARK LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->1 */
+#define BMI160_USER_INTR_MAP_1_INTR2_FIFO_FULL__POS (1)
+#define BMI160_USER_INTR_MAP_1_INTR2_FIFO_FULL__LEN (1)
+#define BMI160_USER_INTR_MAP_1_INTR2_FIFO_FULL__MSK (0x02)
+#define BMI160_USER_INTR_MAP_1_INTR2_FIFO_FULL__REG \
+(BMI160_USER_INTR_MAP_1_ADDR)
+
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->2 */
+#define BMI160_USER_INTR_MAP_1_INTR2_FIFO_WM__POS (2)
+#define BMI160_USER_INTR_MAP_1_INTR2_FIFO_WM__LEN (1)
+#define BMI160_USER_INTR_MAP_1_INTR2_FIFO_WM__MSK (0x04)
+#define BMI160_USER_INTR_MAP_1_INTR2_FIFO_WM__REG \
+(BMI160_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF DATA READY LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->3 */
+#define BMI160_USER_INTR_MAP_1_INTR2_DATA_RDY__POS (3)
+#define BMI160_USER_INTR_MAP_1_INTR2_DATA_RDY__LEN (1)
+#define BMI160_USER_INTR_MAP_1_INTR2_DATA_RDY__MSK (0x08)
+#define BMI160_USER_INTR_MAP_1_INTR2_DATA_RDY__REG \
+(BMI160_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF PMU TRIGGER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->4 */
+#define BMI160_USER_INTR_MAP_1_INTR1_PMU_TRIG__POS (4)
+#define BMI160_USER_INTR_MAP_1_INTR1_PMU_TRIG__LEN (1)
+#define BMI160_USER_INTR_MAP_1_INTR1_PMU_TRIG__MSK (0x10)
+#define BMI160_USER_INTR_MAP_1_INTR1_PMU_TRIG__REG (BMI160_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF FIFO FULL AND
+ WATER MARK LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->5 */
+#define BMI160_USER_INTR_MAP_1_INTR1_FIFO_FULL__POS (5)
+#define BMI160_USER_INTR_MAP_1_INTR1_FIFO_FULL__LEN (1)
+#define BMI160_USER_INTR_MAP_1_INTR1_FIFO_FULL__MSK (0x20)
+#define BMI160_USER_INTR_MAP_1_INTR1_FIFO_FULL__REG \
+(BMI160_USER_INTR_MAP_1_ADDR)
+
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->6 */
+#define BMI160_USER_INTR_MAP_1_INTR1_FIFO_WM__POS (6)
+#define BMI160_USER_INTR_MAP_1_INTR1_FIFO_WM__LEN (1)
+#define BMI160_USER_INTR_MAP_1_INTR1_FIFO_WM__MSK (0x40)
+#define BMI160_USER_INTR_MAP_1_INTR1_FIFO_WM__REG \
+(BMI160_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF DATA READY LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->7 */
+#define BMI160_USER_INTR_MAP_1_INTR1_DATA_RDY__POS (7)
+#define BMI160_USER_INTR_MAP_1_INTR1_DATA_RDY__LEN (1)
+#define BMI160_USER_INTR_MAP_1_INTR1_DATA_RDY__MSK (0x80)
+#define BMI160_USER_INTR_MAP_1_INTR1_DATA_RDY__REG \
+(BMI160_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF LOW_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->0 */
+#define BMI160_USER_INTR_MAP_2_INTR2_LOW_G__POS (0)
+#define BMI160_USER_INTR_MAP_2_INTR2_LOW_G__LEN (1)
+#define BMI160_USER_INTR_MAP_2_INTR2_LOW_G__MSK (0x01)
+#define BMI160_USER_INTR_MAP_2_INTR2_LOW_G__REG (BMI160_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF HIGH_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->1 */
+#define BMI160_USER_INTR_MAP_2_INTR2_HIGH_G__POS (1)
+#define BMI160_USER_INTR_MAP_2_INTR2_HIGH_G__LEN (1)
+#define BMI160_USER_INTR_MAP_2_INTR2_HIGH_G__MSK (0x02)
+#define BMI160_USER_INTR_MAP_2_INTR2_HIGH_G__REG \
+(BMI160_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF ANY MOTION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->2 */
+#define BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION__POS (2)
+#define BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION__LEN (1)
+#define BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION__MSK (0x04)
+#define BMI160_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG \
+(BMI160_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF NO MOTION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->3 */
+#define BMI160_USER_INTR_MAP_2_INTR2_NOMOTION__POS (3)
+#define BMI160_USER_INTR_MAP_2_INTR2_NOMOTION__LEN (1)
+#define BMI160_USER_INTR_MAP_2_INTR2_NOMOTION__MSK (0x08)
+#define BMI160_USER_INTR_MAP_2_INTR2_NOMOTION__REG (BMI160_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF DOUBLE TAP LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->4 */
+#define BMI160_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__POS (4)
+#define BMI160_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__LEN (1)
+#define BMI160_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__MSK (0x10)
+#define BMI160_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__REG \
+(BMI160_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF SINGLE TAP LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->5 */
+#define BMI160_USER_INTR_MAP_2_INTR2_SINGLE_TAP__POS (5)
+#define BMI160_USER_INTR_MAP_2_INTR2_SINGLE_TAP__LEN (1)
+#define BMI160_USER_INTR_MAP_2_INTR2_SINGLE_TAP__MSK (0x20)
+#define BMI160_USER_INTR_MAP_2_INTR2_SINGLE_TAP__REG \
+(BMI160_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF ORIENT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->6 */
+#define BMI160_USER_INTR_MAP_2_INTR2_ORIENT__POS (6)
+#define BMI160_USER_INTR_MAP_2_INTR2_ORIENT__LEN (1)
+#define BMI160_USER_INTR_MAP_2_INTR2_ORIENT__MSK (0x40)
+#define BMI160_USER_INTR_MAP_2_INTR2_ORIENT__REG \
+(BMI160_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF FLAT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->7 */
+#define BMI160_USER_INTR_MAP_2_INTR2_FLAT__POS (7)
+#define BMI160_USER_INTR_MAP_2_INTR2_FLAT__LEN (1)
+#define BMI160_USER_INTR_MAP_2_INTR2_FLAT__MSK (0x80)
+#define BMI160_USER_INTR_MAP_2_INTR2_FLAT__REG (BMI160_USER_INTR_MAP_2_ADDR)
+
+/**************************************************************/
+/**\name TAP SOURCE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Data_0 Description - Reg Addr --> 0x58, Bit --> 3 */
+#define BMI160_USER_INTR_DATA_0_INTR_TAP_SOURCE__POS (3)
+#define BMI160_USER_INTR_DATA_0_INTR_TAP_SOURCE__LEN (1)
+#define BMI160_USER_INTR_DATA_0_INTR_TAP_SOURCE__MSK (0x08)
+#define BMI160_USER_INTR_DATA_0_INTR_TAP_SOURCE__REG \
+(BMI160_USER_INTR_DATA_0_ADDR)
+
+/**************************************************************/
+/**\name HIGH SOURCE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Data_0 Description - Reg Addr --> 0x58, Bit --> 7 */
+#define BMI160_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__POS (7)
+#define BMI160_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__LEN (1)
+#define BMI160_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__MSK (0x80)
+#define BMI160_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__REG \
+(BMI160_USER_INTR_DATA_0_ADDR)
+
+/**************************************************************/
+/**\name MOTION SOURCE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Data_1 Description - Reg Addr --> 0x59, Bit --> 7 */
+#define BMI160_USER_INTR_DATA_1_INTR_MOTION_SOURCE__POS (7)
+#define BMI160_USER_INTR_DATA_1_INTR_MOTION_SOURCE__LEN (1)
+#define BMI160_USER_INTR_DATA_1_INTR_MOTION_SOURCE__MSK (0x80)
+#define BMI160_USER_INTR_DATA_1_INTR_MOTION_SOURCE__REG \
+ (BMI160_USER_INTR_DATA_1_ADDR)
+/**************************************************************/
+/**\name LOW HIGH DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_0 Description - Reg Addr --> 0x5a, Bit --> 0...7 */
+#define BMI160_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__POS (0)
+#define BMI160_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__LEN (8)
+#define BMI160_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__MSK (0xFF)
+#define BMI160_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__REG \
+ (BMI160_USER_INTR_LOWHIGH_0_ADDR)
+/**************************************************************/
+/**\name LOW THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_1 Description - Reg Addr --> 0x5b, Bit --> 0...7 */
+#define BMI160_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__POS (0)
+#define BMI160_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__LEN (8)
+#define BMI160_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__MSK (0xFF)
+#define BMI160_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__REG \
+ (BMI160_USER_INTR_LOWHIGH_1_ADDR)
+/**************************************************************/
+/**\name LOW HYSTERESIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_2 Description - Reg Addr --> 0x5c, Bit --> 0...1 */
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__POS (0)
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__LEN (2)
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__MSK (0x03)
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__REG \
+ (BMI160_USER_INTR_LOWHIGH_2_ADDR)
+/**************************************************************/
+/**\name LOW MODE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_2 Description - Reg Addr --> 0x5c, Bit --> 2 */
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__POS (2)
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__LEN (1)
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__MSK (0x04)
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__REG \
+ (BMI160_USER_INTR_LOWHIGH_2_ADDR)
+/**************************************************************/
+/**\name HIGH_G HYSTERESIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_2 Description - Reg Addr --> 0x5c, Bit --> 6...7 */
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__POS (6)
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__LEN (2)
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__MSK (0xC0)
+#define BMI160_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__REG \
+ (BMI160_USER_INTR_LOWHIGH_2_ADDR)
+/**************************************************************/
+/**\name HIGH_G DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_3 Description - Reg Addr --> 0x5d, Bit --> 0...7 */
+#define BMI160_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__POS (0)
+#define BMI160_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__LEN (8)
+#define BMI160_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__MSK (0xFF)
+#define BMI160_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__REG \
+ (BMI160_USER_INTR_LOWHIGH_3_ADDR)
+/**************************************************************/
+/**\name HIGH_G THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_4 Description - Reg Addr --> 0x5e, Bit --> 0...7 */
+#define BMI160_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__POS (0)
+#define BMI160_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__LEN (8)
+#define BMI160_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__MSK (0xFF)
+#define BMI160_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__REG \
+ (BMI160_USER_INTR_LOWHIGH_4_ADDR)
+/**************************************************************/
+/**\name ANY MOTION DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_0 Description - Reg Addr --> 0x5f, Bit --> 0...1 */
+#define BMI160_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__POS (0)
+#define BMI160_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__LEN (2)
+#define BMI160_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__MSK (0x03)
+#define BMI160_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__REG \
+ (BMI160_USER_INTR_MOTION_0_ADDR)
+/**************************************************************/
+/**\name SLOW/NO MOTION DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+ /* Int_Motion_0 Description - Reg Addr --> 0x5f, Bit --> 2...7 */
+#define BMI160_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__POS (2)
+#define BMI160_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__LEN (6)
+#define BMI160_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__MSK (0xFC)
+#define BMI160_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__REG \
+ (BMI160_USER_INTR_MOTION_0_ADDR)
+/**************************************************************/
+/**\name ANY MOTION THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_1 Description - Reg Addr --> (0x60), Bit --> 0...7 */
+#define BMI160_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__POS (0)
+#define BMI160_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__LEN (8)
+#define BMI160_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__MSK (0xFF)
+#define BMI160_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__REG \
+ (BMI160_USER_INTR_MOTION_1_ADDR)
+/**************************************************************/
+/**\name SLOW/NO MOTION THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_2 Description - Reg Addr --> 0x61, Bit --> 0...7 */
+#define BMI160_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__POS (0)
+#define BMI160_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__LEN (8)
+#define BMI160_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__MSK (0xFF)
+#define BMI160_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__REG \
+ (BMI160_USER_INTR_MOTION_2_ADDR)
+/**************************************************************/
+/**\name SLOW/NO MOTION SELECT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_3 Description - Reg Addr --> (0x62), Bit --> 0 */
+#define BMI160_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__POS (0)
+#define BMI160_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__LEN (1)
+#define BMI160_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__MSK (0x01)
+#define BMI160_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__REG \
+(BMI160_USER_INTR_MOTION_3_ADDR)
+/**************************************************************/
+/**\name SIGNIFICANT MOTION SELECT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_3 Description - Reg Addr --> (0x62), Bit --> 1 */
+#define BMI160_USER_INTR_SIGNIFICATION_MOTION_SELECT__POS (1)
+#define BMI160_USER_INTR_SIGNIFICATION_MOTION_SELECT__LEN (1)
+#define BMI160_USER_INTR_SIGNIFICATION_MOTION_SELECT__MSK (0x02)
+#define BMI160_USER_INTR_SIGNIFICATION_MOTION_SELECT__REG \
+ (BMI160_USER_INTR_MOTION_3_ADDR)
+
+/* Int_Motion_3 Description - Reg Addr --> (0x62), Bit --> 3..2 */
+#define BMI160_USER_INTR_SIGNIFICANT_MOTION_SKIP__POS (2)
+#define BMI160_USER_INTR_SIGNIFICANT_MOTION_SKIP__LEN (2)
+#define BMI160_USER_INTR_SIGNIFICANT_MOTION_SKIP__MSK (0x0C)
+#define BMI160_USER_INTR_SIGNIFICANT_MOTION_SKIP__REG \
+ (BMI160_USER_INTR_MOTION_3_ADDR)
+
+/* Int_Motion_3 Description - Reg Addr --> (0x62), Bit --> 5..4 */
+#define BMI160_USER_INTR_SIGNIFICANT_MOTION_PROOF__POS (4)
+#define BMI160_USER_INTR_SIGNIFICANT_MOTION_PROOF__LEN (2)
+#define BMI160_USER_INTR_SIGNIFICANT_MOTION_PROOF__MSK (0x30)
+#define BMI160_USER_INTR_SIGNIFICANT_MOTION_PROOF__REG \
+ (BMI160_USER_INTR_MOTION_3_ADDR)
+/**************************************************************/
+/**\name TAP DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* INT_TAP_0 Description - Reg Addr --> (0x63), Bit --> 0..2*/
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_DURN__POS (0)
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_DURN__LEN (3)
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_DURN__MSK (0x07)
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_DURN__REG \
+(BMI160_USER_INTR_TAP_0_ADDR)
+/**************************************************************/
+/**\name TAP SHOCK LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Tap_0 Description - Reg Addr --> (0x63), Bit --> 6 */
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_SHOCK__POS (6)
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_SHOCK__LEN (1)
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_SHOCK__MSK (0x40)
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_SHOCK__REG (BMI160_USER_INTR_TAP_0_ADDR)
+/**************************************************************/
+/**\name TAP QUIET LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Tap_0 Description - Reg Addr --> (0x63), Bit --> 7 */
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_QUIET__POS (7)
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_QUIET__LEN (1)
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_QUIET__MSK (0x80)
+#define BMI160_USER_INTR_TAP_0_INTR_TAP_QUIET__REG (BMI160_USER_INTR_TAP_0_ADDR)
+/**************************************************************/
+/**\name TAP THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Tap_1 Description - Reg Addr --> (0x64), Bit --> 0...4 */
+#define BMI160_USER_INTR_TAP_1_INTR_TAP_THRES__POS (0)
+#define BMI160_USER_INTR_TAP_1_INTR_TAP_THRES__LEN (5)
+#define BMI160_USER_INTR_TAP_1_INTR_TAP_THRES__MSK (0x1F)
+#define BMI160_USER_INTR_TAP_1_INTR_TAP_THRES__REG (BMI160_USER_INTR_TAP_1_ADDR)
+/**************************************************************/
+/**\name ORIENT MODE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_0 Description - Reg Addr --> (0x65), Bit --> 0...1 */
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__POS (0)
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__LEN (2)
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__MSK (0x03)
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__REG \
+ (BMI160_USER_INTR_ORIENT_0_ADDR)
+/**************************************************************/
+/**\name ORIENT BLOCKING LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_0 Description - Reg Addr --> (0x65), Bit --> 2...3 */
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__POS (2)
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__LEN (2)
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__MSK (0x0C)
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__REG \
+ (BMI160_USER_INTR_ORIENT_0_ADDR)
+/**************************************************************/
+/**\name ORIENT HYSTERESIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_0 Description - Reg Addr --> (0x65), Bit --> 4...7 */
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__POS (4)
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__LEN (4)
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__MSK (0xF0)
+#define BMI160_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__REG \
+ (BMI160_USER_INTR_ORIENT_0_ADDR)
+/**************************************************************/
+/**\name ORIENT THETA LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_1 Description - Reg Addr --> 0x66, Bit --> 0...5 */
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__POS (0)
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__LEN (6)
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__MSK (0x3F)
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__REG \
+ (BMI160_USER_INTR_ORIENT_1_ADDR)
+/**************************************************************/
+/**\name ORIENT UD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_1 Description - Reg Addr --> 0x66, Bit --> 6 */
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__POS (6)
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__LEN (1)
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__MSK (0x40)
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__REG \
+ (BMI160_USER_INTR_ORIENT_1_ADDR)
+/**************************************************************/
+/**\name ORIENT AXIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_1 Description - Reg Addr --> 0x66, Bit --> 7 */
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__POS (7)
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__LEN (1)
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__MSK (0x80)
+#define BMI160_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__REG \
+ (BMI160_USER_INTR_ORIENT_1_ADDR)
+/**************************************************************/
+/**\name FLAT THETA LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Flat_0 Description - Reg Addr --> 0x67, Bit --> 0...5 */
+#define BMI160_USER_INTR_FLAT_0_INTR_FLAT_THETA__POS (0)
+#define BMI160_USER_INTR_FLAT_0_INTR_FLAT_THETA__LEN (6)
+#define BMI160_USER_INTR_FLAT_0_INTR_FLAT_THETA__MSK (0x3F)
+#define BMI160_USER_INTR_FLAT_0_INTR_FLAT_THETA__REG \
+ (BMI160_USER_INTR_FLAT_0_ADDR)
+/**************************************************************/
+/**\name FLAT HYSTERESIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Flat_1 Description - Reg Addr --> (0x68), Bit --> 0...3 */
+#define BMI160_USER_INTR_FLAT_1_INTR_FLAT_HYST__POS (0)
+#define BMI160_USER_INTR_FLAT_1_INTR_FLAT_HYST__LEN (4)
+#define BMI160_USER_INTR_FLAT_1_INTR_FLAT_HYST__MSK (0x0F)
+#define BMI160_USER_INTR_FLAT_1_INTR_FLAT_HYST__REG \
+(BMI160_USER_INTR_FLAT_1_ADDR)
+/**************************************************************/
+/**\name FLAT HOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Flat_1 Description - Reg Addr --> (0x68), Bit --> 4...5 */
+#define BMI160_USER_INTR_FLAT_1_INTR_FLAT_HOLD__POS (4)
+#define BMI160_USER_INTR_FLAT_1_INTR_FLAT_HOLD__LEN (2)
+#define BMI160_USER_INTR_FLAT_1_INTR_FLAT_HOLD__MSK (0x30)
+#define BMI160_USER_INTR_FLAT_1_INTR_FLAT_HOLD__REG \
+(BMI160_USER_INTR_FLAT_1_ADDR)
+/**************************************************************/
+/**\name FOC ACCEL XYZ LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Foc_Conf Description - Reg Addr --> (0x69), Bit --> 0...1 */
+#define BMI160_USER_FOC_ACCEL_Z__POS (0)
+#define BMI160_USER_FOC_ACCEL_Z__LEN (2)
+#define BMI160_USER_FOC_ACCEL_Z__MSK (0x03)
+#define BMI160_USER_FOC_ACCEL_Z__REG (BMI160_USER_FOC_CONFIG_ADDR)
+
+/* Foc_Conf Description - Reg Addr --> (0x69), Bit --> 2...3 */
+#define BMI160_USER_FOC_ACCEL_Y__POS (2)
+#define BMI160_USER_FOC_ACCEL_Y__LEN (2)
+#define BMI160_USER_FOC_ACCEL_Y__MSK (0x0C)
+#define BMI160_USER_FOC_ACCEL_Y__REG (BMI160_USER_FOC_CONFIG_ADDR)
+
+/* Foc_Conf Description - Reg Addr --> (0x69), Bit --> 4...5 */
+#define BMI160_USER_FOC_ACCEL_X__POS (4)
+#define BMI160_USER_FOC_ACCEL_X__LEN (2)
+#define BMI160_USER_FOC_ACCEL_X__MSK (0x30)
+#define BMI160_USER_FOC_ACCEL_X__REG (BMI160_USER_FOC_CONFIG_ADDR)
+/**************************************************************/
+/**\name FOC GYRO LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Foc_Conf Description - Reg Addr --> (0x69), Bit --> 6 */
+#define BMI160_USER_FOC_GYRO_ENABLE__POS (6)
+#define BMI160_USER_FOC_GYRO_ENABLE__LEN (1)
+#define BMI160_USER_FOC_GYRO_ENABLE__MSK (0x40)
+#define BMI160_USER_FOC_GYRO_ENABLE__REG \
+(BMI160_USER_FOC_CONFIG_ADDR)
+/**************************************************************/
+/**\name NVM PROGRAM LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* CONF Description - Reg Addr --> (0x6A), Bit --> 1 */
+#define BMI160_USER_CONFIG_NVM_PROG_ENABLE__POS (1)
+#define BMI160_USER_CONFIG_NVM_PROG_ENABLE__LEN (1)
+#define BMI160_USER_CONFIG_NVM_PROG_ENABLE__MSK (0x02)
+#define BMI160_USER_CONFIG_NVM_PROG_ENABLE__REG \
+(BMI160_USER_CONFIG_ADDR)
+
+/*IF_CONF Description - Reg Addr --> (0x6B), Bit --> 0 */
+
+#define BMI160_USER_IF_CONFIG_SPI3__POS (0)
+#define BMI160_USER_IF_CONFIG_SPI3__LEN (1)
+#define BMI160_USER_IF_CONFIG_SPI3__MSK (0x01)
+#define BMI160_USER_IF_CONFIG_SPI3__REG \
+(BMI160_USER_IF_CONFIG_ADDR)
+
+/*IF_CONF Description - Reg Addr --> (0x6B), Bit --> 5..4 */
+#define BMI160_USER_IF_CONFIG_IF_MODE__POS (4)
+#define BMI160_USER_IF_CONFIG_IF_MODE__LEN (2)
+#define BMI160_USER_IF_CONFIG_IF_MODE__MSK (0x30)
+#define BMI160_USER_IF_CONFIG_IF_MODE__REG \
+(BMI160_USER_IF_CONFIG_ADDR)
+/**************************************************************/
+/**\name GYRO SLEEP CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Pmu_Trigger Description - Reg Addr --> 0x6c, Bit --> 0...2 */
+#define BMI160_USER_GYRO_SLEEP_TRIGGER__POS (0)
+#define BMI160_USER_GYRO_SLEEP_TRIGGER__LEN (3)
+#define BMI160_USER_GYRO_SLEEP_TRIGGER__MSK (0x07)
+#define BMI160_USER_GYRO_SLEEP_TRIGGER__REG (BMI160_USER_PMU_TRIGGER_ADDR)
+
+/* Pmu_Trigger Description - Reg Addr --> 0x6c, Bit --> 3...4 */
+#define BMI160_USER_GYRO_WAKEUP_TRIGGER__POS (3)
+#define BMI160_USER_GYRO_WAKEUP_TRIGGER__LEN (2)
+#define BMI160_USER_GYRO_WAKEUP_TRIGGER__MSK (0x18)
+#define BMI160_USER_GYRO_WAKEUP_TRIGGER__REG (BMI160_USER_PMU_TRIGGER_ADDR)
+
+/* Pmu_Trigger Description - Reg Addr --> 0x6c, Bit --> 5 */
+#define BMI160_USER_GYRO_SLEEP_STATE__POS (5)
+#define BMI160_USER_GYRO_SLEEP_STATE__LEN (1)
+#define BMI160_USER_GYRO_SLEEP_STATE__MSK (0x20)
+#define BMI160_USER_GYRO_SLEEP_STATE__REG (BMI160_USER_PMU_TRIGGER_ADDR)
+
+/* Pmu_Trigger Description - Reg Addr --> 0x6c, Bit --> 6 */
+#define BMI160_USER_GYRO_WAKEUP_INTR__POS (6)
+#define BMI160_USER_GYRO_WAKEUP_INTR__LEN (1)
+#define BMI160_USER_GYRO_WAKEUP_INTR__MSK (0x40)
+#define BMI160_USER_GYRO_WAKEUP_INTR__REG (BMI160_USER_PMU_TRIGGER_ADDR)
+/**************************************************************/
+/**\name ACCEL SELF TEST LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Self_Test Description - Reg Addr --> 0x6d, Bit --> 0...1 */
+#define BMI160_USER_ACCEL_SELFTEST_AXIS__POS (0)
+#define BMI160_USER_ACCEL_SELFTEST_AXIS__LEN (2)
+#define BMI160_USER_ACCEL_SELFTEST_AXIS__MSK (0x03)
+#define BMI160_USER_ACCEL_SELFTEST_AXIS__REG (BMI160_USER_SELF_TEST_ADDR)
+
+/* Self_Test Description - Reg Addr --> 0x6d, Bit --> 2 */
+#define BMI160_USER_ACCEL_SELFTEST_SIGN__POS (2)
+#define BMI160_USER_ACCEL_SELFTEST_SIGN__LEN (1)
+#define BMI160_USER_ACCEL_SELFTEST_SIGN__MSK (0x04)
+#define BMI160_USER_ACCEL_SELFTEST_SIGN__REG (BMI160_USER_SELF_TEST_ADDR)
+
+/* Self_Test Description - Reg Addr --> 0x6d, Bit --> 3 */
+#define BMI160_USER_SELFTEST_AMP__POS (3)
+#define BMI160_USER_SELFTEST_AMP__LEN (1)
+#define BMI160_USER_SELFTEST_AMP__MSK (0x08)
+#define BMI160_USER_SELFTEST_AMP__REG (BMI160_USER_SELF_TEST_ADDR)
+/**************************************************************/
+/**\name GYRO SELF TEST LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Self_Test Description - Reg Addr --> 0x6d, Bit --> 4 */
+#define BMI160_USER_GYRO_SELFTEST_START__POS (4)
+#define BMI160_USER_GYRO_SELFTEST_START__LEN (1)
+#define BMI160_USER_GYRO_SELFTEST_START__MSK (0x10)
+#define BMI160_USER_GYRO_SELFTEST_START__REG \
+(BMI160_USER_SELF_TEST_ADDR)
+/**************************************************************/
+/**\name NV_CONFIG LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* NV_CONF Description - Reg Addr --> (0x70), Bit --> 0 */
+#define BMI160_USER_NV_CONFIG_SPI_ENABLE__POS (0)
+#define BMI160_USER_NV_CONFIG_SPI_ENABLE__LEN (1)
+#define BMI160_USER_NV_CONFIG_SPI_ENABLE__MSK (0x01)
+#define BMI160_USER_NV_CONFIG_SPI_ENABLE__REG (BMI160_USER_NV_CONFIG_ADDR)
+
+/*IF_CONF Description - Reg Addr --> (0x70), Bit --> 1 */
+#define BMI160_USER_IF_CONFIG_I2C_WDT_SELECT__POS (1)
+#define BMI160_USER_IF_CONFIG_I2C_WDT_SELECT__LEN (1)
+#define BMI160_USER_IF_CONFIG_I2C_WDT_SELECT__MSK (0x02)
+#define BMI160_USER_IF_CONFIG_I2C_WDT_SELECT__REG \
+(BMI160_USER_NV_CONFIG_ADDR)
+
+/*IF_CONF Description - Reg Addr --> (0x70), Bit --> 2 */
+#define BMI160_USER_IF_CONFIG_I2C_WDT_ENABLE__POS (2)
+#define BMI160_USER_IF_CONFIG_I2C_WDT_ENABLE__LEN (1)
+#define BMI160_USER_IF_CONFIG_I2C_WDT_ENABLE__MSK (0x04)
+#define BMI160_USER_IF_CONFIG_I2C_WDT_ENABLE__REG \
+(BMI160_USER_NV_CONFIG_ADDR)
+
+/* NV_CONF Description - Reg Addr --> (0x70), Bit --> 3 */
+#define BMI160_USER_NV_CONFIG_SPARE0__POS (3)
+#define BMI160_USER_NV_CONFIG_SPARE0__LEN (1)
+#define BMI160_USER_NV_CONFIG_SPARE0__MSK (0x08)
+#define BMI160_USER_NV_CONFIG_SPARE0__REG (BMI160_USER_NV_CONFIG_ADDR)
+
+/* NV_CONF Description - Reg Addr --> (0x70), Bit --> 4...7 */
+#define BMI160_USER_NV_CONFIG_NVM_COUNTER__POS (4)
+#define BMI160_USER_NV_CONFIG_NVM_COUNTER__LEN (4)
+#define BMI160_USER_NV_CONFIG_NVM_COUNTER__MSK (0xF0)
+#define BMI160_USER_NV_CONFIG_NVM_COUNTER__REG (BMI160_USER_NV_CONFIG_ADDR)
+/**************************************************************/
+/**\name ACCEL MANUAL OFFSET LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Offset_0 Description - Reg Addr --> (0x71), Bit --> 0...7 */
+#define BMI160_USER_OFFSET_0_ACCEL_OFF_X__POS (0)
+#define BMI160_USER_OFFSET_0_ACCEL_OFF_X__LEN (8)
+#define BMI160_USER_OFFSET_0_ACCEL_OFF_X__MSK (0xFF)
+#define BMI160_USER_OFFSET_0_ACCEL_OFF_X__REG (BMI160_USER_OFFSET_0_ADDR)
+
+/* Offset_1 Description - Reg Addr --> 0x72, Bit --> 0...7 */
+#define BMI160_USER_OFFSET_1_ACCEL_OFF_Y__POS (0)
+#define BMI160_USER_OFFSET_1_ACCEL_OFF_Y__LEN (8)
+#define BMI160_USER_OFFSET_1_ACCEL_OFF_Y__MSK (0xFF)
+#define BMI160_USER_OFFSET_1_ACCEL_OFF_Y__REG (BMI160_USER_OFFSET_1_ADDR)
+
+/* Offset_2 Description - Reg Addr --> 0x73, Bit --> 0...7 */
+#define BMI160_USER_OFFSET_2_ACCEL_OFF_Z__POS (0)
+#define BMI160_USER_OFFSET_2_ACCEL_OFF_Z__LEN (8)
+#define BMI160_USER_OFFSET_2_ACCEL_OFF_Z__MSK (0xFF)
+#define BMI160_USER_OFFSET_2_ACCEL_OFF_Z__REG (BMI160_USER_OFFSET_2_ADDR)
+/**************************************************************/
+/**\name GYRO MANUAL OFFSET LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Offset_3 Description - Reg Addr --> 0x74, Bit --> 0...7 */
+#define BMI160_USER_OFFSET_3_GYRO_OFF_X__POS (0)
+#define BMI160_USER_OFFSET_3_GYRO_OFF_X__LEN (8)
+#define BMI160_USER_OFFSET_3_GYRO_OFF_X__MSK (0xFF)
+#define BMI160_USER_OFFSET_3_GYRO_OFF_X__REG (BMI160_USER_OFFSET_3_ADDR)
+
+/* Offset_4 Description - Reg Addr --> 0x75, Bit --> 0...7 */
+#define BMI160_USER_OFFSET_4_GYRO_OFF_Y__POS (0)
+#define BMI160_USER_OFFSET_4_GYRO_OFF_Y__LEN (8)
+#define BMI160_USER_OFFSET_4_GYRO_OFF_Y__MSK (0xFF)
+#define BMI160_USER_OFFSET_4_GYRO_OFF_Y__REG (BMI160_USER_OFFSET_4_ADDR)
+
+/* Offset_5 Description - Reg Addr --> 0x76, Bit --> 0...7 */
+#define BMI160_USER_OFFSET_5_GYRO_OFF_Z__POS (0)
+#define BMI160_USER_OFFSET_5_GYRO_OFF_Z__LEN (8)
+#define BMI160_USER_OFFSET_5_GYRO_OFF_Z__MSK (0xFF)
+#define BMI160_USER_OFFSET_5_GYRO_OFF_Z__REG (BMI160_USER_OFFSET_5_ADDR)
+
+
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 0..1 */
+#define BMI160_USER_OFFSET_6_GYRO_OFF_X__POS (0)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_X__LEN (2)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_X__MSK (0x03)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_X__REG (BMI160_USER_OFFSET_6_ADDR)
+
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 2...3 */
+#define BMI160_USER_OFFSET_6_GYRO_OFF_Y__POS (2)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_Y__LEN (2)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_Y__MSK (0x0C)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_Y__REG (BMI160_USER_OFFSET_6_ADDR)
+
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 4...5 */
+#define BMI160_USER_OFFSET_6_GYRO_OFF_Z__POS (4)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_Z__LEN (2)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_Z__MSK (0x30)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_Z__REG (BMI160_USER_OFFSET_6_ADDR)
+/**************************************************************/
+/**\name ACCEL OFFSET ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 6 */
+#define BMI160_USER_OFFSET_6_ACCEL_OFF_ENABLE__POS (6)
+#define BMI160_USER_OFFSET_6_ACCEL_OFF_ENABLE__LEN (1)
+#define BMI160_USER_OFFSET_6_ACCEL_OFF_ENABLE__MSK (0x40)
+#define BMI160_USER_OFFSET_6_ACCEL_OFF_ENABLE__REG \
+(BMI160_USER_OFFSET_6_ADDR)
+/**************************************************************/
+/**\name GYRO OFFSET ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 7 */
+#define BMI160_USER_OFFSET_6_GYRO_OFF_EN__POS (7)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_EN__LEN (1)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_EN__MSK (0x80)
+#define BMI160_USER_OFFSET_6_GYRO_OFF_EN__REG (BMI160_USER_OFFSET_6_ADDR)
+/**************************************************************/
+/**\name STEP COUNTER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* STEP_CNT_0 Description - Reg Addr --> 0x78, Bit --> 0 to 7 */
+#define BMI160_USER_STEP_COUNT_LSB__POS (0)
+#define BMI160_USER_STEP_COUNT_LSB__LEN (7)
+#define BMI160_USER_STEP_COUNT_LSB__MSK (0xFF)
+#define BMI160_USER_STEP_COUNT_LSB__REG (BMI160_USER_STEP_COUNT_0_ADDR)
+
+/* STEP_CNT_1 Description - Reg Addr --> 0x79, Bit --> 0 to 7 */
+#define BMI160_USER_STEP_COUNT_MSB__POS (0)
+#define BMI160_USER_STEP_COUNT_MSB__LEN (7)
+#define BMI160_USER_STEP_COUNT_MSB__MSK (0xFF)
+#define BMI160_USER_STEP_COUNT_MSB__REG (BMI160_USER_STEP_COUNT_1_ADDR)
+/**************************************************************/
+/**\name STEP COUNTER CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* STEP_CONFIG_0 Description - Reg Addr --> 0x7A, Bit --> 0 to 7 */
+#define BMI160_USER_STEP_CONFIG_ZERO__POS (0)
+#define BMI160_USER_STEP_CONFIG_ZERO__LEN (7)
+#define BMI160_USER_STEP_CONFIG_ZERO__MSK (0xFF)
+#define BMI160_USER_STEP_CONFIG_ZERO__REG \
+(BMI160_USER_STEP_CONFIG_0_ADDR)
+
+
+/* STEP_CONFIG_1 Description - Reg Addr --> 0x7B, Bit --> 0 to 2 and
+4 to 7 */
+#define BMI160_USER_STEP_CONFIG_ONE_CNF1__POS (0)
+#define BMI160_USER_STEP_CONFIG_ONE_CNF1__LEN (3)
+#define BMI160_USER_STEP_CONFIG_ONE_CNF1__MSK (0x07)
+#define BMI160_USER_STEP_CONFIG_ONE_CNF1__REG \
+(BMI160_USER_STEP_CONFIG_1_ADDR)
+
+#define BMI160_USER_STEP_CONFIG_ONE_CNF2__POS (4)
+#define BMI160_USER_STEP_CONFIG_ONE_CNF2__LEN (4)
+#define BMI160_USER_STEP_CONFIG_ONE_CNF2__MSK (0xF0)
+#define BMI160_USER_STEP_CONFIG_ONE_CNF2__REG \
+(BMI160_USER_STEP_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name STEP COUNTER ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* STEP_CONFIG_1 Description - Reg Addr --> 0x7B, Bit --> 0 to 2 */
+#define BMI160_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__POS (3)
+#define BMI160_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__LEN (1)
+#define BMI160_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__MSK (0x08)
+#define BMI160_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__REG \
+(BMI160_USER_STEP_CONFIG_1_ADDR)
+
+/* USER REGISTERS DEFINITION END */
+/**************************************************************************/
+/* CMD REGISTERS DEFINITION START */
+/**************************************************************/
+/**\name COMMAND REGISTER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Command description address - Reg Addr --> 0x7E, Bit --> 0....7 */
+#define BMI160_CMD_COMMANDS__POS (0)
+#define BMI160_CMD_COMMANDS__LEN (8)
+#define BMI160_CMD_COMMANDS__MSK (0xFF)
+#define BMI160_CMD_COMMANDS__REG (BMI160_CMD_COMMANDS_ADDR)
+/**************************************************************/
+/**\name PAGE ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Target page address - Reg Addr --> 0x7F, Bit --> 4....5 */
+#define BMI160_CMD_TARGET_PAGE__POS (4)
+#define BMI160_CMD_TARGET_PAGE__LEN (2)
+#define BMI160_CMD_TARGET_PAGE__MSK (0x30)
+#define BMI160_CMD_TARGET_PAGE__REG (BMI160_CMD_EXT_MODE_ADDR)
+
+/* Target page address - Reg Addr --> 0x7F, Bit --> 4....5 */
+#define BMI160_CMD_PAGING_EN__POS (7)
+#define BMI160_CMD_PAGING_EN__LEN (1)
+#define BMI160_CMD_PAGING_EN__MSK (0x80)
+#define BMI160_CMD_PAGING_EN__REG (BMI160_CMD_EXT_MODE_ADDR)
+
+/* Target page address - Reg Addr --> 0x7F, Bit --> 4....5 */
+#define BMI160_COM_C_TRIM_FIVE__POS (0)
+#define BMI160_COM_C_TRIM_FIVE__LEN (8)
+#define BMI160_COM_C_TRIM_FIVE__MSK (0xFF)
+#define BMI160_COM_C_TRIM_FIVE__REG (BMI160_COM_C_TRIM_FIVE_ADDR)
+
+/**************************************************************************/
+/* CMD REGISTERS DEFINITION END */
+
+/**************************************************/
+/**\name FIFO FRAME COUNT DEFINITION */
+/*************************************************/
+#define FIFO_FRAME (1024)
+#define FIFO_CONFIG_CHECK1 (0x00)
+#define FIFO_CONFIG_CHECK2 (0x80)
+/**************************************************/
+/**\name MAG SENSOR SELECT */
+/*************************************************/
+#define BST_BMM (0)
+#define BST_AKM (1)
+#define BMI160_YAS537_I2C_ADDRESS (0x2E)
+/**************************************************/
+/**\name ACCEL RANGE */
+/*************************************************/
+#define BMI160_ACCEL_RANGE_2G (0X03)
+#define BMI160_ACCEL_RANGE_4G (0X05)
+#define BMI160_ACCEL_RANGE_8G (0X08)
+#define BMI160_ACCEL_RANGE_16G (0X0C)
+/**************************************************/
+/**\name ACCEL ODR */
+/*************************************************/
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_RESERVED (0x00)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_0_78HZ (0x01)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_1_56HZ (0x02)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_3_12HZ (0x03)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_6_25HZ (0x04)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_12_5HZ (0x05)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_25HZ (0x06)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_50HZ (0x07)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_100HZ (0x08)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_200HZ (0x09)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_400HZ (0x0A)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_800HZ (0x0B)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_1600HZ (0x0C)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_RESERVED0 (0x0D)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_RESERVED1 (0x0E)
+#define BMI160_ACCEL_OUTPUT_DATA_RATE_RESERVED2 (0x0F)
+/**************************************************/
+/**\name ACCEL BANDWIDTH PARAMETER */
+/*************************************************/
+#define BMI160_ACCEL_OSR4_AVG1 (0x00)
+#define BMI160_ACCEL_OSR2_AVG2 (0x01)
+#define BMI160_ACCEL_NORMAL_AVG4 (0x02)
+#define BMI160_ACCEL_CIC_AVG8 (0x03)
+#define BMI160_ACCEL_RES_AVG16 (0x04)
+#define BMI160_ACCEL_RES_AVG32 (0x05)
+#define BMI160_ACCEL_RES_AVG64 (0x06)
+#define BMI160_ACCEL_RES_AVG128 (0x07)
+/**************************************************/
+/**\name GYRO ODR */
+/*************************************************/
+#define BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED (0x00)
+#define BMI160_GYRO_OUTPUT_DATA_RATE_25HZ (0x06)
+#define BMI160_GYRO_OUTPUT_DATA_RATE_50HZ (0x07)
+#define BMI160_GYRO_OUTPUT_DATA_RATE_100HZ (0x08)
+#define BMI160_GYRO_OUTPUT_DATA_RATE_200HZ (0x09)
+#define BMI160_GYRO_OUTPUT_DATA_RATE_400HZ (0x0A)
+#define BMI160_GYRO_OUTPUT_DATA_RATE_800HZ (0x0B)
+#define BMI160_GYRO_OUTPUT_DATA_RATE_1600HZ (0x0C)
+#define BMI160_GYRO_OUTPUT_DATA_RATE_3200HZ (0x0D)
+/**************************************************/
+/**\name GYRO BANDWIDTH PARAMETER */
+/*************************************************/
+#define BMI160_GYRO_OSR4_MODE (0x00)
+#define BMI160_GYRO_OSR2_MODE (0x01)
+#define BMI160_GYRO_NORMAL_MODE (0x02)
+#define BMI160_GYRO_CIC_MODE (0x03)
+/**************************************************/
+/**\name GYROSCOPE RANGE PARAMETER */
+/*************************************************/
+#define BMI160_GYRO_RANGE_2000_DEG_SEC (0x00)
+#define BMI160_GYRO_RANGE_1000_DEG_SEC (0x01)
+#define BMI160_GYRO_RANGE_500_DEG_SEC (0x02)
+#define BMI160_GYRO_RANGE_250_DEG_SEC (0x03)
+#define BMI160_GYRO_RANGE_125_DEG_SEC (0x04)
+/**************************************************/
+/**\name MAG ODR */
+/*************************************************/
+#define BMI160_MAG_OUTPUT_DATA_RATE_RESERVED (0x00)
+#define BMI160_MAG_OUTPUT_DATA_RATE_0_78HZ (0x01)
+#define BMI160_MAG_OUTPUT_DATA_RATE_1_56HZ (0x02)
+#define BMI160_MAG_OUTPUT_DATA_RATE_3_12HZ (0x03)
+#define BMI160_MAG_OUTPUT_DATA_RATE_6_25HZ (0x04)
+#define BMI160_MAG_OUTPUT_DATA_RATE_12_5HZ (0x05)
+#define BMI160_MAG_OUTPUT_DATA_RATE_25HZ (0x06)
+#define BMI160_MAG_OUTPUT_DATA_RATE_50HZ (0x07)
+#define BMI160_MAG_OUTPUT_DATA_RATE_100HZ (0x08)
+#define BMI160_MAG_OUTPUT_DATA_RATE_200HZ (0x09)
+#define BMI160_MAG_OUTPUT_DATA_RATE_400HZ (0x0A)
+#define BMI160_MAG_OUTPUT_DATA_RATE_800HZ (0x0B)
+#define BMI160_MAG_OUTPUT_DATA_RATE_1600HZ (0x0C)
+#define BMI160_MAG_OUTPUT_DATA_RATE_RESERVED0 (0x0D)
+#define BMI160_MAG_OUTPUT_DATA_RATE_RESERVED1 (0x0E)
+#define BMI160_MAG_OUTPUT_DATA_RATE_RESERVED2 (0x0F)
+
+/**************************************************/
+/**\name ENABLE/DISABLE SELECTIONS */
+/*************************************************/
+
+/* Enable accel and gyro offset */
+#define ACCEL_OFFSET_ENABLE (0x01)
+#define GYRO_OFFSET_ENABLE (0x01)
+
+/* command register definition */
+#define START_FOC_ACCEL_GYRO (0X03)
+
+ /* INT ENABLE 1 */
+#define BMI160_ANY_MOTION_X_ENABLE (0)
+#define BMI160_ANY_MOTION_Y_ENABLE (1)
+#define BMI160_ANY_MOTION_Z_ENABLE (2)
+#define BMI160_DOUBLE_TAP_ENABLE (4)
+#define BMI160_SINGLE_TAP_ENABLE (5)
+#define BMI160_ORIENT_ENABLE (6)
+#define BMI160_FLAT_ENABLE (7)
+
+/* INT ENABLE 1 */
+#define BMI160_HIGH_G_X_ENABLE (0)
+#define BMI160_HIGH_G_Y_ENABLE (1)
+#define BMI160_HIGH_G_Z_ENABLE (2)
+#define BMI160_LOW_G_ENABLE (3)
+#define BMI160_DATA_RDY_ENABLE (4)
+#define BMI160_FIFO_FULL_ENABLE (5)
+#define BMI160_FIFO_WM_ENABLE (6)
+
+/* INT ENABLE 2 */
+#define BMI160_NOMOTION_X_ENABLE (0)
+#define BMI160_NOMOTION_Y_ENABLE (1)
+#define BMI160_NOMOTION_Z_ENABLE (2)
+#define BMI160_STEP_DETECTOR_EN (3)
+
+/* FOC axis selection for accel*/
+#define FOC_X_AXIS (0)
+#define FOC_Y_AXIS (1)
+#define FOC_Z_AXIS (2)
+
+/* IN OUT CONTROL */
+#define BMI160_INTR1_EDGE_CTRL (0)
+#define BMI160_INTR2_EDGE_CTRL (1)
+#define BMI160_INTR1_LEVEL (0)
+#define BMI160_INTR2_LEVEL (1)
+#define BMI160_INTR1_OUTPUT_TYPE (0)
+#define BMI160_INTR2_OUTPUT_TYPE (1)
+#define BMI160_INTR1_OUTPUT_ENABLE (0)
+#define BMI160_INTR2_OUTPUT_ENABLE (1)
+
+#define BMI160_INTR1_INPUT_ENABLE (0)
+#define BMI160_INTR2_INPUT_ENABLE (1)
+
+/* INTERRUPT MAPS */
+#define BMI160_INTR1_MAP_LOW_G (0)
+#define BMI160_INTR2_MAP_LOW_G (1)
+#define BMI160_INTR1_MAP_HIGH_G (0)
+#define BMI160_INTR2_MAP_HIGH_G (1)
+#define BMI160_INTR1_MAP_ANY_MOTION (0)
+#define BMI160_INTR2_MAP_ANY_MOTION (1)
+#define BMI160_INTR1_MAP_NOMO (0)
+#define BMI160_INTR2_MAP_NOMO (1)
+#define BMI160_INTR1_MAP_DOUBLE_TAP (0)
+#define BMI160_INTR2_MAP_DOUBLE_TAP (1)
+#define BMI160_INTR1_MAP_SINGLE_TAP (0)
+#define BMI160_INTR2_MAP_SINGLE_TAP (1)
+#define BMI160_INTR1_MAP_ORIENT (0)
+#define BMI160_INTR2_MAP_ORIENT (1)
+#define BMI160_INTR1_MAP_FLAT (0)
+#define BMI160_INTR2_MAP_FLAT (1)
+#define BMI160_INTR1_MAP_DATA_RDY (0)
+#define BMI160_INTR2_MAP_DATA_RDY (1)
+#define BMI160_INTR1_MAP_FIFO_WM (0)
+#define BMI160_INTR2_MAP_FIFO_WM (1)
+#define BMI160_INTR1_MAP_FIFO_FULL (0)
+#define BMI160_INTR2_MAP_FIFO_FULL (1)
+#define BMI160_INTR1_MAP_PMUTRIG (0)
+#define BMI160_INTR2_MAP_PMUTRIG (1)
+
+/* Interrupt mapping*/
+#define BMI160_MAP_INTR1 (0)
+#define BMI160_MAP_INTR2 (1)
+/**************************************************/
+/**\name TAP DURATION */
+/*************************************************/
+#define BMI160_TAP_DURN_50MS (0x00)
+#define BMI160_TAP_DURN_100MS (0x01)
+#define BMI160_TAP_DURN_150MS (0x02)
+#define BMI160_TAP_DURN_200MS (0x03)
+#define BMI160_TAP_DURN_250MS (0x04)
+#define BMI160_TAP_DURN_375MS (0x05)
+#define BMI160_TAP_DURN_500MS (0x06)
+#define BMI160_TAP_DURN_700MS (0x07)
+/**************************************************/
+/**\name TAP SHOCK */
+/*************************************************/
+#define BMI160_TAP_SHOCK_50MS (0x00)
+#define BMI160_TAP_SHOCK_75MS (0x01)
+/**************************************************/
+/**\name TAP QUIET */
+/*************************************************/
+#define BMI160_TAP_QUIET_30MS (0x00)
+#define BMI160_TAP_QUIET_20MS (0x01)
+/**************************************************/
+/**\name STEP DETECTION SELECTION MODES */
+/*************************************************/
+#define BMI160_STEP_NORMAL_MODE (0)
+#define BMI160_STEP_SENSITIVE_MODE (1)
+#define BMI160_STEP_ROBUST_MODE (2)
+/**************************************************/
+/**\name STEP CONFIGURATION SELECT MODE */
+/*************************************************/
+#define STEP_CONFIG_NORMAL (0X315)
+#define STEP_CONFIG_SENSITIVE (0X2D)
+#define STEP_CONFIG_ROBUST (0X71D)
+/**************************************************/
+/**\name BMM150 TRIM DATA DEFINITIONS */
+/*************************************************/
+#define BMI160_MAG_DIG_X1 (0x5D)
+#define BMI160_MAG_DIG_Y1 (0x5E)
+#define BMI160_MAG_DIG_Z4_LSB (0x62)
+#define BMI160_MAG_DIG_Z4_MSB (0x63)
+#define BMI160_MAG_DIG_X2 (0x64)
+#define BMI160_MAG_DIG_Y2 (0x65)
+#define BMI160_MAG_DIG_Z2_LSB (0x68)
+#define BMI160_MAG_DIG_Z2_MSB (0x69)
+#define BMI160_MAG_DIG_Z1_LSB (0x6A)
+#define BMI160_MAG_DIG_Z1_MSB (0x6B)
+#define BMI160_MAG_DIG_XYZ1_LSB (0x6C)
+#define BMI160_MAG_DIG_XYZ1_MSB (0x6D)
+#define BMI160_MAG_DIG_Z3_LSB (0x6E)
+#define BMI160_MAG_DIG_Z3_MSB (0x6F)
+#define BMI160_MAG_DIG_XY2 (0x70)
+#define BMI160_MAG_DIG_XY1 (0x71)
+/**************************************************/
+/**\name BMM150 PRE-SET MODE DEFINITIONS */
+/*************************************************/
+#define BMI160_MAG_PRESETMODE_LOWPOWER (1)
+#define BMI160_MAG_PRESETMODE_REGULAR (2)
+#define BMI160_MAG_PRESETMODE_HIGHACCURACY (3)
+#define BMI160_MAG_PRESETMODE_ENHANCED (4)
+/**************************************************/
+/**\name BMM150 PRESET MODES - DATA RATES */
+/*************************************************/
+#define BMI160_MAG_LOWPOWER_DR (0x02)
+#define BMI160_MAG_REGULAR_DR (0x02)
+#define BMI160_MAG_HIGHACCURACY_DR (0x2A)
+#define BMI160_MAG_ENHANCED_DR (0x02)
+/**************************************************/
+/**\name BMM150 PRESET MODES - REPETITIONS-XY RATES */
+/*************************************************/
+#define BMI160_MAG_LOWPOWER_REPXY (1)
+#define BMI160_MAG_REGULAR_REPXY (4)
+#define BMI160_MAG_HIGHACCURACY_REPXY (23)
+#define BMI160_MAG_ENHANCED_REPXY (7)
+/**************************************************/
+/**\name BMM150 PRESET MODES - REPETITIONS-Z RATES */
+/*************************************************/
+#define BMI160_MAG_LOWPOWER_REPZ (2)
+#define BMI160_MAG_REGULAR_REPZ (14)
+#define BMI160_MAG_HIGHACCURACY_REPZ (82)
+#define BMI160_MAG_ENHANCED_REPZ (26)
+#define BMI160_MAG_NOAMRL_SWITCH_TIMES (5)
+#define MAG_INTERFACE_PMU_ENABLE (1)
+#define MAG_INTERFACE_PMU_DISABLE (0)
+/**************************************************/
+/**\name USED FOR MAG OVERFLOW CHECK FOR BMM150 */
+/*************************************************/
+#define BMI160_MAG_OVERFLOW_OUTPUT ((s16)-32768)
+#define BMI160_MAG_OVERFLOW_OUTPUT_S32 ((s32)(-2147483647-1))
+#define BMI160_MAG_NEGATIVE_SATURATION_Z ((s16)-32767)
+#define BMI160_MAG_POSITIVE_SATURATION_Z ((u16)32767)
+#define BMI160_MAG_FLIP_OVERFLOW_ADCVAL ((s16)-4096)
+#define BMI160_MAG_HALL_OVERFLOW_ADCVAL ((s16)-16384)
+/**************************************************/
+/**\name BMM150 REGISTER DEFINITION */
+/*************************************************/
+#define BMI160_BMM150_CHIP_ID (0x40)
+#define BMI160_BMM150_POWE_CONTROL_REG (0x4B)
+#define BMI160_BMM150_POWE_MODE_REG (0x4C)
+#define BMI160_BMM150_DATA_REG (0x42)
+#define BMI160_BMM150_XY_REP (0x51)
+#define BMI160_BMM150_Z_REP (0x52)
+/**************************************************/
+/**\name AKM COMPENSATING DATA REGISTERS */
+/*************************************************/
+#define BMI160_BST_AKM_ASAX (0x60)
+#define BMI160_BST_AKM_ASAY (0x61)
+#define BMI160_BST_AKM_ASAZ (0x62)
+/**************************************************/
+/**\name AKM POWER MODE SELECTION */
+/*************************************************/
+#define AKM_POWER_DOWN_MODE (0)
+#define AKM_SINGLE_MEAS_MODE (1)
+#define FUSE_ROM_MODE (2)
+/**************************************************/
+/**\name SECONDARY_MAG POWER MODE SELECTION */
+/*************************************************/
+#define BMI160_MAG_FORCE_MODE (0)
+#define BMI160_MAG_SUSPEND_MODE (1)
+/**************************************************/
+/**\name MAG POWER MODE SELECTION */
+/*************************************************/
+#define FORCE_MODE (0)
+#define SUSPEND_MODE (1)
+#define NORMAL_MODE (2)
+#define MAG_SUSPEND_MODE (1)
+/**************************************************/
+/**\name FIFO CONFIGURATIONS */
+/*************************************************/
+#define FIFO_HEADER_ENABLE (0x01)
+#define FIFO_MAG_ENABLE (0x01)
+#define FIFO_ACCEL_ENABLE (0x01)
+#define FIFO_GYRO_ENABLE (0x01)
+#define FIFO_TIME_ENABLE (0x01)
+#define FIFO_STOPONFULL_ENABLE (0x01)
+#define FIFO_WM_INTERRUPT_ENABLE (0x01)
+#define BMI160_FIFO_INDEX_LENGTH (1)
+#define BMI160_FIFO_TAG_INTR_MASK (0xFC)
+
+/**************************************************/
+/**\name ACCEL POWER MODE */
+/*************************************************/
+#define ACCEL_MODE_NORMAL (0x11)
+#define ACCEL_LOWPOWER (0X12)
+#define ACCEL_SUSPEND (0X10)
+/**************************************************/
+/**\name GYRO POWER MODE */
+/*************************************************/
+#define GYRO_MODE_SUSPEND (0x14)
+#define GYRO_MODE_NORMAL (0x15)
+#define GYRO_MODE_FASTSTARTUP (0x17)
+/**************************************************/
+/**\name MAG POWER MODE */
+/*************************************************/
+#define MAG_MODE_SUSPEND (0x18)
+#define MAG_MODE_NORMAL (0x19)
+#define MAG_MODE_LOWPOWER (0x1A)
+/**************************************************/
+/**\name ENABLE/DISABLE BIT VALUES */
+/*************************************************/
+#define BMI160_ENABLE (0x01)
+#define BMI160_DISABLE (0x00)
+/**************************************************/
+/**\name INTERRUPT EDGE TRIGGER ENABLE */
+/*************************************************/
+#define BMI160_EDGE (0x01)
+#define BMI160_LEVEL (0x00)
+/**************************************************/
+/**\name INTERRUPT LEVEL ENABLE */
+/*************************************************/
+#define BMI160_LEVEL_LOW (0x00)
+#define BMI160_LEVEL_HIGH (0x01)
+/**************************************************/
+/**\name INTERRUPT OUTPUT ENABLE */
+/*************************************************/
+#define BMI160_OPEN_DRAIN (0x01)
+#define BMI160_PUSH_PULL (0x00)
+
+/* interrupt output enable*/
+#define BMI160_INPUT (0x01)
+#define BMI160_OUTPUT (0x00)
+
+/**************************************************/
+/**\name INTERRUPT TAP SOURCE ENABLE */
+/*************************************************/
+#define FILTER_DATA (0x00)
+#define UNFILTER_DATA (0x01)
+/**************************************************/
+/**\name SLOW MOTION/ NO MOTION SELECT */
+/*************************************************/
+#define SLOW_MOTION (0x00)
+#define NO_MOTION (0x01)
+/**************************************************/
+/**\name SIGNIFICANT MOTION SELECTION */
+/*************************************************/
+#define ANY_MOTION (0x00)
+#define SIGNIFICANT_MOTION (0x01)
+/**************************************************/
+/**\name LATCH DURATION */
+/*************************************************/
+#define BMI160_LATCH_DUR_NONE (0x00)
+#define BMI160_LATCH_DUR_312_5_MICRO_SEC (0x01)
+#define BMI160_LATCH_DUR_625_MICRO_SEC (0x02)
+#define BMI160_LATCH_DUR_1_25_MILLI_SEC (0x03)
+#define BMI160_LATCH_DUR_2_5_MILLI_SEC (0x04)
+#define BMI160_LATCH_DUR_5_MILLI_SEC (0x05)
+#define BMI160_LATCH_DUR_10_MILLI_SEC (0x06)
+#define BMI160_LATCH_DUR_20_MILLI_SEC (0x07)
+#define BMI160_LATCH_DUR_40_MILLI_SEC (0x08)
+#define BMI160_LATCH_DUR_80_MILLI_SEC (0x09)
+#define BMI160_LATCH_DUR_160_MILLI_SEC (0x0A)
+#define BMI160_LATCH_DUR_320_MILLI_SEC (0x0B)
+#define BMI160_LATCH_DUR_640_MILLI_SEC (0x0C)
+#define BMI160_LATCH_DUR_1_28_SEC (0x0D)
+#define BMI160_LATCH_DUR_2_56_SEC (0x0E)
+#define BMI160_LATCHED (0x0F)
+/**************************************************/
+/**\name GYRO OFFSET MASK DEFINITION */
+/*************************************************/
+#define BMI160_GYRO_MANUAL_OFFSET_0_7 (0x00FF)
+#define BMI160_GYRO_MANUAL_OFFSET_8_9 (0x0300)
+/**************************************************/
+/**\name STEP CONFIGURATION MASK DEFINITION */
+/*************************************************/
+#define BMI160_STEP_CONFIG_0_7 (0x00FF)
+#define BMI160_STEP_CONFIG_8_10 (0x0700)
+#define BMI160_STEP_CONFIG_11_14 (0xF000)
+/**************************************************/
+/**\name DEFINITION USED FOR DIFFERENT WRITE */
+/*************************************************/
+#define BMI160_WRITE_TARGET_PAGE0 (0x00)
+#define BMI160_WRITE_TARGET_PAGE1 (0x01)
+#define BMI160_WRITE_ENABLE_PAGE1 (0x01)
+#define BMI160_MANUAL_DISABLE (0x00)
+#define BMI160_MANUAL_ENABLE (0x01)
+#define BMI160_YAS_DISABLE_RCOIL (0x00)
+#define BMI160_ENABLE_MAG_IF_MODE (0x02)
+#define BMI160_ENABLE_ANY_MOTION_INTR1 (0x04)
+#define BMI160_ENABLE_ANY_MOTION_INTR2 (0x04)
+#define BMI160_MAG_DATA_READ_REG (0x04)
+#define BMI160_BMM_POWER_MODE_REG (0x06)
+#define BMI160_ENABLE_ANY_MOTION_AXIS (0x07)
+#define BMI160_ENABLE_LOW_G (0x08)
+#define BMI160_YAS532_ACQ_START (0x11)
+#define BMI160_YAS_DEVICE_ID_REG (0x80)
+#define BMI160_FIFO_GYRO_ENABLE (0x80)
+#define BMI160_SIG_MOTION_INTR_ENABLE (0x01)
+#define BMI160_STEP_DETECT_INTR_ENABLE (0x01)
+#define BMI160_LOW_G_INTR_STAT (0x01)
+#define BMI160_PULL_UP_DATA (0x30)
+#define BMI160_FIFO_M_G_A_ENABLE (0xE0)
+#define BMI160_FIFO_M_G_ENABLE (0xA0)
+#define BMI160_FIFO_M_A_ENABLE (0x60)
+#define BMI160_FIFO_G_A_ENABLE (0xC0)
+#define BMI160_FIFO_A_ENABLE (0x40)
+#define BMI160_FIFO_M_ENABLE (0x20)
+/**************************************************/
+/**\name MAG INIT DEFINITION */
+/*************************************************/
+#define BMI160_COMMAND_REG_ONE (0x37)
+#define BMI160_COMMAND_REG_TWO (0x9A)
+#define BMI160_COMMAND_REG_THREE (0xC0)
+#define RESET_STEP_COUNTER (0xB2)
+/**************************************************/
+/**\name BIT SLICE GET AND SET FUNCTIONS */
+/*************************************************/
+#define BMI160_GET_BITSLICE(regvar, bitname)\
+ ((regvar & bitname##__MSK) >> bitname##__POS)
+
+
+#define BMI160_SET_BITSLICE(regvar, bitname, val)\
+ ((regvar & ~bitname##__MSK) | \
+ ((val<<bitname##__POS)&bitname##__MSK))
+
+/**************************************************/
+/**\name FUNCTION DECLARATIONS */
+/*************************************************/
+/**************************************************/
+/**\name FUNCTION FOR BMI160 INITIALIZE */
+/*************************************************/
+/*!
+ * @brief
+ * This function is used for initialize
+ * bus read and bus write functions
+ * assign the chip id and device address
+ * chip id is read in the register 0x00 bit from 0 to 7
+ *
+ * @param bmi160 : structure pointer
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * While changing the parameter of the bmi160_t
+ * consider the following point:
+ * Changing the reference value of the parameter
+ * will changes the local copy or local reference
+ * make sure your changes will not
+ * affect the reference value of the parameter
+ * (Better case don't change the reference value of the parameter)
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_init(struct bmi160_t *bmi160);
+/**************************************************/
+/**\name FUNCTION FOR READ AND WRITE REGISTERS */
+/*************************************************/
+/*!
+ * @brief
+ * This API write the data to
+ * the given register
+ *
+ *
+ * @param v_addr_u8 -> Address of the register
+ * @param v_data_u8 -> The data from the register
+ * @param v_len_u8 -> no of bytes to read
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_write_reg(u8 v_addr_u8,
+u8 *v_data_u8, u8 v_len_u8);
+/*!
+ * @brief
+ * This API reads the data from
+ * the given register
+ *
+ *
+ * @param v_addr_u8 -> Address of the register
+ * @param v_data_u8 -> The data from the register
+ * @param v_len_u8 -> no of bytes to read
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_reg(u8 v_addr_u8,
+u8 *v_data_u8, u8 v_len_u8);
+/**************************************************/
+/**\name FUNCTION FOR ERROR CODES */
+/*************************************************/
+/*!
+ * @brief This API used to reads the fatal error
+ * from the Register 0x02 bit 0
+ * This flag will be reset only by power-on-reset and soft reset
+ *
+ *
+ * @param v_fatal_err_u8 : The status of fatal error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fatal_err(u8
+*v_fatal_err_u8);
+/*!
+ * @brief This API used to read the error code
+ * from register 0x02 bit 1 to 4
+ *
+ *
+ * @param v_err_code_u8 : The status of error codes
+ * error_code | description
+ * ------------|---------------
+ * 0x00 |no error
+ * 0x01 |ACC_CONF error (accel ODR and bandwidth not compatible)
+ * 0x02 |GYR_CONF error (Gyroscope ODR and bandwidth not compatible)
+ * 0x03 |Under sampling mode and interrupt uses pre filtered data
+ * 0x04 |reserved
+ * 0x05 |Selected trigger-readout offset in
+ * - |MAG_IF greater than selected ODR
+ * 0x06 |FIFO configuration error for header less mode
+ * 0x07 |Under sampling mode and pre filtered data as FIFO source
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_err_code(u8
+*v_error_code_u8);
+/*!
+ * @brief This API Reads the i2c error code from the
+ * Register 0x02 bit 5.
+ * This error occurred in I2C master detected
+ *
+ * @param v_i2c_err_code_u8 : The status of i2c fail error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_i2c_fail_err(u8
+*v_i2c_error_code_u8);
+ /*!
+ * @brief This API Reads the dropped command error
+ * from the register 0x02 bit 6
+ *
+ *
+ * @param v_drop_cmd_err_u8 : The status of drop command error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_drop_cmd_err(u8
+*v_drop_cmd_err_u8);
+/*!
+ * @brief This API reads the magnetometer data ready
+ * interrupt not active.
+ * It reads from the error register 0x0x2 bit 7
+ *
+ *
+ *
+ *
+ * @param v_mag_data_rdy_err_u8 : The status of mag data ready interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_dada_rdy_err(u8
+*v_mag_data_rdy_err_u8);
+/*!
+ * @brief This API reads the error status
+ * from the error register 0x02 bit 0 to 7
+ *
+ * @param v_mag_data_rdy_err_u8 : The status of mag data ready interrupt
+ * @param v_fatal_er_u8r : The status of fatal error
+ * @param v_err_code_u8 : The status of error code
+ * @param v_i2c_fail_err_u8 : The status of I2C fail error
+ * @param v_drop_cmd_err_u8 : The status of drop command error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_error_status(u8 *v_fatal_er_u8r,
+u8 *v_err_code_u8, u8 *v_i2c_fail_err_u8,
+u8 *v_drop_cmd_err_u8, u8 *v_mag_data_rdy_err_u8);
+/******************************************************************/
+/**\name FUNCTIONS FOR MAG,ACCEL AND GYRO POWER MODE STATUS */
+/*****************************************************************/
+/*!
+ * @brief This API reads the magnetometer power mode from
+ * PMU status register 0x03 bit 0 and 1
+ *
+ * @param v_mag_power_mode_stat_u8 : The value of mag power mode
+ * mag_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * LOW POWER | 0x02
+ *
+ *
+ * @note The power mode of mag set by the 0x7E command register
+ * @note using the function "bmi160_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x18 | MAG_MODE_SUSPEND
+ * 0x19 | MAG_MODE_NORMAL
+ * 0x1A | MAG_MODE_LOWPOWER
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_power_mode_stat(u8
+*v_mag_power_mode_stat_u8);
+/*!
+ * @brief This API reads the gyroscope power mode from
+ * PMU status register 0x03 bit 2 and 3
+ *
+ * @param v_gyro_power_mode_stat_u8 : The value of gyro power mode
+ * gyro_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * FAST POWER UP | 0x03
+ *
+ * @note The power mode of gyro set by the 0x7E command register
+ * @note using the function "bmi160_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x14 | GYRO_MODE_SUSPEND
+ * 0x15 | GYRO_MODE_NORMAL
+ * 0x17 | GYRO_MODE_FASTSTARTUP
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_power_mode_stat(u8
+*v_gyro_power_mode_stat_u8);
+/*!
+ * @brief This API reads the accelerometer power mode from
+ * PMU status register 0x03 bit 4 and 5
+ *
+ *
+ * @param v_accel_power_mode_stat_u8 : The value of accel power mode
+ * accel_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * LOW POWER | 0x03
+ *
+ * @note The power mode of accel set by the 0x7E command register
+ * @note using the function "bmi160_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x11 | ACCEL_MODE_NORMAL
+ * 0x12 | ACCEL_LOWPOWER
+ * 0x10 | ACCEL_SUSPEND
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_power_mode_stat(u8
+*v_accel_power_mode_stat_u8);
+/*!
+ * @brief This API switch mag interface to normal mode
+ * and confirm whether the mode switching done successfully or not
+*
+ * @return results of bus communication function and current MAG_PMU result
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_interface_normal(void);
+/**************************************************/
+/**\name FUNCTION FOR Mag XYZ data read */
+/*************************************************/
+/*!
+ * @brief This API reads magnetometer data X values
+ * from the register 0x04 and 0x05
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_x_s16 : The value of mag x
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_x(s16 *v_mag_x_s16,
+u8 v_sensor_select_u8);
+/*!
+ * @brief This API reads magnetometer data Y values
+ * from the register 0x06 and 0x07
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_y_s16 : The value of mag y
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_y(s16 *v_mag_y_s16,
+u8 v_sensor_select_u8);
+/*!
+ * @brief This API reads magnetometer data Z values
+ * from the register 0x08 and 0x09
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_z_s16 : The value of mag z
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_z(s16 *v_mag_z_s16,
+u8 v_sensor_select_u8);
+/*!
+ * @brief This API reads magnetometer data RHALL values
+ * from the register 0x0A and 0x0B
+ *
+ *
+ * @param v_mag_r_s16 : The value of BMM150 r data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_r(
+s16 *v_mag_r_s16);
+/*!
+ * @brief This API reads magnetometer data X,Y,Z values
+ * from the register 0x04 to 0x09
+ *
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param mag : The value of mag xyz data
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_xyz(
+struct bmi160_mag_t *mag, u8 v_sensor_select_u8);
+ /*!*
+ * @brief This API reads magnetometer data X,Y,Z,r
+ * values from the register 0x04 to 0x0B
+ *
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param mag : The value of mag-BMM150 xyzr data
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note bmi160_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_mag_xyzr(
+struct bmi160_mag_xyzr_t *mag);
+/**************************************************/
+/**\name FUNCTION FOR GYRO XYZ DATA READ */
+/*************************************************/
+/*!
+ * @brief This API reads gyro data X values
+ * form the register 0x0C and 0x0D
+ *
+ *
+ *
+ *
+ * @param v_gyro_x_s16 : The value of gyro x data
+ *
+ * @note Gyro Configuration use the following function
+ * @note bmi160_set_gyro_output_data_rate()
+ * @note bmi160_set_gyro_bw()
+ * @note bmi160_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_gyro_x(
+s16 *v_gyro_x_s16);
+/*!
+ * @brief This API reads gyro data Y values
+ * form the register 0x0E and 0x0F
+ *
+ *
+ *
+ *
+ * @param v_gyro_y_s16 : The value of gyro y data
+ *
+ * @note Gyro Configuration use the following function
+ * @note bmi160_set_gyro_output_data_rate()
+ * @note bmi160_set_gyro_bw()
+ * @note bmi160_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error result of communication routines
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_gyro_y(
+s16 *v_gyro_y_s16);
+/*!
+ * @brief This API reads gyro data Z values
+ * form the register 0x10 and 0x11
+ *
+ *
+ *
+ *
+ * @param v_gyro_z_s16 : The value of gyro z data
+ *
+ * @note Gyro Configuration use the following function
+ * @note bmi160_set_gyro_output_data_rate()
+ * @note bmi160_set_gyro_bw()
+ * @note bmi160_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_gyro_z(
+s16 *v_gyro_z_s16);
+/*!
+ * @brief This API reads gyro data X,Y,Z values
+ * from the register 0x0C to 0x11
+ *
+ *
+ *
+ *
+ * @param gyro : The value of gyro xyz
+ *
+ * @note Gyro Configuration use the following function
+ * @note bmi160_set_gyro_output_data_rate()
+ * @note bmi160_set_gyro_bw()
+ * @note bmi160_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_gyro_xyz(
+struct bmi160_gyro_t *gyro);
+/**************************************************/
+/**\name FUNCTION FOR ACCEL XYZ DATA READ */
+/*************************************************/
+/*!
+ * @brief This API reads accelerometer data X values
+ * form the register 0x12 and 0x13
+ *
+ *
+ *
+ *
+ * @param v_accel_x_s16 : The value of accel x
+ *
+ * @note For accel configuration use the following functions
+ * @note bmi160_set_accel_output_data_rate()
+ * @note bmi160_set_accel_bw()
+ * @note bmi160_set_accel_under_sampling_parameter()
+ * @note bmi160_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_accel_x(
+s16 *v_accel_x_s16);
+/*!
+ * @brief This API reads accelerometer data Y values
+ * form the register 0x14 and 0x15
+ *
+ *
+ *
+ *
+ * @param v_accel_y_s16 : The value of accel y
+ *
+ * @note For accel configuration use the following functions
+ * @note bmi160_set_accel_output_data_rate()
+ * @note bmi160_set_accel_bw()
+ * @note bmi160_set_accel_under_sampling_parameter()
+ * @note bmi160_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_accel_y(
+s16 *v_accel_y_s16);
+/*!
+ * @brief This API reads accelerometer data Z values
+ * form the register 0x16 and 0x17
+ *
+ *
+ *
+ *
+ * @param v_accel_z_s16 : The value of accel z
+ *
+ * @note For accel configuration use the following functions
+ * @note bmi160_set_accel_output_data_rate()
+ * @note bmi160_set_accel_bw()
+ * @note bmi160_set_accel_under_sampling_parameter()
+ * @note bmi160_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_accel_z(
+s16 *v_accel_z_s16);
+/*!
+ * @brief This API reads accelerometer data X,Y,Z values
+ * from the register 0x12 to 0x17
+ *
+ *
+ *
+ *
+ * @param accel :The value of accel xyz
+ *
+ * @note For accel configuration use the following functions
+ * @note bmi160_set_accel_output_data_rate()
+ * @note bmi160_set_accel_bw()
+ * @note bmi160_set_accel_under_sampling_parameter()
+ * @note bmi160_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_accel_xyz(
+struct bmi160_accel_t *accel);
+/**************************************************/
+/**\name FUNCTION FOR SENSOR TIME */
+/*************************************************/
+/*!
+ * @brief This API reads sensor_time from the register
+ * 0x18 to 0x1A
+ *
+ *
+ * @param v_sensor_time_u32 : The value of sensor time
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_sensor_time(
+u32 *v_sensor_time_u32);
+/**************************************************/
+/**\name FUNCTION FOR GYRO SLEF TEST */
+/*************************************************/
+/*!
+ * @brief This API reads the Gyroscope self test
+ * status from the register 0x1B bit 1
+ *
+ *
+ * @param v_gyro_selftest_u8 : The value of gyro self test status
+ * value | status
+ * ---------|----------------
+ * 0 | Gyroscope self test is running or failed
+ * 1 | Gyroscope self test completed successfully
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_selftest(u8
+*v_gyro_selftest_u8);
+/**************************************************/
+/**\name FUNCTION FOR MANUAL INTERFACE */
+/*************************************************/
+/*!
+ * @brief This API reads the status of
+ * mag manual interface operation form the register 0x1B bit 2
+ *
+ *
+ *
+ * @param v_mag_manual_stat_u8 : The value of mag manual operation status
+ * value | status
+ * ---------|----------------
+ * 0 | Indicates no manual magnetometer
+ * - | interface operation is ongoing
+ * 1 | Indicates manual magnetometer
+ * - | interface operation is ongoing
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_manual_operation_stat(u8
+*v_mag_manual_stat_u8);
+/**************************************************/
+/**\name FUNCTION FOR FAST OFFSET READY */
+/*************************************************/
+/*!
+ * @brief This API reads the fast offset compensation
+ * status form the register 0x1B bit 3
+ *
+ *
+ * @param v_foc_rdy_u8 : The status of fast compensation
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_rdy(u8
+*v_foc_rdy_u8);
+/**************************************************/
+/**\name FUNCTION FOR NVM READY */
+/*************************************************/
+/*!
+ * @brief This API Reads the nvm_rdy status from the
+ * resister 0x1B bit 4
+ *
+ *
+ * @param v_nvm_rdy_u8 : The value of NVM ready status
+ * value | status
+ * ---------|----------------
+ * 0 | NVM write operation in progress
+ * 1 | NVM is ready to accept a new write trigger
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_nvm_rdy(u8
+*v_nvm_rdy_u8);
+/**************************************************/
+/**\name FUNCTION FOR DATA READY FOR MAG, GYRO, AND ACCEL */
+/*************************************************/
+/*!
+ * @brief This API reads the status of mag data ready
+ * from the register 0x1B bit 5
+ * The status get reset when one mag data register is read out
+ *
+ * @param v_data_rdy_u8 : The value of mag data ready status
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_data_rdy_mag(u8
+*v_data_rdy_u8);
+/*!
+ * @brief This API reads the status of gyro data ready form the
+ * register 0x1B bit 6
+ * The status get reset when gyro data register read out
+ *
+ *
+ * @param v_data_rdy_u8 : The value of gyro data ready
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_data_rdy(u8
+*v_data_rdy_u8);
+/*!
+ * @brief This API reads the status of accel data ready form the
+ * register 0x1B bit 7
+ * The status get reset when accel data register read out
+ *
+ *
+ * @param v_data_rdy_u8 : The value of accel data ready status
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_data_rdy(u8
+*drdy_acc);
+/**************************************************/
+/**\name FUNCTION FOR STEP INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the step detector interrupt status
+ * from the register 0x1C bit 0
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The status of step detector interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_step_intr(u8
+*v_step_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR SIGNIFICANT INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the
+ * significant motion interrupt status
+ * from the register 0x1C bit 1
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ *
+ * @param v_significant_intr_u8 : The status of step
+ * motion interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_significant_intr(u8
+*sigmot_intr);
+/**************************************************/
+/**\name FUNCTION FOR ANY MOTION INTERRUPT STATUS */
+/*************************************************/
+ /*!
+ * @brief This API reads the any motion interrupt status
+ * from the register 0x1C bit 2
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ * @param v_any_motion_intr_u8 : The status of any-motion interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_any_motion_intr(u8
+*v_any_motion_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR PMU TRIGGER INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the power mode trigger interrupt status
+ * from the register 0x1C bit 3
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ *
+ * @param v_pmu_trigger_intr_u8 : The status of power mode trigger interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_pmu_trigger_intr(u8
+*v_pmu_trigger_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR DOUBLE TAB STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the double tab status
+ * from the register 0x1C bit 4
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_double_tap_intr_u8 :The status of double tab interrupt
+ *
+ * @note Double tap interrupt can be configured by the following functions
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_double_tap()
+ * @note AXIS MAPPING
+ * @note bmi160_get_stat2_tap_first_x()
+ * @note bmi160_get_stat2_tap_first_y()
+ * @note bmi160_get_stat2_tap_first_z()
+ * @note DURATION
+ * @note bmi160_set_intr_tap_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_tap_thres()
+ * @note TAP QUIET
+ * @note bmi160_set_intr_tap_quiet()
+ * @note TAP SHOCK
+ * @note bmi160_set_intr_tap_shock()
+ * @note TAP SOURCE
+ * @note bmi160_set_intr_tap_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_double_tap_intr(u8
+*v_double_tap_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR SINGLE TAB STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the single tab status
+ * from the register 0x1C bit 5
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_single_tap_intr_u8 :The status of single tap interrupt
+ *
+ * @note Single tap interrupt can be configured by the following functions
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_single_tap()
+ * @note AXIS MAPPING
+ * @note bmi160_get_stat2_tap_first_x()
+ * @note bmi160_get_stat2_tap_first_y()
+ * @note bmi160_get_stat2_tap_first_z()
+ * @note DURATION
+ * @note bmi160_set_intr_tap_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_tap_thres()
+ * @note TAP QUIET
+ * @note bmi160_set_intr_tap_quiet()
+ * @note TAP SHOCK
+ * @note bmi160_set_intr_tap_shock()
+ * @note TAP SOURCE
+ * @note bmi160_set_intr_tap_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_single_tap_intr(u8
+*v_single_tap_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR ORIENT INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the orient status
+ * from the register 0x1C bit 6
+ * flag is associated with a specific interrupt function.
+ * It is set when the orient interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_orient_intr_u8 : The status of orient interrupt
+ *
+ * @note For orient interrupt configuration use the following functions
+ * @note STATUS
+ * @note bmi160_get_stat0_orient_intr()
+ * @note AXIS MAPPING
+ * @note bmi160_get_stat3_orient_xy()
+ * @note bmi160_get_stat3_orient_z()
+ * @note bmi160_set_intr_orient_axes_enable()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_orient()
+ * @note INTERRUPT OUTPUT
+ * @note bmi160_set_intr_orient_ud_enable()
+ * @note THETA
+ * @note bmi160_set_intr_orient_theta()
+ * @note HYSTERESIS
+ * @note bmi160_set_intr_orient_hyst()
+ * @note BLOCKING
+ * @note bmi160_set_intr_orient_blocking()
+ * @note MODE
+ * @note bmi160_set_intr_orient_mode()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_orient_intr(u8
+*v_orient_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR FLAT INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the flat interrupt status
+ * from the register 0x1C bit 7
+ * flag is associated with a specific interrupt function.
+ * It is set when the flat interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_flat_intr_u8 : The status of flat interrupt
+ *
+ * @note For flat configuration use the following functions
+ * @note STATS
+ * @note bmi160_get_stat0_flat_intr()
+ * @note bmi160_get_stat3_flat()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_flat()
+ * @note THETA
+ * @note bmi160_set_intr_flat_theta()
+ * @note HOLD TIME
+ * @note bmi160_set_intr_flat_hold()
+ * @note HYSTERESIS
+ * @note bmi160_set_intr_flat_hyst()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat0_flat_intr(u8
+*v_flat_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR HIGH_G INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the high_g interrupt status
+ * from the register 0x1D bit 2
+ * flag is associated with a specific interrupt function.
+ * It is set when the high g interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be permanently
+ * latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_high_g_intr_u8 : The status of high_g interrupt
+ *
+ * @note High_g interrupt configured by following functions
+ * @note STATUS
+ * @note bmi160_get_stat1_high_g_intr()
+ * @note AXIS MAPPING
+ * @note bmi160_get_stat3_high_g_first_x()
+ * @note bmi160_get_stat3_high_g_first_y()
+ * @note bmi160_get_stat3_high_g_first_z()
+ * @note SIGN MAPPING
+ * @note bmi160_get_stat3_high_g_first_sign()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_high_g()
+ * @note HYSTERESIS
+ * @note bmi160_set_intr_high_g_hyst()
+ * @note DURATION
+ * @note bmi160_set_intr_high_g_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_high_g_thres()
+ * @note SOURCE
+ * @note bmi160_set_intr_low_high_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_high_g_intr(u8
+*v_high_g_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR LOW_G INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the low g interrupt status
+ * from the register 0x1D bit 3
+ * flag is associated with a specific interrupt function.
+ * It is set when the low g interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_low_g_intr_u8 : The status of low_g interrupt
+ *
+ * @note Low_g interrupt configured by following functions
+ * @note STATUS
+ * @note bmi160_get_stat1_low_g_intr()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_low_g()
+ * @note SOURCE
+ * @note bmi160_set_intr_low_high_source()
+ * @note DURATION
+ * @note bmi160_set_intr_low_g_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_low_g_thres()
+ * @note HYSTERESIS
+ * @note bmi160_set_intr_low_g_hyst()
+ * @note MODE
+ * @note bmi160_set_intr_low_g_mode()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_low_g_intr(u8
+*v_low_g_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR DATA READY INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads data ready interrupt status
+ * from the register 0x1D bit 4
+ * flag is associated with a specific interrupt function.
+ * It is set when the data ready interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_data_rdy_intr_u8 : The status of data ready interrupt
+ *
+ * @note Data ready interrupt configured by following functions
+ * @note STATUS
+ * @note bmi160_get_stat1_data_rdy_intr()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_data_rdy()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_data_rdy_intr(u8
+*v_data_rdy_intr_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR FIFO FULL AND WATER MARK INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads data ready FIFO full interrupt status
+ * from the register 0x1D bit 5
+ * flag is associated with a specific interrupt function.
+ * It is set when the FIFO full interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will
+ * be permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_fifo_full_intr_u8 : The status of fifo full interrupt
+ *
+ * @note FIFO full interrupt can be configured by following functions
+ * @note bmi160_set_intr_fifo_full()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_fifo_full_intr(u8
+*v_fifo_full_intr_u8);
+/*!
+ * @brief This API reads data
+ * ready FIFO watermark interrupt status
+ * from the register 0x1D bit 6
+ * flag is associated with a specific interrupt function.
+ * It is set when the FIFO watermark interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_fifo_wm_intr_u8 : The status of fifo water mark interrupt
+ *
+ * @note FIFO full interrupt can be configured by following functions
+ * @note bmi160_set_intr_fifo_wm()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_fifo_wm_intr(u8
+*v_fifo_wm_intr_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR NO MOTION INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads data ready no motion interrupt status
+ * from the register 0x1D bit 7
+ * flag is associated with a specific interrupt function.
+ * It is set when the no motion interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be permanently
+ * latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_nomotion_intr_u8 : The status of no motion interrupt
+ *
+ * @note No motion interrupt can be configured by following function
+ * @note STATUS
+ * @note bmi160_get_stat1_nomotion_intr()
+ * @note INTERRUPT MAPPING
+ * @note bmi160_set_intr_nomotion()
+ * @note DURATION
+ * @note bmi160_set_intr_slow_no_motion_durn()
+ * @note THRESHOLD
+ * @note bmi160_set_intr_slow_no_motion_thres()
+ * @note SLOW/NO MOTION SELECT
+ * @note bmi160_set_intr_slow_no_motion_select()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat1_nomotion_intr(u8
+*nomo_intr);
+/**************************************************/
+/**\name FUNCTIONS FOR ANY MOTION FIRST XYZ AND SIGN INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the status of any motion first x
+ * from the register 0x1E bit 0
+ *
+ *
+ * @param v_anymotion_first_x_u8 : The status of any motion first x interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_any_motion_first_x(u8
+*v_anymotion_first_x_u8);
+/*!
+ * @brief This API reads the status of any motion first y interrupt
+ * from the register 0x1E bit 1
+ *
+ *
+ *
+ *@param v_any_motion_first_y_u8 : The status of any motion first y interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_any_motion_first_y(u8
+*v_any_motion_first_y_u8);
+/*!
+ * @brief This API reads the status of any motion first z interrupt
+ * from the register 0x1E bit 2
+ *
+ *
+ *
+ *
+ *@param v_any_motion_first_z_u8 : The status of any motion first z interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_any_motion_first_z(u8
+*v_any_motion_first_z_u8);
+/*!
+ * @brief This API reads the any motion sign status from the
+ * register 0x1E bit 3
+ *
+ *
+ *
+ *
+ * @param v_anymotion_sign_u8 : The status of any motion sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_any_motion_sign(u8
+*v_anymotion_sign_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR TAP FIRST XYZ AND SIGN INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the any motion tap first x status from the
+ * register 0x1E bit 4
+ *
+ *
+ *
+ *
+ * @param v_tap_first_x_u8 :The status of any motion tap first x
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_tap_first_x(u8
+*v_tap_first_x_u8);
+/*!
+ * @brief This API reads the tap first y interrupt status from the
+ * register 0x1E bit 5
+ *
+ *
+ *
+ *
+ * @param v_tap_first_y_u8 :The status of tap first y interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_tap_first_y(u8
+*v_tap_first_y_u8);
+/*!
+ * @brief This API reads the tap first z interrupt status from the
+ * register 0x1E bit 6
+ *
+ *
+ *
+ *
+ * @param v_tap_first_z_u8 :The status of tap first z interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_tap_first_z(u8
+*v_tap_first_z_u8);
+/*!
+ * @brief This API reads the tap sign status from the
+ * register 0x1E bit 7
+ *
+ *
+ *
+ *
+ * @param v_tap_sign_u8 : The status of tap sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat2_tap_sign(u8
+*tap_sign);
+/**************************************************/
+/**\name FUNCTIONS FOR HIGH_G FIRST XYZ AND SIGN INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the high_g first x status from the
+ * register 0x1F bit 0
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_x_u8 :The status of high_g first x
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_high_g_first_x(u8
+*v_high_g_first_x_u8);
+/*!
+ * @brief This API reads the high_g first y status from the
+ * register 0x1F bit 1
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_y_u8 : The status of high_g first y
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_high_g_first_y(u8
+*v_high_g_first_y_u8);
+/*!
+ * @brief This API reads the high_g first z status from the
+ * register 0x1F bit 3
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_z_u8 : The status of high_g first z
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_high_g_first_z(u8
+*v_high_g_first_z_u8);
+/*!
+ * @brief This API reads the high sign status from the
+ * register 0x1F bit 3
+ *
+ *
+ *
+ *
+ * @param v_high_g_sign_u8 :The status of high sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_high_g_sign(u8
+*v_high_g_sign_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR ORIENT XY AND Z INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the status of orient_xy plane
+ * from the register 0x1F bit 4 and 5
+ *
+ *
+ * @param v_orient_xy_u8 :The status of orient_xy plane
+ * value | status
+ * -----------|-------------
+ * 0x00 | portrait upright
+ * 0x01 | portrait upside down
+ * 0x02 | landscape left
+ * 0x03 | landscape right
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_orient_xy(u8
+*v_orient_xy_u8);
+/*!
+ * @brief This API reads the status of orient z plane
+ * from the register 0x1F bit 6
+ *
+ *
+ * @param v_orient_z_u8 :The status of orient z
+ * value | status
+ * -----------|-------------
+ * 0x00 | upward looking
+ * 0x01 | downward looking
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_orient_z(u8
+*v_orient_z_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR FLAT INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the flat status from the register
+ * 0x1F bit 7
+ *
+ *
+ * @param v_flat_u8 : The status of flat interrupt
+ * value | status
+ * -----------|-------------
+ * 0x00 | non flat
+ * 0x01 | flat position
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_stat3_flat(u8
+*flat);
+/**************************************************/
+/**\name FUNCTION FOR TEMPERATUE READ */
+/*************************************************/
+/*!
+ * @brief This API reads the temperature of the sensor
+ * from the register 0x21 bit 0 to 7
+ *
+ *
+ *
+ * @param v_temp_s16 : The value of temperature
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_temp(s16
+*v_temp_s16);
+/**************************************************/
+/**\name FUNCTION FOR FIFO LENGTH AND FIFO DATA READ */
+/*************************************************/
+/*!
+ * @brief This API reads the of the sensor
+ * form the register 0x23 and 0x24 bit 0 to 7 and 0 to 2
+ * @brief this byte counter is updated each time a complete frame
+ * was read or writtern
+ *
+ *
+ * @param v_fifo_length_u32 : The value of fifo byte counter
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_fifo_length(
+u32 *v_fifo_length_u32);
+/*!
+ * @brief This API reads the fifo data of the sensor
+ * from the register 0x24
+ * @brief Data format depends on the setting of register FIFO_CONFIG
+ *
+ *
+ *
+ * @param v_fifodata_u8 : Pointer holding the fifo data
+ *
+ * @note For reading FIFO data use the following functions
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_fifo_data(
+u8 *v_fifodata_u8, u16 v_fifo_length_u16);
+/**************************************************/
+/**\name FUNCTION FOR ACCEL CONFIGURATIONS */
+/*************************************************/
+/*!
+ * @brief This API is used to get the
+ * accel output date rate form the register 0x40 bit 0 to 3
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of accel output date rate
+ * value | output data rate
+ * -------|--------------------------
+ * 0 | BMI160_ACCEL_OUTPUT_DATA_RATE_RESERVED
+ * 1 | BMI160_ACCEL_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | BMI160_ACCEL_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | BMI160_ACCEL_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | BMI160_ACCEL_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | BMI160_ACCEL_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | BMI160_ACCEL_OUTPUT_DATA_RATE_25HZ
+ * 7 | BMI160_ACCEL_OUTPUT_DATA_RATE_50HZ
+ * 8 | BMI160_ACCEL_OUTPUT_DATA_RATE_100HZ
+ * 9 | BMI160_ACCEL_OUTPUT_DATA_RATE_200HZ
+ * 10 | BMI160_ACCEL_OUTPUT_DATA_RATE_400HZ
+ * 11 | BMI160_ACCEL_OUTPUT_DATA_RATE_800HZ
+ * 12 | BMI160_ACCEL_OUTPUT_DATA_RATE_1600HZ
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_output_data_rate(
+u8 *v_output_data_rate_u8);
+/*!
+ * @brief This API is used to set the
+ * accel output date rate form the register 0x40 bit 0 to 3
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of accel output date rate
+ * value | output data rate
+ * -------|--------------------------
+ * 0 | BMI160_ACCEL_OUTPUT_DATA_RATE_RESERVED
+ * 1 | BMI160_ACCEL_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | BMI160_ACCEL_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | BMI160_ACCEL_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | BMI160_ACCEL_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | BMI160_ACCEL_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | BMI160_ACCEL_OUTPUT_DATA_RATE_25HZ
+ * 7 | BMI160_ACCEL_OUTPUT_DATA_RATE_50HZ
+ * 8 | BMI160_ACCEL_OUTPUT_DATA_RATE_100HZ
+ * 9 | BMI160_ACCEL_OUTPUT_DATA_RATE_200HZ
+ * 10 | BMI160_ACCEL_OUTPUT_DATA_RATE_400HZ
+ * 11 | BMI160_ACCEL_OUTPUT_DATA_RATE_800HZ
+ * 12 | BMI160_ACCEL_OUTPUT_DATA_RATE_1600HZ
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_output_data_rate(u8 odr);
+/*!
+ * @brief This API is used to get the
+ * accel bandwidth from the register 0x40 bit 4 to 6
+ * @brief bandwidth parameter determines filter configuration(acc_us=0)
+ * and averaging for under sampling mode(acc_us=1)
+ *
+ *
+ * @param v_bw_u8 : The value of accel bandwidth
+ *
+ * @note accel bandwidth depends on under sampling parameter
+ * @note under sampling parameter cab be set by the function
+ * "BMI160_SET_ACCEL_UNDER_SAMPLING_PARAMETER"
+ *
+ * @note Filter configuration
+ * accel_us | Filter configuration
+ * -----------|---------------------
+ * 0x00 | OSR4 mode
+ * 0x01 | OSR2 mode
+ * 0x02 | normal mode
+ * 0x03 | CIC mode
+ * 0x04 | Reserved
+ * 0x05 | Reserved
+ * 0x06 | Reserved
+ * 0x07 | Reserved
+ *
+ * @note accel under sampling mode
+ * accel_us | Under sampling mode
+ * -----------|---------------------
+ * 0x00 | no averaging
+ * 0x01 | average 2 samples
+ * 0x02 | average 4 samples
+ * 0x03 | average 8 samples
+ * 0x04 | average 16 samples
+ * 0x05 | average 32 samples
+ * 0x06 | average 64 samples
+ * 0x07 | average 128 samples
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_bw(u8 *v_bw_u8);
+/*!
+ * @brief This API is used to set the
+ * accel bandwidth from the register 0x40 bit 4 to 6
+ * @brief bandwidth parameter determines filter configuration(acc_us=0)
+ * and averaging for under sampling mode(acc_us=1)
+ *
+ *
+ * @param v_bw_u8 : The value of accel bandwidth
+ *
+ * @note accel bandwidth depends on under sampling parameter
+ * @note under sampling parameter cab be set by the function
+ * "BMI160_SET_ACCEL_UNDER_SAMPLING_PARAMETER"
+ *
+ * @note Filter configuration
+ * accel_us | Filter configuration
+ * -----------|---------------------
+ * 0x00 | OSR4 mode
+ * 0x01 | OSR2 mode
+ * 0x02 | normal mode
+ * 0x03 | CIC mode
+ * 0x04 | Reserved
+ * 0x05 | Reserved
+ * 0x06 | Reserved
+ * 0x07 | Reserved
+ *
+ * @note accel under sampling mode
+ * accel_us | Under sampling mode
+ * -----------|---------------------
+ * 0x00 | no averaging
+ * 0x01 | average 2 samples
+ * 0x02 | average 4 samples
+ * 0x03 | average 8 samples
+ * 0x04 | average 16 samples
+ * 0x05 | average 32 samples
+ * 0x06 | average 64 samples
+ * 0x07 | average 128 samples
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_bw(u8 v_bw_u8);
+/*!
+ * @brief This API is used to get the accel
+ * under sampling parameter form the register 0x40 bit 7
+ *
+ *
+ *
+ *
+ * @param v_accel_under_sampling_u8 : The value of accel under sampling
+ * value | under_sampling
+ * ----------|---------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_under_sampling_parameter(
+u8 *v_accel_under_sampling_u8);
+/*!
+ * @brief This API is used to set the accel
+ * under sampling parameter form the register 0x40 bit 7
+ *
+ *
+ *
+ *
+ * @param v_accel_under_sampling_u8 : The value of accel under sampling
+ * value | under_sampling
+ * ----------|---------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_under_sampling_parameter(
+u8 v_accel_under_sampling_u8);
+/*!
+ * @brief This API is used to get the ranges
+ * (g values) of the accel from the register 0x41 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_range_u8 : The value of accel g range
+ * value | g_range
+ * ----------|-----------
+ * 0x03 | BMI160_ACCEL_RANGE_2G
+ * 0x05 | BMI160_ACCEL_RANGE_4G
+ * 0x08 | BMI160_ACCEL_RANGE_8G
+ * 0x0C | BMI160_ACCEL_RANGE_16G
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_range(
+u8 *v_range_u8);
+/*!
+ * @brief This API is used to set the ranges
+ * (g values) of the accel from the register 0x41 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_range_u8 : The value of accel g range
+ * value | g_range
+ * ----------|-----------
+ * 0x03 | BMI160_ACCEL_RANGE_2G
+ * 0x05 | BMI160_ACCEL_RANGE_4G
+ * 0x08 | BMI160_ACCEL_RANGE_8G
+ * 0x0C | BMI160_ACCEL_RANGE_16G
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_range(
+u8 v_range_u8);
+/**************************************************/
+/**\name FUNCTION FOR GYRO CONFIGURATIONS */
+/*************************************************/
+/*!
+ * @brief This API is used to get the
+ * gyroscope output data rate from the register 0x42 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of gyro output data rate
+ * value | gyro output data rate
+ * -----------|-----------------------------
+ * 0x00 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x02 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x03 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x04 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x05 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x06 | BMI160_GYRO_OUTPUT_DATA_RATE_25HZ
+ * 0x07 | BMI160_GYRO_OUTPUT_DATA_RATE_50HZ
+ * 0x08 | BMI160_GYRO_OUTPUT_DATA_RATE_100HZ
+ * 0x09 | BMI160_GYRO_OUTPUT_DATA_RATE_200HZ
+ * 0x0A | BMI160_GYRO_OUTPUT_DATA_RATE_400HZ
+ * 0x0B | BMI160_GYRO_OUTPUT_DATA_RATE_800HZ
+ * 0x0C | BMI160_GYRO_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D | BMI160_GYRO_OUTPUT_DATA_RATE_3200HZ
+ * 0x0E | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x0F | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_output_data_rate(
+u8 *gyro_output_typer);
+/*!
+ * @brief This API is used to set the
+ * gyroscope output data rate from the register 0x42 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of gyro output data rate
+ * value | gyro output data rate
+ * -----------|-----------------------------
+ * 0x00 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x02 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x03 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x04 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x05 | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x06 | BMI160_GYRO_OUTPUT_DATA_RATE_25HZ
+ * 0x07 | BMI160_GYRO_OUTPUT_DATA_RATE_50HZ
+ * 0x08 | BMI160_GYRO_OUTPUT_DATA_RATE_100HZ
+ * 0x09 | BMI160_GYRO_OUTPUT_DATA_RATE_200HZ
+ * 0x0A | BMI160_GYRO_OUTPUT_DATA_RATE_400HZ
+ * 0x0B | BMI160_GYRO_OUTPUT_DATA_RATE_800HZ
+ * 0x0C | BMI160_GYRO_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D | BMI160_GYRO_OUTPUT_DATA_RATE_3200HZ
+ * 0x0E | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x0F | BMI160_GYRO_OUTPUT_DATA_RATE_RESERVED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_output_data_rate(
+u8 gyro_output_typer);
+/*!
+ * @brief This API is used to get the
+ * data of gyro from the register 0x42 bit 4 to 5
+ *
+ *
+ *
+ *
+ * @param v_bw_u8 : The value of gyro bandwidth
+ * value | gyro bandwidth
+ * ----------|----------------
+ * 0x00 | BMI160_GYRO_OSR4_MODE
+ * 0x01 | BMI160_GYRO_OSR2_MODE
+ * 0x02 | BMI160_GYRO_NORMAL_MODE
+ * 0x03 | BMI160_GYRO_CIC_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_bw(u8 *v_bw_u8);
+/*!
+ * @brief This API is used to set the
+ * data of gyro from the register 0x42 bit 4 to 5
+ *
+ *
+ *
+ *
+ * @param v_bw_u8 : The value of gyro bandwidth
+ * value | gyro bandwidth
+ * ----------|----------------
+ * 0x00 | BMI160_GYRO_OSR4_MODE
+ * 0x01 | BMI160_GYRO_OSR2_MODE
+ * 0x02 | BMI160_GYRO_NORMAL_MODE
+ * 0x03 | BMI160_GYRO_CIC_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_bw(u8 v_bw_u8);
+/*!
+ * @brief This API reads the range
+ * of gyro from the register 0x43 bit 0 to 2
+ *
+ * @param v_range_u8 : The value of gyro range
+ * value | range
+ * ----------|-------------------------------
+ * 0x00 | BMI160_GYRO_RANGE_2000_DEG_SEC
+ * 0x01 | BMI160_GYRO_RANGE_1000_DEG_SEC
+ * 0x02 | BMI160_GYRO_RANGE_500_DEG_SEC
+ * 0x03 | BMI160_GYRO_RANGE_250_DEG_SEC
+ * 0x04 | BMI160_GYRO_RANGE_125_DEG_SEC
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_range(
+u8 *v_range_u8);
+/*!
+ * @brief This API set the range
+ * of gyro from the register 0x43 bit 0 to 2
+ *
+ * @param v_range_u8 : The value of gyro range
+ * value | range
+ * ----------|-------------------------------
+ * 0x00 | BMI160_GYRO_RANGE_2000_DEG_SEC
+ * 0x01 | BMI160_GYRO_RANGE_1000_DEG_SEC
+ * 0x02 | BMI160_GYRO_RANGE_500_DEG_SEC
+ * 0x03 | BMI160_GYRO_RANGE_250_DEG_SEC
+ * 0x04 | BMI160_GYRO_RANGE_125_DEG_SEC
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_range(
+u8 v_range_u8);
+/**************************************************/
+/**\name FUNCTION FOR MAG CONFIGURATIONS */
+/*************************************************/
+/*!
+ * @brief This API is used to get the
+ * output data rate of magnetometer from the register 0x44 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rat_u8e : The value of mag output data rate
+ * value | mag output data rate
+ * ---------|---------------------------
+ * 0x00 |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 |BMI160_MAG_OUTPUT_DATA_RATE_0_78HZ
+ * 0x02 |BMI160_MAG_OUTPUT_DATA_RATE_1_56HZ
+ * 0x03 |BMI160_MAG_OUTPUT_DATA_RATE_3_12HZ
+ * 0x04 |BMI160_MAG_OUTPUT_DATA_RATE_6_25HZ
+ * 0x05 |BMI160_MAG_OUTPUT_DATA_RATE_12_5HZ
+ * 0x06 |BMI160_MAG_OUTPUT_DATA_RATE_25HZ
+ * 0x07 |BMI160_MAG_OUTPUT_DATA_RATE_50HZ
+ * 0x08 |BMI160_MAG_OUTPUT_DATA_RATE_100HZ
+ * 0x09 |BMI160_MAG_OUTPUT_DATA_RATE_200HZ
+ * 0x0A |BMI160_MAG_OUTPUT_DATA_RATE_400HZ
+ * 0x0B |BMI160_MAG_OUTPUT_DATA_RATE_800HZ
+ * 0x0C |BMI160_MAG_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED0
+ * 0x0E |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED1
+ * 0x0F |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED2
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_output_data_rate(u8 *odr);
+/*!
+ * @brief This API is used to set the
+ * output data rate of magnetometer from the register 0x44 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rat_u8e : The value of mag output data rate
+ * value | mag output data rate
+ * ---------|---------------------------
+ * 0x00 |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 |BMI160_MAG_OUTPUT_DATA_RATE_0_78HZ
+ * 0x02 |BMI160_MAG_OUTPUT_DATA_RATE_1_56HZ
+ * 0x03 |BMI160_MAG_OUTPUT_DATA_RATE_3_12HZ
+ * 0x04 |BMI160_MAG_OUTPUT_DATA_RATE_6_25HZ
+ * 0x05 |BMI160_MAG_OUTPUT_DATA_RATE_12_5HZ
+ * 0x06 |BMI160_MAG_OUTPUT_DATA_RATE_25HZ
+ * 0x07 |BMI160_MAG_OUTPUT_DATA_RATE_50HZ
+ * 0x08 |BMI160_MAG_OUTPUT_DATA_RATE_100HZ
+ * 0x09 |BMI160_MAG_OUTPUT_DATA_RATE_200HZ
+ * 0x0A |BMI160_MAG_OUTPUT_DATA_RATE_400HZ
+ * 0x0B |BMI160_MAG_OUTPUT_DATA_RATE_800HZ
+ * 0x0C |BMI160_MAG_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED0
+ * 0x0E |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED1
+ * 0x0F |BMI160_MAG_OUTPUT_DATA_RATE_RESERVED2
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_output_data_rate(u8 odr);
+/**************************************************/
+/**\name FUNCTION FOR FIFO CONFIGURATIONS */
+/*************************************************/
+ /*!
+ * @brief This API is used to read Down sampling
+ * for gyro (2**downs_gyro) in the register 0x45 bit 0 to 2
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_gyro_u8 :The value of gyro fifo down
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_down_gyro(
+u8 *v_fifo_down_gyro_u8);
+ /*!
+ * @brief This API is used to set Down sampling
+ * for gyro (2**downs_gyro) in the register 0x45 bit 0 to 2
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_gyro_u8 :The value of gyro fifo down
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_down_gyro(
+u8 v_fifo_down_gyro_u8);
+/*!
+ * @brief This API is used to read gyro fifo filter data
+ * from the register 0x45 bit 3
+ *
+ *
+ *
+ * @param v_gyro_fifo_filter_data_u8 :The value of gyro filter data
+ * value | gyro_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_fifo_filter_data(
+u8 *v_gyro_fifo_filter_data_u8);
+/*!
+ * @brief This API is used to set gyro fifo filter data
+ * from the register 0x45 bit 3
+ *
+ *
+ *
+ * @param v_gyro_fifo_filter_data_u8 :The value of gyro filter data
+ * value | gyro_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_fifo_filter_data(
+u8 v_gyro_fifo_filter_data_u8);
+/*!
+ * @brief This API is used to read Down sampling
+ * for accel (2*downs_accel) from the register 0x45 bit 4 to 6
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_u8 :The value of accel fifo down
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_down_accel(
+u8 *v_fifo_down_u8);
+ /*!
+ * @brief This API is used to set Down sampling
+ * for accel (2*downs_accel) from the register 0x45 bit 4 to 6
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_u8 :The value of accel fifo down
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_down_accel(
+u8 v_fifo_down_u8);
+/*!
+ * @brief This API is used to read accel fifo filter data
+ * from the register 0x45 bit 7
+ *
+ *
+ *
+ * @param v_accel_fifo_filter_u8 :The value of accel filter data
+ * value | accel_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_fifo_filter_data(
+u8 *v_accel_fifo_filter_u8);
+/*!
+ * @brief This API is used to set accel fifo filter data
+ * from the register 0x45 bit 7
+ *
+ *
+ *
+ * @param v_accel_fifo_filter_u8 :The value of accel filter data
+ * value | accel_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_fifo_filter_data(
+u8 v_accel_fifo_filter_u8);
+/**************************************************/
+/**\name FUNCTION FOR FIFO WATER MARK ENABLE */
+/*************************************************/
+/*!
+ * @brief This API is used to Trigger an interrupt
+ * when FIFO contains water mark level from the register 0x46 bit 0 to 7
+ *
+ *
+ *
+ * @param v_fifo_wm_u8 : The value of fifo water mark level
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_wm(
+u8 *v_fifo_wm_u8);
+/*!
+ * @brief This API is used to Trigger an interrupt
+ * when FIFO contains water mark level from the register 0x46 bit 0 to 7
+ *
+ *
+ *
+ * @param v_fifo_wm_u8 : The value of fifo water mark level
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_wm(
+u8 v_fifo_wm_u8);
+/**************************************************/
+/**\name FUNCTION FOR FIFO CONFIGURATIONS */
+/*************************************************/
+/*!
+ * @brief This API reads fifo sensor time
+ * frame after the last valid data frame form the register 0x47 bit 1
+ *
+ *
+ *
+ *
+ * @param v_fifo_time_enable_u8 : The value of sensor time
+ * value | fifo sensor time
+ * ------------|-------------------------
+ * 0x00 | do not return sensortime frame
+ * 0x01 | return sensortime frame
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_time_enable(
+u8 *v_fifo_time_enable_u8);
+/*!
+ * @brief This API set fifo sensor time
+ * frame after the last valid data frame form the register 0x47 bit 1
+ *
+ *
+ *
+ *
+ * @param v_fifo_time_enable_u8 : The value of sensor time
+ * value | fifo sensor time
+ * ------------|-------------------------
+ * 0x00 | do not return sensortime frame
+ * 0x01 | return sensortime frame
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_time_enable(
+u8 v_fifo_time_enable_u8);
+/*!
+ * @brief This API reads FIFO tag interrupt2 enable status
+ * from the resister 0x47 bit 2
+ *
+ * @param v_fifo_tag_intr2_u8 : The value of fifo tag interrupt
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_tag_intr2_enable(
+u8 *v_fifo_tag_intr2_u8);
+/*!
+ * @brief This API set FIFO tag interrupt2 enable status
+ * from the resister 0x47 bit 2
+ *
+ * @param v_fifo_tag_intr2_u8 : The value of fifo tag interrupt
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_tag_intr2_enable(
+u8 v_fifo_tag_intr2_u8);
+/*!
+ * @brief This API get FIFO tag interrupt1 enable status
+ * from the resister 0x47 bit 3
+ *
+ * @param v_fifo_tag_intr1_u8 :The value of fifo tag interrupt1
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_tag_intr1_enable(
+u8 *v_fifo_tag_intr1_u8);
+/*!
+ * @brief This API set FIFO tag interrupt1 enable status
+ * from the resister 0x47 bit 3
+ *
+ * @param v_fifo_tag_intr1_u8 :The value of fifo tag interrupt1
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_tag_intr1_enable(
+u8 v_fifo_tag_intr1_u8);
+/*!
+ * @brief This API reads FIFO frame
+ * header enable from the register 0x47 bit 4
+ *
+ * @param v_fifo_header_u8 :The value of fifo header
+ * value | fifo header
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_header_enable(
+u8 *v_fifo_header_u8);
+/*!
+ * @brief This API set FIFO frame
+ * header enable from the register 0x47 bit 4
+ *
+ * @param v_fifo_header_u8 :The value of fifo header
+ * value | fifo header
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_header_enable(
+u8 v_fifo_header_u8);
+/*!
+ * @brief This API is used to read stored
+ * magnetometer data in FIFO (all 3 axes) from the register 0x47 bit 5
+ *
+ * @param v_fifo_mag_u8 : The value of fifo mag enble
+ * value | fifo mag
+ * ----------|-------------------
+ * 0x00 | no magnetometer data is stored
+ * 0x01 | magnetometer data is stored
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_mag_enable(
+u8 *v_fifo_mag_u8);
+/*!
+ * @brief This API is used to set stored
+ * magnetometer data in FIFO (all 3 axes) from the register 0x47 bit 5
+ *
+ * @param v_fifo_mag_u8 : The value of fifo mag enble
+ * value | fifo mag
+ * ----------|-------------------
+ * 0x00 | no magnetometer data is stored
+ * 0x01 | magnetometer data is stored
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_mag_enable(
+u8 v_fifo_mag_u8);
+/*!
+ * @brief This API is used to read stored
+ * accel data in FIFO (all 3 axes) from the register 0x47 bit 6
+ *
+ * @param v_fifo_accel_u8 : The value of fifo accel enble
+ * value | fifo accel
+ * ----------|-------------------
+ * 0x00 | no accel data is stored
+ * 0x01 | accel data is stored
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_accel_enable(
+u8 *v_fifo_accel_u8);
+/*!
+ * @brief This API is used to set stored
+ * accel data in FIFO (all 3 axes) from the register 0x47 bit 6
+ *
+ * @param v_fifo_accel_u8 : The value of fifo accel enble
+ * value | fifo accel
+ * ----------|-------------------
+ * 0x00 | no accel data is stored
+ * 0x01 | accel data is stored
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_accel_enable(
+u8 v_fifo_accel_u8);
+/*!
+ * @brief This API is used to read stored
+ * gyro data in FIFO (all 3 axes) from the resister 0x47 bit 7
+ *
+ *
+ * @param v_fifo_gyro_u8 : The value of fifo gyro enble
+ * value | fifo gyro
+ * ----------|-------------------
+ * 0x00 | no gyro data is stored
+ * 0x01 | gyro data is stored
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_fifo_gyro_enable(
+u8 *v_fifo_gyro_u8);
+/*!
+ * @brief This API is used to set stored
+ * gyro data in FIFO (all 3 axes) from the resister 0x47 bit 7
+ *
+ *
+ * @param v_fifo_gyro_u8 : The value of fifo gyro enble
+ * value | fifo gyro
+ * ----------|-------------------
+ * 0x00 | no gyro data is stored
+ * 0x01 | gyro data is stored
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_fifo_gyro_enable(
+u8 v_fifo_gyro_u8);
+/***************************************************************/
+/**\name FUNCTION FOR MAG I2C ADDRESS SELECTION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * I2C device address of auxiliary mag from the register 0x4B bit 1 to 7
+ *
+ *
+ *
+ *
+ * @param v_i2c_device_addr_u8 : The value of mag I2C device address
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_i2c_device_addr(
+u8 *v_i2c_device_addr_u8);
+/*!
+ * @brief This API is used to set
+ * I2C device address of auxiliary mag from the register 0x4B bit 1 to 7
+ *
+ *
+ *
+ *
+ * @param v_i2c_device_addr_u8 : The value of mag I2C device address
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_i2c_device_addr(
+u8 v_i2c_device_addr_u8);
+/*!
+ * @brief This API is used to read
+ * Burst data length (1,2,6,8 byte) from the register 0x4C bit 0 to 1
+ *
+ *
+ *
+ *
+ * @param v_mag_burst_u8 : The data of mag burst read lenth
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_burst(
+u8 *v_mag_burst_u8);
+/*!
+ * @brief This API is used to set
+ * Burst data length (1,2,6,8 byte) from the register 0x4C bit 0 to 1
+ *
+ *
+ *
+ *
+ * @param v_mag_burst_u8 : The data of mag burst read lenth
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_burst(
+u8 v_mag_burst_u8);
+/***************************************************************/
+/**\name FUNCTION FOR MAG OFFSET */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * trigger-readout offset in units of 2.5 ms. If set to zero,
+ * the offset is maximum, i.e. after readout a trigger
+ * is issued immediately. from the register 0x4C bit 2 to 5
+ *
+ *
+ *
+ *
+ * @param v_mag_offset_u8 : The value of mag offset
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_offset(
+u8 *v_mag_offset_u8);
+/*!
+ * @brief This API is used to set
+ * trigger-readout offset in units of 2.5 ms. If set to zero,
+ * the offset is maximum, i.e. after readout a trigger
+ * is issued immediately. from the register 0x4C bit 2 to 5
+ *
+ *
+ *
+ *
+ * @param v_mag_offset_u8 : The value of mag offset
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_offset(
+u8 v_mag_offset_u8);
+/***************************************************************/
+/**\name FUNCTION FOR MAG MANUAL/AUTO MODE SELECTION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * Enable register access on MAG_IF[2] or MAG_IF[3] writes.
+ * This implies that the DATA registers are not updated with
+ * magnetometer values. Accessing magnetometer requires
+ * the magnetometer in normal mode in PMU_STATUS.
+ * from the register 0x4C bit 7
+ *
+ *
+ *
+ * @param v_mag_manual_u8 : The value of mag manual enable
+ * value | mag manual
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_manual_enable(
+u8 *v_mag_manual_u8);
+/*!
+ * @brief This API is used to set
+ * Enable register access on MAG_IF[2] or MAG_IF[3] writes.
+ * This implies that the DATA registers are not updated with
+ * magnetometer values. Accessing magnetometer requires
+ * the magnetometer in normal mode in PMU_STATUS.
+ * from the register 0x4C bit 7
+ *
+ *
+ *
+ * @param v_mag_manual_u8 : The value of mag manual enable
+ * value | mag manual
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_manual_enable(
+u8 v_mag_manual_u8);
+/***************************************************************/
+/**\name FUNCTIONS FOR MAG READ, WRITE AND WRITE DATA ADDRESS */
+/***************************************************************/
+/*!
+ * @brief This API is used to read data
+ * magnetometer address to read from the register 0x4D bit 0 to 7
+ * @brief It used to provide mag read address of auxiliary mag
+ *
+ *
+ *
+ *
+ * @param v_mag_read_addr_u8 : The value of address need to be read
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_read_addr(
+u8 *v_mag_read_addr_u8);
+/*!
+ * @brief This API is used to set
+ * magnetometer write address from the register 0x4D bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_read_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_read_addr(
+u8 v_mag_read_addr_u8);
+/*!
+ * @brief This API is used to read
+ * magnetometer write address from the register 0x4E bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_write_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_write_addr(
+u8 *v_mag_write_addr_u8);
+/*!
+ * @brief This API is used to set
+ * magnetometer write address from the register 0x4E bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_write_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_write_addr(
+u8 v_mag_write_addr_u8);
+/*!
+ * @brief This API is used to read magnetometer write data
+ * form the resister 0x4F bit 0 to 7
+ * @brief This writes the data will be wrote to mag
+ *
+ *
+ *
+ * @param v_mag_write_data_u8: The value of mag data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_mag_write_data(
+u8 *v_mag_write_data_u8);
+/*!
+ * @brief This API is used to set magnetometer write data
+ * form the resister 0x4F bit 0 to 7
+ * @brief This writes the data will be wrote to mag
+ *
+ *
+ *
+ * @param v_mag_write_data_u8: The value of mag data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_mag_write_data(
+u8 v_mag_write_data_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT ENABLE OF
+ANY-MOTION XYZ, DOUBLE AND SINGLE TAP, ORIENT AND FLAT */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * interrupt enable from the register 0x50 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_ANY_MOTION_X_ENABLE
+ * 1 | BMI160_ANY_MOTION_Y_ENABLE
+ * 2 | BMI160_ANY_MOTION_Z_ENABLE
+ * 3 | BMI160_DOUBLE_TAP_ENABLE
+ * 4 | BMI160_SINGLE_TAP_ENABLE
+ * 5 | BMI160_ORIENT_ENABLE
+ * 6 | BMI160_FLAT_ENABLE
+ *
+ * @param v_intr_enable_zero_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_enable_0(
+u8 enable, u8 *v_intr_enable_zero_u8);
+/*!
+ * @brief This API is used to set
+ * interrupt enable from the register 0x50 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_ANY_MOTION_X_ENABLE
+ * 1 | BMI160_ANY_MOTION_Y_ENABLE
+ * 2 | BMI160_ANY_MOTION_Z_ENABLE
+ * 3 | BMI160_DOUBLE_TAP_ENABLE
+ * 4 | BMI160_SINGLE_TAP_ENABLE
+ * 5 | BMI160_ORIENT_ENABLE
+ * 6 | BMI160_FLAT_ENABLE
+ *
+ * @param v_intr_enable_zero_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_enable_0(
+u8 enable, u8 v_intr_enable_zero_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT ENABLE OF
+HIGH_G XYZ, LOW_G, DATA READY, FIFO FULL AND FIFO WATER MARK */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * interrupt enable byte1 from the register 0x51 bit 0 to 6
+ * @brief It read the high_g_x,high_g_y,high_g_z,low_g_enable
+ * data ready, fifo full and fifo water mark.
+ *
+ *
+ *
+ * @param v_enable_u8 : The value of interrupt enable
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_HIGH_G_X_ENABLE
+ * 1 | BMI160_HIGH_G_Y_ENABLE
+ * 2 | BMI160_HIGH_G_Z_ENABLE
+ * 3 | BMI160_LOW_G_ENABLE
+ * 4 | BMI160_DATA_RDY_ENABLE
+ * 5 | BMI160_FIFO_FULL_ENABLE
+ * 6 | BMI160_FIFO_WM_ENABLE
+ *
+ * @param v_intr_enable_1_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_enable_1(
+u8 enable, u8 *v_intr_enable_1_u8);
+/*!
+ * @brief This API is used to set
+ * interrupt enable byte1 from the register 0x51 bit 0 to 6
+ * @brief It read the high_g_x,high_g_y,high_g_z,low_g_enable
+ * data ready, fifo full and fifo water mark.
+ *
+ *
+ *
+ * @param v_enable_u8 : The value of interrupt enable
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_HIGH_G_X_ENABLE
+ * 1 | BMI160_HIGH_G_Y_ENABLE
+ * 2 | BMI160_HIGH_G_Z_ENABLE
+ * 3 | BMI160_LOW_G_ENABLE
+ * 4 | BMI160_DATA_RDY_ENABLE
+ * 5 | BMI160_FIFO_FULL_ENABLE
+ * 6 | BMI160_FIFO_WM_ENABLE
+ *
+ * @param v_intr_enable_1_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_enable_1(
+u8 enable, u8 v_intr_enable_1_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT ENABLE OF
+NO MOTION XYZ */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * interrupt enable byte2 from the register bit 0x52 bit 0 to 3
+ * @brief It reads no motion x,y and z
+ *
+ *
+ *
+ * @param v_enable_u8: The value of interrupt enable
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_NOMOTION_X_ENABLE
+ * 1 | BMI160_NOMOTION_Y_ENABLE
+ * 2 | BMI160_NOMOTION_Z_ENABLE
+ *
+ * @param v_intr_enable_2_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_enable_2(
+u8 enable, u8 *v_intr_enable_2_u8);
+/*!
+ * @brief This API is used to set
+ * interrupt enable byte2 from the register bit 0x52 bit 0 to 3
+ * @brief It reads no motion x,y and z
+ *
+ *
+ *
+ * @param v_enable_u8: The value of interrupt enable
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_NOMOTION_X_ENABLE
+ * 1 | BMI160_NOMOTION_Y_ENABLE
+ * 2 | BMI160_NOMOTION_Z_ENABLE
+ *
+ * @param v_intr_enable_2_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_enable_2(
+u8 enable, u8 v_intr_enable_2_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT ENABLE OF
+ STEP DETECTOR */
+/***************************************************************/
+ /*!
+ * @brief This API is used to read
+ * interrupt enable step detector interrupt from
+ * the register bit 0x52 bit 3
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The value of step detector interrupt enable
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_step_detector_enable(
+u8 *v_step_intr_u8);
+ /*!
+ * @brief This API is used to set
+ * interrupt enable step detector interrupt from
+ * the register bit 0x52 bit 3
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The value of step detector interrupt enable
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_step_detector_enable(
+u8 v_step_intr_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT CONTROL */
+/***************************************************************/
+/*!
+ * @brief Configure trigger condition of interrupt1
+ * and interrupt2 pin from the register 0x53
+ * @brief interrupt1 - bit 0
+ * @brief interrupt2 - bit 4
+ *
+ * @param v_channel_u8: The value of edge trigger selection
+ * v_channel_u8 | Edge trigger
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_EDGE_CTRL
+ * 1 | BMI160_INTR2_EDGE_CTRL
+ *
+ * @param v_intr_edge_ctrl_u8 : The value of edge trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_EDGE
+ * 0x00 | BMI160_LEVEL
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_edge_ctrl(
+u8 v_channel_u8, u8 *v_intr_edge_ctrl_u8);
+/*!
+ * @brief Configure trigger condition of interrupt1
+ * and interrupt2 pin from the register 0x53
+ * @brief interrupt1 - bit 0
+ * @brief interrupt2 - bit 4
+ *
+ * @param v_channel_u8: The value of edge trigger selection
+ * v_channel_u8 | Edge trigger
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_EDGE_CTRL
+ * 1 | BMI160_INTR2_EDGE_CTRL
+ *
+ * @param v_intr_edge_ctrl_u8 : The value of edge trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_EDGE
+ * 0x00 | BMI160_LEVEL
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_edge_ctrl(
+u8 v_channel_u8, u8 v_intr_edge_ctrl_u8);
+/*!
+ * @brief API used for get the Configure level condition of interrupt1
+ * and interrupt2 pin form the register 0x53
+ * @brief interrupt1 - bit 1
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of level condition selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_LEVEL
+ * 1 | BMI160_INTR2_LEVEL
+ *
+ * @param v_intr_level_u8 : The value of level of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_LEVEL_HIGH
+ * 0x00 | BMI160_LEVEL_LOW
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_level(
+u8 v_channel_u8, u8 *v_intr_level_u8);
+/*!
+ * @brief API used for set the Configure level condition of interrupt1
+ * and interrupt2 pin form the register 0x53
+ * @brief interrupt1 - bit 1
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of level condition selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_LEVEL
+ * 1 | BMI160_INTR2_LEVEL
+ *
+ * @param v_intr_level_u8 : The value of level of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_LEVEL_HIGH
+ * 0x00 | BMI160_LEVEL_LOW
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_level(
+u8 v_channel_u8, u8 v_intr_level_u8);
+/*!
+ * @brief API used to get configured output enable of interrupt1
+ * and interrupt2 from the register 0x53
+ * @brief interrupt1 - bit 2
+ * @brief interrupt2 - bit 6
+ *
+ *
+ * @param v_channel_u8: The value of output type enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_OUTPUT_TYPE
+ * 1 | BMI160_INTR2_OUTPUT_TYPE
+ *
+ * @param v_intr_output_type_u8 :
+ * The value of output type of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_OPEN_DRAIN
+ * 0x00 | BMI160_PUSH_PULL
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_output_type(
+u8 v_channel_u8, u8 *v_intr_output_type_u8);
+/*!
+ * @brief API used to set output enable of interrupt1
+ * and interrupt2 from the register 0x53
+ * @brief interrupt1 - bit 2
+ * @brief interrupt2 - bit 6
+ *
+ *
+ * @param v_channel_u8: The value of output type enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_OUTPUT_TYPE
+ * 1 | BMI160_INTR2_OUTPUT_TYPE
+ *
+ * @param v_intr_output_type_u8 :
+ * The value of output type of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_OPEN_DRAIN
+ * 0x00 | BMI160_PUSH_PULL
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_output_type(
+u8 v_channel_u8, u8 v_intr_output_type_u8);
+ /*!
+ * @brief API used to get the Output enable for interrupt1
+ * and interrupt1 pin from the register 0x53
+ * @brief interrupt1 - bit 3
+ * @brief interrupt2 - bit 7
+ *
+ * @param v_channel_u8: The value of output enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_OUTPUT_TYPE
+ * 1 | BMI160_INTR2_OUTPUT_TYPE
+ *
+ * @param v_output_enable_u8 :
+ * The value of output enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_INPUT
+ * 0x00 | BMI160_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_output_enable(
+u8 v_channel_u8, u8 *v_output_enable_u8);
+ /*!
+ * @brief API used to set the Output enable for interrupt1
+ * and interrupt1 pin from the register 0x53
+ * @brief interrupt1 - bit 3
+ * @brief interrupt2 - bit 7
+ *
+ * @param v_channel_u8: The value of output enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_OUTPUT_TYPE
+ * 1 | BMI160_INTR2_OUTPUT_TYPE
+ *
+ * @param v_output_enable_u8 :
+ * The value of output enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_INPUT
+ * 0x00 | BMI160_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_output_enable(
+u8 v_channel_u8, u8 v_output_enable_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT LATCH INTERRUPT */
+/***************************************************************/
+/*!
+* @brief This API is used to get the latch duration
+* from the register 0x54 bit 0 to 3
+* @brief This latch selection is not applicable for data ready,
+* orientation and flat interrupts.
+*
+*
+*
+* @param v_latch_intr_u8 : The value of latch duration
+* Latch Duration | value
+* --------------------------------------|------------------
+* BMI160_LATCH_DUR_NONE | 0x00
+* BMI160_LATCH_DUR_312_5_MICRO_SEC | 0x01
+* BMI160_LATCH_DUR_625_MICRO_SEC | 0x02
+* BMI160_LATCH_DUR_1_25_MILLI_SEC | 0x03
+* BMI160_LATCH_DUR_2_5_MILLI_SEC | 0x04
+* BMI160_LATCH_DUR_5_MILLI_SEC | 0x05
+* BMI160_LATCH_DUR_10_MILLI_SEC | 0x06
+* BMI160_LATCH_DUR_20_MILLI_SEC | 0x07
+* BMI160_LATCH_DUR_40_MILLI_SEC | 0x08
+* BMI160_LATCH_DUR_80_MILLI_SEC | 0x09
+* BMI160_LATCH_DUR_160_MILLI_SEC | 0x0A
+* BMI160_LATCH_DUR_320_MILLI_SEC | 0x0B
+* BMI160_LATCH_DUR_640_MILLI_SEC | 0x0C
+* BMI160_LATCH_DUR_1_28_SEC | 0x0D
+* BMI160_LATCH_DUR_2_56_SEC | 0x0E
+* BMI160_LATCHED | 0x0F
+*
+*
+*
+* @return results of bus communication function
+* @retval 0 -> Success
+* @retval -1 -> Error
+*
+*
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_latch_intr(
+u8 *v_latch_intr_u8);
+/*!
+* @brief This API is used to set the latch duration
+* from the register 0x54 bit 0 to 3
+* @brief This latch selection is not applicable for data ready,
+* orientation and flat interrupts.
+*
+*
+*
+* @param v_latch_intr_u8 : The value of latch duration
+* Latch Duration | value
+* --------------------------------------|------------------
+* BMI160_LATCH_DUR_NONE | 0x00
+* BMI160_LATCH_DUR_312_5_MICRO_SEC | 0x01
+* BMI160_LATCH_DUR_625_MICRO_SEC | 0x02
+* BMI160_LATCH_DUR_1_25_MILLI_SEC | 0x03
+* BMI160_LATCH_DUR_2_5_MILLI_SEC | 0x04
+* BMI160_LATCH_DUR_5_MILLI_SEC | 0x05
+* BMI160_LATCH_DUR_10_MILLI_SEC | 0x06
+* BMI160_LATCH_DUR_20_MILLI_SEC | 0x07
+* BMI160_LATCH_DUR_40_MILLI_SEC | 0x08
+* BMI160_LATCH_DUR_80_MILLI_SEC | 0x09
+* BMI160_LATCH_DUR_160_MILLI_SEC | 0x0A
+* BMI160_LATCH_DUR_320_MILLI_SEC | 0x0B
+* BMI160_LATCH_DUR_640_MILLI_SEC | 0x0C
+* BMI160_LATCH_DUR_1_28_SEC | 0x0D
+* BMI160_LATCH_DUR_2_56_SEC | 0x0E
+* BMI160_LATCHED | 0x0F
+*
+*
+*
+* @return results of bus communication function
+* @retval 0 -> Success
+* @retval -1 -> Error
+*
+*
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_latch_intr(
+u8 v_latch_intr_u8);
+/*!
+ * @brief API used to get input enable for interrupt1
+ * and interrupt2 pin from the register 0x54
+ * @brief interrupt1 - bit 4
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of input enable selection
+ * v_channel_u8 | input selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_INPUT_ENABLE
+ * 1 | BMI160_INTR2_INPUT_ENABLE
+ *
+ * @param v_input_en_u8 :
+ * The value of input enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_INPUT
+ * 0x00 | BMI160_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_input_enable(
+u8 v_channel_u8, u8 *v_input_en_u8);
+/*!
+ * @brief API used to set input enable for interrupt1
+ * and interrupt2 pin from the register 0x54
+ * @brief interrupt1 - bit 4
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of input enable selection
+ * v_channel_u8 | input selection
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_INPUT_ENABLE
+ * 1 | BMI160_INTR2_INPUT_ENABLE
+ *
+ * @param v_input_en_u8 :
+ * The value of input enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | BMI160_INPUT
+ * 0x00 | BMI160_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_input_enable(
+u8 v_channel_u8, u8 v_input_en_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT1 AND INTERRUPT2 MAPPING */
+/***************************************************************/
+ /*!
+ * @brief reads the Low g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 0 in the register 0x55
+ * @brief interrupt2 bit 0 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of low_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_LOW_G
+ * 1 | BMI160_INTR2_MAP_LOW_G
+ *
+ * @param v_intr_low_g_u8 : The value of low_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g(
+u8 v_channel_u8, u8 *v_intr_low_g_u8);
+ /*!
+ * @brief set the Low g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 0 in the register 0x55
+ * @brief interrupt2 bit 0 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of low_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_LOW_G
+ * 1 | BMI160_INTR2_MAP_LOW_G
+ *
+ * @param v_intr_low_g_u8 : The value of low_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g(
+u8 v_channel_u8, u8 v_intr_low_g_u8);
+/*!
+ * @brief Reads the HIGH g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 1 in the register 0x55
+ * @brief interrupt2 bit 1 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of high_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_HIGH_G
+ * 1 | BMI160_INTR2_MAP_HIGH_G
+ *
+ * @param v_intr_high_g_u8 : The value of high_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_high_g(
+u8 v_channel_u8, u8 *v_intr_high_g_u8);
+/*!
+ * @brief Write the HIGH g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 1 in the register 0x55
+ * @brief interrupt2 bit 1 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of high_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_HIGH_G
+ * 1 | BMI160_INTR2_MAP_HIGH_G
+ *
+ * @param v_intr_high_g_u8 : The value of high_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_high_g(
+u8 v_channel_u8, u8 v_intr_high_g_u8);
+/*!
+ * @brief Reads the Any motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 2 in the register 0x55
+ * @brief interrupt2 bit 2 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of any motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_ANY_MOTION
+ * 1 | BMI160_INTR2_MAP_ANY_MOTION
+ *
+ * @param v_intr_any_motion_u8 : The value of any motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_any_motion(
+u8 v_channel_u8, u8 *v_intr_any_motion_u8);
+/*!
+ * @brief Write the Any motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 2 in the register 0x55
+ * @brief interrupt2 bit 2 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of any motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_ANY_MOTION
+ * 1 | BMI160_INTR2_MAP_ANY_MOTION
+ *
+ * @param v_intr_any_motion_u8 : The value of any motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_any_motion(
+u8 v_channel_u8, u8 v_intr_any_motion_u8);
+/*!
+ * @brief Reads the No motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 3 in the register 0x55
+ * @brief interrupt2 bit 3 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of no motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_NOMO
+ * 1 | BMI160_INTR2_MAP_NOMO
+ *
+ * @param v_intr_nomotion_u8 : The value of no motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_nomotion(
+u8 v_channel_u8, u8 *v_intr_nomotion_u8);
+/*!
+ * @brief Write the No motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 3 in the register 0x55
+ * @brief interrupt2 bit 3 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of no motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_NOMO
+ * 1 | BMI160_INTR2_MAP_NOMO
+ *
+ * @param v_intr_nomotion_u8 : The value of no motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_nomotion(
+u8 v_channel_u8, u8 v_intr_nomotion_u8);
+/*!
+ * @brief Reads the Double Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 4 in the register 0x55
+ * @brief interrupt2 bit 4 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of double tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_DOUBLE_TAP
+ * 1 | BMI160_INTR2_MAP_DOUBLE_TAP
+ *
+ * @param v_intr_double_tap_u8 : The value of double tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_double_tap(
+u8 v_channel_u8, u8 *v_intr_double_tap_u8);
+/*!
+ * @brief Write the Double Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 4 in the register 0x55
+ * @brief interrupt2 bit 4 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of double tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_DOUBLE_TAP
+ * 1 | BMI160_INTR2_MAP_DOUBLE_TAP
+ *
+ * @param v_intr_double_tap_u8 : The value of double tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_double_tap(
+u8 v_channel_u8, u8 v_intr_double_tap_u8);
+/*!
+ * @brief Reads the Single Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 5 in the register 0x55
+ * @brief interrupt2 bit 5 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of single tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_SINGLE_TAP
+ * 1 | BMI160_INTR2_MAP_SINGLE_TAP
+ *
+ * @param v_intr_single_tap_u8 : The value of single tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_single_tap(
+u8 v_channel_u8, u8 *v_intr_single_tap_u8);
+/*!
+ * @brief Write the Single Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 5 in the register 0x55
+ * @brief interrupt2 bit 5 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of single tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_SINGLE_TAP
+ * 1 | BMI160_INTR2_MAP_SINGLE_TAP
+ *
+ * @param v_intr_single_tap_u8 : The value of single tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_single_tap(
+u8 v_channel_u8, u8 v_intr_single_tap_u8);
+/*!
+ * @brief Reads the Orient interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 6 in the register 0x55
+ * @brief interrupt2 bit 6 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of orient interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_ORIENT
+ * 1 | BMI160_INTR2_MAP_ORIENT
+ *
+ * @param v_intr_orient_u8 : The value of orient enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient(
+u8 v_channel_u8, u8 *v_intr_orient_u8);
+/*!
+ * @brief Write the Orient interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 6 in the register 0x55
+ * @brief interrupt2 bit 6 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of orient interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_ORIENT
+ * 1 | BMI160_INTR2_MAP_ORIENT
+ *
+ * @param v_intr_orient_u8 : The value of orient enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient(
+u8 v_channel_u8, u8 v_intr_orient_u8);
+ /*!
+ * @brief Reads the Flat interrupt
+ * mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 7 in the register 0x55
+ * @brief interrupt2 bit 7 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of flat interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FLAT
+ * 1 | BMI160_INTR2_MAP_FLAT
+ *
+ * @param v_intr_flat_u8 : The value of flat enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_flat(
+u8 v_channel_u8, u8 *v_intr_flat_u8);
+ /*!
+ * @brief Write the Flat interrupt
+ * mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 7 in the register 0x55
+ * @brief interrupt2 bit 7 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of flat interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FLAT
+ * 1 | BMI160_INTR2_MAP_FLAT
+ *
+ * @param v_intr_flat_u8 : The value of flat enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_flat(
+u8 v_channel_u8, u8 v_intr_flat_u8);
+/*!
+ * @brief Reads PMU trigger interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 0 and 4
+ * @brief interrupt1 bit 0 in the register 0x56
+ * @brief interrupt2 bit 4 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of pmu trigger selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_PMUTRIG
+ * 1 | BMI160_INTR2_MAP_PMUTRIG
+ *
+ * @param v_intr_pmu_trig_u8 : The value of pmu trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_pmu_trig(
+u8 v_channel_u8, u8 *v_intr_pmu_trig_u8);
+/*!
+ * @brief Write PMU trigger interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 0 and 4
+ * @brief interrupt1 bit 0 in the register 0x56
+ * @brief interrupt2 bit 4 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of pmu trigger selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_PMUTRIG
+ * 1 | BMI160_INTR2_MAP_PMUTRIG
+ *
+ * @param v_intr_pmu_trig_u8 : The value of pmu trigger enable
+ * value | trigger enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_pmu_trig(
+u8 v_channel_u8, u8 v_intr_pmu_trig_u8);
+/*!
+ * @brief Reads FIFO Full interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 5 and 1
+ * @brief interrupt1 bit 5 in the register 0x56
+ * @brief interrupt2 bit 1 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo full interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FIFO_FULL
+ * 1 | BMI160_INTR2_MAP_FIFO_FULL
+ *
+ * @param v_intr_fifo_full_u8 : The value of fifo full interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_fifo_full(
+u8 v_channel_u8, u8 *v_intr_fifo_full_u8);
+/*!
+ * @brief Write FIFO Full interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 5 and 1
+ * @brief interrupt1 bit 5 in the register 0x56
+ * @brief interrupt2 bit 1 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo full interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FIFO_FULL
+ * 1 | BMI160_INTR2_MAP_FIFO_FULL
+ *
+ * @param v_intr_fifo_full_u8 : The value of fifo full interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_fifo_full(
+u8 v_channel_u8, u8 v_intr_fifo_full_u8);
+/*!
+ * @brief Reads FIFO Watermark interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 6 and 2
+ * @brief interrupt1 bit 6 in the register 0x56
+ * @brief interrupt2 bit 2 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo Watermark interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FIFO_WM
+ * 1 | BMI160_INTR2_MAP_FIFO_WM
+ *
+ * @param v_intr_fifo_wm_u8 : The value of fifo Watermark interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_fifo_wm(
+u8 v_channel_u8, u8 *v_intr_fifo_wm_u8);
+/*!
+ * @brief Write FIFO Watermark interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 6 and 2
+ * @brief interrupt1 bit 6 in the register 0x56
+ * @brief interrupt2 bit 2 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo Watermark interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_FIFO_WM
+ * 1 | BMI160_INTR2_MAP_FIFO_WM
+ *
+ * @param v_intr_fifo_wm_u8 : The value of fifo Watermark interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_fifo_wm(
+u8 v_channel_u8, u8 v_intr_fifo_wm_u8);
+/*!
+ * @brief Reads Data Ready interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56
+ * @brief interrupt1 bit 7 in the register 0x56
+ * @brief interrupt2 bit 3 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of data ready interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_DATA_RDY
+ * 1 | BMI160_INTR2_MAP_DATA_RDY
+ *
+ * @param v_intr_data_rdy_u8 : The value of data ready interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_data_rdy(
+u8 v_channel_u8, u8 *v_intr_data_rdy_u8);
+/*!
+ * @brief Write Data Ready interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56
+ * @brief interrupt1 bit 7 in the register 0x56
+ * @brief interrupt2 bit 3 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of data ready interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | BMI160_INTR1_MAP_DATA_RDY
+ * 1 | BMI160_INTR2_MAP_DATA_RDY
+ *
+ * @param v_intr_data_rdy_u8 : The value of data ready interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | BMI160_ENABLE
+ * 0x00 | BMI160_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_data_rdy(
+u8 v_channel_u8, u8 v_intr_data_rdy_u8);
+/***************************************************************/
+/**\name FUNCTION FOR TAP SOURCE CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API reads data source for the interrupt
+ * engine for the single and double tap interrupts from the register
+ * 0x58 bit 3
+ *
+ *
+ * @param v_tap_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_source(
+u8 *v_tap_source_u8);
+ /*!
+ * @brief This API write data source for the interrupt
+ * engine for the single and double tap interrupts from the register
+ * 0x58 bit 3
+ *
+ *
+ * @param v_tap_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_source(
+u8 v_tap_source_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G AND HIGH_G SOURCE CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API Reads Data source for the
+ * interrupt engine for the low and high g interrupts
+ * from the register 0x58 bit 7
+ *
+ * @param v_low_high_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_high_source(
+u8 *v_low_high_source_u8);
+ /*!
+ * @brief This API write Data source for the
+ * interrupt engine for the low and high g interrupts
+ * from the register 0x58 bit 7
+ *
+ * @param v_low_high_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_high_source(
+u8 v_low_high_source_u8);
+/***************************************************************/
+/**\name FUNCTION FOR MOTION SOURCE CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API reads Data source for the
+ * interrupt engine for the nomotion and anymotion interrupts
+ * from the register 0x59 bit 7
+ *
+ * @param v_motion_source_u8 :
+ * The value of the any/no motion interrupt source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_motion_source(
+u8 *v_motion_source_u8);
+ /*!
+ * @brief This API write Data source for the
+ * interrupt engine for the nomotion and anymotion interrupts
+ * from the register 0x59 bit 7
+ *
+ * @param v_motion_source_u8 :
+ * The value of the any/no motion interrupt source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_motion_source(
+u8 v_motion_source_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G DURATION CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read the low_g duration from register
+ * 0x5A bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_durn_u8 : The value of low_g duration
+ *
+ * @note Low_g duration trigger trigger delay according to
+ * "(v_low_g_durn_u8 * 2.5)ms" in a range from 2.5ms to 640ms.
+ * the default corresponds delay is 20ms
+ * @note When low_g data source of interrupt is unfiltered
+ * the sensor must not be in low power mode
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g_durn(
+u8 *v_low_durn_u8);
+ /*!
+ * @brief This API is used to write the low_g duration from register
+ * 0x5A bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_durn_u8 : The value of low_g duration
+ *
+ * @note Low_g duration trigger trigger delay according to
+ * "(v_low_g_durn_u8 * 2.5)ms" in a range from 2.5ms to 640ms.
+ * the default corresponds delay is 20ms
+ * @note When low_g data source of interrupt is unfiltered
+ * the sensor must not be in low power mode
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g_durn(
+u8 v_low_durn_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G THRESH CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read Threshold
+ * definition for the low-g interrupt from the register 0x5B bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_thres_u8 : The value of low_g threshold
+ *
+ * @note Low_g interrupt trigger threshold according to
+ * (v_low_g_thres_u8 * 7.81)mg for v_low_g_thres_u8 > 0
+ * 3.91 mg for v_low_g_thres_u8 = 0
+ * The threshold range is form 3.91mg to 2.000mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g_thres(
+u8 *v_low_g_thres_u8);
+/*!
+ * @brief This API is used to write Threshold
+ * definition for the low-g interrupt from the register 0x5B bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_thres_u8 : The value of low_g threshold
+ *
+ * @note Low_g interrupt trigger threshold according to
+ * (v_low_g_thres_u8 * 7.81)mg for v_low_g_thres_u8 > 0
+ * 3.91 mg for v_low_g_thres_u8 = 0
+ * The threshold range is form 3.91mg to 2.000mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g_thres(
+u8 v_low_g_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G HYSTERESIS CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API Reads Low-g interrupt hysteresis
+ * from the register 0x5C bit 0 to 1
+ *
+ * @param v_low_hyst_u8 :The value of low_g hysteresis
+ *
+ * @note Low_g hysteresis calculated by v_low_hyst_u8*125 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g_hyst(
+u8 *v_low_hyst_u8);
+ /*!
+ * @brief This API write Low-g interrupt hysteresis
+ * from the register 0x5C bit 0 to 1
+ *
+ * @param v_low_hyst_u8 :The value of low_g hysteresis
+ *
+ * @note Low_g hysteresis calculated by v_low_hyst_u8*125 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g_hyst(
+u8 v_low_hyst_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G MODE CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API reads Low-g interrupt mode
+ * from the register 0x5C bit 2
+ *
+ * @param v_low_g_mode_u8 : The value of low_g mode
+ * Value | Description
+ * ----------|-----------------
+ * 0 | single-axis
+ * 1 | axis-summing
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_low_g_mode(
+u8 *v_low_g_mode_u8);
+/*!
+ * @brief This API write Low-g interrupt mode
+ * from the register 0x5C bit 2
+ *
+ * @param v_low_g_mode_u8 : The value of low_g mode
+ * Value | Description
+ * ----------|-----------------
+ * 0 | single-axis
+ * 1 | axis-summing
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_low_g_mode(
+u8 v_low_g_mode_u8);
+/***************************************************************/
+/**\name FUNCTION FOR HIGH_G HYST CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API reads High-g interrupt hysteresis
+ * from the register 0x5C bit 6 and 7
+ *
+ * @param v_high_g_hyst_u8 : The value of high hysteresis
+ *
+ * @note High_g hysteresis changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g hysteresis
+ * ----------------|---------------------
+ * 2g | high_hy*125 mg
+ * 4g | high_hy*250 mg
+ * 8g | high_hy*500 mg
+ * 16g | high_hy*1000 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_high_g_hyst(
+u8 *v_high_g_hyst_u8);
+/*!
+ * @brief This API write High-g interrupt hysteresis
+ * from the register 0x5C bit 6 and 7
+ *
+ * @param v_high_g_hyst_u8 : The value of high hysteresis
+ *
+ * @note High_g hysteresis changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g hysteresis
+ * ----------------|---------------------
+ * 2g | high_hy*125 mg
+ * 4g | high_hy*250 mg
+ * 8g | high_hy*500 mg
+ * 16g | high_hy*1000 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_high_g_hyst(
+u8 v_high_g_hyst_u8);
+/***************************************************************/
+/**\name FUNCTION FOR HIGH_G DURATION CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read Delay
+ * time definition for the high-g interrupt from the register
+ * 0x5D bit 0 to 7
+ *
+ *
+ *
+ * @param v_high_g_durn_u8 : The value of high duration
+ *
+ * @note High_g interrupt delay triggered according to
+ * v_high_g_durn_u8 * 2.5ms in a range from 2.5ms to 640ms
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_high_g_durn(
+u8 *v_high_g_durn_u8);
+/*!
+ * @brief This API is used to write Delay
+ * time definition for the high-g interrupt from the register
+ * 0x5D bit 0 to 7
+ *
+ *
+ *
+ * @param v_high_g_durn_u8 : The value of high duration
+ *
+ * @note High_g interrupt delay triggered according to
+ * v_high_g_durn_u8 * 2.5ms in a range from 2.5ms to 640ms
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_high_g_durn(
+u8 v_high_g_durn_u8);
+/***************************************************************/
+/**\name FUNCTION FOR HIGH_G THRESHOLD CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read Threshold
+ * definition for the high-g interrupt from the register 0x5E 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_high_g_thres_u8 : Pointer holding the value of Threshold
+ * @note High_g threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | v_high_g_thres_u8*7.81 mg
+ * 4g | v_high_g_thres_u8*15.63 mg
+ * 8g | v_high_g_thres_u8*31.25 mg
+ * 16g | v_high_g_thres_u8*62.5 mg
+ * @note when v_high_g_thres_u8 = 0
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | 3.91 mg
+ * 4g | 7.81 mg
+ * 8g | 15.63 mg
+ * 16g | 31.25 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_high_g_thres(
+u8 *v_high_g_thres_u8);
+/*!
+ * @brief This API is used to write Threshold
+ * definition for the high-g interrupt from the register 0x5E 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_high_g_thres_u8 : Pointer holding the value of Threshold
+ * @note High_g threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | v_high_g_thres_u8*7.81 mg
+ * 4g | v_high_g_thres_u8*15.63 mg
+ * 8g | v_high_g_thres_u8*31.25 mg
+ * 16g | v_high_g_thres_u8*62.5 mg
+ * @note when v_high_g_thres_u8 = 0
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | 3.91 mg
+ * 4g | 7.81 mg
+ * 8g | 15.63 mg
+ * 16g | 31.25 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_high_g_thres(
+u8 v_high_g_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ANY MOTION DURATION CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API reads any motion duration
+ * from the register 0x5F bit 0 and 1
+ *
+ * @param v_any_motion_durn_u8 : The value of any motion duration
+ *
+ * @note Any motion duration can be calculated by "v_any_motion_durn_u8 + 1"
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_any_motion_durn(
+u8 *v_any_motion_durn_u8);
+/*!
+ * @brief This API write any motion duration
+ * from the register 0x5F bit 0 and 1
+ *
+ * @param v_any_motion_durn_u8 : The value of any motion duration
+ *
+ * @note Any motion duration can be calculated by "v_any_motion_durn_u8 + 1"
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_any_motion_durn(
+u8 nomotion);
+/***************************************************************/
+/**\name FUNCTION FOR SLOW NO MOTION DURATION CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API read Slow/no-motion
+ * interrupt trigger delay duration from the register 0x5F bit 2 to 7
+ *
+ * @param v_slow_no_motion_u8 :The value of slow no motion duration
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * @note v_slow_no_motion_u8(5:4)=0b00 ->
+ * [v_slow_no_motion_u8(3:0) + 1] * 1.28s (1.28s-20.48s)
+ * @note v_slow_no_motion_u8(5:4)=1 ->
+ * [v_slow_no_motion_u8(3:0)+5] * 5.12s (25.6s-102.4s)
+ * @note v_slow_no_motion_u8(5)='1' ->
+ * [(v_slow_no_motion_u8:0)+11] * 10.24s (112.64s-430.08s);
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_slow_no_motion_durn(
+u8 *v_slow_no_motion_u8);
+ /*!
+ * @brief This API write Slow/no-motion
+ * interrupt trigger delay duration from the register 0x5F bit 2 to 7
+ *
+ * @param v_slow_no_motion_u8 :The value of slow no motion duration
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * @note v_slow_no_motion_u8(5:4)=0b00 ->
+ * [v_slow_no_motion_u8(3:0) + 1] * 1.28s (1.28s-20.48s)
+ * @note v_slow_no_motion_u8(5:4)=1 ->
+ * [v_slow_no_motion_u8(3:0)+5] * 5.12s (25.6s-102.4s)
+ * @note v_slow_no_motion_u8(5)='1' ->
+ * [(v_slow_no_motion_u8:0)+11] * 10.24s (112.64s-430.08s);
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_slow_no_motion_durn(
+u8 v_slow_no_motion_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ANY MOTION THRESHOLD CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read threshold
+ * definition for the any-motion interrupt
+ * from the register 0x60 bit 0 to 7
+ *
+ *
+ * @param v_any_motion_thres_u8 : The value of any motion threshold
+ *
+ * @note any motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | v_any_motion_thres_u8*3.91 mg
+ * 4g | v_any_motion_thres_u8*7.81 mg
+ * 8g | v_any_motion_thres_u8*15.63 mg
+ * 16g | v_any_motion_thres_u8*31.25 mg
+ * @note when v_any_motion_thres_u8 = 0
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_any_motion_thres(
+u8 *v_any_motion_thres_u8);
+/*!
+ * @brief This API is used to write threshold
+ * definition for the any-motion interrupt
+ * from the register 0x60 bit 0 to 7
+ *
+ *
+ * @param v_any_motion_thres_u8 : The value of any motion threshold
+ *
+ * @note any motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | v_any_motion_thres_u8*3.91 mg
+ * 4g | v_any_motion_thres_u8*7.81 mg
+ * 8g | v_any_motion_thres_u8*15.63 mg
+ * 16g | v_any_motion_thres_u8*31.25 mg
+ * @note when v_any_motion_thres_u8 = 0
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_any_motion_thres(
+u8 v_any_motion_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR SLO/NO MOTION THRESHOLD CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API is used to read threshold
+ * for the slow/no-motion interrupt
+ * from the register 0x61 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_slow_no_motion_thres_u8 : The value of slow no motion threshold
+ * @note slow no motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | v_slow_no_motion_thres_u8*3.91 mg
+ * 4g | v_slow_no_motion_thres_u8*7.81 mg
+ * 8g | v_slow_no_motion_thres_u8*15.63 mg
+ * 16g | v_slow_no_motion_thres_u8*31.25 mg
+ * @note when v_slow_no_motion_thres_u8 = 0
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_slow_no_motion_thres(
+u8 *v_slow_no_motion_thres_u8);
+ /*!
+ * @brief This API is used to write threshold
+ * for the slow/no-motion interrupt
+ * from the register 0x61 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_slow_no_motion_thres_u8 : The value of slow no motion threshold
+ * @note slow no motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | v_slow_no_motion_thres_u8*3.91 mg
+ * 4g | v_slow_no_motion_thres_u8*7.81 mg
+ * 8g | v_slow_no_motion_thres_u8*15.63 mg
+ * 16g | v_slow_no_motion_thres_u8*31.25 mg
+ * @note when v_slow_no_motion_thres_u8 = 0
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_slow_no_motion_thres(
+u8 v_slow_no_motion_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR SLO/NO MOTION SELECT CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API is used to read
+ * the slow/no-motion selection from the register 0x62 bit 0
+ *
+ *
+ *
+ *
+ * @param v_intr_slow_no_motion_select_u8 :
+ * The value of slow/no-motion select
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SLOW_MOTION
+ * 0x01 | NO_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_slow_no_motion_select(
+u8 *v_intr_slow_no_motion_select_u8);
+ /*!
+ * @brief This API is used to write
+ * the slow/no-motion selection from the register 0x62 bit 0
+ *
+ *
+ *
+ *
+ * @param v_intr_slow_no_motion_select_u8 :
+ * The value of slow/no-motion select
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SLOW_MOTION
+ * 0x01 | NO_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_slow_no_motion_select(
+u8 v_intr_slow_no_motion_select_u8);
+/***************************************************************/
+/**\name FUNCTION FOR SIGNIFICANT MOTION SELECT CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API is used to select
+ * the significant or any motion interrupt from the register 0x62 bit 1
+ *
+ *
+ *
+ *
+ * @param v_intr_significant_motion_select_u8 :
+ * the value of significant or any motion interrupt selection
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | ANY_MOTION
+ * 0x01 | SIGNIFICANT_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_significant_motion_select(
+u8 *int_sig_mot_sel);
+ /*!
+ * @brief This API is used to write, select
+ * the significant or any motion interrupt from the register 0x62 bit 1
+ *
+ *
+ *
+ *
+ * @param v_intr_significant_motion_select_u8 :
+ * the value of significant or any motion interrupt selection
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | ANY_MOTION
+ * 0x01 | SIGNIFICANT_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_significant_motion_select(
+u8 int_sig_mot_sel);
+ /*!
+ * @brief This API is used to read
+ * the significant skip time from the register 0x62 bit 2 and 3
+ *
+ *
+ *
+ *
+ * @param v_int_sig_mot_skip_u8 : the value of significant skip time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | skip time 1.5 seconds
+ * 0x01 | skip time 3 seconds
+ * 0x02 | skip time 6 seconds
+ * 0x03 | skip time 12 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_significant_motion_skip(
+u8 *v_int_sig_mot_skip_u8);
+ /*!
+ * @brief This API is used to write
+ * the significant skip time from the register 0x62 bit 2 and 3
+ *
+ *
+ *
+ *
+ * @param v_int_sig_mot_skip_u8 : the value of significant skip time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | skip time 1.5 seconds
+ * 0x01 | skip time 3 seconds
+ * 0x02 | skip time 6 seconds
+ * 0x03 | skip time 12 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_significant_motion_skip(
+u8 v_int_sig_mot_skip_u8);
+ /*!
+ * @brief This API is used to read
+ * the significant proof time from the register 0x62 bit 4 and 5
+ *
+ *
+ *
+ *
+ * @param v_significant_motion_proof_u8 :
+ * the value of significant proof time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | proof time 0.25 seconds
+ * 0x01 | proof time 0.5 seconds
+ * 0x02 | proof time 1 seconds
+ * 0x03 | proof time 2 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_significant_motion_proof(
+u8 *int_sig_mot_proof);
+ /*!
+ * @brief This API is used to write
+ * the significant proof time from the register 0x62 bit 4 and 5
+ *
+ *
+ *
+ *
+ * @param v_significant_motion_proof_u8 :
+ * the value of significant proof time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | proof time 0.25 seconds
+ * 0x01 | proof time 0.5 seconds
+ * 0x02 | proof time 1 seconds
+ * 0x03 | proof time 2 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_significant_motion_proof(
+u8 int_sig_mot_proof);
+/***************************************************************/
+/**\name FUNCTION FOR TAP DURATION CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API is used to get the tap duration
+ * from the register 0x63 bit 0 to 2
+ *
+ *
+ *
+ * @param v_tap_durn_u8 : The value of tap duration
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_DURN_50MS
+ * 0x01 | BMI160_TAP_DURN_100MS
+ * 0x03 | BMI160_TAP_DURN_150MS
+ * 0x04 | BMI160_TAP_DURN_200MS
+ * 0x05 | BMI160_TAP_DURN_250MS
+ * 0x06 | BMI160_TAP_DURN_375MS
+ * 0x07 | BMI160_TAP_DURN_700MS
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_durn(
+u8 *v_tap_durn_u8);
+/*!
+ * @brief This API is used to write the tap duration
+ * from the register 0x63 bit 0 to 2
+ *
+ *
+ *
+ * @param v_tap_durn_u8 : The value of tap duration
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_DURN_50MS
+ * 0x01 | BMI160_TAP_DURN_100MS
+ * 0x03 | BMI160_TAP_DURN_150MS
+ * 0x04 | BMI160_TAP_DURN_200MS
+ * 0x05 | BMI160_TAP_DURN_250MS
+ * 0x06 | BMI160_TAP_DURN_375MS
+ * 0x07 | BMI160_TAP_DURN_700MS
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_durn(
+u8 v_tap_durn_u8);
+/***************************************************************/
+/**\name FUNCTION FOR TAP SHOCK CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read the
+ * tap shock duration from the register 0x63 bit 2
+ *
+ * @param v_tap_shock_u8 :The value of tap shock
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_SHOCK_50MS
+ * 0x01 | BMI160_TAP_SHOCK_75MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_shock(
+u8 *v_tap_shock_u8);
+ /*!
+ * @brief This API write the
+ * tap shock duration from the register 0x63 bit 2
+ *
+ * @param v_tap_shock_u8 :The value of tap shock
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_SHOCK_50MS
+ * 0x01 | BMI160_TAP_SHOCK_75MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_shock(
+u8 v_tap_shock_u8);
+/***************************************************************/
+/**\name FUNCTION FOR TAP QUIET CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read
+ * tap quiet duration from the register 0x63 bit 7
+ *
+ *
+ * @param v_tap_quiet_u8 : The value of tap quiet
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_QUIET_30MS
+ * 0x01 | BMI160_TAP_QUIET_20MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_quiet(
+u8 *v_tap_quiet_u8);
+/*!
+ * @brief This API write
+ * tap quiet duration from the register 0x63 bit 7
+ *
+ *
+ * @param v_tap_quiet_u8 : The value of tap quiet
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | BMI160_TAP_QUIET_30MS
+ * 0x01 | BMI160_TAP_QUIET_20MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_quiet(
+u8 v_tap_quiet_u8);
+/***************************************************************/
+/**\name FUNCTION FOR TAP THRESHOLD CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read Threshold of the
+ * single/double tap interrupt from the register 0x64 bit 0 to 4
+ *
+ *
+ * @param v_tap_thres_u8 : The value of single/double tap threshold
+ *
+ * @note single/double tap threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | single/double tap threshold
+ * ----------------|---------------------
+ * 2g | ((v_tap_thres_u8 + 1) * 62.5)mg
+ * 4g | ((v_tap_thres_u8 + 1) * 125)mg
+ * 8g | ((v_tap_thres_u8 + 1) * 250)mg
+ * 16g | ((v_tap_thres_u8 + 1) * 500)mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_tap_thres(
+u8 *v_tap_thres_u8);
+ /*!
+ * @brief This API write Threshold of the
+ * single/double tap interrupt from the register 0x64 bit 0 to 4
+ *
+ *
+ * @param v_tap_thres_u8 : The value of single/double tap threshold
+ *
+ * @note single/double tap threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | single/double tap threshold
+ * ----------------|---------------------
+ * 2g | ((v_tap_thres_u8 + 1) * 62.5)mg
+ * 4g | ((v_tap_thres_u8 + 1) * 125)mg
+ * 8g | ((v_tap_thres_u8 + 1) * 250)mg
+ * 16g | ((v_tap_thres_u8 + 1) * 500)mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_tap_thres(
+u8 v_tap_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT MODE CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read the threshold for orientation interrupt
+ * from the register 0x65 bit 0 and 1
+ *
+ * @param v_orient_mode_u8 : The value of threshold for orientation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | symmetrical
+ * 0x01 | high-asymmetrical
+ * 0x02 | low-asymmetrical
+ * 0x03 | symmetrical
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_mode(
+u8 *v_orient_mode_u8);
+ /*!
+ * @brief This API write the threshold for orientation interrupt
+ * from the register 0x65 bit 0 and 1
+ *
+ * @param v_orient_mode_u8 : The value of threshold for orientation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | symmetrical
+ * 0x01 | high-asymmetrical
+ * 0x02 | low-asymmetrical
+ * 0x03 | symmetrical
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_mode(
+u8 v_orient_mode_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT BLOCKING CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read the orient blocking mode
+ * that is used for the generation of the orientation interrupt.
+ * from the register 0x65 bit 2 and 3
+ *
+ * @param v_orient_blocking_u8 : The value of orient blocking mode
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | No blocking
+ * 0x01 | Theta blocking or acceleration in any axis > 1.5g
+ * 0x02 | Theta blocking or acceleration slope in any axis >
+ * - | 0.2g or acceleration in any axis > 1.5g
+ * 0x03 | Theta blocking or acceleration slope in any axis >
+ * - | 0.4g or acceleration in any axis >
+ * - | 1.5g and value of orient is not stable
+ * - | for at least 100 ms
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_blocking(
+u8 *v_orient_blocking_u8);
+/*!
+ * @brief This API write the orient blocking mode
+ * that is used for the generation of the orientation interrupt.
+ * from the register 0x65 bit 2 and 3
+ *
+ * @param v_orient_blocking_u8 : The value of orient blocking mode
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | No blocking
+ * 0x01 | Theta blocking or acceleration in any axis > 1.5g
+ * 0x02 | Theta blocking or acceleration slope in any axis >
+ * - | 0.2g or acceleration in any axis > 1.5g
+ * 0x03 | Theta blocking or acceleration slope in any axis >
+ * - | 0.4g or acceleration in any axis >
+ * - | 1.5g and value of orient is not stable
+ * - | for at least 100 ms
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_blocking(
+u8 v_orient_blocking_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT HYSTERESIS CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read Orient interrupt
+ * hysteresis, from the register 0x64 bit 4 to 7
+ *
+ *
+ *
+ * @param v_orient_hyst_u8 : The value of orient hysteresis
+ *
+ * @note 1 LSB corresponds to 62.5 mg,
+ * irrespective of the selected accel range
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_hyst(
+u8 *v_orient_hyst_u8);
+/*!
+ * @brief This API write Orient interrupt
+ * hysteresis, from the register 0x64 bit 4 to 7
+ *
+ *
+ *
+ * @param v_orient_hyst_u8 : The value of orient hysteresis
+ *
+ * @note 1 LSB corresponds to 62.5 mg,
+ * irrespective of the selected accel range
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_hyst(
+u8 v_orient_hyst_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT THETA CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read Orient
+ * blocking angle (0 to 44.8) from the register 0x66 bit 0 to 5
+ *
+ * @param v_orient_theta_u8 : The value of Orient blocking angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_theta(
+u8 *v_orient_theta_u8);
+ /*!
+ * @brief This API write Orient
+ * blocking angle (0 to 44.8) from the register 0x66 bit 0 to 5
+ *
+ * @param v_orient_theta_u8 : The value of Orient blocking angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_theta(
+u8 v_orient_theta_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT OUTPUT ENABLE CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read orient change
+ * of up/down bit from the register 0x66 bit 6
+ *
+ * @param v_orient_ud_u8 : The value of orient change of up/down
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | Is ignored
+ * 0x01 | Generates orientation interrupt
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_ud_enable(
+u8 *v_orient_ud_u8);
+/*!
+ * @brief This API write orient change
+ * of up/down bit from the register 0x66 bit 6
+ *
+ * @param v_orient_ud_u8 : The value of orient change of up/down
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | Is ignored
+ * 0x01 | Generates orientation interrupt
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_ud_enable(
+u8 v_orient_ud_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT AXIS ENABLE CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read orientation axes changes
+ * from the register 0x66 bit 7
+ *
+ * @param v_orient_axes_u8 : The value of orient axes assignment
+ * value | Behaviour | Name
+ * ----------|--------------------|------
+ * 0x00 | x = x, y = y, z = z|orient_ax_noex
+ * 0x01 | x = y, y = z, z = x|orient_ax_ex
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_orient_axes_enable(
+u8 *v_orient_axes_u8);
+ /*!
+ * @brief This API write orientation axes changes
+ * from the register 0x66 bit 7
+ *
+ * @param v_orient_axes_u8 : The value of orient axes assignment
+ * value | Behaviour | Name
+ * ----------|--------------------|------
+ * 0x00 | x = x, y = y, z = z|orient_ax_noex
+ * 0x01 | x = y, y = z, z = x|orient_ax_ex
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_orient_axes_enable(
+u8 v_orient_axes_u8);
+/***************************************************************/
+/**\name FUNCTION FOR FLAT THETA CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read Flat angle (0 to 44.8) for flat interrupt
+ * from the register 0x67 bit 0 to 5
+ *
+ * @param v_flat_theta_u8 : The value of flat angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_flat_theta(
+u8 *v_flat_theta_u8);
+ /*!
+ * @brief This API write Flat angle (0 to 44.8) for flat interrupt
+ * from the register 0x67 bit 0 to 5
+ *
+ * @param v_flat_theta_u8 : The value of flat angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_flat_theta(
+u8 v_flat_theta_u8);
+/***************************************************************/
+/**\name FUNCTION FOR FLAT HOLD CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read Flat interrupt hold time;
+ * from the register 0x68 bit 4 and 5
+ *
+ * @param v_flat_hold_u8 : The value of flat hold time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | 0ms
+ * 0x01 | 512ms
+ * 0x01 | 1024ms
+ * 0x01 | 2048ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_flat_hold(
+u8 *v_flat_hold_u8);
+/*!
+ * @brief This API write Flat interrupt hold time;
+ * from the register 0x68 bit 4 and 5
+ *
+ * @param v_flat_hold_u8 : The value of flat hold time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | 0ms
+ * 0x01 | 512ms
+ * 0x01 | 1024ms
+ * 0x01 | 2048ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_flat_hold(
+u8 v_flat_hold_u8);
+/***************************************************************/
+/**\name FUNCTION FOR FLAT HYSTERESIS CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read flat interrupt hysteresis
+ * from the register 0x68 bit 0 to 3
+ *
+ * @param v_flat_hyst_u8 : The value of flat hysteresis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_intr_flat_hyst(
+u8 *v_flat_hyst_u8);
+/*!
+ * @brief This API write flat interrupt hysteresis
+ * from the register 0x68 bit 0 to 3
+ *
+ * @param v_flat_hyst_u8 : The value of flat hysteresis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_intr_flat_hyst(
+u8 v_flat_hyst_u8);
+/***************************************************************/
+/**\name FUNCTION FAST OFFSET COMPENSATION FOR ACCEL */
+/***************************************************************/
+ /*!
+ * @brief This API read accel offset compensation
+ * target value for z-axis from the register 0x69 bit 0 and 1
+ *
+ * @param v_foc_accel_z_u8 : the value of accel offset compensation z axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_accel_z(
+u8 *v_foc_accel_z_u8);
+ /*!
+ * @brief This API write accel offset compensation
+ * target value for z-axis from the register 0x69 bit 0 and 1
+ *
+ * @param v_foc_accel_z_u8 : the value of accel offset compensation z axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_foc_accel_z(
+u8 v_foc_accel_z_u8);
+/*!
+ * @brief This API read accel offset compensation
+ * target value for y-axis
+ * from the register 0x69 bit 2 and 3
+ *
+ * @param v_foc_accel_y_u8 : the value of accel offset compensation y axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_accel_y(
+u8 *v_foc_accel_y_u8);
+/*!
+ * @brief This API write accel offset compensation
+ * target value for y-axis
+ * from the register 0x69 bit 2 and 3
+ *
+ * @param v_foc_accel_y_u8 : the value of accel offset compensation y axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_foc_accel_y(
+u8 v_foc_accel_y_u8);
+/*!
+ * @brief This API read accel offset compensation
+ * target value for x-axis is
+ * from the register 0x69 bit 4 and 5
+ *
+ * @param v_foc_accel_x_u8 : the value of accel offset compensation x axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_accel_x(
+u8 *v_foc_accel_x_u8);
+/*!
+ * @brief This API write accel offset compensation
+ * target value for x-axis is
+ * from the register 0x69 bit 4 and 5
+ *
+ * @param v_foc_accel_x_u8 : the value of accel offset compensation x axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_foc_accel_x(
+u8 v_foc_accel_x_u8);
+/***************************************************************/
+/**\name FUNCTION FAST OFFSET COMPENSATION FOR GYRO */
+/***************************************************************/
+/*!
+ * @brief This API write gyro fast offset enable
+ * from the register 0x69 bit 6
+ *
+ * @param v_foc_gyro_u8 : The value of gyro fast offset enable
+ * value | Description
+ * ----------|-------------
+ * 0 | fast offset compensation disabled
+ * 1 | fast offset compensation enabled
+ *
+ * @param v_gyro_off_x_s16 : The value of gyro fast offset x axis data
+ * @param v_gyro_off_y_s16 : The value of gyro fast offset y axis data
+ * @param v_gyro_off_z_s16 : The value of gyro fast offset z axis data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_foc_gyro_enable(
+u8 v_foc_gyro_u8, s16 *v_gyro_off_x_s16,
+s16 *v_gyro_off_y_s16, s16 *v_gyro_off_z_s16);
+/***************************************************/
+/**\name FUNCTION FOR NVM*/
+/***************************************************/
+ /*!
+ * @brief This API read NVM program enable
+ * from the register 0x6A bit 1
+ *
+ * @param v_nvm_prog_u8 : The value of NVM program enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_nvm_prog_enable(
+u8 *v_nvm_prog_u8);
+ /*!
+ * @brief This API write NVM program enable
+ * from the register 0x6A bit 1
+ *
+ * @param v_nvm_prog_u8 : The value of NVM program enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_nvm_prog_enable(
+u8 v_nvm_prog_u8);
+/***************************************************/
+/**\name FUNCTION FOR SPI MODE*/
+/***************************************************/
+/*!
+ * @brief This API read to configure SPI
+ * Interface Mode for primary and OIS interface
+ * from the register 0x6B bit 0
+ *
+ * @param v_spi3_u8 : The value of SPI mode selection
+ * Value | Description
+ * --------|-------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_spi3(
+u8 *v_spi3_u8);
+/*!
+ * @brief This API write to configure SPI
+ * Interface Mode for primary and OIS interface
+ * from the register 0x6B bit 0
+ *
+ * @param v_spi3_u8 : The value of SPI mode selection
+ * Value | Description
+ * --------|-------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_spi3(
+u8 v_spi3_u8);
+/***************************************************/
+/**\name FUNCTION FOR FOC GYRO */
+/***************************************************/
+/*!
+ * @brief This API read gyro fast offset enable
+ * from the register 0x69 bit 6
+ *
+ * @param v_foc_gyro_u8 : The value of gyro fast offset enable
+ * value | Description
+ * ----------|-------------
+ * 0 | fast offset compensation disabled
+ * 1 | fast offset compensation enabled
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_foc_gyro_enable(
+u8 *v_foc_gyro_u8);
+/***************************************************/
+/**\name FUNCTION FOR I2C WATCHDOG TIMBER */
+/***************************************************/
+/*!
+ * @brief This API read I2C Watchdog timer
+ * from the register 0x70 bit 1
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watch dog timer
+ * Value | Description
+ * --------|-------------
+ * 0 | I2C watchdog v_timeout_u8 after 1 ms
+ * 1 | I2C watchdog v_timeout_u8 after 50 ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_i2c_wdt_select(
+u8 *v_i2c_wdt_u8);
+/*!
+ * @brief This API write I2C Watchdog timer
+ * from the register 0x70 bit 1
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watch dog timer
+ * Value | Description
+ * --------|-------------
+ * 0 | I2C watchdog v_timeout_u8 after 1 ms
+ * 1 | I2C watchdog v_timeout_u8 after 50 ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE
+bmi160_set_i2c_wdt_select(u8 v_i2c_wdt_u8);
+/*!
+ * @brief This API read I2C watchdog enable
+ * from the register 0x70 bit 2
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watchdog enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_i2c_wdt_enable(
+u8 *v_i2c_wdt_u8);
+/*!
+ * @brief This API write I2C watchdog enable
+ * from the register 0x70 bit 2
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watchdog enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_i2c_wdt_enable(
+u8 v_i2c_wdt_u8);
+/***************************************************/
+/**\name FUNCTION FOR IF MODE*/
+/***************************************************/
+/*!
+ * @brief This API read I2C interface configuration(if) moe
+ * from the register 0x6B bit 4 and 5
+ *
+ * @param v_if_mode_u8 : The value of interface configuration mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Primary interface:autoconfig / secondary interface:off
+ * 0x01 | Primary interface:I2C / secondary interface:OIS
+ * 0x02 | Primary interface:autoconfig/secondary interface:Magnetometer
+ * 0x03 | Reserved
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_if_mode(
+u8 *v_if_mode_u8);
+/*!
+ * @brief This API write I2C interface configuration(if) moe
+ * from the register 0x6B bit 4 and 5
+ *
+ * @param v_if_mode_u8 : The value of interface configuration mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Primary interface:autoconfig / secondary interface:off
+ * 0x01 | Primary interface:I2C / secondary interface:OIS
+ * 0x02 | Primary interface:autoconfig/secondary interface:Magnetometer
+ * 0x03 | Reserved
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_if_mode(
+u8 v_if_mode_u8);
+/***************************************************/
+/**\name FUNCTION FOR GYRO SLEEP TRIGGER INTERRUPT CONFIGURATION*/
+/***************************************************/
+/*!
+ * @brief This API read gyro sleep trigger
+ * from the register 0x6C bit 0 to 2
+ *
+ * @param v_gyro_sleep_trigger_u8 : The value of gyro sleep trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | nomotion: no / Not INT1 pin: no / INT2 pin: no
+ * 0x01 | nomotion: no / Not INT1 pin: no / INT2 pin: yes
+ * 0x02 | nomotion: no / Not INT1 pin: yes / INT2 pin: no
+ * 0x03 | nomotion: no / Not INT1 pin: yes / INT2 pin: yes
+ * 0x04 | nomotion: yes / Not INT1 pin: no / INT2 pin: no
+ * 0x05 | anymotion: yes / Not INT1 pin: no / INT2 pin: yes
+ * 0x06 | anymotion: yes / Not INT1 pin: yes / INT2 pin: no
+ * 0x07 | anymotion: yes / Not INT1 pin: yes / INT2 pin: yes
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_sleep_trigger(
+u8 *v_gyro_sleep_trigger_u8);
+/*!
+ * @brief This API write gyro sleep trigger
+ * from the register 0x6C bit 0 to 2
+ *
+ * @param v_gyro_sleep_trigger_u8 : The value of gyro sleep trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | nomotion: no / Not INT1 pin: no / INT2 pin: no
+ * 0x01 | nomotion: no / Not INT1 pin: no / INT2 pin: yes
+ * 0x02 | nomotion: no / Not INT1 pin: yes / INT2 pin: no
+ * 0x03 | nomotion: no / Not INT1 pin: yes / INT2 pin: yes
+ * 0x04 | nomotion: yes / Not INT1 pin: no / INT2 pin: no
+ * 0x05 | anymotion: yes / Not INT1 pin: no / INT2 pin: yes
+ * 0x06 | anymotion: yes / Not INT1 pin: yes / INT2 pin: no
+ * 0x07 | anymotion: yes / Not INT1 pin: yes / INT2 pin: yes
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_sleep_trigger(
+u8 v_gyro_sleep_trigger_u8);
+/*!
+ * @brief This API read gyro wakeup trigger
+ * from the register 0x6C bit 3 and 4
+ *
+ * @param v_gyro_wakeup_trigger_u8 : The value of gyro wakeup trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | anymotion: no / INT1 pin: no
+ * 0x01 | anymotion: no / INT1 pin: yes
+ * 0x02 | anymotion: yes / INT1 pin: no
+ * 0x03 | anymotion: yes / INT1 pin: yes
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_wakeup_trigger(
+u8 *v_gyro_wakeup_trigger_u8);
+/*!
+ * @brief This API write gyro wakeup trigger
+ * from the register 0x6C bit 3 and 4
+ *
+ * @param v_gyro_wakeup_trigger_u8 : The value of gyro wakeup trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | anymotion: no / INT1 pin: no
+ * 0x01 | anymotion: no / INT1 pin: yes
+ * 0x02 | anymotion: yes / INT1 pin: no
+ * 0x03 | anymotion: yes / INT1 pin: yes
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_wakeup_trigger(
+u8 v_gyro_wakeup_trigger_u8);
+/*!
+ * @brief This API read Target state for gyro sleep mode
+ * from the register 0x6C bit 5
+ *
+ * @param v_gyro_sleep_state_u8 : The value of gyro sleep mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Sleep transition to fast wake up state
+ * 0x01 | Sleep transition to suspend state
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_sleep_state(
+u8 *v_gyro_sleep_state_u8);
+/*!
+ * @brief This API write Target state for gyro sleep mode
+ * from the register 0x6C bit 5
+ *
+ * @param v_gyro_sleep_state_u8 : The value of gyro sleep mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Sleep transition to fast wake up state
+ * 0x01 | Sleep transition to suspend state
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_sleep_state(
+u8 v_gyro_sleep_state_u8);
+/*!
+ * @brief This API read gyro wakeup interrupt
+ * from the register 0x6C bit 6
+ *
+ * @param v_gyro_wakeup_intr_u8 : The valeu of gyro wakeup interrupt
+ * Value | Description
+ * --------|-------------
+ * 0x00 | DISABLE
+ * 0x01 | ENABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_wakeup_intr(
+u8 *v_gyro_wakeup_intr_u8);
+/*!
+ * @brief This API write gyro wakeup interrupt
+ * from the register 0x6C bit 6
+ *
+ * @param v_gyro_wakeup_intr_u8 : The valeu of gyro wakeup interrupt
+ * Value | Description
+ * --------|-------------
+ * 0x00 | DISABLE
+ * 0x01 | ENABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_wakeup_intr(
+u8 v_gyro_wakeup_intr_u8);
+/***************************************************/
+/**\name FUNCTION FOR ACCEL SELF TEST */
+/***************************************************/
+/*!
+ * @brief This API read accel select axis to be self-test
+ *
+ * @param v_accel_selftest_axis_u8 :
+ * The value of accel self test axis selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | disabled
+ * 0x01 | x-axis
+ * 0x02 | y-axis
+ * 0x03 | z-axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_selftest_axis(
+u8 *acc_selftest_axis);
+/*!
+ * @brief This API write accel select axis to be self-test
+ *
+ * @param v_accel_selftest_axis_u8 :
+ * The value of accel self test axis selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | disabled
+ * 0x01 | x-axis
+ * 0x02 | y-axis
+ * 0x03 | z-axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_selftest_axis(
+u8 acc_selftest_axis);
+/*!
+ * @brief This API read accel self test axis sign
+ * from the register 0x6D bit 2
+ *
+ * @param v_accel_selftest_sign_u8: The value of accel self test axis sign
+ * Value | Description
+ * --------|-------------
+ * 0x00 | negative
+ * 0x01 | positive
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_selftest_sign(
+u8 *acc_selftest_sign);
+/*!
+ * @brief This API write accel self test axis sign
+ * from the register 0x6D bit 2
+ *
+ * @param v_accel_selftest_sign_u8: The value of accel self test axis sign
+ * Value | Description
+ * --------|-------------
+ * 0x00 | negative
+ * 0x01 | positive
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_selftest_sign(
+u8 acc_selftest_sign);
+/*!
+ * @brief This API read accel self test amplitude
+ * from the register 0x6D bit 3
+ * select amplitude of the selftest deflection:
+ *
+ * @param v_accel_selftest_amp_u8 : The value of accel self test amplitude
+ * Value | Description
+ * --------|-------------
+ * 0x00 | LOW
+ * 0x01 | HIGH
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_selftest_amp(
+u8 *acc_selftest_amp);
+/*!
+ * @brief This API write accel self test amplitude
+ * from the register 0x6D bit 3
+ * select amplitude of the selftest deflection:
+ *
+ * @param v_accel_selftest_amp_u8 : The value of accel self test amplitude
+ * Value | Description
+ * --------|-------------
+ * 0x00 | LOW
+ * 0x01 | HIGH
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_selftest_amp(
+u8 acc_selftest_amp);
+/***************************************************/
+/**\name FUNCTION FOR GYRO SELF TEST */
+/***************************************************/
+/*!
+ * @brief This API read gyro self test trigger
+ *
+ * @param v_gyro_selftest_start_u8: The value of gyro self test start
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_selftest_start(
+u8 *v_gyro_selftest_start_u8);
+/*!
+ * @brief This API write gyro self test trigger
+ *
+ * @param v_gyro_selftest_start_u8: The value of gyro self test start
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_selftest_start(
+u8 v_gyro_selftest_start_u8);
+/***************************************************/
+/**\name FUNCTION FOR SPI/I2C ENABLE */
+/***************************************************/
+ /*!
+ * @brief This API read primary interface selection I2C or SPI
+ * from the register 0x70 bit 0
+ *
+ * @param v_spi_enable_u8: The value of Interface selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | I2C Enable
+ * 0x01 | I2C DISBALE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_spi_enable(
+u8 *v_spi_enable_u8);
+ /*!
+ * @brief This API write primary interface selection I2C or SPI
+ * from the register 0x70 bit 0
+ *
+ * @param v_spi_enable_u8: The value of Interface selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | I2C Enable
+ * 0x01 | I2C DISBALE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_spi_enable(
+u8 v_spi_enable_u8);
+ /*!
+ * @brief This API read the spare zero
+ * form register 0x70 bit 3
+ *
+ *
+ * @param v_spare0_trim_u8: The value of spare zero
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_spare0_trim
+(u8 *v_spare0_trim_u8);
+ /*!
+ * @brief This API write the spare zero
+ * form register 0x70 bit 3
+ *
+ *
+ * @param v_spare0_trim_u8: The value of spare zero
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_spare0_trim
+(u8 v_spare0_trim_u8);
+/***************************************************/
+/**\name FUNCTION FOR NVM COUNTER */
+/***************************************************/
+ /*!
+ * @brief This API read the NVM counter
+ * form register 0x70 bit 4 to 7
+ *
+ *
+ * @param v_nvm_counter_u8: The value of NVM counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_nvm_counter(
+u8 *v_nvm_counter_u8);
+ /*!
+ * @brief This API write the NVM counter
+ * form register 0x70 bit 4 to 7
+ *
+ *
+ * @param v_nvm_counter_u8: The value of NVM counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_nvm_counter(
+u8 v_nvm_counter_u8);
+/***************************************************/
+/**\name FUNCTION FOR ACCEL MANUAL OFFSET COMPENSATION */
+/***************************************************/
+/*!
+ * @brief This API read accel manual offset compensation of x axis
+ * from the register 0x71 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_x_s8:
+ * The value of accel manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_offset_compensation_xaxis(
+s8 *v_accel_off_x_s8);
+/*!
+ * @brief This API write accel manual offset compensation of x axis
+ * from the register 0x71 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_x_s8:
+ * The value of accel manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_offset_compensation_xaxis(
+s8 v_accel_off_x_s8);
+/*!
+ * @brief This API read accel manual offset compensation of y axis
+ * from the register 0x72 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_y_s8:
+ * The value of accel manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_offset_compensation_yaxis(
+s8 *v_accel_off_y_s8);
+/*!
+ * @brief This API write accel manual offset compensation of y axis
+ * from the register 0x72 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_y_s8:
+ * The value of accel manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_offset_compensation_yaxis(
+s8 v_accel_off_y_s8);
+/*!
+ * @brief This API read accel manual offset compensation of z axis
+ * from the register 0x73 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_z_s8:
+ * The value of accel manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_offset_compensation_zaxis(
+s8 *v_accel_off_z_s8);
+/*!
+ * @brief This API write accel manual offset compensation of z axis
+ * from the register 0x73 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_z_s8:
+ * The value of accel manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_offset_compensation_zaxis(
+s8 v_accel_off_z_s8);
+/***************************************************/
+/**\name FUNCTION FOR GYRO MANUAL OFFSET COMPENSATION */
+/***************************************************/
+/*!
+ * @brief This API read gyro manual offset compensation of x axis
+ * from the register 0x74 bit 0 to 7 and 0x77 bit 0 and 1
+ *
+ *
+ *
+ * @param v_gyro_off_x_s16:
+ * The value of gyro manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_offset_compensation_xaxis(
+s16 *v_gyro_off_x_s16);
+/*!
+ * @brief This API write gyro manual offset compensation of x axis
+ * from the register 0x74 bit 0 to 7 and 0x77 bit 0 and 1
+ *
+ *
+ *
+ * @param v_gyro_off_x_s16:
+ * The value of gyro manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_offset_compensation_xaxis(
+s16 v_gyro_off_x_s16);
+/*!
+ * @brief This API read gyro manual offset compensation of y axis
+ * from the register 0x75 bit 0 to 7 and 0x77 bit 2 and 3
+ *
+ *
+ *
+ * @param v_gyro_off_y_s16:
+ * The value of gyro manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_offset_compensation_yaxis(
+s16 *v_gyro_off_y_s16);
+/*!
+ * @brief This API write gyro manual offset compensation of y axis
+ * from the register 0x75 bit 0 to 7 and 0x77 bit 2 and 3
+ *
+ *
+ *
+ * @param v_gyro_off_y_s16:
+ * The value of gyro manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_offset_compensation_yaxis(
+s16 v_gyro_off_y_s16);
+/*!
+ * @brief This API read gyro manual offset compensation of z axis
+ * from the register 0x76 bit 0 to 7 and 0x77 bit 4 and 5
+ *
+ *
+ *
+ * @param v_gyro_off_z_s16:
+ * The value of gyro manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_offset_compensation_zaxis(
+s16 *v_gyro_off_z_s16);
+/*!
+ * @brief This API write gyro manual offset compensation of z axis
+ * from the register 0x76 bit 0 to 7 and 0x77 bit 4 and 5
+ *
+ *
+ *
+ * @param v_gyro_off_z_s16:
+ * The value of gyro manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_offset_compensation_zaxis(
+s16 v_gyro_off_z_s16);
+/*!
+ * @brief This API writes accel fast offset compensation
+ * from the register 0x69 bit 0 to 5
+ * @brief This API writes each axis individually
+ * FOC_X_AXIS - bit 4 and 5
+ * FOC_Y_AXIS - bit 2 and 3
+ * FOC_Z_AXIS - bit 0 and 1
+ *
+ * @param v_foc_accel_u8: The value of accel offset compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_axis_u8: The value of accel offset axis selection
+ * value | axis
+ * ----------|-------------------
+ * 0 | FOC_X_AXIS
+ * 1 | FOC_Y_AXIS
+ * 2 | FOC_Z_AXIS
+ *
+ * @param v_accel_offset_s8: The accel offset value
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_foc_trigger(u8 axis,
+u8 foc_acc, s8 *accel_offset);
+/*!
+ * @brief This API write fast accel offset compensation
+ * it writes all axis together.To the register 0x69 bit 0 to 5
+ * FOC_X_AXIS - bit 4 and 5
+ * FOC_Y_AXIS - bit 2 and 3
+ * FOC_Z_AXIS - bit 0 and 1
+ *
+ * @param v_foc_accel_x_u8: The value of accel offset x compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_foc_accel_y_u8: The value of accel offset y compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_foc_accel_z_u8: The value of accel offset z compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_accel_off_x_s8: The value of accel offset x axis
+ * @param v_accel_off_y_s8: The value of accel offset y axis
+ * @param v_accel_off_z_s8: The value of accel offset z axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_accel_foc_trigger_xyz(u8 v_foc_accel_x_u8,
+u8 v_foc_accel_y_u8, u8 v_foc_accel_z_u8,
+s8 *acc_off_x, s8 *acc_off_y, s8 *acc_off_z);
+/***************************************************/
+/**\name FUNCTION FOR ACEL AND GYRO OFFSET ENABLE */
+/***************************************************/
+/*!
+ * @brief This API read the accel offset enable bit
+ * from the register 0x77 bit 6
+ *
+ *
+ *
+ * @param v_accel_off_enable_u8: The value of accel offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_accel_offset_enable(
+u8 *acc_off_en);
+/*!
+ * @brief This API write the accel offset enable bit
+ * from the register 0x77 bit 6
+ *
+ *
+ *
+ * @param v_accel_off_enable_u8: The value of accel offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_accel_offset_enable(
+u8 acc_off_en);
+/*!
+ * @brief This API read the accel offset enable bit
+ * from the register 0x77 bit 7
+ *
+ *
+ *
+ * @param v_gyro_off_enable_u8: The value of gyro offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_gyro_offset_enable(
+u8 *v_gyro_off_enable_u8);
+/*!
+ * @brief This API write the accel offset enable bit
+ * from the register 0x77 bit 7
+ *
+ *
+ *
+ * @param v_gyro_off_enable_u8: The value of gyro offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_gyro_offset_enable(
+u8 v_gyro_off_enable_u8);
+/***************************************************/
+/**\name FUNCTION FOR STEP COUNTER INTERRUPT */
+/***************************************************/
+/*!
+ * @brief This API reads step counter value
+ * form the register 0x78 and 0x79
+ *
+ *
+ *
+ *
+ * @param v_step_cnt_s16 : The value of step counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_step_count(u16 *v_step_cnt_s16);
+ /*!
+ * @brief This API Reads
+ * step counter configuration
+ * from the register 0x7A bit 0 to 7
+ * and from the register 0x7B bit 0 to 2 and 4 to 7
+ *
+ *
+ * @param v_step_config_u16 : The value of step configuration
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_step_config(
+u16 *v_step_config_u16);
+ /*!
+ * @brief This API write
+ * step counter configuration
+ * from the register 0x7A bit 0 to 7
+ * and from the register 0x7B bit 0 to 2 and 4 to 7
+ *
+ *
+ * @param v_step_config_u16 :
+ * the value of Enable step configuration
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_step_config(
+u16 v_step_config_u16);
+ /*!
+ * @brief This API read enable step counter
+ * from the register 0x7B bit 3
+ *
+ *
+ * @param v_step_counter_u8 : The value of step counter enable
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_step_counter_enable(
+u8 *v_step_counter_u8);
+ /*!
+ * @brief This API write enable step counter
+ * from the register 0x7B bit 3
+ *
+ *
+ * @param v_step_counter_u8 : The value of step counter enable
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_step_counter_enable(
+u8 v_step_counter_u8);
+ /*!
+ * @brief This API set Step counter modes
+ *
+ *
+ * @param v_step_mode_u8 : The value of step counter mode
+ * value | mode
+ * ----------|-----------
+ * 0 | BMI160_STEP_NORMAL_MODE
+ * 1 | BMI160_STEP_SENSITIVE_MODE
+ * 2 | BMI160_STEP_ROBUST_MODE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_step_mode(u8 v_step_mode_u8);
+/*!
+ * @brief This API used to trigger the signification motion
+ * interrupt
+ *
+ *
+ * @param v_significant_u8 : The value of interrupt selection
+ * value | interrupt
+ * ----------|-----------
+ * 0 | BMI160_MAP_INTR1
+ * 1 | BMI160_MAP_INTR2
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_map_significant_motion_intr(
+u8 v_significant_u8);
+/*!
+ * @brief This API used to trigger the step detector
+ * interrupt
+ *
+ *
+ * @param v_step_detector_u8 : The value of interrupt selection
+ * value | interrupt
+ * ----------|-----------
+ * 0 | BMI160_MAP_INTR1
+ * 1 | BMI160_MAP_INTR2
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_map_step_detector_intr(
+u8 v_step_detector_u8);
+ /*!
+ * @brief This API used to clear the step counter interrupt
+ * interrupt
+ *
+ *
+ * @param : None
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_clear_step_counter(void);
+/***************************************************/
+/**\name FUNCTION FOR STEP COMMAND REGISTER WRITE */
+/***************************************************/
+ /*!
+ * @brief This API writes value to the register 0x7E bit 0 to 7
+ *
+ *
+ * @param v_command_reg_u8 : The value to write command register
+ * value | Description
+ * ---------|--------------------------------------------------------
+ * 0x00 | Reserved
+ * 0x03 | Starts fast offset calibration for the accel and gyro
+ * 0x10 | Sets the PMU mode for the Accelerometer to suspend
+ * 0x11 | Sets the PMU mode for the Accelerometer to normal
+ * 0x12 | Sets the PMU mode for the Accelerometer Lowpower
+ * 0x14 | Sets the PMU mode for the Gyroscope to suspend
+ * 0x15 | Sets the PMU mode for the Gyroscope to normal
+ * 0x16 | Reserved
+ * 0x17 | Sets the PMU mode for the Gyroscope to fast start-up
+ * 0x18 | Sets the PMU mode for the Magnetometer to suspend
+ * 0x19 | Sets the PMU mode for the Magnetometer to normal
+ * 0x1A | Sets the PMU mode for the Magnetometer to Lowpower
+ * 0xB0 | Clears all data in the FIFO
+ * 0xB1 | Resets the interrupt engine
+ * 0xB2 | step_cnt_clr Clears the step counter
+ * 0xB6 | Triggers a reset
+ * 0x37 | See extmode_en_last
+ * 0x9A | See extmode_en_last
+ * 0xC0 | Enable the extended mode
+ * 0xC4 | Erase NVM cell
+ * 0xC8 | Load NVM cell
+ * 0xF0 | Reset acceleration data path
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_command_register(
+u8 v_command_reg_u8);
+/***************************************************/
+/**\name FUNCTION FOR PAGE ENABLE */
+/***************************************************/
+ /*!
+ * @brief This API read target page from the register 0x7F bit 4 and 5
+ *
+ * @param v_target_page_u8: The value of target page
+ * value | page
+ * ---------|-----------
+ * 0 | User data/configure page
+ * 1 | Chip level trim/test page
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_target_page(
+u8 *v_target_page_u8);
+ /*!
+ * @brief This API write target page from the register 0x7F bit 4 and 5
+ *
+ * @param v_target_page_u8: The value of target page
+ * value | page
+ * ---------|-----------
+ * 0 | User data/configure page
+ * 1 | Chip level trim/test page
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_target_page(
+u8 v_target_page_u8);
+ /*!
+ * @brief This API read page enable from the register 0x7F bit 7
+ *
+ *
+ *
+ * @param v_page_enable_u8: The value of page enable
+ * value | page
+ * ---------|-----------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_paging_enable(
+u8 *v_page_enable_u8);
+ /*!
+ * @brief This API write page enable from the register 0x7F bit 7
+ *
+ *
+ *
+ * @param v_page_enable_u8: The value of page enable
+ * value | page
+ * ---------|-----------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_paging_enable(
+u8 v_page_enable_u8);
+ /*!
+ * @brief This API read
+ * pull up configuration from the register 0X85 bit 4 an 5
+ *
+ *
+ *
+ * @param v_control_pullup_u8: The value of pull up register
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_get_pullup_configuration(
+u8 *v_control_pullup_u8);
+ /*!
+ * @brief This API write
+ * pull up configuration from the register 0X85 bit 4 an 5
+ *
+ *
+ *
+ * @param v_control_pullup_u8: The value of pull up register
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_pullup_configuration(
+u8 v_control_pullup_u8);
+/***************************************************/
+/**\name FUNCTION FOR BMM150 */
+/***************************************************/
+ /*!
+ * @brief This function used for initialize the bmm150 sensor
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_interface_init(void);
+ /*!
+ * @brief This function used for set the mag power control
+ * bit enable
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_wakeup(void);
+ /*!
+ * @brief This function used for read the trim values of magnetometer
+ *
+ * @note
+ * Before reading the mag trimming values
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_bmm150_mag_trim(void);
+ /*!
+ * @brief This function used for read the compensated value of mag
+ * Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_compensate_xyz(
+struct bmi160_mag_xyz_s32_t *mag_comp_xyz);
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_compensate_xyz_raw(
+struct bmi160_mag_xyz_s32_t *mag_comp_xyz, struct bmi160_mag_xyzr_t mag_xyzr);
+
+/*!
+ * @brief This API used to get the compensated BMM150-X data
+ * the out put of X as s32
+ * Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_x_s16 : The value of mag raw X data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 bmi160_bmm150_mag_compensate_X(s16 v_mag_data_x_s16, u16 v_data_r_u16);
+/*!
+ * @brief This API used to get the compensated BMM150-Y data
+ * the out put of Y as s32
+ * Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_y_s16 : The value of mag raw Y data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated Y data value output as s32
+ */
+s32 bmi160_bmm150_mag_compensate_Y(s16 v_mag_data_y_s16, u16 v_data_r_u16);
+/*!
+ * @brief This API used to get the compensated BMM150-Z data
+ * the out put of Z as s32
+ * Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_z_s16 : The value of mag raw Z data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated Z data value output as s32
+ */
+s32 bmi160_bmm150_mag_compensate_Z(s16 v_mag_data_z_s16, u16 v_data_r_u16);
+/*!
+ * @brief This API used to set the pre-set modes of bmm150
+ * The pre-set mode setting is depend on data rate and xy and z repetitions
+ *
+ * @note
+ * Before set the mag preset mode
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_mode_u8: The value of pre-set mode selection value
+ * value | pre_set mode
+ * ----------|------------
+ * 1 | BMI160_MAG_PRESETMODE_LOWPOWER
+ * 2 | BMI160_MAG_PRESETMODE_REGULAR
+ * 3 | BMI160_MAG_PRESETMODE_HIGHACCURACY
+ * 4 | BMI160_MAG_PRESETMODE_ENHANCED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_bmm150_mag_presetmode(u8 mode);
+/*!
+ * @brief This function used for set the magnetometer
+ * power mode.
+ * @note
+ * Before set the mag power mode
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @param v_mag_pow_mode_u8 : The value of mag power mode
+ * value | mode
+ * ----------|------------
+ * 0 | FORCE_MODE
+ * 1 | SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bmm150_mag_set_power_mode(u8 mag_pow_mode);
+ /*!
+ * @brief This function used for set the magnetometer
+ * power mode.
+ * @note
+ * Before set the mag power mode
+ * make sure the following two point is addressed
+ * Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ *
+ * @param v_mag_sec_if_pow_mode_u8 : The value of mag power mode
+ * value | mode
+ * ----------|------------
+ * 0 | BMI160_MAG_FORCE_MODE
+ * 1 | BMI160_MAG_SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_bmm150_mag_and_secondary_if_power_mode(
+u8 v_mag_sec_if_pow_mode_u8);
+/***************************************************/
+/**\name FUNCTIONS FOR AKM09911 AND AKM09912*/
+/***************************************************/
+ /*!
+ * @brief This function used for initialize
+ * the AKM09911 and AKM09912 sensor
+ *
+ *
+ * @param v_akm_i2c_address_u8: The value of device address
+ * AKM sensor | Slave address
+ * --------------|---------------------
+ * AKM09911 | AKM09911_I2C_ADDR_1
+ * - | and AKM09911_I2C_ADDR_2
+ * AKM09912 | AKM09912_I2C_ADDR_1
+ * - | AKM09912_I2C_ADDR_2
+ * - | AKM09912_I2C_ADDR_3
+ * - | AKM09912_I2C_ADDR_4
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm_mag_interface_init(
+u8 v_akm_i2c_address_u8);
+ /*!
+ * @brief This function used for read the sensitivity data of
+ * AKM09911 and AKM09912
+ *
+ * @note Before reading the mag sensitivity values
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_bst_akm_sensitivity_data(void);
+/*!
+ * @brief This API used to get the compensated X data
+ * of AKM09911 the out put of X as s32
+ * @note Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_x_s16 : The value of X data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09911_compensate_X(s16 v_bst_akm_x_s16);
+/*!
+ * @brief This API used to get the compensated Y data
+ * of AKM09911 the out put of Y as s32
+ * @note Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_y_s16 : The value of Y data
+ *
+ * @return results of compensated Y data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09911_compensate_Y(s16 v_bst_akm_y_s16);
+/*!
+ * @brief This API used to get the compensated Z data
+ * of AKM09911 the out put of Z as s32
+ * @note Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_z_s16 : The value of Z data
+ *
+ * @return results of compensated Z data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09911_compensate_Z(s16 v_bst_akm_z_s16);
+/*!
+ * @brief This API used to get the compensated X data
+ * of AKM09912 the out put of X as s32
+ * @note Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_x_s16 : The value of X data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09912_compensate_X(s16 v_bst_akm_x_s16);
+/*!
+ * @brief This API used to get the compensated Y data
+ * of AKM09912 the out put of Y as s32
+ * @note Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_y_s16 : The value of Y data
+ *
+ * @return results of compensated Y data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09912_compensate_Y(s16 v_bst_akm_y_s16);
+/*!
+ * @brief This API used to get the compensated Z data
+ * of AKM09912 the out put of Z as s32
+ * @note Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bst_akm_z_s16 : The value of Z data
+ *
+ * @return results of compensated Z data value output as s32
+ *
+ */
+s32 bmi160_bst_akm09912_compensate_Z(s16 v_bst_akm_z_s16);
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09911
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm09911_compensate_xyz(
+struct bmi160_mag_xyz_s32_t *bst_akm_xyz);
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09912
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm09912_compensate_xyz(
+struct bmi160_mag_xyz_s32_t *bst_akm_xyz);
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm09912_compensate_xyz_raw(
+struct bmi160_mag_xyz_s32_t *bst_akm_xyz);
+/*!
+ * @brief This function used for set the AKM09911 and AKM09912
+ * power mode.
+ * @note Before set the AKM power mode
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function bmi160_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * bmi160_set_command_register(0x19) function.
+ *
+ * @param v_akm_pow_mode_u8 : The value of akm power mode
+ * value | Description
+ * ---------|--------------------
+ * 0 | AKM_POWER_DOWN_MODE
+ * 1 | AKM_SINGLE_MEAS_MODE
+ * 2 | FUSE_ROM_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_akm_set_powermode(u8 v_akm_pow_mode_u8);
+ /*!
+ * @brief This function used for set the magnetometer
+ * power mode of AKM09911 and AKM09912
+ * @note Before set the mag power mode
+ * make sure the following two point is addressed
+ * Make sure the mag interface is enabled or not,
+ * by using the bmi160_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function bmi160_get_if_mode(0x02)
+ *
+ * @param v_mag_sec_if_pow_mode_u8 : The value of secondary if power mode
+ * value | Description
+ * ---------|--------------------
+ * 0 | BMI160_MAG_FORCE_MODE
+ * 1 | BMI160_MAG_SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_set_bst_akm_and_secondary_if_powermode(
+u8 v_mag_sec_if_pow_mode_u8);
+/***************************************************/
+/**\name FUNCTIONS FOR YAMAH-YAS532 */
+/***************************************************/
+/*!
+ * @brief This function used for read the YAMAH-YAS532 init
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas532_mag_interface_init(
+void);
+/*!
+ * @brief This function used to set the YAS532 initial values
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_set_initial_values(void);
+/*!
+ * @brief This function used for YAS532 offset correction
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_magnetic_measure_set_offset(
+void);
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS532 calibration data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas532_calib_values(void);
+/*!
+ * @brief This function used for calculate the
+ * YAS532 read the linear data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_xy1y2_to_linear(
+u16 *v_xy1y2_u16, s32 *xy1y2_linear);
+/*!
+ * @brief This function used for read the YAS532 sensor data
+ * @param v_acquisition_command_u8: used to set the data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ * @param v_busy_u8 : used to get the busy flay for sensor data read
+ * @param v_temp_u16 : used to get the temperature data
+ * @param v_xy1y2_u16 : used to get the sensor xy1y2 data
+ * @param v_overflow_u8 : used to get the overflow data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_normal_measurement_data(
+u8 v_acquisition_command_u8, u8 *v_busy_u8,
+u16 *v_temp_u16, u16 *v_xy1y2_u16, u8 *v_overflow_u8);
+/*!
+ * @brief This function used for YAS532 sensor data
+ * @param v_acquisition_command_u8 : the value of CMDR
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ * @param xyz_data : the vector xyz output
+ * @param v_overflow_s8 : the value of overflow
+ * @param v_temp_correction_u8 : the value of temperate correction enable
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_measurement_xyz_data(
+struct yas532_vector *xyz_data, u8 *v_overflow_s8, u8 v_temp_correction_u8,
+u8 v_acquisition_command_u8);
+/*!
+ * @brief This function used for YAS532 write data acquisition
+ * command register write
+ * @param v_command_reg_data_u8 : the value of data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_acquisition_command_register(
+u8 v_command_reg_data_u8);
+/*!
+ * @brief This function used write offset of YAS532
+ *
+ * @param p_offset_s8 : The value of offset to write
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas532_set_offset(
+const s8 *p_offset_s8);
+/*!
+ * @brief This function used to init the YAMAH-YAS537
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas537_mag_interface_init(
+void);
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 calibration data
+ *
+ *
+ * @param v_rcoil_u8 : The value of r coil
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas537_calib_values(
+u8 v_rcoil_u8);
+/*!
+ * @brief This function used for YAS537 write data acquisition
+ * command register write
+ * @param v_command_reg_data_u8 : the value of data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yas537_acquisition_command_register(
+u8 v_command_reg_data_u8);
+
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_coil_stat_u8: The value of R coil status
+ * @param v_busy_u8: The value of busy status
+ * @param v_temperature_u16: The value of temperature
+ * @param xy1y2: The value of raw xy1y2 data
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas537_read_xy1y2_data(
+u8 *v_coil_stat_u8, u8 *v_busy_u8,
+u16 *v_temperature_u16, u16 *xy1y2, u8 *v_ouflow_u8);
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_bst_yamaha_yas537_measure_xyz_data(
+u8 *v_ouflow_u8, struct yas_vector *vector_xyz);
+
+/***************************************************/
+/**\name FUNCTIONS FOR FIFO DATA READ */
+/***************************************************/
+/*!
+ * @brief This function used for reading the
+ * fifo data of header less mode
+ *
+ *
+ *
+ * @note Configure the below functions for FIFO header less mode
+ * @note 1. bmi160_set_fifo_down_gyro
+ * @note 2. bmi160_set_gyro_fifo_filter_data
+ * @note 3. bmi160_set_fifo_down_accel
+ * @note 4. bmi160_set_accel_fifo_filter_dat
+ * @note 5. bmi160_set_fifo_mag_enable
+ * @note 6. bmi160_set_fifo_accel_enable
+ * @note 7. bmi160_set_fifo_gyro_enable
+ * @note For interrupt configuration
+ * @note 1. bmi160_set_intr_fifo_full
+ * @note 2. bmi160_set_intr_fifo_wm
+ * @note 3. bmi160_set_fifo_tag_intr2_enable
+ * @note 4. bmi160_set_fifo_tag_intr1_enable
+ *
+ * @note The fifo reads the whole 1024 bytes
+ * and processing the data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_fifo_headerless_mode(
+void);
+/*!
+ * @brief This function used for reading the
+ * fifo data of header less mode for using user defined length
+ *
+ *
+ * @param v_fifo_user_length_u16: The value of length of fifo read data
+ *
+ * @note Configure the below functions for FIFO header less mode
+ * @note 1. bmi160_set_fifo_down_gyro
+ * @note 2. bmi160_set_gyro_fifo_filter_data
+ * @note 3. bmi160_set_fifo_down_accel
+ * @note 4. bmi160_set_accel_fifo_filter_dat
+ * @note 5. bmi160_set_fifo_mag_enable
+ * @note 6. bmi160_set_fifo_accel_enable
+ * @note 7. bmi160_set_fifo_gyro_enable
+ * @note For interrupt configuration
+ * @note 1. bmi160_set_intr_fifo_full
+ * @note 2. bmi160_set_intr_fifo_wm
+ * @note 3. bmi160_set_fifo_tag_intr2_enable
+ * @note 4. bmi160_set_fifo_tag_intr1_enable
+ *
+ * @note The fifo reads the whole 1024 bytes
+ * and processing the data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE
+bmi160_read_fifo_headerless_mode_user_defined_length(
+u16 v_fifo_user_length_u16);
+/*!
+ * @brief This function used for reading the
+ * fifo data of header mode
+ *
+ *
+ * @note Configure the below functions for FIFO header mode
+ * @note 1. bmi160_set_fifo_down_gyro()
+ * @note 2. bmi160_set_gyro_fifo_filter_data()
+ * @note 3. bmi160_set_fifo_down_accel()
+ * @note 4. bmi160_set_accel_fifo_filter_dat()
+ * @note 5. bmi160_set_fifo_mag_enable()
+ * @note 6. bmi160_set_fifo_accel_enable()
+ * @note 7. bmi160_set_fifo_gyro_enable()
+ * @note 8. bmi160_set_fifo_header_enable()
+ * @note For interrupt configuration
+ * @note 1. bmi160_set_intr_fifo_full()
+ * @note 2. bmi160_set_intr_fifo_wm()
+ * @note 3. bmi160_set_fifo_tag_intr2_enable()
+ * @note 4. bmi160_set_fifo_tag_intr1_enable()
+ *
+ * @note The fifo reads the whole 1024 bytes
+ * and processing the data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_fifo_header_data(
+void);
+/*!
+ * @brief This function used for reading the
+ * fifo data of header mode for using user defined length
+ *
+ *
+ * @note Configure the below functions for FIFO header mode
+ * @note 1. bmi160_set_fifo_down_gyro()
+ * @note 2. bmi160_set_gyro_fifo_filter_data()
+ * @note 3. bmi160_set_fifo_down_accel()
+ * @note 4. bmi160_set_accel_fifo_filter_dat()
+ * @note 5. bmi160_set_fifo_mag_enable()
+ * @note 6. bmi160_set_fifo_accel_enable()
+ * @note 7. bmi160_set_fifo_gyro_enable()
+ * @note 8. bmi160_set_fifo_header_enable()
+ * @note For interrupt configuration
+ * @note 1. bmi160_set_intr_fifo_full()
+ * @note 2. bmi160_set_intr_fifo_wm()
+ * @note 3. bmi160_set_fifo_tag_intr2_enable()
+ * @note 4. bmi160_set_fifo_tag_intr1_enable()
+ *
+ * @note The fifo reads the whole 1024 bytes
+ * and processing the data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+BMI160_RETURN_FUNCTION_TYPE bmi160_read_fifo_header_data_user_defined_length(
+u16 v_fifo_user_length_u16);
+/*!
+ * @brief This function used for reading
+ * bmi160_t structure
+ *
+ * @return the reference and values of bmi160_t
+ *
+ *
+*/
+struct bmi160_t *bmi160_get_ptr(void);
+
+#endif
+
diff --git a/drivers/input/sensors/bmi160/bmi160_driver.c b/drivers/input/sensors/bmi160/bmi160_driver.c
new file mode 100644
index 000000000000..55a30b9af339
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bmi160_driver.c
@@ -0,0 +1,4022 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * @filename bmi160_driver.c
+ * @date 2016/08/01 14:40
+ * @id "b5ff23a"
+ * @version 1.3
+ *
+ * @brief
+ * The core code of BMI160 device driver
+ *
+ * @detail
+ * This file implements the core code of BMI160 device driver,
+ * which includes hardware related functions, input device register,
+ * device attribute files, etc.
+*/
+
+#include "bmi160.h"
+#include "bmi160_driver.h"
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+
+
+#define DRIVER_VERSION "0.0.53.0"
+#define I2C_BURST_READ_MAX_LEN (256)
+#define BMI160_STORE_COUNT (6000)
+#define LMADA (1)
+uint64_t g_current_apts_us;
+
+
+enum BMI_SENSOR_INT_T {
+ /* Interrupt enable0*/
+ BMI_ANYMO_X_INT = 0,
+ BMI_ANYMO_Y_INT,
+ BMI_ANYMO_Z_INT,
+ BMI_D_TAP_INT,
+ BMI_S_TAP_INT,
+ BMI_ORIENT_INT,
+ BMI_FLAT_INT,
+ /* Interrupt enable1*/
+ BMI_HIGH_X_INT,
+ BMI_HIGH_Y_INT,
+ BMI_HIGH_Z_INT,
+ BMI_LOW_INT,
+ BMI_DRDY_INT,
+ BMI_FFULL_INT,
+ BMI_FWM_INT,
+ /* Interrupt enable2 */
+ BMI_NOMOTION_X_INT,
+ BMI_NOMOTION_Y_INT,
+ BMI_NOMOTION_Z_INT,
+ BMI_STEP_DETECTOR_INT,
+ INT_TYPE_MAX
+};
+
+/*bmi fifo sensor type combination*/
+enum BMI_SENSOR_FIFO_COMBINATION {
+ BMI_FIFO_A = 0,
+ BMI_FIFO_G,
+ BMI_FIFO_M,
+ BMI_FIFO_G_A,
+ BMI_FIFO_M_A,
+ BMI_FIFO_M_G,
+ BMI_FIFO_M_G_A,
+ BMI_FIFO_COM_MAX
+};
+
+/*bmi fifo analyse return err status*/
+enum BMI_FIFO_ANALYSE_RETURN_T {
+ FIFO_OVER_READ_RETURN = -10,
+ FIFO_SENSORTIME_RETURN = -9,
+ FIFO_SKIP_OVER_LEN = -8,
+ FIFO_M_G_A_OVER_LEN = -7,
+ FIFO_M_G_OVER_LEN = -6,
+ FIFO_M_A_OVER_LEN = -5,
+ FIFO_G_A_OVER_LEN = -4,
+ FIFO_M_OVER_LEN = -3,
+ FIFO_G_OVER_LEN = -2,
+ FIFO_A_OVER_LEN = -1
+};
+
+/*!bmi sensor generic power mode enum */
+enum BMI_DEV_OP_MODE {
+ SENSOR_PM_NORMAL = 0,
+ SENSOR_PM_LP1,
+ SENSOR_PM_SUSPEND,
+ SENSOR_PM_LP2
+};
+
+/*! bmi acc sensor power mode enum */
+enum BMI_ACC_PM_TYPE {
+ BMI_ACC_PM_NORMAL = 0,
+ BMI_ACC_PM_LP1,
+ BMI_ACC_PM_SUSPEND,
+ BMI_ACC_PM_LP2,
+ BMI_ACC_PM_MAX
+};
+
+/*! bmi gyro sensor power mode enum */
+enum BMI_GYRO_PM_TYPE {
+ BMI_GYRO_PM_NORMAL = 0,
+ BMI_GYRO_PM_FAST_START,
+ BMI_GYRO_PM_SUSPEND,
+ BMI_GYRO_PM_MAX
+};
+
+/*! bmi mag sensor power mode enum */
+enum BMI_MAG_PM_TYPE {
+ BMI_MAG_PM_NORMAL = 0,
+ BMI_MAG_PM_LP1,
+ BMI_MAG_PM_SUSPEND,
+ BMI_MAG_PM_LP2,
+ BMI_MAG_PM_MAX
+};
+
+
+/*! bmi sensor support type*/
+enum BMI_SENSOR_TYPE {
+ BMI_ACC_SENSOR,
+ BMI_GYRO_SENSOR,
+ BMI_MAG_SENSOR,
+ BMI_SENSOR_TYPE_MAX
+};
+
+/*!bmi sensor generic power mode enum */
+enum BMI_AXIS_TYPE {
+ X_AXIS = 0,
+ Y_AXIS,
+ Z_AXIS,
+ AXIS_MAX
+};
+
+/*!bmi sensor generic intterrupt enum */
+enum BMI_INT_TYPE {
+ BMI160_INT0 = 0,
+ BMI160_INT1,
+ BMI160_INT_MAX
+};
+
+/*! bmi sensor time resolution definition*/
+enum BMI_SENSOR_TIME_RS_TYPE {
+ TS_0_78_HZ = 1,/*0.78HZ*/
+ TS_1_56_HZ,/*1.56HZ*/
+ TS_3_125_HZ,/*3.125HZ*/
+ TS_6_25_HZ,/*6.25HZ*/
+ TS_12_5_HZ,/*12.5HZ*/
+ TS_25_HZ,/*25HZ, odr=6*/
+ TS_50_HZ,/*50HZ*/
+ TS_100_HZ,/*100HZ*/
+ TS_200_HZ,/*200HZ*/
+ TS_400_HZ,/*400HZ*/
+ TS_800_HZ,/*800HZ*/
+ TS_1600_HZ,/*1600HZ*/
+ TS_MAX_HZ
+};
+
+/*! bmi sensor interface mode */
+enum BMI_SENSOR_IF_MODE_TYPE {
+ /*primary interface:autoconfig/secondary interface off*/
+ P_AUTO_S_OFF = 0,
+ /*primary interface:I2C/secondary interface:OIS*/
+ P_I2C_S_OIS,
+ /*primary interface:autoconfig/secondary interface:Magnetometer*/
+ P_AUTO_S_MAG,
+ /*interface mode reseved*/
+ IF_MODE_RESEVED
+
+};
+
+/*! bmi160 acc/gyro calibration status in H/W layer */
+enum BMI_CALIBRATION_STATUS_TYPE {
+ /*BMI FAST Calibration ready x/y/z status*/
+ BMI_ACC_X_FAST_CALI_RDY = 0,
+ BMI_ACC_Y_FAST_CALI_RDY,
+ BMI_ACC_Z_FAST_CALI_RDY
+};
+
+unsigned int reg_op_addr;
+
+static const int bmi_pmu_cmd_acc_arr[BMI_ACC_PM_MAX] = {
+ /*!bmi pmu for acc normal, low power1,
+ * suspend, low power2 mode command */
+ CMD_PMU_ACC_NORMAL,
+ CMD_PMU_ACC_LP1,
+ CMD_PMU_ACC_SUSPEND,
+ CMD_PMU_ACC_LP2
+};
+
+static const int bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_MAX] = {
+ /*!bmi pmu for gyro normal, fast startup,
+ * suspend mode command */
+ CMD_PMU_GYRO_NORMAL,
+ CMD_PMU_GYRO_FASTSTART,
+ CMD_PMU_GYRO_SUSPEND
+};
+
+static const int bmi_pmu_cmd_mag_arr[BMI_MAG_PM_MAX] = {
+ /*!bmi pmu for mag normal, low power1,
+ * suspend, low power2 mode command */
+ CMD_PMU_MAG_NORMAL,
+ CMD_PMU_MAG_LP1,
+ CMD_PMU_MAG_SUSPEND,
+ CMD_PMU_MAG_LP2
+};
+
+static const char *bmi_axis_name[AXIS_MAX] = {"x", "y", "z"};
+
+static const int bmi_interrupt_type[] = {
+ /*!bmi interrupt type */
+ /* Interrupt enable0 , index=0~6*/
+ BMI160_ANY_MOTION_X_ENABLE,
+ BMI160_ANY_MOTION_Y_ENABLE,
+ BMI160_ANY_MOTION_Z_ENABLE,
+ BMI160_DOUBLE_TAP_ENABLE,
+ BMI160_SINGLE_TAP_ENABLE,
+ BMI160_ORIENT_ENABLE,
+ BMI160_FLAT_ENABLE,
+ /* Interrupt enable1, index=7~13*/
+ BMI160_HIGH_G_X_ENABLE,
+ BMI160_HIGH_G_Y_ENABLE,
+ BMI160_HIGH_G_Z_ENABLE,
+ BMI160_LOW_G_ENABLE,
+ BMI160_DATA_RDY_ENABLE,
+ BMI160_FIFO_FULL_ENABLE,
+ BMI160_FIFO_WM_ENABLE,
+ /* Interrupt enable2, index = 14~17*/
+ BMI160_NOMOTION_X_ENABLE,
+ BMI160_NOMOTION_Y_ENABLE,
+ BMI160_NOMOTION_Z_ENABLE,
+ BMI160_STEP_DETECTOR_EN
+};
+
+/*! bmi sensor time depend on ODR*/
+struct bmi_sensor_time_odr_tbl {
+ u32 ts_duration_lsb;
+ u32 ts_duration_us;
+ u32 ts_delat;/*sub current delat fifo_time*/
+};
+
+struct bmi160_axis_data_t {
+ s16 x;
+ s16 y;
+ s16 z;
+};
+
+struct bmi160_type_mapping_type {
+
+ /*! bmi16x sensor chip id */
+ uint16_t chip_id;
+
+ /*! bmi16x chip revision code */
+ uint16_t revision_id;
+
+ /*! bma2x2 sensor name */
+ const char *sensor_name;
+};
+
+struct bmi160_store_info_t {
+ uint8_t current_frm_cnt;
+ uint64_t current_apts_us[2];
+ uint8_t fifo_ts_total_frmcnt;
+ uint64_t fifo_time;
+};
+
+uint64_t get_current_timestamp(void)
+{
+ uint64_t ts_ap;
+ struct timespec tmp_time;
+ get_monotonic_boottime(&tmp_time);
+ ts_ap = (uint64_t)tmp_time.tv_sec * 1000000000 + tmp_time.tv_nsec;
+ return ts_ap;
+
+}
+
+/*! sensor support type map */
+static const struct bmi160_type_mapping_type sensor_type_map[] = {
+
+ {SENSOR_CHIP_ID_BMI, SENSOR_CHIP_REV_ID_BMI, "BMI160/162AB"},
+ {SENSOR_CHIP_ID_BMI_C2, SENSOR_CHIP_REV_ID_BMI, "BMI160C2"},
+ {SENSOR_CHIP_ID_BMI_C3, SENSOR_CHIP_REV_ID_BMI, "BMI160C3"},
+
+};
+
+/*!bmi160 sensor time depends on ODR */
+static const struct bmi_sensor_time_odr_tbl
+ sensortime_duration_tbl[TS_MAX_HZ] = {
+ {0x010000, 2560000, 0x00ffff},/*2560ms, 0.39hz, odr=resver*/
+ {0x008000, 1280000, 0x007fff},/*1280ms, 0.78hz, odr_acc=1*/
+ {0x004000, 640000, 0x003fff},/*640ms, 1.56hz, odr_acc=2*/
+ {0x002000, 320000, 0x001fff},/*320ms, 3.125hz, odr_acc=3*/
+ {0x001000, 160000, 0x000fff},/*160ms, 6.25hz, odr_acc=4*/
+ {0x000800, 80000, 0x0007ff},/*80ms, 12.5hz*/
+ {0x000400, 40000, 0x0003ff},/*40ms, 25hz, odr_acc = odr_gyro =6*/
+ {0x000200, 20000, 0x0001ff},/*20ms, 50hz, odr = 7*/
+ {0x000100, 10000, 0x0000ff},/*10ms, 100hz, odr=8*/
+ {0x000080, 5000, 0x00007f},/*5ms, 200hz, odr=9*/
+ {0x000040, 2500, 0x00003f},/*2.5ms, 400hz, odr=10*/
+ {0x000020, 1250, 0x00001f},/*1.25ms, 800hz, odr=11*/
+ {0x000010, 625, 0x00000f},/*0.625ms, 1600hz, odr=12*/
+
+};
+
+#if defined(CONFIG_USE_QUALCOMM_HAL)
+#define POLL_INTERVAL_MIN_MS 10
+#define POLL_INTERVAL_MAX_MS 4000
+#define POLL_DEFAULT_INTERVAL_MS 200
+#define BMI160_ACCEL_MIN_VALUE -32768
+#define BMI160_ACCEL_MAX_VALUE 32767
+#define BMI160_GYRO_MIN_VALUE -32768
+#define BMI160_GYRO_MAX_VALUE 32767
+#define BMI160_ACCEL_DEFAULT_POLL_INTERVAL_MS 200
+#define BMI160_GYRO_DEFAULT_POLL_INTERVAL_MS 200
+#define BMI160_ACCEL_MIN_POLL_INTERVAL_MS 10
+#define BMI160_ACCEL_MAX_POLL_INTERVAL_MS 5000
+#define BMI160_GYRO_MIN_POLL_INTERVAL_MS 10
+#define BMI160_GYRO_MAX_POLL_INTERVAL_MS 5000
+static struct sensors_classdev bmi160_accel_cdev = {
+ .name = "bmi160-accel",
+ .vendor = "bosch",
+ .version = 1,
+ .handle = SENSORS_ACCELERATION_HANDLE,
+ .type = SENSOR_TYPE_ACCELEROMETER,
+ .max_range = "156.8", /* 16g */
+ .resolution = "0.153125", /* 15.6mg */
+ .sensor_power = "0.13", /* typical value */
+ .min_delay = POLL_INTERVAL_MIN_MS * 1000, /* in microseconds */
+ .max_delay = POLL_INTERVAL_MAX_MS,
+ .delay_msec = POLL_DEFAULT_INTERVAL_MS, /* in millisecond */
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+ .enabled = 0,
+ .max_latency = 0,
+ .flags = 0,
+ .sensors_enable = NULL,
+ .sensors_poll_delay = NULL,
+ .sensors_set_latency = NULL,
+ .sensors_flush = NULL,
+ .sensors_self_test = NULL,
+};
+static struct sensors_classdev bmi160_gyro_cdev = {
+ .name = "bmi160-gyro",
+ .vendor = "bosch",
+ .version = 1,
+ .handle = SENSORS_GYROSCOPE_HANDLE,
+ .type = SENSOR_TYPE_GYROSCOPE,
+ .max_range = "34.906586", /* rad/s */
+ .resolution = "0.0010681152", /* rad/s */
+ .sensor_power = "3.6", /* 3.6 mA */
+ .min_delay = BMI160_GYRO_MIN_POLL_INTERVAL_MS * 1000,
+ .max_delay = BMI160_GYRO_MAX_POLL_INTERVAL_MS,
+ .delay_msec = BMI160_GYRO_DEFAULT_POLL_INTERVAL_MS,
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+ .enabled = 0,
+ .max_latency = 0,
+ .flags = 0, /* SENSOR_FLAG_CONTINUOUS_MODE */
+ .sensors_enable = NULL,
+ .sensors_poll_delay = NULL,
+ .sensors_enable_wakeup = NULL,
+ .sensors_set_latency = NULL,
+ .sensors_flush = NULL,
+};
+#endif
+static void bmi_delay(u32 msec)
+{
+ if (msec <= 20)
+ usleep_range(msec * 1000, msec * 1000);
+ else
+ msleep(msec);
+}
+
+static void bmi_dump_reg(struct bmi_client_data *client_data)
+{
+ #define REG_MAX0 0x24
+ #define REG_MAX1 0x56
+ int i;
+ u8 dbg_buf0[REG_MAX0];
+ u8 dbg_buf1[REG_MAX1];
+ u8 dbg_buf_str0[REG_MAX0 * 3 + 1] = "";
+ u8 dbg_buf_str1[REG_MAX1 * 3 + 1] = "";
+
+ dev_notice(client_data->dev, "\nFrom 0x00:\n");
+
+ client_data->device.bus_read(client_data->device.dev_addr,
+ BMI_REG_NAME(USER_CHIP_ID), dbg_buf0, REG_MAX0);
+ for (i = 0; i < REG_MAX0; i++) {
+ snprintf(dbg_buf_str0 + i * 3, 16, "%02x%c", dbg_buf0[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ dev_notice(client_data->dev, "%s\n", dbg_buf_str0);
+
+ client_data->device.bus_read(client_data->device.dev_addr,
+ BMI160_USER_ACCEL_CONFIG_ADDR, dbg_buf1, REG_MAX1);
+ dev_notice(client_data->dev, "\nFrom 0x40:\n");
+ for (i = 0; i < REG_MAX1; i++) {
+ snprintf(dbg_buf_str1 + i * 3, 16, "%02x%c", dbg_buf1[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ dev_notice(client_data->dev, "\n%s\n", dbg_buf_str1);
+ }
+
+
+void bmi_fifo_frame_bytes_extend_calc(
+ struct bmi_client_data *client_data,
+ unsigned int *fifo_frmbytes_extend)
+{
+
+ switch (client_data->fifo_data_sel) {
+ case BMI_FIFO_A_SEL:
+ case BMI_FIFO_G_SEL:
+ *fifo_frmbytes_extend = 7;
+ break;
+ case BMI_FIFO_G_A_SEL:
+ *fifo_frmbytes_extend = 13;
+ break;
+ case BMI_FIFO_M_SEL:
+ *fifo_frmbytes_extend = 9;
+ break;
+ case BMI_FIFO_M_A_SEL:
+ case BMI_FIFO_M_G_SEL:
+ /*8(mag) + 6(gyro or acc) +1(head) = 15*/
+ *fifo_frmbytes_extend = 15;
+ break;
+ case BMI_FIFO_M_G_A_SEL:
+ /*8(mag) + 6(gyro or acc) + 6 + 1 = 21*/
+ *fifo_frmbytes_extend = 21;
+ break;
+ default:
+ *fifo_frmbytes_extend = 0;
+ break;
+
+ };
+
+}
+
+
+static int bmi_input_init(struct bmi_client_data *client_data)
+{
+ struct input_dev *dev;
+ int err = 0;
+
+ dev = input_allocate_device();
+ if (NULL == dev)
+ return -ENOMEM;
+#if defined(CONFIG_USE_QUALCOMM_HAL)
+ dev->name = "bmi160-accel";
+#else
+ dev->name = SENSOR_NAME;
+#endif
+ dev->id.bustype = BUS_I2C;
+
+ input_set_capability(dev, EV_MSC, MSC_GESTURE);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_SGM);
+
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_FAST_GYRO_CALIB_DONE);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_STEP_DETECTOR);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_FAST_ACC_CALIB_DONE);
+
+
+ input_set_capability(dev, EV_REL, REL_X);
+ input_set_capability(dev, EV_REL, REL_Y);
+ input_set_capability(dev, EV_REL, REL_Z);
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ input_set_capability(dev, EV_ABS, ABS_MISC);
+ input_set_abs_params(dev, ABS_X,
+ BMI160_ACCEL_MIN_VALUE, BMI160_ACCEL_MAX_VALUE,
+ 0, 0);
+ input_set_abs_params(dev, ABS_Y,
+ BMI160_ACCEL_MIN_VALUE, BMI160_ACCEL_MAX_VALUE,
+ 0, 0);
+ input_set_abs_params(dev, ABS_Z,
+ BMI160_ACCEL_MIN_VALUE, BMI160_ACCEL_MAX_VALUE,
+ 0, 0);
+ #endif
+ input_set_drvdata(dev, client_data);
+
+ err = input_register_device(dev);
+ if (err < 0) {
+ input_free_device(dev);
+ dev_notice(client_data->dev, "bmi160 input free!\n");
+ return err;
+ }
+ client_data->input = dev;
+ dev_notice(client_data->dev,
+ "bmi160 input register successfully, %s!\n",
+ client_data->input->name);
+ return err;
+}
+
+//#if defined(CONFIG_USE_QUALCOMM_HAL)
+static int bmi_gyro_input_init(struct bmi_client_data *client_data)
+{
+ struct input_dev *dev;
+ int err = 0;
+
+ dev = input_allocate_device();
+ if (NULL == dev)
+ return -ENOMEM;
+ dev->name = "bmi160-gyro";
+ dev->id.bustype = BUS_I2C;
+ input_set_capability(dev, EV_ABS, ABS_MISC);
+ input_set_capability(dev, EV_MSC, MSC_GESTURE);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_SGM);
+
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_FAST_GYRO_CALIB_DONE);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_STEP_DETECTOR);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_FAST_ACC_CALIB_DONE);
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ input_set_abs_params(dev, ABS_RX,
+ BMI160_ACCEL_MIN_VALUE, BMI160_ACCEL_MAX_VALUE,
+ 0, 0);
+ input_set_abs_params(dev, ABS_RY,
+ BMI160_ACCEL_MIN_VALUE, BMI160_ACCEL_MAX_VALUE,
+ 0, 0);
+ input_set_abs_params(dev, ABS_RZ,
+ BMI160_ACCEL_MIN_VALUE, BMI160_ACCEL_MAX_VALUE,
+ 0, 0);
+ #endif
+ input_set_drvdata(dev, client_data);
+ err = input_register_device(dev);
+ if (err < 0) {
+ input_free_device(dev);
+ dev_notice(client_data->dev, "bmi160 input free!\n");
+ return err;
+ }
+ client_data->gyro_input = dev;
+ dev_notice(client_data->dev,
+ "bmi160 input register successfully, %s!\n",
+ client_data->gyro_input->name);
+ return err;
+}
+//#endif
+static void bmi_input_destroy(struct bmi_client_data *client_data)
+{
+ struct input_dev *dev = client_data->input;
+
+ input_unregister_device(dev);
+ input_free_device(dev);
+}
+
+static int bmi_check_chip_id(struct bmi_client_data *client_data)
+{
+ int8_t err = 0;
+ int8_t i = 0;
+ uint8_t chip_id = 0;
+ uint8_t read_count = 0;
+ u8 bmi_sensor_cnt = sizeof(sensor_type_map)
+ / sizeof(struct bmi160_type_mapping_type);
+ /* read and check chip id */
+ while (read_count++ < CHECK_CHIP_ID_TIME_MAX) {
+ if (client_data->device.bus_read(client_data->device.dev_addr,
+ BMI_REG_NAME(USER_CHIP_ID), &chip_id, 1) < 0) {
+
+ dev_err(client_data->dev,
+ "Bosch Sensortec Device not found"
+ "read chip_id:%d\n", chip_id);
+ continue;
+ } else {
+ for (i = 0; i < bmi_sensor_cnt; i++) {
+ if (sensor_type_map[i].chip_id == chip_id) {
+ client_data->chip_id = chip_id;
+ dev_notice(client_data->dev,
+ "Bosch Sensortec Device detected, "
+ "HW IC name: %s\n", sensor_type_map[i].sensor_name);
+ return 0;
+ }
+ }
+ if (i < bmi_sensor_cnt)
+ break;
+ else {
+ if (read_count == CHECK_CHIP_ID_TIME_MAX) {
+ dev_err(client_data->dev,
+ "Failed!Bosch Sensortec Device not found"
+ " mismatch chip_id:%d\n", chip_id);
+ err = -ENODEV;
+ return err;
+ }
+ }
+ bmi_delay(1);
+ }
+ }
+ err = -ENODEV;
+ return err;
+
+}
+
+static int bmi_pmu_set_suspend(struct bmi_client_data *client_data)
+{
+ int err = 0;
+ if (client_data == NULL)
+ return -EINVAL;
+ else {
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_acc_arr[SENSOR_PM_SUSPEND]);
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[SENSOR_PM_SUSPEND]);
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_mag_arr[SENSOR_PM_SUSPEND]);
+ client_data->pw.acc_pm = BMI_ACC_PM_SUSPEND;
+ client_data->pw.gyro_pm = BMI_GYRO_PM_SUSPEND;
+ client_data->pw.mag_pm = BMI_MAG_PM_SUSPEND;
+ }
+
+ return err;
+}
+
+static int bmi_get_err_status(struct bmi_client_data *client_data)
+{
+ int err = 0;
+
+ err = BMI_CALL_API(get_error_status)(&client_data->err_st.fatal_err,
+ &client_data->err_st.err_code, &client_data->err_st.i2c_fail,
+ &client_data->err_st.drop_cmd, &client_data->err_st.mag_drdy_err);
+ return err;
+}
+
+static void bmi_work_func(struct work_struct *work)
+{
+ struct bmi_client_data *client_data =
+ container_of((struct delayed_work *)work,
+ struct bmi_client_data, work);
+ unsigned long delay =
+ msecs_to_jiffies(atomic_read(&client_data->delay));
+ struct bmi160_accel_t data;
+ int err;
+
+ err = BMI_CALL_API(read_accel_xyz)(&data);
+ if (err < 0)
+ return;
+
+ /*report current frame via input event*/
+ input_event(client_data->input, EV_REL, REL_X, data.x);
+ input_event(client_data->input, EV_REL, REL_Y, data.y);
+ input_event(client_data->input, EV_REL, REL_Z, data.z);
+ input_sync(client_data->input);
+
+ schedule_delayed_work(&client_data->work, delay);
+}
+
+static ssize_t bmi160_chip_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "0x%x\n", client_data->chip_id);
+}
+
+static ssize_t bmi160_err_st_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err = 0;
+ err = bmi_get_err_status(client_data);
+ if (err)
+ return err;
+ else {
+ return snprintf(buf, 128, "fatal_err:0x%x, err_code:%d,\n\n"
+ "i2c_fail_err:%d, drop_cmd_err:%d, mag_drdy_err:%d\n",
+ client_data->err_st.fatal_err,
+ client_data->err_st.err_code,
+ client_data->err_st.i2c_fail,
+ client_data->err_st.drop_cmd,
+ client_data->err_st.mag_drdy_err);
+
+ }
+}
+
+static ssize_t bmi160_sensor_time_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ u32 sensor_time;
+ err = BMI_CALL_API(get_sensor_time)(&sensor_time);
+ if (err)
+ return err;
+ else
+ return snprintf(buf, 16, "0x%x\n", (unsigned int)sensor_time);
+}
+
+static ssize_t bmi160_fifo_flush_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long enable;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &enable);
+ if (err)
+ return err;
+ if (enable)
+ err = BMI_CALL_API(set_command_register)(CMD_CLR_FIFO_DATA);
+
+ if (err)
+ dev_err(client_data->dev, "fifo flush failed!\n");
+
+ return count;
+
+}
+
+
+static ssize_t bmi160_fifo_bytecount_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned int fifo_bytecount = 0;
+
+ BMI_CALL_API(fifo_length)(&fifo_bytecount);
+ err = snprintf(buf, 16, "%u\n", fifo_bytecount);
+ return err;
+}
+
+static ssize_t bmi160_fifo_bytecount_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ client_data->fifo_bytecount = (unsigned int) data;
+
+ return count;
+}
+
+int bmi160_fifo_data_sel_get(struct bmi_client_data *client_data)
+{
+ int err = 0;
+ unsigned char fifo_acc_en, fifo_gyro_en, fifo_mag_en;
+ unsigned char fifo_datasel;
+
+ err += BMI_CALL_API(get_fifo_accel_enable)(&fifo_acc_en);
+ err += BMI_CALL_API(get_fifo_gyro_enable)(&fifo_gyro_en);
+ err += BMI_CALL_API(get_fifo_mag_enable)(&fifo_mag_en);
+
+ if (err)
+ return err;
+
+ fifo_datasel = (fifo_acc_en << BMI_ACC_SENSOR) |
+ (fifo_gyro_en << BMI_GYRO_SENSOR) |
+ (fifo_mag_en << BMI_MAG_SENSOR);
+
+ client_data->fifo_data_sel = fifo_datasel;
+
+ return err;
+
+
+}
+
+static ssize_t bmi160_fifo_data_sel_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ err = bmi160_fifo_data_sel_get(client_data);
+ if (err) {
+ dev_err(client_data->dev, "get fifo_sel failed!\n");
+ return -EINVAL;
+ }
+ return snprintf(buf, 16, "%d\n", client_data->fifo_data_sel);
+}
+
+/* write any value to clear all the fifo data. */
+static ssize_t bmi160_fifo_data_sel_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+ unsigned char fifo_datasel;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /* data format: aimed 0b0000 0x(m)x(g)x(a), x:1 enable, 0:disable*/
+ if (data > 7)
+ return -EINVAL;
+
+
+ fifo_datasel = (unsigned char)data;
+
+
+ err += BMI_CALL_API(set_fifo_accel_enable)
+ ((fifo_datasel & (1 << BMI_ACC_SENSOR)) ? 1 : 0);
+ err += BMI_CALL_API(set_fifo_gyro_enable)
+ (fifo_datasel & (1 << BMI_GYRO_SENSOR) ? 1 : 0);
+ err += BMI_CALL_API(set_fifo_mag_enable)
+ ((fifo_datasel & (1 << BMI_MAG_SENSOR)) ? 1 : 0);
+
+ err += BMI_CALL_API(set_command_register)(CMD_CLR_FIFO_DATA);
+ if (err)
+ return -EIO;
+ else {
+ dev_notice(client_data->dev, "FIFO A_en:%d, G_en:%d, M_en:%d\n",
+ (fifo_datasel & (1 << BMI_ACC_SENSOR)) ? 1 : 0,
+ (fifo_datasel & (1 << BMI_GYRO_SENSOR) ? 1 : 0),
+ ((fifo_datasel & (1 << BMI_MAG_SENSOR)) ? 1 : 0));
+ client_data->fifo_data_sel = fifo_datasel;
+ }
+ return count;
+}
+
+static ssize_t bmi160_fifo_data_out_frame_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ int err = 0;
+ uint32_t fifo_bytecount = 0;
+
+ err = BMI_CALL_API(fifo_length)(&fifo_bytecount);
+ if (err < 0) {
+ dev_err(client_data->dev, "read fifo_length err");
+ return -EINVAL;
+ }
+ if (fifo_bytecount == 0)
+ return 0;
+ err = bmi_burst_read_wrapper(client_data->device.dev_addr,
+ BMI160_USER_FIFO_DATA__REG, buf,
+ fifo_bytecount);
+ if (err) {
+ dev_err(client_data->dev, "read fifo err");
+ BMI_CALL_API(set_command_register)(CMD_CLR_FIFO_DATA);
+ return -EINVAL;
+ }
+ return fifo_bytecount;
+
+}
+
+static ssize_t bmi160_fifo_watermark_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char data = 0xff;
+
+ err = BMI_CALL_API(get_fifo_wm)(&data);
+
+ if (err)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_fifo_watermark_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long data;
+ unsigned char fifo_watermark;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ fifo_watermark = (unsigned char)data;
+ err = BMI_CALL_API(set_fifo_wm)(fifo_watermark);
+ if (err)
+ return -EIO;
+
+ return count;
+}
+
+
+static ssize_t bmi160_fifo_header_en_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char data = 0xff;
+
+ err = BMI_CALL_API(get_fifo_header_enable)(&data);
+
+ if (err)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_fifo_header_en_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+ unsigned char fifo_header_en;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ if (data > 1)
+ return -ENOENT;
+
+ fifo_header_en = (unsigned char)data;
+ err = BMI_CALL_API(set_fifo_header_enable)(fifo_header_en);
+ if (err)
+ return -EIO;
+
+ client_data->fifo_head_en = fifo_header_en;
+
+ return count;
+}
+
+static ssize_t bmi160_fifo_time_en_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char data = 0;
+
+ err = BMI_CALL_API(get_fifo_time_enable)(&data);
+
+ if (!err)
+ err = snprintf(buf, 16, "%d\n", data);
+
+ return err;
+}
+
+static ssize_t bmi160_fifo_time_en_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long data;
+ unsigned char fifo_ts_en;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ fifo_ts_en = (unsigned char)data;
+
+ err = BMI_CALL_API(set_fifo_time_enable)(fifo_ts_en);
+ if (err)
+ return -EIO;
+
+ return count;
+}
+
+static ssize_t bmi160_fifo_int_tag_en_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ unsigned char fifo_tag_int1 = 0;
+ unsigned char fifo_tag_int2 = 0;
+ unsigned char fifo_tag_int;
+
+ err += BMI_CALL_API(get_fifo_tag_intr1_enable)(&fifo_tag_int1);
+ err += BMI_CALL_API(get_fifo_tag_intr2_enable)(&fifo_tag_int2);
+
+ fifo_tag_int = (fifo_tag_int1 << BMI160_INT0) |
+ (fifo_tag_int2 << BMI160_INT1);
+
+ if (!err)
+ err = snprintf(buf, 16, "%d\n", fifo_tag_int);
+
+ return err;
+}
+
+static ssize_t bmi160_fifo_int_tag_en_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+ unsigned char fifo_tag_int_en;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ if (data > 3)
+ return -EINVAL;
+
+ fifo_tag_int_en = (unsigned char)data;
+
+ err += BMI_CALL_API(set_fifo_tag_intr1_enable)
+ ((fifo_tag_int_en & (1 << BMI160_INT0)) ? 1 : 0);
+ err += BMI_CALL_API(set_fifo_tag_intr2_enable)
+ ((fifo_tag_int_en & (1 << BMI160_INT1)) ? 1 : 0);
+
+ if (err) {
+ dev_err(client_data->dev, "fifo int tag en err:%d\n", err);
+ return -EIO;
+ }
+ client_data->fifo_int_tag_en = fifo_tag_int_en;
+
+ return count;
+}
+
+static int bmi160_set_acc_op_mode(struct bmi_client_data *client_data,
+ unsigned long op_mode)
+{
+ int err = 0;
+ unsigned char stc_enable;
+ unsigned char std_enable;
+ mutex_lock(&client_data->mutex_op_mode);
+
+ if (op_mode < BMI_ACC_PM_MAX) {
+ switch (op_mode) {
+ case BMI_ACC_PM_NORMAL:
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_acc_arr[BMI_ACC_PM_NORMAL]);
+ client_data->pw.acc_pm = BMI_ACC_PM_NORMAL;
+ bmi_delay(10);
+ break;
+ case BMI_ACC_PM_LP1:
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_acc_arr[BMI_ACC_PM_LP1]);
+ client_data->pw.acc_pm = BMI_ACC_PM_LP1;
+ bmi_delay(3);
+ break;
+ case BMI_ACC_PM_SUSPEND:
+ BMI_CALL_API(get_step_counter_enable)(&stc_enable);
+ BMI_CALL_API(get_step_detector_enable)(&std_enable);
+ if ((stc_enable == 0) && (std_enable == 0) &&
+ (client_data->sig_flag == 0)) {
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_acc_arr[BMI_ACC_PM_SUSPEND]);
+ client_data->pw.acc_pm = BMI_ACC_PM_SUSPEND;
+ bmi_delay(10);
+ }
+ break;
+ case BMI_ACC_PM_LP2:
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_acc_arr[BMI_ACC_PM_LP2]);
+ client_data->pw.acc_pm = BMI_ACC_PM_LP2;
+ bmi_delay(3);
+ break;
+ default:
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ } else {
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ return err;
+
+
+}
+
+static ssize_t bmi160_temperature_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ s16 temp = 0xff;
+
+ err = BMI_CALL_API(get_temp)(&temp);
+
+ if (!err)
+ err = snprintf(buf, 16, "0x%x\n", temp);
+
+ return err;
+}
+
+static ssize_t bmi160_place_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int place = BOSCH_SENSOR_PLACE_UNKNOWN;
+
+ if (NULL != client_data->bst_pd)
+ place = client_data->bst_pd->place;
+
+ return snprintf(buf, 16, "%d\n", place);
+}
+
+static ssize_t bmi160_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&client_data->delay));
+
+}
+
+static ssize_t bmi160_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ if (data == 0) {
+ err = -EINVAL;
+ return err;
+ }
+
+ if (data < BMI_DELAY_MIN)
+ data = BMI_DELAY_MIN;
+
+ atomic_set(&client_data->delay, (unsigned int)data);
+
+ return count;
+}
+
+static ssize_t bmi160_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&client_data->wkqueue_en));
+
+}
+
+static ssize_t bmi160_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long enable;
+ int pre_enable = atomic_read(&client_data->wkqueue_en);
+
+ err = kstrtoul(buf, 10, &enable);
+ if (err)
+ return err;
+
+ enable = enable ? 1 : 0;
+ mutex_lock(&client_data->mutex_enable);
+ if (enable) {
+ if (pre_enable == 0) {
+ bmi160_set_acc_op_mode(client_data,
+ BMI_ACC_PM_NORMAL);
+ schedule_delayed_work(&client_data->work,
+ msecs_to_jiffies(atomic_read(&client_data->delay)));
+ atomic_set(&client_data->wkqueue_en, 1);
+ }
+
+ } else {
+ if (pre_enable == 1) {
+ bmi160_set_acc_op_mode(client_data,
+ BMI_ACC_PM_SUSPEND);
+
+ cancel_delayed_work_sync(&client_data->work);
+ atomic_set(&client_data->wkqueue_en, 0);
+ }
+ }
+
+ mutex_unlock(&client_data->mutex_enable);
+
+ return count;
+}
+
+#if defined(BMI160_ENABLE_INT1) || defined(BMI160_ENABLE_INT2)
+/* accel sensor part */
+static ssize_t bmi160_anymot_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char data;
+
+ err = BMI_CALL_API(get_intr_any_motion_durn)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_anymot_duration_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_intr_any_motion_durn)((unsigned char)data);
+ if (err < 0)
+ return -EIO;
+
+ return count;
+}
+
+static ssize_t bmi160_anymot_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = BMI_CALL_API(get_intr_any_motion_thres)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_anymot_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_intr_any_motion_thres)((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_step_detector_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data = 0;
+ u8 step_det;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ err = BMI_CALL_API(get_step_detector_enable)(&step_det);
+ /*bmi160_get_status0_step_int*/
+ if (err < 0)
+ return err;
+/*client_data->std will be updated in bmi_stepdetector_interrupt_handle */
+ if ((step_det == 1) && (client_data->std == 1)) {
+ data = 1;
+ client_data->std = 0;
+ }
+ else {
+ data = 0;
+ }
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_step_detector_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = BMI_CALL_API(get_step_detector_enable)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_step_detector_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_step_detector_enable)((unsigned char)data);
+ if (err < 0)
+ return -EIO;
+ if (data == 0)
+ client_data->pedo_data.wkar_step_detector_status = 0;
+ return count;
+}
+
+static ssize_t bmi160_signification_motion_enable_store(
+ struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /*0x62 (bit 1) INT_MOTION_3 int_sig_mot_sel*/
+ err = BMI_CALL_API(set_intr_significant_motion_select)(
+ (unsigned char)data);
+ if (err < 0)
+ return -EIO;
+ if (data == 1) {
+ err = BMI_CALL_API(set_intr_enable_0)
+ (BMI160_ANY_MOTION_X_ENABLE, 1);
+ err += BMI_CALL_API(set_intr_enable_0)
+ (BMI160_ANY_MOTION_Y_ENABLE, 1);
+ err += BMI_CALL_API(set_intr_enable_0)
+ (BMI160_ANY_MOTION_Z_ENABLE, 1);
+ if (err < 0)
+ return -EIO;
+ enable_irq_wake(client_data->IRQ);
+ client_data->sig_flag = 1;
+ } else {
+ err = BMI_CALL_API(set_intr_enable_0)
+ (BMI160_ANY_MOTION_X_ENABLE, 0);
+ err += BMI_CALL_API(set_intr_enable_0)
+ (BMI160_ANY_MOTION_Y_ENABLE, 0);
+ err += BMI_CALL_API(set_intr_enable_0)
+ (BMI160_ANY_MOTION_Z_ENABLE, 0);
+ if (err < 0)
+ return -EIO;
+ disable_irq_wake(client_data->IRQ);
+ client_data->sig_flag = 0;
+ }
+ return count;
+}
+
+static ssize_t bmi160_signification_motion_enable_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+ /*0x62 (bit 1) INT_MOTION_3 int_sig_mot_sel*/
+ err = BMI_CALL_API(get_intr_significant_motion_select)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static int sigmotion_init_interrupts(u8 sig_map_int_pin)
+{
+ int ret = 0;
+/*0x60 */
+ ret += bmi160_set_intr_any_motion_thres(0x1e);
+/* 0x62(bit 3~2) 0=1.5s */
+ ret += bmi160_set_intr_significant_motion_skip(0);
+/*0x62(bit 5~4) 1=0.5s*/
+ ret += bmi160_set_intr_significant_motion_proof(1);
+/*0x50 (bit 0, 1, 2) INT_EN_0 anymo x y z*/
+ ret += bmi160_map_significant_motion_intr(sig_map_int_pin);
+/*0x62 (bit 1) INT_MOTION_3 int_sig_mot_sel
+close the signification_motion*/
+ ret += bmi160_set_intr_significant_motion_select(0);
+/*close the anymotion interrupt*/
+ ret += BMI_CALL_API(set_intr_enable_0)
+ (BMI160_ANY_MOTION_X_ENABLE, 0);
+ ret += BMI_CALL_API(set_intr_enable_0)
+ (BMI160_ANY_MOTION_Y_ENABLE, 0);
+ ret += BMI_CALL_API(set_intr_enable_0)
+ (BMI160_ANY_MOTION_Z_ENABLE, 0);
+ if (ret)
+ printk(KERN_ERR "bmi160 sig motion failed setting,%d!\n", ret);
+ return ret;
+
+}
+#endif
+
+static ssize_t bmi160_acc_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char range;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = BMI_CALL_API(get_accel_range)(&range);
+ if (err)
+ return err;
+
+ client_data->range.acc_range = range;
+ return snprintf(buf, 16, "%d\n", range);
+}
+
+static ssize_t bmi160_acc_range_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long range;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+
+ err = kstrtoul(buf, 10, &range);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_accel_range)(range);
+ if (err)
+ return -EIO;
+
+ client_data->range.acc_range = range;
+ return count;
+}
+
+static ssize_t bmi160_acc_odr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char acc_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = BMI_CALL_API(get_accel_output_data_rate)(&acc_odr);
+ if (err)
+ return err;
+
+ client_data->odr.acc_odr = acc_odr;
+ return snprintf(buf, 16, "%d\n", acc_odr);
+}
+
+static ssize_t bmi160_acc_odr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long acc_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &acc_odr);
+ if (err)
+ return err;
+
+ if (acc_odr < 1 || acc_odr > 12)
+ return -EIO;
+
+ if (acc_odr < 5)
+ err = BMI_CALL_API(set_accel_under_sampling_parameter)(1);
+ else
+ err = BMI_CALL_API(set_accel_under_sampling_parameter)(0);
+
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_accel_output_data_rate)(acc_odr);
+ if (err)
+ return -EIO;
+ client_data->odr.acc_odr = acc_odr;
+ return count;
+}
+
+static ssize_t bmi160_acc_op_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err = 0;
+ u8 accel_pmu_status = 0;
+ err = BMI_CALL_API(get_accel_power_mode_stat)(
+ &accel_pmu_status);
+
+ if (err)
+ return err;
+ else
+ return snprintf(buf, 32, "reg:%d, val:%d\n", accel_pmu_status,
+ client_data->pw.acc_pm);
+}
+
+static ssize_t bmi160_acc_op_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long op_mode;
+ err = kstrtoul(buf, 10, &op_mode);
+ if (err)
+ return err;
+
+ err = bmi160_set_acc_op_mode(client_data, op_mode);
+ if (err)
+ return err;
+ else
+ return count;
+
+}
+
+static ssize_t bmi160_acc_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bmi160_accel_t data;
+
+ int err;
+
+ err = BMI_CALL_API(read_accel_xyz)(&data);
+ if (err < 0)
+ return err;
+
+ return snprintf(buf, 48, "%hd %hd %hd\n",
+ data.x, data.y, data.z);
+}
+
+static ssize_t bmi160_acc_fast_calibration_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = BMI_CALL_API(get_foc_accel_x)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_acc_fast_calibration_x_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ s8 accel_offset_x = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /* 0: disable, 1: +1g, 2: -1g, 3: 0g */
+ if (data > 3)
+ return -EINVAL;
+
+ err = BMI_CALL_API(set_accel_foc_trigger)(X_AXIS,
+ data, &accel_offset_x);
+ if (err)
+ return -EIO;
+ else
+ client_data->calib_status |=
+ BMI_FAST_CALI_TRUE << BMI_ACC_X_FAST_CALI_RDY;
+ return count;
+}
+
+static ssize_t bmi160_acc_fast_calibration_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = BMI_CALL_API(get_foc_accel_y)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_acc_fast_calibration_y_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ s8 accel_offset_y = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /* 0: disable, 1: +1g, 2: -1g, 3: 0g */
+ if (data > 3)
+ return -EINVAL;
+
+ err = BMI_CALL_API(set_accel_foc_trigger)(Y_AXIS,
+ data, &accel_offset_y);
+ if (err)
+ return -EIO;
+ else
+ client_data->calib_status |=
+ BMI_FAST_CALI_TRUE << BMI_ACC_Y_FAST_CALI_RDY;
+ return count;
+}
+
+static ssize_t bmi160_acc_fast_calibration_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = BMI_CALL_API(get_foc_accel_z)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_acc_fast_calibration_z_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ s8 accel_offset_z = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ unsigned char data1[3] = {0};
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /* 0: disable, 1: +1g, 2: -1g, 3: 0g */
+ if (data > 3)
+ return -EINVAL;
+
+ err = BMI_CALL_API(set_accel_foc_trigger)(Z_AXIS,
+ data, &accel_offset_z);
+ if (err)
+ return -EIO;
+ else
+ client_data->calib_status |=
+ BMI_FAST_CALI_TRUE << BMI_ACC_Z_FAST_CALI_RDY;
+
+ if (client_data->calib_status == BMI_FAST_CALI_ALL_RDY) {
+ err = BMI_CALL_API(get_accel_offset_compensation_xaxis)(
+ &data1[0]);
+ err += BMI_CALL_API(get_accel_offset_compensation_yaxis)(
+ &data1[1]);
+ err += BMI_CALL_API(get_accel_offset_compensation_zaxis)(
+ &data1[2]);
+ dev_info(client_data->dev, "accx %d, accy %d, accz %d\n",
+ data1[0], data1[1], data1[2]);
+ if (err)
+ return -EIO;
+ input_event(client_data->input, EV_MSC,
+ INPUT_EVENT_FAST_ACC_CALIB_DONE,
+ (data1[0] | (data1[1] << 8) | (data1[2] << 16)));
+ input_sync(client_data->input);
+ client_data->calib_status = 0;
+ }
+
+ return count;
+}
+
+static ssize_t bmi160_acc_offset_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = BMI_CALL_API(get_accel_offset_compensation_xaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+
+static ssize_t bmi160_acc_offset_x_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_accel_offset_compensation_xaxis)
+ ((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_acc_offset_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = BMI_CALL_API(get_accel_offset_compensation_yaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_acc_offset_y_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_accel_offset_compensation_yaxis)
+ ((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_acc_offset_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = BMI_CALL_API(get_accel_offset_compensation_zaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_acc_offset_z_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_accel_offset_compensation_zaxis)
+ ((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_test_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ u8 raw_data[15] = {0};
+ unsigned int sensor_time = 0;
+
+ int err;
+ memset(raw_data, 0, sizeof(raw_data));
+
+ err = client_data->device.bus_read(client_data->device.dev_addr,
+ BMI160_USER_DATA_8_GYRO_X_LSB__REG, raw_data, 15);
+ if (err)
+ return err;
+
+ udelay(10);
+ sensor_time = (u32)(raw_data[14] << 16 | raw_data[13] << 8
+ | raw_data[12]);
+
+ return snprintf(buf, 128, "%d %d %d %d %d %d %u",
+ (s16)(raw_data[1] << 8 | raw_data[0]),
+ (s16)(raw_data[3] << 8 | raw_data[2]),
+ (s16)(raw_data[5] << 8 | raw_data[4]),
+ (s16)(raw_data[7] << 8 | raw_data[6]),
+ (s16)(raw_data[9] << 8 | raw_data[8]),
+ (s16)(raw_data[11] << 8 | raw_data[10]),
+ sensor_time);
+
+}
+
+static ssize_t bmi160_step_counter_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = BMI_CALL_API(get_step_counter_enable)(&data);
+
+ client_data->stc_enable = data;
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_step_counter_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_step_counter_enable)((unsigned char)data);
+
+ client_data->stc_enable = data;
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+
+static ssize_t bmi160_step_counter_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_step_mode)((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_step_counter_clc_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = bmi160_clear_step_counter();
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_step_counter_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u16 data;
+ int err;
+ static u16 last_stc_value;
+
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = BMI_CALL_API(read_step_count)(&data);
+
+ if (err < 0)
+ return err;
+ if (data >= last_stc_value) {
+ client_data->pedo_data.last_step_counter_value += (
+ data - last_stc_value);
+ last_stc_value = data;
+ } else
+ last_stc_value = data;
+ return snprintf(buf, 16, "%d\n",
+ client_data->pedo_data.last_step_counter_value);
+}
+
+static ssize_t bmi160_bmi_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ u8 raw_data[12] = {0};
+
+ int err;
+ memset(raw_data, 0, sizeof(raw_data));
+
+ err = client_data->device.bus_read(client_data->device.dev_addr,
+ BMI160_USER_DATA_8_GYRO_X_LSB__REG, raw_data, 12);
+ if (err)
+ return err;
+ /*output:gyro x y z acc x y z*/
+ return snprintf(buf, 96, "%hd %d %hd %hd %hd %hd\n",
+ (s16)(raw_data[1] << 8 | raw_data[0]),
+ (s16)(raw_data[3] << 8 | raw_data[2]),
+ (s16)(raw_data[5] << 8 | raw_data[4]),
+ (s16)(raw_data[7] << 8 | raw_data[6]),
+ (s16)(raw_data[9] << 8 | raw_data[8]),
+ (s16)(raw_data[11] << 8 | raw_data[10]));
+
+}
+
+
+static ssize_t bmi160_selftest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "0x%x\n",
+ atomic_read(&client_data->selftest_result));
+}
+
+static int bmi_restore_hw_cfg(struct bmi_client_data *client);
+
+/*!
+ * @brief store selftest result which make up of acc and gyro
+ * format: 0b 0000 xxxx x:1 failed, 0 success
+ * bit3: gyro_self
+ * bit2..0: acc_self z y x
+ */
+static ssize_t bmi160_selftest_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err = 0;
+ int i = 0;
+
+ u8 acc_selftest = 0;
+ u8 gyro_selftest = 0;
+ u8 bmi_selftest = 0;
+ s16 axis_p_value, axis_n_value;
+ u16 diff_axis[3] = {0xff, 0xff, 0xff};
+ u8 acc_odr, range, acc_selftest_amp, acc_selftest_sign;
+
+ dev_notice(client_data->dev, "Selftest for BMI16x starting.\n");
+
+ client_data->selftest = 1;
+
+ /*soft reset*/
+ err = BMI_CALL_API(set_command_register)(CMD_RESET_USER_REG);
+ msleep(70);
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_acc_arr[BMI_ACC_PM_NORMAL]);
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_NORMAL]);
+ err += BMI_CALL_API(set_accel_under_sampling_parameter)(0);
+ err += BMI_CALL_API(set_accel_output_data_rate)(
+ BMI160_ACCEL_OUTPUT_DATA_RATE_1600HZ);
+
+ /* set to 8G range*/
+ err += BMI_CALL_API(set_accel_range)(BMI160_ACCEL_RANGE_8G);
+ /* set to self amp high */
+ err += BMI_CALL_API(set_accel_selftest_amp)(BMI_SELFTEST_AMP_HIGH);
+
+
+ err += BMI_CALL_API(get_accel_output_data_rate)(&acc_odr);
+ err += BMI_CALL_API(get_accel_range)(&range);
+ err += BMI_CALL_API(get_accel_selftest_amp)(&acc_selftest_amp);
+ err += BMI_CALL_API(read_accel_x)(&axis_n_value);
+
+ dev_info(client_data->dev,
+ "acc_odr:%d, acc_range:%d, acc_selftest_amp:%d, acc_x:%d\n",
+ acc_odr, range, acc_selftest_amp, axis_n_value);
+
+ for (i = X_AXIS; i < AXIS_MAX; i++) {
+ axis_n_value = 0;
+ axis_p_value = 0;
+ /* set every selftest axis */
+ /*set_acc_selftest_axis(param),param x:1, y:2, z:3
+ * but X_AXIS:0, Y_AXIS:1, Z_AXIS:2
+ * so we need to +1*/
+ err += BMI_CALL_API(set_accel_selftest_axis)(i + 1);
+ msleep(50);
+ switch (i) {
+ case X_AXIS:
+ /* set negative sign */
+ err += BMI_CALL_API(set_accel_selftest_sign)(0);
+ err += BMI_CALL_API(get_accel_selftest_sign)(
+ &acc_selftest_sign);
+
+ msleep(60);
+ err += BMI_CALL_API(read_accel_x)(&axis_n_value);
+ dev_info(client_data->dev,
+ "acc_x_selftest_sign:%d, axis_n_value:%d\n",
+ acc_selftest_sign, axis_n_value);
+
+ /* set postive sign */
+ err += BMI_CALL_API(set_accel_selftest_sign)(1);
+ err += BMI_CALL_API(get_accel_selftest_sign)(
+ &acc_selftest_sign);
+
+ msleep(60);
+ err += BMI_CALL_API(read_accel_x)(&axis_p_value);
+ dev_info(client_data->dev,
+ "acc_x_selftest_sign:%d, axis_p_value:%d\n",
+ acc_selftest_sign, axis_p_value);
+ diff_axis[i] = abs(axis_p_value - axis_n_value);
+ break;
+
+ case Y_AXIS:
+ /* set negative sign */
+ err += BMI_CALL_API(set_accel_selftest_sign)(0);
+ msleep(60);
+ err += BMI_CALL_API(read_accel_y)(&axis_n_value);
+ /* set postive sign */
+ err += BMI_CALL_API(set_accel_selftest_sign)(1);
+ msleep(60);
+ err += BMI_CALL_API(read_accel_y)(&axis_p_value);
+ diff_axis[i] = abs(axis_p_value - axis_n_value);
+ break;
+
+ case Z_AXIS:
+ /* set negative sign */
+ err += BMI_CALL_API(set_accel_selftest_sign)(0);
+ msleep(60);
+ err += BMI_CALL_API(read_accel_z)(&axis_n_value);
+ /* set postive sign */
+ err += BMI_CALL_API(set_accel_selftest_sign)(1);
+ msleep(60);
+ err += BMI_CALL_API(read_accel_z)(&axis_p_value);
+ /* also start gyro self test */
+ err += BMI_CALL_API(set_gyro_selftest_start)(1);
+ msleep(60);
+ err += BMI_CALL_API(get_gyro_selftest)(&gyro_selftest);
+
+ diff_axis[i] = abs(axis_p_value - axis_n_value);
+ break;
+ default:
+ err += -EINVAL;
+ break;
+ }
+ if (err) {
+ dev_err(client_data->dev,
+ "Failed selftest axis:%s, p_val=%d, n_val=%d\n",
+ bmi_axis_name[i], axis_p_value, axis_n_value);
+ client_data->selftest = 0;
+ return -EINVAL;
+ }
+
+ /*400mg for acc z axis*/
+ if (Z_AXIS == i) {
+ if (diff_axis[i] < 1639) {
+ acc_selftest |= 1 << i;
+ dev_err(client_data->dev,
+ "Over selftest minimum for "
+ "axis:%s,diff=%d,p_val=%d, n_val=%d\n",
+ bmi_axis_name[i], diff_axis[i],
+ axis_p_value, axis_n_value);
+ }
+ } else {
+ /*800mg for x or y axis*/
+ if (diff_axis[i] < 3277) {
+ acc_selftest |= 1 << i;
+
+ if (bmi_get_err_status(client_data) < 0)
+ return err;
+ dev_err(client_data->dev,
+ "Over selftest minimum for "
+ "axis:%s,diff=%d, p_val=%d, n_val=%d\n",
+ bmi_axis_name[i], diff_axis[i],
+ axis_p_value, axis_n_value);
+ dev_err(client_data->dev, "err_st:0x%x\n",
+ client_data->err_st.err_st_all);
+
+ }
+ }
+
+ }
+ /* gyro_selftest==1,gyro selftest successfully,
+ * but bmi_result bit4 0 is successful, 1 is failed*/
+ bmi_selftest = (acc_selftest & 0x0f) | ((!gyro_selftest) << AXIS_MAX);
+ atomic_set(&client_data->selftest_result, bmi_selftest);
+ /*soft reset*/
+ err = BMI_CALL_API(set_command_register)(CMD_RESET_USER_REG);
+ if (err) {
+ client_data->selftest = 0;
+ return err;
+ }
+ msleep(50);
+
+ bmi_restore_hw_cfg(client_data);
+
+ client_data->selftest = 0;
+ dev_notice(client_data->dev, "Selftest for BMI16x finished\n");
+
+ return count;
+}
+
+/* gyro sensor part */
+static ssize_t bmi160_gyro_op_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int err = 0;
+ u8 gyro_pmu_status = 0;
+
+ err = BMI_CALL_API(get_gyro_power_mode_stat)(
+ &gyro_pmu_status);
+
+ if (err)
+ return err;
+ else
+ return snprintf(buf, 32, "reg:%d, val:%d\n", gyro_pmu_status,
+ client_data->pw.gyro_pm);
+}
+
+static ssize_t bmi160_gyro_op_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ unsigned long op_mode;
+ int err;
+
+ err = kstrtoul(buf, 10, &op_mode);
+ if (err)
+ return err;
+
+ mutex_lock(&client_data->mutex_op_mode);
+
+ if (op_mode < BMI_GYRO_PM_MAX) {
+ switch (op_mode) {
+ case BMI_GYRO_PM_NORMAL:
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_NORMAL]);
+ client_data->pw.gyro_pm = BMI_GYRO_PM_NORMAL;
+ bmi_delay(60);
+ break;
+ case BMI_GYRO_PM_FAST_START:
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_FAST_START]);
+ client_data->pw.gyro_pm = BMI_GYRO_PM_FAST_START;
+ bmi_delay(60);
+ break;
+ case BMI_GYRO_PM_SUSPEND:
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_SUSPEND]);
+ client_data->pw.gyro_pm = BMI_GYRO_PM_SUSPEND;
+ bmi_delay(60);
+ break;
+ default:
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ } else {
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ if (err)
+ return err;
+ else
+ return count;
+
+}
+
+static ssize_t bmi160_gyro_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bmi160_gyro_t data;
+ int err;
+
+ err = BMI_CALL_API(read_gyro_xyz)(&data);
+ if (err < 0)
+ return err;
+
+
+ return snprintf(buf, 48, "%hd %hd %hd\n", data.x,
+ data.y, data.z);
+}
+
+static ssize_t bmi160_gyro_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char range;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = BMI_CALL_API(get_gyro_range)(&range);
+ if (err)
+ return err;
+
+ client_data->range.gyro_range = range;
+ return snprintf(buf, 16, "%d\n", range);
+}
+
+static ssize_t bmi160_gyro_range_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long range;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &range);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_gyro_range)(range);
+ if (err)
+ return -EIO;
+
+ client_data->range.gyro_range = range;
+ return count;
+}
+
+static ssize_t bmi160_gyro_odr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char gyro_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = BMI_CALL_API(get_gyro_output_data_rate)(&gyro_odr);
+ if (err)
+ return err;
+
+ client_data->odr.gyro_odr = gyro_odr;
+ return snprintf(buf, 16, "%d\n", gyro_odr);
+}
+
+static ssize_t bmi160_gyro_odr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long gyro_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &gyro_odr);
+ if (err)
+ return err;
+
+ if (gyro_odr < 6 || gyro_odr > 13)
+ return -EIO;
+
+ err = BMI_CALL_API(set_gyro_output_data_rate)(gyro_odr);
+ if (err)
+ return -EIO;
+
+ client_data->odr.gyro_odr = gyro_odr;
+ return count;
+}
+
+static ssize_t bmi160_gyro_fast_calibration_en_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = BMI_CALL_API(get_foc_gyro_enable)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_gyro_fast_calibration_en_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long enable;
+ s8 err;
+ s16 gyr_off_x;
+ s16 gyr_off_y;
+ s16 gyr_off_z;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &enable);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_foc_gyro_enable)((u8)enable,
+ &gyr_off_x, &gyr_off_y, &gyr_off_z);
+
+ if (err < 0)
+ return -EIO;
+ else {
+ input_event(client_data->input, EV_MSC,
+ INPUT_EVENT_FAST_GYRO_CALIB_DONE, 1);
+ input_sync(client_data->input);
+ }
+ return count;
+}
+
+static ssize_t bmi160_gyro_offset_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s16 data = 0;
+ s8 err = 0;
+
+ err = BMI_CALL_API(get_gyro_offset_compensation_xaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_gyro_offset_x_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ s8 err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_gyro_offset_compensation_xaxis)((s16)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_gyro_offset_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s16 data = 0;
+ s8 err = 0;
+
+ err = BMI_CALL_API(get_gyro_offset_compensation_yaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_gyro_offset_y_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ s8 err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_gyro_offset_compensation_yaxis)((s16)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_gyro_offset_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s16 data = 0;
+ int err = 0;
+
+ err = BMI_CALL_API(get_gyro_offset_compensation_zaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t bmi160_gyro_offset_z_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = BMI_CALL_API(set_gyro_offset_compensation_zaxis)((s16)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+
+/* mag sensor part */
+#ifdef BMI160_MAG_INTERFACE_SUPPORT
+static ssize_t bmi160_mag_op_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ u8 mag_op_mode;
+ s8 err;
+ err = bmi160_get_mag_power_mode_stat(&mag_op_mode);
+ if (err) {
+ dev_err(client_data->dev,
+ "Failed to get BMI160 mag power mode:%d\n", err);
+ return err;
+ } else
+ return snprintf(buf, 32, "%d, reg:%d\n",
+ client_data->pw.mag_pm, mag_op_mode);
+}
+
+static ssize_t bmi160_mag_op_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ unsigned long op_mode;
+ int err;
+
+ err = kstrtoul(buf, 10, &op_mode);
+ if (err)
+ return err;
+
+ if (op_mode == client_data->pw.mag_pm)
+ return count;
+
+ mutex_lock(&client_data->mutex_op_mode);
+
+
+ if (op_mode < BMI_MAG_PM_MAX) {
+ switch (op_mode) {
+ case BMI_MAG_PM_NORMAL:
+ /* need to modify as mag sensor connected,
+ * set write address to 0x4c and triggers
+ * write operation
+ * 0x4c(op mode control reg)
+ * enables normal mode in magnetometer */
+#if defined(BMI160_AKM09912_SUPPORT)
+ err = bmi160_set_bst_akm_and_secondary_if_powermode(
+ BMI160_MAG_FORCE_MODE);
+#else
+ err = bmi160_set_bmm150_mag_and_secondary_if_power_mode(
+ BMI160_MAG_FORCE_MODE);
+#endif
+ client_data->pw.mag_pm = BMI_MAG_PM_NORMAL;
+ bmi_delay(5);
+ break;
+ case BMI_MAG_PM_LP1:
+ /* need to modify as mag sensor connected,
+ * set write address to 0x4 band triggers
+ * write operation
+ * 0x4b(bmm150, power control reg, bit0)
+ * enables power in magnetometer*/
+#if defined(BMI160_AKM09912_SUPPORT)
+ err = bmi160_set_bst_akm_and_secondary_if_powermode(
+ BMI160_MAG_FORCE_MODE);
+#else
+ err = bmi160_set_bmm150_mag_and_secondary_if_power_mode(
+ BMI160_MAG_FORCE_MODE);
+#endif
+ client_data->pw.mag_pm = BMI_MAG_PM_LP1;
+ bmi_delay(5);
+ break;
+ case BMI_MAG_PM_SUSPEND:
+ case BMI_MAG_PM_LP2:
+#if defined(BMI160_AKM09912_SUPPORT)
+ err = bmi160_set_bst_akm_and_secondary_if_powermode(
+ BMI160_MAG_SUSPEND_MODE);
+#else
+ err = bmi160_set_bmm150_mag_and_secondary_if_power_mode(
+ BMI160_MAG_SUSPEND_MODE);
+#endif
+ client_data->pw.mag_pm = op_mode;
+ bmi_delay(5);
+ break;
+ default:
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ } else {
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ if (err) {
+ dev_err(client_data->dev,
+ "Failed to switch BMI160 mag power mode:%d\n",
+ client_data->pw.mag_pm);
+ return err;
+ } else
+ return count;
+
+}
+
+static ssize_t bmi160_mag_odr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ unsigned char mag_odr = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = BMI_CALL_API(get_mag_output_data_rate)(&mag_odr);
+ if (err)
+ return err;
+
+ client_data->odr.mag_odr = mag_odr;
+ return snprintf(buf, 16, "%d\n", mag_odr);
+}
+
+static ssize_t bmi160_mag_odr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long mag_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &mag_odr);
+ if (err)
+ return err;
+ /*1~25/32hz,..6(25hz),7(50hz),... */
+ err = BMI_CALL_API(set_mag_output_data_rate)(mag_odr);
+ if (err)
+ return -EIO;
+
+ client_data->odr.mag_odr = mag_odr;
+ return count;
+}
+
+static ssize_t bmi160_mag_i2c_address_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ s8 err;
+
+ err = BMI_CALL_API(set_mag_manual_enable)(1);
+ err += BMI_CALL_API(get_i2c_device_addr)(&data);
+ err += BMI_CALL_API(set_mag_manual_enable)(0);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "0x%x\n", data);
+}
+
+static ssize_t bmi160_mag_i2c_address_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err += BMI_CALL_API(set_mag_manual_enable)(1);
+ if (!err)
+ err += BMI_CALL_API(set_i2c_device_addr)((unsigned char)data);
+ err += BMI_CALL_API(set_mag_manual_enable)(0);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_mag_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ struct bmi160_mag_xyz_s32_t data;
+ int err;
+ /* raw data with compensation */
+#if defined(BMI160_AKM09912_SUPPORT)
+ err = bmi160_bst_akm09912_compensate_xyz(&data);
+#else
+ err = bmi160_bmm150_mag_compensate_xyz(&data);
+#endif
+
+ if (err < 0) {
+ memset(&data, 0, sizeof(data));
+ dev_err(client_data->dev, "mag not ready!\n");
+ }
+ return snprintf(buf, 48, "%hd %hd %hd\n", data.x,
+ data.y, data.z);
+}
+static ssize_t bmi160_mag_offset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ unsigned char mag_offset;
+ err = BMI_CALL_API(get_mag_offset)(&mag_offset);
+ if (err)
+ return err;
+
+ return snprintf(buf, 16, "%d\n", mag_offset);
+
+}
+
+static ssize_t bmi160_mag_offset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err += BMI_CALL_API(set_mag_manual_enable)(1);
+ if (err == 0)
+ err += BMI_CALL_API(set_mag_offset)((unsigned char)data);
+ err += BMI_CALL_API(set_mag_manual_enable)(0);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t bmi160_mag_chip_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s8 err = 0;
+ u8 mag_chipid;
+
+ err = bmi160_set_mag_manual_enable(0x01);
+ /* read mag chip_id value */
+#if defined(BMI160_AKM09912_SUPPORT)
+ err += bmi160_set_mag_read_addr(AKM09912_CHIP_ID_REG);
+ /* 0x04 is mag_x lsb register */
+ err += bmi160_read_reg(BMI160_USER_DATA_0_MAG_X_LSB__REG,
+ &mag_chipid, 1);
+
+ /* Must add this commands to re-set data register addr of mag sensor */
+ err += bmi160_set_mag_read_addr(AKM_DATA_REGISTER);
+#else
+ err += bmi160_set_mag_read_addr(BMI160_BMM150_CHIP_ID);
+ /* 0x04 is mag_x lsb register */
+ err += bmi160_read_reg(BMI160_USER_DATA_0_MAG_X_LSB__REG,
+ &mag_chipid, 1);
+
+ /* Must add this commands to re-set data register addr of mag sensor */
+ /* 0x42 is bmm150 data register address */
+ err += bmi160_set_mag_read_addr(BMI160_BMM150_DATA_REG);
+#endif
+
+ err += bmi160_set_mag_manual_enable(0x00);
+
+ if (err)
+ return err;
+
+ return snprintf(buf, 16, "%x\n", mag_chipid);
+
+}
+
+static ssize_t bmi160_mag_chip_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 mag_chipid = 0;
+#if defined(BMI160_AKM09912_SUPPORT)
+ mag_chipid = 15;
+#else
+ mag_chipid = 150;
+#endif
+ return snprintf(buf, 16, "%d\n", mag_chipid);
+}
+
+struct bmi160_mag_xyz_s32_t mag_compensate;
+static ssize_t bmi160_mag_compensate_xyz_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ memcpy(buf, &mag_compensate, sizeof(mag_compensate));
+ return sizeof(mag_compensate);
+}
+static ssize_t bmi160_mag_compensate_xyz_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct bmi160_mag_xyzr_t mag_raw;
+ memset(&mag_compensate, 0, sizeof(mag_compensate));
+ memset(&mag_raw, 0, sizeof(mag_raw));
+ mag_raw.x = (buf[1] << 8 | buf[0]);
+ mag_raw.y = (buf[3] << 8 | buf[2]);
+ mag_raw.z = (buf[5] << 8 | buf[4]);
+ mag_raw.r = (buf[7] << 8 | buf[6]);
+ mag_raw.x = mag_raw.x >> 3;
+ mag_raw.y = mag_raw.y >> 3;
+ mag_raw.z = mag_raw.z >> 1;
+ mag_raw.r = mag_raw.r >> 2;
+ bmi160_bmm150_mag_compensate_xyz_raw(
+ &mag_compensate, mag_raw);
+ return count;
+}
+
+#endif
+
+#if defined(BMI160_ENABLE_INT1) || defined(BMI160_ENABLE_INT2)
+static ssize_t bmi_enable_int_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int interrupt_type, value;
+
+ sscanf(buf, "%3d %3d", &interrupt_type, &value);
+
+ if (interrupt_type < 0 || interrupt_type > 16)
+ return -EINVAL;
+
+ if (interrupt_type <= BMI_FLAT_INT) {
+ if (BMI_CALL_API(set_intr_enable_0)
+ (bmi_interrupt_type[interrupt_type], value) < 0)
+ return -EINVAL;
+ } else if (interrupt_type <= BMI_FWM_INT) {
+ if (BMI_CALL_API(set_intr_enable_1)
+ (bmi_interrupt_type[interrupt_type], value) < 0)
+ return -EINVAL;
+ } else {
+ if (BMI_CALL_API(set_intr_enable_2)
+ (bmi_interrupt_type[interrupt_type], value) < 0)
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+#endif
+
+static ssize_t bmi160_show_reg_sel(struct device *dev
+ , struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+
+ return snprintf(buf, 64, "reg=0X%02X, len=%d\n",
+ client_data->reg_sel, client_data->reg_len);
+}
+
+static ssize_t bmi160_store_reg_sel(struct device *dev
+ , struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ ssize_t ret;
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+ ret = sscanf(buf, "%11X %11d",
+ &client_data->reg_sel, &client_data->reg_len);
+ if (ret != 2) {
+ dev_err(client_data->dev, "Invalid argument");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t bmi160_show_reg_val(struct device *dev
+ , struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+
+ ssize_t ret;
+ u8 reg_data[128], i;
+ int pos;
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+
+ ret = bmi_burst_read_wrapper(client_data->device.dev_addr,
+ client_data->reg_sel,
+ reg_data, client_data->reg_len);
+ if (ret < 0) {
+ dev_err(client_data->dev, "Reg op failed");
+ return ret;
+ }
+
+ pos = 0;
+ for (i = 0; i < client_data->reg_len; ++i) {
+ pos += snprintf(buf + pos, 16, "%02X", reg_data[i]);
+ buf[pos++] = (i + 1) % 16 == 0 ? '\n' : ' ';
+ }
+ if (buf[pos - 1] == ' ')
+ buf[pos - 1] = '\n';
+
+ return pos;
+}
+
+static ssize_t bmi160_store_reg_val(struct device *dev
+ , struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ ssize_t ret;
+ u8 reg_data[32];
+ int i, j, status, digit;
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+ status = 0;
+ for (i = j = 0; i < count && j < client_data->reg_len; ++i) {
+ if (buf[i] == ' ' || buf[i] == '\n' || buf[i] == '\t' ||
+ buf[i] == '\r') {
+ status = 0;
+ ++j;
+ continue;
+ }
+ digit = buf[i] & 0x10 ? (buf[i] & 0xF) : ((buf[i] & 0xF) + 9);
+ printk(KERN_INFO "digit is %d", digit);
+ switch (status) {
+ case 2:
+ ++j; /* Fall thru */
+ case 0:
+ reg_data[j] = digit;
+ status = 1;
+ break;
+ case 1:
+ reg_data[j] = reg_data[j] * 16 + digit;
+ status = 2;
+ break;
+ }
+ }
+ if (status > 0)
+ ++j;
+ if (j > client_data->reg_len)
+ j = client_data->reg_len;
+ else if (j < client_data->reg_len) {
+ dev_err(client_data->dev, "Invalid argument");
+ return -EINVAL;
+ }
+ printk(KERN_INFO "Reg data read as");
+ for (i = 0; i < j; ++i)
+ printk(KERN_INFO "%d", reg_data[i]);
+
+ ret = BMI_CALL_API(write_reg)(
+ client_data->reg_sel,
+ reg_data, client_data->reg_len);
+ if (ret < 0) {
+ dev_err(client_data->dev, "Reg op failed");
+ return ret;
+ }
+
+ return count;
+}
+
+static ssize_t bmi160_driver_version_show(struct device *dev
+ , struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmi_client_data *client_data = input_get_drvdata(input);
+ int ret;
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+
+ ret = snprintf(buf, 128, "Driver version: %s\n",
+ DRIVER_VERSION);
+
+ return ret;
+}
+static DEVICE_ATTR(chip_id, S_IRUGO,
+ bmi160_chip_id_show, NULL);
+static DEVICE_ATTR(err_st, S_IRUGO,
+ bmi160_err_st_show, NULL);
+static DEVICE_ATTR(sensor_time, S_IRUGO,
+ bmi160_sensor_time_show, NULL);
+
+static DEVICE_ATTR(selftest, S_IRUGO | S_IWUSR,
+ bmi160_selftest_show, bmi160_selftest_store);
+static DEVICE_ATTR(fifo_flush, S_IRUGO | S_IWUSR,
+ NULL, bmi160_fifo_flush_store);
+static DEVICE_ATTR(fifo_bytecount, S_IRUGO | S_IWUSR,
+ bmi160_fifo_bytecount_show, bmi160_fifo_bytecount_store);
+static DEVICE_ATTR(fifo_data_sel, S_IRUGO | S_IWUSR,
+ bmi160_fifo_data_sel_show, bmi160_fifo_data_sel_store);
+static DEVICE_ATTR(fifo_data_frame, S_IRUGO,
+ bmi160_fifo_data_out_frame_show, NULL);
+
+static DEVICE_ATTR(fifo_watermark, S_IRUGO | S_IWUSR,
+ bmi160_fifo_watermark_show, bmi160_fifo_watermark_store);
+
+static DEVICE_ATTR(fifo_header_en, S_IRUGO | S_IWUSR,
+ bmi160_fifo_header_en_show, bmi160_fifo_header_en_store);
+static DEVICE_ATTR(fifo_time_en, S_IRUGO | S_IWUSR,
+ bmi160_fifo_time_en_show, bmi160_fifo_time_en_store);
+static DEVICE_ATTR(fifo_int_tag_en, S_IRUGO | S_IWUSR,
+ bmi160_fifo_int_tag_en_show, bmi160_fifo_int_tag_en_store);
+
+static DEVICE_ATTR(temperature, S_IRUGO,
+ bmi160_temperature_show, NULL);
+static DEVICE_ATTR(place, S_IRUGO,
+ bmi160_place_show, NULL);
+static DEVICE_ATTR(delay, S_IRUGO | S_IWUSR,
+ bmi160_delay_show, bmi160_delay_store);
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
+ bmi160_enable_show, bmi160_enable_store);
+static DEVICE_ATTR(acc_range, S_IRUGO | S_IWUSR,
+ bmi160_acc_range_show, bmi160_acc_range_store);
+static DEVICE_ATTR(acc_odr, S_IRUGO | S_IWUSR,
+ bmi160_acc_odr_show, bmi160_acc_odr_store);
+static DEVICE_ATTR(acc_op_mode, S_IRUGO | S_IWUSR,
+ bmi160_acc_op_mode_show, bmi160_acc_op_mode_store);
+static DEVICE_ATTR(acc_value, S_IRUGO,
+ bmi160_acc_value_show, NULL);
+static DEVICE_ATTR(acc_fast_calibration_x, S_IRUGO | S_IWUSR,
+ bmi160_acc_fast_calibration_x_show,
+ bmi160_acc_fast_calibration_x_store);
+static DEVICE_ATTR(acc_fast_calibration_y, S_IRUGO | S_IWUSR,
+ bmi160_acc_fast_calibration_y_show,
+ bmi160_acc_fast_calibration_y_store);
+static DEVICE_ATTR(acc_fast_calibration_z, S_IRUGO | S_IWUSR,
+ bmi160_acc_fast_calibration_z_show,
+ bmi160_acc_fast_calibration_z_store);
+static DEVICE_ATTR(acc_offset_x, S_IRUGO | S_IWUSR,
+ bmi160_acc_offset_x_show,
+ bmi160_acc_offset_x_store);
+static DEVICE_ATTR(acc_offset_y, S_IRUGO | S_IWUSR,
+ bmi160_acc_offset_y_show,
+ bmi160_acc_offset_y_store);
+static DEVICE_ATTR(acc_offset_z, S_IRUGO | S_IWUSR,
+ bmi160_acc_offset_z_show,
+ bmi160_acc_offset_z_store);
+static DEVICE_ATTR(test, S_IRUGO,
+ bmi160_test_show, NULL);
+static DEVICE_ATTR(stc_enable, S_IRUGO | S_IWUSR,
+ bmi160_step_counter_enable_show,
+ bmi160_step_counter_enable_store);
+static DEVICE_ATTR(stc_mode, S_IRUGO | S_IWUSR,
+ NULL, bmi160_step_counter_mode_store);
+static DEVICE_ATTR(stc_clc, S_IRUGO | S_IWUSR,
+ NULL, bmi160_step_counter_clc_store);
+static DEVICE_ATTR(stc_value, S_IRUGO,
+ bmi160_step_counter_value_show, NULL);
+static DEVICE_ATTR(reg_sel, S_IRUGO | S_IWUSR,
+ bmi160_show_reg_sel, bmi160_store_reg_sel);
+static DEVICE_ATTR(reg_val, S_IRUGO | S_IWUSR,
+ bmi160_show_reg_val, bmi160_store_reg_val);
+static DEVICE_ATTR(driver_version, S_IRUGO,
+ bmi160_driver_version_show, NULL);
+/* gyro part */
+static DEVICE_ATTR(gyro_op_mode, S_IRUGO | S_IWUSR,
+ bmi160_gyro_op_mode_show, bmi160_gyro_op_mode_store);
+static DEVICE_ATTR(gyro_value, S_IRUGO,
+ bmi160_gyro_value_show, NULL);
+static DEVICE_ATTR(gyro_range, S_IRUGO | S_IWUSR,
+ bmi160_gyro_range_show, bmi160_gyro_range_store);
+static DEVICE_ATTR(gyro_odr, S_IRUGO | S_IWUSR,
+ bmi160_gyro_odr_show, bmi160_gyro_odr_store);
+static DEVICE_ATTR(gyro_fast_calibration_en, S_IRUGO | S_IWUSR,
+bmi160_gyro_fast_calibration_en_show, bmi160_gyro_fast_calibration_en_store);
+static DEVICE_ATTR(gyro_offset_x, S_IRUGO | S_IWUSR,
+bmi160_gyro_offset_x_show, bmi160_gyro_offset_x_store);
+static DEVICE_ATTR(gyro_offset_y, S_IRUGO | S_IWUSR,
+bmi160_gyro_offset_y_show, bmi160_gyro_offset_y_store);
+static DEVICE_ATTR(gyro_offset_z, S_IRUGO | S_IWUSR,
+bmi160_gyro_offset_z_show, bmi160_gyro_offset_z_store);
+
+#ifdef BMI160_MAG_INTERFACE_SUPPORT
+static DEVICE_ATTR(mag_op_mode, S_IRUGO | S_IWUSR,
+ bmi160_mag_op_mode_show, bmi160_mag_op_mode_store);
+static DEVICE_ATTR(mag_odr, S_IRUGO | S_IWUSR,
+ bmi160_mag_odr_show, bmi160_mag_odr_store);
+static DEVICE_ATTR(mag_i2c_addr, S_IRUGO | S_IWUSR,
+ bmi160_mag_i2c_address_show, bmi160_mag_i2c_address_store);
+static DEVICE_ATTR(mag_value, S_IRUGO,
+ bmi160_mag_value_show, NULL);
+static DEVICE_ATTR(mag_offset, S_IRUGO | S_IWUSR,
+ bmi160_mag_offset_show, bmi160_mag_offset_store);
+static DEVICE_ATTR(mag_chip_id, S_IRUGO,
+ bmi160_mag_chip_id_show, NULL);
+static DEVICE_ATTR(mag_chip_name, S_IRUGO,
+ bmi160_mag_chip_name_show, NULL);
+static DEVICE_ATTR(mag_compensate, S_IRUGO | S_IWUSR,
+ bmi160_mag_compensate_xyz_show,
+ bmi160_mag_compensate_xyz_store);
+#endif
+
+
+#if defined(BMI160_ENABLE_INT1) || defined(BMI160_ENABLE_INT2)
+static DEVICE_ATTR(enable_int, S_IRUGO | S_IWUSR,
+ NULL, bmi_enable_int_store);
+static DEVICE_ATTR(anymot_duration, S_IRUGO | S_IWUSR,
+ bmi160_anymot_duration_show, bmi160_anymot_duration_store);
+static DEVICE_ATTR(anymot_threshold, S_IRUGO | S_IWUSR,
+ bmi160_anymot_threshold_show, bmi160_anymot_threshold_store);
+static DEVICE_ATTR(std_stu, S_IRUGO,
+ bmi160_step_detector_status_show, NULL);
+static DEVICE_ATTR(std_en, S_IRUGO | S_IWUSR,
+ bmi160_step_detector_enable_show,
+ bmi160_step_detector_enable_store);
+static DEVICE_ATTR(sig_en, S_IRUGO | S_IWUSR,
+ bmi160_signification_motion_enable_show,
+ bmi160_signification_motion_enable_store);
+
+#endif
+
+
+
+static DEVICE_ATTR(bmi_value, S_IRUGO,
+ bmi160_bmi_value_show, NULL);
+
+
+static struct attribute *bmi160_attributes[] = {
+ &dev_attr_chip_id.attr,
+ &dev_attr_err_st.attr,
+ &dev_attr_sensor_time.attr,
+ &dev_attr_selftest.attr,
+ &dev_attr_driver_version.attr,
+ &dev_attr_test.attr,
+ &dev_attr_fifo_flush.attr,
+ &dev_attr_fifo_header_en.attr,
+ &dev_attr_fifo_time_en.attr,
+ &dev_attr_fifo_int_tag_en.attr,
+ &dev_attr_fifo_bytecount.attr,
+ &dev_attr_fifo_data_sel.attr,
+ &dev_attr_fifo_data_frame.attr,
+
+ &dev_attr_fifo_watermark.attr,
+
+ &dev_attr_enable.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_temperature.attr,
+ &dev_attr_place.attr,
+
+ &dev_attr_acc_range.attr,
+ &dev_attr_acc_odr.attr,
+ &dev_attr_acc_op_mode.attr,
+ &dev_attr_acc_value.attr,
+
+ &dev_attr_acc_fast_calibration_x.attr,
+ &dev_attr_acc_fast_calibration_y.attr,
+ &dev_attr_acc_fast_calibration_z.attr,
+ &dev_attr_acc_offset_x.attr,
+ &dev_attr_acc_offset_y.attr,
+ &dev_attr_acc_offset_z.attr,
+
+ &dev_attr_stc_enable.attr,
+ &dev_attr_stc_mode.attr,
+ &dev_attr_stc_clc.attr,
+ &dev_attr_stc_value.attr,
+
+ &dev_attr_gyro_op_mode.attr,
+ &dev_attr_gyro_value.attr,
+ &dev_attr_gyro_range.attr,
+ &dev_attr_gyro_odr.attr,
+ &dev_attr_gyro_fast_calibration_en.attr,
+ &dev_attr_gyro_offset_x.attr,
+ &dev_attr_gyro_offset_y.attr,
+ &dev_attr_gyro_offset_z.attr,
+
+#ifdef BMI160_MAG_INTERFACE_SUPPORT
+ &dev_attr_mag_chip_id.attr,
+ &dev_attr_mag_op_mode.attr,
+ &dev_attr_mag_odr.attr,
+ &dev_attr_mag_i2c_addr.attr,
+ &dev_attr_mag_chip_name.attr,
+ &dev_attr_mag_value.attr,
+ &dev_attr_mag_offset.attr,
+ &dev_attr_mag_compensate.attr,
+#endif
+
+#if defined(BMI160_ENABLE_INT1) || defined(BMI160_ENABLE_INT2)
+ &dev_attr_enable_int.attr,
+
+ &dev_attr_anymot_duration.attr,
+ &dev_attr_anymot_threshold.attr,
+ &dev_attr_std_stu.attr,
+ &dev_attr_std_en.attr,
+ &dev_attr_sig_en.attr,
+
+#endif
+ &dev_attr_reg_sel.attr,
+ &dev_attr_reg_val.attr,
+ &dev_attr_bmi_value.attr,
+ NULL
+};
+
+static struct attribute_group bmi160_attribute_group = {
+ .attrs = bmi160_attributes
+};
+
+#if defined(BMI160_ENABLE_INT1) || defined(BMI160_ENABLE_INT2)
+static void bmi_slope_interrupt_handle(struct bmi_client_data *client_data)
+{
+ /* anym_first[0..2]: x, y, z */
+ u8 anym_first[3] = {0};
+ u8 status2;
+ u8 anym_sign;
+ u8 i = 0;
+
+ client_data->device.bus_read(client_data->device.dev_addr,
+ BMI160_USER_INTR_STAT_2_ADDR, &status2, 1);
+ anym_first[0] = BMI160_GET_BITSLICE(status2,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_X);
+ anym_first[1] = BMI160_GET_BITSLICE(status2,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y);
+ anym_first[2] = BMI160_GET_BITSLICE(status2,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z);
+ anym_sign = BMI160_GET_BITSLICE(status2,
+ BMI160_USER_INTR_STAT_2_ANY_MOTION_SIGN);
+
+ for (i = 0; i < 3; i++) {
+ if (anym_first[i]) {
+ /*1: negative*/
+ if (anym_sign)
+ dev_notice(client_data->dev,
+ "Anymotion interrupt happend!"
+ "%s axis, negative sign\n", bmi_axis_name[i]);
+ else
+ dev_notice(client_data->dev,
+ "Anymotion interrupt happend!"
+ "%s axis, postive sign\n", bmi_axis_name[i]);
+ }
+ }
+
+
+}
+
+static void bmi_fifo_watermark_interrupt_handle
+ (struct bmi_client_data *client_data)
+{
+ int err = 0;
+ unsigned int fifo_len0 = 0;
+ unsigned int fifo_frmbytes_ext = 0;
+ unsigned char *fifo_data = NULL;
+ fifo_data = kzalloc(FIFO_DATA_BUFSIZE, GFP_KERNEL);
+ /*TO DO*/
+ if (NULL == fifo_data) {
+ dev_err(client_data->dev, "no memory available");
+ err = -ENOMEM;
+ }
+ bmi_fifo_frame_bytes_extend_calc(client_data, &fifo_frmbytes_ext);
+
+ if (client_data->pw.acc_pm == 2 && client_data->pw.gyro_pm == 2
+ && client_data->pw.mag_pm == 2)
+ printk(KERN_INFO "pw_acc: %d, pw_gyro: %d\n",
+ client_data->pw.acc_pm, client_data->pw.gyro_pm);
+ if (!client_data->fifo_data_sel)
+ printk(KERN_INFO "no selsect sensor fifo, fifo_data_sel:%d\n",
+ client_data->fifo_data_sel);
+
+ err = BMI_CALL_API(fifo_length)(&fifo_len0);
+ client_data->fifo_bytecount = fifo_len0;
+
+ if (client_data->fifo_bytecount == 0 || err)
+ return;
+
+ if (client_data->fifo_bytecount + fifo_frmbytes_ext > FIFO_DATA_BUFSIZE)
+ client_data->fifo_bytecount = FIFO_DATA_BUFSIZE;
+ /* need give attention for the time of burst read*/
+ if (!err) {
+ err = bmi_burst_read_wrapper(client_data->device.dev_addr,
+ BMI160_USER_FIFO_DATA__REG, fifo_data,
+ client_data->fifo_bytecount + fifo_frmbytes_ext);
+ } else
+ dev_err(client_data->dev, "read fifo leght err");
+
+ if (err)
+ dev_err(client_data->dev, "brust read fifo err\n");
+ /*err = bmi_fifo_analysis_handle(client_data, fifo_data,
+ client_data->fifo_bytecount + 20, fifo_out_data);*/
+ if (fifo_data != NULL) {
+ kfree(fifo_data);
+ fifo_data = NULL;
+ }
+
+}
+static void bmi_data_ready_interrupt_handle(
+ struct bmi_client_data *client_data, uint8_t status)
+{
+ uint8_t data12[12] = {0};
+ struct bmi160_accel_t accel;
+ struct bmi160_gyro_t gyro;
+ struct timespec ts;
+ client_data->device.bus_read(client_data->device.dev_addr,
+ BMI160_USER_DATA_8_ADDR, data12, 12);
+ if (status & 0x80)
+ {
+ /*report acc data*/
+ /* Data X */
+ accel.x = (s16)((((s32)((s8)data12[7])) << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[6]));
+ /* Data Y */
+ accel.y = (s16)((((s32)((s8)data12[9])) << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[8]));
+ /* Data Z */
+ accel.z = (s16)((((s32)((s8)data12[11]))<< BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[10]));
+ ts = ns_to_timespec(client_data->timestamp);
+ //printk("acc puneet ts.tv_sec %ld ts.tv_nsec %ld\n",ts.tv_sec,ts.tv_nsec);
+ input_event(client_data->input, EV_MSC, 6, ts.tv_sec);
+ input_event(client_data->input, EV_MSC, 6, ts.tv_nsec);
+ input_event(client_data->input, EV_MSC, MSC_GESTURE, accel.x);
+ input_event(client_data->input, EV_MSC, MSC_RAW, accel.y);
+ input_event(client_data->input, EV_MSC, MSC_SCAN, accel.z);
+ input_sync(client_data->input);
+ }
+ if (status & 0x40)
+ {
+ /*report gyro data*/
+ /* Data X */
+ gyro.x = (s16)((((s32)((s8)data12[1])) << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[0]));
+ /* Data Y */
+ gyro.y = (s16)((((s32)((s8)data12[3])) << BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[2]));
+ /* Data Z */
+ gyro.z = (s16)((((s32)((s8)data12[5]))<< BMI160_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[4]));
+ ts = ns_to_timespec(client_data->timestamp);
+ //printk("gyro puneet ts.tv_sec %ld ts.tv_nsec %ld\n",ts.tv_sec,ts.tv_nsec);
+ input_event(client_data->gyro_input, EV_MSC, 6, ts.tv_sec);
+ input_event(client_data->gyro_input, EV_MSC, 6, ts.tv_nsec);
+ input_event(client_data->gyro_input, EV_MSC, MSC_GESTURE, gyro.x);
+ input_event(client_data->gyro_input, EV_MSC, MSC_RAW, gyro.y);
+ input_event(client_data->gyro_input, EV_MSC, MSC_SCAN, gyro.z);
+ input_sync(client_data->gyro_input);
+ }
+}
+
+static void bmi_signification_motion_interrupt_handle(
+ struct bmi_client_data *client_data)
+{
+ printk(KERN_INFO "bmi_signification_motion_interrupt_handle\n");
+ input_event(client_data->input, EV_MSC, INPUT_EVENT_SGM, 1);
+/*input_report_rel(client_data->input,INPUT_EVENT_SGM,1);*/
+ input_sync(client_data->input);
+ bmi160_set_command_register(CMD_RESET_INT_ENGINE);
+
+}
+static void bmi_stepdetector_interrupt_handle(
+ struct bmi_client_data *client_data)
+{
+ u8 current_step_dector_st = 0;
+ client_data->pedo_data.wkar_step_detector_status++;
+ current_step_dector_st =
+ client_data->pedo_data.wkar_step_detector_status;
+ client_data->std = ((current_step_dector_st == 1) ? 0 : 1);
+
+ input_event(client_data->input, EV_MSC, INPUT_EVENT_STEP_DETECTOR, 1);
+ input_sync(client_data->input);
+}
+
+static void bmi_irq_work_func(struct work_struct *work)
+{
+ struct bmi_client_data *client_data =
+ container_of((struct work_struct *)work,
+ struct bmi_client_data, irq_work);
+
+ unsigned char int_status[4] = {0, 0, 0, 0};
+ uint8_t status = 0;
+
+ //client_data->device.bus_read(client_data->device.dev_addr,
+ // BMI160_USER_INTR_STAT_0_ADDR, int_status, 4);
+ client_data->device.bus_read(client_data->device.dev_addr,
+ BMI160_USER_STAT_ADDR, &status, 1);
+ //printk("status = 0x%x", status);
+ if (BMI160_GET_BITSLICE(int_status[0],
+ BMI160_USER_INTR_STAT_0_ANY_MOTION))
+ bmi_slope_interrupt_handle(client_data);
+
+ if (BMI160_GET_BITSLICE(int_status[0],
+ BMI160_USER_INTR_STAT_0_STEP_INTR))
+ bmi_stepdetector_interrupt_handle(client_data);
+ if (BMI160_GET_BITSLICE(int_status[1],
+ BMI160_USER_INTR_STAT_1_FIFO_WM_INTR))
+ bmi_fifo_watermark_interrupt_handle(client_data);
+ if ((status & 0x80) || (status & 0x40))
+ bmi_data_ready_interrupt_handle(client_data, status);
+ /* Clear ALL inputerrupt status after handler sig mition*/
+ /* Put this commads intot the last one*/
+ if (BMI160_GET_BITSLICE(int_status[0],
+ BMI160_USER_INTR_STAT_0_SIGNIFICANT_INTR))
+ bmi_signification_motion_interrupt_handle(client_data);
+
+}
+
+static void bmi160_delay_sigmo_work_func(struct work_struct *work)
+{
+ struct bmi_client_data *client_data =
+ container_of(work, struct bmi_client_data,
+ delay_work_sig.work);
+ unsigned char int_status[4] = {0, 0, 0, 0};
+
+ client_data->device.bus_read(client_data->device.dev_addr,
+ BMI160_USER_INTR_STAT_0_ADDR, int_status, 4);
+ if (BMI160_GET_BITSLICE(int_status[0],
+ BMI160_USER_INTR_STAT_0_SIGNIFICANT_INTR))
+ bmi_signification_motion_interrupt_handle(client_data);
+}
+
+static irqreturn_t bmi_irq_handler(int irq, void *handle)
+{
+ struct bmi_client_data *client_data = handle;
+ int in_suspend_copy;
+ in_suspend_copy = atomic_read(&client_data->in_suspend);
+ client_data->timestamp= get_current_timestamp();
+ if (client_data == NULL)
+ return IRQ_HANDLED;
+ if (client_data->dev == NULL)
+ return IRQ_HANDLED;
+ /*this only deal with SIG_motion CTS test*/
+ if ((in_suspend_copy == 1) &&
+ (client_data->sig_flag == 1)) {
+ /*wake_lock_timeout(&client_data->wakelock, HZ);*/
+ schedule_delayed_work(&client_data->delay_work_sig,
+ msecs_to_jiffies(50));
+ }
+ schedule_work(&client_data->irq_work);
+
+ return IRQ_HANDLED;
+}
+#endif /* defined(BMI_ENABLE_INT1)||defined(BMI_ENABLE_INT2) */
+
+static int bmi_restore_hw_cfg(struct bmi_client_data *client)
+{
+ int err = 0;
+
+ if ((client->fifo_data_sel) & (1 << BMI_ACC_SENSOR)) {
+ err += BMI_CALL_API(set_accel_range)(client->range.acc_range);
+ err += BMI_CALL_API(set_accel_output_data_rate)
+ (client->odr.acc_odr);
+ err += BMI_CALL_API(set_fifo_accel_enable)(1);
+ }
+ if ((client->fifo_data_sel) & (1 << BMI_GYRO_SENSOR)) {
+ err += BMI_CALL_API(set_gyro_range)(client->range.gyro_range);
+ err += BMI_CALL_API(set_gyro_output_data_rate)
+ (client->odr.gyro_odr);
+ err += BMI_CALL_API(set_fifo_gyro_enable)(1);
+ }
+ if ((client->fifo_data_sel) & (1 << BMI_MAG_SENSOR)) {
+ err += BMI_CALL_API(set_mag_output_data_rate)
+ (client->odr.mag_odr);
+ err += BMI_CALL_API(set_fifo_mag_enable)(1);
+ }
+ err += BMI_CALL_API(set_command_register)(CMD_CLR_FIFO_DATA);
+
+ mutex_lock(&client->mutex_op_mode);
+ if (client->pw.acc_pm != BMI_ACC_PM_SUSPEND) {
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_acc_arr[BMI_ACC_PM_NORMAL]);
+ bmi_delay(3);
+ }
+ mutex_unlock(&client->mutex_op_mode);
+
+ mutex_lock(&client->mutex_op_mode);
+ if (client->pw.gyro_pm != BMI_GYRO_PM_SUSPEND) {
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_NORMAL]);
+ bmi_delay(3);
+ }
+ mutex_unlock(&client->mutex_op_mode);
+
+ mutex_lock(&client->mutex_op_mode);
+
+ if (client->pw.mag_pm != BMI_MAG_PM_SUSPEND) {
+#ifdef BMI160_AKM09912_SUPPORT
+ err += bmi160_set_bst_akm_and_secondary_if_powermode
+ (BMI160_MAG_FORCE_MODE);
+#else
+ err += bmi160_set_bmm150_mag_and_secondary_if_power_mode
+ (BMI160_MAG_FORCE_MODE);
+#endif
+ bmi_delay(3);
+ }
+ mutex_unlock(&client->mutex_op_mode);
+
+ return err;
+}
+
+#if defined(CONFIG_USE_QUALCOMM_HAL)
+static void bmi160_accel_work_fn(struct work_struct *work)
+{
+ struct bmi_client_data *sensor;
+ ktime_t timestamp;
+ struct bmi160_accel_t data;
+ int err;
+ sensor = container_of((struct delayed_work *)work,
+ struct bmi_client_data, accel_poll_work);
+ timestamp = ktime_get();
+ err = BMI_CALL_API(read_accel_xyz)(&data);
+ if (err)
+ dev_err(sensor->dev, "read data err");
+ input_report_abs(sensor->input, ABS_X,
+ (data.x));
+ input_report_abs(sensor->input, ABS_Y,
+ (data.y));
+ input_report_abs(sensor->input, ABS_Z,
+ (data.z));
+ input_event(sensor->input,
+ EV_SYN, SYN_TIME_SEC,
+ ktime_to_timespec(timestamp).tv_sec);
+ input_event(sensor->input, EV_SYN,
+ SYN_TIME_NSEC,
+ ktime_to_timespec(timestamp).tv_nsec);
+ input_sync(sensor->input);
+ if (atomic_read(&sensor->accel_en))
+ queue_delayed_work(sensor->data_wq,
+ &sensor->accel_poll_work,
+ msecs_to_jiffies(sensor->accel_poll_ms));
+}
+static void bmi160_gyro_work_fn(struct work_struct *work)
+{
+ struct bmi_client_data *sensor;
+ ktime_t timestamp;
+ struct bmi160_gyro_t data;
+ int err;
+ sensor = container_of((struct delayed_work *)work,
+ struct bmi_client_data, gyro_poll_work);
+ timestamp = ktime_get();
+ err = BMI_CALL_API(read_gyro_xyz)(&data);
+ if (err)
+ dev_err(sensor->dev, "read data err");
+ input_report_abs(sensor->gyro_input, ABS_RX,
+ (data.x));
+ input_report_abs(sensor->gyro_input, ABS_RY,
+ (data.y));
+ input_report_abs(sensor->gyro_input, ABS_RZ,
+ (data.z));
+ input_event(sensor->gyro_input,
+ EV_SYN, SYN_TIME_SEC,
+ ktime_to_timespec(timestamp).tv_sec);
+ input_event(sensor->gyro_input, EV_SYN,
+ SYN_TIME_NSEC,
+ ktime_to_timespec(timestamp).tv_nsec);
+ input_sync(sensor->gyro_input);
+ if (atomic_read(&sensor->gyro_en))
+ queue_delayed_work(sensor->data_wq,
+ &sensor->gyro_poll_work,
+ msecs_to_jiffies(sensor->gyro_poll_ms));
+}
+static int bmi160_set_gyro_op_mode(struct bmi_client_data *client_data,
+ unsigned long op_mode)
+{
+ int err = 0;
+ mutex_lock(&client_data->mutex_op_mode);
+ if (op_mode < BMI_GYRO_PM_MAX) {
+ switch (op_mode) {
+ case BMI_GYRO_PM_NORMAL:
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_NORMAL]);
+ client_data->pw.gyro_pm = BMI_GYRO_PM_NORMAL;
+ bmi_delay(60);
+ break;
+ case BMI_GYRO_PM_FAST_START:
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_FAST_START]);
+ client_data->pw.gyro_pm = BMI_GYRO_PM_FAST_START;
+ bmi_delay(60);
+ break;
+ case BMI_GYRO_PM_SUSPEND:
+ err = BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_SUSPEND]);
+ client_data->pw.gyro_pm = BMI_GYRO_PM_SUSPEND;
+ bmi_delay(60);
+ break;
+ default:
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ } else {
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ mutex_unlock(&client_data->mutex_op_mode);
+ return err;
+}
+static int bmi160_accel_set_enable(
+ struct bmi_client_data *client_data, bool enable)
+{
+ int ret = 0;
+ dev_notice(client_data->dev,
+ "bmi160_accel_set_enable enable=%d\n", enable);
+ if (enable) {
+ ret = bmi160_set_acc_op_mode(client_data, 0);
+ if (ret) {
+ dev_err(client_data->dev,
+ "Fail to enable accel engine ret=%d\n", ret);
+ ret = -EBUSY;
+ goto exit;
+ }
+ queue_delayed_work(client_data->data_wq,
+ &client_data->accel_poll_work,
+ msecs_to_jiffies(client_data->accel_poll_ms));
+ atomic_set(&client_data->accel_en, 1);
+ } else {
+ atomic_set(&client_data->accel_en, 0);
+ cancel_delayed_work_sync(&client_data->accel_poll_work);
+ ret = bmi160_set_acc_op_mode(client_data, 2);
+ if (ret) {
+ dev_err(client_data->dev,
+ "Fail to disable accel engine ret=%d\n", ret);
+ ret = -EBUSY;
+ goto exit;
+ }
+ }
+exit:
+ return ret;
+}
+static int bmi160_accel_set_poll_delay(struct bmi_client_data *client_data,
+ unsigned long delay)
+{
+ dev_info(client_data->dev,
+ "bmi160_accel_set_poll_delay delay_ms=%ld\n", delay);
+ if (delay < BMI160_ACCEL_MIN_POLL_INTERVAL_MS)
+ delay = BMI160_ACCEL_MIN_POLL_INTERVAL_MS;
+ if (delay > BMI160_ACCEL_MAX_POLL_INTERVAL_MS)
+ delay = BMI160_ACCEL_MAX_POLL_INTERVAL_MS;
+ client_data->accel_poll_ms = delay;
+ if (!atomic_read(&client_data->accel_en))
+ goto exit;
+ cancel_delayed_work_sync(&client_data->accel_poll_work);
+ queue_delayed_work(client_data->data_wq,
+ &client_data->accel_poll_work,
+ msecs_to_jiffies(client_data->accel_poll_ms));
+exit:
+ return 0;
+}
+static int bmi160_gyro_set_enable(
+ struct bmi_client_data *client_data, bool enable)
+{
+ int ret = 0;
+ dev_notice(client_data->dev,
+ "bmi160_gyro_set_enable enable=%d\n", enable);
+ if (enable) {
+ ret = bmi160_set_gyro_op_mode(client_data, 0);
+ if (ret) {
+ dev_err(client_data->dev,
+ "Fail to enable gyro engine ret=%d\n", ret);
+ ret = -EBUSY;
+ goto exit;
+ }
+ queue_delayed_work(client_data->data_wq,
+ &client_data->gyro_poll_work,
+ msecs_to_jiffies(client_data->gyro_poll_ms));
+ atomic_set(&client_data->gyro_en, 1);
+ } else {
+ atomic_set(&client_data->gyro_en, 0);
+ cancel_delayed_work_sync(&client_data->gyro_poll_work);
+ ret = bmi160_set_gyro_op_mode(client_data, 2);
+ if (ret) {
+ dev_err(client_data->dev,
+ "Fail to disable accel engine ret=%d\n", ret);
+ ret = -EBUSY;
+ goto exit;
+ }
+ }
+exit:
+ return ret;
+}
+static int bmi160_gyro_set_poll_delay(struct bmi_client_data *client_data,
+ unsigned long delay)
+{
+ dev_info(client_data->dev,
+ "bmi160_accel_set_poll_delay delay_ms=%ld\n", delay);
+ if (delay < BMI160_GYRO_MIN_POLL_INTERVAL_MS)
+ delay = BMI160_GYRO_MIN_POLL_INTERVAL_MS;
+ if (delay > BMI160_GYRO_MAX_POLL_INTERVAL_MS)
+ delay = BMI160_GYRO_MAX_POLL_INTERVAL_MS;
+ client_data->gyro_poll_ms = delay;
+ if (!atomic_read(&client_data->gyro_en))
+ goto exit;
+ cancel_delayed_work_sync(&client_data->gyro_poll_work);
+ queue_delayed_work(client_data->data_wq,
+ &client_data->gyro_poll_work,
+ msecs_to_jiffies(client_data->gyro_poll_ms));
+exit:
+ return 0;
+}
+static int bmi160_accel_cdev_enable(struct sensors_classdev *sensors_cdev,
+ unsigned int enable)
+{
+ struct bmi_client_data *sensor = container_of(sensors_cdev,
+ struct bmi_client_data, accel_cdev);
+ return bmi160_accel_set_enable(sensor, enable);
+}
+static int bmi160_accel_cdev_poll_delay(struct sensors_classdev *sensors_cdev,
+ unsigned int delay_ms)
+{
+ struct bmi_client_data *sensor = container_of(sensors_cdev,
+ struct bmi_client_data, accel_cdev);
+
+ return bmi160_accel_set_poll_delay(sensor, delay_ms);
+}
+
+static int bmi160_gyro_cdev_enable(struct sensors_classdev *sensors_cdev,
+ unsigned int enable)
+{
+ struct bmi_client_data *sensor = container_of(sensors_cdev,
+ struct bmi_client_data, gyro_cdev);
+
+ return bmi160_gyro_set_enable(sensor, enable);
+}
+
+static int bmi160_gyro_cdev_poll_delay(struct sensors_classdev *sensors_cdev,
+ unsigned int delay_ms)
+{
+ struct bmi_client_data *sensor = container_of(sensors_cdev,
+ struct bmi_client_data, gyro_cdev);
+
+ return bmi160_gyro_set_poll_delay(sensor, delay_ms);
+}
+#endif
+
+int bmi_probe(struct bmi_client_data *client_data, struct device *dev)
+{
+ int err = 0;
+#ifdef BMI160_MAG_INTERFACE_SUPPORT
+ u8 mag_dev_addr;
+ u8 mag_urst_len;
+ u8 mag_op_mode;
+#endif
+ /* check chip id */
+ err = bmi_check_chip_id(client_data);
+ if (err)
+ goto exit_err_clean;
+
+ dev_set_drvdata(dev, client_data);
+ client_data->dev = dev;
+
+ mutex_init(&client_data->mutex_enable);
+ mutex_init(&client_data->mutex_op_mode);
+
+ /* input device init */
+ err = bmi_input_init(client_data);
+ if (err < 0)
+ goto exit_err_clean;
+
+ /* sysfs node creation */
+ err = sysfs_create_group(&client_data->input->dev.kobj,
+ &bmi160_attribute_group);
+
+ if (err < 0)
+ goto exit_err_sysfs;
+
+ if (NULL != dev->platform_data) {
+ client_data->bst_pd = kzalloc(sizeof(*client_data->bst_pd),
+ GFP_KERNEL);
+
+ if (NULL != client_data->bst_pd) {
+ memcpy(client_data->bst_pd, dev->platform_data,
+ sizeof(*client_data->bst_pd));
+ dev_notice(dev, "%s sensor driver set place: p%d\n",
+ client_data->bst_pd->name,
+ client_data->bst_pd->place);
+ }
+ }
+
+ if (NULL != client_data->bst_pd) {
+ memcpy(client_data->bst_pd, dev->platform_data,
+ sizeof(*client_data->bst_pd));
+ dev_notice(dev, "%s sensor driver set place: p%d\n",
+ client_data->bst_pd->name,
+ client_data->bst_pd->place);
+ }
+
+
+ /* workqueue init */
+ INIT_DELAYED_WORK(&client_data->work, bmi_work_func);
+ atomic_set(&client_data->delay, BMI_DELAY_DEFAULT);
+ atomic_set(&client_data->wkqueue_en, 0);
+
+ /* h/w init */
+ client_data->device.delay_msec = bmi_delay;
+ err = BMI_CALL_API(init)(&client_data->device);
+
+ bmi_dump_reg(client_data);
+
+ /*power on detected*/
+ /*or softrest(cmd 0xB6) */
+ /*fatal err check*/
+ /*soft reset*/
+ err += BMI_CALL_API(set_command_register)(CMD_RESET_USER_REG);
+ bmi_delay(3);
+ if (err)
+ dev_err(dev, "Failed soft reset, er=%d", err);
+ /*usr data config page*/
+ err += BMI_CALL_API(set_target_page)(USER_DAT_CFG_PAGE);
+ if (err)
+ dev_err(dev, "Failed cffg page, er=%d", err);
+ err += bmi_get_err_status(client_data);
+ if (err) {
+ dev_err(dev, "Failed to bmi16x init!err_st=0x%x\n",
+ client_data->err_st.err_st_all);
+ goto exit_err_sysfs;
+ }
+
+#ifdef BMI160_MAG_INTERFACE_SUPPORT
+ err += bmi160_set_command_register(MAG_MODE_NORMAL);
+ bmi_delay(2);
+ err += bmi160_get_mag_power_mode_stat(&mag_op_mode);
+ bmi_delay(2);
+ err += BMI_CALL_API(get_i2c_device_addr)(&mag_dev_addr);
+ bmi_delay(2);
+#if defined(BMI160_AKM09912_SUPPORT)
+ err += BMI_CALL_API(set_i2c_device_addr)(BMI160_AKM09912_I2C_ADDRESS);
+ bmi160_bst_akm_mag_interface_init(BMI160_AKM09912_I2C_ADDRESS);
+#else
+ err += BMI_CALL_API(set_i2c_device_addr)(
+ BMI160_AUX_BMM150_I2C_ADDRESS);
+ bmi160_bmm150_mag_interface_init();
+#endif
+
+ err += bmi160_set_mag_burst(3);
+ err += bmi160_get_mag_burst(&mag_urst_len);
+ if (err)
+ dev_err(client_data->dev, "Failed cffg mag, er=%d", err);
+ dev_info(client_data->dev,
+ "BMI160 mag_urst_len:%d, mag_add:0x%x, mag_op_mode:%d\n",
+ mag_urst_len, mag_dev_addr, mag_op_mode);
+#endif
+ if (err < 0)
+ goto exit_err_sysfs;
+
+
+#if defined(BMI160_ENABLE_INT1) || defined(BMI160_ENABLE_INT2)
+ /*wake_lock_init(&client_data->wakelock,
+ WAKE_LOCK_SUSPEND, "bmi160");*/
+ client_data->gpio_pin = of_get_named_gpio_flags(dev->of_node,
+ "bmi,gpio_irq", 0, NULL);
+ dev_info(client_data->dev, "BMI160 qpio number:%d\n",
+ client_data->gpio_pin);
+ err += gpio_request_one(client_data->gpio_pin,
+ GPIOF_IN, "bmi160_int");
+ err += gpio_direction_input(client_data->gpio_pin);
+ client_data->IRQ = gpio_to_irq(client_data->gpio_pin);
+ if (err) {
+ dev_err(client_data->dev,
+ "can not request gpio to irq number\n");
+ client_data->gpio_pin = 0;
+ }
+ INIT_DELAYED_WORK(&client_data->delay_work_sig,
+ bmi160_delay_sigmo_work_func);
+#ifdef BMI160_ENABLE_INT1
+ /* maps interrupt to INT1/InT2 pin */
+ BMI_CALL_API(set_intr_any_motion)(BMI_INT0, ENABLE);
+ BMI_CALL_API(set_intr_fifo_wm)(BMI_INT0, ENABLE);
+ BMI_CALL_API(set_intr_data_rdy)(BMI_INT0, ENABLE);
+
+ /*Set interrupt trige level way */
+ BMI_CALL_API(set_intr_edge_ctrl)(BMI_INT0, BMI_INT_LEVEL);
+ bmi160_set_intr_level(BMI_INT0, 1);
+ /*set interrupt latch temporary, 5 ms*/
+ /*bmi160_set_latch_int(5);*/
+
+ BMI_CALL_API(set_output_enable)(
+ BMI160_INTR1_OUTPUT_ENABLE, ENABLE);
+ sigmotion_init_interrupts(BMI160_MAP_INTR1);
+ BMI_CALL_API(map_step_detector_intr)(BMI160_MAP_INTR1);
+ /*close step_detector in init function*/
+ BMI_CALL_API(set_step_detector_enable)(0);
+#endif
+
+#ifdef BMI160_ENABLE_INT2
+ /* maps interrupt to INT1/InT2 pin */
+ BMI_CALL_API(set_intr_any_motion)(BMI_INT1, ENABLE);
+ BMI_CALL_API(set_intr_fifo_wm)(BMI_INT1, ENABLE);
+ BMI_CALL_API(set_intr_data_rdy)(BMI_INT1, ENABLE);
+
+ /*Set interrupt trige level way */
+ BMI_CALL_API(set_intr_edge_ctrl)(BMI_INT1, BMI_INT_LEVEL);
+ bmi160_set_intr_level(BMI_INT1, 1);
+ /*set interrupt latch temporary, 5 ms*/
+ /*bmi160_set_latch_int(5);*/
+
+ BMI_CALL_API(set_output_enable)(
+ BMI160_INTR2_OUTPUT_ENABLE, ENABLE);
+ sigmotion_init_interrupts(BMI160_MAP_INTR2);
+ BMI_CALL_API(map_step_detector_intr)(BMI160_MAP_INTR2);
+ /*close step_detector in init function*/
+ BMI_CALL_API(set_step_detector_enable)(0);
+#endif
+ err = request_irq(client_data->IRQ, bmi_irq_handler,
+ IRQF_TRIGGER_RISING, "bmi160", client_data);
+ if (err)
+ dev_err(client_data->dev, "could not request irq\n");
+
+ INIT_WORK(&client_data->irq_work, bmi_irq_work_func);
+#endif
+
+ client_data->selftest = 0;
+
+ client_data->fifo_data_sel = 0;
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ BMI_CALL_API(set_accel_output_data_rate)(9);/*defalut odr 200HZ*/
+ BMI_CALL_API(set_gyro_output_data_rate)(9);/*defalut odr 200HZ*/
+ #endif
+ BMI_CALL_API(get_accel_output_data_rate)(&client_data->odr.acc_odr);
+ BMI_CALL_API(get_gyro_output_data_rate)(&client_data->odr.gyro_odr);
+ BMI_CALL_API(get_mag_output_data_rate)(&client_data->odr.mag_odr);
+ BMI_CALL_API(set_fifo_time_enable)(1);
+ BMI_CALL_API(get_accel_range)(&client_data->range.acc_range);
+ BMI_CALL_API(get_gyro_range)(&client_data->range.gyro_range);
+ /* now it's power on which is considered as resuming from suspend */
+
+ /* gyro input device init */
+ err = bmi_gyro_input_init(client_data);
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ /* gyro input device init */
+ err = bmi_gyro_input_init(client_data);
+ if (err < 0)
+ goto exit_err_clean;
+ client_data->accel_poll_ms = BMI160_ACCEL_DEFAULT_POLL_INTERVAL_MS;
+ client_data->gyro_poll_ms = BMI160_GYRO_DEFAULT_POLL_INTERVAL_MS;
+ client_data->data_wq = create_freezable_workqueue("bmi160_data_work");
+ if (!client_data->data_wq) {
+ dev_err(dev, "Cannot create workqueue!\n");
+ goto exit_err_clean;
+ }
+ INIT_DELAYED_WORK(&client_data->accel_poll_work,
+ bmi160_accel_work_fn);
+ client_data->accel_cdev = bmi160_accel_cdev;
+ client_data->accel_cdev.delay_msec = client_data->accel_poll_ms;
+ client_data->accel_cdev.sensors_enable = bmi160_accel_cdev_enable;
+ client_data->accel_cdev.sensors_poll_delay =
+ bmi160_accel_cdev_poll_delay;
+ err = sensors_classdev_register(dev, &client_data->accel_cdev);
+ if (err) {
+ dev_err(dev,
+ "create accel class device file failed!\n");
+ goto exit_err_clean;
+ }
+ INIT_DELAYED_WORK(&client_data->gyro_poll_work, bmi160_gyro_work_fn);
+ client_data->gyro_cdev = bmi160_gyro_cdev;
+ client_data->gyro_cdev.delay_msec = client_data->gyro_poll_ms;
+ client_data->gyro_cdev.sensors_enable = bmi160_gyro_cdev_enable;
+ client_data->gyro_cdev.sensors_poll_delay = bmi160_gyro_cdev_poll_delay;
+ err = sensors_classdev_register(dev, &client_data->gyro_cdev);
+ if (err) {
+ dev_err(dev,
+ "create accel class device file failed!\n");
+ goto exit_err_clean;
+ }
+ #endif
+ /* set sensor PMU into suspend power mode for all */
+ if (bmi_pmu_set_suspend(client_data) < 0) {
+ dev_err(dev, "Failed to set BMI160 to suspend power mode\n");
+ goto exit_err_sysfs;
+ }
+ /*enable the data ready interrupt*/
+ BMI_CALL_API(set_intr_enable_1)(BMI160_DATA_RDY_ENABLE, 1);
+ dev_notice(dev, "sensor_time:%d, %d, %d",
+ sensortime_duration_tbl[0].ts_delat,
+ sensortime_duration_tbl[0].ts_duration_lsb,
+ sensortime_duration_tbl[0].ts_duration_us);
+ dev_notice(dev, "sensor %s probed successfully", SENSOR_NAME);
+
+ return 0;
+
+exit_err_sysfs:
+ if (err)
+ bmi_input_destroy(client_data);
+
+exit_err_clean:
+ if (err) {
+ if (client_data != NULL) {
+ if (NULL != client_data->bst_pd) {
+ kfree(client_data->bst_pd);
+ client_data->bst_pd = NULL;
+ }
+ }
+ }
+ return err;
+}
+EXPORT_SYMBOL(bmi_probe);
+
+/*!
+ * @brief remove bmi client
+ *
+ * @param dev the pointer of device
+ *
+ * @return zero
+ * @retval zero
+*/
+int bmi_remove(struct device *dev)
+{
+ int err = 0;
+ struct bmi_client_data *client_data = dev_get_drvdata(dev);
+
+ if (NULL != client_data) {
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&client_data->early_suspend_handler);
+#endif
+ mutex_lock(&client_data->mutex_enable);
+ if (BMI_ACC_PM_NORMAL == client_data->pw.acc_pm ||
+ BMI_GYRO_PM_NORMAL == client_data->pw.gyro_pm ||
+ BMI_MAG_PM_NORMAL == client_data->pw.mag_pm) {
+ cancel_delayed_work_sync(&client_data->work);
+ }
+ mutex_unlock(&client_data->mutex_enable);
+
+ err = bmi_pmu_set_suspend(client_data);
+
+ bmi_delay(5);
+
+ sysfs_remove_group(&client_data->input->dev.kobj,
+ &bmi160_attribute_group);
+ bmi_input_destroy(client_data);
+
+ if (NULL != client_data->bst_pd) {
+ kfree(client_data->bst_pd);
+ client_data->bst_pd = NULL;
+ }
+ kfree(client_data);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(bmi_remove);
+
+static int bmi_post_resume(struct bmi_client_data *client_data)
+{
+ int err = 0;
+
+ mutex_lock(&client_data->mutex_enable);
+
+ if (atomic_read(&client_data->wkqueue_en) == 1) {
+ bmi160_set_acc_op_mode(client_data, BMI_ACC_PM_NORMAL);
+ schedule_delayed_work(&client_data->work,
+ msecs_to_jiffies(
+ atomic_read(&client_data->delay)));
+ }
+ mutex_unlock(&client_data->mutex_enable);
+
+ return err;
+}
+
+
+int bmi_suspend(struct device *dev)
+{
+ int err = 0;
+ struct bmi_client_data *client_data = dev_get_drvdata(dev);
+ unsigned char stc_enable;
+ unsigned char std_enable;
+ dev_err(client_data->dev, "bmi suspend function entrance");
+
+ atomic_set(&client_data->in_suspend, 1);
+ if (atomic_read(&client_data->wkqueue_en) == 1) {
+ bmi160_set_acc_op_mode(client_data, BMI_ACC_PM_SUSPEND);
+ cancel_delayed_work_sync(&client_data->work);
+ }
+ BMI_CALL_API(get_step_counter_enable)(&stc_enable);
+ BMI_CALL_API(get_step_detector_enable)(&std_enable);
+ if (client_data->pw.acc_pm != BMI_ACC_PM_SUSPEND &&
+ (stc_enable != 1) && (std_enable != 1) &&
+ (client_data->sig_flag != 1)) {
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_acc_arr[BMI_ACC_PM_SUSPEND]);
+ bmi_delay(3);
+ }
+ if (client_data->pw.gyro_pm != BMI_GYRO_PM_SUSPEND) {
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_SUSPEND]);
+ bmi_delay(3);
+ }
+
+ if (client_data->pw.mag_pm != BMI_MAG_PM_SUSPEND) {
+#if defined(BMI160_AKM09912_SUPPORT)
+ err += bmi160_set_bst_akm_and_secondary_if_powermode(
+ BMI160_MAG_SUSPEND_MODE);
+#else
+ err += bmi160_set_bmm150_mag_and_secondary_if_power_mode(
+ BMI160_MAG_SUSPEND_MODE);
+#endif
+ bmi_delay(3);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(bmi_suspend);
+
+int bmi_resume(struct device *dev)
+{
+ int err = 0;
+ struct bmi_client_data *client_data = dev_get_drvdata(dev);
+ atomic_set(&client_data->in_suspend, 0);
+ if (client_data->pw.acc_pm != BMI_ACC_PM_SUSPEND) {
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_acc_arr[BMI_ACC_PM_NORMAL]);
+ bmi_delay(3);
+ }
+ if (client_data->pw.gyro_pm != BMI_GYRO_PM_SUSPEND) {
+ err += BMI_CALL_API(set_command_register)
+ (bmi_pmu_cmd_gyro_arr[BMI_GYRO_PM_NORMAL]);
+ bmi_delay(3);
+ }
+
+ if (client_data->pw.mag_pm != BMI_MAG_PM_SUSPEND) {
+#if defined(BMI160_AKM09912_SUPPORT)
+ err += bmi160_set_bst_akm_and_secondary_if_powermode
+ (BMI160_MAG_FORCE_MODE);
+#else
+ err += bmi160_set_bmm150_mag_and_secondary_if_power_mode
+ (BMI160_MAG_FORCE_MODE);
+#endif
+ bmi_delay(3);
+ }
+ /* post resume operation */
+ err += bmi_post_resume(client_data);
+
+ return err;
+}
+EXPORT_SYMBOL(bmi_resume);
+
diff --git a/drivers/input/sensors/bmi160/bmi160_driver.h b/drivers/input/sensors/bmi160/bmi160_driver.h
new file mode 100644
index 000000000000..993a8859cffa
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bmi160_driver.h
@@ -0,0 +1,409 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * @filename bmi160_driver.h
+ * @date 2015/08/17 14:40
+ * @id "e90a329"
+ * @version 1.3
+ *
+ * @brief
+ * The head file of BMI160 device driver core code
+*/
+#ifndef _BMI160_DRIVER_H
+#define _BMI160_DRIVER_H
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/unistd.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/ktime.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include "bmi160.h"
+
+#if defined(CONFIG_USE_QUALCOMM_HAL)
+#include <linux/sensors.h>
+#endif
+/* sensor specific */
+#define SENSOR_NAME "bmi160"
+#define BMI160_ENABLE_INT1 1
+//#define BMI160_ENABLE_INT2 1
+/*#define BMI160_MAG_INTERFACE_SUPPORT 1*/
+
+/*#define BMI160_AKM09912_SUPPORT 1*/
+#define BMI_USE_BASIC_I2C_FUNC 1
+#define SENSOR_CHIP_ID_BMI (0xD0)
+#define SENSOR_CHIP_ID_BMI_C2 (0xD1)
+#define SENSOR_CHIP_ID_BMI_C3 (0xD3)
+
+#define SENSOR_CHIP_REV_ID_BMI (0x00)
+
+#define CHECK_CHIP_ID_TIME_MAX 5
+
+#define BMI_REG_NAME(name) BMI160_##name##__REG
+#define BMI_VAL_NAME(name) BMI160_##name
+#define BMI_CALL_API(name) bmi160_##name
+
+#define BMI_I2C_WRITE_DELAY_TIME (1)
+
+/* generic */
+#define BMI_MAX_RETRY_I2C_XFER (10)
+#define BMI_MAX_RETRY_WAKEUP (5)
+#define BMI_MAX_RETRY_WAIT_DRDY (100)
+
+#define BMI_DELAY_MIN (1)
+#define BMI_DELAY_DEFAULT (200)
+
+#define BMI_VALUE_MAX (32767)
+#define BMI_VALUE_MIN (-32768)
+
+#define BYTES_PER_LINE (16)
+
+#define BUF_SIZE_PRINT (16)
+
+#define BMI_FAST_CALI_TRUE (1)
+#define BMI_FAST_CALI_ALL_RDY (7)
+
+/*! FIFO 1024 byte, max fifo frame count not over 150 */
+#define FIFO_FRAME_CNT 170
+#define FIFO_DATA_BUFSIZE 1024
+
+
+#define FRAME_LEN_ACC 6
+#define FRAME_LEN_GYRO 6
+#define FRAME_LEN_MAG 8
+
+/*! BMI Self test */
+#define BMI_SELFTEST_AMP_HIGH 1
+
+/* CMD */
+#define CMD_FOC_START 0x03
+#define CMD_PMU_ACC_SUSPEND 0x10
+#define CMD_PMU_ACC_NORMAL 0x11
+#define CMD_PMU_ACC_LP1 0x12
+#define CMD_PMU_ACC_LP2 0x13
+#define CMD_PMU_GYRO_SUSPEND 0x14
+#define CMD_PMU_GYRO_NORMAL 0x15
+#define CMD_PMU_GYRO_FASTSTART 0x17
+#define CMD_PMU_MAG_SUSPEND 0x18
+#define CMD_PMU_MAG_NORMAL 0x19
+#define CMD_PMU_MAG_LP1 0x1A
+#define CMD_PMU_MAG_LP2 0x1B
+#define CMD_CLR_FIFO_DATA 0xB0
+#define CMD_RESET_INT_ENGINE 0xB1
+#define CMD_RESET_USER_REG 0xB6
+
+#define USER_DAT_CFG_PAGE 0x00
+
+/*! FIFO Head definition*/
+#define FIFO_HEAD_A 0x84
+#define FIFO_HEAD_G 0x88
+#define FIFO_HEAD_M 0x90
+
+#define FIFO_HEAD_G_A (FIFO_HEAD_G | FIFO_HEAD_A)
+#define FIFO_HEAD_M_A (FIFO_HEAD_M | FIFO_HEAD_A)
+#define FIFO_HEAD_M_G (FIFO_HEAD_M | FIFO_HEAD_G)
+
+#define FIFO_HEAD_M_G_A (FIFO_HEAD_M | FIFO_HEAD_G | FIFO_HEAD_A)
+
+#define FIFO_HEAD_SENSOR_TIME 0x44
+#define FIFO_HEAD_SKIP_FRAME 0x40
+#define FIFO_HEAD_OVER_READ_LSB 0x80
+#define FIFO_HEAD_OVER_READ_MSB 0x00
+
+/*! FIFO head mode Frame bytes number definition */
+#define A_BYTES_FRM 6
+#define G_BYTES_FRM 6
+#define M_BYTES_FRM 8
+#define GA_BYTES_FRM 12
+#define MG_BYTES_FRM 14
+#define MA_BYTES_FRM 14
+#define MGA_BYTES_FRM 20
+
+#define ACC_FIFO_HEAD "acc"
+#define GYRO_FIFO_HEAD "gyro"
+#define MAG_FIFO_HEAD "mag"
+
+/*! Bosch sensor unknown place*/
+#define BOSCH_SENSOR_PLACE_UNKNOWN (-1)
+/*! Bosch sensor remapping table size P0~P7*/
+#define MAX_AXIS_REMAP_TAB_SZ 8
+
+#define ENABLE 1
+#define DISABLE 0
+
+/* bmi sensor HW interrupt pin number */
+#define BMI_INT0 0
+#define BMI_INT1 1
+
+#define BMI_INT_LEVEL 0
+#define BMI_INT_EDGE 1
+
+/*! BMI mag interface */
+
+
+/* compensated output value returned if sensor had overflow */
+#define BMM050_OVERFLOW_OUTPUT -32768
+#define BMM050_OVERFLOW_OUTPUT_S32 ((s32)(-2147483647-1))
+
+/* Trim Extended Registers */
+#define BMM050_DIG_X1 0x5D
+#define BMM050_DIG_Y1 0x5E
+#define BMM050_DIG_Z4_LSB 0x62
+#define BMM050_DIG_Z4_MSB 0x63
+#define BMM050_DIG_X2 0x64
+#define BMM050_DIG_Y2 0x65
+#define BMM050_DIG_Z2_LSB 0x68
+#define BMM050_DIG_Z2_MSB 0x69
+#define BMM050_DIG_Z1_LSB 0x6A
+#define BMM050_DIG_Z1_MSB 0x6B
+#define BMM050_DIG_XYZ1_LSB 0x6C
+#define BMM050_DIG_XYZ1_MSB 0x6D
+#define BMM050_DIG_Z3_LSB 0x6E
+#define BMM050_DIG_Z3_MSB 0x6F
+#define BMM050_DIG_XY2 0x70
+#define BMM050_DIG_XY1 0x71
+
+struct bmi160mag_compensate_t {
+ signed char dig_x1;
+ signed char dig_y1;
+
+ signed char dig_x2;
+ signed char dig_y2;
+
+ u16 dig_z1;
+ s16 dig_z2;
+ s16 dig_z3;
+ s16 dig_z4;
+
+ unsigned char dig_xy1;
+ signed char dig_xy2;
+
+ u16 dig_xyz1;
+};
+
+/*bmi fifo sensor type combination*/
+enum BMI_FIFO_DATA_SELECT_T {
+ BMI_FIFO_A_SEL = 1,
+ BMI_FIFO_G_SEL,
+ BMI_FIFO_G_A_SEL,
+ BMI_FIFO_M_SEL,
+ BMI_FIFO_M_A_SEL,
+ BMI_FIFO_M_G_SEL,
+ BMI_FIFO_M_G_A_SEL,
+ BMI_FIFO_DATA_SEL_MAX
+};
+
+/*bmi interrupt about step_detector and sgm*/
+#define INPUT_EVENT_STEP_DETECTOR 5
+#define INPUT_EVENT_SGM 3/*7*/
+#define INPUT_EVENT_FAST_ACC_CALIB_DONE 6
+#define INPUT_EVENT_FAST_GYRO_CALIB_DONE 4
+
+
+/*!
+* Bst sensor common definition,
+* please give parameters in BSP file.
+*/
+struct bosch_sensor_specific {
+ char *name;
+ /* 0 to 7 */
+ unsigned int place:3;
+ int irq;
+ int (*irq_gpio_cfg)(void);
+};
+
+/*! bmi160 sensor spec of power mode */
+struct pw_mode {
+ u8 acc_pm;
+ u8 gyro_pm;
+ u8 mag_pm;
+};
+
+/*! bmi160 sensor spec of odr */
+struct odr_t {
+ u8 acc_odr;
+ u8 gyro_odr;
+ u8 mag_odr;
+};
+
+/*! bmi160 sensor spec of range */
+struct range_t {
+ u8 acc_range;
+ u8 gyro_range;
+};
+
+/*! bmi160 sensor error status */
+struct err_status {
+ u8 fatal_err;
+ u8 err_code;
+ u8 i2c_fail;
+ u8 drop_cmd;
+ u8 mag_drdy_err;
+ u8 err_st_all;
+};
+
+/*! bmi160 fifo frame for all sensors */
+struct fifo_frame_t {
+ struct bmi160_accel_t *acc_farr;
+ struct bmi160_gyro_t *gyro_farr;
+ struct bmi160_mag_xyz_s32_t *mag_farr;
+
+ unsigned char acc_frame_cnt;
+ unsigned char gyro_frame_cnt;
+ unsigned char mag_frame_cnt;
+
+ u32 acc_lastf_ts;
+ u32 gyro_lastf_ts;
+ u32 mag_lastf_ts;
+};
+
+/*! bmi160 fifo sensor time */
+struct fifo_sensor_time_t {
+ u32 acc_ts;
+ u32 gyro_ts;
+ u32 mag_ts;
+};
+
+struct pedometer_data_t {
+ /*! Fix step detector misinformation for the first time*/
+ u8 wkar_step_detector_status;
+ u_int32_t last_step_counter_value;
+};
+
+struct bmi_client_data {
+ struct bmi160_t device;
+ struct device *dev;
+ struct input_dev *input;/*acc_device*/
+ struct input_dev *gyro_input;
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ struct input_dev *gyro_input;
+ struct sensors_classdev accel_cdev;
+ struct sensors_classdev gyro_cdev;
+ struct delayed_work accel_poll_work;
+ struct delayed_work gyro_poll_work;
+ u32 accel_poll_ms;
+ u32 gyro_poll_ms;
+ u32 accel_latency_ms;
+ u32 gyro_latency_ms;
+ atomic_t accel_en;
+ atomic_t gyro_en;
+ struct workqueue_struct *data_wq;
+ #endif
+ struct delayed_work work;
+ struct work_struct irq_work;
+
+ u8 chip_id;
+
+ struct pw_mode pw;
+ struct odr_t odr;
+ struct range_t range; /*TO DO*/
+ struct err_status err_st;
+ struct pedometer_data_t pedo_data;
+ s8 place;
+ u8 selftest;
+ /*struct wake_lock wakelock;*/
+ struct delayed_work delay_work_sig;
+ atomic_t in_suspend;
+
+ atomic_t wkqueue_en; /*TO DO acc gyro mag*/
+ atomic_t delay;
+ atomic_t selftest_result;
+
+ u8 fifo_data_sel;
+ u16 fifo_bytecount;
+ u8 fifo_head_en;
+ unsigned char fifo_int_tag_en;
+ struct fifo_frame_t fifo_frame;
+
+ unsigned char *fifo_data;
+ u64 fifo_time;
+ u8 stc_enable;
+ uint16_t gpio_pin;
+ u8 std;
+ u8 sig_flag;
+ unsigned char calib_status;
+ struct mutex mutex_op_mode;
+ struct mutex mutex_enable;
+ struct bosch_sensor_specific *bst_pd;
+ int IRQ;
+ int reg_sel;
+ int reg_len;
+ uint64_t timestamp;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend_handler;
+#endif
+};
+
+
+/*!
+ * we use a typedef to hide the detail,
+ * because this type might be changed
+ */
+struct bosch_sensor_axis_remap {
+ /* src means which source will be mapped to target x, y, z axis */
+ /* if an target OS axis is remapped from (-)x,
+ * src is 0, sign_* is (-)1 */
+ /* if an target OS axis is remapped from (-)y,
+ * src is 1, sign_* is (-)1 */
+ /* if an target OS axis is remapped from (-)z,
+ * src is 2, sign_* is (-)1 */
+ int src_x:3;
+ int src_y:3;
+ int src_z:3;
+
+ int sign_x:2;
+ int sign_y:2;
+ int sign_z:2;
+};
+
+
+struct bosch_sensor_data {
+ union {
+ int16_t v[3];
+ struct {
+ int16_t x;
+ int16_t y;
+ int16_t z;
+ };
+ };
+};
+
+s8 bmi_burst_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u16 len);
+int bmi_probe(struct bmi_client_data *client_data, struct device *dev);
+int bmi_remove(struct device *dev);
+int bmi_suspend(struct device *dev);
+int bmi_resume(struct device *dev);
+
+
+
+
+#endif/*_BMI160_DRIVER_H*/
+/*@}*/
+
diff --git a/drivers/input/sensors/bmi160/bmi160_i2c.c b/drivers/input/sensors/bmi160/bmi160_i2c.c
new file mode 100644
index 000000000000..511f6de9a47e
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bmi160_i2c.c
@@ -0,0 +1,411 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * @filename bmi160_i2c.c
+ * @date 2014/11/25 14:40
+ * @id "20f77db"
+ * @version 1.3
+ *
+ * @brief
+ * This file implements moudle function, which add
+ * the driver to I2C core.
+*/
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "bmi160_driver.h"
+#include <linux/regulator/consumer.h>
+
+/*! @defgroup bmi160_i2c_src
+ * @brief bmi160 i2c driver module
+ @{*/
+
+static struct i2c_client *bmi_client;
+
+struct BMI160Supply {
+ struct regulator *vdd_reg;
+ struct regulator *vio_reg;
+};
+
+/*!
+ * @brief define i2c wirte function
+ *
+ * @param client the pointer of i2c client
+ * @param reg_addr register address
+ * @param data the pointer of data buffer
+ * @param len block size need to write
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+/* i2c read routine for API*/
+static s8 bmi_i2c_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len)
+ {
+#if !defined BMI_USE_BASIC_I2C_FUNC
+ s32 dummy;
+ if (NULL == client)
+ return -EINVAL;
+
+ while (0 != len--) {
+#ifdef BMI_SMBUS
+ dummy = i2c_smbus_read_byte_data(client, reg_addr);
+ if (dummy < 0) {
+ dev_err(&client->dev, "i2c smbus read error");
+ return -EIO;
+ }
+ *data = (u8)(dummy & 0xff);
+#else
+ dummy = i2c_master_send(client, (char *)&reg_addr, 1);
+ if (dummy < 0) {
+ dev_err(&client->dev, "i2c bus master write error");
+ return -EIO;
+ }
+
+ dummy = i2c_master_recv(client, (char *)data, 1);
+ if (dummy < 0) {
+ dev_err(&client->dev, "i2c bus master read error");
+ return -EIO;
+ }
+#endif
+ reg_addr++;
+ data++;
+ }
+ return 0;
+#else
+ int retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ for (retry = 0; retry < BMI_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg,
+ ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ usleep_range(BMI_I2C_WRITE_DELAY_TIME * 1000,
+ BMI_I2C_WRITE_DELAY_TIME * 1000);
+ }
+
+ if (BMI_MAX_RETRY_I2C_XFER <= retry) {
+ dev_err(&client->dev, "I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+#endif
+ }
+
+
+static s8 bmi_i2c_burst_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u16 len)
+{
+ int retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ for (retry = 0; retry < BMI_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ usleep_range(BMI_I2C_WRITE_DELAY_TIME * 1000,
+ BMI_I2C_WRITE_DELAY_TIME * 1000);
+ }
+
+ if (BMI_MAX_RETRY_I2C_XFER <= retry) {
+ dev_err(&client->dev, "I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+
+/* i2c write routine for */
+static s8 bmi_i2c_write(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len)
+{
+#if !defined BMI_USE_BASIC_I2C_FUNC
+ s32 dummy;
+
+#ifndef BMI_SMBUS
+ u8 buffer[2];
+#endif
+
+ if (NULL == client)
+ return -EPERM;
+
+ while (0 != len--) {
+#ifdef BMI_SMBUS
+ dummy = i2c_smbus_write_byte_data(client, reg_addr, *data);
+#else
+ buffer[0] = reg_addr;
+ buffer[1] = *data;
+ dummy = i2c_master_send(client, (char *)buffer, 2);
+#endif
+ reg_addr++;
+ data++;
+ if (dummy < 0) {
+ dev_err(&client->dev, "error writing i2c bus");
+ return -EPERM;
+ }
+
+ }
+ usleep_range(BMI_I2C_WRITE_DELAY_TIME * 1000,
+ BMI_I2C_WRITE_DELAY_TIME * 1000);
+ return 0;
+#else
+ u8 buffer[2];
+ int retry;
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = buffer,
+ },
+ };
+
+ while (0 != len--) {
+ buffer[0] = reg_addr;
+ buffer[1] = *data;
+ for (retry = 0; retry < BMI_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg,
+ ARRAY_SIZE(msg)) > 0) {
+ break;
+ } else {
+ usleep_range(BMI_I2C_WRITE_DELAY_TIME * 1000,
+ BMI_I2C_WRITE_DELAY_TIME * 1000);
+ }
+ }
+ if (BMI_MAX_RETRY_I2C_XFER <= retry) {
+ dev_err(&client->dev, "I2C xfer error");
+ return -EIO;
+ }
+ reg_addr++;
+ data++;
+ }
+
+ usleep_range(BMI_I2C_WRITE_DELAY_TIME * 1000,
+ BMI_I2C_WRITE_DELAY_TIME * 1000);
+ return 0;
+#endif
+}
+
+
+static s8 bmi_i2c_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ int err = 0;
+ err = bmi_i2c_read(bmi_client, reg_addr, data, len);
+ return err;
+}
+
+static s8 bmi_i2c_write_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ int err = 0;
+ err = bmi_i2c_write(bmi_client, reg_addr, data, len);
+ return err;
+}
+
+s8 bmi_burst_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u16 len)
+{
+ int err = 0;
+ err = bmi_i2c_burst_read(bmi_client, reg_addr, data, len);
+ return err;
+}
+EXPORT_SYMBOL(bmi_burst_read_wrapper);
+/*!
+ * @brief BMI probe function via i2c bus
+ *
+ * @param client the pointer of i2c client
+ * @param id the pointer of i2c device id
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static int bmi_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct bmi_client_data *client_data = NULL;
+ struct BMI160Supply bmi160Supply;
+
+ dev_info(&client->dev, "BMI160 i2c function probe entrance");
+
+ dev_info(&client->dev, "bmi_i2c_probe regulator ON\n");
+
+ bmi160Supply.vdd_reg = devm_regulator_get(&client->dev, "vdd");
+ if (IS_ERR(bmi160Supply.vdd_reg)) {
+ if (PTR_ERR(bmi160Supply.vdd_reg) != -EPROBE_DEFER)
+ dev_err(&client->dev, "bmi160Supply->vdd_reg EPROBE_DEFER Unable to get regulator\n");
+ err = PTR_ERR(bmi160Supply.vdd_reg);
+ goto exit_err_clean;
+ }
+
+ dev_err(&client->dev, "bmi_i2c_probe before regulator_enable(VDD)\n");
+ if (regulator_enable(bmi160Supply.vdd_reg)) {
+ dev_err(&client->dev, "bmi160Supply->vdd_reg error!regulator cannot enable");
+ err = -EIO;
+ goto exit_err_clean;
+ }
+ dev_err(&client->dev, "bmi_i2c_probe after regulator_enable(VDD)\n");
+
+ bmi160Supply.vio_reg = devm_regulator_get(&client->dev, "vio");
+ if (IS_ERR(bmi160Supply.vio_reg)) {
+ if (PTR_ERR(bmi160Supply.vio_reg) != -EPROBE_DEFER)
+ dev_err(&client->dev, "bmi160Supply->vio_reg EPROBE_DEFER Unable to get regulator\n");
+ err = PTR_ERR(bmi160Supply.vio_reg);
+ goto exit_err_clean;
+ }
+
+ dev_err(&client->dev, "bmi_i2c_probe before regulator_enable(VIO)\n");
+ if (regulator_enable(bmi160Supply.vio_reg)) {
+ dev_err(&client->dev, "bmi160Supply->vio_reg error!regulator cannot enable");
+ err = -EIO;
+ goto exit_err_clean;
+ }
+ dev_err(&client->dev, "bmi_i2c_probe after regulator_enable(VIO)\n");
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "i2c_check_functionality error!");
+ err = -EIO;
+ goto exit_err_clean;
+ }
+
+ if (NULL == bmi_client) {
+ bmi_client = client;
+ } else {
+ dev_err(&client->dev,
+ "this driver does not support multiple clients");
+ err = -EBUSY;
+ goto exit_err_clean;
+ }
+
+ client_data = kzalloc(sizeof(struct bmi_client_data),
+ GFP_KERNEL);
+ if (NULL == client_data) {
+ dev_err(&client->dev, "no memory available");
+ err = -ENOMEM;
+ goto exit_err_clean;
+ }
+
+ client_data->device.bus_read = bmi_i2c_read_wrapper;
+ client_data->device.bus_write = bmi_i2c_write_wrapper;
+
+ return bmi_probe(client_data, &client->dev);
+
+exit_err_clean:
+ if (err)
+ bmi_client = NULL;
+ return err;
+}
+/*
+static int bmi_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ int err = 0;
+ err = bmi_suspend(&client->dev);
+ return err;
+}
+
+static int bmi_i2c_resume(struct i2c_client *client)
+{
+ int err = 0;
+
+ err = bmi_resume(&client->dev);
+
+ return err;
+}
+*/
+
+static int bmi_i2c_remove(struct i2c_client *client)
+{
+ int err = 0;
+ err = bmi_remove(&client->dev);
+ bmi_client = NULL;
+
+ return err;
+}
+
+
+
+static const struct i2c_device_id bmi_id[] = {
+ {SENSOR_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, bmi_id);
+
+static const struct of_device_id bmi160_of_match[] = {
+ { .compatible = "bosch-sensortec,bmi160", },
+ { .compatible = "bmi160", },
+ { .compatible = "bosch, bmi160", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bmi160_of_match);
+
+static struct i2c_driver bmi_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+ .of_match_table = bmi160_of_match,
+ },
+ .class = I2C_CLASS_HWMON,
+ .id_table = bmi_id,
+ .probe = bmi_i2c_probe,
+ .remove = bmi_i2c_remove,
+ /*.suspend = bmi_i2c_suspend,
+ .resume = bmi_i2c_resume,*/
+};
+
+static int __init BMI_i2c_init(void)
+{
+ return i2c_add_driver(&bmi_i2c_driver);
+}
+
+static void __exit BMI_i2c_exit(void)
+{
+ i2c_del_driver(&bmi_i2c_driver);
+}
+
+MODULE_AUTHOR("Contact <contact@bosch-sensortec.com>");
+MODULE_DESCRIPTION("driver for " SENSOR_NAME);
+MODULE_LICENSE("GPL v2");
+
+module_init(BMI_i2c_init);
+module_exit(BMI_i2c_exit);
+
diff --git a/drivers/input/sensors/bmi160/bmi160_spi.c b/drivers/input/sensors/bmi160/bmi160_spi.c
new file mode 100644
index 000000000000..8da1e21e7fd7
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bmi160_spi.c
@@ -0,0 +1,299 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * @filename bmi160_spi.c
+ * @date 2014/11/25 14:40
+ * @id "20f77db"
+ * @version 1.3
+ *
+ * @brief
+ * This file implements moudle function, which add
+ * the driver to SPI core.
+*/
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include "bmi160_driver.h"
+
+/*! @defgroup bmi160_spi_src
+ * @brief bmi160 spi driver module
+ @{*/
+/*! the maximum of transfer buffer size */
+#define BMI_MAX_BUFFER_SIZE 32
+
+static struct spi_device *bmi_spi_client;
+
+/*!
+ * @brief define spi wirte function
+ *
+ * @param dev_addr sensor device address
+ * @param reg_addr register address
+ * @param data the pointer of data buffer
+ * @param len block size need to write
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static char bmi_spi_write_block(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ struct spi_device *client = bmi_spi_client;
+ u8 buffer[BMI_MAX_BUFFER_SIZE + 1];
+ struct spi_transfer xfer = {
+ .tx_buf = buffer,
+ .len = len + 1,
+ };
+ struct spi_message msg;
+
+ if (len > BMI_MAX_BUFFER_SIZE)
+ return -EINVAL;
+
+ buffer[0] = reg_addr&0x7F;/* write: MSB = 0 */
+ memcpy(&buffer[1], data, len);
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+ return spi_sync(client, &msg);
+}
+
+/*!
+ * @brief define spi read function
+ *
+ * @param dev_addr sensor device address
+ * @param reg_addr register address
+ * @param data the pointer of data buffer
+ * @param len block size need to read
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static char bmi_spi_read_block(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ struct spi_device *client = bmi_spi_client;
+ u8 reg = reg_addr | 0x80;/* read: MSB = 1 */
+ struct spi_transfer xfer[2] = {
+ [0] = {
+ .tx_buf = &reg,
+ .len = 1,
+ },
+ [1] = {
+ .rx_buf = data,
+ .len = len,
+ }
+ };
+ struct spi_message msg;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer[0], &msg);
+ spi_message_add_tail(&xfer[1], &msg);
+ return spi_sync(client, &msg);
+}
+
+s8 bmi_burst_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u16 len)
+{
+ struct spi_device *client = bmi_spi_client;
+ u8 reg = reg_addr | 0x80;/* read: MSB = 1 */
+ struct spi_transfer xfer[2] = {
+ [0] = {
+ .tx_buf = &reg,
+ .len = 1,
+ },
+ [1] = {
+ .rx_buf = data,
+ .len = len,
+ }
+ };
+ struct spi_message msg;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer[0], &msg);
+ spi_message_add_tail(&xfer[1], &msg);
+ return spi_sync(client, &msg);
+}
+EXPORT_SYMBOL(bmi_burst_read_wrapper);
+/*!
+ * @brief BMI probe function via spi bus
+ *
+ * @param client the pointer of spi client
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static int bmi_spi_probe(struct spi_device *client)
+{
+ int status;
+ int err = 0;
+ struct bmi_client_data *client_data = NULL;
+
+ if (NULL == bmi_spi_client)
+ bmi_spi_client = client;
+ else{
+ dev_err(&client->dev, "This driver does not support multiple clients!\n");
+ return -EBUSY;
+ }
+
+ client->bits_per_word = 8;
+ status = spi_setup(client);
+ if (status < 0) {
+ dev_err(&client->dev, "spi_setup failed!\n");
+ return status;
+ }
+
+ client_data = kzalloc(sizeof(struct bmi_client_data), GFP_KERNEL);
+ if (NULL == client_data) {
+ dev_err(&client->dev, "no memory available");
+ err = -ENOMEM;
+ goto exit_err_clean;
+ }
+
+ client_data->device.bus_read = bmi_spi_read_block;
+ client_data->device.bus_write = bmi_spi_write_block;
+
+ return bmi_probe(client_data, &client->dev);
+
+exit_err_clean:
+ if (err)
+ bmi_spi_client = NULL;
+ return err;
+}
+
+/*!
+ * @brief shutdown bmi device in spi driver
+ *
+ * @param client the pointer of spi client
+ *
+ * @return no return value
+*/
+static void bmi_spi_shutdown(struct spi_device *client)
+{
+#ifdef CONFIG_PM
+ bmi_suspend(&client->dev);
+#endif
+}
+
+/*!
+ * @brief remove bmi spi client
+ *
+ * @param client the pointer of spi client
+ *
+ * @return zero
+ * @retval zero
+*/
+static int bmi_spi_remove(struct spi_device *client)
+{
+ int err = 0;
+ err = bmi_remove(&client->dev);
+ bmi_spi_client = NULL;
+
+ return err;
+}
+
+#ifdef CONFIG_PM
+/*!
+ * @brief suspend bmi device in spi driver
+ *
+ * @param dev the pointer of device
+ *
+ * @return zero
+ * @retval zero
+*/
+static int bmi_spi_suspend(struct device *dev)
+{
+ int err = 0;
+ err = bmi_suspend(dev);
+ return err;
+}
+
+/*!
+ * @brief resume bmi device in spi driver
+ *
+ * @param dev the pointer of device
+ *
+ * @return zero
+ * @retval zero
+*/
+static int bmi_spi_resume(struct device *dev)
+{
+ int err = 0;
+ /* post resume operation */
+ err = bmi_resume(dev);
+
+ return err;
+}
+
+/*!
+ * @brief register spi device power manager hooks
+*/
+static const struct dev_pm_ops bmi_spi_pm_ops = {
+ /**< device suspend */
+ .suspend = bmi_spi_suspend,
+ /**< device resume */
+ .resume = bmi_spi_resume
+};
+#endif
+
+/*!
+ * @brief register spi device id
+*/
+static const struct spi_device_id bmi_id[] = {
+ { SENSOR_NAME, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, bmi_id);
+
+/*!
+ * @brief register spi driver hooks
+*/
+static struct spi_driver bmi_spi_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+#ifdef CONFIG_PM
+ .pm = &bmi_spi_pm_ops,
+#endif
+ },
+ .id_table = bmi_id,
+ .probe = bmi_spi_probe,
+ .shutdown = bmi_spi_shutdown,
+ .remove = bmi_spi_remove
+};
+
+/*!
+ * @brief initialize bmi spi module
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static int __init bmi_spi_init(void)
+{
+ return spi_register_driver(&bmi_spi_driver);
+}
+
+/*!
+ * @brief remove bmi spi module
+ *
+ * @return no return value
+*/
+static void __exit bmi_spi_exit(void)
+{
+ spi_unregister_driver(&bmi_spi_driver);
+}
+
+
+MODULE_AUTHOR("Contact <contact@bosch-sensortec.com>");
+MODULE_DESCRIPTION("BMI160 SPI DRIVER");
+MODULE_LICENSE("GPL v2");
+
+module_init(bmi_spi_init);
+module_exit(bmi_spi_exit);
+/*@}*/
+
diff --git a/drivers/input/sensors/bmi160/bs_log.c b/drivers/input/sensors/bmi160/bs_log.c
new file mode 100644
index 000000000000..6574607607e1
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bs_log.c
@@ -0,0 +1,50 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * @filename bs_log.c
+ * @date "Wed Sep 24 15:27:12 2014 +0800"
+ * @id "e416c14"
+ *
+ * @brief
+ * The source file of BOSCH SENSOR LOG
+*/
+
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/unistd.h>
+#include <linux/types.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#endif
+
+#include <linux/time.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#ifdef BOSCH_DRIVER_LOG_FUNC
+#define BSLOG_VAR_DEF
+#include "bs_log.h"
+
+void set_debug_log_level(uint8_t level)
+{
+ debug_log_level = level;
+}
+
+uint8_t get_debug_log_level(void)
+{
+ return debug_log_level;
+}
+
+EXPORT_SYMBOL(set_debug_log_level);
+EXPORT_SYMBOL(get_debug_log_level);
+
+#endif/*BOSCH_DRIVER_LOG_FUNC*/
+/*@}*/
diff --git a/drivers/input/sensors/bmi160/bs_log.h b/drivers/input/sensors/bmi160/bs_log.h
new file mode 100644
index 000000000000..ed2d2b37f533
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bs_log.h
@@ -0,0 +1,171 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * @filename bs_log.h
+ * @date "Sat Oct 11 16:12:16 2014 +0800"
+ * @id "762cc9e"
+ *
+ * @brief
+ * The head file of BOSCH SENSOR LOG
+*/
+
+#ifndef __BS_LOG_H
+#define __BS_LOG_H
+
+#include <linux/kernel.h>
+
+/*! @ trace functions
+ @{*/
+/*! ERROR LOG LEVEL */
+#define LOG_LEVEL_E 3
+/*! NOTICE LOG LEVEL */
+#define LOG_LEVEL_N 5
+/*! INFORMATION LOG LEVEL */
+#define LOG_LEVEL_I 6
+/*! DEBUG LOG LEVEL */
+#define LOG_LEVEL_D 7
+/*! DEBUG_FWDL LOG LEVEL */
+#define LOG_LEVEL_DF 10
+/*! DEBUG_DATA LOG LEVEL */
+#define LOG_LEVEL_DA 15
+/*! ALL LOG LEVEL */
+#define LOG_LEVEL_A 20
+
+#ifndef MODULE_TAG
+/*! MODULE TAG DEFINATION */
+#define MODULE_TAG "<BS_LOG>"
+#endif
+
+#ifndef LOG_LEVEL
+/*! LOG LEVEL DEFINATION */
+#define LOG_LEVEL LOG_LEVEL_I
+#endif
+
+#ifdef BOSCH_DRIVER_LOG_FUNC
+ #ifdef BSLOG_VAR_DEF
+ uint8_t debug_log_level = LOG_LEVEL;
+ #else
+ extern uint8_t debug_log_level;
+ #endif
+
+ /*! print error message */
+ #define PERR(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_E)\
+ printk(KERN_INFO "\n" "[E]" KERN_ERR MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print notice message */
+ #define PNOTICE(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_N)\
+ printk(KERN_INFO "\n" "[N]" KERN_NOTICE MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print information message */
+ #define PINFO(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_I)\
+ printk(KERN_INFO "\n" "[I]" KERN_INFO MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print debug message */
+ #define PDEBUG(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_D)\
+ printk(KERN_INFO "\n" "[D]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print debug fw download message */
+ #define PDEBUG_FWDL(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_DF)\
+ printk(KERN_INFO "\n" "[DF]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print debug data log message */
+ #define PDEBUG_DLOG(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_DA)\
+ printk(KERN_INFO "\n" "[DA]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ void set_debug_log_level(uint8_t level);
+ uint8_t get_debug_log_level(void);
+
+#else
+
+ #if (LOG_LEVEL >= LOG_LEVEL_E)
+ /*! print error message */
+ #define PERR(fmt, args...) \
+ printk(KERN_INFO "\n" "[E]" KERN_ERR MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PERR(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_N)
+ /*! print notice message */
+ #define PNOTICE(fmt, args...) \
+ printk(KERN_INFO "\n" "[N]" KERN_NOTICE MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PNOTICE(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_I)
+ /*! print information message */
+ #define PINFO(fmt, args...) printk(KERN_INFO "\n" "[I]" KERN_INFO MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PINFO(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_D)
+ /*! print debug message */
+ #define PDEBUG(fmt, args...) printk(KERN_INFO "\n" "[D]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PDEBUG(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_DF)
+ /*! print debug fw download message */
+ #define PDEBUG_FWDL(fmt, args...) printk(KERN_INFO "\n" "[DF]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PDEBUG_FWDL(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_DA)
+ /*! print debug data log message */
+ #define PDEBUG_DLOG(fmt, args...) printk(KERN_INFO "\n" "[DA]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PDEBUG_DLOG(fmt, args...)
+ #endif
+
+ #define set_debug_log_level(level) {}
+ #define get_debug_log_level() (LOG_LEVEL)
+
+#endif
+
+#endif/*__BS_LOG_H*/
+/*@}*/
diff --git a/drivers/input/sensors/bmi160/bstclass.c b/drivers/input/sensors/bmi160/bstclass.c
new file mode 100644
index 000000000000..4937ccac51c5
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bstclass.c
@@ -0,0 +1,238 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * @filename bstclass.c
+ * @date 2015/11/17 13:44
+ * @id "836294d"
+ * @version 1.5.9
+ *
+ * @brief
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/poll.h>
+#include <linux/mutex.h>
+#include <linux/rcupdate.h>
+#include <linux/compiler.h>
+#include <linux/compat.h>
+#include "bstclass.h"
+#include "bs_log.h"
+
+static LIST_HEAD(bst_dev_list);
+
+/*
+ * bst_mutex protects access to both bst_dev_list and input_handler_list.
+ * This also causes bst_[un]register_device and bst_[un]register_handler
+ * be mutually exclusive which simplifies locking in drivers implementing
+ * input handlers.
+ */
+static DEFINE_MUTEX(bst_mutex);
+
+
+static void bst_dev_release(struct device *device)
+{
+ struct bst_dev *dev = to_bst_dev(device);
+ if (NULL != dev)
+ kfree(dev);
+ module_put(THIS_MODULE);
+}
+
+
+#ifdef CONFIG_PM
+static int bst_dev_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int bst_dev_resume(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops bst_dev_pm_ops = {
+ .suspend = bst_dev_suspend,
+ .resume = bst_dev_resume,
+ .poweroff = bst_dev_suspend,
+ .restore = bst_dev_resume,
+};
+#endif /* CONFIG_PM */
+
+static const struct attribute_group *bst_dev_attr_groups[] = {
+ NULL
+};
+
+static struct device_type bst_dev_type = {
+ .groups = bst_dev_attr_groups,
+ .release = bst_dev_release,
+#ifdef CONFIG_PM
+ .pm = &bst_dev_pm_ops,
+#endif
+};
+
+
+
+static char *bst_devnode(struct device *dev, mode_t *mode)
+{
+ return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
+}
+
+struct class bst_class = {
+ .name = "bst",
+ .owner = THIS_MODULE,
+ .devnode = (void*)bst_devnode,
+ .dev_release = bst_dev_release,
+};
+EXPORT_SYMBOL_GPL(bst_class);
+
+/**
+ * bst_allocate_device - allocate memory for new input device
+ *
+ * Returns prepared struct bst_dev or NULL.
+ *
+ * NOTE: Use bst_free_device() to free devices that have not been
+ * registered; bst_unregister_device() should be used for already
+ * registered devices.
+ */
+struct bst_dev *bst_allocate_device(void)
+{
+ struct bst_dev *dev;
+
+ dev = kzalloc(sizeof(struct bst_dev), GFP_KERNEL);
+ if (dev) {
+ dev->dev.type = &bst_dev_type;
+ dev->dev.class = &bst_class;
+ device_initialize(&dev->dev);
+ mutex_init(&dev->mutex);
+ INIT_LIST_HEAD(&dev->node);
+ __module_get(THIS_MODULE);
+ }
+ return dev;
+}
+EXPORT_SYMBOL(bst_allocate_device);
+
+
+
+/**
+ * bst_free_device - free memory occupied by bst_dev structure
+ * @dev: input device to free
+ *
+ * This function should only be used if bst_register_device()
+ * was not called yet or if it failed. Once device was registered
+ * use bst_unregister_device() and memory will be freed once last
+ * reference to the device is dropped.
+ *
+ * Device should be allocated by bst_allocate_device().
+ *
+ * NOTE: If there are references to the input device then memory
+ * will not be freed until last reference is dropped.
+ */
+void bst_free_device(struct bst_dev *dev)
+{
+ if (dev)
+ bst_put_device(dev);
+}
+EXPORT_SYMBOL(bst_free_device);
+
+/**
+ * bst_register_device - register device with input core
+ * @dev: device to be registered
+ *
+ * This function registers device with input core. The device must be
+ * allocated with bst_allocate_device() and all it's capabilities
+ * set up before registering.
+ * If function fails the device must be freed with bst_free_device().
+ * Once device has been successfully registered it can be unregistered
+ * with bst_unregister_device(); bst_free_device() should not be
+ * called in this case.
+ */
+int bst_register_device(struct bst_dev *dev)
+{
+ const char *path;
+ int error;
+
+
+ /*
+ * If delay and period are pre-set by the driver, then autorepeating
+ * is handled by the driver itself and we don't do it in input.c.
+ */
+ dev_set_name(&dev->dev, dev->name);
+
+ error = device_add(&dev->dev);
+ if (error)
+ return error;
+
+ path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
+ PINFO("%s as %s\n",
+ dev->name ? dev->name : "Unspecified device",
+ path ? path : "N/A");
+ kfree(path);
+ error = mutex_lock_interruptible(&bst_mutex);
+ if (error) {
+ device_del(&dev->dev);
+ return error;
+ }
+
+ list_add_tail(&dev->node, &bst_dev_list);
+
+ mutex_unlock(&bst_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(bst_register_device);
+
+/**
+ * bst_unregister_device - unregister previously registered device
+ * @dev: device to be unregistered
+ *
+ * This function unregisters an input device. Once device is unregistered
+ * the caller should not try to access it as it may get freed at any moment.
+ */
+void bst_unregister_device(struct bst_dev *dev)
+{
+ int ret = 0;
+ ret = mutex_lock_interruptible(&bst_mutex);
+ if(ret){
+ return;
+ }
+
+ list_del_init(&dev->node);
+ mutex_unlock(&bst_mutex);
+ device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL(bst_unregister_device);
+
+static int __init bst_init(void)
+{
+ int err;
+ /*bst class register*/
+ err = class_register(&bst_class);
+ if (err) {
+ pr_err("unable to register bst_dev class\n");
+ return err;
+ }
+ return err;
+}
+
+static void __exit bst_exit(void)
+{
+ /*bst class*/
+ class_unregister(&bst_class);
+}
+
+/*subsys_initcall(bst_init);*/
+
+MODULE_AUTHOR("contact@bosch-sensortec.com");
+MODULE_DESCRIPTION("BST CLASS CORE");
+MODULE_LICENSE("GPL V2");
+
+module_init(bst_init);
+module_exit(bst_exit);
diff --git a/drivers/input/sensors/bmi160/bstclass.h b/drivers/input/sensors/bmi160/bstclass.h
new file mode 100644
index 000000000000..7aa776031a1f
--- /dev/null
+++ b/drivers/input/sensors/bmi160/bstclass.h
@@ -0,0 +1,78 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * @filename bstcalss.h
+ * @date 2015/11/17 13:44
+ * @id "836294d"
+ * @version 1.5.9
+ *
+ * @brief
+ */
+
+#ifndef _BSTCLASS_H
+#define _BSTCLASS_H
+
+#ifdef __KERNEL__
+#include <linux/time.h>
+#include <linux/list.h>
+#else
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <linux/types.h>
+#endif
+
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/mod_devicetable.h>
+
+struct bst_dev {
+ const char *name;
+
+ int (*open)(struct bst_dev *dev);
+ void (*close)(struct bst_dev *dev);
+ struct mutex mutex;
+ struct device dev;
+ struct list_head node;
+};
+
+#define to_bst_dev(d) container_of(d, struct bst_dev, dev)
+
+struct bst_dev *bst_allocate_device(void);
+void bst_free_device(struct bst_dev *dev);
+
+static inline struct bst_dev *bst_get_device(struct bst_dev *dev)
+{
+ return dev ? to_bst_dev(get_device(&dev->dev)) : NULL;
+}
+
+static inline void bst_put_device(struct bst_dev *dev)
+{
+ if (dev)
+ put_device(&dev->dev);
+}
+
+static inline void *bst_get_drvdata(struct bst_dev *dev)
+{
+ return dev_get_drvdata(&dev->dev);
+}
+
+static inline void bst_set_drvdata(struct bst_dev *dev, void *data)
+{
+ dev_set_drvdata(&dev->dev, data);
+}
+
+int __must_check bst_register_device(struct bst_dev *);
+void bst_unregister_device(struct bst_dev *);
+
+void bst_reset_device(struct bst_dev *);
+
+
+extern struct class bst_class;
+
+#endif
diff --git a/drivers/input/sensors/smi130/Kconfig b/drivers/input/sensors/smi130/Kconfig
new file mode 100644
index 000000000000..0dd0b393f893
--- /dev/null
+++ b/drivers/input/sensors/smi130/Kconfig
@@ -0,0 +1,121 @@
+#
+# Makefile for Bosch sensors driver.
+#
+config BOSCH_DRIVER_LOG_FUNC
+ tristate "Bosch Sensortec driver smart log function support"
+ depends on (I2C || SPI_MASTER) && SYSFS
+ help
+ If you say yes here, you get support for smart log function in Bosch Sensortec driver.
+
+config SENSORS_SMI_ACC2X2
+ tristate "SMI130_ACC acceleration sensor support"
+ depends on I2C
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ acceleration sensors SMI_ACC255/SMI_ACC254/SMI_ACC355/SMI_ACC250E/SMI_ACC222E/SMI_ACC280.
+
+config SENSORS_SMI_ACC2X2_ENABLE_INT1
+ tristate "SMI_ACC2X2 acceleration sensor interrupt INT1 support"
+ depends on SENSORS_SMI_ACC2X2
+ help
+ If you say yes here, you get INT1 support for Bosch Sensortec
+ acceleration sensors SMI_ACC255/SMI_ACC250E/SMI_ACC222E/SMI_ACC280.
+ Select it will disable interrupt INT2 support
+
+config SENSORS_SMI_ACC2X2_ENABLE_INT2
+ tristate "SMI_ACC2X2 acceleration sensor interrupt INT2 support"
+ depends on SENSORS_SMI_ACC2X2 && !SENSORS_SMI_ACC2X2_ENABLE_INT1
+ help
+ If you say yes here, you get INT2 support for Bosch Sensortec
+ acceleration sensors SMI_ACC255/SMI_ACC250E/SMI_ACC222E/SMI_ACC280.
+ Can only open if you do NOT open interrupt INT1 support
+
+config SIG_MOTION
+ tristate "support significant motion sensor function"
+ depends on SENSORS_SMI_ACC2X2 && ( SENSORS_SMI_ACC2X2_ENABLE_INT1 || SENSORS_SMI_ACC2X2_ENABLE_INT2)
+ help
+ If you say yes here, if you want to support Bosch significant motion sensor function
+
+config DOUBLE_TAP
+ tristate "support double tap sensor function"
+ depends on SENSORS_SMI_ACC2X2 && ( SENSORS_SMI_ACC2X2_ENABLE_INT1 || SENSORS_SMI_ACC2X2_ENABLE_INT2)
+ help
+ If you say yes here, you get support Bosch double tap sensor function
+
+config SENSORS_SMI_GYRO
+ tristate "Bosch Gyroscope Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ gyroscope sensor drivers of SMI130_GYRO/SMI055/BMI058 e.t.c.
+
+config SENSORS_SMI_GYRO_FIFO
+ tristate "Bosch Gyroscope FIFO Support"
+ depends on SENSORS_SMI_GYRO
+ help
+ If you say yes here, you get support for Gyroscope sensor FIFO operations.
+ Please check whether the chip supports fifo feature to open it.
+
+config SENSORS_BMI058
+ tristate "BMI058 Sensor Support"
+ depends on (SENSORS_SMI_GYRO || SENSORS_SMI_ACC2X2)
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ sensor driver of BMI058.
+
+config SENSORS_YAS537
+ tristate "YAS537 Magnetic Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support for YAMAHA
+ sensor YAS537 Magnetic Sensor
+
+config SENSORS_BMM050
+ tristate "BMM050 Magnetic Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ sensor BMM050 Magnetic Sensor
+
+config SENSORS_AKM09911
+ tristate "AKM09911 Mag Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support AKM09911 Sensor support.
+
+config SENSORS_AKM09912
+ tristate "AKM09912 Mag Sensor Driver"
+ depends on I2C
+ help
+ If you say yes here, you get support AKM09912 Sensor support.
+
+config SENSORS_SMI_ACC420
+ tristate "SMI_ACC4XY Sensor Support"
+ depends on I2C || SPI_MASTER
+ help
+ If you say yes here, you get support for Bosch Sensortec's sensor driver of SMI_ACC420.
+config SENSORS_SMI_ACC421
+ tristate "SMI_ACC4XY Sensor Support"
+ depends on I2C || SPI_MASTER
+ help
+ If you say yes here, you get support for Bosch Sensortec's sensor driver of SMI_ACC421.
+config SENSORS_SMI_ACC422
+ tristate "SMI_ACC4XY Sensor Support"
+ depends on I2C || SPI_MASTER
+ help
+ If you say yes here, you get support for Bosch Sensortec's sensor driver of SMI_ACC422.
+config SENSORS_SMI_ACC455
+ tristate "SMI_ACC4XY Sensor Support"
+ depends on I2C || SPI_MASTER
+ help
+ If you say yes here, you get support for Bosch Sensortec's sensor driver of SMI_ACC455.
+
+config SMI_ACC4XY_MAG_INTERFACE_SUPPORT
+tristate "SMI_ACC4XY Sensor mag interface support"
+depends on SENSORS_SMI_ACC4XY
+ help
+ If you say yes here, you get support for Bosch Sensortec's
+ sensor driver of SMI_ACC4XY with mag sensor support.
+
+
+
diff --git a/drivers/input/sensors/smi130/Makefile b/drivers/input/sensors/smi130/Makefile
new file mode 100644
index 000000000000..ad1e5437d652
--- /dev/null
+++ b/drivers/input/sensors/smi130/Makefile
@@ -0,0 +1,47 @@
+#
+# Makefile for Bosch sensor driver.
+#
+
+obj-$(CONFIG_BOSCH_DRIVER_LOG_FUNC) += bs_log.o
+obj-y += boschclass.o
+ifeq ($(CONFIG_BOSCH_DRIVER_LOG_FUNC),y)
+ EXTRA_CFLAGS += -DBOSCH_DRIVER_LOG_FUNC
+endif
+
+obj-y += smi130_acc.o
+
+ifeq ($(CONFIG_SENSORS_SMI_ACC2X2_ENABLE_INT1),y)
+ EXTRA_CFLAGS += -DSMI_ACC2X2_ENABLE_INT1
+endif
+
+ifeq ($(CONFIG_BOSCH_SMI_ACC2X2_ENABLE_INT2),y)
+ EXTRA_CFLAGS += -DSMI_ACC2X2_ENABLE_INT2
+endif
+
+obj-y += smi130_gyro_driver.o smi130_gyro.o
+EXTRA_CFLAGS += -DSMI_GYRO_USE_BASIC_I2C_FUNC
+
+obj-y += smi130_driver.o smi130.o
+ifeq ($(CONFIG_SMI130_MAG_INTERFACE_SUPPORT),y)
+ EXTRA_CFLAGS += -DSMI130_MAG_INTERFACE_SUPPORT
+endif
+ifeq ($(CONFIG_SENSORS_SMI130_ENABLE_INT1),y)
+ EXTRA_CFLAGS += -DSMI130_ENABLE_INT1
+endif
+
+ifeq ($(CONFIG_SENSORS_SMI130_ENABLE_INT2),y)
+ EXTRA_CFLAGS += -DSMI130_ENABLE_INT2
+endif
+
+obj-y += smi130_i2c.o
+
+EXTRA_CFLAGS += -DSMI_USE_BASIC_I2C_FUNC
+
+obj-$(CONFIG_SENSORS_SMI130_SPI) += smi130_spi.o
+
+
+
+
+
+
+
diff --git a/drivers/input/sensors/smi130/boschclass.c b/drivers/input/sensors/smi130/boschclass.c
new file mode 100644
index 000000000000..8c28ab158da4
--- /dev/null
+++ b/drivers/input/sensors/smi130/boschclass.c
@@ -0,0 +1,341 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename boschclass.c
+ * @date 2015/11/17 13:44
+ * @Modification Date 2018/08/28 18:20
+ * @id "836294d"
+ * @version 1.5.9
+ *
+ * @brief
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/poll.h>
+#include <linux/mutex.h>
+#include <linux/rcupdate.h>
+#include <linux/compiler.h>
+#include <linux/compat.h>
+#include "boschclass.h"
+#include "bs_log.h"
+
+static LIST_HEAD(bosch_dev_list);
+
+/*
+ * bosch_mutex protects access to both bosch_dev_list and input_handler_list.
+ * This also causes bosch_[un]register_device and bosch_[un]register_handler
+ * be mutually exclusive which simplifies locking in drivers implementing
+ * input handlers.
+ */
+static DEFINE_MUTEX(bosch_mutex);
+
+
+static void bosch_dev_release(struct device *device)
+{
+ struct bosch_dev *dev = to_bosch_dev(device);
+ if (NULL != dev)
+ kfree(dev);
+ module_put(THIS_MODULE);
+}
+
+
+#ifdef CONFIG_PM
+static int bosch_dev_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int bosch_dev_resume(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops bosch_dev_pm_ops = {
+ .suspend = bosch_dev_suspend,
+ .resume = bosch_dev_resume,
+ .poweroff = bosch_dev_suspend,
+ .restore = bosch_dev_resume,
+};
+#endif /* CONFIG_PM */
+
+static const struct attribute_group *bosch_dev_attr_groups[] = {
+ NULL
+};
+
+static struct device_type bosch_dev_type = {
+ .groups = bosch_dev_attr_groups,
+ .release = bosch_dev_release,
+#ifdef CONFIG_PM
+ .pm = &bosch_dev_pm_ops,
+#endif
+};
+
+
+
+static char *bosch_devnode(struct device *dev, mode_t *mode)
+{
+ return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
+}
+
+struct class bosch_class = {
+ .name = "bosch",
+ .owner = THIS_MODULE,
+ .devnode = (void*)bosch_devnode,
+ .dev_release = bosch_dev_release,
+};
+EXPORT_SYMBOL_GPL(bosch_class);
+
+/**
+ * bosch_allocate_device - allocate memory for new input device
+ *
+ * Returns prepared struct bosch_dev or NULL.
+ *
+ * NOTE: Use bosch_free_device() to free devices that have not been
+ * registered; bosch_unregister_device() should be used for already
+ * registered devices.
+ */
+struct bosch_dev *bosch_allocate_device(void)
+{
+ struct bosch_dev *dev;
+
+ dev = kzalloc(sizeof(struct bosch_dev), GFP_KERNEL);
+ if (dev) {
+ dev->dev.type = &bosch_dev_type;
+ dev->dev.class = &bosch_class;
+ device_initialize(&dev->dev);
+ mutex_init(&dev->mutex);
+ INIT_LIST_HEAD(&dev->node);
+ __module_get(THIS_MODULE);
+ }
+ return dev;
+}
+EXPORT_SYMBOL(bosch_allocate_device);
+
+
+
+/**
+ * bosch_free_device - free memory occupied by bosch_dev structure
+ * @dev: input device to free
+ *
+ * This function should only be used if bosch_register_device()
+ * was not called yet or if it failed. Once device was registered
+ * use bosch_unregister_device() and memory will be freed once last
+ * reference to the device is dropped.
+ *
+ * Device should be allocated by bosch_allocate_device().
+ *
+ * NOTE: If there are references to the input device then memory
+ * will not be freed until last reference is dropped.
+ */
+void bosch_free_device(struct bosch_dev *dev)
+{
+ if (dev)
+ bosch_put_device(dev);
+}
+EXPORT_SYMBOL(bosch_free_device);
+
+/**
+ * bosch_register_device - register device with input core
+ * @dev: device to be registered
+ *
+ * This function registers device with input core. The device must be
+ * allocated with bosch_allocate_device() and all it's capabilities
+ * set up before registering.
+ * If function fails the device must be freed with bosch_free_device().
+ * Once device has been successfully registered it can be unregistered
+ * with bosch_unregister_device(); bosch_free_device() should not be
+ * called in this case.
+ */
+int bosch_register_device(struct bosch_dev *dev)
+{
+ const char *path;
+ int error;
+
+
+ /*
+ * If delay and period are pre-set by the driver, then autorepeating
+ * is handled by the driver itself and we don't do it in input.c.
+ */
+ dev_set_name(&dev->dev, dev->name);
+
+ error = device_add(&dev->dev);
+ if (error)
+ return error;
+
+ path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
+ PINFO("%s as %s\n",
+ dev->name ? dev->name : "Unspecified device",
+ path ? path : "N/A");
+ kfree(path);
+ error = mutex_lock_interruptible(&bosch_mutex);
+ if (error) {
+ device_del(&dev->dev);
+ return error;
+ }
+
+ list_add_tail(&dev->node, &bosch_dev_list);
+
+ mutex_unlock(&bosch_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(bosch_register_device);
+
+/**
+ * bosch_unregister_device - unregister previously registered device
+ * @dev: device to be unregistered
+ *
+ * This function unregisters an input device. Once device is unregistered
+ * the caller should not try to access it as it may get freed at any moment.
+ */
+void bosch_unregister_device(struct bosch_dev *dev)
+{
+ int ret = 0;
+ ret = mutex_lock_interruptible(&bosch_mutex);
+ if(ret){
+ return;
+ }
+
+ list_del_init(&dev->node);
+ mutex_unlock(&bosch_mutex);
+ device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL(bosch_unregister_device);
+
+static int __init bosch_init(void)
+{
+ int err;
+ /*bosch class register*/
+ err = class_register(&bosch_class);
+ if (err) {
+ pr_err("unable to register bosch_dev class\n");
+ return err;
+ }
+ return err;
+}
+
+static void __exit bosch_exit(void)
+{
+ /*bosch class*/
+ class_unregister(&bosch_class);
+}
+
+/*subsys_initcall(bosch_init);*/
+
+MODULE_AUTHOR("contact@bosch-sensortec.com");
+MODULE_DESCRIPTION("BST CLASS CORE");
+MODULE_LICENSE("GPL V2");
+
+module_init(bosch_init);
+module_exit(bosch_exit);
diff --git a/drivers/input/sensors/smi130/boschclass.h b/drivers/input/sensors/smi130/boschclass.h
new file mode 100644
index 000000000000..a89cc5d94e64
--- /dev/null
+++ b/drivers/input/sensors/smi130/boschclass.h
@@ -0,0 +1,181 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename boschcalss.h
+ * @date 2015/11/17 13:44
+ * @Modification Date 2018/08/28 18:20
+ * @id "836294d"
+ * @version 1.5.9
+ *
+ * @brief
+ */
+
+#ifndef _BSTCLASS_H
+#define _BSTCLASS_H
+
+#ifdef __KERNEL__
+#include <linux/time.h>
+#include <linux/list.h>
+#else
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <linux/types.h>
+#endif
+
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/mod_devicetable.h>
+
+struct bosch_dev {
+ const char *name;
+
+ int (*open)(struct bosch_dev *dev);
+ void (*close)(struct bosch_dev *dev);
+ struct mutex mutex;
+ struct device dev;
+ struct list_head node;
+};
+
+#define to_bosch_dev(d) container_of(d, struct bosch_dev, dev)
+
+struct bosch_dev *bosch_allocate_device(void);
+void bosch_free_device(struct bosch_dev *dev);
+
+static inline struct bosch_dev *bosch_get_device(struct bosch_dev *dev)
+{
+ return dev ? to_bosch_dev(get_device(&dev->dev)) : NULL;
+}
+
+static inline void bosch_put_device(struct bosch_dev *dev)
+{
+ if (dev)
+ put_device(&dev->dev);
+}
+
+static inline void *bosch_get_drvdata(struct bosch_dev *dev)
+{
+ return dev_get_drvdata(&dev->dev);
+}
+
+static inline void bosch_set_drvdata(struct bosch_dev *dev, void *data)
+{
+ dev_set_drvdata(&dev->dev, data);
+}
+
+int __must_check bosch_register_device(struct bosch_dev *);
+void bosch_unregister_device(struct bosch_dev *);
+
+void bosch_reset_device(struct bosch_dev *);
+
+
+extern struct class bosch_class;
+
+#endif
diff --git a/drivers/input/sensors/smi130/bs_log.c b/drivers/input/sensors/smi130/bs_log.c
new file mode 100644
index 000000000000..05ddddd96683
--- /dev/null
+++ b/drivers/input/sensors/smi130/bs_log.c
@@ -0,0 +1,153 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename bs_log.c
+ * @date "Wed Sep 24 15:27:12 2014 +0800"
+ * @Modification Date 2018/08/28 18:20
+ * @id "e416c14"
+ *
+ * @brief
+ * The source file of BOSCH SENSOR LOG
+*/
+
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/unistd.h>
+#include <linux/types.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#endif
+
+#include <linux/time.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#ifdef BOSCH_DRIVER_LOG_FUNC
+#define BSLOG_VAR_DEF
+#include "bs_log.h"
+
+void set_debug_log_level(uint8_t level)
+{
+ debug_log_level = level;
+}
+
+uint8_t get_debug_log_level(void)
+{
+ return debug_log_level;
+}
+
+EXPORT_SYMBOL(set_debug_log_level);
+EXPORT_SYMBOL(get_debug_log_level);
+
+#endif/*BOSCH_DRIVER_LOG_FUNC*/
+/*@}*/
diff --git a/drivers/input/sensors/smi130/bs_log.h b/drivers/input/sensors/smi130/bs_log.h
new file mode 100644
index 000000000000..86ef153c5281
--- /dev/null
+++ b/drivers/input/sensors/smi130/bs_log.h
@@ -0,0 +1,274 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename bs_log.h
+ * @date "Sat Oct 11 16:12:16 2014 +0800"
+ * @Modification Date 2018/08/28 18:20
+ * @id "762cc9e"
+ *
+ * @brief
+ * The head file of BOSCH SENSOR LOG
+*/
+
+#ifndef __BS_LOG_H
+#define __BS_LOG_H
+
+#include <linux/kernel.h>
+
+/*! @ trace functions
+ @{*/
+/*! ERROR LOG LEVEL */
+#define LOG_LEVEL_E 3
+/*! NOTICE LOG LEVEL */
+#define LOG_LEVEL_N 5
+/*! INFORMATION LOG LEVEL */
+#define LOG_LEVEL_I 6
+/*! DEBUG LOG LEVEL */
+#define LOG_LEVEL_D 7
+/*! DEBUG_FWDL LOG LEVEL */
+#define LOG_LEVEL_DF 10
+/*! DEBUG_DATA LOG LEVEL */
+#define LOG_LEVEL_DA 15
+/*! ALL LOG LEVEL */
+#define LOG_LEVEL_A 20
+
+#ifndef MODULE_TAG
+/*! MODULE TAG DEFINATION */
+#define MODULE_TAG "<BS_LOG>"
+#endif
+
+#ifndef LOG_LEVEL
+/*! LOG LEVEL DEFINATION */
+#define LOG_LEVEL LOG_LEVEL_I
+#endif
+
+#ifdef BOSCH_DRIVER_LOG_FUNC
+ #ifdef BSLOG_VAR_DEF
+ uint8_t debug_log_level = LOG_LEVEL;
+ #else
+ extern uint8_t debug_log_level;
+ #endif
+
+ /*! print error message */
+ #define PERR(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_E)\
+ printk(KERN_INFO "\n" "[E]" KERN_ERR MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print notice message */
+ #define PNOTICE(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_N)\
+ printk(KERN_INFO "\n" "[N]" KERN_NOTICE MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print information message */
+ #define PINFO(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_I)\
+ printk(KERN_INFO "\n" "[I]" KERN_INFO MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print debug message */
+ #define PDEBUG(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_D)\
+ printk(KERN_INFO "\n" "[D]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print debug fw download message */
+ #define PDEBUG_FWDL(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_DF)\
+ printk(KERN_INFO "\n" "[DF]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ /*! print debug data log message */
+ #define PDEBUG_DLOG(fmt, args...) do\
+ {\
+ if (debug_log_level >= LOG_LEVEL_DA)\
+ printk(KERN_INFO "\n" "[DA]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args);\
+ } while (0)
+
+ void set_debug_log_level(uint8_t level);
+ uint8_t get_debug_log_level(void);
+
+#else
+
+ #if (LOG_LEVEL >= LOG_LEVEL_E)
+ /*! print error message */
+ #define PERR(fmt, args...) \
+ printk(KERN_INFO "\n" "[E]" KERN_ERR MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PERR(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_N)
+ /*! print notice message */
+ #define PNOTICE(fmt, args...) \
+ printk(KERN_INFO "\n" "[N]" KERN_NOTICE MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PNOTICE(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_I)
+ /*! print information message */
+ #define PINFO(fmt, args...) printk(KERN_INFO "\n" "[I]" KERN_INFO MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PINFO(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_D)
+ /*! print debug message */
+ #define PDEBUG(fmt, args...) printk(KERN_INFO "\n" "[D]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PDEBUG(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_DF)
+ /*! print debug fw download message */
+ #define PDEBUG_FWDL(fmt, args...) printk(KERN_INFO "\n" "[DF]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PDEBUG_FWDL(fmt, args...)
+ #endif
+
+ #if (LOG_LEVEL >= LOG_LEVEL_DA)
+ /*! print debug data log message */
+ #define PDEBUG_DLOG(fmt, args...) printk(KERN_INFO "\n" "[DA]" KERN_DEBUG MODULE_TAG \
+ "<%s><%d>" fmt "\n", __func__, __LINE__, ##args)
+ #else
+ /*! invalid message */
+ #define PDEBUG_DLOG(fmt, args...)
+ #endif
+
+ #define set_debug_log_level(level) {}
+ #define get_debug_log_level() (LOG_LEVEL)
+
+#endif
+
+#endif/*__BS_LOG_H*/
+/*@}*/
diff --git a/drivers/input/sensors/smi130/modules.order b/drivers/input/sensors/smi130/modules.order
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/input/sensors/smi130/modules.order
diff --git a/drivers/input/sensors/smi130/readme.md b/drivers/input/sensors/smi130/readme.md
new file mode 100644
index 000000000000..48b2cc16b134
--- /dev/null
+++ b/drivers/input/sensors/smi130/readme.md
@@ -0,0 +1,49 @@
+# SMI130 sensor API
+## Introduction
+This package contains the Robert Bosch GmbH's SMI130 sensor driver (sensor API)
+
+## Version
+File | Version | Date
+---------------------|---------|---------------
+smi130.h | 2.0.9 | 2018/08/28
+smi130.c | 2.0.9 | 2018/08/28
+smi130_spi.c | 1.3 | 2018/08/28
+smi130_i2c.c | 1.3 | 2018/08/28
+smi130_gyro_driver.c | 1.5.9 | 2018/08/28
+smi130_gyro.c | 1.5 | 2018/08/28
+smi130_gyro.h | 1.5 | 2018/08/28
+smi130_driver.h | 1.3 | 2018/08/28
+smi130_driver.c | 1.3 | 2018/08/28
+smi130_acc.c | 2.1.2 | 2018/08/28
+bs_log.h | | 2018/08/28
+bs_log.c | | 2018/08/28
+boschcalss.h | 1.5.9 | 2018/08/28
+boschclass.c | 1.5.9 | 2018/08/28
+
+
+
+## File information
+* smi130.h : The head file of SMI130API
+* smi130.c : Sensor Driver for SMI130 sensor
+* smi130_spi.c : This file implements moudle function, which add the driver to SPI core.
+* smi130_i2c.c : This file implements moudle function, which add the driver to I2C core.
+* smi130_driver.h : The head file of SMI130 device driver core code
+* smi130_driver.c : This file implements the core code of SMI130 device driver
+* bs_log.h : The head file of BOSCH SENSOR LOG
+* bs_log.c : The source file of BOSCH SENSOR LOG
+* boschcalss.h :
+* boschclass.c :
+
+
+## Supported sensor interface
+* SPI 4-wire
+* I2C
+
+## Copyright
+
+Copyright (C) 2016 - 2017 Bosch Sensortec GmbH
+Modification Copyright (C) 2018 Robert Bosch Kft All Rights Reserved
+
+This software program is licensed subject to the GNU General
+Public License (GPL).Version 2,June 1991,
+available at http://www.fsf.org/copyleft/gpl.html \ No newline at end of file
diff --git a/drivers/input/sensors/smi130/smi130.c b/drivers/input/sensors/smi130/smi130.c
new file mode 100644
index 000000000000..1ddd3b56877a
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130.c
@@ -0,0 +1,18785 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+*
+* @filename smi130.c
+* @Date: 2015/04/02
+* @Modification Date 2018/08/28 18:20
+* @id 836294d
+* @Revision: 2.0.9 $
+*
+* Usage: Sensor Driver for SMI130 sensor
+*/
+
+
+#include "smi130.h"
+#include <linux/kernel.h>
+
+/* user defined code to be added here ... */
+struct smi130_t *p_smi130;
+/* used for reading the mag trim values for compensation*/
+struct trim_data_t mag_trim_mbl;
+/* the following variable used for avoiding the selecting of auto mode
+when it is running in the manual mode of BMM150 mag interface*/
+u8 V_bmm150_maual_auto_condition_u8_mbl = SMI130_INIT_VALUE;
+/* used for reading the AKM compensating data */
+struct bosch_akm_sensitivity_data_t akm_asa_data_mbl;
+/* Assign the fifo time */
+u32 V_fifo_time_U32_mbl = SMI130_INIT_VALUE;
+
+/* FIFO data read for 1024 bytes of data */
+u8 v_fifo_data_u8_mbl[FIFO_FRAME] = {SMI130_INIT_VALUE};
+/* YAMAHA-YAS532*/
+/* value of coeff*/
+static const int yas532_version_ac_coef[] = {YAS532_VERSION_AC_COEF_X,
+YAS532_VERSION_AC_COEF_Y1, YAS532_VERSION_AC_COEF_Y2};
+/* used for reading the yas532 calibration data*/
+struct yas532_t yas532_data_mbl;
+/* used for reading the yas537 calibration data*/
+struct yas537_t yas537_data_mbl;
+/*!
+ * @brief
+ * This function is used for initialize
+ * bus read and bus write functions
+ * assign the chip id and device address
+ * chip id is read in the register 0x00 bit from 0 to 7
+ *
+ * @param smi130 : structure pointer
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * While changing the parameter of the smi130_t
+ * consider the following point:
+ * Changing the reference value of the parameter
+ * will changes the local copy or local reference
+ * make sure your changes will not
+ * affect the reference value of the parameter
+ * (Better case don't change the reference value of the parameter)
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_init(struct smi130_t *smi130)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ u8 v_pmu_data_u8 = SMI130_INIT_VALUE;
+ /* assign smi130 ptr */
+ p_smi130 = smi130;
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_CHIP_ID__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* read Chip Id */
+ p_smi130->chip_id = v_data_u8;
+ /* To avoid gyro wakeup it is required to write 0x00 to 0x6C*/
+ com_rslt += smi130_write_reg(SMI130_USER_PMU_TRIGGER_ADDR,
+ &v_pmu_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ return com_rslt;
+}
+/*!
+ * @brief
+ * This API write the data to
+ * the given register
+ *
+ *
+ * @param v_addr_u8 -> Address of the register
+ * @param v_data_u8 -> The data from the register
+ * @param v_len_u8 -> no of bytes to read
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_write_reg(u8 v_addr_u8,
+u8 *v_data_u8, u8 v_len_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write data from register*/
+ com_rslt =
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->dev_addr,
+ v_addr_u8, v_data_u8, v_len_u8);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief
+ * This API reads the data from
+ * the given register
+ *
+ *
+ * @param v_addr_u8 -> Address of the register
+ * @param v_data_u8 -> The data from the register
+ * @param v_len_u8 -> no of bytes to read
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_read_reg(u8 v_addr_u8,
+u8 *v_data_u8, u8 v_len_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* Read data from register*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ v_addr_u8, v_data_u8, v_len_u8);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API used to reads the fatal error
+ * from the Register 0x02 bit 0
+ * This flag will be reset only by power-on-reset and soft reset
+ *
+ *
+ * @param v_fatal_err_u8 : The status of fatal error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fatal_err(u8
+*v_fatal_err_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* reading the fatal error status*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FATAL_ERR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fatal_err_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FATAL_ERR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API used to read the error code
+ * from register 0x02 bit 1 to 4
+ *
+ *
+ * @param v_err_code_u8 : The status of error codes
+ * error_code | description
+ * ------------|---------------
+ * 0x00 |no error
+ * 0x01 |ACC_CONF error (accel ODR and bandwidth not compatible)
+ * 0x02 |GYR_CONF error (Gyroscope ODR and bandwidth not compatible)
+ * 0x03 |Under sampling mode and interrupt uses pre filtered data
+ * 0x04 |reserved
+ * 0x05 |Selected trigger-readout offset in
+ * - |MAG_IF greater than selected ODR
+ * 0x06 |FIFO configuration error for header less mode
+ * 0x07 |Under sampling mode and pre filtered data as FIFO source
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_err_code(u8
+*v_err_code_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ERR_CODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_err_code_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_ERR_CODE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API Reads the i2c error code from the
+ * Register 0x02 bit 5.
+ * This error occurred in I2C master detected
+ *
+ * @param v_i2c_err_code_u8 : The status of i2c fail error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_i2c_fail_err(u8
+*v_i2c_err_code_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_I2C_FAIL_ERR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_i2c_err_code_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_I2C_FAIL_ERR);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API Reads the dropped command error
+ * from the register 0x02 bit 6
+ *
+ *
+ * @param v_drop_cmd_err_u8 : The status of drop command error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_drop_cmd_err(u8
+*v_drop_cmd_err_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_DROP_CMD_ERR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_drop_cmd_err_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_DROP_CMD_ERR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the magnetometer data ready
+ * interrupt not active.
+ * It reads from the error register 0x0x2 bit 7
+ *
+ *
+ *
+ *
+ * @param v_mag_data_rdy_err_u8 : The status of mag data ready interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_dada_rdy_err(
+u8 *v_mag_data_rdy_err_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_MAG_DADA_RDY_ERR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_data_rdy_err_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_DADA_RDY_ERR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the error status
+ * from the error register 0x02 bit 0 to 7
+ *
+ * @param v_mag_data_rdy_err_u8 : The status of mag data ready interrupt
+ * @param v_fatal_er_u8r : The status of fatal error
+ * @param v_err_code_u8 : The status of error code
+ * @param v_i2c_fail_err_u8 : The status of I2C fail error
+ * @param v_drop_cmd_err_u8 : The status of drop command error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_error_status(u8 *v_fatal_er_u8r,
+u8 *v_err_code_u8, u8 *v_i2c_fail_err_u8,
+u8 *v_drop_cmd_err_u8, u8 *v_mag_data_rdy_err_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the error codes*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ERR_STAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* fatal error*/
+ *v_fatal_er_u8r =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FATAL_ERR);
+ /* user error*/
+ *v_err_code_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_ERR_CODE);
+ /* i2c fail error*/
+ *v_i2c_fail_err_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_I2C_FAIL_ERR);
+ /* drop command error*/
+ *v_drop_cmd_err_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_DROP_CMD_ERR);
+ /* mag data ready error*/
+ *v_mag_data_rdy_err_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_DADA_RDY_ERR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the magnetometer power mode from
+ * PMU status register 0x03 bit 0 and 1
+ *
+ * @param v_mag_power_mode_stat_u8 : The value of mag power mode
+ * mag_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * LOW POWER | 0x02
+ *
+ *
+ * @note The power mode of mag set by the 0x7E command register
+ * @note using the function "smi130_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x18 | MAG_MODE_SUSPEND
+ * 0x19 | MAG_MODE_NORMAL
+ * 0x1A | MAG_MODE_LOWPOWER
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_power_mode_stat(u8
+*v_mag_power_mode_stat_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_POWER_MODE_STAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_power_mode_stat_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_POWER_MODE_STAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the gyroscope power mode from
+ * PMU status register 0x03 bit 2 and 3
+ *
+ * @param v_gyro_power_mode_stat_u8 : The value of gyro power mode
+ * gyro_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * FAST POWER UP | 0x03
+ *
+ * @note The power mode of gyro set by the 0x7E command register
+ * @note using the function "smi130_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x14 | GYRO_MODE_SUSPEND
+ * 0x15 | GYRO_MODE_NORMAL
+ * 0x17 | GYRO_MODE_FASTSTARTUP
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_power_mode_stat(u8
+*v_gyro_power_mode_stat_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_GYRO_POWER_MODE_STAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_power_mode_stat_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_POWER_MODE_STAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the accelerometer power mode from
+ * PMU status register 0x03 bit 4 and 5
+ *
+ *
+ * @param v_accel_power_mode_stat_u8 : The value of accel power mode
+ * accel_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * LOW POWER | 0x02
+ *
+ * @note The power mode of accel set by the 0x7E command register
+ * @note using the function "smi130_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x11 | ACCEL_MODE_NORMAL
+ * 0x12 | ACCEL_LOWPOWER
+ * 0x10 | ACCEL_SUSPEND
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_power_mode_stat(u8
+*v_accel_power_mode_stat_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ACCEL_POWER_MODE_STAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_power_mode_stat_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_POWER_MODE_STAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API switch mag interface to normal mode
+ * and confirm whether the mode switching done successfully or not
+*
+ * @return results of bus communication function and current MAG_PMU result
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_interface_normal(void)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = SMI130_INIT_VALUE;
+ /* aim to check the result of switching mag normal */
+ u8 v_try_times_u8 = SMI130_MAG_NOAMRL_SWITCH_TIMES;
+ u8 v_mag_pum_status_u8 = SMI130_INIT_VALUE;
+
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt = smi130_set_command_register(MAG_MODE_NORMAL);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ while (v_try_times_u8) {
+ com_rslt = smi130_get_mag_power_mode_stat(&v_mag_pum_status_u8);
+ if (v_mag_pum_status_u8 == MAG_INTERFACE_PMU_ENABLE)
+ break;
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ v_try_times_u8--;
+ }
+ if (v_mag_pum_status_u8 == MAG_INTERFACE_PMU_ENABLE)
+ com_rslt += SUCCESS;
+ else
+ com_rslt += E_SMI130_COMM_RES;
+
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data X values
+ * from the register 0x04 and 0x05
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_x_s16 : The value of mag x
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_x(s16 *v_mag_x_s16,
+u8 v_sensor_select_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the mag X lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[SMI130_MAG_X_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_sensor_select_u8) {
+ case BST_BMM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_DATA_MAG_X_LSB__REG,
+ v_data_u8, SMI130_MAG_X_DATA_LENGTH);
+ /* X axis*/
+ v_data_u8[SMI130_MAG_X_LSB_BYTE] =
+ SMI130_GET_BITSLICE(v_data_u8[SMI130_MAG_X_LSB_BYTE],
+ SMI130_USER_DATA_MAG_X_LSB);
+ *v_mag_x_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_MAG_X_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_05_BITS) |
+ (v_data_u8[SMI130_MAG_X_LSB_BYTE]));
+ break;
+ case BST_AKM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_0_MAG_X_LSB__REG,
+ v_data_u8, SMI130_MAG_X_DATA_LENGTH);
+ *v_mag_x_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_MAG_X_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_MAG_X_LSB_BYTE]));
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data Y values
+ * from the register 0x06 and 0x07
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_y_s16 : The value of mag y
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_y(s16 *v_mag_y_s16,
+u8 v_sensor_select_u8)
+{
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_OUT_OF_RANGE;
+ /* Array contains the mag Y lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[SMI130_MAG_Y_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_sensor_select_u8) {
+ case BST_BMM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_DATA_MAG_Y_LSB__REG,
+ v_data_u8, SMI130_MAG_Y_DATA_LENGTH);
+ /*Y-axis lsb value shifting*/
+ v_data_u8[SMI130_MAG_Y_LSB_BYTE] =
+ SMI130_GET_BITSLICE(v_data_u8[SMI130_MAG_Y_LSB_BYTE],
+ SMI130_USER_DATA_MAG_Y_LSB);
+ *v_mag_y_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_MAG_Y_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_05_BITS) |
+ (v_data_u8[SMI130_MAG_Y_LSB_BYTE]));
+ break;
+ case BST_AKM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_DATA_2_MAG_Y_LSB__REG,
+ v_data_u8, SMI130_MAG_Y_DATA_LENGTH);
+ *v_mag_y_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_MAG_Y_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_MAG_Y_LSB_BYTE]));
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data Z values
+ * from the register 0x08 and 0x09
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_z_s16 : The value of mag z
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_z(s16 *v_mag_z_s16,
+u8 v_sensor_select_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the mag Z lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[SMI130_MAG_Z_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_sensor_select_u8) {
+ case BST_BMM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_DATA_MAG_Z_LSB__REG,
+ v_data_u8, SMI130_MAG_Z_DATA_LENGTH);
+ /*Z-axis lsb value shifting*/
+ v_data_u8[SMI130_MAG_Z_LSB_BYTE] =
+ SMI130_GET_BITSLICE(v_data_u8[SMI130_MAG_Z_LSB_BYTE],
+ SMI130_USER_DATA_MAG_Z_LSB);
+ *v_mag_z_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_MAG_Z_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_07_BITS) |
+ (v_data_u8[SMI130_MAG_Z_LSB_BYTE]));
+ break;
+ case BST_AKM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_DATA_4_MAG_Z_LSB__REG,
+ v_data_u8, SMI130_MAG_Z_DATA_LENGTH);
+ *v_mag_z_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_MAG_Z_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | (
+ v_data_u8[SMI130_MAG_Z_LSB_BYTE]));
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data RHALL values
+ * from the register 0x0A and 0x0B
+ *
+ *
+ * @param v_mag_r_s16 : The value of BMM150 r data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_r(s16 *v_mag_r_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the mag R lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[SMI130_MAG_R_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_6_RHALL_LSB__REG,
+ v_data_u8, SMI130_MAG_R_DATA_LENGTH);
+ /*R-axis lsb value shifting*/
+ v_data_u8[SMI130_MAG_R_LSB_BYTE] =
+ SMI130_GET_BITSLICE(v_data_u8[SMI130_MAG_R_LSB_BYTE],
+ SMI130_USER_DATA_MAG_R_LSB);
+ *v_mag_r_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_MAG_R_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_06_BITS) |
+ (v_data_u8[SMI130_MAG_R_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads magnetometer data X,Y,Z values
+ * from the register 0x04 to 0x09
+ *
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param mag : The value of mag xyz data
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_xyz(
+struct smi130_mag_t *mag, u8 v_sensor_select_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the mag XYZ lSB and MSB data
+ v_data_u8[0] - X-LSB
+ v_data_u8[1] - X-MSB
+ v_data_u8[0] - Y-LSB
+ v_data_u8[1] - Y-MSB
+ v_data_u8[0] - Z-LSB
+ v_data_u8[1] - Z-MSB
+ */
+ u8 v_data_u8[SMI130_MAG_XYZ_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_sensor_select_u8) {
+ case BST_BMM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_DATA_MAG_X_LSB__REG,
+ v_data_u8, SMI130_MAG_XYZ_DATA_LENGTH);
+ /*X-axis lsb value shifting*/
+ v_data_u8[SMI130_DATA_FRAME_MAG_X_LSB_BYTE] =
+ SMI130_GET_BITSLICE(
+ v_data_u8[SMI130_DATA_FRAME_MAG_X_LSB_BYTE],
+ SMI130_USER_DATA_MAG_X_LSB);
+ /* Data X */
+ mag->x = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_X_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_05_BITS) |
+ (v_data_u8[SMI130_DATA_FRAME_MAG_X_LSB_BYTE]));
+ /* Data Y */
+ /*Y-axis lsb value shifting*/
+ v_data_u8[SMI130_DATA_FRAME_MAG_Y_LSB_BYTE] =
+ SMI130_GET_BITSLICE(
+ v_data_u8[SMI130_DATA_FRAME_MAG_Y_LSB_BYTE],
+ SMI130_USER_DATA_MAG_Y_LSB);
+ mag->y = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_Y_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_05_BITS) |
+ (v_data_u8[SMI130_DATA_FRAME_MAG_Y_LSB_BYTE]));
+
+ /* Data Z */
+ /*Z-axis lsb value shifting*/
+ v_data_u8[SMI130_DATA_FRAME_MAG_Z_LSB_BYTE]
+ = SMI130_GET_BITSLICE(
+ v_data_u8[SMI130_DATA_FRAME_MAG_Z_LSB_BYTE],
+ SMI130_USER_DATA_MAG_Z_LSB);
+ mag->z = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_Z_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_07_BITS) |
+ (v_data_u8[SMI130_DATA_FRAME_MAG_Z_LSB_BYTE]));
+ break;
+ case BST_AKM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_0_MAG_X_LSB__REG,
+ v_data_u8, SMI130_MAG_XYZ_DATA_LENGTH);
+ /* Data X */
+ mag->x = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_X_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_DATA_FRAME_MAG_X_LSB_BYTE]));
+ /* Data Y */
+ mag->y = ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_Y_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_DATA_FRAME_MAG_Y_LSB_BYTE]));
+ /* Data Z */
+ mag->z = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_Z_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_DATA_FRAME_MAG_Z_LSB_BYTE]));
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!*
+ * @brief This API reads magnetometer data X,Y,Z,r
+ * values from the register 0x04 to 0x0B
+ *
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param mag : The value of mag-BMM150 xyzr data
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_xyzr(
+struct smi130_mag_xyzr_t *mag)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8[SMI130_MAG_XYZR_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_MAG_X_LSB__REG,
+ v_data_u8, SMI130_MAG_XYZR_DATA_LENGTH);
+
+ /* Data X */
+ /*X-axis lsb value shifting*/
+ v_data_u8[SMI130_DATA_FRAME_MAG_X_LSB_BYTE]
+ = SMI130_GET_BITSLICE(
+ v_data_u8[SMI130_DATA_FRAME_MAG_X_LSB_BYTE],
+ SMI130_USER_DATA_MAG_X_LSB);
+ mag->x = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_X_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_05_BITS)
+ | (v_data_u8[SMI130_DATA_FRAME_MAG_X_LSB_BYTE]));
+ /* Data Y */
+ /*Y-axis lsb value shifting*/
+ v_data_u8[SMI130_DATA_FRAME_MAG_Y_LSB_BYTE]
+ = SMI130_GET_BITSLICE(
+ v_data_u8[SMI130_DATA_FRAME_MAG_Y_LSB_BYTE],
+ SMI130_USER_DATA_MAG_Y_LSB);
+ mag->y = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_Y_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_05_BITS)
+ | (v_data_u8[
+ SMI130_DATA_FRAME_MAG_Y_LSB_BYTE]));
+
+ /* Data Z */
+ /*Z-axis lsb value shifting*/
+ v_data_u8[SMI130_DATA_FRAME_MAG_Z_LSB_BYTE]
+ = SMI130_GET_BITSLICE(
+ v_data_u8[SMI130_DATA_FRAME_MAG_Z_LSB_BYTE],
+ SMI130_USER_DATA_MAG_Z_LSB);
+ mag->z = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_Z_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_07_BITS)
+ | (v_data_u8[SMI130_DATA_FRAME_MAG_Z_LSB_BYTE]));
+
+ /* RHall */
+ /*R-axis lsb value shifting*/
+ v_data_u8[SMI130_DATA_FRAME_MAG_R_LSB_BYTE]
+ = SMI130_GET_BITSLICE(
+ v_data_u8[SMI130_DATA_FRAME_MAG_R_LSB_BYTE],
+ SMI130_USER_DATA_MAG_R_LSB);
+ mag->r = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_MAG_R_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_06_BITS)
+ | (v_data_u8[SMI130_DATA_FRAME_MAG_R_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads gyro data X values
+ * form the register 0x0C and 0x0D
+ *
+ *
+ *
+ *
+ * @param v_gyro_x_s16 : The value of gyro x data
+ *
+ * @note Gyro Configuration use the following function
+ * @note smi130_set_gyro_output_data_rate()
+ * @note smi130_set_gyro_bw()
+ * @note smi130_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_gyro_x(s16 *v_gyro_x_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the gyro X lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[MSB_ONE] - MSB*/
+ u8 v_data_u8[SMI130_GYRO_X_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_8_GYRO_X_LSB__REG,
+ v_data_u8, SMI130_GYRO_DATA_LENGTH);
+
+ *v_gyro_x_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_GYRO_X_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[SMI130_GYRO_X_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads gyro data Y values
+ * form the register 0x0E and 0x0F
+ *
+ *
+ *
+ *
+ * @param v_gyro_y_s16 : The value of gyro y data
+ *
+ * @note Gyro Configuration use the following function
+ * @note smi130_set_gyro_output_data_rate()
+ * @note smi130_set_gyro_bw()
+ * @note smi130_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error result of communication routines
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_gyro_y(s16 *v_gyro_y_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the gyro Y lSB and MSB data
+ v_data_u8[LSB_ZERO] - LSB
+ v_data_u8[MSB_ONE] - MSB*/
+ u8 v_data_u8[SMI130_GYRO_Y_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro y data*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_10_GYRO_Y_LSB__REG,
+ v_data_u8, SMI130_GYRO_DATA_LENGTH);
+
+ *v_gyro_y_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_GYRO_Y_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[SMI130_GYRO_Y_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads gyro data Z values
+ * form the register 0x10 and 0x11
+ *
+ *
+ *
+ *
+ * @param v_gyro_z_s16 : The value of gyro z data
+ *
+ * @note Gyro Configuration use the following function
+ * @note smi130_set_gyro_output_data_rate()
+ * @note smi130_set_gyro_bw()
+ * @note smi130_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_gyro_z(s16 *v_gyro_z_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the gyro Z lSB and MSB data
+ v_data_u8[LSB_ZERO] - LSB
+ v_data_u8[MSB_ONE] - MSB*/
+ u8 v_data_u8[SMI130_GYRO_Z_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro z data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_12_GYRO_Z_LSB__REG,
+ v_data_u8, SMI130_GYRO_DATA_LENGTH);
+
+ *v_gyro_z_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_GYRO_Z_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[SMI130_GYRO_Z_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads gyro data X,Y,Z values
+ * from the register 0x0C to 0x11
+ *
+ *
+ *
+ *
+ * @param gyro : The value of gyro xyz
+ *
+ * @note Gyro Configuration use the following function
+ * @note smi130_set_gyro_output_data_rate()
+ * @note smi130_set_gyro_bw()
+ * @note smi130_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_gyro_xyz(struct smi130_gyro_t *gyro)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the mag XYZ lSB and MSB data
+ v_data_u8[0] - X-LSB
+ v_data_u8[1] - X-MSB
+ v_data_u8[0] - Y-LSB
+ v_data_u8[1] - Y-MSB
+ v_data_u8[0] - Z-LSB
+ v_data_u8[1] - Z-MSB
+ */
+ u8 v_data_u8[SMI130_GYRO_XYZ_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the gyro xyz data*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_8_GYRO_X_LSB__REG,
+ v_data_u8, SMI130_GYRO_XYZ_DATA_LENGTH);
+
+ /* Data X */
+ gyro->x = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_GYRO_X_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[SMI130_DATA_FRAME_GYRO_X_LSB_BYTE]));
+ /* Data Y */
+ gyro->y = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_GYRO_Y_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[SMI130_DATA_FRAME_GYRO_Y_LSB_BYTE]));
+
+ /* Data Z */
+ gyro->z = (s16)
+ ((((s32)((s8)v_data_u8[
+ SMI130_DATA_FRAME_GYRO_Z_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[SMI130_DATA_FRAME_GYRO_Z_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads accelerometer data X values
+ * form the register 0x12 and 0x13
+ *
+ *
+ *
+ *
+ * @param v_accel_x_s16 : The value of accel x
+ *
+ * @note For accel configuration use the following functions
+ * @note smi130_set_accel_output_data_rate()
+ * @note smi130_set_accel_bw()
+ * @note smi130_set_accel_under_sampling_parameter()
+ * @note smi130_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_accel_x(s16 *v_accel_x_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the accel X lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[SMI130_ACCEL_X_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_14_ACCEL_X_LSB__REG,
+ v_data_u8, SMI130_ACCEL_DATA_LENGTH);
+
+ *v_accel_x_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_ACCEL_X_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[SMI130_ACCEL_X_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads accelerometer data Y values
+ * form the register 0x14 and 0x15
+ *
+ *
+ *
+ *
+ * @param v_accel_y_s16 : The value of accel y
+ *
+ * @note For accel configuration use the following functions
+ * @note smi130_set_accel_output_data_rate()
+ * @note smi130_set_accel_bw()
+ * @note smi130_set_accel_under_sampling_parameter()
+ * @note smi130_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_accel_y(s16 *v_accel_y_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the accel Y lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[SMI130_ACCEL_Y_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_16_ACCEL_Y_LSB__REG,
+ v_data_u8, SMI130_ACCEL_DATA_LENGTH);
+
+ *v_accel_y_s16 = (s16)
+ ((((s32)((s8)v_data_u8[SMI130_ACCEL_Y_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (v_data_u8[SMI130_ACCEL_Y_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads accelerometer data Z values
+ * form the register 0x16 and 0x17
+ *
+ *
+ *
+ *
+ * @param v_accel_z_s16 : The value of accel z
+ *
+ * @note For accel configuration use the following functions
+ * @note smi130_set_accel_output_data_rate()
+ * @note smi130_set_accel_bw()
+ * @note smi130_set_accel_under_sampling_parameter()
+ * @note smi130_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_accel_z(s16 *v_accel_z_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the accel Z lSB and MSB data
+ a_data_u8r[LSB_ZERO] - LSB
+ a_data_u8r[MSB_ONE] - MSB*/
+ u8 a_data_u8r[SMI130_ACCEL_Z_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_18_ACCEL_Z_LSB__REG,
+ a_data_u8r, SMI130_ACCEL_DATA_LENGTH);
+
+ *v_accel_z_s16 = (s16)
+ ((((s32)((s8)a_data_u8r[SMI130_ACCEL_Z_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[SMI130_ACCEL_Z_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads accelerometer data X,Y,Z values
+ * from the register 0x12 to 0x17
+ *
+ *
+ *
+ *
+ * @param accel :The value of accel xyz
+ *
+ * @note For accel configuration use the following functions
+ * @note smi130_set_accel_output_data_rate()
+ * @note smi130_set_accel_bw()
+ * @note smi130_set_accel_under_sampling_parameter()
+ * @note smi130_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_accel_xyz(
+struct smi130_accel_t *accel)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the accel XYZ lSB and MSB data
+ a_data_u8r[0] - X-LSB
+ a_data_u8r[1] - X-MSB
+ a_data_u8r[0] - Y-LSB
+ a_data_u8r[1] - Y-MSB
+ a_data_u8r[0] - Z-LSB
+ a_data_u8r[1] - Z-MSB
+ */
+ u8 a_data_u8r[SMI130_ACCEL_XYZ_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_14_ACCEL_X_LSB__REG,
+ a_data_u8r, SMI130_ACCEL_XYZ_DATA_LENGTH);
+
+ /* Data X */
+ accel->x = (s16)
+ ((((s32)((s8)a_data_u8r[
+ SMI130_DATA_FRAME_ACCEL_X_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[SMI130_DATA_FRAME_ACCEL_X_LSB_BYTE]));
+ /* Data Y */
+ accel->y = (s16)
+ ((((s32)((s8)a_data_u8r[
+ SMI130_DATA_FRAME_ACCEL_Y_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[SMI130_DATA_FRAME_ACCEL_Y_LSB_BYTE]));
+
+ /* Data Z */
+ accel->z = (s16)
+ ((((s32)((s8)a_data_u8r[
+ SMI130_DATA_FRAME_ACCEL_Z_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[SMI130_DATA_FRAME_ACCEL_Z_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads sensor_time from the register
+ * 0x18 to 0x1A
+ *
+ *
+ * @param v_sensor_time_u32 : The value of sensor time
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_sensor_time(u32 *v_sensor_time_u32)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the sensor time it is 32 bit data
+ a_data_u8r[0] - sensor time
+ a_data_u8r[1] - sensor time
+ a_data_u8r[0] - sensor time
+ */
+ u8 a_data_u8r[SMI130_SENSOR_TIME_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_SENSORTIME_0_SENSOR_TIME_LSB__REG,
+ a_data_u8r, SMI130_SENSOR_TIME_LENGTH);
+
+ *v_sensor_time_u32 = (u32)
+ ((((u32)a_data_u8r[SMI130_SENSOR_TIME_MSB_BYTE])
+ << SMI130_SHIFT_BIT_POSITION_BY_16_BITS)
+ |(((u32)a_data_u8r[SMI130_SENSOR_TIME_XLSB_BYTE])
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[SMI130_SENSOR_TIME_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the Gyroscope self test
+ * status from the register 0x1B bit 1
+ *
+ *
+ * @param v_gyro_selftest_u8 : The value of gyro self test status
+ * value | status
+ * ---------|----------------
+ * 0 | Gyroscope self test is running or failed
+ * 1 | Gyroscope self test completed successfully
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_selftest(u8
+*v_gyro_selftest_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STAT_GYRO_SELFTEST_OK__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_selftest_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_STAT_GYRO_SELFTEST_OK);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of
+ * mag manual interface operation form the register 0x1B bit 2
+ *
+ *
+ *
+ * @param v_mag_manual_stat_u8 : The value of mag manual operation status
+ * value | status
+ * ---------|----------------
+ * 0 | Indicates no manual magnetometer
+ * - | interface operation is ongoing
+ * 1 | Indicates manual magnetometer
+ * - | interface operation is ongoing
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_manual_operation_stat(u8
+*v_mag_manual_stat_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read manual operation*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STAT_MAG_MANUAL_OPERATION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_manual_stat_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_STAT_MAG_MANUAL_OPERATION);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the fast offset compensation
+ * status form the register 0x1B bit 3
+ *
+ *
+ * @param v_foc_rdy_u8 : The status of fast compensation
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_rdy(u8
+*v_foc_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the FOC status*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STAT_FOC_RDY__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_rdy_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_STAT_FOC_RDY);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API Reads the nvm_rdy status from the
+ * resister 0x1B bit 4
+ *
+ *
+ * @param v_nvm_rdy_u8 : The value of NVM ready status
+ * value | status
+ * ---------|----------------
+ * 0 | NVM write operation in progress
+ * 1 | NVM is ready to accept a new write trigger
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_nvm_rdy(u8
+*v_nvm_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the nvm ready status*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STAT_NVM_RDY__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_nvm_rdy_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_STAT_NVM_RDY);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of mag data ready
+ * from the register 0x1B bit 5
+ * The status get reset when one mag data register is read out
+ *
+ * @param v_data_rdy_u8 : The value of mag data ready status
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_data_rdy_mag(u8
+*v_data_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STAT_DATA_RDY_MAG__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_data_rdy_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_STAT_DATA_RDY_MAG);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of gyro data ready form the
+ * register 0x1B bit 6
+ * The status get reset when gyro data register read out
+ *
+ *
+ * @param v_data_rdy_u8 : The value of gyro data ready
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_data_rdy(u8
+*v_data_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STAT_DATA_RDY_GYRO__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_data_rdy_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_STAT_DATA_RDY_GYRO);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of accel data ready form the
+ * register 0x1B bit 7
+ * The status get reset when accel data register read out
+ *
+ *
+ * @param v_data_rdy_u8 : The value of accel data ready status
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_data_rdy(u8
+*v_data_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /*reads the status of accel data ready*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STAT_DATA_RDY_ACCEL__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_data_rdy_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_STAT_DATA_RDY_ACCEL);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the step detector interrupt status
+ * from the register 0x1C bit 0
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The status of step detector interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_step_intr(u8
+*v_step_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_0_STEP_INTR__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_step_intr_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_0_STEP_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the
+ * significant motion interrupt status
+ * from the register 0x1C bit 1
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ *
+ * @param v_significant_intr_u8 : The status of step
+ * motion interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_significant_intr(u8
+*v_significant_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_0_SIGNIFICANT_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_significant_intr_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_0_SIGNIFICANT_INTR);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API reads the any motion interrupt status
+ * from the register 0x1C bit 2
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ * @param v_any_motion_intr_u8 : The status of any-motion interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_any_motion_intr(u8
+*v_any_motion_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_0_ANY_MOTION__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_intr_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_0_ANY_MOTION);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the power mode trigger interrupt status
+ * from the register 0x1C bit 3
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ *
+ * @param v_pmu_trigger_intr_u8 : The status of power mode trigger interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_pmu_trigger_intr(u8
+*v_pmu_trigger_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_0_PMU_TRIGGER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_pmu_trigger_intr_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_0_PMU_TRIGGER);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the double tab status
+ * from the register 0x1C bit 4
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_double_tap_intr_u8 :The status of double tab interrupt
+ *
+ * @note Double tap interrupt can be configured by the following functions
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_double_tap()
+ * @note AXIS MAPPING
+ * @note smi130_get_stat2_tap_first_x()
+ * @note smi130_get_stat2_tap_first_y()
+ * @note smi130_get_stat2_tap_first_z()
+ * @note DURATION
+ * @note smi130_set_intr_tap_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_tap_thres()
+ * @note TAP QUIET
+ * @note smi130_set_intr_tap_quiet()
+ * @note TAP SHOCK
+ * @note smi130_set_intr_tap_shock()
+ * @note TAP SOURCE
+ * @note smi130_set_intr_tap_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_double_tap_intr(u8
+*v_double_tap_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_0_DOUBLE_TAP_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_double_tap_intr_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_0_DOUBLE_TAP_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the single tab status
+ * from the register 0x1C bit 5
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_single_tap_intr_u8 :The status of single tap interrupt
+ *
+ * @note Single tap interrupt can be configured by the following functions
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_single_tap()
+ * @note AXIS MAPPING
+ * @note smi130_get_stat2_tap_first_x()
+ * @note smi130_get_stat2_tap_first_y()
+ * @note smi130_get_stat2_tap_first_z()
+ * @note DURATION
+ * @note smi130_set_intr_tap_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_tap_thres()
+ * @note TAP QUIET
+ * @note smi130_set_intr_tap_quiet()
+ * @note TAP SHOCK
+ * @note smi130_set_intr_tap_shock()
+ * @note TAP SOURCE
+ * @note smi130_set_intr_tap_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_single_tap_intr(u8
+*v_single_tap_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_0_SINGLE_TAP_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_single_tap_intr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_0_SINGLE_TAP_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the orient_mbl status
+ * from the register 0x1C bit 6
+ * flag is associated with a specific interrupt function.
+ * It is set when the orient_mbl interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_orient_mbl_intr_u8 : The status of orient_mbl interrupt
+ *
+ * @note For orient_mbl interrupt configuration use the following functions
+ * @note STATUS
+ * @note smi130_get_stat0_orient_mbl_intr()
+ * @note AXIS MAPPING
+ * @note smi130_get_stat3_orient_mbl_xy()
+ * @note smi130_get_stat3_orient_mbl_z()
+ * @note smi130_set_intr_orient_mbl_axes_enable()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_orient_mbl()
+ * @note INTERRUPT OUTPUT
+ * @note smi130_set_intr_orient_mbl_ud_enable()
+ * @note THETA
+ * @note smi130_set_intr_orient_mbl_theta()
+ * @note HYSTERESIS
+ * @note smi130_set_intr_orient_mbl_hyst()
+ * @note BLOCKING
+ * @note smi130_set_intr_orient_mbl_blocking()
+ * @note MODE
+ * @note smi130_set_intr_orient_mbl_mode()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_orient_mbl_intr(u8
+*v_orient_mbl_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_0_ORIENT__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mbl_intr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_0_ORIENT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the flat interrupt status
+ * from the register 0x1C bit 7
+ * flag is associated with a specific interrupt function.
+ * It is set when the flat interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_flat_intr_u8 : The status of flat interrupt
+ *
+ * @note For flat configuration use the following functions
+ * @note STATS
+ * @note smi130_get_stat0_flat_intr()
+ * @note smi130_get_stat3_flat()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_flat()
+ * @note THETA
+ * @note smi130_set_intr_flat_theta()
+ * @note HOLD TIME
+ * @note smi130_set_intr_flat_hold()
+ * @note HYSTERESIS
+ * @note smi130_set_intr_flat_hyst()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_flat_intr(u8
+*v_flat_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_0_FLAT__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_intr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_0_FLAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high_g interrupt status
+ * from the register 0x1D bit 2
+ * flag is associated with a specific interrupt function.
+ * It is set when the high g interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be permanently
+ * latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_high_g_intr_u8 : The status of high_g interrupt
+ *
+ * @note High_g interrupt configured by following functions
+ * @note STATUS
+ * @note smi130_get_stat1_high_g_intr()
+ * @note AXIS MAPPING
+ * @note smi130_get_stat3_high_g_first_x()
+ * @note smi130_get_stat3_high_g_first_y()
+ * @note smi130_get_stat3_high_g_first_z()
+ * @note SIGN MAPPING
+ * @note smi130_get_stat3_high_g_first_sign()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_high_g()
+ * @note HYSTERESIS
+ * @note smi130_set_intr_high_g_hyst()
+ * @note DURATION
+ * @note smi130_set_intr_high_g_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_high_g_thres()
+ * @note SOURCE
+ * @note smi130_set_intr_low_high_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_high_g_intr(u8
+*v_high_g_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_1_HIGH_G_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_intr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_1_HIGH_G_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the low g interrupt status
+ * from the register 0x1D bit 3
+ * flag is associated with a specific interrupt function.
+ * It is set when the low g interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_low_g_intr_u8 : The status of low_g interrupt
+ *
+ * @note Low_g interrupt configured by following functions
+ * @note STATUS
+ * @note smi130_get_stat1_low_g_intr()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_low_g()
+ * @note SOURCE
+ * @note smi130_set_intr_low_high_source()
+ * @note DURATION
+ * @note smi130_set_intr_low_g_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_low_g_thres()
+ * @note HYSTERESIS
+ * @note smi130_set_intr_low_g_hyst()
+ * @note MODE
+ * @note smi130_set_intr_low_g_mode()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_low_g_intr(u8
+*v_low_g_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_1_LOW_G_INTR__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_g_intr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_1_LOW_G_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads data ready interrupt status
+ * from the register 0x1D bit 4
+ * flag is associated with a specific interrupt function.
+ * It is set when the data ready interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_data_rdy_intr_u8 : The status of data ready interrupt
+ *
+ * @note Data ready interrupt configured by following functions
+ * @note STATUS
+ * @note smi130_get_stat1_data_rdy_intr()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_data_rdy()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_data_rdy_intr(u8
+*v_data_rdy_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_1_DATA_RDY_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_data_rdy_intr_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_1_DATA_RDY_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads data ready FIFO full interrupt status
+ * from the register 0x1D bit 5
+ * flag is associated with a specific interrupt function.
+ * It is set when the FIFO full interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will
+ * be permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_fifo_full_intr_u8 : The status of fifo full interrupt
+ *
+ * @note FIFO full interrupt can be configured by following functions
+ * @note smi130_set_intr_fifo_full()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_fifo_full_intr(u8
+*v_fifo_full_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_1_FIFO_FULL_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_full_intr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_1_FIFO_FULL_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads data
+ * ready FIFO watermark interrupt status
+ * from the register 0x1D bit 6
+ * flag is associated with a specific interrupt function.
+ * It is set when the FIFO watermark interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_fifo_wm_intr_u8 : The status of fifo water mark interrupt
+ *
+ * @note FIFO full interrupt can be configured by following functions
+ * @note smi130_set_intr_fifo_wm()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_fifo_wm_intr(u8
+*v_fifo_wm_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_1_FIFO_WM_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_wm_intr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_1_FIFO_WM_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads data ready no motion interrupt status
+ * from the register 0x1D bit 7
+ * flag is associated with a specific interrupt function.
+ * It is set when the no motion interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be permanently
+ * latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_nomotion_intr_u8 : The status of no motion interrupt
+ *
+ * @note No motion interrupt can be configured by following function
+ * @note STATUS
+ * @note smi130_get_stat1_nomotion_intr()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_nomotion()
+ * @note DURATION
+ * @note smi130_set_intr_slow_no_motion_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_slow_no_motion_thres()
+ * @note SLOW/NO MOTION SELECT
+ * @note smi130_set_intr_slow_no_motion_select()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_nomotion_intr(u8
+*v_nomotion_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the no motion interrupt*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_1_NOMOTION_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_nomotion_intr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_1_NOMOTION_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ *@brief This API reads the status of any motion first x
+ * from the register 0x1E bit 0
+ *
+ *
+ *@param v_anymotion_first_x_u8 : The status of any motion first x interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_any_motion_first_x(u8
+*v_anymotion_first_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the any motion first x interrupt*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_anymotion_first_x_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of any motion first y interrupt
+ * from the register 0x1E bit 1
+ *
+ *
+ *
+ *@param v_any_motion_first_y_u8 : The status of any motion first y interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_any_motion_first_y(u8
+*v_any_motion_first_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the any motion first y interrupt*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_first_y_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of any motion first z interrupt
+ * from the register 0x1E bit 2
+ *
+ *
+ *
+ *
+ *@param v_any_motion_first_z_u8 : The status of any motion first z interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_any_motion_first_z(u8
+*v_any_motion_first_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the any motion first z interrupt*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_first_z_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the any motion sign status from the
+ * register 0x1E bit 3
+ *
+ *
+ *
+ *
+ * @param v_anymotion_sign_u8 : The status of any motion sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_any_motion_sign(u8
+*v_anymotion_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read any motion sign interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_SIGN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_anymotion_sign_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_SIGN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the any motion tap first x status from the
+ * register 0x1E bit 4
+ *
+ *
+ *
+ *
+ * @param v_tap_first_x_u8 :The status of any motion tap first x
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_tap_first_x(u8
+*v_tap_first_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read tap first x interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_2_TAP_FIRST_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_first_x_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_2_TAP_FIRST_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the tap first y interrupt status from the
+ * register 0x1E bit 5
+ *
+ *
+ *
+ *
+ * @param v_tap_first_y_u8 :The status of tap first y interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_tap_first_y(u8
+*v_tap_first_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read tap first y interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_2_TAP_FIRST_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_first_y_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_2_TAP_FIRST_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the tap first z interrupt status from the
+ * register 0x1E bit 6
+ *
+ *
+ *
+ *
+ * @param v_tap_first_z_u8 :The status of tap first z interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_tap_first_z(u8
+*v_tap_first_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read tap first z interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_2_TAP_FIRST_Z__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_first_z_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_2_TAP_FIRST_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the tap sign status from the
+ * register 0x1E bit 7
+ *
+ *
+ *
+ *
+ * @param v_tap_sign_u8 : The status of tap sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_tap_sign(u8
+*v_tap_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read tap_sign interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_2_TAP_SIGN__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_sign_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_2_TAP_SIGN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high_g first x status from the
+ * register 0x1F bit 0
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_x_u8 :The status of high_g first x
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_high_g_first_x(u8
+*v_high_g_first_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read highg_x interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_first_x_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high_g first y status from the
+ * register 0x1F bit 1
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_y_u8 : The status of high_g first y
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_high_g_first_y(u8
+*v_high_g_first_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read highg_y interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_first_y_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high_g first z status from the
+ * register 0x1F bit 3
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_z_u8 : The status of high_g first z
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_high_g_first_z(u8
+*v_high_g_first_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read highg_z interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Z__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_first_z_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the high sign status from the
+ * register 0x1F bit 3
+ *
+ *
+ *
+ *
+ * @param v_high_g_sign_u8 :The status of high sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_high_g_sign(u8
+*v_high_g_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read highg_sign interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_3_HIGH_G_SIGN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_sign_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_3_HIGH_G_SIGN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of orient_mbl_xy plane
+ * from the register 0x1F bit 4 and 5
+ *
+ *
+ * @param v_orient_mbl_xy_u8 :The status of orient_mbl_xy plane
+ * value | status
+ * -----------|-------------
+ * 0x00 | portrait upright
+ * 0x01 | portrait upside down
+ * 0x02 | landscape left
+ * 0x03 | landscape right
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_orient_mbl_xy(u8
+*v_orient_mbl_xy_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read orient_mbl plane xy interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_3_ORIENT_XY__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mbl_xy_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_3_ORIENT_XY);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the status of orient_mbl z plane
+ * from the register 0x1F bit 6
+ *
+ *
+ * @param v_orient_mbl_z_u8 :The status of orient_mbl z
+ * value | status
+ * -----------|-------------
+ * 0x00 | upward looking
+ * 0x01 | downward looking
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_orient_mbl_z(u8
+*v_orient_mbl_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read orient_mbl z plane interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_3_ORIENT_Z__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mbl_z_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_3_ORIENT_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the flat status from the register
+ * 0x1F bit 7
+ *
+ *
+ * @param v_flat_u8 : The status of flat interrupt
+ * value | status
+ * -----------|-------------
+ * 0x00 | non flat
+ * 0x01 | flat position
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_flat(u8
+*v_flat_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read flat interrupt status */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_INTR_STAT_3_FLAT__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_STAT_3_FLAT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the temperature of the sensor
+ * from the register 0x21 bit 0 to 7
+ *
+ *
+ *
+ * @param v_temp_s16 : The value of temperature
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_temp(s16
+*v_temp_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the temperature lSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 v_data_u8[SMI130_TEMP_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read temperature data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_TEMP_LSB_VALUE__REG, v_data_u8,
+ SMI130_TEMP_DATA_LENGTH);
+ *v_temp_s16 =
+ (s16)(((s32)((s8) (v_data_u8[SMI130_TEMP_MSB_BYTE]) <<
+ SMI130_SHIFT_BIT_POSITION_BY_08_BITS))
+ | v_data_u8[SMI130_TEMP_LSB_BYTE]);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the of the sensor
+ * form the register 0x23 and 0x24 bit 0 to 7 and 0 to 2
+ * @brief this byte counter is updated each time a complete frame
+ * was read or writtern
+ *
+ *
+ * @param v_fifo_length_u32 : The value of fifo byte counter
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_fifo_length(u32 *v_fifo_length_u32)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array contains the fifo length data
+ v_data_u8[0] - fifo length
+ v_data_u8[1] - fifo length*/
+ u8 a_data_u8r[SMI130_FIFO_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read fifo length*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_BYTE_COUNTER_LSB__REG, a_data_u8r,
+ SMI130_FIFO_DATA_LENGTH);
+
+ a_data_u8r[SMI130_FIFO_LENGTH_MSB_BYTE] =
+ SMI130_GET_BITSLICE(
+ a_data_u8r[SMI130_FIFO_LENGTH_MSB_BYTE],
+ SMI130_USER_FIFO_BYTE_COUNTER_MSB);
+
+ *v_fifo_length_u32 =
+ (u32)(((u32)((u8) (
+ a_data_u8r[SMI130_FIFO_LENGTH_MSB_BYTE]) <<
+ SMI130_SHIFT_BIT_POSITION_BY_08_BITS))
+ | a_data_u8r[SMI130_FIFO_LENGTH_LSB_BYTE]);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the fifo data of the sensor
+ * from the register 0x24
+ * @brief Data format depends on the setting of register FIFO_CONFIG
+ *
+ *
+ *
+ * @param v_fifodata_u8 : Pointer holding the fifo data
+ * @param fifo_length_u16 : The value of fifo length maximum
+ * 1024
+ *
+ * @note For reading FIFO data use the following functions
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_fifo_data(
+u8 *v_fifodata_u8, u16 v_fifo_length_u16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read fifo data*/
+ com_rslt =
+ p_smi130->SMI130_BURST_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_DATA__REG,
+ v_fifodata_u8, v_fifo_length_u16);
+
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * accel output date rate form the register 0x40 bit 0 to 3
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of accel output date rate
+ * value | output data rate
+ * -------|--------------------------
+ * 0 | SMI130_ACCEL_OUTPUT_DATA_RATE_RESERVED
+ * 1 | SMI130_ACCEL_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | SMI130_ACCEL_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | SMI130_ACCEL_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | SMI130_ACCEL_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | SMI130_ACCEL_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | SMI130_ACCEL_OUTPUT_DATA_RATE_25HZ
+ * 7 | SMI130_ACCEL_OUTPUT_DATA_RATE_50HZ
+ * 8 | SMI130_ACCEL_OUTPUT_DATA_RATE_100HZ
+ * 9 | SMI130_ACCEL_OUTPUT_DATA_RATE_200HZ
+ * 10 | SMI130_ACCEL_OUTPUT_DATA_RATE_400HZ
+ * 11 | SMI130_ACCEL_OUTPUT_DATA_RATE_800HZ
+ * 12 | SMI130_ACCEL_OUTPUT_DATA_RATE_1600HZ
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_output_data_rate(
+u8 *v_output_data_rate_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel output data rate*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_data_rate_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * accel output date rate form the register 0x40 bit 0 to 3
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of accel output date rate
+ * value | output data rate
+ * -------|--------------------------
+ * 0 | SMI130_ACCEL_OUTPUT_DATA_RATE_RESERVED
+ * 1 | SMI130_ACCEL_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | SMI130_ACCEL_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | SMI130_ACCEL_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | SMI130_ACCEL_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | SMI130_ACCEL_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | SMI130_ACCEL_OUTPUT_DATA_RATE_25HZ
+ * 7 | SMI130_ACCEL_OUTPUT_DATA_RATE_50HZ
+ * 8 | SMI130_ACCEL_OUTPUT_DATA_RATE_100HZ
+ * 9 | SMI130_ACCEL_OUTPUT_DATA_RATE_200HZ
+ * 10 | SMI130_ACCEL_OUTPUT_DATA_RATE_400HZ
+ * 11 | SMI130_ACCEL_OUTPUT_DATA_RATE_800HZ
+ * 12 | SMI130_ACCEL_OUTPUT_DATA_RATE_1600HZ
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_output_data_rate(
+u8 v_output_data_rate_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* accel output data rate selection */
+ if ((v_output_data_rate_u8 != SMI130_INIT_VALUE) &&
+ (v_output_data_rate_u8 <= SMI130_MAX_ACCEL_OUTPUT_DATA_RATE)) {
+ /* write accel output data rate */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE,
+ v_output_data_rate_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * accel bandwidth from the register 0x40 bit 4 to 6
+ * @brief bandwidth parameter determines filter configuration(acc_us=0)
+ * and averaging for under sampling mode(acc_us=1)
+ *
+ *
+ * @param v_bw_u8 : The value of accel bandwidth
+ *
+ * @note accel bandwidth depends on under sampling parameter
+ * @note under sampling parameter cab be set by the function
+ * "SMI130_SET_ACCEL_UNDER_SAMPLING_PARAMETER"
+ *
+ * @note Filter configuration
+ * accel_us | Filter configuration
+ * -----------|---------------------
+ * 0x00 | OSR4 mode
+ * 0x01 | OSR2 mode
+ * 0x02 | normal mode
+ * 0x03 | CIC mode
+ * 0x04 | Reserved
+ * 0x05 | Reserved
+ * 0x06 | Reserved
+ * 0x07 | Reserved
+ *
+ * @note accel under sampling mode
+ * accel_us | Under sampling mode
+ * -----------|---------------------
+ * 0x00 | no averaging
+ * 0x01 | average 2 samples
+ * 0x02 | average 4 samples
+ * 0x03 | average 8 samples
+ * 0x04 | average 16 samples
+ * 0x05 | average 32 samples
+ * 0x06 | average 64 samples
+ * 0x07 | average 128 samples
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_bw(u8 *v_bw_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel bandwidth */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_BW__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_bw_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_BW);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * accel bandwidth from the register 0x40 bit 4 to 6
+ * @brief bandwidth parameter determines filter configuration(acc_us=0)
+ * and averaging for under sampling mode(acc_us=1)
+ *
+ *
+ * @param v_bw_u8 : The value of accel bandwidth
+ *
+ * @note accel bandwidth depends on under sampling parameter
+ * @note under sampling parameter cab be set by the function
+ * "SMI130_SET_ACCEL_UNDER_SAMPLING_PARAMETER"
+ *
+ * @note Filter configuration
+ * accel_us | Filter configuration
+ * -----------|---------------------
+ * 0x00 | OSR4 mode
+ * 0x01 | OSR2 mode
+ * 0x02 | normal mode
+ * 0x03 | CIC mode
+ * 0x04 | Reserved
+ * 0x05 | Reserved
+ * 0x06 | Reserved
+ * 0x07 | Reserved
+ *
+ * @note accel under sampling mode
+ * accel_us | Under sampling mode
+ * -----------|---------------------
+ * 0x00 | no averaging
+ * 0x01 | average 2 samples
+ * 0x02 | average 4 samples
+ * 0x03 | average 8 samples
+ * 0x04 | average 16 samples
+ * 0x05 | average 32 samples
+ * 0x06 | average 64 samples
+ * 0x07 | average 128 samples
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_bw(u8 v_bw_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* select accel bandwidth*/
+ if (v_bw_u8 <= SMI130_MAX_ACCEL_BW) {
+ /* write accel bandwidth*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_BW__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_BW,
+ v_bw_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_BW__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the accel
+ * under sampling parameter form the register 0x40 bit 7
+ *
+ *
+ *
+ *
+ * @param v_accel_under_sampling_u8 : The value of accel under sampling
+ * value | under_sampling
+ * ----------|---------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_under_sampling_parameter(
+u8 *v_accel_under_sampling_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel under sampling parameter */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_under_sampling_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the accel
+ * under sampling parameter form the register 0x40 bit 7
+ *
+ *
+ *
+ *
+ * @param v_accel_under_sampling_u8 : The value of accel under sampling
+ * value | under_sampling
+ * ----------|---------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_under_sampling_parameter(
+u8 v_accel_under_sampling_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_accel_under_sampling_u8 <= SMI130_MAX_UNDER_SAMPLING) {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ /* write the accel under sampling parameter */
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING,
+ v_accel_under_sampling_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API is used to get the ranges
+ * (g values) of the accel from the register 0x41 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_range_u8 : The value of accel g range
+ * value | g_range
+ * ----------|-----------
+ * 0x03 | SMI130_ACCEL_RANGE_2G
+ * 0x05 | SMI130_ACCEL_RANGE_4G
+ * 0x08 | SMI130_ACCEL_RANGE_8G
+ * 0x0C | SMI130_ACCEL_RANGE_16G
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_range(
+u8 *v_range_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel range*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ACCEL_RANGE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_range_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_RANGE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the ranges
+ * (g values) of the accel from the register 0x41 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_range_u8 : The value of accel g range
+ * value | g_range
+ * ----------|-----------
+ * 0x03 | SMI130_ACCEL_RANGE_2G
+ * 0x05 | SMI130_ACCEL_RANGE_4G
+ * 0x08 | SMI130_ACCEL_RANGE_8G
+ * 0x0C | SMI130_ACCEL_RANGE_16G
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_range(u8 v_range_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if ((v_range_u8 == SMI130_ACCEL_RANGE0) ||
+ (v_range_u8 == SMI130_ACCEL_RANGE1) ||
+ (v_range_u8 == SMI130_ACCEL_RANGE3) ||
+ (v_range_u8 == SMI130_ACCEL_RANGE4)) {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_ACCEL_RANGE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(
+ v_data_u8, SMI130_USER_ACCEL_RANGE,
+ v_range_u8);
+ /* write the accel range*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_RANGE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * gyroscope output data rate from the register 0x42 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of gyro output data rate
+ * value | gyro output data rate
+ * -----------|-----------------------------
+ * 0x00 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x02 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x03 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x04 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x05 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x06 | SMI130_GYRO_OUTPUT_DATA_RATE_25HZ
+ * 0x07 | SMI130_GYRO_OUTPUT_DATA_RATE_50HZ
+ * 0x08 | SMI130_GYRO_OUTPUT_DATA_RATE_100HZ
+ * 0x09 | SMI130_GYRO_OUTPUT_DATA_RATE_200HZ
+ * 0x0A | SMI130_GYRO_OUTPUT_DATA_RATE_400HZ
+ * 0x0B | SMI130_GYRO_OUTPUT_DATA_RATE_800HZ
+ * 0x0C | SMI130_GYRO_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D | SMI130_GYRO_OUTPUT_DATA_RATE_3200HZ
+ * 0x0E | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x0F | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_output_data_rate(
+u8 *v_output_data_rate_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the gyro output data rate*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_data_rate_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_CONFIG_OUTPUT_DATA_RATE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * gyroscope output data rate from the register 0x42 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of gyro output data rate
+ * value | gyro output data rate
+ * -----------|-----------------------------
+ * 0x00 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x02 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x03 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x04 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x05 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x06 | SMI130_GYRO_OUTPUT_DATA_RATE_25HZ
+ * 0x07 | SMI130_GYRO_OUTPUT_DATA_RATE_50HZ
+ * 0x08 | SMI130_GYRO_OUTPUT_DATA_RATE_100HZ
+ * 0x09 | SMI130_GYRO_OUTPUT_DATA_RATE_200HZ
+ * 0x0A | SMI130_GYRO_OUTPUT_DATA_RATE_400HZ
+ * 0x0B | SMI130_GYRO_OUTPUT_DATA_RATE_800HZ
+ * 0x0C | SMI130_GYRO_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D | SMI130_GYRO_OUTPUT_DATA_RATE_3200HZ
+ * 0x0E | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x0F | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_output_data_rate(
+u8 v_output_data_rate_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* select the gyro output data rate*/
+ if ((v_output_data_rate_u8 < SMI130_OUTPUT_DATA_RATE6) &&
+ (v_output_data_rate_u8 != SMI130_INIT_VALUE)
+ && (v_output_data_rate_u8 != SMI130_OUTPUT_DATA_RATE1)
+ && (v_output_data_rate_u8 != SMI130_OUTPUT_DATA_RATE2)
+ && (v_output_data_rate_u8 != SMI130_OUTPUT_DATA_RATE3)
+ && (v_output_data_rate_u8 != SMI130_OUTPUT_DATA_RATE4)
+ && (v_output_data_rate_u8 != SMI130_OUTPUT_DATA_RATE5)
+ && (v_output_data_rate_u8 != SMI130_OUTPUT_DATA_RATE6)
+ && (v_output_data_rate_u8 != SMI130_OUTPUT_DATA_RATE7)) {
+ /* write the gyro output data rate */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_CONFIG_OUTPUT_DATA_RATE,
+ v_output_data_rate_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * data of gyro from the register 0x42 bit 4 to 5
+ *
+ *
+ *
+ *
+ * @param v_bw_u8 : The value of gyro bandwidth
+ * value | gyro bandwidth
+ * ----------|----------------
+ * 0x00 | SMI130_GYRO_OSR4_MODE
+ * 0x01 | SMI130_GYRO_OSR2_MODE
+ * 0x02 | SMI130_GYRO_NORMAL_MODE
+ * 0x03 | SMI130_GYRO_CIC_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_bw(u8 *v_bw_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro bandwidth*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_GYRO_CONFIG_BW__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_bw_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_CONFIG_BW);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * data of gyro from the register 0x42 bit 4 to 5
+ *
+ *
+ *
+ *
+ * @param v_bw_u8 : The value of gyro bandwidth
+ * value | gyro bandwidth
+ * ----------|----------------
+ * 0x00 | SMI130_GYRO_OSR4_MODE
+ * 0x01 | SMI130_GYRO_OSR2_MODE
+ * 0x02 | SMI130_GYRO_NORMAL_MODE
+ * 0x03 | SMI130_GYRO_CIC_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_bw(u8 v_bw_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_bw_u8 <= SMI130_MAX_GYRO_BW) {
+ /* write the gyro bandwidth*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_GYRO_CONFIG_BW__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_CONFIG_BW, v_bw_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_CONFIG_BW__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads the range
+ * of gyro from the register 0x43 bit 0 to 2
+ *
+ * @param v_range_u8 : The value of gyro range
+ * value | range
+ * ----------|-------------------------------
+ * 0x00 | SMI130_GYRO_RANGE_2000_DEG_SEC
+ * 0x01 | SMI130_GYRO_RANGE_1000_DEG_SEC
+ * 0x02 | SMI130_GYRO_RANGE_500_DEG_SEC
+ * 0x03 | SMI130_GYRO_RANGE_250_DEG_SEC
+ * 0x04 | SMI130_GYRO_RANGE_125_DEG_SEC
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_range(u8 *v_range_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the gyro range */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_GYRO_RANGE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_range_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_RANGE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set the range
+ * of gyro from the register 0x43 bit 0 to 2
+ *
+ * @param v_range_u8 : The value of gyro range
+ * value | range
+ * ----------|-------------------------------
+ * 0x00 | SMI130_GYRO_RANGE_2000_DEG_SEC
+ * 0x01 | SMI130_GYRO_RANGE_1000_DEG_SEC
+ * 0x02 | SMI130_GYRO_RANGE_500_DEG_SEC
+ * 0x03 | SMI130_GYRO_RANGE_250_DEG_SEC
+ * 0x04 | SMI130_GYRO_RANGE_125_DEG_SEC
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_range(u8 v_range_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_range_u8 <= SMI130_MAX_GYRO_RANGE) {
+ /* write the gyro range value */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_GYRO_RANGE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_RANGE,
+ v_range_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_GYRO_RANGE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the
+ * output data rate of magnetometer from the register 0x44 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rat_u8e : The value of mag output data rate
+ * value | mag output data rate
+ * ---------|---------------------------
+ * 0x00 |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 |SMI130_MAG_OUTPUT_DATA_RATE_0_78HZ
+ * 0x02 |SMI130_MAG_OUTPUT_DATA_RATE_1_56HZ
+ * 0x03 |SMI130_MAG_OUTPUT_DATA_RATE_3_12HZ
+ * 0x04 |SMI130_MAG_OUTPUT_DATA_RATE_6_25HZ
+ * 0x05 |SMI130_MAG_OUTPUT_DATA_RATE_12_5HZ
+ * 0x06 |SMI130_MAG_OUTPUT_DATA_RATE_25HZ
+ * 0x07 |SMI130_MAG_OUTPUT_DATA_RATE_50HZ
+ * 0x08 |SMI130_MAG_OUTPUT_DATA_RATE_100HZ
+ * 0x09 |SMI130_MAG_OUTPUT_DATA_RATE_200HZ
+ * 0x0A |SMI130_MAG_OUTPUT_DATA_RATE_400HZ
+ * 0x0B |SMI130_MAG_OUTPUT_DATA_RATE_800HZ
+ * 0x0C |SMI130_MAG_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED0
+ * 0x0E |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED1
+ * 0x0F |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED2
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_output_data_rate(
+u8 *v_output_data_rat_u8e)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the mag data output rate*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_data_rat_u8e = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_CONFIG_OUTPUT_DATA_RATE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set the
+ * output data rate of magnetometer from the register 0x44 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rat_u8e : The value of mag output data rate
+ * value | mag output data rate
+ * ---------|---------------------------
+ * 0x00 |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 |SMI130_MAG_OUTPUT_DATA_RATE_0_78HZ
+ * 0x02 |SMI130_MAG_OUTPUT_DATA_RATE_1_56HZ
+ * 0x03 |SMI130_MAG_OUTPUT_DATA_RATE_3_12HZ
+ * 0x04 |SMI130_MAG_OUTPUT_DATA_RATE_6_25HZ
+ * 0x05 |SMI130_MAG_OUTPUT_DATA_RATE_12_5HZ
+ * 0x06 |SMI130_MAG_OUTPUT_DATA_RATE_25HZ
+ * 0x07 |SMI130_MAG_OUTPUT_DATA_RATE_50HZ
+ * 0x08 |SMI130_MAG_OUTPUT_DATA_RATE_100HZ
+ * 0x09 |SMI130_MAG_OUTPUT_DATA_RATE_200HZ
+ * 0x0A |SMI130_MAG_OUTPUT_DATA_RATE_400HZ
+ * 0x0B |SMI130_MAG_OUTPUT_DATA_RATE_800HZ
+ * 0x0C |SMI130_MAG_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED0
+ * 0x0E |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED1
+ * 0x0F |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED2
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_output_data_rate(
+u8 v_output_data_rat_u8e)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* select the mag data output rate*/
+ if ((v_output_data_rat_u8e
+ <= SMI130_MAX_ACCEL_OUTPUT_DATA_RATE)
+ && (v_output_data_rat_u8e
+ != SMI130_OUTPUT_DATA_RATE0)
+ && (v_output_data_rat_u8e
+ != SMI130_OUTPUT_DATA_RATE6)
+ && (v_output_data_rat_u8e
+ != SMI130_OUTPUT_DATA_RATE7)) {
+ /* write the mag data output rate*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_CONFIG_OUTPUT_DATA_RATE,
+ v_output_data_rat_u8e);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_MAG_CONFIG_OUTPUT_DATA_RATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to read Down sampling
+ * for gyro (2**downs_gyro) in the register 0x45 bit 0 to 2
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_gyro_u8 :The value of gyro fifo down
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_down_gyro(
+u8 *v_fifo_down_gyro_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the gyro fifo down*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_DOWN_GYRO__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_down_gyro_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_DOWN_GYRO);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to set Down sampling
+ * for gyro (2**downs_gyro) in the register 0x45 bit 0 to 2
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_gyro_u8 :The value of gyro fifo down
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_down_gyro(
+u8 v_fifo_down_gyro_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write the gyro fifo down*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_DOWN_GYRO__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_FIFO_DOWN_GYRO,
+ v_fifo_down_gyro_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_DOWN_GYRO__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read gyro fifo filter data
+ * from the register 0x45 bit 3
+ *
+ *
+ *
+ * @param v_gyro_fifo_filter_data_u8 :The value of gyro filter data
+ * value | gyro_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_fifo_filter_data(
+u8 *v_gyro_fifo_filter_data_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the gyro fifo filter data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_FILTER_GYRO__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_fifo_filter_data_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_FILTER_GYRO);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set gyro fifo filter data
+ * from the register 0x45 bit 3
+ *
+ *
+ *
+ * @param v_gyro_fifo_filter_data_u8 :The value of gyro filter data
+ * value | gyro_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_fifo_filter_data(
+u8 v_gyro_fifo_filter_data_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_gyro_fifo_filter_data_u8
+ <= SMI130_MAX_VALUE_FIFO_FILTER) {
+ /* write the gyro fifo filter data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_FILTER_GYRO__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_FIFO_FILTER_GYRO,
+ v_gyro_fifo_filter_data_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_FILTER_GYRO__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read Down sampling
+ * for accel (2*downs_accel) from the register 0x45 bit 4 to 6
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_u8 :The value of accel fifo down
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_down_accel(
+u8 *v_fifo_down_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel fifo down data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_DOWN_ACCEL__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_down_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_DOWN_ACCEL);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to set Down sampling
+ * for accel (2*downs_accel) from the register 0x45 bit 4 to 6
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_u8 :The value of accel fifo down
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_down_accel(
+u8 v_fifo_down_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write the accel fifo down data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_DOWN_ACCEL__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_DOWN_ACCEL, v_fifo_down_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_DOWN_ACCEL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read accel fifo filter data
+ * from the register 0x45 bit 7
+ *
+ *
+ *
+ * @param v_accel_fifo_filter_u8 :The value of accel filter data
+ * value | accel_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_fifo_filter_data(
+u8 *v_accel_fifo_filter_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel fifo filter data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_FILTER_ACCEL__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_fifo_filter_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_FILTER_ACCEL);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set accel fifo filter data
+ * from the register 0x45 bit 7
+ *
+ *
+ *
+ * @param v_accel_fifo_filter_u8 :The value of accel filter data
+ * value | accel_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_fifo_filter_data(
+u8 v_accel_fifo_filter_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_accel_fifo_filter_u8 <= SMI130_MAX_VALUE_FIFO_FILTER) {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_FILTER_ACCEL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ /* write accel fifo filter data */
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_FILTER_ACCEL,
+ v_accel_fifo_filter_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_FILTER_ACCEL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to Trigger an interrupt
+ * when FIFO contains water mark level from the register 0x46 bit 0 to 7
+ *
+ *
+ *
+ * @param v_fifo_wm_u8 : The value of fifo water mark level
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_wm(
+u8 *v_fifo_wm_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the fifo water mark level*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_WM__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_wm_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_WM);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to Trigger an interrupt
+ * when FIFO contains water mark level from the register 0x46 bit 0 to 7
+ *
+ *
+ *
+ * @param v_fifo_wm_u8 : The value of fifo water mark level
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_wm(
+u8 v_fifo_wm_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write the fifo water mark level*/
+ com_rslt =
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_WM__REG,
+ &v_fifo_wm_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads fifo sensor time
+ * frame after the last valid data frame form the register 0x47 bit 1
+ *
+ *
+ *
+ *
+ * @param v_fifo_time_enable_u8 : The value of sensor time
+ * value | fifo sensor time
+ * ------------|-------------------------
+ * 0x00 | do not return sensortime frame
+ * 0x01 | return sensortime frame
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_time_enable(
+u8 *v_fifo_time_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the fifo sensor time*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_TIME_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_time_enable_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_TIME_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set fifo sensor time
+ * frame after the last valid data frame form the register 0x47 bit 1
+ *
+ *
+ *
+ *
+ * @param v_fifo_time_enable_u8 : The value of sensor time
+ * value | fifo sensor time
+ * ------------|-------------------------
+ * 0x00 | do not return sensortime frame
+ * 0x01 | return sensortime frame
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_time_enable(
+u8 v_fifo_time_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_fifo_time_enable_u8 <= SMI130_MAX_VALUE_FIFO_TIME) {
+ /* write the fifo sensor time*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_TIME_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_TIME_ENABLE,
+ v_fifo_time_enable_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_TIME_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads FIFO tag interrupt2 enable status
+ * from the resister 0x47 bit 2
+ *
+ * @param v_fifo_tag_intr2_u8 : The value of fifo tag interrupt
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_tag_intr2_enable(
+u8 *v_fifo_tag_intr2_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the fifo tag interrupt2*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_TAG_INTR2_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_tag_intr2_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_TAG_INTR2_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set FIFO tag interrupt2 enable status
+ * from the resister 0x47 bit 2
+ *
+ * @param v_fifo_tag_intr2_u8 : The value of fifo tag interrupt
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_tag_intr2_enable(
+u8 v_fifo_tag_intr2_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_fifo_tag_intr2_u8 <= SMI130_MAX_VALUE_FIFO_INTR) {
+ /* write the fifo tag interrupt2*/
+ com_rslt = smi130_set_input_enable(1,
+ v_fifo_tag_intr2_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_TAG_INTR2_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_TAG_INTR2_ENABLE,
+ v_fifo_tag_intr2_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_TAG_INTR2_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API get FIFO tag interrupt1 enable status
+ * from the resister 0x47 bit 3
+ *
+ * @param v_fifo_tag_intr1_u8 :The value of fifo tag interrupt1
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_tag_intr1_enable(
+u8 *v_fifo_tag_intr1_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read fifo tag interrupt*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_TAG_INTR1_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_tag_intr1_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_TAG_INTR1_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set FIFO tag interrupt1 enable status
+ * from the resister 0x47 bit 3
+ *
+ * @param v_fifo_tag_intr1_u8 :The value of fifo tag interrupt1
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_tag_intr1_enable(
+u8 v_fifo_tag_intr1_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_fifo_tag_intr1_u8 <= SMI130_MAX_VALUE_FIFO_INTR) {
+ /* write the fifo tag interrupt*/
+ com_rslt = smi130_set_input_enable(SMI130_INIT_VALUE,
+ v_fifo_tag_intr1_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_TAG_INTR1_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_TAG_INTR1_ENABLE,
+ v_fifo_tag_intr1_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_TAG_INTR1_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads FIFO frame
+ * header enable from the register 0x47 bit 4
+ *
+ * @param v_fifo_header_u8 :The value of fifo header
+ * value | fifo header
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_header_enable(
+u8 *v_fifo_header_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read fifo header */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_HEADER_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_header_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_HEADER_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API set FIFO frame
+ * header enable from the register 0x47 bit 4
+ *
+ * @param v_fifo_header_u8 :The value of fifo header
+ * value | fifo header
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_header_enable(
+u8 v_fifo_header_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_fifo_header_u8 <= SMI130_MAX_VALUE_FIFO_HEADER) {
+ /* write the fifo header */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_HEADER_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_HEADER_ENABLE,
+ v_fifo_header_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_HEADER_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read stored
+ * magnetometer data in FIFO (all 3 axes) from the register 0x47 bit 5
+ *
+ * @param v_fifo_mag_u8 : The value of fifo mag enble
+ * value | fifo mag
+ * ----------|-------------------
+ * 0x00 | no magnetometer data is stored
+ * 0x01 | magnetometer data is stored
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_mag_enable(
+u8 *v_fifo_mag_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the fifo mag enable*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_MAG_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_mag_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_MAG_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set stored
+ * magnetometer data in FIFO (all 3 axes) from the register 0x47 bit 5
+ *
+ * @param v_fifo_mag_u8 : The value of fifo mag enble
+ * value | fifo mag
+ * ----------|-------------------
+ * 0x00 | no magnetometer data is stored
+ * 0x01 | magnetometer data is stored
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_mag_enable(
+u8 v_fifo_mag_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_fifo_mag_u8 <= SMI130_MAX_VALUE_FIFO_MAG) {
+ /* write the fifo mag enable*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_FIFO_MAG_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_MAG_ENABLE,
+ v_fifo_mag_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_FIFO_MAG_ENABLE__REG,
+ &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read stored
+ * accel data in FIFO (all 3 axes) from the register 0x47 bit 6
+ *
+ * @param v_fifo_accel_u8 : The value of fifo accel enble
+ * value | fifo accel
+ * ----------|-------------------
+ * 0x00 | no accel data is stored
+ * 0x01 | accel data is stored
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_accel_enable(
+u8 *v_fifo_accel_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel fifo enable*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_ACCEL_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_accel_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_ACCEL_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set stored
+ * accel data in FIFO (all 3 axes) from the register 0x47 bit 6
+ *
+ * @param v_fifo_accel_u8 : The value of fifo accel enble
+ * value | fifo accel
+ * ----------|-------------------
+ * 0x00 | no accel data is stored
+ * 0x01 | accel data is stored
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_accel_enable(
+u8 v_fifo_accel_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_fifo_accel_u8 <= SMI130_MAX_VALUE_FIFO_ACCEL) {
+ /* write the fifo mag enables*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_ACCEL_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_ACCEL_ENABLE, v_fifo_accel_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_ACCEL_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read stored
+ * gyro data in FIFO (all 3 axes) from the resister 0x47 bit 7
+ *
+ *
+ * @param v_fifo_gyro_u8 : The value of fifo gyro enble
+ * value | fifo gyro
+ * ----------|-------------------
+ * 0x00 | no gyro data is stored
+ * 0x01 | gyro data is stored
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_gyro_enable(
+u8 *v_fifo_gyro_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read fifo gyro enable */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_GYRO_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_fifo_gyro_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_GYRO_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set stored
+ * gyro data in FIFO (all 3 axes) from the resister 0x47 bit 7
+ *
+ *
+ * @param v_fifo_gyro_u8 : The value of fifo gyro enble
+ * value | fifo gyro
+ * ----------|-------------------
+ * 0x00 | no gyro data is stored
+ * 0x01 | gyro data is stored
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_gyro_enable(
+u8 v_fifo_gyro_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_fifo_gyro_u8 <= SMI130_MAX_VALUE_FIFO_GYRO) {
+ /* write fifo gyro enable*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_FIFO_GYRO_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FIFO_GYRO_ENABLE, v_fifo_gyro_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FIFO_GYRO_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * I2C device address of auxiliary mag from the register 0x4B bit 1 to 7
+ *
+ *
+ *
+ *
+ * @param v_i2c_device_addr_u8 : The value of mag I2C device address
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_i2c_device_addr(
+u8 *v_i2c_device_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the mag I2C device address*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_I2C_DEVICE_ADDR__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_i2c_device_addr_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_I2C_DEVICE_ADDR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * I2C device address of auxiliary mag from the register 0x4B bit 1 to 7
+ *
+ *
+ *
+ *
+ * @param v_i2c_device_addr_u8 : The value of mag I2C device address
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_i2c_device_addr(
+u8 v_i2c_device_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write the mag I2C device address*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_I2C_DEVICE_ADDR__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_I2C_DEVICE_ADDR,
+ v_i2c_device_addr_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_I2C_DEVICE_ADDR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * Burst data length (1,2,6,8 byte) from the register 0x4C bit 0 to 1
+ *
+ *
+ *
+ *
+ * @param v_mag_burst_u8 : The data of mag burst read lenth
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_burst(
+u8 *v_mag_burst_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read mag burst mode length*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_BURST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_burst_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_BURST);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * Burst data length (1,2,6,8 byte) from the register 0x4C bit 0 to 1
+ *
+ *
+ *
+ *
+ * @param v_mag_burst_u8 : The data of mag burst read lenth
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_burst(
+u8 v_mag_burst_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write mag burst mode length*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_BURST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_BURST, v_mag_burst_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_MAG_BURST__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * trigger-readout offset in units of 2.5 ms. If set to zero,
+ * the offset is maximum, i.e. after readout a trigger
+ * is issued immediately. from the register 0x4C bit 2 to 5
+ *
+ *
+ *
+ *
+ * @param v_mag_offset_u8 : The value of mag offset
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_offset(
+u8 *v_mag_offset_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_OFFSET__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_offset_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_OFFSET);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * trigger-readout offset in units of 2.5 ms. If set to zero,
+ * the offset is maximum, i.e. after readout a trigger
+ * is issued immediately. from the register 0x4C bit 2 to 5
+ *
+ *
+ *
+ *
+ * @param v_mag_offset_u8 : The value of mag offset
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_offset(
+u8 v_mag_offset_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_OFFSET__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_OFFSET, v_mag_offset_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_OFFSET__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * Enable register access on MAG_IF[2] or MAG_IF[3] writes.
+ * This implies that the DATA registers are not updated with
+ * magnetometer values. Accessing magnetometer requires
+ * the magnetometer in normal mode in PMU_STATUS.
+ * from the register 0x4C bit 7
+ *
+ *
+ *
+ * @param v_mag_manual_u8 : The value of mag manual enable
+ * value | mag manual
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_manual_enable(
+u8 *v_mag_manual_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read mag manual */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_MANUAL_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_manual_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_MANUAL_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * Enable register access on MAG_IF[2] or MAG_IF[3] writes.
+ * This implies that the DATA registers are not updated with
+ * magnetometer values. Accessing magnetometer requires
+ * the magnetometer in normal mode in PMU_STATUS.
+ * from the register 0x4C bit 7
+ *
+ *
+ *
+ * @param v_mag_manual_u8 : The value of mag manual enable
+ * value | mag manual
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_manual_enable(
+u8 v_mag_manual_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = SMI130_INIT_VALUE;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write the mag manual*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_MANUAL_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ if (com_rslt == SUCCESS) {
+ /* set the bit of mag manual enable*/
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_MAG_MANUAL_ENABLE, v_mag_manual_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->dev_addr,
+ SMI130_USER_MAG_MANUAL_ENABLE__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ if (com_rslt == SUCCESS)
+ p_smi130->mag_manual_enable = v_mag_manual_u8;
+ else
+ p_smi130->mag_manual_enable = E_SMI130_COMM_RES;
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read data
+ * magnetometer address to read from the register 0x4D bit 0 to 7
+ * @brief It used to provide mag read address of auxiliary mag
+ *
+ *
+ *
+ *
+ * @param v_mag_read_addr_u8 : The value of address need to be read
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_read_addr(
+u8 *v_mag_read_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the written address*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_READ_ADDR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_read_addr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_READ_ADDR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * magnetometer write address from the register 0x4D bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_read_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_read_addr(
+u8 v_mag_read_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write the mag read address*/
+ com_rslt =
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->dev_addr,
+ SMI130_USER_READ_ADDR__REG, &v_mag_read_addr_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * magnetometer write address from the register 0x4E bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_write_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_write_addr(
+u8 *v_mag_write_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the address of last written */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_WRITE_ADDR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_write_addr_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_WRITE_ADDR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * magnetometer write address from the register 0x4E bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_write_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_write_addr(
+u8 v_mag_write_addr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write the data of mag address to write data */
+ com_rslt =
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->dev_addr,
+ SMI130_USER_WRITE_ADDR__REG, &v_mag_write_addr_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read magnetometer write data
+ * form the resister 0x4F bit 0 to 7
+ * @brief This writes the data will be wrote to mag
+ *
+ *
+ *
+ * @param v_mag_write_data_u8: The value of mag data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_write_data(
+u8 *v_mag_write_data_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_WRITE_DATA__REG, &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_mag_write_data_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_WRITE_DATA);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set magnetometer write data
+ * form the resister 0x4F bit 0 to 7
+ * @brief This writes the data will be wrote to mag
+ *
+ *
+ *
+ * @param v_mag_write_data_u8: The value of mag data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_write_data(
+u8 v_mag_write_data_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt =
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->dev_addr,
+ SMI130_USER_WRITE_DATA__REG, &v_mag_write_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * interrupt enable from the register 0x50 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_ANY_MOTION_X_ENABLE
+ * 1 | SMI130_ANY_MOTION_Y_ENABLE
+ * 2 | SMI130_ANY_MOTION_Z_ENABLE
+ * 3 | SMI130_DOUBLE_TAP_ENABLE
+ * 4 | SMI130_SINGLE_TAP_ENABLE
+ * 5 | SMI130_ORIENT_ENABLE
+ * 6 | SMI130_FLAT_ENABLE
+ *
+ * @param v_intr_enable_zero_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_enable_0(
+u8 v_enable_u8, u8 *v_intr_enable_zero_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* select interrupt to read*/
+ switch (v_enable_u8) {
+ case SMI130_ANY_MOTION_X_ENABLE:
+ /* read the any motion interrupt x data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE);
+ break;
+ case SMI130_ANY_MOTION_Y_ENABLE:
+ /* read the any motion interrupt y data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE);
+ break;
+ case SMI130_ANY_MOTION_Z_ENABLE:
+ /* read the any motion interrupt z data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE);
+ break;
+ case SMI130_DOUBLE_TAP_ENABLE:
+ /* read the double tap interrupt data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE);
+ break;
+ case SMI130_SINGLE_TAP_ENABLE:
+ /* read the single tap interrupt data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE);
+ break;
+ case SMI130_ORIENT_ENABLE:
+ /* read the orient_mbl interrupt data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_0_ORIENT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_ORIENT_ENABLE);
+ break;
+ case SMI130_FLAT_ENABLE:
+ /* read the flat interrupt data */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_0_FLAT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_zero_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_FLAT_ENABLE);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * interrupt enable from the register 0x50 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_ANY_MOTION_X_ENABLE
+ * 1 | SMI130_ANY_MOTION_Y_ENABLE
+ * 2 | SMI130_ANY_MOTION_Z_ENABLE
+ * 3 | SMI130_DOUBLE_TAP_ENABLE
+ * 4 | SMI130_SINGLE_TAP_ENABLE
+ * 5 | SMI130_ORIENT_ENABLE
+ * 6 | SMI130_FLAT_ENABLE
+ *
+ * @param v_intr_enable_zero_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_enable_0(
+u8 v_enable_u8, u8 v_intr_enable_zero_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case SMI130_ANY_MOTION_X_ENABLE:
+ /* write any motion x*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_ANY_MOTION_Y_ENABLE:
+ /* write any motion y*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_ANY_MOTION_Z_ENABLE:
+ /* write any motion z*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_DOUBLE_TAP_ENABLE:
+ /* write double tap*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_SINGLE_TAP_ENABLE:
+ /* write single tap */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_ORIENT_ENABLE:
+ /* write orient_mbl interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_0_ORIENT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_ORIENT_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_ORIENT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_FLAT_ENABLE:
+ /* write flat interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_0_FLAT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_0_FLAT_ENABLE,
+ v_intr_enable_zero_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_0_FLAT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * interrupt enable byte1 from the register 0x51 bit 0 to 6
+ * @brief It read the high_g_x,high_g_y,high_g_z,low_g_enable
+ * data ready, fifo full and fifo water mark.
+ *
+ *
+ *
+ * @param v_enable_u8 : The value of interrupt enable
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_HIGH_G_X_ENABLE
+ * 1 | SMI130_HIGH_G_Y_ENABLE
+ * 2 | SMI130_HIGH_G_Z_ENABLE
+ * 3 | SMI130_LOW_G_ENABLE
+ * 4 | SMI130_DATA_RDY_ENABLE
+ * 5 | SMI130_FIFO_FULL_ENABLE
+ * 6 | SMI130_FIFO_WM_ENABLE
+ *
+ * @param v_intr_enable_1_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_enable_1(
+u8 v_enable_u8, u8 *v_intr_enable_1_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case SMI130_HIGH_G_X_ENABLE:
+ /* read high_g_x interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE);
+ break;
+ case SMI130_HIGH_G_Y_ENABLE:
+ /* read high_g_y interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE);
+ break;
+ case SMI130_HIGH_G_Z_ENABLE:
+ /* read high_g_z interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE);
+ break;
+ case SMI130_LOW_G_ENABLE:
+ /* read low_g interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE);
+ break;
+ case SMI130_DATA_RDY_ENABLE:
+ /* read data ready interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_DATA_RDY_ENABLE);
+ break;
+ case SMI130_FIFO_FULL_ENABLE:
+ /* read fifo full interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE);
+ break;
+ case SMI130_FIFO_WM_ENABLE:
+ /* read fifo water mark interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_1_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_FIFO_WM_ENABLE);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * interrupt enable byte1 from the register 0x51 bit 0 to 6
+ * @brief It read the high_g_x,high_g_y,high_g_z,low_g_enable
+ * data ready, fifo full and fifo water mark.
+ *
+ *
+ *
+ * @param v_enable_u8 : The value of interrupt enable
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_HIGH_G_X_ENABLE
+ * 1 | SMI130_HIGH_G_Y_ENABLE
+ * 2 | SMI130_HIGH_G_Z_ENABLE
+ * 3 | SMI130_LOW_G_ENABLE
+ * 4 | SMI130_DATA_RDY_ENABLE
+ * 5 | SMI130_FIFO_FULL_ENABLE
+ * 6 | SMI130_FIFO_WM_ENABLE
+ *
+ * @param v_intr_enable_1_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_enable_1(
+u8 v_enable_u8, u8 v_intr_enable_1_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case SMI130_HIGH_G_X_ENABLE:
+ /* write high_g_x interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_HIGH_G_Y_ENABLE:
+ /* write high_g_y interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_HIGH_G_Z_ENABLE:
+ /* write high_g_z interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_LOW_G_ENABLE:
+ /* write low_g interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_DATA_RDY_ENABLE:
+ /* write data ready interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_DATA_RDY_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_FIFO_FULL_ENABLE:
+ /* write fifo full interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_FIFO_WM_ENABLE:
+ /* write fifo water mark interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_1_FIFO_WM_ENABLE,
+ v_intr_enable_1_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read
+ * interrupt enable byte2 from the register bit 0x52 bit 0 to 3
+ * @brief It reads no motion x,y and z
+ *
+ *
+ *
+ * @param v_enable_u8: The value of interrupt enable
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_NOMOTION_X_ENABLE
+ * 1 | SMI130_NOMOTION_Y_ENABLE
+ * 2 | SMI130_NOMOTION_Z_ENABLE
+ *
+ * @param v_intr_enable_2_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_enable_2(
+u8 v_enable_u8, u8 *v_intr_enable_2_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case SMI130_NOMOTION_X_ENABLE:
+ /* read no motion x */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_2_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE);
+ break;
+ case SMI130_NOMOTION_Y_ENABLE:
+ /* read no motion y */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_2_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE);
+ break;
+ case SMI130_NOMOTION_Z_ENABLE:
+ /* read no motion z */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_enable_2_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to set
+ * interrupt enable byte2 from the register bit 0x52 bit 0 to 3
+ * @brief It reads no motion x,y and z
+ *
+ *
+ *
+ * @param v_enable_u8: The value of interrupt enable
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_NOMOTION_X_ENABLE
+ * 1 | SMI130_NOMOTION_Y_ENABLE
+ * 2 | SMI130_NOMOTION_Z_ENABLE
+ *
+ * @param v_intr_enable_2_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_enable_2(
+u8 v_enable_u8, u8 v_intr_enable_2_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_enable_u8) {
+ case SMI130_NOMOTION_X_ENABLE:
+ /* write no motion x */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE,
+ v_intr_enable_2_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_NOMOTION_Y_ENABLE:
+ /* write no motion y */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE,
+ v_intr_enable_2_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_NOMOTION_Z_ENABLE:
+ /* write no motion z */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE,
+ v_intr_enable_2_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to read
+ * interrupt enable step detector interrupt from
+ * the register bit 0x52 bit 3
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The value of step detector interrupt enable
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_step_detector_enable(
+u8 *v_step_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the step detector interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_step_intr_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to set
+ * interrupt enable step detector interrupt from
+ * the register bit 0x52 bit 3
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The value of step detector interrupt enable
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_step_detector_enable(
+u8 v_step_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE,
+ v_step_intr_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Configure trigger condition of interrupt1
+ * and interrupt2 pin from the register 0x53
+ * @brief interrupt1 - bit 0
+ * @brief interrupt2 - bit 4
+ *
+ * @param v_channel_u8: The value of edge trigger selection
+ * v_channel_u8 | Edge trigger
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_EDGE_CTRL
+ * 1 | SMI130_INTR2_EDGE_CTRL
+ *
+ * @param v_intr_edge_ctrl_u8 : The value of edge trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_EDGE
+ * 0x00 | SMI130_LEVEL
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_edge_ctrl(
+u8 v_channel_u8, u8 *v_intr_edge_ctrl_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case SMI130_INTR1_EDGE_CTRL:
+ /* read the edge trigger interrupt1*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_EDGE_CTRL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_edge_ctrl_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_EDGE_CTRL);
+ break;
+ case SMI130_INTR2_EDGE_CTRL:
+ /* read the edge trigger interrupt2*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_EDGE_CTRL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_edge_ctrl_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_EDGE_CTRL);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Configure trigger condition of interrupt1
+ * and interrupt2 pin from the register 0x53
+ * @brief interrupt1 - bit 0
+ * @brief interrupt2 - bit 4
+ *
+ * @param v_channel_u8: The value of edge trigger selection
+ * v_channel_u8 | Edge trigger
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_EDGE_CTRL
+ * 1 | SMI130_INTR2_EDGE_CTRL
+ *
+ * @param v_intr_edge_ctrl_u8 : The value of edge trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_EDGE
+ * 0x00 | SMI130_LEVEL
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_edge_ctrl(
+u8 v_channel_u8, u8 v_intr_edge_ctrl_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case SMI130_INTR1_EDGE_CTRL:
+ /* write the edge trigger interrupt1*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_EDGE_CTRL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_EDGE_CTRL,
+ v_intr_edge_ctrl_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_EDGE_CTRL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_EDGE_CTRL:
+ /* write the edge trigger interrupt2*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_EDGE_CTRL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_EDGE_CTRL,
+ v_intr_edge_ctrl_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_EDGE_CTRL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used for get the Configure level condition of interrupt1
+ * and interrupt2 pin form the register 0x53
+ * @brief interrupt1 - bit 1
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of level condition selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_LEVEL
+ * 1 | SMI130_INTR2_LEVEL
+ *
+ * @param v_intr_level_u8 : The value of level of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_LEVEL_HIGH
+ * 0x00 | SMI130_LEVEL_LOW
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_level(
+u8 v_channel_u8, u8 *v_intr_level_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case SMI130_INTR1_LEVEL:
+ /* read the interrupt1 level*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_LEVEL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_level_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_LEVEL);
+ break;
+ case SMI130_INTR2_LEVEL:
+ /* read the interrupt2 level*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_LEVEL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_level_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_LEVEL);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used for set the Configure level condition of interrupt1
+ * and interrupt2 pin form the register 0x53
+ * @brief interrupt1 - bit 1
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of level condition selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_LEVEL
+ * 1 | SMI130_INTR2_LEVEL
+ *
+ * @param v_intr_level_u8 : The value of level of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_LEVEL_HIGH
+ * 0x00 | SMI130_LEVEL_LOW
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_level(
+u8 v_channel_u8, u8 v_intr_level_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case SMI130_INTR1_LEVEL:
+ /* write the interrupt1 level*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_LEVEL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_LEVEL, v_intr_level_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_LEVEL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_LEVEL:
+ /* write the interrupt2 level*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_LEVEL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_LEVEL, v_intr_level_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_LEVEL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used to get configured output enable of interrupt1
+ * and interrupt2 from the register 0x53
+ * @brief interrupt1 - bit 2
+ * @brief interrupt2 - bit 6
+ *
+ *
+ * @param v_channel_u8: The value of output type enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_OUTPUT_TYPE
+ * 1 | SMI130_INTR2_OUTPUT_TYPE
+ *
+ * @param v_intr_output_type_u8 :
+ * The value of output type of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_OPEN_DRAIN
+ * 0x00 | SMI130_PUSH_PULL
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_output_type(
+u8 v_channel_u8, u8 *v_intr_output_type_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case SMI130_INTR1_OUTPUT_TYPE:
+ /* read the output type of interrupt1*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_OUTPUT_TYPE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_output_type_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_OUTPUT_TYPE);
+ break;
+ case SMI130_INTR2_OUTPUT_TYPE:
+ /* read the output type of interrupt2*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_OUTPUT_TYPE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_output_type_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_OUTPUT_TYPE);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used to set output enable of interrupt1
+ * and interrupt2 from the register 0x53
+ * @brief interrupt1 - bit 2
+ * @brief interrupt2 - bit 6
+ *
+ *
+ * @param v_channel_u8: The value of output type enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_OUTPUT_TYPE
+ * 1 | SMI130_INTR2_OUTPUT_TYPE
+ *
+ * @param v_intr_output_type_u8 :
+ * The value of output type of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_OPEN_DRAIN
+ * 0x00 | SMI130_PUSH_PULL
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_output_type(
+u8 v_channel_u8, u8 v_intr_output_type_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case SMI130_INTR1_OUTPUT_TYPE:
+ /* write the output type of interrupt1*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_OUTPUT_TYPE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_OUTPUT_TYPE,
+ v_intr_output_type_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_OUTPUT_TYPE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_OUTPUT_TYPE:
+ /* write the output type of interrupt2*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_OUTPUT_TYPE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_OUTPUT_TYPE,
+ v_intr_output_type_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_OUTPUT_TYPE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief API used to get the Output enable for interrupt1
+ * and interrupt1 pin from the register 0x53
+ * @brief interrupt1 - bit 3
+ * @brief interrupt2 - bit 7
+ *
+ * @param v_channel_u8: The value of output enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_OUTPUT_TYPE
+ * 1 | SMI130_INTR2_OUTPUT_TYPE
+ *
+ * @param v_output_enable_u8 :
+ * The value of output enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_INPUT
+ * 0x00 | SMI130_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_output_enable(
+u8 v_channel_u8, u8 *v_output_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case SMI130_INTR1_OUTPUT_ENABLE:
+ /* read the output enable of interrupt1*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_OUTPUT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_enable_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_OUTPUT_ENABLE);
+ break;
+ case SMI130_INTR2_OUTPUT_ENABLE:
+ /* read the output enable of interrupt2*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_OUTPUT_EN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_output_enable_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_OUTPUT_EN);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief API used to set the Output enable for interrupt1
+ * and interrupt1 pin from the register 0x53
+ * @brief interrupt1 - bit 3
+ * @brief interrupt2 - bit 7
+ *
+ * @param v_channel_u8: The value of output enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_OUTPUT_TYPE
+ * 1 | SMI130_INTR2_OUTPUT_TYPE
+ *
+ * @param v_output_enable_u8 :
+ * The value of output enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_INPUT
+ * 0x00 | SMI130_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_output_enable(
+u8 v_channel_u8, u8 v_output_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case SMI130_INTR1_OUTPUT_ENABLE:
+ /* write the output enable of interrupt1*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_OUTPUT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_OUTPUT_ENABLE,
+ v_output_enable_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_OUTPUT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_OUTPUT_ENABLE:
+ /* write the output enable of interrupt2*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_OUTPUT_EN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_OUTPUT_EN,
+ v_output_enable_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_OUTPUT_EN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+* @brief This API is used to get the latch duration
+* from the register 0x54 bit 0 to 3
+* @brief This latch selection is not applicable for data ready,
+* orient_mblation and flat interrupts.
+*
+*
+*
+* @param v_latch_intr_u8 : The value of latch duration
+* Latch Duration | value
+* --------------------------------------|------------------
+* SMI130_LATCH_DUR_NONE | 0x00
+* SMI130_LATCH_DUR_312_5_MICRO_SEC | 0x01
+* SMI130_LATCH_DUR_625_MICRO_SEC | 0x02
+* SMI130_LATCH_DUR_1_25_MILLI_SEC | 0x03
+* SMI130_LATCH_DUR_2_5_MILLI_SEC | 0x04
+* SMI130_LATCH_DUR_5_MILLI_SEC | 0x05
+* SMI130_LATCH_DUR_10_MILLI_SEC | 0x06
+* SMI130_LATCH_DUR_20_MILLI_SEC | 0x07
+* SMI130_LATCH_DUR_40_MILLI_SEC | 0x08
+* SMI130_LATCH_DUR_80_MILLI_SEC | 0x09
+* SMI130_LATCH_DUR_160_MILLI_SEC | 0x0A
+* SMI130_LATCH_DUR_320_MILLI_SEC | 0x0B
+* SMI130_LATCH_DUR_640_MILLI_SEC | 0x0C
+* SMI130_LATCH_DUR_1_28_SEC | 0x0D
+* SMI130_LATCH_DUR_2_56_SEC | 0x0E
+* SMI130_LATCHED | 0x0F
+*
+*
+*
+* @return results of bus communication function
+* @retval 0 -> Success
+* @retval -1 -> Error
+*
+*
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_latch_intr(
+u8 *v_latch_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the latch duration value */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_LATCH__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_latch_intr_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LATCH);
+ }
+ return com_rslt;
+}
+/*!
+* @brief This API is used to set the latch duration
+* from the register 0x54 bit 0 to 3
+* @brief This latch selection is not applicable for data ready,
+* orient_mblation and flat interrupts.
+*
+*
+*
+* @param v_latch_intr_u8 : The value of latch duration
+* Latch Duration | value
+* --------------------------------------|------------------
+* SMI130_LATCH_DUR_NONE | 0x00
+* SMI130_LATCH_DUR_312_5_MICRO_SEC | 0x01
+* SMI130_LATCH_DUR_625_MICRO_SEC | 0x02
+* SMI130_LATCH_DUR_1_25_MILLI_SEC | 0x03
+* SMI130_LATCH_DUR_2_5_MILLI_SEC | 0x04
+* SMI130_LATCH_DUR_5_MILLI_SEC | 0x05
+* SMI130_LATCH_DUR_10_MILLI_SEC | 0x06
+* SMI130_LATCH_DUR_20_MILLI_SEC | 0x07
+* SMI130_LATCH_DUR_40_MILLI_SEC | 0x08
+* SMI130_LATCH_DUR_80_MILLI_SEC | 0x09
+* SMI130_LATCH_DUR_160_MILLI_SEC | 0x0A
+* SMI130_LATCH_DUR_320_MILLI_SEC | 0x0B
+* SMI130_LATCH_DUR_640_MILLI_SEC | 0x0C
+* SMI130_LATCH_DUR_1_28_SEC | 0x0D
+* SMI130_LATCH_DUR_2_56_SEC | 0x0E
+* SMI130_LATCHED | 0x0F
+*
+*
+*
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+*
+*
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_latch_intr(u8 v_latch_intr_u8)
+{
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_latch_intr_u8 <= SMI130_MAX_LATCH_INTR) {
+ /* write the latch duration value */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_LATCH__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LATCH, v_latch_intr_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_LATCH__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used to get input enable for interrupt1
+ * and interrupt2 pin from the register 0x54
+ * @brief interrupt1 - bit 4
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of input enable selection
+ * v_channel_u8 | input selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_INPUT_ENABLE
+ * 1 | SMI130_INTR2_INPUT_ENABLE
+ *
+ * @param v_input_en_u8 :
+ * The value of input enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_INPUT
+ * 0x00 | SMI130_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_input_enable(
+u8 v_channel_u8, u8 *v_input_en_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read input enable of interrup1 and interrupt2*/
+ case SMI130_INTR1_INPUT_ENABLE:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_INPUT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_input_en_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_INPUT_ENABLE);
+ break;
+ case SMI130_INTR2_INPUT_ENABLE:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_INPUT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_input_en_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_INPUT_ENABLE);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief API used to set input enable for interrupt1
+ * and interrupt2 pin from the register 0x54
+ * @brief interrupt1 - bit 4
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of input enable selection
+ * v_channel_u8 | input selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_INPUT_ENABLE
+ * 1 | SMI130_INTR2_INPUT_ENABLE
+ *
+ * @param v_input_en_u8 :
+ * The value of input enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_INPUT
+ * 0x00 | SMI130_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_input_enable(
+u8 v_channel_u8, u8 v_input_en_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write input enable of interrup1 and interrupt2*/
+ case SMI130_INTR1_INPUT_ENABLE:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_INPUT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR1_INPUT_ENABLE, v_input_en_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR1_INPUT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_INPUT_ENABLE:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_INPUT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR2_INPUT_ENABLE, v_input_en_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR2_INPUT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief reads the Low g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 0 in the register 0x55
+ * @brief interrupt2 bit 0 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of low_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_LOW_G
+ * 1 | SMI130_INTR2_MAP_LOW_G
+ *
+ * @param v_intr_low_g_u8 : The value of low_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g(
+u8 v_channel_u8, u8 *v_intr_low_g_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the low_g interrupt */
+ case SMI130_INTR1_MAP_LOW_G:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_low_g_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_LOW_G);
+ break;
+ case SMI130_INTR2_MAP_LOW_G:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_low_g_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_LOW_G);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief set the Low g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 0 in the register 0x55
+ * @brief interrupt2 bit 0 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of low_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_LOW_G
+ * 1 | SMI130_INTR2_MAP_LOW_G
+ *
+ * @param v_intr_low_g_u8 : The value of low_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g(
+u8 v_channel_u8, u8 v_intr_low_g_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+u8 v_step_cnt_stat_u8 = SMI130_INIT_VALUE;
+u8 v_step_det_stat_u8 = SMI130_INIT_VALUE;
+
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* check the step detector interrupt enable status*/
+ com_rslt = smi130_get_step_detector_enable(&v_step_det_stat_u8);
+ /* disable the step detector interrupt */
+ if (v_step_det_stat_u8 != SMI130_INIT_VALUE)
+ com_rslt += smi130_set_step_detector_enable(SMI130_INIT_VALUE);
+ /* check the step counter interrupt enable status*/
+ com_rslt += smi130_get_step_counter_enable(&v_step_cnt_stat_u8);
+ /* disable the step counter interrupt */
+ if (v_step_cnt_stat_u8 != SMI130_INIT_VALUE)
+ com_rslt += smi130_set_step_counter_enable(
+ SMI130_INIT_VALUE);
+ switch (v_channel_u8) {
+ /* write the low_g interrupt*/
+ case SMI130_INTR1_MAP_LOW_G:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_LOW_G, v_intr_low_g_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_LOW_G:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_LOW_G, v_intr_low_g_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the HIGH g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 1 in the register 0x55
+ * @brief interrupt2 bit 1 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of high_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_HIGH_G
+ * 1 | SMI130_INTR2_MAP_HIGH_G
+ *
+ * @param v_intr_high_g_u8 : The value of high_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_high_g(
+u8 v_channel_u8, u8 *v_intr_high_g_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the high_g interrupt*/
+ switch (v_channel_u8) {
+ case SMI130_INTR1_MAP_HIGH_G:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_HIGH_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_high_g_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_HIGH_G);
+ break;
+ case SMI130_INTR2_MAP_HIGH_G:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_HIGH_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_high_g_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_HIGH_G);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the HIGH g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 1 in the register 0x55
+ * @brief interrupt2 bit 1 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of high_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_HIGH_G
+ * 1 | SMI130_INTR2_MAP_HIGH_G
+ *
+ * @param v_intr_high_g_u8 : The value of high_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_high_g(
+u8 v_channel_u8, u8 v_intr_high_g_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the high_g interrupt*/
+ case SMI130_INTR1_MAP_HIGH_G:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_HIGH_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_HIGH_G, v_intr_high_g_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_HIGH_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_HIGH_G:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_HIGH_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_HIGH_G, v_intr_high_g_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_HIGH_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the Any motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 2 in the register 0x55
+ * @brief interrupt2 bit 2 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of any motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_ANY_MOTION
+ * 1 | SMI130_INTR2_MAP_ANY_MOTION
+ *
+ * @param v_intr_any_motion_u8 : The value of any motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_any_motion(
+u8 v_channel_u8, u8 *v_intr_any_motion_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the any motion interrupt */
+ case SMI130_INTR1_MAP_ANY_MOTION:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_any_motion_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION);
+ break;
+ case SMI130_INTR2_MAP_ANY_MOTION:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_any_motion_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the Any motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 2 in the register 0x55
+ * @brief interrupt2 bit 2 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of any motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_ANY_MOTION
+ * 1 | SMI130_INTR2_MAP_ANY_MOTION
+ *
+ * @param v_intr_any_motion_u8 : The value of any motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_any_motion(
+u8 v_channel_u8, u8 v_intr_any_motion_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+u8 sig_mot_stat = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the status of significant motion interrupt */
+ com_rslt = smi130_get_intr_significant_motion_select(&sig_mot_stat);
+ /* disable the significant motion interrupt */
+ if (sig_mot_stat != SMI130_INIT_VALUE)
+ com_rslt += smi130_set_intr_significant_motion_select(
+ SMI130_INIT_VALUE);
+ switch (v_channel_u8) {
+ /* write the any motion interrupt */
+ case SMI130_INTR1_MAP_ANY_MOTION:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION,
+ v_intr_any_motion_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_ANY_MOTION:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION,
+ v_intr_any_motion_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the No motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 3 in the register 0x55
+ * @brief interrupt2 bit 3 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of no motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_NOMO
+ * 1 | SMI130_INTR2_MAP_NOMO
+ *
+ * @param v_intr_nomotion_u8 : The value of no motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_nomotion(
+u8 v_channel_u8, u8 *v_intr_nomotion_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the no motion interrupt*/
+ case SMI130_INTR1_MAP_NOMO:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_NOMOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_nomotion_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_NOMOTION);
+ break;
+ case SMI130_INTR2_MAP_NOMO:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_NOMOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_nomotion_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_NOMOTION);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the No motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 3 in the register 0x55
+ * @brief interrupt2 bit 3 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of no motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_NOMO
+ * 1 | SMI130_INTR2_MAP_NOMO
+ *
+ * @param v_intr_nomotion_u8 : The value of no motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_nomotion(
+u8 v_channel_u8, u8 v_intr_nomotion_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the no motion interrupt*/
+ case SMI130_INTR1_MAP_NOMO:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_NOMOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_NOMOTION,
+ v_intr_nomotion_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_NOMOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_NOMO:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_NOMOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_NOMOTION,
+ v_intr_nomotion_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_NOMOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the Double Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 4 in the register 0x55
+ * @brief interrupt2 bit 4 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of double tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_DOUBLE_TAP
+ * 1 | SMI130_INTR2_MAP_DOUBLE_TAP
+ *
+ * @param v_intr_double_tap_u8 : The value of double tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_double_tap(
+u8 v_channel_u8, u8 *v_intr_double_tap_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ case SMI130_INTR1_MAP_DOUBLE_TAP:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_double_tap_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_DOUBLE_TAP);
+ break;
+ case SMI130_INTR2_MAP_DOUBLE_TAP:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_double_tap_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_DOUBLE_TAP);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the Double Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 4 in the register 0x55
+ * @brief interrupt2 bit 4 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of double tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_DOUBLE_TAP
+ * 1 | SMI130_INTR2_MAP_DOUBLE_TAP
+ *
+ * @param v_intr_double_tap_u8 : The value of double tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_double_tap(
+u8 v_channel_u8, u8 v_intr_double_tap_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* set the double tap interrupt */
+ case SMI130_INTR1_MAP_DOUBLE_TAP:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_DOUBLE_TAP,
+ v_intr_double_tap_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_DOUBLE_TAP:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_DOUBLE_TAP,
+ v_intr_double_tap_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the Single Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 5 in the register 0x55
+ * @brief interrupt2 bit 5 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of single tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_SINGLE_TAP
+ * 1 | SMI130_INTR2_MAP_SINGLE_TAP
+ *
+ * @param v_intr_single_tap_u8 : The value of single tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_single_tap(
+u8 v_channel_u8, u8 *v_intr_single_tap_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* reads the single tap interrupt*/
+ case SMI130_INTR1_MAP_SINGLE_TAP:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_SINGLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_single_tap_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_SINGLE_TAP);
+ break;
+ case SMI130_INTR2_MAP_SINGLE_TAP:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_SINGLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_single_tap_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_SINGLE_TAP);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the Single Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 5 in the register 0x55
+ * @brief interrupt2 bit 5 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of single tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_SINGLE_TAP
+ * 1 | SMI130_INTR2_MAP_SINGLE_TAP
+ *
+ * @param v_intr_single_tap_u8 : The value of single tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_single_tap(
+u8 v_channel_u8, u8 v_intr_single_tap_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the single tap interrupt */
+ case SMI130_INTR1_MAP_SINGLE_TAP:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_SINGLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_SINGLE_TAP,
+ v_intr_single_tap_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_SINGLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_SINGLE_TAP:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_SINGLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_SINGLE_TAP,
+ v_intr_single_tap_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_SINGLE_TAP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads the Orient interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 6 in the register 0x55
+ * @brief interrupt2 bit 6 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of orient_mbl interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_ORIENT
+ * 1 | SMI130_INTR2_MAP_ORIENT
+ *
+ * @param v_intr_orient_mbl_u8 : The value of orient_mbl enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl(
+u8 v_channel_u8, u8 *v_intr_orient_mbl_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the orient_mblation interrupt*/
+ case SMI130_INTR1_MAP_ORIENT:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_ORIENT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_orient_mbl_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_ORIENT);
+ break;
+ case SMI130_INTR2_MAP_ORIENT:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_ORIENT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_orient_mbl_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_ORIENT);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write the Orient interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 6 in the register 0x55
+ * @brief interrupt2 bit 6 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of orient_mbl interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_ORIENT
+ * 1 | SMI130_INTR2_MAP_ORIENT
+ *
+ * @param v_intr_orient_mbl_u8 : The value of orient_mbl enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl(
+u8 v_channel_u8, u8 v_intr_orient_mbl_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the orient_mblation interrupt*/
+ case SMI130_INTR1_MAP_ORIENT:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_ORIENT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_ORIENT, v_intr_orient_mbl_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_ORIENT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_ORIENT:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_ORIENT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_ORIENT, v_intr_orient_mbl_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_ORIENT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief Reads the Flat interrupt
+ * mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 7 in the register 0x55
+ * @brief interrupt2 bit 7 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of flat interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FLAT
+ * 1 | SMI130_INTR2_MAP_FLAT
+ *
+ * @param v_intr_flat_u8 : The value of flat enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_flat(
+u8 v_channel_u8, u8 *v_intr_flat_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the flat interrupt*/
+ case SMI130_INTR1_MAP_FLAT:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_FLAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_flat_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_FLAT);
+ break;
+ case SMI130_INTR2_MAP_FLAT:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_FLAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_flat_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_FLAT);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief Write the Flat interrupt
+ * mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 7 in the register 0x55
+ * @brief interrupt2 bit 7 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of flat interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FLAT
+ * 1 | SMI130_INTR2_MAP_FLAT
+ *
+ * @param v_intr_flat_u8 : The value of flat enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_flat(
+u8 v_channel_u8, u8 v_intr_flat_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the flat interrupt */
+ case SMI130_INTR1_MAP_FLAT:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_0_INTR1_FLAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_0_INTR1_FLAT,
+ v_intr_flat_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_MAP_0_INTR1_FLAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_FLAT:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_2_INTR2_FLAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_2_INTR2_FLAT,
+ v_intr_flat_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_MAP_2_INTR2_FLAT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Reads PMU trigger interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 0 and 4
+ * @brief interrupt1 bit 0 in the register 0x56
+ * @brief interrupt2 bit 4 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of pmu trigger selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_PMUTRIG
+ * 1 | SMI130_INTR2_MAP_PMUTRIG
+ *
+ * @param v_intr_pmu_trig_u8 : The value of pmu trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_pmu_trig(
+u8 v_channel_u8, u8 *v_intr_pmu_trig_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the pmu trigger interrupt*/
+ case SMI130_INTR1_MAP_PMUTRIG:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_PMU_TRIG__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_pmu_trig_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR1_PMU_TRIG);
+ break;
+ case SMI130_INTR2_MAP_PMUTRIG:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_PMU_TRIG__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_pmu_trig_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR2_PMU_TRIG);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write PMU trigger interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 0 and 4
+ * @brief interrupt1 bit 0 in the register 0x56
+ * @brief interrupt2 bit 4 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of pmu trigger selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_PMUTRIG
+ * 1 | SMI130_INTR2_MAP_PMUTRIG
+ *
+ * @param v_intr_pmu_trig_u8 : The value of pmu trigger enable
+ * value | trigger enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_pmu_trig(
+u8 v_channel_u8, u8 v_intr_pmu_trig_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the pmu trigger interrupt */
+ case SMI130_INTR1_MAP_PMUTRIG:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_PMU_TRIG__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR1_PMU_TRIG,
+ v_intr_pmu_trig_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_PMU_TRIG__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_PMUTRIG:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_PMU_TRIG__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR2_PMU_TRIG,
+ v_intr_pmu_trig_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_PMU_TRIG__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief Reads FIFO Full interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 5 and 1
+ * @brief interrupt1 bit 5 in the register 0x56
+ * @brief interrupt2 bit 1 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo full interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FIFO_FULL
+ * 1 | SMI130_INTR2_MAP_FIFO_FULL
+ *
+ * @param v_intr_fifo_full_u8 : The value of fifo full interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_fifo_full(
+u8 v_channel_u8, u8 *v_intr_fifo_full_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the fifo full interrupt */
+ case SMI130_INTR1_MAP_FIFO_FULL:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_FIFO_FULL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_fifo_full_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR1_FIFO_FULL);
+ break;
+ case SMI130_INTR2_MAP_FIFO_FULL:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_FIFO_FULL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_fifo_full_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR2_FIFO_FULL);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write FIFO Full interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 5 and 1
+ * @brief interrupt1 bit 5 in the register 0x56
+ * @brief interrupt2 bit 1 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo full interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FIFO_FULL
+ * 1 | SMI130_INTR2_MAP_FIFO_FULL
+ *
+ * @param v_intr_fifo_full_u8 : The value of fifo full interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_fifo_full(
+u8 v_channel_u8, u8 v_intr_fifo_full_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the fifo full interrupt */
+ case SMI130_INTR1_MAP_FIFO_FULL:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_FIFO_FULL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR1_FIFO_FULL,
+ v_intr_fifo_full_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_MAP_1_INTR1_FIFO_FULL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_FIFO_FULL:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_FIFO_FULL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR2_FIFO_FULL,
+ v_intr_fifo_full_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_MAP_1_INTR2_FIFO_FULL__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Reads FIFO Watermark interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 6 and 2
+ * @brief interrupt1 bit 6 in the register 0x56
+ * @brief interrupt2 bit 2 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo Watermark interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FIFO_WM
+ * 1 | SMI130_INTR2_MAP_FIFO_WM
+ *
+ * @param v_intr_fifo_wm_u8 : The value of fifo Watermark interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_fifo_wm(
+u8 v_channel_u8, u8 *v_intr_fifo_wm_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* read the fifo water mark interrupt */
+ case SMI130_INTR1_MAP_FIFO_WM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_FIFO_WM__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_fifo_wm_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR1_FIFO_WM);
+ break;
+ case SMI130_INTR2_MAP_FIFO_WM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_FIFO_WM__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_fifo_wm_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR2_FIFO_WM);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write FIFO Watermark interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 6 and 2
+ * @brief interrupt1 bit 6 in the register 0x56
+ * @brief interrupt2 bit 2 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo Watermark interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FIFO_WM
+ * 1 | SMI130_INTR2_MAP_FIFO_WM
+ *
+ * @param v_intr_fifo_wm_u8 : The value of fifo Watermark interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_fifo_wm(
+u8 v_channel_u8, u8 v_intr_fifo_wm_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /* write the fifo water mark interrupt */
+ case SMI130_INTR1_MAP_FIFO_WM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_FIFO_WM__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR1_FIFO_WM,
+ v_intr_fifo_wm_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_MAP_1_INTR1_FIFO_WM__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_FIFO_WM:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_FIFO_WM__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR2_FIFO_WM,
+ v_intr_fifo_wm_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr,
+ SMI130_USER_INTR_MAP_1_INTR2_FIFO_WM__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Reads Data Ready interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56
+ * @brief interrupt1 bit 7 in the register 0x56
+ * @brief interrupt2 bit 3 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of data ready interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_DATA_RDY
+ * 1 | SMI130_INTR2_MAP_DATA_RDY
+ *
+ * @param v_intr_data_rdy_u8 : The value of data ready interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_data_rdy(
+u8 v_channel_u8, u8 *v_intr_data_rdy_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /*Read Data Ready interrupt*/
+ case SMI130_INTR1_MAP_DATA_RDY:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_DATA_RDY__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_data_rdy_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR1_DATA_RDY);
+ break;
+ case SMI130_INTR2_MAP_DATA_RDY:
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_DATA_RDY__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_data_rdy_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR2_DATA_RDY);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief Write Data Ready interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56
+ * @brief interrupt1 bit 7 in the register 0x56
+ * @brief interrupt2 bit 3 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of data ready interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_DATA_RDY
+ * 1 | SMI130_INTR2_MAP_DATA_RDY
+ *
+ * @param v_intr_data_rdy_u8 : The value of data ready interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_data_rdy(
+u8 v_channel_u8, u8 v_intr_data_rdy_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ switch (v_channel_u8) {
+ /*Write Data Ready interrupt*/
+ case SMI130_INTR1_MAP_DATA_RDY:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_DATA_RDY__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR1_DATA_RDY,
+ v_intr_data_rdy_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR1_DATA_RDY__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ case SMI130_INTR2_MAP_DATA_RDY:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_DATA_RDY__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MAP_1_INTR2_DATA_RDY,
+ v_intr_data_rdy_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(p_smi130->
+ dev_addr, SMI130_USER_INTR_MAP_1_INTR2_DATA_RDY__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API reads data source for the interrupt
+ * engine for the single and double tap interrupts from the register
+ * 0x58 bit 3
+ *
+ *
+ * @param v_tap_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_source(u8 *v_tap_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the tap source interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_DATA_0_INTR_TAP_SOURCE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_source_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_DATA_0_INTR_TAP_SOURCE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write data source for the interrupt
+ * engine for the single and double tap interrupts from the register
+ * 0x58 bit 3
+ *
+ *
+ * @param v_tap_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_source(
+u8 v_tap_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_tap_source_u8 <= SMI130_MAX_VALUE_SOURCE_INTR) {
+ /* write the tap source interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_DATA_0_INTR_TAP_SOURCE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_DATA_0_INTR_TAP_SOURCE,
+ v_tap_source_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_DATA_0_INTR_TAP_SOURCE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API Reads Data source for the
+ * interrupt engine for the low and high g interrupts
+ * from the register 0x58 bit 7
+ *
+ * @param v_low_high_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_high_source(
+u8 *v_low_high_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the high_low_g source interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_high_source_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Data source for the
+ * interrupt engine for the low and high g interrupts
+ * from the register 0x58 bit 7
+ *
+ * @param v_low_high_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_high_source(
+u8 v_low_high_source_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_low_high_source_u8 <= SMI130_MAX_VALUE_SOURCE_INTR) {
+ /* write the high_low_g source interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE,
+ v_low_high_source_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API reads Data source for the
+ * interrupt engine for the nomotion and anymotion interrupts
+ * from the register 0x59 bit 7
+ *
+ * @param v_motion_source_u8 :
+ * The value of the any/no motion interrupt source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_motion_source(
+u8 *v_motion_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the any/no motion interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_DATA_1_INTR_MOTION_SOURCE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_motion_source_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_DATA_1_INTR_MOTION_SOURCE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Data source for the
+ * interrupt engine for the nomotion and anymotion interrupts
+ * from the register 0x59 bit 7
+ *
+ * @param v_motion_source_u8 :
+ * The value of the any/no motion interrupt source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_motion_source(
+u8 v_motion_source_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_motion_source_u8 <= SMI130_MAX_VALUE_SOURCE_INTR) {
+ /* write the any/no motion interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_DATA_1_INTR_MOTION_SOURCE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_DATA_1_INTR_MOTION_SOURCE,
+ v_motion_source_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_DATA_1_INTR_MOTION_SOURCE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to read the low_g duration from register
+ * 0x5A bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_durn_u8 : The value of low_g duration
+ *
+ * @note Low_g duration trigger trigger delay according to
+ * "(v_low_g_durn_u8 * 2.5)ms" in a range from 2.5ms to 640ms.
+ * the default corresponds delay is 20ms
+ * @note When low_g data source of interrupt is unfiltered
+ * the sensor must not be in low power mode
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g_durn(
+u8 *v_low_g_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the low_g interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_g_durn_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_0_INTR_LOW_DURN);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to write the low_g duration from register
+ * 0x5A bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_durn_u8 : The value of low_g duration
+ *
+ * @note Low_g duration trigger trigger delay according to
+ * "(v_low_g_durn_u8 * 2.5)ms" in a range from 2.5ms to 640ms.
+ * the default corresponds delay is 20ms
+ * @note When low_g data source of interrupt is unfiltered
+ * the sensor must not be in low power mode
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g_durn(u8 v_low_g_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write the low_g interrupt */
+ com_rslt = p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__REG,
+ &v_low_g_durn_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read Threshold
+ * definition for the low-g interrupt from the register 0x5B bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_thres_u8 : The value of low_g threshold
+ *
+ * @note Low_g interrupt trigger threshold according to
+ * (v_low_g_thres_u8 * 7.81)mg for v_low_g_thres_u8 > 0
+ * 3.91 mg for v_low_g_thres_u8 = 0
+ * The threshold range is form 3.91mg to 2.000mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g_thres(
+u8 *v_low_g_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read low_g threshold */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_g_thres_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_1_INTR_LOW_THRES);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write Threshold
+ * definition for the low-g interrupt from the register 0x5B bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_thres_u8 : The value of low_g threshold
+ *
+ * @note Low_g interrupt trigger threshold according to
+ * (v_low_g_thres_u8 * 7.81)mg for v_low_g_thres_u8 > 0
+ * 3.91 mg for v_low_g_thres_u8 = 0
+ * The threshold range is form 3.91mg to 2.000mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g_thres(
+u8 v_low_g_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write low_g threshold */
+ com_rslt = p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__REG,
+ &v_low_g_thres_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API Reads Low-g interrupt hysteresis
+ * from the register 0x5C bit 0 to 1
+ *
+ * @param v_low_hyst_u8 :The value of low_g hysteresis
+ *
+ * @note Low_g hysteresis calculated by v_low_hyst_u8*125 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g_hyst(
+u8 *v_low_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read low_g hysteresis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_hyst_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Low-g interrupt hysteresis
+ * from the register 0x5C bit 0 to 1
+ *
+ * @param v_low_hyst_u8 :The value of low_g hysteresis
+ *
+ * @note Low_g hysteresis calculated by v_low_hyst_u8*125 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g_hyst(
+u8 v_low_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write low_g hysteresis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST,
+ v_low_hyst_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads Low-g interrupt mode
+ * from the register 0x5C bit 2
+ *
+ * @param v_low_g_mode_u8 : The value of low_g mode
+ * Value | Description
+ * ----------|-----------------
+ * 0 | single-axis
+ * 1 | axis-summing
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g_mode(u8 *v_low_g_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /*read Low-g interrupt mode*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_low_g_mode_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Low-g interrupt mode
+ * from the register 0x5C bit 2
+ *
+ * @param v_low_g_mode_u8 : The value of low_g mode
+ * Value | Description
+ * ----------|-----------------
+ * 0 | single-axis
+ * 1 | axis-summing
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g_mode(
+u8 v_low_g_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_low_g_mode_u8 <= SMI130_MAX_VALUE_LOW_G_MODE) {
+ /*write Low-g interrupt mode*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE,
+ v_low_g_mode_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads High-g interrupt hysteresis
+ * from the register 0x5C bit 6 and 7
+ *
+ * @param v_high_g_hyst_u8 : The value of high hysteresis
+ *
+ * @note High_g hysteresis changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g hysteresis
+ * ----------------|---------------------
+ * 2g | high_hy*125 mg
+ * 4g | high_hy*250 mg
+ * 8g | high_hy*500 mg
+ * 16g | high_hy*1000 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_high_g_hyst(
+u8 *v_high_g_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read high_g hysteresis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_hyst_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write High-g interrupt hysteresis
+ * from the register 0x5C bit 6 and 7
+ *
+ * @param v_high_g_hyst_u8 : The value of high hysteresis
+ *
+ * @note High_g hysteresis changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g hysteresis
+ * ----------------|---------------------
+ * 2g | high_hy*125 mg
+ * 4g | high_hy*250 mg
+ * 8g | high_hy*500 mg
+ * 16g | high_hy*1000 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_high_g_hyst(
+u8 v_high_g_hyst_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write high_g hysteresis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST,
+ v_high_g_hyst_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read Delay
+ * time definition for the high-g interrupt from the register
+ * 0x5D bit 0 to 7
+ *
+ *
+ *
+ * @param v_high_g_durn_u8 : The value of high duration
+ *
+ * @note High_g interrupt delay triggered according to
+ * v_high_g_durn_u8 * 2.5ms in a range from 2.5ms to 640ms
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_high_g_durn(
+u8 *v_high_g_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read high_g duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_durn_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write Delay
+ * time definition for the high-g interrupt from the register
+ * 0x5D bit 0 to 7
+ *
+ *
+ *
+ * @param v_high_g_durn_u8 : The value of high duration
+ *
+ * @note High_g interrupt delay triggered according to
+ * v_high_g_durn_u8 * 2.5ms in a range from 2.5ms to 640ms
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_high_g_durn(
+u8 v_high_g_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write high_g duration*/
+ com_rslt = p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__REG,
+ &v_high_g_durn_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to read Threshold
+ * definition for the high-g interrupt from the register 0x5E 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_high_g_thres_u8 : Pointer holding the value of Threshold
+ * @note High_g threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | v_high_g_thres_u8*7.81 mg
+ * 4g | v_high_g_thres_u8*15.63 mg
+ * 8g | v_high_g_thres_u8*31.25 mg
+ * 16g | v_high_g_thres_u8*62.5 mg
+ * @note when v_high_g_thres_u8 = 0
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | 3.91 mg
+ * 4g | 7.81 mg
+ * 8g | 15.63 mg
+ * 16g | 31.25 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_high_g_thres(
+u8 *v_high_g_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_high_g_thres_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write Threshold
+ * definition for the high-g interrupt from the register 0x5E 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_high_g_thres_u8 : Pointer holding the value of Threshold
+ * @note High_g threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | v_high_g_thres_u8*7.81 mg
+ * 4g | v_high_g_thres_u8*15.63 mg
+ * 8g | v_high_g_thres_u8*31.25 mg
+ * 16g | v_high_g_thres_u8*62.5 mg
+ * @note when v_high_g_thres_u8 = 0
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | 3.91 mg
+ * 4g | 7.81 mg
+ * 8g | 15.63 mg
+ * 16g | 31.25 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_high_g_thres(
+u8 v_high_g_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ com_rslt = p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__REG,
+ &v_high_g_thres_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads any motion duration
+ * from the register 0x5F bit 0 and 1
+ *
+ * @param v_any_motion_durn_u8 : The value of any motion duration
+ *
+ * @note Any motion duration can be calculated by "v_any_motion_durn_u8 + 1"
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_any_motion_durn(
+u8 *v_any_motion_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read any motion duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_durn_u8 = SMI130_GET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write any motion duration
+ * from the register 0x5F bit 0 and 1
+ *
+ * @param v_any_motion_durn_u8 : The value of any motion duration
+ *
+ * @note Any motion duration can be calculated by "v_any_motion_durn_u8 + 1"
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_any_motion_durn(
+u8 v_any_motion_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write any motion duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN,
+ v_any_motion_durn_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read Slow/no-motion
+ * interrupt trigger delay duration from the register 0x5F bit 2 to 7
+ *
+ * @param v_slow_no_motion_u8 :The value of slow no motion duration
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * @note v_slow_no_motion_u8(5:4)=0b00 ->
+ * [v_slow_no_motion_u8(3:0) + 1] * 1.28s (1.28s-20.48s)
+ * @note v_slow_no_motion_u8(5:4)=1 ->
+ * [v_slow_no_motion_u8(3:0)+5] * 5.12s (25.6s-102.4s)
+ * @note v_slow_no_motion_u8(5)='1' ->
+ * [(v_slow_no_motion_u8:0)+11] * 10.24s (112.64s-430.08s);
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_slow_no_motion_durn(
+u8 *v_slow_no_motion_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read slow no motion duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_slow_no_motion_u8 = SMI130_GET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN);
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API write Slow/no-motion
+ * interrupt trigger delay duration from the register 0x5F bit 2 to 7
+ *
+ * @param v_slow_no_motion_u8 :The value of slow no motion duration
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * @note v_slow_no_motion_u8(5:4)=0b00 ->
+ * [v_slow_no_motion_u8(3:0) + 1] * 1.28s (1.28s-20.48s)
+ * @note v_slow_no_motion_u8(5:4)=1 ->
+ * [v_slow_no_motion_u8(3:0)+5] * 5.12s (25.6s-102.4s)
+ * @note v_slow_no_motion_u8(5)='1' ->
+ * [(v_slow_no_motion_u8:0)+11] * 10.24s (112.64s-430.08s);
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_slow_no_motion_durn(
+u8 v_slow_no_motion_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write slow no motion duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN,
+ v_slow_no_motion_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API is used to read threshold
+ * definition for the any-motion interrupt
+ * from the register 0x60 bit 0 to 7
+ *
+ *
+ * @param v_any_motion_thres_u8 : The value of any motion threshold
+ *
+ * @note any motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | v_any_motion_thres_u8*3.91 mg
+ * 4g | v_any_motion_thres_u8*7.81 mg
+ * 8g | v_any_motion_thres_u8*15.63 mg
+ * 16g | v_any_motion_thres_u8*31.25 mg
+ * @note when v_any_motion_thres_u8 = 0
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_any_motion_thres(
+u8 *v_any_motion_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read any motion threshold*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_any_motion_thres_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write threshold
+ * definition for the any-motion interrupt
+ * from the register 0x60 bit 0 to 7
+ *
+ *
+ * @param v_any_motion_thres_u8 : The value of any motion threshold
+ *
+ * @note any motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | v_any_motion_thres_u8*3.91 mg
+ * 4g | v_any_motion_thres_u8*7.81 mg
+ * 8g | v_any_motion_thres_u8*15.63 mg
+ * 16g | v_any_motion_thres_u8*31.25 mg
+ * @note when v_any_motion_thres_u8 = 0
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_any_motion_thres(
+u8 v_any_motion_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write any motion threshold*/
+ com_rslt = p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__REG,
+ &v_any_motion_thres_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to read threshold
+ * for the slow/no-motion interrupt
+ * from the register 0x61 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_slow_no_motion_thres_u8 : The value of slow no motion threshold
+ * @note slow no motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | v_slow_no_motion_thres_u8*3.91 mg
+ * 4g | v_slow_no_motion_thres_u8*7.81 mg
+ * 8g | v_slow_no_motion_thres_u8*15.63 mg
+ * 16g | v_slow_no_motion_thres_u8*31.25 mg
+ * @note when v_slow_no_motion_thres_u8 = 0
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_slow_no_motion_thres(
+u8 *v_slow_no_motion_thres_u8)
+{
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read slow no motion threshold*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_slow_no_motion_thres_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES);
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to write threshold
+ * for the slow/no-motion interrupt
+ * from the register 0x61 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_slow_no_motion_thres_u8 : The value of slow no motion threshold
+ * @note slow no motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | v_slow_no_motion_thres_u8*3.91 mg
+ * 4g | v_slow_no_motion_thres_u8*7.81 mg
+ * 8g | v_slow_no_motion_thres_u8*15.63 mg
+ * 16g | v_slow_no_motion_thres_u8*31.25 mg
+ * @note when v_slow_no_motion_thres_u8 = 0
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_slow_no_motion_thres(
+u8 v_slow_no_motion_thres_u8)
+{
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write slow no motion threshold*/
+ com_rslt = p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__REG,
+ &v_slow_no_motion_thres_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to read
+ * the slow/no-motion selection from the register 0x62 bit 0
+ *
+ *
+ *
+ *
+ * @param v_intr_slow_no_motion_select_u8 :
+ * The value of slow/no-motion select
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SLOW_MOTION
+ * 0x01 | NO_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_slow_no_motion_select(
+u8 *v_intr_slow_no_motion_select_u8)
+{
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read slow no motion select*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_slow_no_motion_select_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT);
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to write
+ * the slow/no-motion selection from the register 0x62 bit 0
+ *
+ *
+ *
+ *
+ * @param v_intr_slow_no_motion_select_u8 :
+ * The value of slow/no-motion select
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SLOW_MOTION
+ * 0x01 | NO_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_slow_no_motion_select(
+u8 v_intr_slow_no_motion_select_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+} else {
+if (v_intr_slow_no_motion_select_u8 <= SMI130_MAX_VALUE_NO_MOTION) {
+ /* write slow no motion select*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT,
+ v_intr_slow_no_motion_select_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+} else {
+com_rslt = E_SMI130_OUT_OF_RANGE;
+}
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to select
+ * the significant or any motion interrupt from the register 0x62 bit 1
+ *
+ *
+ *
+ *
+ * @param v_intr_significant_motion_select_u8 :
+ * the value of significant or any motion interrupt selection
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | ANY_MOTION
+ * 0x01 | SIGNIFICANT_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_significant_motion_select(
+u8 *v_intr_significant_motion_select_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the significant or any motion interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_SIGNIFICATION_MOTION_SELECT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_intr_significant_motion_select_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_SIGNIFICATION_MOTION_SELECT);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to write, select
+ * the significant or any motion interrupt from the register 0x62 bit 1
+ *
+ *
+ *
+ *
+ * @param v_intr_significant_motion_select_u8 :
+ * the value of significant or any motion interrupt selection
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | ANY_MOTION
+ * 0x01 | SIGNIFICANT_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_significant_motion_select(
+u8 v_intr_significant_motion_select_u8)
+{
+/* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_intr_significant_motion_select_u8 <=
+ SMI130_MAX_VALUE_SIGNIFICANT_MOTION) {
+ /* write the significant or any motion interrupt*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_SIGNIFICATION_MOTION_SELECT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_SIGNIFICATION_MOTION_SELECT,
+ v_intr_significant_motion_select_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_SIGNIFICATION_MOTION_SELECT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API is used to read
+ * the significant skip time from the register 0x62 bit 2 and 3
+ *
+ *
+ *
+ *
+ * @param v_int_sig_mot_skip_u8 : the value of significant skip time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | skip time 1.5 seconds
+ * 0x01 | skip time 3 seconds
+ * 0x02 | skip time 6 seconds
+ * 0x03 | skip time 12 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_significant_motion_skip(
+u8 *v_int_sig_mot_skip_u8)
+{
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read significant skip time*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_SKIP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_int_sig_mot_skip_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_SKIP);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to write
+ * the significant skip time from the register 0x62 bit 2 and 3
+ *
+ *
+ *
+ *
+ * @param v_int_sig_mot_skip_u8 : the value of significant skip time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | skip time 1.5 seconds
+ * 0x01 | skip time 3 seconds
+ * 0x02 | skip time 6 seconds
+ * 0x03 | skip time 12 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_significant_motion_skip(
+u8 v_int_sig_mot_skip_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_int_sig_mot_skip_u8 <= SMI130_MAX_UNDER_SIG_MOTION) {
+ /* write significant skip time*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_SKIP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_SKIP,
+ v_int_sig_mot_skip_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_SKIP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to read
+ * the significant proof time from the register 0x62 bit 4 and 5
+ *
+ *
+ *
+ *
+ * @param v_significant_motion_proof_u8 :
+ * the value of significant proof time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | proof time 0.25 seconds
+ * 0x01 | proof time 0.5 seconds
+ * 0x02 | proof time 1 seconds
+ * 0x03 | proof time 2 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_significant_motion_proof(
+u8 *v_significant_motion_proof_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read significant proof time */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_PROOF__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_significant_motion_proof_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_PROOF);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API is used to write
+ * the significant proof time from the register 0x62 bit 4 and 5
+ *
+ *
+ *
+ *
+ * @param v_significant_motion_proof_u8 :
+ * the value of significant proof time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | proof time 0.25 seconds
+ * 0x01 | proof time 0.5 seconds
+ * 0x02 | proof time 1 seconds
+ * 0x03 | proof time 2 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_significant_motion_proof(
+u8 v_significant_motion_proof_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_significant_motion_proof_u8
+ <= SMI130_MAX_UNDER_SIG_MOTION) {
+ /* write significant proof time */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_PROOF__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_PROOF,
+ v_significant_motion_proof_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_SIGNIFICANT_MOTION_PROOF__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to get the tap duration
+ * from the register 0x63 bit 0 to 2
+ *
+ *
+ *
+ * @param v_tap_durn_u8 : The value of tap duration
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_DURN_50MS
+ * 0x01 | SMI130_TAP_DURN_100MS
+ * 0x03 | SMI130_TAP_DURN_150MS
+ * 0x04 | SMI130_TAP_DURN_200MS
+ * 0x05 | SMI130_TAP_DURN_250MS
+ * 0x06 | SMI130_TAP_DURN_375MS
+ * 0x07 | SMI130_TAP_DURN_700MS
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_durn(
+u8 *v_tap_durn_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read tap duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_durn_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_DURN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API is used to write the tap duration
+ * from the register 0x63 bit 0 to 2
+ *
+ *
+ *
+ * @param v_tap_durn_u8 : The value of tap duration
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_DURN_50MS
+ * 0x01 | SMI130_TAP_DURN_100MS
+ * 0x03 | SMI130_TAP_DURN_150MS
+ * 0x04 | SMI130_TAP_DURN_200MS
+ * 0x05 | SMI130_TAP_DURN_250MS
+ * 0x06 | SMI130_TAP_DURN_375MS
+ * 0x07 | SMI130_TAP_DURN_700MS
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_durn(
+u8 v_tap_durn_u8)
+{
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_tap_durn_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_tap_durn_u8 <= SMI130_MAX_TAP_TURN) {
+ switch (v_tap_durn_u8) {
+ case SMI130_TAP_DURN_50MS:
+ v_data_tap_durn_u8 = SMI130_TAP_DURN_50MS;
+ break;
+ case SMI130_TAP_DURN_100MS:
+ v_data_tap_durn_u8 = SMI130_TAP_DURN_100MS;
+ break;
+ case SMI130_TAP_DURN_150MS:
+ v_data_tap_durn_u8 = SMI130_TAP_DURN_150MS;
+ break;
+ case SMI130_TAP_DURN_200MS:
+ v_data_tap_durn_u8 = SMI130_TAP_DURN_200MS;
+ break;
+ case SMI130_TAP_DURN_250MS:
+ v_data_tap_durn_u8 = SMI130_TAP_DURN_250MS;
+ break;
+ case SMI130_TAP_DURN_375MS:
+ v_data_tap_durn_u8 = SMI130_TAP_DURN_375MS;
+ break;
+ case SMI130_TAP_DURN_500MS:
+ v_data_tap_durn_u8 = SMI130_TAP_DURN_500MS;
+ break;
+ case SMI130_TAP_DURN_700MS:
+ v_data_tap_durn_u8 = SMI130_TAP_DURN_700MS;
+ break;
+ default:
+ break;
+ }
+ /* write tap duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_DURN,
+ v_data_tap_durn_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_DURN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read the
+ * tap shock duration from the register 0x63 bit 2
+ *
+ * @param v_tap_shock_u8 :The value of tap shock
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_SHOCK_50MS
+ * 0x01 | SMI130_TAP_SHOCK_75MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_shock(
+u8 *v_tap_shock_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read tap shock duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_SHOCK__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_shock_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_SHOCK);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write the
+ * tap shock duration from the register 0x63 bit 2
+ *
+ * @param v_tap_shock_u8 :The value of tap shock
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_SHOCK_50MS
+ * 0x01 | SMI130_TAP_SHOCK_75MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_shock(u8 v_tap_shock_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_tap_shock_u8 <= SMI130_MAX_VALUE_TAP_SHOCK) {
+ /* write tap shock duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_SHOCK__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_SHOCK,
+ v_tap_shock_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_SHOCK__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read
+ * tap quiet duration from the register 0x63 bit 7
+ *
+ *
+ * @param v_tap_quiet_u8 : The value of tap quiet
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_QUIET_30MS
+ * 0x01 | SMI130_TAP_QUIET_20MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_quiet(
+u8 *v_tap_quiet_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read tap quiet duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_QUIET__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_quiet_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_QUIET);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write
+ * tap quiet duration from the register 0x63 bit 7
+ *
+ *
+ * @param v_tap_quiet_u8 : The value of tap quiet
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_QUIET_30MS
+ * 0x01 | SMI130_TAP_QUIET_20MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_quiet(u8 v_tap_quiet_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_tap_quiet_u8 <= SMI130_MAX_VALUE_TAP_QUIET) {
+ /* write tap quiet duration*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_QUIET__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_QUIET,
+ v_tap_quiet_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_0_INTR_TAP_QUIET__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read Threshold of the
+ * single/double tap interrupt from the register 0x64 bit 0 to 4
+ *
+ *
+ * @param v_tap_thres_u8 : The value of single/double tap threshold
+ *
+ * @note single/double tap threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | single/double tap threshold
+ * ----------------|---------------------
+ * 2g | ((v_tap_thres_u8 + 1) * 62.5)mg
+ * 4g | ((v_tap_thres_u8 + 1) * 125)mg
+ * 8g | ((v_tap_thres_u8 + 1) * 250)mg
+ * 16g | ((v_tap_thres_u8 + 1) * 500)mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_thres(
+u8 *v_tap_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read tap threshold*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_1_INTR_TAP_THRES__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_tap_thres_u8 = SMI130_GET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_TAP_1_INTR_TAP_THRES);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Threshold of the
+ * single/double tap interrupt from the register 0x64 bit 0 to 4
+ *
+ *
+ * @param v_tap_thres_u8 : The value of single/double tap threshold
+ *
+ * @note single/double tap threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | single/double tap threshold
+ * ----------------|---------------------
+ * 2g | ((v_tap_thres_u8 + 1) * 62.5)mg
+ * 4g | ((v_tap_thres_u8 + 1) * 125)mg
+ * 8g | ((v_tap_thres_u8 + 1) * 250)mg
+ * 16g | ((v_tap_thres_u8 + 1) * 500)mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_thres(
+u8 v_tap_thres_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write tap threshold*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_1_INTR_TAP_THRES__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_TAP_1_INTR_TAP_THRES,
+ v_tap_thres_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_TAP_1_INTR_TAP_THRES__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read the threshold for orient_mblation interrupt
+ * from the register 0x65 bit 0 and 1
+ *
+ * @param v_orient_mbl_mode_u8 : The value of threshold for orient_mblation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | symmetrical
+ * 0x01 | high-asymmetrical
+ * 0x02 | low-asymmetrical
+ * 0x03 | symmetrical
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_mode(
+u8 *v_orient_mbl_mode_u8)
+{
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read orient_mblation threshold*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mbl_mode_u8 = SMI130_GET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_MODE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write the threshold for orient_mblation interrupt
+ * from the register 0x65 bit 0 and 1
+ *
+ * @param v_orient_mbl_mode_u8 : The value of threshold for orient_mblation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | symmetrical
+ * 0x01 | high-asymmetrical
+ * 0x02 | low-asymmetrical
+ * 0x03 | symmetrical
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_mode(
+u8 v_orient_mbl_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_orient_mbl_mode_u8 <= SMI130_MAX_ORIENT_MODE) {
+ /* write orient_mblation threshold*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_MODE,
+ v_orient_mbl_mode_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read the orient_mbl blocking mode
+ * that is used for the generation of the orient_mblation interrupt.
+ * from the register 0x65 bit 2 and 3
+ *
+ * @param v_orient_mbl_blocking_u8 : The value of orient_mbl blocking mode
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | No blocking
+ * 0x01 | Theta blocking or acceleration in any axis > 1.5g
+ * 0x02 | Theta blocking or acceleration slope in any axis >
+ * - | 0.2g or acceleration in any axis > 1.5g
+ * 0x03 | Theta blocking or acceleration slope in any axis >
+ * - | 0.4g or acceleration in any axis >
+ * - | 1.5g and value of orient_mbl is not stable
+ * - | for at least 100 ms
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_blocking(
+u8 *v_orient_mbl_blocking_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read orient_mbl blocking mode*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mbl_blocking_u8 = SMI130_GET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write the orient_mbl blocking mode
+ * that is used for the generation of the orient_mblation interrupt.
+ * from the register 0x65 bit 2 and 3
+ *
+ * @param v_orient_mbl_blocking_u8 : The value of orient_mbl blocking mode
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | No blocking
+ * 0x01 | Theta blocking or acceleration in any axis > 1.5g
+ * 0x02 | Theta blocking or acceleration slope in any axis >
+ * - | 0.2g or acceleration in any axis > 1.5g
+ * 0x03 | Theta blocking or acceleration slope in any axis >
+ * - | 0.4g or acceleration in any axis >
+ * - | 1.5g and value of orient_mbl is not stable
+ * - | for at least 100 ms
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_blocking(
+u8 v_orient_mbl_blocking_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_orient_mbl_blocking_u8 <= SMI130_MAX_ORIENT_BLOCKING) {
+ /* write orient_mbl blocking mode*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING,
+ v_orient_mbl_blocking_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API read Orient interrupt
+ * hysteresis, from the register 0x64 bit 4 to 7
+ *
+ *
+ *
+ * @param v_orient_mbl_hyst_u8 : The value of orient_mbl hysteresis
+ *
+ * @note 1 LSB corresponds to 62.5 mg,
+ * irrespective of the selected accel range
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_hyst(
+u8 *v_orient_mbl_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read orient_mbl hysteresis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mbl_hyst_u8 = SMI130_GET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_HYST);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Orient interrupt
+ * hysteresis, from the register 0x64 bit 4 to 7
+ *
+ *
+ *
+ * @param v_orient_mbl_hyst_u8 : The value of orient_mbl hysteresis
+ *
+ * @note 1 LSB corresponds to 62.5 mg,
+ * irrespective of the selected accel range
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_hyst(
+u8 v_orient_mbl_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write orient_mbl hysteresis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_HYST,
+ v_orient_mbl_hyst_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read Orient
+ * blocking angle (0 to 44.8) from the register 0x66 bit 0 to 5
+ *
+ * @param v_orient_mbl_theta_u8 : The value of Orient blocking angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_theta(
+u8 *v_orient_mbl_theta_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read Orient blocking angle*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mbl_theta_u8 = SMI130_GET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_THETA);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Orient
+ * blocking angle (0 to 44.8) from the register 0x66 bit 0 to 5
+ *
+ * @param v_orient_mbl_theta_u8 : The value of Orient blocking angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_theta(
+u8 v_orient_mbl_theta_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_orient_mbl_theta_u8 <= SMI130_MAX_ORIENT_THETA) {
+ /* write Orient blocking angle*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_THETA,
+ v_orient_mbl_theta_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API read orient_mbl change
+ * of up/down bit from the register 0x66 bit 6
+ *
+ * @param v_orient_mbl_ud_u8 : The value of orient_mbl change of up/down
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | Is ignored
+ * 0x01 | Generates orient_mblation interrupt
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_ud_enable(
+u8 *v_orient_mbl_ud_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read orient_mbl up/down enable*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mbl_ud_u8 = SMI130_GET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write orient_mbl change
+ * of up/down bit from the register 0x66 bit 6
+ *
+ * @param v_orient_mbl_ud_u8 : The value of orient_mbl change of up/down
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | Is ignored
+ * 0x01 | Generates orient_mblation interrupt
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_ud_enable(
+u8 v_orient_mbl_ud_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_orient_mbl_ud_u8 <= SMI130_MAX_VALUE_ORIENT_UD) {
+ /* write orient_mbl up/down enable */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE,
+ v_orient_mbl_ud_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API read orient_mblation axes changes
+ * from the register 0x66 bit 7
+ *
+ * @param v_orient_mbl_axes_u8 : The value of orient_mbl axes assignment
+ * value | Behaviour | Name
+ * ----------|--------------------|------
+ * 0x00 | x = x, y = y, z = z|orient_mbl_ax_noex
+ * 0x01 | x = y, y = z, z = x|orient_mbl_ax_ex
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_axes_enable(
+u8 *v_orient_mbl_axes_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read orient_mblation axes changes */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_orient_mbl_axes_u8 = SMI130_GET_BITSLICE
+ (v_data_u8,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write orient_mblation axes changes
+ * from the register 0x66 bit 7
+ *
+ * @param v_orient_mbl_axes_u8 : The value of orient_mbl axes assignment
+ * value | Behaviour | Name
+ * ----------|--------------------|------
+ * 0x00 | x = x, y = y, z = z|orient_mbl_ax_noex
+ * 0x01 | x = y, y = z, z = x|orient_mbl_ax_ex
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_axes_enable(
+u8 v_orient_mbl_axes_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_orient_mbl_axes_u8 <= SMI130_MAX_VALUE_ORIENT_AXES) {
+ /*write orient_mblation axes changes */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX,
+ v_orient_mbl_axes_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+}
+return com_rslt;
+}
+ /*!
+ * @brief This API read Flat angle (0 to 44.8) for flat interrupt
+ * from the register 0x67 bit 0 to 5
+ *
+ * @param v_flat_theta_u8 : The value of flat angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_flat_theta(
+u8 *v_flat_theta_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read Flat angle*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_FLAT_0_INTR_FLAT_THETA__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_theta_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_FLAT_0_INTR_FLAT_THETA);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write Flat angle (0 to 44.8) for flat interrupt
+ * from the register 0x67 bit 0 to 5
+ *
+ * @param v_flat_theta_u8 : The value of flat angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_flat_theta(
+u8 v_flat_theta_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_flat_theta_u8 <= SMI130_MAX_FLAT_THETA) {
+ /* write Flat angle */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_FLAT_0_INTR_FLAT_THETA__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_FLAT_0_INTR_FLAT_THETA,
+ v_flat_theta_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_FLAT_0_INTR_FLAT_THETA__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read Flat interrupt hold time;
+ * from the register 0x68 bit 4 and 5
+ *
+ * @param v_flat_hold_u8 : The value of flat hold time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | 0ms
+ * 0x01 | 512ms
+ * 0x01 | 1024ms
+ * 0x01 | 2048ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_flat_hold(
+u8 *v_flat_hold_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read flat hold time*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HOLD__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_hold_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HOLD);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Flat interrupt hold time;
+ * from the register 0x68 bit 4 and 5
+ *
+ * @param v_flat_hold_u8 : The value of flat hold time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | 0ms
+ * 0x01 | 512ms
+ * 0x01 | 1024ms
+ * 0x01 | 2048ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_flat_hold(
+u8 v_flat_hold_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_flat_hold_u8 <= SMI130_MAX_FLAT_HOLD) {
+ /* write flat hold time*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HOLD__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HOLD,
+ v_flat_hold_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HOLD__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read flat interrupt hysteresis
+ * from the register 0x68 bit 0 to 3
+ *
+ * @param v_flat_hyst_u8 : The value of flat hysteresis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_flat_hyst(
+u8 *v_flat_hyst_u8)
+{
+ /* variable used to return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the flat hysteresis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_flat_hyst_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HYST);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write flat interrupt hysteresis
+ * from the register 0x68 bit 0 to 3
+ *
+ * @param v_flat_hyst_u8 : The value of flat hysteresis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_flat_hyst(
+u8 v_flat_hyst_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_flat_hyst_u8 <= SMI130_MAX_FLAT_HYST) {
+ /* read the flat hysteresis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HYST,
+ v_flat_hyst_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_INTR_FLAT_1_INTR_FLAT_HYST__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read accel offset compensation
+ * target value for z-axis from the register 0x69 bit 0 and 1
+ *
+ * @param v_foc_accel_z_u8 : the value of accel offset compensation z axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_accel_z(u8 *v_foc_accel_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel offset compensation for z axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_accel_z_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_ACCEL_Z);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write accel offset compensation
+ * target value for z-axis from the register 0x69 bit 0 and 1
+ *
+ * @param v_foc_accel_z_u8 : the value of accel offset compensation z axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_foc_accel_z(
+u8 v_foc_accel_z_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write the accel offset compensation for z axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_ACCEL_Z,
+ v_foc_accel_z_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel offset compensation
+ * target value for y-axis
+ * from the register 0x69 bit 2 and 3
+ *
+ * @param v_foc_accel_y_u8 : the value of accel offset compensation y axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_accel_y(u8 *v_foc_accel_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel offset compensation for y axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_accel_y_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_ACCEL_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel offset compensation
+ * target value for y-axis
+ * from the register 0x69 bit 2 and 3
+ *
+ * @param v_foc_accel_y_u8 : the value of accel offset compensation y axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x02 | -1g
+ * 0x03 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_foc_accel_y(u8 v_foc_accel_y_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_foc_accel_y_u8 <= SMI130_MAX_ACCEL_FOC) {
+ /* write the accel offset compensation for y axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_ACCEL_Y,
+ v_foc_accel_y_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel offset compensation
+ * target value for x-axis is
+ * from the register 0x69 bit 4 and 5
+ *
+ * @param v_foc_accel_x_u8 : the value of accel offset compensation x axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x02 | -1g
+ * 0x03 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_accel_x(u8 *v_foc_accel_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the accel offset compensation for x axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_accel_x_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_ACCEL_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel offset compensation
+ * target value for x-axis is
+ * from the register 0x69 bit 4 and 5
+ *
+ * @param v_foc_accel_x_u8 : the value of accel offset compensation x axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_foc_accel_x(u8 v_foc_accel_x_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_foc_accel_x_u8 <= SMI130_MAX_ACCEL_FOC) {
+ /* write the accel offset compensation for x axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_ACCEL_X,
+ v_foc_accel_x_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API writes accel fast offset compensation
+ * from the register 0x69 bit 0 to 5
+ * @brief This API writes each axis individually
+ * FOC_X_AXIS - bit 4 and 5
+ * FOC_Y_AXIS - bit 2 and 3
+ * FOC_Z_AXIS - bit 0 and 1
+ *
+ * @param v_foc_accel_u8: The value of accel offset compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_axis_u8: The value of accel offset axis selection
+ * value | axis
+ * ----------|-------------------
+ * 0 | FOC_X_AXIS
+ * 1 | FOC_Y_AXIS
+ * 2 | FOC_Z_AXIS
+ *
+ * @param v_accel_offset_s8: The accel offset value
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_foc_trigger(u8 v_axis_u8,
+u8 v_foc_accel_u8, s8 *v_accel_offset_s8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+s8 v_status_s8 = SUCCESS;
+u8 v_timeout_u8 = SMI130_INIT_VALUE;
+s8 v_foc_accel_offset_x_s8 = SMI130_INIT_VALUE;
+s8 v_foc_accel_offset_y_s8 = SMI130_INIT_VALUE;
+s8 v_foc_accel_offset_z_s8 = SMI130_INIT_VALUE;
+u8 focstatus = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+} else {
+ v_status_s8 = smi130_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ switch (v_axis_u8) {
+ case FOC_X_AXIS:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_ACCEL_X,
+ v_foc_accel_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the
+ FOC need to write
+ 0x03 in the register 0x7e*/
+ com_rslt +=
+ smi130_set_command_register(
+ START_FOC_ACCEL_GYRO);
+
+ com_rslt +=
+ smi130_get_foc_rdy(&focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ SMI130_MAXIMUM_TIMEOUT)) {
+ p_smi130->delay_msec(
+ SMI130_DELAY_SETTLING_TIME);
+ com_rslt = smi130_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == SMI130_FOC_STAT_HIGH)) {
+ com_rslt +=
+ smi130_get_accel_offset_compensation_xaxis(
+ &v_foc_accel_offset_x_s8);
+ *v_accel_offset_s8 =
+ v_foc_accel_offset_x_s8;
+ }
+ break;
+ case FOC_Y_AXIS:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_ACCEL_Y,
+ v_foc_accel_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the FOC
+ need to write 0x03
+ in the register 0x7e*/
+ com_rslt +=
+ smi130_set_command_register(
+ START_FOC_ACCEL_GYRO);
+
+ com_rslt +=
+ smi130_get_foc_rdy(&focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ SMI130_MAXIMUM_TIMEOUT)) {
+ p_smi130->delay_msec(
+ SMI130_DELAY_SETTLING_TIME);
+ com_rslt = smi130_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == SMI130_FOC_STAT_HIGH)) {
+ com_rslt +=
+ smi130_get_accel_offset_compensation_yaxis(
+ &v_foc_accel_offset_y_s8);
+ *v_accel_offset_s8 =
+ v_foc_accel_offset_y_s8;
+ }
+ break;
+ case FOC_Z_AXIS:
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_ACCEL_Z,
+ v_foc_accel_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Z__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the FOC need to write
+ 0x03 in the register 0x7e*/
+ com_rslt +=
+ smi130_set_command_register(
+ START_FOC_ACCEL_GYRO);
+
+ com_rslt +=
+ smi130_get_foc_rdy(&focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ SMI130_MAXIMUM_TIMEOUT)) {
+ p_smi130->delay_msec(
+ SMI130_DELAY_SETTLING_TIME);
+ com_rslt = smi130_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == SMI130_FOC_STAT_HIGH)) {
+ com_rslt +=
+ smi130_get_accel_offset_compensation_zaxis(
+ &v_foc_accel_offset_z_s8);
+ *v_accel_offset_s8 =
+ v_foc_accel_offset_z_s8;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+}
+return com_rslt;
+}
+/*!
+ * @brief This API write fast accel offset compensation
+ * it writes all axis together.To the register 0x69 bit 0 to 5
+ * FOC_X_AXIS - bit 4 and 5
+ * FOC_Y_AXIS - bit 2 and 3
+ * FOC_Z_AXIS - bit 0 and 1
+ *
+ * @param v_foc_accel_x_u8: The value of accel offset x compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_foc_accel_y_u8: The value of accel offset y compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_foc_accel_z_u8: The value of accel offset z compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_accel_off_x_s8: The value of accel offset x axis
+ * @param v_accel_off_y_s8: The value of accel offset y axis
+ * @param v_accel_off_z_s8: The value of accel offset z axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_accel_foc_trigger_xyz(u8 v_foc_accel_x_u8,
+u8 v_foc_accel_y_u8, u8 v_foc_accel_z_u8, s8 *v_accel_off_x_s8,
+s8 *v_accel_off_y_s8, s8 *v_accel_off_z_s8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 focx = SMI130_INIT_VALUE;
+u8 focy = SMI130_INIT_VALUE;
+u8 focz = SMI130_INIT_VALUE;
+s8 v_foc_accel_offset_x_s8 = SMI130_INIT_VALUE;
+s8 v_foc_accel_offset_y_s8 = SMI130_INIT_VALUE;
+s8 v_foc_accel_offset_z_s8 = SMI130_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+u8 v_timeout_u8 = SMI130_INIT_VALUE;
+u8 focstatus = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ v_status_s8 = smi130_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ /* foc x axis*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_X__REG,
+ &focx, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ focx = SMI130_SET_BITSLICE(focx,
+ SMI130_USER_FOC_ACCEL_X,
+ v_foc_accel_x_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_X__REG,
+ &focx, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* foc y axis*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Y__REG,
+ &focy, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ focy = SMI130_SET_BITSLICE(focy,
+ SMI130_USER_FOC_ACCEL_Y,
+ v_foc_accel_y_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Y__REG,
+ &focy, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* foc z axis*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Z__REG,
+ &focz, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ focz = SMI130_SET_BITSLICE(focz,
+ SMI130_USER_FOC_ACCEL_Z,
+ v_foc_accel_z_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_ACCEL_Z__REG,
+ &focz, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the FOC need to
+ write 0x03 in the register 0x7e*/
+ com_rslt += smi130_set_command_register(
+ START_FOC_ACCEL_GYRO);
+
+ com_rslt += smi130_get_foc_rdy(
+ &focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ SMI130_MAXIMUM_TIMEOUT)) {
+ p_smi130->delay_msec(
+ SMI130_DELAY_SETTLING_TIME);
+ com_rslt = smi130_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == SMI130_GEN_READ_WRITE_DATA_LENGTH)) {
+ com_rslt +=
+ smi130_get_accel_offset_compensation_xaxis(
+ &v_foc_accel_offset_x_s8);
+ *v_accel_off_x_s8 =
+ v_foc_accel_offset_x_s8;
+ com_rslt +=
+ smi130_get_accel_offset_compensation_yaxis(
+ &v_foc_accel_offset_y_s8);
+ *v_accel_off_y_s8 =
+ v_foc_accel_offset_y_s8;
+ com_rslt +=
+ smi130_get_accel_offset_compensation_zaxis(
+ &v_foc_accel_offset_z_s8);
+ *v_accel_off_z_s8 =
+ v_foc_accel_offset_z_s8;
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API read gyro fast offset enable
+ * from the register 0x69 bit 6
+ *
+ * @param v_foc_gyro_u8 : The value of gyro fast offset enable
+ * value | Description
+ * ----------|-------------
+ * 0 | fast offset compensation disabled
+ * 1 | fast offset compensation enabled
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_gyro_enable(
+u8 *v_foc_gyro_u8)
+{
+ /* used for return the status of bus communication */
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the gyro fast offset enable*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_FOC_GYRO_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_foc_gyro_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_GYRO_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro fast offset enable
+ * from the register 0x69 bit 6
+ *
+ * @param v_foc_gyro_u8 : The value of gyro fast offset enable
+ * value | Description
+ * ----------|-------------
+ * 0 | fast offset compensation disabled
+ * 1 | fast offset compensation enabled
+ *
+ * @param v_gyro_off_x_s16 : The value of gyro fast offset x axis data
+ * @param v_gyro_off_y_s16 : The value of gyro fast offset y axis data
+ * @param v_gyro_off_z_s16 : The value of gyro fast offset z axis data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_foc_gyro_enable(
+u8 v_foc_gyro_u8, s16 *v_gyro_off_x_s16,
+s16 *v_gyro_off_y_s16, s16 *v_gyro_off_z_s16)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+u8 v_timeout_u8 = SMI130_INIT_VALUE;
+s16 offsetx = SMI130_INIT_VALUE;
+s16 offsety = SMI130_INIT_VALUE;
+s16 offsetz = SMI130_INIT_VALUE;
+u8 focstatus = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ v_status_s8 = smi130_set_gyro_offset_enable(
+ GYRO_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_FOC_GYRO_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_FOC_GYRO_ENABLE,
+ v_foc_gyro_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_FOC_GYRO_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ /* trigger the FOC need to write 0x03
+ in the register 0x7e*/
+ com_rslt += smi130_set_command_register
+ (START_FOC_ACCEL_GYRO);
+
+ com_rslt += smi130_get_foc_rdy(&focstatus);
+ if ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH)) {
+ while ((com_rslt != SUCCESS) ||
+ (focstatus != SMI130_FOC_STAT_HIGH
+ && v_timeout_u8 <
+ SMI130_MAXIMUM_TIMEOUT)) {
+ p_smi130->delay_msec(
+ SMI130_DELAY_SETTLING_TIME);
+ com_rslt = smi130_get_foc_rdy(
+ &focstatus);
+ v_timeout_u8++;
+ }
+ }
+ if ((com_rslt == SUCCESS) &&
+ (focstatus == SMI130_FOC_STAT_HIGH)) {
+ com_rslt +=
+ smi130_get_gyro_offset_compensation_xaxis
+ (&offsetx);
+ *v_gyro_off_x_s16 = offsetx;
+
+ com_rslt +=
+ smi130_get_gyro_offset_compensation_yaxis
+ (&offsety);
+ *v_gyro_off_y_s16 = offsety;
+
+ com_rslt +=
+ smi130_get_gyro_offset_compensation_zaxis(
+ &offsetz);
+ *v_gyro_off_z_s16 = offsetz;
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+return com_rslt;
+}
+ /*!
+ * @brief This API read NVM program enable
+ * from the register 0x6A bit 1
+ *
+ * @param v_nvm_prog_u8 : The value of NVM program enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_nvm_prog_enable(
+u8 *v_nvm_prog_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read NVM program*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_CONFIG_NVM_PROG_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_nvm_prog_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_CONFIG_NVM_PROG_ENABLE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write NVM program enable
+ * from the register 0x6A bit 1
+ *
+ * @param v_nvm_prog_u8 : The value of NVM program enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_nvm_prog_enable(
+u8 v_nvm_prog_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_nvm_prog_u8 <= SMI130_MAX_VALUE_NVM_PROG) {
+ /* write the NVM program*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_CONFIG_NVM_PROG_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_CONFIG_NVM_PROG_ENABLE,
+ v_nvm_prog_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_CONFIG_NVM_PROG_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read to configure SPI
+ * Interface Mode for primary and OIS interface
+ * from the register 0x6B bit 0
+ *
+ * @param v_spi3_u8 : The value of SPI mode selection
+ * Value | Description
+ * --------|-------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_spi3(
+u8 *v_spi3_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read SPI mode*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_SPI3__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_spi3_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_IF_CONFIG_SPI3);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write to configure SPI
+ * Interface Mode for primary and OIS interface
+ * from the register 0x6B bit 0
+ *
+ * @param v_spi3_u8 : The value of SPI mode selection
+ * Value | Description
+ * --------|-------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_spi3(
+u8 v_spi3_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_spi3_u8 <= SMI130_MAX_VALUE_SPI3) {
+ /* write SPI mode*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_SPI3__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_IF_CONFIG_SPI3,
+ v_spi3_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_SPI3__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read I2C Watchdog timer
+ * from the register 0x70 bit 1
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watch dog timer
+ * Value | Description
+ * --------|-------------
+ * 0 | I2C watchdog v_timeout_u8 after 1 ms
+ * 1 | I2C watchdog v_timeout_u8 after 50 ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_i2c_wdt_select(
+u8 *v_i2c_wdt_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read I2C watch dog timer */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_I2C_WDT_SELECT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_i2c_wdt_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_IF_CONFIG_I2C_WDT_SELECT);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write I2C Watchdog timer
+ * from the register 0x70 bit 1
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watch dog timer
+ * Value | Description
+ * --------|-------------
+ * 0 | I2C watchdog v_timeout_u8 after 1 ms
+ * 1 | I2C watchdog v_timeout_u8 after 50 ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_i2c_wdt_select(
+u8 v_i2c_wdt_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_i2c_wdt_u8 <= SMI130_MAX_VALUE_I2C_WDT) {
+ /* write I2C watch dog timer */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_I2C_WDT_SELECT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_IF_CONFIG_I2C_WDT_SELECT,
+ v_i2c_wdt_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_I2C_WDT_SELECT__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read I2C watchdog enable
+ * from the register 0x70 bit 2
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watchdog enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_i2c_wdt_enable(
+u8 *v_i2c_wdt_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read i2c watch dog eneble */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_I2C_WDT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_i2c_wdt_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_IF_CONFIG_I2C_WDT_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write I2C watchdog enable
+ * from the register 0x70 bit 2
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watchdog enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_i2c_wdt_enable(
+u8 v_i2c_wdt_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_i2c_wdt_u8 <= SMI130_MAX_VALUE_I2C_WDT) {
+ /* write i2c watch dog eneble */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_I2C_WDT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_IF_CONFIG_I2C_WDT_ENABLE,
+ v_i2c_wdt_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_I2C_WDT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read I2C interface configuration(if) moe
+ * from the register 0x6B bit 4 and 5
+ *
+ * @param v_if_mode_u8 : The value of interface configuration mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Primary interface:autoconfig / secondary interface:off
+ * 0x01 | Primary interface:I2C / secondary interface:OIS
+ * 0x02 | Primary interface:autoconfig/secondary interface:Magnetometer
+ * 0x03 | Reserved
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_if_mode(
+u8 *v_if_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read if mode*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_IF_MODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_if_mode_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_IF_CONFIG_IF_MODE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write I2C interface configuration(if) moe
+ * from the register 0x6B bit 4 and 5
+ *
+ * @param v_if_mode_u8 : The value of interface configuration mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Primary interface:autoconfig / secondary interface:off
+ * 0x01 | Primary interface:I2C / secondary interface:OIS
+ * 0x02 | Primary interface:autoconfig/secondary interface:Magnetometer
+ * 0x03 | Reserved
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_if_mode(
+u8 v_if_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_if_mode_u8 <= SMI130_MAX_IF_MODE) {
+ /* write if mode*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_IF_MODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_IF_CONFIG_IF_MODE,
+ v_if_mode_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_IF_CONFIG_IF_MODE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro sleep trigger
+ * from the register 0x6C bit 0 to 2
+ *
+ * @param v_gyro_sleep_trigger_u8 : The value of gyro sleep trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | nomotion: no / Not INT1 pin: no / INT2 pin: no
+ * 0x01 | nomotion: no / Not INT1 pin: no / INT2 pin: yes
+ * 0x02 | nomotion: no / Not INT1 pin: yes / INT2 pin: no
+ * 0x03 | nomotion: no / Not INT1 pin: yes / INT2 pin: yes
+ * 0x04 | nomotion: yes / Not INT1 pin: no / INT2 pin: no
+ * 0x05 | anymotion: yes / Not INT1 pin: no / INT2 pin: yes
+ * 0x06 | anymotion: yes / Not INT1 pin: yes / INT2 pin: no
+ * 0x07 | anymotion: yes / Not INT1 pin: yes / INT2 pin: yes
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_sleep_trigger(
+u8 *v_gyro_sleep_trigger_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro sleep trigger */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_SLEEP_TRIGGER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_sleep_trigger_u8 =
+ SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_SLEEP_TRIGGER);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro sleep trigger
+ * from the register 0x6C bit 0 to 2
+ *
+ * @param v_gyro_sleep_trigger_u8 : The value of gyro sleep trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | nomotion: no / Not INT1 pin: no / INT2 pin: no
+ * 0x01 | nomotion: no / Not INT1 pin: no / INT2 pin: yes
+ * 0x02 | nomotion: no / Not INT1 pin: yes / INT2 pin: no
+ * 0x03 | nomotion: no / Not INT1 pin: yes / INT2 pin: yes
+ * 0x04 | nomotion: yes / Not INT1 pin: no / INT2 pin: no
+ * 0x05 | anymotion: yes / Not INT1 pin: no / INT2 pin: yes
+ * 0x06 | anymotion: yes / Not INT1 pin: yes / INT2 pin: no
+ * 0x07 | anymotion: yes / Not INT1 pin: yes / INT2 pin: yes
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_sleep_trigger(
+u8 v_gyro_sleep_trigger_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_gyro_sleep_trigger_u8 <= SMI130_MAX_GYRO_SLEEP_TIGGER) {
+ /* write gyro sleep trigger */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_SLEEP_TRIGGER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_SLEEP_TRIGGER,
+ v_gyro_sleep_trigger_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_SLEEP_TRIGGER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro wakeup trigger
+ * from the register 0x6C bit 3 and 4
+ *
+ * @param v_gyro_wakeup_trigger_u8 : The value of gyro wakeup trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | anymotion: no / INT1 pin: no
+ * 0x01 | anymotion: no / INT1 pin: yes
+ * 0x02 | anymotion: yes / INT1 pin: no
+ * 0x03 | anymotion: yes / INT1 pin: yes
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_wakeup_trigger(
+u8 *v_gyro_wakeup_trigger_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro wakeup trigger */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_WAKEUP_TRIGGER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_wakeup_trigger_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_GYRO_WAKEUP_TRIGGER);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro wakeup trigger
+ * from the register 0x6C bit 3 and 4
+ *
+ * @param v_gyro_wakeup_trigger_u8 : The value of gyro wakeup trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | anymotion: no / INT1 pin: no
+ * 0x01 | anymotion: no / INT1 pin: yes
+ * 0x02 | anymotion: yes / INT1 pin: no
+ * 0x03 | anymotion: yes / INT1 pin: yes
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_wakeup_trigger(
+u8 v_gyro_wakeup_trigger_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_gyro_wakeup_trigger_u8
+ <= SMI130_MAX_GYRO_WAKEUP_TRIGGER) {
+ /* write gyro wakeup trigger */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_WAKEUP_TRIGGER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_WAKEUP_TRIGGER,
+ v_gyro_wakeup_trigger_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_WAKEUP_TRIGGER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read Target state for gyro sleep mode
+ * from the register 0x6C bit 5
+ *
+ * @param v_gyro_sleep_state_u8 : The value of gyro sleep mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Sleep transition to fast wake up state
+ * 0x01 | Sleep transition to suspend state
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_sleep_state(
+u8 *v_gyro_sleep_state_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro sleep state*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_SLEEP_STATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_sleep_state_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_GYRO_SLEEP_STATE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write Target state for gyro sleep mode
+ * from the register 0x6C bit 5
+ *
+ * @param v_gyro_sleep_state_u8 : The value of gyro sleep mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Sleep transition to fast wake up state
+ * 0x01 | Sleep transition to suspend state
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_sleep_state(
+u8 v_gyro_sleep_state_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_gyro_sleep_state_u8 <= SMI130_MAX_VALUE_SLEEP_STATE) {
+ /* write gyro sleep state*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_SLEEP_STATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_SLEEP_STATE,
+ v_gyro_sleep_state_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_SLEEP_STATE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro wakeup interrupt
+ * from the register 0x6C bit 6
+ *
+ * @param v_gyro_wakeup_intr_u8 : The valeu of gyro wakeup interrupt
+ * Value | Description
+ * --------|-------------
+ * 0x00 | DISABLE
+ * 0x01 | ENABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_wakeup_intr(
+u8 *v_gyro_wakeup_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro wakeup interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_WAKEUP_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_wakeup_intr_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_GYRO_WAKEUP_INTR);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro wakeup interrupt
+ * from the register 0x6C bit 6
+ *
+ * @param v_gyro_wakeup_intr_u8 : The valeu of gyro wakeup interrupt
+ * Value | Description
+ * --------|-------------
+ * 0x00 | DISABLE
+ * 0x01 | ENABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_wakeup_intr(
+u8 v_gyro_wakeup_intr_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_gyro_wakeup_intr_u8 <= SMI130_MAX_VALUE_WAKEUP_INTR) {
+ /* write gyro wakeup interrupt */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_WAKEUP_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_WAKEUP_INTR,
+ v_gyro_wakeup_intr_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_WAKEUP_INTR__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel select axis to be self-test
+ *
+ * @param v_accel_selftest_axis_u8 :
+ * The value of accel self test axis selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | disabled
+ * 0x01 | x-axis
+ * 0x02 | y-axis
+ * 0x03 | z-axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_selftest_axis(
+u8 *v_accel_selftest_axis_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read accel self test axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_SELFTEST_AXIS__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_selftest_axis_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_ACCEL_SELFTEST_AXIS);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel select axis to be self-test
+ *
+ * @param v_accel_selftest_axis_u8 :
+ * The value of accel self test axis selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | disabled
+ * 0x01 | x-axis
+ * 0x02 | y-axis
+ * 0x03 | z-axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_selftest_axis(
+u8 v_accel_selftest_axis_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_accel_selftest_axis_u8
+ <= SMI130_MAX_ACCEL_SELFTEST_AXIS) {
+ /* write accel self test axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_SELFTEST_AXIS__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_SELFTEST_AXIS,
+ v_accel_selftest_axis_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_SELFTEST_AXIS__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel self test axis sign
+ * from the register 0x6D bit 2
+ *
+ * @param v_accel_selftest_sign_u8: The value of accel self test axis sign
+ * Value | Description
+ * --------|-------------
+ * 0x00 | negative
+ * 0x01 | positive
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_selftest_sign(
+u8 *v_accel_selftest_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read accel self test axis sign*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_SELFTEST_SIGN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_selftest_sign_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_ACCEL_SELFTEST_SIGN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel self test axis sign
+ * from the register 0x6D bit 2
+ *
+ * @param v_accel_selftest_sign_u8: The value of accel self test axis sign
+ * Value | Description
+ * --------|-------------
+ * 0x00 | negative
+ * 0x01 | positive
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_selftest_sign(
+u8 v_accel_selftest_sign_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_accel_selftest_sign_u8 <=
+ SMI130_MAX_VALUE_SELFTEST_SIGN) {
+ /* write accel self test axis sign*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_SELFTEST_SIGN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_ACCEL_SELFTEST_SIGN,
+ v_accel_selftest_sign_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_ACCEL_SELFTEST_SIGN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel self test amplitude
+ * from the register 0x6D bit 3
+ * select amplitude of the selftest deflection:
+ *
+ * @param v_accel_selftest_amp_u8 : The value of accel self test amplitude
+ * Value | Description
+ * --------|-------------
+ * 0x00 | LOW
+ * 0x01 | HIGH
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_selftest_amp(
+u8 *v_accel_selftest_amp_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read self test amplitude*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_SELFTEST_AMP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_selftest_amp_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_SELFTEST_AMP);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel self test amplitude
+ * from the register 0x6D bit 3
+ * select amplitude of the selftest deflection:
+ *
+ * @param v_accel_selftest_amp_u8 : The value of accel self test amplitude
+ * Value | Description
+ * --------|-------------
+ * 0x00 | LOW
+ * 0x01 | HIGH
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_selftest_amp(
+u8 v_accel_selftest_amp_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_accel_selftest_amp_u8 <=
+ SMI130_MAX_VALUE_SELFTEST_AMP) {
+ /* write self test amplitude*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_SELFTEST_AMP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_SELFTEST_AMP,
+ v_accel_selftest_amp_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_SELFTEST_AMP__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro self test trigger
+ *
+ * @param v_gyro_selftest_start_u8: The value of gyro self test start
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_selftest_start(
+u8 *v_gyro_selftest_start_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro self test start */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_SELFTEST_START__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_selftest_start_u8 = SMI130_GET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_GYRO_SELFTEST_START);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro self test trigger
+ *
+ * @param v_gyro_selftest_start_u8: The value of gyro self test start
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_selftest_start(
+u8 v_gyro_selftest_start_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_gyro_selftest_start_u8 <=
+ SMI130_MAX_VALUE_SELFTEST_START) {
+ /* write gyro self test start */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_SELFTEST_START__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_GYRO_SELFTEST_START,
+ v_gyro_selftest_start_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_GYRO_SELFTEST_START__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read primary interface selection I2C or SPI
+ * from the register 0x70 bit 0
+ *
+ * @param v_spi_enable_u8: The value of Interface selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | I2C Enable
+ * 0x01 | I2C DISBALE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_spi_enable(u8 *v_spi_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read interface section*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_NV_CONFIG_SPI_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_spi_enable_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_NV_CONFIG_SPI_ENABLE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write primary interface selection I2C or SPI
+ * from the register 0x70 bit 0
+ *
+ * @param v_spi_enable_u8: The value of Interface selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | I2C Enable
+ * 0x01 | I2C DISBALE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_spi_enable(u8 v_spi_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write interface section*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_NV_CONFIG_SPI_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_NV_CONFIG_SPI_ENABLE,
+ v_spi_enable_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_NV_CONFIG_SPI_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read the spare zero
+ * form register 0x70 bit 3
+ *
+ *
+ * @param v_spare0_trim_u8: The value of spare zero
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_spare0_trim(u8 *v_spare0_trim_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read spare zero*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_NV_CONFIG_SPARE0__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_spare0_trim_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_NV_CONFIG_SPARE0);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write the spare zero
+ * form register 0x70 bit 3
+ *
+ *
+ * @param v_spare0_trim_u8: The value of spare zero
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_spare0_trim(u8 v_spare0_trim_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write spare zero*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_NV_CONFIG_SPARE0__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_NV_CONFIG_SPARE0,
+ v_spare0_trim_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_NV_CONFIG_SPARE0__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read the NVM counter
+ * form register 0x70 bit 4 to 7
+ *
+ *
+ * @param v_nvm_counter_u8: The value of NVM counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_nvm_counter(u8 *v_nvm_counter_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read NVM counter*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_NV_CONFIG_NVM_COUNTER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_nvm_counter_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_NV_CONFIG_NVM_COUNTER);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write the NVM counter
+ * form register 0x70 bit 4 to 7
+ *
+ *
+ * @param v_nvm_counter_u8: The value of NVM counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_nvm_counter(
+u8 v_nvm_counter_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write NVM counter*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_NV_CONFIG_NVM_COUNTER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_NV_CONFIG_NVM_COUNTER,
+ v_nvm_counter_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_NV_CONFIG_NVM_COUNTER__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel manual offset compensation of x axis
+ * from the register 0x71 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_x_s8:
+ * The value of accel manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_offset_compensation_xaxis(
+s8 *v_accel_off_x_s8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read accel manual offset compensation of x axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_0_ACCEL_OFF_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_off_x_s8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_OFFSET_0_ACCEL_OFF_X);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel manual offset compensation of x axis
+ * from the register 0x71 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_x_s8:
+ * The value of accel manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_offset_compensation_xaxis(
+s8 v_accel_off_x_s8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* enable accel offset */
+ v_status_s8 = smi130_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ /* write accel manual offset compensation of x axis*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_0_ACCEL_OFF_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_OFFSET_0_ACCEL_OFF_X,
+ v_accel_off_x_s8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_0_ACCEL_OFF_X__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel manual offset compensation of y axis
+ * from the register 0x72 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_y_s8:
+ * The value of accel manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_offset_compensation_yaxis(
+s8 *v_accel_off_y_s8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read accel manual offset compensation of y axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_1_ACCEL_OFF_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_off_y_s8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_OFFSET_1_ACCEL_OFF_Y);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel manual offset compensation of y axis
+ * from the register 0x72 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_y_s8:
+ * The value of accel manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_offset_compensation_yaxis(
+s8 v_accel_off_y_s8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* enable accel offset */
+ v_status_s8 = smi130_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ /* write accel manual offset compensation of y axis*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_1_ACCEL_OFF_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(
+ v_data_u8,
+ SMI130_USER_OFFSET_1_ACCEL_OFF_Y,
+ v_accel_off_y_s8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_1_ACCEL_OFF_Y__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read accel manual offset compensation of z axis
+ * from the register 0x73 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_z_s8:
+ * The value of accel manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_offset_compensation_zaxis(
+s8 *v_accel_off_z_s8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read accel manual offset compensation of z axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_2_ACCEL_OFF_Z__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_off_z_s8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_OFFSET_2_ACCEL_OFF_Z);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write accel manual offset compensation of z axis
+ * from the register 0x73 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_z_s8:
+ * The value of accel manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_offset_compensation_zaxis(
+s8 v_accel_off_z_s8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ u8 v_status_s8 = SUCCESS;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* enable accel offset */
+ v_status_s8 = smi130_set_accel_offset_enable(
+ ACCEL_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ /* write accel manual offset
+ compensation of z axis*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_2_ACCEL_OFF_Z__REG,
+ &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_OFFSET_2_ACCEL_OFF_Z,
+ v_accel_off_z_s8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_2_ACCEL_OFF_Z__REG,
+ &v_data_u8,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read gyro manual offset compensation of x axis
+ * from the register 0x74 bit 0 to 7 and 0x77 bit 0 and 1
+ *
+ *
+ *
+ * @param v_gyro_off_x_s16:
+ * The value of gyro manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_offset_compensation_xaxis(
+s16 *v_gyro_off_x_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data1_u8r = SMI130_INIT_VALUE;
+ u8 v_data2_u8r = SMI130_INIT_VALUE;
+ s16 v_data3_u8r, v_data4_u8r = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro offset x*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_3_GYRO_OFF_X__REG,
+ &v_data1_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data1_u8r = SMI130_GET_BITSLICE(v_data1_u8r,
+ SMI130_USER_OFFSET_3_GYRO_OFF_X);
+ com_rslt += p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_X__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data2_u8r = SMI130_GET_BITSLICE(v_data2_u8r,
+ SMI130_USER_OFFSET_6_GYRO_OFF_X);
+ v_data3_u8r = v_data2_u8r
+ << SMI130_SHIFT_BIT_POSITION_BY_14_BITS;
+ v_data4_u8r = v_data1_u8r
+ << SMI130_SHIFT_BIT_POSITION_BY_06_BITS;
+ v_data3_u8r = v_data3_u8r | v_data4_u8r;
+ *v_gyro_off_x_s16 = v_data3_u8r
+ >> SMI130_SHIFT_BIT_POSITION_BY_06_BITS;
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro manual offset compensation of x axis
+ * from the register 0x74 bit 0 to 7 and 0x77 bit 0 and 1
+ *
+ *
+ *
+ * @param v_gyro_off_x_s16:
+ * The value of gyro manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_offset_compensation_xaxis(
+s16 v_gyro_off_x_s16)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data1_u8r, v_data2_u8r = SMI130_INIT_VALUE;
+u16 v_data3_u8r = SMI130_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write gyro offset x*/
+ v_status_s8 = smi130_set_gyro_offset_enable(
+ GYRO_OFFSET_ENABLE);
+ if (v_status_s8 == SUCCESS) {
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_3_GYRO_OFF_X__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data1_u8r =
+ ((s8) (v_gyro_off_x_s16 &
+ SMI130_GYRO_MANUAL_OFFSET_0_7));
+ v_data2_u8r = SMI130_SET_BITSLICE(
+ v_data2_u8r,
+ SMI130_USER_OFFSET_3_GYRO_OFF_X,
+ v_data1_u8r);
+ /* write 0x74 bit 0 to 7*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_3_GYRO_OFF_X__REG,
+ &v_data2_u8r,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ com_rslt += p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_X__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u8r =
+ (u16) (v_gyro_off_x_s16 &
+ SMI130_GYRO_MANUAL_OFFSET_8_9);
+ v_data1_u8r = (u8)(v_data3_u8r
+ >> SMI130_SHIFT_BIT_POSITION_BY_08_BITS);
+ v_data2_u8r = SMI130_SET_BITSLICE(
+ v_data2_u8r,
+ SMI130_USER_OFFSET_6_GYRO_OFF_X,
+ v_data1_u8r);
+ /* write 0x77 bit 0 and 1*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_X__REG,
+ &v_data2_u8r,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ return ERROR;
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API read gyro manual offset compensation of y axis
+ * from the register 0x75 bit 0 to 7 and 0x77 bit 2 and 3
+ *
+ *
+ *
+ * @param v_gyro_off_y_s16:
+ * The value of gyro manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_offset_compensation_yaxis(
+s16 *v_gyro_off_y_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data1_u8r = SMI130_INIT_VALUE;
+ u8 v_data2_u8r = SMI130_INIT_VALUE;
+ s16 v_data3_u8r, v_data4_u8r = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro offset y*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_4_GYRO_OFF_Y__REG,
+ &v_data1_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data1_u8r = SMI130_GET_BITSLICE(v_data1_u8r,
+ SMI130_USER_OFFSET_4_GYRO_OFF_Y);
+ com_rslt += p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Y__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data2_u8r = SMI130_GET_BITSLICE(v_data2_u8r,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Y);
+ v_data3_u8r = v_data2_u8r
+ << SMI130_SHIFT_BIT_POSITION_BY_14_BITS;
+ v_data4_u8r = v_data1_u8r
+ << SMI130_SHIFT_BIT_POSITION_BY_06_BITS;
+ v_data3_u8r = v_data3_u8r | v_data4_u8r;
+ *v_gyro_off_y_s16 = v_data3_u8r
+ >> SMI130_SHIFT_BIT_POSITION_BY_06_BITS;
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro manual offset compensation of y axis
+ * from the register 0x75 bit 0 to 7 and 0x77 bit 2 and 3
+ *
+ *
+ *
+ * @param v_gyro_off_y_s16:
+ * The value of gyro manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_offset_compensation_yaxis(
+s16 v_gyro_off_y_s16)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data1_u8r, v_data2_u8r = SMI130_INIT_VALUE;
+u16 v_data3_u8r = SMI130_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* enable gyro offset bit */
+ v_status_s8 = smi130_set_gyro_offset_enable(
+ GYRO_OFFSET_ENABLE);
+ /* write gyro offset y*/
+ if (v_status_s8 == SUCCESS) {
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_4_GYRO_OFF_Y__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data1_u8r =
+ ((s8) (v_gyro_off_y_s16 &
+ SMI130_GYRO_MANUAL_OFFSET_0_7));
+ v_data2_u8r = SMI130_SET_BITSLICE(
+ v_data2_u8r,
+ SMI130_USER_OFFSET_4_GYRO_OFF_Y,
+ v_data1_u8r);
+ /* write 0x75 bit 0 to 7*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_4_GYRO_OFF_Y__REG,
+ &v_data2_u8r,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ com_rslt += p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Y__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u8r =
+ (u16) (v_gyro_off_y_s16 &
+ SMI130_GYRO_MANUAL_OFFSET_8_9);
+ v_data1_u8r = (u8)(v_data3_u8r
+ >> SMI130_SHIFT_BIT_POSITION_BY_08_BITS);
+ v_data2_u8r = SMI130_SET_BITSLICE(
+ v_data2_u8r,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Y,
+ v_data1_u8r);
+ /* write 0x77 bit 2 and 3*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Y__REG,
+ &v_data2_u8r,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ return ERROR;
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API read gyro manual offset compensation of z axis
+ * from the register 0x76 bit 0 to 7 and 0x77 bit 4 and 5
+ *
+ *
+ *
+ * @param v_gyro_off_z_s16:
+ * The value of gyro manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_offset_compensation_zaxis(
+s16 *v_gyro_off_z_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data1_u8r = SMI130_INIT_VALUE;
+ u8 v_data2_u8r = SMI130_INIT_VALUE;
+ s16 v_data3_u8r, v_data4_u8r = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro manual offset z axis*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_5_GYRO_OFF_Z__REG,
+ &v_data1_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data1_u8r = SMI130_GET_BITSLICE
+ (v_data1_u8r,
+ SMI130_USER_OFFSET_5_GYRO_OFF_Z);
+ com_rslt +=
+ p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Z__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data2_u8r = SMI130_GET_BITSLICE(
+ v_data2_u8r,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Z);
+ v_data3_u8r = v_data2_u8r
+ << SMI130_SHIFT_BIT_POSITION_BY_14_BITS;
+ v_data4_u8r = v_data1_u8r
+ << SMI130_SHIFT_BIT_POSITION_BY_06_BITS;
+ v_data3_u8r = v_data3_u8r | v_data4_u8r;
+ *v_gyro_off_z_s16 = v_data3_u8r
+ >> SMI130_SHIFT_BIT_POSITION_BY_06_BITS;
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write gyro manual offset compensation of z axis
+ * from the register 0x76 bit 0 to 7 and 0x77 bit 4 and 5
+ *
+ *
+ *
+ * @param v_gyro_off_z_s16:
+ * The value of gyro manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_offset_compensation_zaxis(
+s16 v_gyro_off_z_s16)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data1_u8r, v_data2_u8r = SMI130_INIT_VALUE;
+u16 v_data3_u8r = SMI130_INIT_VALUE;
+u8 v_status_s8 = SUCCESS;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* enable gyro offset*/
+ v_status_s8 = smi130_set_gyro_offset_enable(
+ GYRO_OFFSET_ENABLE);
+ /* write gyro manual offset z axis*/
+ if (v_status_s8 == SUCCESS) {
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_5_GYRO_OFF_Z__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data1_u8r =
+ ((u8) (v_gyro_off_z_s16 &
+ SMI130_GYRO_MANUAL_OFFSET_0_7));
+ v_data2_u8r = SMI130_SET_BITSLICE(
+ v_data2_u8r,
+ SMI130_USER_OFFSET_5_GYRO_OFF_Z,
+ v_data1_u8r);
+ /* write 0x76 bit 0 to 7*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_5_GYRO_OFF_Z__REG,
+ &v_data2_u8r,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ com_rslt += p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Z__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u8r =
+ (u16) (v_gyro_off_z_s16 &
+ SMI130_GYRO_MANUAL_OFFSET_8_9);
+ v_data1_u8r = (u8)(v_data3_u8r
+ >> SMI130_SHIFT_BIT_POSITION_BY_08_BITS);
+ v_data2_u8r = SMI130_SET_BITSLICE(
+ v_data2_u8r,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Z,
+ v_data1_u8r);
+ /* write 0x77 bit 4 and 5*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_Z__REG,
+ &v_data2_u8r,
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ return ERROR;
+ }
+ }
+return com_rslt;
+}
+/*!
+ * @brief This API read the accel offset enable bit
+ * from the register 0x77 bit 6
+ *
+ *
+ *
+ * @param v_accel_off_enable_u8: The value of accel offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_offset_enable(
+u8 *v_accel_off_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read accel offset enable */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_ACCEL_OFF_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_accel_off_enable_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_OFFSET_6_ACCEL_OFF_ENABLE);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write the accel offset enable bit
+ * from the register 0x77 bit 6
+ *
+ *
+ *
+ * @param v_accel_off_enable_u8: The value of accel offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_offset_enable(
+u8 v_accel_off_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write accel offset enable */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_ACCEL_OFF_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_OFFSET_6_ACCEL_OFF_ENABLE,
+ v_accel_off_enable_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_ACCEL_OFF_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API read the accel offset enable bit
+ * from the register 0x77 bit 7
+ *
+ *
+ *
+ * @param v_gyro_off_enable_u8: The value of gyro offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_offset_enable(
+u8 *v_gyro_off_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read gyro offset*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_EN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_gyro_off_enable_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_OFFSET_6_GYRO_OFF_EN);
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API write the accel offset enable bit
+ * from the register 0x77 bit 7
+ *
+ *
+ *
+ * @param v_gyro_off_enable_u8: The value of gyro offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_offset_enable(
+u8 v_gyro_off_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write gyro offset*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_EN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 = SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_OFFSET_6_GYRO_OFF_EN,
+ v_gyro_off_enable_u8);
+ com_rslt += p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_OFFSET_6_GYRO_OFF_EN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API reads step counter value
+ * form the register 0x78 and 0x79
+ *
+ *
+ *
+ *
+ * @param v_step_cnt_s16 : The value of step counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_step_count(u16 *v_step_cnt_s16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* array having the step counter LSB and MSB data
+ v_data_u8[0] - LSB
+ v_data_u8[1] - MSB*/
+ u8 a_data_u8r[SMI130_STEP_COUNT_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read step counter */
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STEP_COUNT_LSB__REG,
+ a_data_u8r, SMI130_STEP_COUNTER_LENGTH);
+
+ *v_step_cnt_s16 = (s16)
+ ((((s32)((s8)a_data_u8r[SMI130_STEP_COUNT_MSB_BYTE]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8r[SMI130_STEP_COUNT_LSB_BYTE]));
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API Reads
+ * step counter configuration
+ * from the register 0x7A bit 0 to 7
+ * and from the register 0x7B bit 0 to 2 and 4 to 7
+ *
+ *
+ * @param v_step_config_u16 : The value of step configuration
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_step_config(
+u16 *v_step_config_u16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data1_u8r = SMI130_INIT_VALUE;
+ u8 v_data2_u8r = SMI130_INIT_VALUE;
+ u16 v_data3_u8r = SMI130_INIT_VALUE;
+ /* Read the 0 to 7 bit*/
+ com_rslt =
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_ZERO__REG,
+ &v_data1_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* Read the 8 to 10 bit*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_ONE_CNF1__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data2_u8r = SMI130_GET_BITSLICE(v_data2_u8r,
+ SMI130_USER_STEP_CONFIG_ONE_CNF1);
+ v_data3_u8r = ((u16)((((u32)
+ ((u8)v_data2_u8r))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | (v_data1_u8r)));
+ /* Read the 11 to 14 bit*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_ONE_CNF2__REG,
+ &v_data1_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data1_u8r = SMI130_GET_BITSLICE(v_data1_u8r,
+ SMI130_USER_STEP_CONFIG_ONE_CNF2);
+ *v_step_config_u16 = ((u16)((((u32)
+ ((u8)v_data1_u8r))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | (v_data3_u8r)));
+
+ return com_rslt;
+}
+ /*!
+ * @brief This API write
+ * step counter configuration
+ * from the register 0x7A bit 0 to 7
+ * and from the register 0x7B bit 0 to 2 and 4 to 7
+ *
+ *
+ * @param v_step_config_u16 :
+ * the value of Enable step configuration
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_step_config(
+u16 v_step_config_u16)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data1_u8r = SMI130_INIT_VALUE;
+ u8 v_data2_u8r = SMI130_INIT_VALUE;
+ u16 v_data3_u16 = SMI130_INIT_VALUE;
+
+ /* write the 0 to 7 bit*/
+ v_data1_u8r = (u8)(v_step_config_u16 &
+ SMI130_STEP_CONFIG_0_7);
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_ZERO__REG,
+ &v_data1_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* write the 8 to 10 bit*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_ONE_CNF1__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u16 = (u16) (v_step_config_u16 &
+ SMI130_STEP_CONFIG_8_10);
+ v_data1_u8r = (u8)(v_data3_u16
+ >> SMI130_SHIFT_BIT_POSITION_BY_08_BITS);
+ v_data2_u8r = SMI130_SET_BITSLICE(v_data2_u8r,
+ SMI130_USER_STEP_CONFIG_ONE_CNF1, v_data1_u8r);
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_ONE_CNF1__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ /* write the 11 to 14 bit*/
+ com_rslt += p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_ONE_CNF2__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data3_u16 = (u16) (v_step_config_u16 &
+ SMI130_STEP_CONFIG_11_14);
+ v_data1_u8r = (u8)(v_data3_u16
+ >> SMI130_SHIFT_BIT_POSITION_BY_12_BITS);
+ v_data2_u8r = SMI130_SET_BITSLICE(v_data2_u8r,
+ SMI130_USER_STEP_CONFIG_ONE_CNF2, v_data1_u8r);
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_ONE_CNF2__REG,
+ &v_data2_u8r, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+
+ return com_rslt;
+}
+ /*!
+ * @brief This API read enable step counter
+ * from the register 0x7B bit 3
+ *
+ *
+ * @param v_step_counter_u8 : The value of step counter enable
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_step_counter_enable(
+u8 *v_step_counter_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the step counter */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_step_counter_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write enable step counter
+ * from the register 0x7B bit 3
+ *
+ *
+ * @param v_step_counter_u8 : The value of step counter enable
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_step_counter_enable(u8 v_step_counter_u8)
+{
+/* variable used for return the status of communication result*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+/* check the p_smi130 structure as NULL*/
+if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+} else {
+ if (v_step_counter_u8 <= SMI130_MAX_GYRO_STEP_COUNTER) {
+ /* write the step counter */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE,
+ v_step_counter_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+}
+ return com_rslt;
+}
+ /*!
+ * @brief This API set Step counter modes
+ *
+ *
+ * @param v_step_mode_u8 : The value of step counter mode
+ * value | mode
+ * ----------|-----------
+ * 0 | SMI130_STEP_NORMAL_MODE
+ * 1 | SMI130_STEP_SENSITIVE_MODE
+ * 2 | SMI130_STEP_ROBUST_MODE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_step_mode(u8 v_step_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+
+ switch (v_step_mode_u8) {
+ case SMI130_STEP_NORMAL_MODE:
+ com_rslt = smi130_set_step_config(
+ STEP_CONFIG_NORMAL);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ case SMI130_STEP_SENSITIVE_MODE:
+ com_rslt = smi130_set_step_config(
+ STEP_CONFIG_SENSITIVE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ case SMI130_STEP_ROBUST_MODE:
+ com_rslt = smi130_set_step_config(
+ STEP_CONFIG_ROBUST);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+
+ return com_rslt;
+}
+/*!
+ * @brief This API used to trigger the signification motion
+ * interrupt
+ *
+ *
+ * @param v_significant_u8 : The value of interrupt selection
+ * value | interrupt
+ * ----------|-----------
+ * 0 | SMI130_MAP_INTR1
+ * 1 | SMI130_MAP_INTR2
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_map_significant_motion_intr(
+u8 v_significant_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_sig_motion_u8 = SMI130_INIT_VALUE;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ u8 v_any_motion_intr1_stat_u8 = SMI130_ENABLE_ANY_MOTION_INTR1;
+ u8 v_any_motion_intr2_stat_u8 = SMI130_ENABLE_ANY_MOTION_INTR2;
+ u8 v_any_motion_axis_stat_u8 = SMI130_ENABLE_ANY_MOTION_AXIS;
+ /* enable the significant motion interrupt */
+ com_rslt = smi130_get_intr_significant_motion_select(&v_sig_motion_u8);
+ if (v_sig_motion_u8 != SMI130_SIG_MOTION_STAT_HIGH)
+ com_rslt += smi130_set_intr_significant_motion_select(
+ SMI130_SIG_MOTION_INTR_ENABLE);
+ switch (v_significant_u8) {
+ case SMI130_MAP_INTR1:
+ /* interrupt */
+ com_rslt += smi130_read_reg(
+ SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_any_motion_intr1_stat_u8;
+ /* map the signification interrupt to any-motion interrupt1*/
+ com_rslt += smi130_write_reg(
+ SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* axis*/
+ com_rslt = smi130_read_reg(SMI130_USER_INTR_ENABLE_0_ADDR,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_any_motion_axis_stat_u8;
+ com_rslt += smi130_write_reg(
+ SMI130_USER_INTR_ENABLE_0_ADDR,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+
+ case SMI130_MAP_INTR2:
+ /* map the signification interrupt to any-motion interrupt2*/
+ com_rslt += smi130_read_reg(
+ SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_any_motion_intr2_stat_u8;
+ com_rslt += smi130_write_reg(
+ SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* axis*/
+ com_rslt = smi130_read_reg(SMI130_USER_INTR_ENABLE_0_ADDR,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_any_motion_axis_stat_u8;
+ com_rslt += smi130_write_reg(
+ SMI130_USER_INTR_ENABLE_0_ADDR,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This API used to trigger the step detector
+ * interrupt
+ *
+ *
+ * @param v_step_detector_u8 : The value of interrupt selection
+ * value | interrupt
+ * ----------|-----------
+ * 0 | SMI130_MAP_INTR1
+ * 1 | SMI130_MAP_INTR2
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_map_step_detector_intr(
+u8 v_step_detector_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_step_det_u8 = SMI130_INIT_VALUE;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ u8 v_low_g_intr_u81_stat_u8 = SMI130_LOW_G_INTR_STAT;
+ u8 v_low_g_intr_u82_stat_u8 = SMI130_LOW_G_INTR_STAT;
+ u8 v_low_g_enable_u8 = SMI130_ENABLE_LOW_G;
+ /* read the v_status_s8 of step detector interrupt*/
+ com_rslt = smi130_get_step_detector_enable(&v_step_det_u8);
+ if (v_step_det_u8 != SMI130_STEP_DET_STAT_HIGH)
+ com_rslt += smi130_set_step_detector_enable(
+ SMI130_STEP_DETECT_INTR_ENABLE);
+ switch (v_step_detector_u8) {
+ case SMI130_MAP_INTR1:
+ com_rslt += smi130_read_reg(
+ SMI130_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_low_g_intr_u81_stat_u8;
+ /* map the step detector interrupt
+ to Low-g interrupt 1*/
+ com_rslt += smi130_write_reg(
+ SMI130_USER_INTR_MAP_0_INTR1_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* Enable the Low-g interrupt*/
+ com_rslt = smi130_read_reg(
+ SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_low_g_enable_u8;
+ com_rslt += smi130_write_reg(
+ SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ case SMI130_MAP_INTR2:
+ /* map the step detector interrupt
+ to Low-g interrupt 1*/
+ com_rslt += smi130_read_reg(
+ SMI130_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_low_g_intr_u82_stat_u8;
+
+ com_rslt += smi130_write_reg(
+ SMI130_USER_INTR_MAP_2_INTR2_LOW_G__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* Enable the Low-g interrupt*/
+ com_rslt = smi130_read_reg(
+ SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_data_u8 |= v_low_g_enable_u8;
+ com_rslt += smi130_write_reg(
+ SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API used to clear the step counter interrupt
+ * interrupt
+ *
+ *
+ * @param : None
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_clear_step_counter(void)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* clear the step counter*/
+ com_rslt = smi130_set_command_register(RESET_STEP_COUNTER);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+
+}
+ /*!
+ * @brief This API writes value to the register 0x7E bit 0 to 7
+ *
+ *
+ * @param v_command_reg_u8 : The value to write command register
+ * value | Description
+ * ---------|--------------------------------------------------------
+ * 0x00 | Reserved
+ * 0x03 | Starts fast offset calibration for the accel and gyro
+ * 0x10 | Sets the PMU mode for the Accelerometer to suspend
+ * 0x11 | Sets the PMU mode for the Accelerometer to normal
+ * 0x12 | Sets the PMU mode for the Accelerometer Lowpower
+ * 0x14 | Sets the PMU mode for the Gyroscope to suspend
+ * 0x15 | Sets the PMU mode for the Gyroscope to normal
+ * 0x16 | Reserved
+ * 0x17 | Sets the PMU mode for the Gyroscope to fast start-up
+ * 0x18 | Sets the PMU mode for the Magnetometer to suspend
+ * 0x19 | Sets the PMU mode for the Magnetometer to normal
+ * 0x1A | Sets the PMU mode for the Magnetometer to Lowpower
+ * 0xB0 | Clears all data in the FIFO
+ * 0xB1 | Resets the interrupt engine
+ * 0xB2 | step_cnt_clr Clears the step counter
+ * 0xB6 | Triggers a reset
+ * 0x37 | See extmode_en_last
+ * 0x9A | See extmode_en_last
+ * 0xC0 | Enable the extended mode
+ * 0xC4 | Erase NVM cell
+ * 0xC8 | Load NVM cell
+ * 0xF0 | Reset acceleration data path
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_command_register(u8 v_command_reg_u8)
+{
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write command register */
+ com_rslt = p_smi130->SMI130_BUS_WRITE_FUNC(
+ p_smi130->dev_addr,
+ SMI130_CMD_COMMANDS__REG,
+ &v_command_reg_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read target page from the register 0x7F bit 4 and 5
+ *
+ * @param v_target_page_u8: The value of target page
+ * value | page
+ * ---------|-----------
+ * 0 | User data/configure page
+ * 1 | Chip level trim/test page
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_target_page(u8 *v_target_page_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the page*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_CMD_TARGET_PAGE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_target_page_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_CMD_TARGET_PAGE);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write target page from the register 0x7F bit 4 and 5
+ *
+ * @param v_target_page_u8: The value of target page
+ * value | page
+ * ---------|-----------
+ * 0 | User data/configure page
+ * 1 | Chip level trim/test page
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_target_page(u8 v_target_page_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_target_page_u8 <= SMI130_MAX_TARGET_PAGE) {
+ /* write the page*/
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_CMD_TARGET_PAGE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_CMD_TARGET_PAGE,
+ v_target_page_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_CMD_TARGET_PAGE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read page enable from the register 0x7F bit 7
+ *
+ *
+ *
+ * @param v_page_enable_u8: The value of page enable
+ * value | page
+ * ---------|-----------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_paging_enable(u8 *v_page_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the page enable */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_CMD_PAGING_EN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_page_enable_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_CMD_PAGING_EN);
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API write page enable from the register 0x7F bit 7
+ *
+ *
+ *
+ * @param v_page_enable_u8: The value of page enable
+ * value | page
+ * ---------|-----------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_paging_enable(
+u8 v_page_enable_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ if (v_page_enable_u8 <= SMI130_MAX_VALUE_PAGE) {
+ /* write the page enable */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_CMD_PAGING_EN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_CMD_PAGING_EN,
+ v_page_enable_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_CMD_PAGING_EN__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ } else {
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ }
+ }
+ return com_rslt;
+}
+ /*!
+ * @brief This API read
+ * pull up configuration from the register 0X85 bit 4 an 5
+ *
+ *
+ *
+ * @param v_control_pullup_u8: The value of pull up register
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_pullup_configuration(
+u8 *v_control_pullup_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read pull up value */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC(
+ p_smi130->dev_addr,
+ SMI130_COM_C_TRIM_FIVE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ *v_control_pullup_u8 = SMI130_GET_BITSLICE(v_data_u8,
+ SMI130_COM_C_TRIM_FIVE);
+ }
+ return com_rslt;
+
+}
+ /*!
+ * @brief This API write
+ * pull up configuration from the register 0X85 bit 4 an 5
+ *
+ *
+ *
+ * @param v_control_pullup_u8: The value of pull up register
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_pullup_configuration(
+u8 v_control_pullup_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* write pull up value */
+ com_rslt = p_smi130->SMI130_BUS_READ_FUNC
+ (p_smi130->dev_addr,
+ SMI130_COM_C_TRIM_FIVE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ if (com_rslt == SUCCESS) {
+ v_data_u8 =
+ SMI130_SET_BITSLICE(v_data_u8,
+ SMI130_COM_C_TRIM_FIVE,
+ v_control_pullup_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_WRITE_FUNC
+ (p_smi130->dev_addr,
+ SMI130_COM_C_TRIM_FIVE__REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ }
+ }
+ return com_rslt;
+}
+
+/*!
+ * @brief This function used for read the compensated value of mag
+ * Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_compensate_xyz(
+struct smi130_mag_xyz_s32_t *mag_comp_xyz)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ struct smi130_mag_xyzr_t mag_xyzr;
+ com_rslt = smi130_read_mag_xyzr(&mag_xyzr);
+ if (com_rslt)
+ return com_rslt;
+ /* Compensation for X axis */
+ mag_comp_xyz->x = smi130_bmm150_mag_compensate_X(
+ mag_xyzr.x, mag_xyzr.r);
+
+ /* Compensation for Y axis */
+ mag_comp_xyz->y = smi130_bmm150_mag_compensate_Y(
+ mag_xyzr.y, mag_xyzr.r);
+
+ /* Compensation for Z axis */
+ mag_comp_xyz->z = smi130_bmm150_mag_compensate_Z(
+ mag_xyzr.z, mag_xyzr.r);
+
+ return com_rslt;
+}
+
+/*!
+ * @brief This function used for read the compensated value of mag
+ * Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_compensate_xyz_raw(
+struct smi130_mag_xyz_s32_t *mag_comp_xyz, struct smi130_mag_xyzr_t mag_xyzr)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+
+ /* Compensation for X axis */
+ mag_comp_xyz->x = smi130_bmm150_mag_compensate_X(
+ mag_xyzr.x, mag_xyzr.r);
+
+ /* Compensation for Y axis */
+ mag_comp_xyz->y = smi130_bmm150_mag_compensate_Y(
+ mag_xyzr.y, mag_xyzr.r);
+
+ /* Compensation for Z axis */
+ mag_comp_xyz->z = smi130_bmm150_mag_compensate_Z(
+ mag_xyzr.z, mag_xyzr.r);
+
+ return com_rslt;
+}
+/*!
+ * @brief This API used to get the compensated BMM150-X data
+ * the out put of X as s32
+ * Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_x_s16 : The value of mag raw X data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 smi130_bmm150_mag_compensate_X(s16 v_mag_data_x_s16, u16 v_data_r_u16)
+{
+s32 inter_retval = SMI130_INIT_VALUE;
+/* no overflow */
+if (v_mag_data_x_s16 != SMI130_MAG_FLIP_OVERFLOW_ADCVAL) {
+ if ((v_data_r_u16 != 0)
+ && (mag_trim_mbl.dig_xyz1 != 0)) {
+ inter_retval = ((s32)(((u16)
+ ((((s32)mag_trim_mbl.dig_xyz1)
+ << SMI130_SHIFT_BIT_POSITION_BY_14_BITS)/
+ (v_data_r_u16 != 0 ?
+ v_data_r_u16 : mag_trim_mbl.dig_xyz1))) -
+ ((u16)0x4000)));
+ } else {
+ inter_retval = SMI130_MAG_OVERFLOW_OUTPUT;
+ return inter_retval;
+ }
+ inter_retval = ((s32)((((s32)v_mag_data_x_s16) *
+ ((((((((s32)mag_trim_mbl.dig_xy2) *
+ ((((s32)inter_retval) *
+ ((s32)inter_retval))
+ >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS)) +
+ (((s32)inter_retval) *
+ ((s32)(((s16)mag_trim_mbl.dig_xy1)
+ << SMI130_SHIFT_BIT_POSITION_BY_07_BITS))))
+ >> SMI130_SHIFT_BIT_POSITION_BY_09_BITS) +
+ ((s32)0x100000)) *
+ ((s32)(((s16)mag_trim_mbl.dig_x2) +
+ ((s16)0xA0))))
+ >> SMI130_SHIFT_BIT_POSITION_BY_12_BITS))
+ >> SMI130_SHIFT_BIT_POSITION_BY_13_BITS)) +
+ (((s16)mag_trim_mbl.dig_x1)
+ << SMI130_SHIFT_BIT_POSITION_BY_03_BITS);
+ /* check the overflow output */
+ if (inter_retval == (s32)SMI130_MAG_OVERFLOW_OUTPUT)
+ inter_retval = SMI130_MAG_OVERFLOW_OUTPUT_S32;
+} else {
+ /* overflow */
+ inter_retval = SMI130_MAG_OVERFLOW_OUTPUT;
+}
+return inter_retval;
+}
+/*!
+ * @brief This API used to get the compensated BMM150-Y data
+ * the out put of Y as s32
+ * Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_y_s16 : The value of mag raw Y data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated Y data value output as s32
+ */
+s32 smi130_bmm150_mag_compensate_Y(s16 v_mag_data_y_s16, u16 v_data_r_u16)
+{
+s32 inter_retval = SMI130_INIT_VALUE;
+/* no overflow */
+if (v_mag_data_y_s16 != SMI130_MAG_FLIP_OVERFLOW_ADCVAL) {
+ if ((v_data_r_u16 != 0)
+ && (mag_trim_mbl.dig_xyz1 != 0)) {
+ inter_retval = ((s32)(((u16)(((
+ (s32)mag_trim_mbl.dig_xyz1)
+ << SMI130_SHIFT_BIT_POSITION_BY_14_BITS) /
+ (v_data_r_u16 != 0 ?
+ v_data_r_u16 : mag_trim_mbl.dig_xyz1))) -
+ ((u16)0x4000)));
+ } else {
+ inter_retval = SMI130_MAG_OVERFLOW_OUTPUT;
+ return inter_retval;
+ }
+ inter_retval = ((s32)((((s32)v_mag_data_y_s16) * ((((((((s32)
+ mag_trim_mbl.dig_xy2) * ((((s32) inter_retval) *
+ ((s32)inter_retval)) >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS))
+ + (((s32)inter_retval) *
+ ((s32)(((s16)mag_trim_mbl.dig_xy1)
+ << SMI130_SHIFT_BIT_POSITION_BY_07_BITS))))
+ >> SMI130_SHIFT_BIT_POSITION_BY_09_BITS) +
+ ((s32)0x100000))
+ * ((s32)(((s16)mag_trim_mbl.dig_y2)
+ + ((s16)0xA0))))
+ >> SMI130_SHIFT_BIT_POSITION_BY_12_BITS))
+ >> SMI130_SHIFT_BIT_POSITION_BY_13_BITS)) +
+ (((s16)mag_trim_mbl.dig_y1)
+ << SMI130_SHIFT_BIT_POSITION_BY_03_BITS);
+ /* check the overflow output */
+ if (inter_retval == (s32)SMI130_MAG_OVERFLOW_OUTPUT)
+ inter_retval = SMI130_MAG_OVERFLOW_OUTPUT_S32;
+} else {
+ /* overflow */
+ inter_retval = SMI130_MAG_OVERFLOW_OUTPUT;
+}
+return inter_retval;
+}
+/*!
+ * @brief This API used to get the compensated BMM150-Z data
+ * the out put of Z as s32
+ * Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_z_s16 : The value of mag raw Z data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated Z data value output as s32
+ */
+s32 smi130_bmm150_mag_compensate_Z(s16 v_mag_data_z_s16, u16 v_data_r_u16)
+{
+ s32 retval = SMI130_INIT_VALUE;
+
+ if (v_mag_data_z_s16 != SMI130_MAG_HALL_OVERFLOW_ADCVAL) {
+ if ((v_data_r_u16 != 0)
+ && (mag_trim_mbl.dig_z2 != 0)
+ /* && (mag_trim_mbl.dig_z3 != 0)*/
+ && (mag_trim_mbl.dig_z1 != 0)
+ && (mag_trim_mbl.dig_xyz1 != 0)) {
+ retval = (((((s32)(v_mag_data_z_s16 - mag_trim_mbl.dig_z4))
+ << SMI130_SHIFT_BIT_POSITION_BY_15_BITS) -
+ ((((s32)mag_trim_mbl.dig_z3) *
+ ((s32)(((s16)v_data_r_u16) -
+ ((s16)mag_trim_mbl.dig_xyz1))))
+ >> SMI130_SHIFT_BIT_POSITION_BY_02_BITS))/
+ (mag_trim_mbl.dig_z2 +
+ ((s16)(((((s32)mag_trim_mbl.dig_z1) *
+ ((((s16)v_data_r_u16)
+ << SMI130_SHIFT_BIT_POSITION_BY_01_BIT))) +
+ (1 << SMI130_SHIFT_BIT_POSITION_BY_15_BITS))
+ >> SMI130_SHIFT_BIT_POSITION_BY_16_BITS))));
+ }
+ } else {
+ retval = SMI130_MAG_OVERFLOW_OUTPUT;
+ }
+ return retval;
+}
+ /*!
+ * @brief This function used for initialize the bmm150 sensor
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_interface_init(void)
+{
+ /* This variable used for provide the communication
+ results*/
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = SMI130_INIT_VALUE;
+ u8 v_pull_value_u8 = SMI130_INIT_VALUE;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ /* accel operation mode to normal*/
+ com_rslt = smi130_set_command_register(ACCEL_MODE_NORMAL);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* write the mag power mode as NORMAL*/
+ com_rslt += smi130_set_mag_interface_normal();
+
+ /* register 0x7E write the 0x37, 0x9A and 0x30*/
+ com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_ONE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_TWO);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_THREE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /*switch the page1*/
+ com_rslt += smi130_set_target_page(SMI130_WRITE_TARGET_PAGE1);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_target_page(&v_data_u8);
+ com_rslt += smi130_set_paging_enable(SMI130_WRITE_ENABLE_PAGE1);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_paging_enable(&v_data_u8);
+ /* enable the pullup configuration from
+ the register 0x05 bit 4 and 5 as 10*/
+ smi130_get_pullup_configuration(&v_pull_value_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ v_pull_value_u8 = v_pull_value_u8 | SMI130_PULL_UP_DATA;
+ com_rslt += smi130_set_pullup_configuration(v_pull_value_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /*switch the page0*/
+ com_rslt += smi130_set_target_page(SMI130_WRITE_TARGET_PAGE0);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_target_page(&v_data_u8);
+ /* Write the BMM150 i2c address*/
+ com_rslt += smi130_set_i2c_device_addr(SMI130_AUX_BMM150_I2C_ADDRESS);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* enable the mag interface to manual mode*/
+ com_rslt += smi130_set_mag_manual_enable(SMI130_MANUAL_ENABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_mag_manual_enable(&v_data_u8);
+ /*Enable the MAG interface */
+ com_rslt += smi130_set_if_mode(SMI130_ENABLE_MAG_IF_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_if_mode(&v_data_u8);
+ /* Mag normal mode*/
+ com_rslt += smi130_bmm150_mag_wakeup();
+ printk(KERN_INFO "com_rslt:%d, <%s><%d>\n",
+ com_rslt, __func__, __LINE__);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* Read the BMM150 device id is 0x32*/
+ /*com_rslt += smi130_set_mag_read_addr(SMI130_BMM150_CHIP_ID);*/
+ /*p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);*/
+ /*com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);*/
+ /**v_chip_id_u8 = v_data_u8;*/
+ /*p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);*/
+ /* write the power mode register*/
+ com_rslt += smi130_set_mag_write_data(SMI130_BMM_POWER_MODE_REG);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /*write 0x4C register to write set power mode to normal*/
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_POWE_MODE_REG);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* read the mag trim values*/
+ com_rslt += smi130_read_bmm150_mag_trim_mbl();
+ printk(KERN_INFO "com_rslt:%d, <%s><%d>\n",
+ com_rslt, __func__, __LINE__);
+ /* To avoid the auto mode enable when manual mode operation running*/
+ V_bmm150_maual_auto_condition_u8_mbl = SMI130_MANUAL_ENABLE;
+ /* write the XY and Z repetitions*/
+ com_rslt += smi130_set_bmm150_mag_presetmode(
+ SMI130_MAG_PRESETMODE_REGULAR);
+ printk(KERN_INFO "com_rslt:%d, <%s><%d>\n",
+ com_rslt, __func__, __LINE__);
+ /* To avoid the auto mode enable when manual mode operation running*/
+ V_bmm150_maual_auto_condition_u8_mbl = SMI130_MANUAL_DISABLE;
+ /* Set the power mode of mag as force mode*/
+ /* The data have to write for the register
+ It write the value in the register 0x4F */
+ com_rslt += smi130_set_mag_write_data(SMI130_BMM150_FORCE_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ printk(KERN_INFO "com_rslt:%d, <%s><%d>\n",
+ com_rslt, __func__, __LINE__);
+ /* write into power mode register*/
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_POWE_MODE_REG);
+ /* write the mag v_data_bw_u8 as 25Hz*/
+ com_rslt += smi130_set_mag_output_data_rate(
+ SMI130_MAG_OUTPUT_DATA_RATE_25HZ);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ /* When mag interface is auto mode - The mag read address
+ starts the register 0x42*/
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_BMM150_DATA_REG);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* enable mag interface to auto mode*/
+ com_rslt += smi130_set_mag_manual_enable(SMI130_MANUAL_DISABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_mag_manual_enable(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for set the mag power control
+ * bit enable
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_wakeup(void)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = SMI130_INIT_VALUE;
+ u8 v_try_times_u8 = SMI130_BMM150_MAX_RETRY_WAKEUP;
+ u8 v_power_control_bit_u8 = SMI130_INIT_VALUE;
+ u8 i = SMI130_INIT_VALUE;
+
+ for (i = SMI130_INIT_VALUE; i < v_try_times_u8; i++) {
+ com_rslt = smi130_set_mag_write_data(SMI130_BMM150_POWER_ON);
+ p_smi130->delay_msec(SMI130_BMM150_WAKEUP_DELAY1);
+ /*write 0x4B register to enable power control bit*/
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_POWE_CONTROL_REG);
+ p_smi130->delay_msec(SMI130_BMM150_WAKEUP_DELAY2);
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_BMM150_POWE_CONTROL_REG);
+ /* 0x04 is secondary read mag x lsb register */
+ p_smi130->delay_msec(SMI130_BMM150_WAKEUP_DELAY3);
+ com_rslt += smi130_read_reg(SMI130_USER_DATA_0_ADDR,
+ &v_power_control_bit_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ v_power_control_bit_u8 = SMI130_BMM150_SET_POWER_CONTROL
+ & v_power_control_bit_u8;
+ if (v_power_control_bit_u8 == SMI130_BMM150_POWER_ON)
+ break;
+ }
+ com_rslt = (i >= v_try_times_u8) ?
+ SMI130_BMM150_POWER_ON_FAIL : SMI130_BMM150_POWER_ON_SUCCESS;
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for set the magnetometer
+ * power mode.
+ * @note
+ * Before set the mag power mode
+ * make sure the following two point is addressed
+ * Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ *
+ * @param v_mag_sec_if_pow_mode_u8 : The value of mag power mode
+ * value | mode
+ * ----------|------------
+ * 0 | SMI130_MAG_FORCE_MODE
+ * 1 | SMI130_MAG_SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_bmm150_mag_and_secondary_if_power_mode(
+u8 v_mag_sec_if_pow_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = SMI130_INIT_VALUE;
+ /* set the accel power mode to NORMAL*/
+ com_rslt = smi130_set_command_register(ACCEL_MODE_NORMAL);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ /* set mag interface manual mode*/
+ if (p_smi130->mag_manual_enable != SMI130_MANUAL_ENABLE) {
+ com_rslt += smi130_set_mag_manual_enable(
+ SMI130_MANUAL_ENABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+
+ switch (v_mag_sec_if_pow_mode_u8) {
+ case SMI130_MAG_FORCE_MODE:
+ /* set the secondary mag power mode as NORMAL*/
+ com_rslt += smi130_set_mag_interface_normal();
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ /* set the mag power mode as FORCE mode*/
+ com_rslt += smi130_bmm150_mag_set_power_mode(FORCE_MODE);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ case SMI130_MAG_SUSPEND_MODE:
+ /* set the mag power mode as SUSPEND mode*/
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ com_rslt += smi130_bmm150_mag_set_power_mode(SUSPEND_MODE);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* set the secondary mag power mode as SUSPEND*/
+ com_rslt += smi130_set_command_register(MAG_MODE_SUSPEND);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ if (p_smi130->mag_manual_enable == SMI130_MANUAL_ENABLE) {
+ /* set mag interface auto mode*/
+ com_rslt += smi130_set_mag_manual_enable(
+ SMI130_MANUAL_DISABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ return com_rslt;
+}
+/*!
+ * @brief This function used for set the magnetometer
+ * power mode.
+ * @note
+ * Before set the mag power mode
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @param v_mag_pow_mode_u8 : The value of mag power mode
+ * value | mode
+ * ----------|------------
+ * 0 | FORCE_MODE
+ * 1 | SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_set_power_mode(
+u8 v_mag_pow_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = SMI130_INIT_VALUE;
+ u8 manual_enable_status = 0;
+ /* set mag interface manual mode*/
+ if (p_smi130->mag_manual_enable != SMI130_MANUAL_ENABLE) {
+ com_rslt = smi130_set_mag_manual_enable(
+ SMI130_MANUAL_ENABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_get_mag_manual_enable(&manual_enable_status);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ printk(KERN_INFO "1com_rslt:%d, manual:%d, manual_read:%d\n",
+ com_rslt, p_smi130->mag_manual_enable, manual_enable_status);
+ }
+ printk(KERN_INFO "2com_rslt:%d, manual:%d, manual_read:%d\n",
+ com_rslt, p_smi130->mag_manual_enable, manual_enable_status);
+
+ switch (v_mag_pow_mode_u8) {
+ case FORCE_MODE:
+ /* Set the power control bit enabled */
+ com_rslt = smi130_bmm150_mag_wakeup();
+ /* write the mag power mode as FORCE mode*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_BMM150_FORCE_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_POWE_MODE_REG);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* To avoid the auto mode enable when manual
+ mode operation running*/
+ V_bmm150_maual_auto_condition_u8_mbl = SMI130_MANUAL_ENABLE;
+ /* set the preset mode */
+ com_rslt += smi130_set_bmm150_mag_presetmode(
+ SMI130_MAG_PRESETMODE_REGULAR);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* To avoid the auto mode enable when manual
+ mode operation running*/
+ V_bmm150_maual_auto_condition_u8_mbl = SMI130_MANUAL_DISABLE;
+ /* set the mag read address to data registers*/
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_BMM150_DATA_REG);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ case SUSPEND_MODE:
+ printk(KERN_INFO "3com_rslt:%d, manual:%d, read_manual:%d\n",
+ com_rslt, p_smi130->mag_manual_enable, manual_enable_status);
+ /* Set the power mode of mag as suspend mode*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_BMM150_POWER_OFF);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_POWE_CONTROL_REG);
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ printk(KERN_INFO "4com_rslt:%d, manual:%d, manual_read:%d\n",
+ com_rslt, p_smi130->mag_manual_enable, manual_enable_status);
+ /* set mag interface auto mode*/
+ if (p_smi130->mag_manual_enable == SMI130_MANUAL_ENABLE) {
+ com_rslt += smi130_set_mag_manual_enable(
+ SMI130_MANUAL_DISABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_get_mag_manual_enable(&manual_enable_status);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "5com_rslt:%d, manual:%d, manual_read:%d\n",
+ com_rslt, p_smi130->mag_manual_enable, manual_enable_status);
+ return com_rslt;
+}
+/*!
+ * @brief This API used to set the pre-set modes of bmm150
+ * The pre-set mode setting is depend on data rate and xy and z repetitions
+ *
+ * @note
+ * Before set the mag preset mode
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_mode_u8: The value of pre-set mode selection value
+ * value | pre_set mode
+ * ----------|------------
+ * 1 | SMI130_MAG_PRESETMODE_LOWPOWER
+ * 2 | SMI130_MAG_PRESETMODE_REGULAR
+ * 3 | SMI130_MAG_PRESETMODE_HIGHACCURACY
+ * 4 | SMI130_MAG_PRESETMODE_ENHANCED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_bmm150_mag_presetmode(u8 v_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ switch (v_mode_u8) {
+ case SMI130_MAG_PRESETMODE_LOWPOWER:
+ /* write the XY and Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt = smi130_set_mag_write_data(
+ SMI130_MAG_LOWPOWER_REPXY);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_XY_REP);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* write the Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_MAG_LOWPOWER_REPZ);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_Z_REP);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* set the mag v_data_u8 rate as 10 to the register 0x4C*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_MAG_LOWPOWER_DR);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_POWE_MODE_REG);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ case SMI130_MAG_PRESETMODE_REGULAR:
+ /* write the XY and Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt = smi130_set_mag_write_data(
+ SMI130_MAG_REGULAR_REPXY);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_XY_REP);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* write the Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_MAG_REGULAR_REPZ);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_Z_REP);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* set the mag v_data_u8 rate as 10 to the register 0x4C*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_MAG_REGULAR_DR);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_POWE_MODE_REG);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ case SMI130_MAG_PRESETMODE_HIGHACCURACY:
+ /* write the XY and Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt = smi130_set_mag_write_data(
+ SMI130_MAG_HIGHACCURACY_REPXY);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_XY_REP);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* write the Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_MAG_HIGHACCURACY_REPZ);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_Z_REP);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* set the mag v_data_u8 rate as 20 to the register 0x4C*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_MAG_HIGHACCURACY_DR);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_POWE_MODE_REG);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ case SMI130_MAG_PRESETMODE_ENHANCED:
+ /* write the XY and Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt = smi130_set_mag_write_data(
+ SMI130_MAG_ENHANCED_REPXY);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_XY_REP);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* write the Z repetitions*/
+ /* The v_data_u8 have to write for the register
+ It write the value in the register 0x4F*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_MAG_ENHANCED_REPZ);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_Z_REP);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* set the mag v_data_u8 rate as 10 to the register 0x4C*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_MAG_ENHANCED_DR);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_BMM150_POWE_MODE_REG);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for read the trim values of magnetometer
+ *
+ * @note
+ * Before reading the mag trimming values
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_bmm150_mag_trim_mbl(void)
+{
+ /* This variable used for provide the communication
+ results*/
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array holding the bmm150 trim data
+ */
+ u8 v_data_u8[SMI130_MAG_TRIM_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE};
+ /* read dig_x1 value */
+ com_rslt = smi130_set_mag_read_addr(
+ SMI130_MAG_DIG_X1);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_X1],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_x1 = v_data_u8[SMI130_BMM150_DIG_X1];
+ /* read dig_y1 value */
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_MAG_DIG_Y1);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_Y1],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_y1 = v_data_u8[SMI130_BMM150_DIG_Y1];
+
+ /* read dig_x2 value */
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_MAG_DIG_X2);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_X2],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_x2 = v_data_u8[SMI130_BMM150_DIG_X2];
+ /* read dig_y2 value */
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_MAG_DIG_Y2);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_Y3],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_y2 = v_data_u8[SMI130_BMM150_DIG_Y3];
+
+ /* read dig_xy1 value */
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_MAG_DIG_XY1);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_XY1],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_xy1 = v_data_u8[SMI130_BMM150_DIG_XY1];
+ /* read dig_xy2 value */
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_MAG_DIG_XY2);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 ls register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_XY2],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_xy2 = v_data_u8[SMI130_BMM150_DIG_XY2];
+
+ /* read dig_z1 lsb value */
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_MAG_DIG_Z1_LSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_Z1_LSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* read dig_z1 msb value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_MAG_DIG_Z1_MSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_Z1_MSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_z1 =
+ (u16)((((u32)((u8)v_data_u8[SMI130_BMM150_DIG_Z1_MSB]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_BMM150_DIG_Z1_LSB]));
+
+ /* read dig_z2 lsb value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_MAG_DIG_Z2_LSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_Z2_LSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* read dig_z2 msb value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_MAG_DIG_Z2_MSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_Z2_MSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_z2 =
+ (s16)((((s32)((s8)v_data_u8[SMI130_BMM150_DIG_Z2_MSB]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_BMM150_DIG_Z2_LSB]));
+
+ /* read dig_z3 lsb value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_MAG_DIG_Z3_LSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_DIG_Z3_LSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* read dig_z3 msb value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_MAG_DIG_Z3_MSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_DIG_Z3_MSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_z3 =
+ (s16)((((s32)((s8)v_data_u8[SMI130_BMM150_DIG_DIG_Z3_MSB]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_BMM150_DIG_DIG_Z3_LSB]));
+
+ /* read dig_z4 lsb value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_MAG_DIG_Z4_LSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_DIG_Z4_LSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* read dig_z4 msb value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_MAG_DIG_Z4_MSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_DIG_Z4_MSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_z4 =
+ (s16)((((s32)((s8)v_data_u8[SMI130_BMM150_DIG_DIG_Z4_MSB]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_BMM150_DIG_DIG_Z4_LSB]));
+
+ /* read dig_xyz1 lsb value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_MAG_DIG_XYZ1_LSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_DIG_XYZ1_LSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* read dig_xyz1 msb value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_MAG_DIG_XYZ1_MSB);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is v_mag_x_s16 msb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[SMI130_BMM150_DIG_DIG_XYZ1_MSB],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ mag_trim_mbl.dig_xyz1 =
+ (u16)((((u32)((u8)v_data_u8[SMI130_BMM150_DIG_DIG_XYZ1_MSB]))
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) |
+ (v_data_u8[SMI130_BMM150_DIG_DIG_XYZ1_LSB]));
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for initialize
+ * the AKM09911 and AKM09912 sensor
+ *
+ *
+ * @param v_akm_i2c_address_u8: The value of device address
+ * AKM sensor | Slave address
+ * --------------|---------------------
+ * AKM09911 | AKM09911_I2C_ADDR_1
+ * - | and AKM09911_I2C_ADDR_2
+ * AKM09912 | AKM09912_I2C_ADDR_1
+ * - | AKM09912_I2C_ADDR_2
+ * - | AKM09912_I2C_ADDR_3
+ * - | AKM09912_I2C_ADDR_4
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm_mag_interface_init(
+u8 v_akm_i2c_address_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_pull_value_u8 = SMI130_INIT_VALUE;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ u8 v_akm_chip_id_u8 = SMI130_INIT_VALUE;
+ /* accel operation mode to normal*/
+ com_rslt = smi130_set_command_register(ACCEL_MODE_NORMAL);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_command_register(MAG_MODE_NORMAL);
+ p_smi130->delay_msec(SMI130_AKM_INIT_DELAY);
+ smi130_get_mag_power_mode_stat(&v_data_u8);
+ /* register 0x7E write the 0x37, 0x9A and 0x30*/
+ com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_ONE);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_TWO);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_THREE);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /*switch the page1*/
+ com_rslt += smi130_set_target_page(SMI130_WRITE_TARGET_PAGE1);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_target_page(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_paging_enable(SMI130_WRITE_ENABLE_PAGE1);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_paging_enable(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* enable the pullup configuration from
+ the register 0x05 bit 4 and 5 to 10*/
+ smi130_get_pullup_configuration(&v_pull_value_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ v_pull_value_u8 = v_pull_value_u8 | SMI130_PULL_UP_DATA;
+ com_rslt += smi130_set_pullup_configuration(v_pull_value_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ /*switch the page0*/
+ com_rslt += smi130_set_target_page(SMI130_WRITE_TARGET_PAGE0);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_target_page(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* Write the AKM09911 0r AKM09912 i2c address*/
+ com_rslt += smi130_set_i2c_device_addr(v_akm_i2c_address_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* enable the mag interface to manual mode*/
+ com_rslt += smi130_set_mag_manual_enable(SMI130_MANUAL_ENABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_mag_manual_enable(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /*Enable the MAG interface */
+ com_rslt += smi130_set_if_mode(SMI130_ENABLE_MAG_IF_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_if_mode(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ /* Set the AKM Fuse ROM mode */
+ /* Set value for fuse ROM mode*/
+ com_rslt += smi130_set_mag_write_data(AKM_FUSE_ROM_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* AKM mode address is 0x31*/
+ com_rslt += smi130_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Read the Fuse ROM v_data_u8 from registers
+ 0x60,0x61 and 0x62*/
+ /* ASAX v_data_u8 */
+ com_rslt += smi130_read_bosch_akm_sensitivity_data();
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* read the device id of the AKM sensor
+ if device id is 0x05 - AKM09911
+ if device id is 0x04 - AKM09912*/
+ com_rslt += smi130_set_mag_read_addr(AKM09912_CHIP_ID_REG);
+ /* 0x04 is mag_x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_akm_chip_id_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ printk(KERN_INFO "smi130,addr:0x%x, akm_chip_id:0x%x",
+ v_akm_i2c_address_u8, v_akm_chip_id_u8);
+ /* Set value power down mode mode*/
+ com_rslt += smi130_set_mag_write_data(AKM_POWER_DOWN_MODE_DATA);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* AKM mode address is 0x31*/
+ com_rslt += smi130_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Set AKM Force mode*/
+ com_rslt += smi130_set_mag_write_data(
+ AKM_SINGLE_MEASUREMENT_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* AKM mode address is 0x31*/
+ com_rslt += smi130_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Set the AKM read xyz v_data_u8 address*/
+ com_rslt += smi130_set_mag_read_addr(AKM_DATA_REGISTER);
+ /* write the mag v_data_bw_u8 as 25Hz*/
+ com_rslt += smi130_set_mag_output_data_rate(
+ SMI130_MAG_OUTPUT_DATA_RATE_25HZ);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* Enable mag interface to auto mode*/
+ com_rslt += smi130_set_mag_manual_enable(SMI130_MANUAL_DISABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_mag_manual_enable(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for read the sensitivity data of
+ * AKM09911 and AKM09912
+ *
+ * @note Before reading the mag sensitivity values
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_bosch_akm_sensitivity_data(void)
+{
+ /* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array holding the sensitivity ax,ay and az data*/
+ u8 v_data_u8[SMI130_AKM_SENSITIVITY_DATA_SIZE] = {
+ SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* read asax value */
+ com_rslt = smi130_set_mag_read_addr(SMI130_BST_AKM_ASAX);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[AKM_ASAX],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ akm_asa_data_mbl.asax = v_data_u8[AKM_ASAX];
+ /* read asay value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_BST_AKM_ASAY);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[AKM_ASAY],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ akm_asa_data_mbl.asay = v_data_u8[AKM_ASAY];
+ /* read asaz value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_BST_AKM_ASAZ);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[AKM_ASAZ],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ akm_asa_data_mbl.asaz = v_data_u8[AKM_ASAZ];
+
+ return com_rslt;
+}
+/*!
+ * @brief This API used to get the compensated X data
+ * of AKM09911 the out put of X as s32
+ * @note Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_x_s16 : The value of X data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09911_compensate_X(s16 v_bosch_akm_x_s16)
+{
+ /*Return value of AKM x compensated v_data_u8*/
+ s32 retval = SMI130_INIT_VALUE;
+ /* Convert raw v_data_u8 into compensated v_data_u8*/
+ retval = (v_bosch_akm_x_s16 *
+ ((akm_asa_data_mbl.asax/AKM09911_SENSITIVITY_DIV) +
+ SMI130_GEN_READ_WRITE_DATA_LENGTH));
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated Y data
+ * of AKM09911 the out put of Y as s32
+ * @note Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_y_s16 : The value of Y data
+ *
+ * @return results of compensated Y data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09911_compensate_Y(s16 v_bosch_akm_y_s16)
+{
+ /*Return value of AKM y compensated v_data_u8*/
+ s32 retval = SMI130_INIT_VALUE;
+ /* Convert raw v_data_u8 into compensated v_data_u8*/
+ retval = (v_bosch_akm_y_s16 *
+ ((akm_asa_data_mbl.asay/AKM09911_SENSITIVITY_DIV) +
+ SMI130_GEN_READ_WRITE_DATA_LENGTH));
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated Z data
+ * of AKM09911 the out put of Z as s32
+ * @note Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_z_s16 : The value of Z data
+ *
+ * @return results of compensated Z data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09911_compensate_Z(s16 v_bosch_akm_z_s16)
+{
+ /*Return value of AKM z compensated v_data_u8*/
+ s32 retval = SMI130_INIT_VALUE;
+ /* Convert raw v_data_u8 into compensated v_data_u8*/
+ retval = (v_bosch_akm_z_s16 *
+ ((akm_asa_data_mbl.asaz/AKM09911_SENSITIVITY_DIV) +
+ SMI130_GEN_READ_WRITE_DATA_LENGTH));
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated X data
+ * of AKM09912 the out put of X as s32
+ * @note Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_x_s16 : The value of X data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09912_compensate_X(s16 v_bosch_akm_x_s16)
+{
+ /*Return value of AKM x compensated data*/
+ s32 retval = SMI130_INIT_VALUE;
+ /* Convert raw data into compensated data*/
+ retval = v_bosch_akm_x_s16 *
+ (akm_asa_data_mbl.asax + AKM09912_SENSITIVITY)
+ / AKM09912_SENSITIVITY_DIV;
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated Y data
+ * of AKM09912 the out put of Y as s32
+ * @note Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_y_s16 : The value of Y data
+ *
+ * @return results of compensated Y data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09912_compensate_Y(s16 v_bosch_akm_y_s16)
+{
+ /*Return value of AKM y compensated data*/
+ s32 retval = SMI130_INIT_VALUE;
+ /* Convert raw data into compensated data*/
+ retval = v_bosch_akm_y_s16 *
+ (akm_asa_data_mbl.asax + AKM09912_SENSITIVITY)
+ / AKM09912_SENSITIVITY_DIV;
+ return retval;
+}
+/*!
+ * @brief This API used to get the compensated Z data
+ * of AKM09912 the out put of Z as s32
+ * @note Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_z_s16 : The value of Z data
+ *
+ * @return results of compensated Z data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09912_compensate_Z(s16 v_bosch_akm_z_s16)
+{
+ /*Return value of AKM z compensated data*/
+ s32 retval = SMI130_INIT_VALUE;
+ /* Convert raw data into compensated data*/
+ retval = v_bosch_akm_z_s16 *
+ (akm_asa_data_mbl.asax + AKM09912_SENSITIVITY)
+ / AKM09912_SENSITIVITY_DIV;
+ return retval;
+}
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09911
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm09911_compensate_xyz(
+struct smi130_mag_xyz_s32_t *bosch_akm_xyz)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ struct smi130_mag_t mag_xyz;
+
+ com_rslt = smi130_read_mag_xyz(&mag_xyz, BST_AKM);
+ /* Compensation for X axis */
+ bosch_akm_xyz->x = smi130_bosch_akm09911_compensate_X(mag_xyz.x);
+
+ /* Compensation for Y axis */
+ bosch_akm_xyz->y = smi130_bosch_akm09911_compensate_Y(mag_xyz.y);
+
+ /* Compensation for Z axis */
+ bosch_akm_xyz->z = smi130_bosch_akm09911_compensate_Z(mag_xyz.z);
+
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09912
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm09912_compensate_xyz(
+struct smi130_mag_xyz_s32_t *bosch_akm_xyz)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ struct smi130_mag_t mag_xyz;
+
+ com_rslt = smi130_read_mag_xyz(&mag_xyz, BST_AKM);
+ printk(KERN_INFO "akm09912_raw_x:%d, %d, %d, <%s>,<%d>",
+ mag_xyz.x, mag_xyz.y, mag_xyz.z, __func__, __LINE__);
+ /* Compensation for X axis */
+ bosch_akm_xyz->x = smi130_bosch_akm09912_compensate_X(mag_xyz.x);
+
+ /* Compensation for Y axis */
+ bosch_akm_xyz->y = smi130_bosch_akm09912_compensate_Y(mag_xyz.y);
+
+ /* Compensation for Z axis */
+ bosch_akm_xyz->z = smi130_bosch_akm09912_compensate_Z(mag_xyz.z);
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09912
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm09912_compensate_xyz_raw(
+struct smi130_mag_xyz_s32_t *bosch_akm_xyz)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Compensation for X axis */
+ bosch_akm_xyz->x = smi130_bosch_akm09912_compensate_X(bosch_akm_xyz->x);
+
+ /* Compensation for Y axis */
+ bosch_akm_xyz->y = smi130_bosch_akm09912_compensate_Y(bosch_akm_xyz->y);
+
+ /* Compensation for Z axis */
+ bosch_akm_xyz->z = smi130_bosch_akm09912_compensate_Z(bosch_akm_xyz->z);
+
+ return com_rslt;
+}
+/*!
+ * @brief This function used for set the AKM09911 and AKM09912
+ * power mode.
+ * @note Before set the AKM power mode
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @param v_akm_pow_mode_u8 : The value of akm power mode
+ * value | Description
+ * ---------|--------------------
+ * 0 | AKM_POWER_DOWN_MODE
+ * 1 | AKM_SINGLE_MEAS_MODE
+ * 2 | FUSE_ROM_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm_set_powermode(
+u8 v_akm_pow_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = SMI130_INIT_VALUE;
+ /* set mag interface manual mode*/
+ if (p_smi130->mag_manual_enable != SMI130_MANUAL_ENABLE) {
+ com_rslt = smi130_set_mag_manual_enable(
+ SMI130_MANUAL_ENABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__);
+ switch (v_akm_pow_mode_u8) {
+ case AKM_POWER_DOWN_MODE:
+ /* Set the power mode of AKM as power down mode*/
+ com_rslt += smi130_set_mag_write_data(AKM_POWER_DOWN_MODE_DATA);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ case AKM_SINGLE_MEAS_MODE:
+ /* Set the power mode of AKM as
+ single measurement mode*/
+ com_rslt += smi130_set_mag_write_data
+ (AKM_SINGLE_MEASUREMENT_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_read_addr(AKM_DATA_REGISTER);
+ break;
+ case FUSE_ROM_MODE:
+ /* Set the power mode of AKM as
+ Fuse ROM mode*/
+ com_rslt += smi130_set_mag_write_data(AKM_FUSE_ROM_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Sensitivity v_data_u8 */
+ com_rslt += smi130_read_bosch_akm_sensitivity_data();
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* power down mode*/
+ com_rslt += smi130_set_mag_write_data(AKM_POWER_DOWN_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(AKM_POWER_MODE_REG);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ /* set mag interface auto mode*/
+ if (p_smi130->mag_manual_enable == SMI130_MANUAL_ENABLE) {
+ com_rslt += smi130_set_mag_manual_enable(
+ SMI130_MANUAL_DISABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_INFO "com_rslt:%d, manual:%d, <%s><%d>\n",
+ com_rslt, p_smi130->mag_manual_enable, __func__, __LINE__);
+ return com_rslt;
+}
+ /*!
+ * @brief This function used for set the magnetometer
+ * power mode of AKM09911 and AKM09912
+ * @note Before set the mag power mode
+ * make sure the following two point is addressed
+ * Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ *
+ * @param v_mag_sec_if_pow_mode_u8 : The value of secondary if power mode
+ * value | Description
+ * ---------|--------------------
+ * 0 | SMI130_MAG_FORCE_MODE
+ * 1 | SMI130_MAG_SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_bosch_akm_and_secondary_if_powermode(
+u8 v_mag_sec_if_pow_mode_u8)
+{
+ /* variable used for return the status of communication result*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* accel operation mode to normal*/
+ com_rslt = smi130_set_command_register(ACCEL_MODE_NORMAL);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* set mag interface manual mode*/
+ if (p_smi130->mag_manual_enable != SMI130_MANUAL_ENABLE) {
+ com_rslt = smi130_set_mag_manual_enable(
+ SMI130_MANUAL_ENABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ }
+ printk(KERN_ERR "com_rslt:%d, manual:%d,after setacc normal mode\n",
+ com_rslt, p_smi130->mag_manual_enable);
+ switch (v_mag_sec_if_pow_mode_u8) {
+ case SMI130_MAG_FORCE_MODE:
+ /* set the secondary mag power mode as NORMAL*/
+ com_rslt += smi130_set_mag_interface_normal();
+ /* set the akm power mode as single measurement mode*/
+ com_rslt += smi130_bosch_akm_set_powermode(AKM_SINGLE_MEAS_MODE);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_read_addr(AKM_DATA_REGISTER);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ break;
+ case SMI130_MAG_SUSPEND_MODE:
+ /* set the akm power mode as power down mode*/
+ com_rslt += smi130_bosch_akm_set_powermode(AKM_POWER_DOWN_MODE);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* set the secondary mag power mode as SUSPEND*/
+ com_rslt += smi130_set_command_register(MAG_MODE_SUSPEND);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ break;
+ default:
+ com_rslt = E_SMI130_OUT_OF_RANGE;
+ break;
+ }
+ /* set mag interface auto mode*/
+ if (p_smi130->mag_manual_enable == SMI130_MANUAL_ENABLE)
+ com_rslt += smi130_set_mag_manual_enable(
+ SMI130_MANUAL_DISABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ return com_rslt;
+}
+/*!
+ * @brief This function used for read the YAMAH-YAS532 init
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas532_mag_interface_init(
+void)
+{
+ /* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ u8 v_pull_value_u8 = SMI130_INIT_VALUE;
+ u8 v_data_u8 = SMI130_INIT_VALUE;
+ u8 i = SMI130_INIT_VALUE;
+ /* accel operation mode to normal*/
+ com_rslt = smi130_set_command_register(ACCEL_MODE_NORMAL);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* write mag power mode as NORMAL*/
+ com_rslt += smi130_set_mag_interface_normal();
+ /* register 0x7E write the 0x37, 0x9A and 0x30*/
+ com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_ONE);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_TWO);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_THREE);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /*switch the page1*/
+ com_rslt += smi130_set_target_page(SMI130_WRITE_TARGET_PAGE1);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_target_page(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_paging_enable(SMI130_WRITE_ENABLE_PAGE1);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_paging_enable(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* enable the pullup configuration from
+ the register 0x05 bit 4 and 5 as 10*/
+ smi130_get_pullup_configuration(&v_pull_value_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ v_pull_value_u8 = v_pull_value_u8 | SMI130_PULL_UP_DATA;
+ com_rslt += smi130_set_pullup_configuration(v_pull_value_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /*switch the page0*/
+ com_rslt += smi130_set_target_page(SMI130_WRITE_TARGET_PAGE0);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_target_page(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* Write the YAS532 i2c address*/
+ com_rslt += smi130_set_i2c_device_addr(SMI130_AUX_YAS532_I2C_ADDRESS);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* enable the mag interface to manual mode*/
+ com_rslt += smi130_set_mag_manual_enable(SMI130_MANUAL_ENABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_mag_manual_enable(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /*Enable the MAG interface */
+ com_rslt += smi130_set_if_mode(SMI130_ENABLE_MAG_IF_MODE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_if_mode(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ v_data_u8 = SMI130_MANUAL_DISABLE;
+ /* Read the YAS532 device id is 0x02*/
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS_DEVICE_ID_REG);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* Read the YAS532 calibration data*/
+ com_rslt += smi130_bosch_yamaha_yas532_calib_values();
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* Assign the data acquisition mode*/
+ yas532_data_mbl.measure_state = YAS532_MAG_STATE_INIT_COIL;
+ /* Set the default offset as invalid offset*/
+ set_vector(yas532_data_mbl.v_hard_offset_s8, INVALID_OFFSET);
+ /* set the transform to zero */
+ yas532_data_mbl.transform = SMI130_NULL;
+ /* Assign overflow as zero*/
+ yas532_data_mbl.overflow = 0;
+ #if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+ yas532_data_mbl.temp_data.num =
+ yas532_data_mbl.temp_data.idx = 0;
+ #endif
+ /* Assign the coef value*/
+ for (i = 0; i < 3; i++) {
+ yas532_data_mbl.coef[i] = yas532_version_ac_coef[i];
+ yas532_data_mbl.last_raw[i] = 0;
+ }
+ yas532_data_mbl.last_raw[3] = 0;
+ /* Set the initial values of yas532*/
+ com_rslt += smi130_bosch_yas532_set_initial_values();
+ /* write the mag v_data_bw_u8 as 25Hz*/
+ com_rslt += smi130_set_mag_output_data_rate(
+ SMI130_MAG_OUTPUT_DATA_RATE_25HZ);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* Enable mag interface to auto mode*/
+ com_rslt += smi130_set_mag_manual_enable(
+ SMI130_MANUAL_DISABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ smi130_get_mag_manual_enable(&v_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+}
+/*!
+ * @brief This function used to set the YAS532 initial values
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_set_initial_values(void)
+{
+/* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* write testr1 as 0x00*/
+ com_rslt = smi130_set_mag_write_data(
+ SMI130_YAS532_WRITE_TESTR1);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(SMI130_YAS532_TESTR1);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write testr2 as 0x00*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_YAS532_WRITE_TESTR2);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(SMI130_YAS532_TESTR2);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write Rcoil as 0x00*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_YAS532_WRITE_RCOIL);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(SMI130_YAS532_RCOIL);
+ p_smi130->delay_msec(SMI130_YAS532_SET_INITIAL_VALUE_DELAY);
+ /* check the valid offset*/
+ if (is_valid_offset(yas532_data_mbl.v_hard_offset_s8)) {
+ com_rslt += smi130_bosch_yas532_set_offset(
+ yas532_data_mbl.v_hard_offset_s8);
+ yas532_data_mbl.measure_state = YAS532_MAG_STATE_NORMAL;
+ } else {
+ /* set the default offset as invalid offset*/
+ set_vector(yas532_data_mbl.v_hard_offset_s8, INVALID_OFFSET);
+ /*Set the default measure state for offset correction*/
+ yas532_data_mbl.measure_state = YAS532_MAG_STATE_MEASURE_OFFSET;
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This function used for YAS532 offset correction
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_magnetic_measure_set_offset(
+void)
+{
+ /* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* used for offset value set to the offset register*/
+ s8 v_hard_offset_s8[SMI130_HARD_OFFSET_DATA_SIZE] = {
+ SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* offset correction factors*/
+ static const u8 v_correct_u8[SMI130_YAS_CORRECT_DATA_SIZE] = {
+ 16, 8, 4, 2, 1};
+ /* used for the temperature */
+ u16 v_temp_u16 = SMI130_INIT_VALUE;
+ /* used for the xy1y2 read*/
+ u16 v_xy1y2_u16[SMI130_YAS_XY1Y2_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* local flag for assign the values*/
+ s32 v_flag_s32[SMI130_YAS_FLAG_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ u8 i, j, v_busy_u8, v_overflow_u8 = SMI130_INIT_VALUE;
+
+ for (i = 0; i < 5; i++) {
+ /* set the offset values*/
+ com_rslt = smi130_bosch_yas532_set_offset(v_hard_offset_s8);
+ /* read the sensor data*/
+ com_rslt += smi130_bosch_yas532_normal_measurement_data(
+ SMI130_YAS532_ACQ_START, &v_busy_u8, &v_temp_u16,
+ v_xy1y2_u16, &v_overflow_u8);
+ /* check the sensor busy status*/
+ if (v_busy_u8)
+ return E_SMI130_BUSY;
+ /* calculate the magnetic correction with
+ offset and assign the values
+ to the offset register */
+ for (j = 0; j < 3; j++) {
+ if (YAS532_DATA_CENTER == v_xy1y2_u16[j])
+ v_flag_s32[j] = 0;
+ if (YAS532_DATA_CENTER < v_xy1y2_u16[j])
+ v_flag_s32[j] = 1;
+ if (v_xy1y2_u16[j] < YAS532_DATA_CENTER)
+ v_flag_s32[j] = -1;
+ }
+ for (j = 0; j < 3; j++) {
+ if (v_flag_s32[j])
+ v_hard_offset_s8[j] = (s8)(v_hard_offset_s8[j]
+ + v_flag_s32[j] * v_correct_u8[i]);
+ }
+ }
+ /* set the offset */
+ com_rslt += smi130_bosch_yas532_set_offset(v_hard_offset_s8);
+ return com_rslt;
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS532 calibration data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas532_calib_values(void)
+{
+ /* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array holding the YAS532 calibration values */
+ u8 v_data_u8[SMI130_YAS532_CALIB_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* Read the DX value */
+ com_rslt = smi130_set_mag_read_addr(SMI130_YAS532_CALIB_CX);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[0], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ yas532_data_mbl.calib_yas532.cx = (s32)((v_data_u8[0]
+ * 10) - 1280);
+ /* Read the DY1 value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB_CY1);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[1], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ yas532_data_mbl.calib_yas532.cy1 =
+ (s32)((v_data_u8[1] * 10) - 1280);
+ /* Read the DY2 value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB_CY2);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[2], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ yas532_data_mbl.calib_yas532.cy2 =
+ (s32)((v_data_u8[2] * 10) - 1280);
+ /* Read the D2 and D3 value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB1);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[3], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ yas532_data_mbl.calib_yas532.a2 =
+ (s32)(((v_data_u8[3] >>
+ SMI130_SHIFT_BIT_POSITION_BY_02_BITS)
+ & 0x03F) - 32);
+ /* Read the D3 and D4 value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB2);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[4], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a3*/
+ yas532_data_mbl.calib_yas532.a3 = (s32)((((v_data_u8[3] <<
+ SMI130_SHIFT_BIT_POSITION_BY_02_BITS) & 0x0C) |
+ ((v_data_u8[4]
+ >> SMI130_SHIFT_BIT_POSITION_BY_06_BITS)
+ & 0x03)) - 8);
+ /* calculate a4*/
+ yas532_data_mbl.calib_yas532.a4 = (s32)((v_data_u8[4]
+ & 0x3F) - 32);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* Read the D5 and D6 value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB3);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[5], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a5*/
+ yas532_data_mbl.calib_yas532.a5 =
+ (s32)(((v_data_u8[5]
+ >> SMI130_SHIFT_BIT_POSITION_BY_02_BITS)
+ & 0x3F) + 38);
+ /* Read the D6 and D7 value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB4);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[6], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a6*/
+ yas532_data_mbl.calib_yas532.a6 =
+ (s32)((((v_data_u8[5]
+ << SMI130_SHIFT_BIT_POSITION_BY_04_BITS)
+ & 0x30) | ((v_data_u8[6] >>
+ SMI130_SHIFT_BIT_POSITION_BY_04_BITS)
+ & 0x0F)) - 32);
+ /* Read the D7 and D8 value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB5);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[7], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a7*/
+ yas532_data_mbl.calib_yas532.a7 = (s32)((((v_data_u8[6]
+ << SMI130_SHIFT_BIT_POSITION_BY_03_BITS)
+ & 0x78) |
+ ((v_data_u8[7]
+ >> SMI130_SHIFT_BIT_POSITION_BY_05_BITS) &
+ 0x07)) - 64);
+ /* Read the D8 and D9 value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CLAIB6);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[8], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a8*/
+ yas532_data_mbl.calib_yas532.a8 = (s32)((((v_data_u8[7] <<
+ SMI130_GEN_READ_WRITE_DATA_LENGTH) & 0x3E) |
+ ((v_data_u8[8] >>
+ SMI130_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01)) -
+ 32);
+
+ /* Read the D8 and D9 value */
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB7);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[9], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* calculate a9*/
+ yas532_data_mbl.calib_yas532.a9 = (s32)(((v_data_u8[8] <<
+ SMI130_GEN_READ_WRITE_DATA_LENGTH) & 0xFE) |
+ ((v_data_u8[9] >>
+ SMI130_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01));
+ /* calculate k*/
+ yas532_data_mbl.calib_yas532.k = (s32)((v_data_u8[9] >>
+ SMI130_SHIFT_BIT_POSITION_BY_02_BITS) & 0x1F);
+ /* Read the value from register 0x9A*/
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB8);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[10],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* Read the value from register 0x9B*/
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIIB9);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[11],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* Read the value from register 0x9C*/
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB10);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[12],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* Read the value from register 0x9D*/
+ com_rslt += smi130_set_mag_read_addr(SMI130_YAS532_CALIB11);
+ /* 0x04 is secondary read mag x lsb register */
+ com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+ &v_data_u8[13],
+ SMI130_GEN_READ_WRITE_DATA_LENGTH);
+ /* Calculate the fxy1y2 and rxy1y1*/
+ yas532_data_mbl.calib_yas532.fxy1y2[0] =
+ (u8)(((v_data_u8[10]
+ & 0x01)
+ << SMI130_SHIFT_BIT_POSITION_BY_01_BIT)
+ | ((v_data_u8[11] >>
+ SMI130_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01));
+ yas532_data_mbl.calib_yas532.rxy1y2[0] =
+ ((s8)(((v_data_u8[10]
+ >> SMI130_SHIFT_BIT_POSITION_BY_01_BIT) & 0x3F)
+ << SMI130_SHIFT_BIT_POSITION_BY_02_BITS))
+ >> SMI130_SHIFT_BIT_POSITION_BY_02_BITS;
+ yas532_data_mbl.calib_yas532.fxy1y2[1] =
+ (u8)(((v_data_u8[11] & 0x01)
+ << SMI130_SHIFT_BIT_POSITION_BY_01_BIT)
+ | ((v_data_u8[12] >>
+ SMI130_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01));
+ yas532_data_mbl.calib_yas532.rxy1y2[1] =
+ ((s8)(((v_data_u8[11]
+ >> SMI130_SHIFT_BIT_POSITION_BY_01_BIT) & 0x3F)
+ << SMI130_SHIFT_BIT_POSITION_BY_02_BITS))
+ >> SMI130_SHIFT_BIT_POSITION_BY_02_BITS;
+ yas532_data_mbl.calib_yas532.fxy1y2[2] =
+ (u8)(((v_data_u8[12] & 0x01)
+ << SMI130_SHIFT_BIT_POSITION_BY_01_BIT)
+ | ((v_data_u8[13]
+ >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01));
+ yas532_data_mbl.calib_yas532.rxy1y2[2] =
+ ((s8)(((v_data_u8[12]
+ >> SMI130_SHIFT_BIT_POSITION_BY_01_BIT) & 0x3F)
+ << SMI130_SHIFT_BIT_POSITION_BY_02_BITS))
+ >> SMI130_SHIFT_BIT_POSITION_BY_02_BITS;
+
+ return com_rslt;
+}
+/*!
+ * @brief This function used for calculate the
+ * YAS532 read the linear data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_xy1y2_to_linear(
+u16 *v_xy1y2_u16, s32 *xy1y2_linear)
+{
+ /* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = SUCCESS;
+ static const u16 v_calib_data[] = {
+ 3721, 3971, 4221, 4471};
+ u8 i = SMI130_INIT_VALUE;
+
+ for (i = 0; i < 3; i++)
+ xy1y2_linear[i] = v_xy1y2_u16[i] -
+ v_calib_data[yas532_data_mbl.calib_yas532.fxy1y2[i]]
+ + (yas532_data_mbl.v_hard_offset_s8[i] -
+ yas532_data_mbl.calib_yas532.rxy1y2[i])
+ * yas532_data_mbl.coef[i];
+ return com_rslt;
+}
+/*!
+ * @brief This function used for read the YAS532 sensor data
+ * @param v_acquisition_command_u8: used to set the data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ * @param v_busy_u8 : used to get the busy flay for sensor data read
+ * @param v_temp_u16 : used to get the temperature data
+ * @param v_xy1y2_u16 : used to get the sensor xy1y2 data
+ * @param v_overflow_u8 : used to get the overflow data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_normal_measurement_data(
+u8 v_acquisition_command_u8, u8 *v_busy_u8,
+u16 *v_temp_u16, u16 *v_xy1y2_u16, u8 *v_overflow_u8)
+{
+ /* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = SMI130_INIT_VALUE;
+ /* Array holding the YAS532 xyy1 data*/
+ u8 v_data_u8[SMI130_YAS_XY1Y2T_DATA_SIZE] = {
+ SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ u8 i = SMI130_INIT_VALUE;
+ /* check the p_smi130 structure as NULL*/
+ if (p_smi130 == SMI130_NULL) {
+ return E_SMI130_NULL_PTR;
+ } else {
+ /* read the sensor data */
+ com_rslt = smi130_bosch_yas532_acquisition_command_register(
+ v_acquisition_command_u8);
+ com_rslt +=
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_MAG_X_LSB__REG,
+ v_data_u8, SMI130_MAG_YAS_DATA_LENGTH);
+ /* read the xyy1 data*/
+ *v_busy_u8 =
+ ((v_data_u8[0]
+ >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS) & 0x01);
+ *v_temp_u16 =
+ (u16)((((s32)v_data_u8[0]
+ << SMI130_SHIFT_BIT_POSITION_BY_03_BITS)
+ & 0x3F8) | ((v_data_u8[1]
+ >> SMI130_SHIFT_BIT_POSITION_BY_05_BITS) & 0x07));
+ v_xy1y2_u16[0] =
+ (u16)((((s32)v_data_u8[2]
+ << SMI130_SHIFT_BIT_POSITION_BY_06_BITS) & 0x1FC0)
+ | ((v_data_u8[3] >>
+ SMI130_SHIFT_BIT_POSITION_BY_02_BITS) & 0x3F));
+ v_xy1y2_u16[1] =
+ (u16)((((s32)v_data_u8[4]
+ << SMI130_SHIFT_BIT_POSITION_BY_06_BITS)
+ & 0x1FC0)
+ | ((v_data_u8[5]
+ >> SMI130_SHIFT_BIT_POSITION_BY_02_BITS) & 0x3F));
+ v_xy1y2_u16[2] =
+ (u16)((((s32)v_data_u8[6]
+ << SMI130_SHIFT_BIT_POSITION_BY_06_BITS)
+ & 0x1FC0)
+ | ((v_data_u8[7]
+ >> SMI130_SHIFT_BIT_POSITION_BY_02_BITS) & 0x3F));
+ *v_overflow_u8 = 0;
+ for (i = 0; i < 3; i++) {
+ if (v_xy1y2_u16[i] == YAS532_DATA_OVERFLOW)
+ *v_overflow_u8 |= (1 << (i * 2));
+ if (v_xy1y2_u16[i] == YAS532_DATA_UNDERFLOW)
+ *v_overflow_u8 |= (1 << (i * 2 + 1));
+ }
+ }
+ return com_rslt;
+}
+/*!
+ * @brief This function used for YAS532 sensor data
+ * @param v_acquisition_command_u8 : the value of CMDR
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ * @param xyz_data : the vector xyz output
+ * @param v_overflow_s8 : the value of overflow
+ * @param v_temp_correction_u8 : the value of temperate correction enable
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_measurement_xyz_data(
+struct yas532_vector *xyz_data, u8 *v_overflow_s8, u8 v_temp_correction_u8,
+u8 v_acquisition_command_u8)
+{
+ /* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = SMI130_INIT_VALUE;
+ /* Array holding the linear calculation output*/
+ s32 v_xy1y2_linear_s32[SMI130_YAS_XY1Y2_DATA_SIZE] = {
+ SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* Array holding the temperature data */
+ s32 v_xyz_tmp_s32[SMI130_YAS_TEMP_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ s32 tmp = SMI130_INIT_VALUE;
+ s32 sx, sy1, sy2, sy, sz = SMI130_INIT_VALUE;
+ u8 i, v_busy_u8 = SMI130_INIT_VALUE;
+ u16 v_temp_u16 = SMI130_INIT_VALUE;
+ /* Array holding the xyy1 sensor raw data*/
+ u16 v_xy1y2_u16[SMI130_YAS_XY1Y2_DATA_SIZE] = {SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ #if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+ s32 sum = SMI130_INIT_VALUE;
+ #endif
+ *v_overflow_s8 = SMI130_INIT_VALUE;
+ switch (yas532_data_mbl.measure_state) {
+ case YAS532_MAG_STATE_INIT_COIL:
+ if (p_smi130->mag_manual_enable != SMI130_MANUAL_ENABLE)
+ com_rslt = smi130_set_mag_manual_enable(
+ SMI130_MANUAL_ENABLE);
+ /* write Rcoil*/
+ com_rslt += smi130_set_mag_write_data(
+ SMI130_YAS_DISABLE_RCOIL);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(SMI130_YAS532_RCOIL);
+ p_smi130->delay_msec(SMI130_YAS532_MEASUREMENT_DELAY);
+ if (!yas532_data_mbl.overflow && is_valid_offset(
+ yas532_data_mbl.v_hard_offset_s8))
+ yas532_data_mbl.measure_state = 0;
+ break;
+ case YAS532_MAG_STATE_MEASURE_OFFSET:
+ com_rslt = smi130_bosch_yas532_magnetic_measure_set_offset();
+ yas532_data_mbl.measure_state = 0;
+ break;
+ default:
+ break;
+ }
+ /* Read sensor data*/
+ com_rslt += smi130_bosch_yas532_normal_measurement_data(
+ v_acquisition_command_u8, &v_busy_u8, &v_temp_u16,
+ v_xy1y2_u16, v_overflow_s8);
+ /* Calculate the linear data*/
+ com_rslt += smi130_bosch_yas532_xy1y2_to_linear(v_xy1y2_u16,
+ v_xy1y2_linear_s32);
+ /* Calculate temperature correction */
+ #if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+ yas532_data_mbl.temp_data.log[yas532_data_mbl.temp_data.idx++] =
+ v_temp_u16;
+ if (YAS532_MAG_TEMPERATURE_LOG <= yas532_data_mbl.temp_data.idx)
+ yas532_data_mbl.temp_data.idx = 0;
+ yas532_data_mbl.temp_data.num++;
+ if (YAS532_MAG_TEMPERATURE_LOG <= yas532_data_mbl.temp_data.num)
+ yas532_data_mbl.temp_data.num = YAS532_MAG_TEMPERATURE_LOG;
+ for (i = 0; i < yas532_data_mbl.temp_data.num; i++)
+ sum += yas532_data_mbl.temp_data.log[i];
+ tmp = sum * 10 / yas532_data_mbl.temp_data.num
+ - YAS532_TEMP20DEGREE_TYPICAL * 10;
+ #else
+ tmp = (v_temp_u16 - YAS532_TEMP20DEGREE_TYPICAL)
+ * 10;
+ #endif
+ sx = v_xy1y2_linear_s32[0];
+ sy1 = v_xy1y2_linear_s32[1];
+ sy2 = v_xy1y2_linear_s32[2];
+ /* Temperature correction */
+ if (v_temp_correction_u8) {
+ sx -= (yas532_data_mbl.calib_yas532.cx * tmp)
+ / 1000;
+ sy1 -= (yas532_data_mbl.calib_yas532.cy1 * tmp)
+ / 1000;
+ sy2 -= (yas532_data_mbl.calib_yas532.cy2 * tmp)
+ / 1000;
+ }
+ sy = sy1 - sy2;
+ sz = -sy1 - sy2;
+
+ xyz_data->yas532_vector_xyz[0] = yas532_data_mbl.calib_yas532.k *
+ ((100 * sx + yas532_data_mbl.calib_yas532.a2 * sy +
+ yas532_data_mbl.calib_yas532.a3 * sz) / 10);
+ xyz_data->yas532_vector_xyz[1] = yas532_data_mbl.calib_yas532.k *
+ ((yas532_data_mbl.calib_yas532.a4 * sx + yas532_data_mbl.calib_yas532.a5 * sy +
+ yas532_data_mbl.calib_yas532.a6 * sz) / 10);
+ xyz_data->yas532_vector_xyz[2] = yas532_data_mbl.calib_yas532.k *
+ ((yas532_data_mbl.calib_yas532.a7 * sx + yas532_data_mbl.calib_yas532.a8 * sy +
+ yas532_data_mbl.calib_yas532.a9 * sz) / 10);
+ if (yas532_data_mbl.transform != SMI130_NULL) {
+ for (i = 0; i < 3; i++) {
+ v_xyz_tmp_s32[i] = yas532_data_mbl.transform[i
+ * 3] *
+ xyz_data->yas532_vector_xyz[0]
+ + yas532_data_mbl.transform[i * 3 + 1] *
+ xyz_data->yas532_vector_xyz[1]
+ + yas532_data_mbl.transform[i * 3 + 2] *
+ xyz_data->yas532_vector_xyz[2];
+ }
+ set_vector(xyz_data->yas532_vector_xyz, v_xyz_tmp_s32);
+ }
+ for (i = 0; i < 3; i++) {
+ xyz_data->yas532_vector_xyz[i] -=
+ xyz_data->yas532_vector_xyz[i] % 10;
+ if (*v_overflow_s8 & (1
+ << (i * 2)))
+ xyz_data->yas532_vector_xyz[i] +=
+ 1; /* set overflow */
+ if (*v_overflow_s8 & (1 <<
+ (i * 2 + 1)))
+ xyz_data->yas532_vector_xyz[i] += 2; /* set underflow */
+ }
+
+
+if (v_busy_u8)
+ return com_rslt;
+ if (0 < *v_overflow_s8) {
+ if (!yas532_data_mbl.overflow)
+ yas532_data_mbl.overflow = 1;
+ yas532_data_mbl.measure_state = YAS532_MAG_STATE_INIT_COIL;
+ } else
+ yas532_data_mbl.overflow = 0;
+ for (i = 0; i < 3; i++)
+ yas532_data_mbl.last_raw[i] = v_xy1y2_u16[i];
+ yas532_data_mbl.last_raw[i] = v_temp_u16;
+ return com_rslt;
+}
+/*!
+ * @brief This function used for YAS532 write data acquisition
+ * command register write
+ * @param v_command_reg_data_u8 : the value of data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_acquisition_command_register(
+u8 v_command_reg_data_u8)
+{
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+
+ if (p_smi130->mag_manual_enable != SMI130_MANUAL_ENABLE)
+ com_rslt = smi130_set_mag_manual_enable(
+ SMI130_MANUAL_ENABLE);
+
+ com_rslt = smi130_set_mag_write_data(v_command_reg_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* YAMAHA YAS532-0x82*/
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_YAS532_COMMAND_REGISTER);
+ p_smi130->delay_msec(SMI130_YAS_ACQ_COMMAND_DELAY);
+ com_rslt += smi130_set_mag_read_addr(
+ SMI130_YAS532_DATA_REGISTER);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ if (p_smi130->mag_manual_enable == SMI130_MANUAL_ENABLE)
+ com_rslt += smi130_set_mag_manual_enable(SMI130_MANUAL_DISABLE);
+
+ return com_rslt;
+
+}
+/*!
+ * @brief This function used write offset of YAS532
+ *
+ * @param p_offset_s8 : The value of offset to write
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_set_offset(
+const s8 *p_offset_s8)
+{
+ /* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+
+ if (p_smi130->mag_manual_enable != SMI130_MANUAL_ENABLE)
+ com_rslt = smi130_set_mag_manual_enable(SMI130_MANUAL_ENABLE);
+ p_smi130->delay_msec(SMI130_YAS532_OFFSET_DELAY);
+
+ /* Write offset X data*/
+ com_rslt = smi130_set_mag_write_data(p_offset_s8[0]);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* YAS532 offset x write*/
+ com_rslt += smi130_set_mag_write_addr(SMI130_YAS532_OFFSET_X);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ /* Write offset Y data*/
+ com_rslt = smi130_set_mag_write_data(p_offset_s8[1]);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* YAS532 offset y write*/
+ com_rslt += smi130_set_mag_write_addr(SMI130_YAS532_OFFSET_Y);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ /* Write offset Z data*/
+ com_rslt = smi130_set_mag_write_data(p_offset_s8[2]);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* YAS532 offset z write*/
+ com_rslt += smi130_set_mag_write_addr(SMI130_YAS532_OFFSET_Z);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ set_vector(yas532_data_mbl.v_hard_offset_s8, p_offset_s8);
+
+ if (p_smi130->mag_manual_enable == SMI130_MANUAL_ENABLE)
+ com_rslt = smi130_set_mag_manual_enable(SMI130_MANUAL_DISABLE);
+ return com_rslt;
+}
+/*!
+ * @brief This function used to init the YAMAH-YAS537
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas537_mag_interface_init(
+void)
+{
+/* This variable used for provide the communication
+results*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+u8 v_pull_value_u8 = SMI130_INIT_VALUE;
+u8 v_data_u8 = SMI130_INIT_VALUE;
+u8 i = SMI130_INIT_VALUE;
+/* accel operation mode to normal*/
+com_rslt = smi130_set_command_register(ACCEL_MODE_NORMAL);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* write mag power mode as NORMAL*/
+com_rslt += smi130_set_mag_interface_normal();
+/* register 0x7E write the 0x37, 0x9A and 0x30*/
+com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_ONE);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_TWO);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+com_rslt += smi130_set_command_register(SMI130_COMMAND_REG_THREE);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/*switch the page1*/
+com_rslt += smi130_set_target_page(SMI130_WRITE_TARGET_PAGE1);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+smi130_get_target_page(&v_data_u8);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+com_rslt += smi130_set_paging_enable(SMI130_WRITE_ENABLE_PAGE1);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+smi130_get_paging_enable(&v_data_u8);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* enable the pullup configuration from
+the register 0x05 bit 4 and 5 as 10*/
+smi130_get_pullup_configuration(&v_pull_value_u8);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+v_pull_value_u8 = v_pull_value_u8 | SMI130_PULL_UP_DATA;
+com_rslt += smi130_set_pullup_configuration(v_pull_value_u8);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/*switch the page0*/
+com_rslt += smi130_set_target_page(SMI130_WRITE_TARGET_PAGE0);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+smi130_get_target_page(&v_data_u8);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* Write the YAS532 i2c address*/
+com_rslt += smi130_set_i2c_device_addr(SMI130_YAS537_I2C_ADDRESS);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* enable the mag interface to manual mode*/
+com_rslt += smi130_set_mag_manual_enable(SMI130_MANUAL_ENABLE);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+smi130_get_mag_manual_enable(&v_data_u8);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/*Enable the MAG interface */
+com_rslt += smi130_set_if_mode(SMI130_ENABLE_MAG_IF_MODE);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+smi130_get_if_mode(&v_data_u8);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+v_data_u8 = SMI130_MANUAL_DISABLE;
+/* Read the YAS537 device id*/
+com_rslt += smi130_set_mag_read_addr(SMI130_YAS_DEVICE_ID_REG);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&v_data_u8, SMI130_GEN_READ_WRITE_DATA_LENGTH);
+yas537_data_mbl.dev_id = v_data_u8;
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* Read the YAS532 calibration data*/
+com_rslt +=
+smi130_bosch_yamaha_yas537_calib_values(
+SMI130_GEN_READ_WRITE_DATA_LENGTH);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* set the mode to NORMAL*/
+yas537_data_mbl.measure_state = YAS537_MAG_STATE_NORMAL;
+/* set the transform to zero */
+yas537_data_mbl.transform = SMI130_NULL;
+yas537_data_mbl.average = 32;
+for (i = 0; i < 3; i++) {
+ yas537_data_mbl.hard_offset[i] = -128;
+ yas537_data_mbl.last_after_rcoil[i] = 0;
+}
+for (i = 0; i < 4; i++)
+ yas537_data_mbl.last_raw[i] = 0;
+/* write the mag bandwidth as 25Hz*/
+com_rslt += smi130_set_mag_output_data_rate(
+SMI130_MAG_OUTPUT_DATA_RATE_25HZ);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* Enable mag interface to auto mode*/
+com_rslt += smi130_set_mag_manual_enable(
+SMI130_MANUAL_DISABLE);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+smi130_get_mag_manual_enable(&v_data_u8);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+return com_rslt;
+}
+/*!
+* @brief This function used for read the
+* YAMAHA YAS537 calibration data
+*
+*
+* @param v_rcoil_u8 : The value of r coil
+*
+*
+* @return results of bus communication function
+* @retval 0 -> Success
+* @retval -1 -> Error
+*
+*
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas537_calib_values(
+u8 v_rcoil_u8)
+{
+/* This variable used for provide the communication
+results*/
+SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+/* Array holding the YAS532 calibration values */
+u8 a_data_u8[SMI130_YAS537_CALIB_DATA_SIZE] = {
+SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+};
+static const u8 v_avrr_u8[] = {0x50, 0x60, 0x70};
+u8 v_cal_valid_u8 = SMI130_INIT_VALUE, i;
+/* write soft reset as 0x02*/
+com_rslt = smi130_set_mag_write_data(
+YAS537_SRSTR_DATA);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+com_rslt += smi130_set_mag_write_addr(YAS537_REG_SRSTR);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* Read the DX value */
+com_rslt = smi130_set_mag_read_addr(YAS537_REG_CALR_C0);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[0], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the DY1 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_C1);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[1], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the DY2 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_C2);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[2], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D2 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_C3);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[3], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D3 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_C4);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[4], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D4 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_C5);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[5], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D5 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_C6);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[6], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D6 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_C7);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[7], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D7 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_C8);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[8], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D8 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_C9);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[9], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the D9 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_CA);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[10], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the RX value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_CB);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[11], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the RY1 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_CC);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[12], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the RY2 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_CD);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[13], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the RY2 value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_CE);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[14], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the CHF value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_CF);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[15], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* Read the VER value */
+com_rslt += smi130_set_mag_read_addr(YAS537_REG_CALR_DO);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+/* 0x04 is secondary read mag x lsb register */
+com_rslt += smi130_read_reg(SMI130_MAG_DATA_READ_REG,
+&a_data_u8[16], SMI130_GEN_READ_WRITE_DATA_LENGTH);
+/* get the calib ver*/
+yas537_data_mbl.calib_yas537.ver =
+(a_data_u8[16] >> SMI130_SHIFT_BIT_POSITION_BY_06_BITS);
+for (i = 0; i < 17; i++) {
+ if (((i < 16 && a_data_u8[i]) != 0))
+ v_cal_valid_u8 = 1;
+ if ((i < 16 &&
+ (a_data_u8[i] & 0x3F)) != 0)
+ v_cal_valid_u8 = 1;
+}
+if (!v_cal_valid_u8)
+ return ERROR;
+if (yas537_data_mbl.calib_yas537.ver == 0) {
+ for (i = 0; i < 17; i++) {
+ if (i < 12) {
+ /* write offset*/
+ com_rslt += smi130_set_mag_write_data(
+ a_data_u8[i]);
+ p_smi130->delay_msec(
+ SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ YAS537_REG_MTCR + i);
+ p_smi130->delay_msec(
+ SMI130_GEN_READ_WRITE_DELAY);
+ } else if (i < 15) {
+ /* write offset correction*/
+ com_rslt += smi130_set_mag_write_data(
+ a_data_u8[i]);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr((
+ (YAS537_REG_OXR + i) - 12));
+ p_smi130->delay_msec(
+ SMI130_GEN_READ_WRITE_DELAY);
+ yas537_data_mbl.hard_offset[i - 12]
+ = a_data_u8[i];
+ } else {
+ /* write offset correction*/
+ com_rslt += smi130_set_mag_write_data(
+ a_data_u8[i]);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr((
+ (YAS537_REG_OXR + i) - 11));
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ }
+
+}
+} else if (yas537_data_mbl.calib_yas537.ver == 1) {
+ for (i = 0; i < 3; i++) {
+ /* write offset*/
+ com_rslt += smi130_set_mag_write_data(
+ a_data_u8[i]);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ YAS537_REG_MTCR + i);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ if (com_rslt == SUCCESS) {
+ /* write offset*/
+ com_rslt += smi130_set_mag_write_data(
+ a_data_u8[i + 12]);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ YAS537_REG_OXR + i);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ yas537_data_mbl.hard_offset[i] =
+ a_data_u8[i + 12];
+ } else {
+ com_rslt = ERROR;
+ }
+ }
+ /* write offset*/
+ com_rslt += smi130_set_mag_write_data(
+ ((a_data_u8[i] & 0xE0) | 0x10));
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(
+ YAS537_REG_MTCR + i);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write offset*/
+ com_rslt += smi130_set_mag_write_data(
+ ((a_data_u8[15]
+ >> SMI130_SHIFT_BIT_POSITION_BY_03_BITS)
+ & 0x1E));
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(YAS537_REG_HCKR);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write offset*/
+ com_rslt += smi130_set_mag_write_data(
+ ((a_data_u8[15] << 1) & 0x1E));
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(YAS537_REG_LCKR);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ /* write offset*/
+ com_rslt += smi130_set_mag_write_data(
+ (a_data_u8[16] & 0x3F));
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(YAS537_REG_OCR);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+
+ /* Assign the calibration values*/
+ /* a2 */
+ yas537_data_mbl.calib_yas537.a2 =
+ ((((a_data_u8[3]
+ << SMI130_SHIFT_BIT_POSITION_BY_02_BITS)
+ & 0x7C)
+ | (a_data_u8[4]
+ >> SMI130_SHIFT_BIT_POSITION_BY_06_BITS)) - 64);
+ /* a3 */
+ yas537_data_mbl.calib_yas537.a3 =
+ ((((a_data_u8[4] << SMI130_SHIFT_BIT_POSITION_BY_01_BIT)
+ & 0x7E)
+ | (a_data_u8[5]
+ >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS)) - 64);
+ /* a4 */
+ yas537_data_mbl.calib_yas537.a4 =
+ ((((a_data_u8[5]
+ << SMI130_SHIFT_BIT_POSITION_BY_01_BIT)
+ & 0xFE)
+ | (a_data_u8[6]
+ >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS))
+ - 128);
+ /* a5 */
+ yas537_data_mbl.calib_yas537.a5 =
+ ((((a_data_u8[6]
+ << SMI130_SHIFT_BIT_POSITION_BY_02_BITS)
+ & 0x1FC)
+ | (a_data_u8[7]
+ >> SMI130_SHIFT_BIT_POSITION_BY_06_BITS))
+ - 112);
+ /* a6 */
+ yas537_data_mbl.calib_yas537.a6 =
+ ((((a_data_u8[7]
+ << SMI130_SHIFT_BIT_POSITION_BY_01_BIT)
+ & 0x7E)
+ | (a_data_u8[8]
+ >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS)) - 64);
+ /* a7 */
+ yas537_data_mbl.calib_yas537.a7 =
+ ((((a_data_u8[8]
+ << SMI130_SHIFT_BIT_POSITION_BY_01_BIT)
+ & 0xFE)
+ | (a_data_u8[9]
+ >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS))
+ - 128);
+ /* a8 */
+ yas537_data_mbl.calib_yas537.a8 = ((a_data_u8[9] &
+ 0x7F) - 64);
+ /* a9 */
+ yas537_data_mbl.calib_yas537.a9 = ((((a_data_u8[10]
+ << SMI130_SHIFT_BIT_POSITION_BY_01_BIT) & 0x1FE)
+ | (a_data_u8[11]
+ >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS))
+ - 112);
+ /* k */
+ yas537_data_mbl.calib_yas537.k = (
+ a_data_u8[11] & 0x7F);
+ } else {
+ return ERROR;
+ }
+/* write A/D converter*/
+com_rslt += smi130_set_mag_write_data(
+YAS537_WRITE_A_D_CONVERTER);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+com_rslt += smi130_set_mag_write_addr(YAS537_REG_ADCCALR);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* write A/D converter second register*/
+com_rslt += smi130_set_mag_write_data(
+YAS537_WRITE_A_D_CONVERTER2);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+com_rslt += smi130_set_mag_write_addr(YAS537_REG_ADCCALR_ONE);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* write temperature calibration register*/
+com_rslt += smi130_set_mag_write_data(YAS537_WRITE_TEMP_CALIB);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+com_rslt += smi130_set_mag_write_addr(YAS537_REG_TRMR);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+/* write average filter register*/
+com_rslt += smi130_set_mag_write_data(
+v_avrr_u8[yas537_data_mbl.average]);
+p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+com_rslt += smi130_set_mag_write_addr(YAS537_REG_AVRR);
+p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+if (v_rcoil_u8) {
+ /* write average; filter register*/
+ com_rslt += smi130_set_mag_write_data(
+ YAS537_WRITE_FILTER);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(YAS537_REG_CONFR);
+ p_smi130->delay_msec(
+ SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+}
+
+return com_rslt;
+
+}
+/*!
+ * @brief This function used for YAS537 write data acquisition
+ * command register write
+ * @param v_command_reg_data_u8 : the value of data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas537_acquisition_command_register(
+u8 v_command_reg_data_u8)
+{
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+
+ if (p_smi130->mag_manual_enable != SMI130_MANUAL_ENABLE)
+ com_rslt = smi130_set_mag_manual_enable(
+ SMI130_MANUAL_ENABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ com_rslt = smi130_set_mag_write_data(v_command_reg_data_u8);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ /* YAMAHA YAS532-0x82*/
+ com_rslt += smi130_set_mag_write_addr(
+ SMI130_REG_YAS537_CMDR);
+ /* set the mode to RECORD*/
+ yas537_data_mbl.measure_state = YAS537_MAG_STATE_RECORD_DATA;
+ p_smi130->delay_msec(SMI130_YAS_ACQ_COMMAND_DELAY);
+ com_rslt += smi130_set_mag_read_addr(
+ YAS537_REG_TEMPERATURE_0);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ if (p_smi130->mag_manual_enable == SMI130_MANUAL_ENABLE)
+ com_rslt += smi130_set_mag_manual_enable(
+ SMI130_MANUAL_DISABLE);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+
+ return com_rslt;
+
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param xy1y2: The value of raw xy1y2 data
+ * @param xyz: The value of xyz data
+ *
+ *
+ * @return None
+ *
+ *
+ */
+static void xy1y2_to_xyz(u16 *xy1y2, s32 *xyz)
+{
+ xyz[0] = ((xy1y2[0] - 8192)
+ * 300);
+ xyz[1] = (((xy1y2[1] - xy1y2[2])
+ * 1732) / 10);
+ xyz[2] = (((-xy1y2[2] - xy1y2[2])
+ + 16384) * 300);
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_coil_stat_u8: The value of R coil status
+ * @param v_busy_u8: The value of busy status
+ * @param v_temperature_u16: The value of temperature
+ * @param xy1y2: The value of raw xy1y2 data
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas537_read_xy1y2_data(
+u8 *v_coil_stat_u8, u8 *v_busy_u8,
+u16 *v_temperature_u16, u16 *xy1y2, u8 *v_ouflow_u8)
+{
+ /* This variable used for provide the communication
+ results*/
+ SMI130_RETURN_FUNCTION_TYPE com_rslt = E_SMI130_COMM_RES;
+ /* Array holding the YAS532 calibration values */
+ u8 a_data_u8[SMI130_YAS_XY1Y2T_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE,
+ };
+ u8 i = SMI130_INIT_VALUE;
+ s32 a_h_s32[SMI130_YAS_H_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ s32 a_s_s32[SMI130_YAS_S_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ /* set command register*/
+ com_rslt = smi130_bosch_yas537_acquisition_command_register(
+ YAS537_SET_COMMAND_REGISTER);
+ /* read the yas537 sensor data of xy1y2*/
+ com_rslt +=
+ p_smi130->SMI130_BUS_READ_FUNC(p_smi130->dev_addr,
+ SMI130_USER_DATA_MAG_X_LSB__REG,
+ a_data_u8, SMI130_MAG_YAS_DATA_LENGTH);
+ /* read the busy flag*/
+ *v_busy_u8 = a_data_u8[2]
+ >> SMI130_SHIFT_BIT_POSITION_BY_07_BITS;
+ /* read the coil status*/
+ *v_coil_stat_u8 =
+ ((a_data_u8[2] >>
+ SMI130_SHIFT_BIT_POSITION_BY_06_BITS) & 0X01);
+ /* read temperature data*/
+ *v_temperature_u16 = (u16)((a_data_u8[0]
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | a_data_u8[1]);
+ /* read x data*/
+ xy1y2[0] = (u16)(((a_data_u8[2] &
+ 0x3F)
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | (a_data_u8[3]));
+ /* read y1 data*/
+ xy1y2[1] = (u16)((a_data_u8[4]
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | a_data_u8[5]);
+ /* read y2 data*/
+ xy1y2[2] = (u16)((a_data_u8[6]
+ << SMI130_SHIFT_BIT_POSITION_BY_08_BITS)
+ | a_data_u8[7]);
+ for (i = 0; i < 3; i++)
+ yas537_data_mbl.last_raw[i] = xy1y2[i];
+ yas537_data_mbl.last_raw[i] = *v_temperature_u16;
+ if (yas537_data_mbl.calib_yas537.ver == 1) {
+ for (i = 0; i < 3; i++)
+ a_s_s32[i] = xy1y2[i] - 8192;
+ /* read hx*/
+ a_h_s32[0] = ((yas537_data_mbl.calib_yas537.k * (
+ (128 * a_s_s32[0]) +
+ (yas537_data_mbl.calib_yas537.a2 * a_s_s32[1]) +
+ (yas537_data_mbl.calib_yas537.a3 * a_s_s32[2])))
+ / (8192));
+ /* read hy1*/
+ a_h_s32[1] = ((yas537_data_mbl.calib_yas537.k * (
+ (yas537_data_mbl.calib_yas537.a4 * a_s_s32[0]) +
+ (yas537_data_mbl.calib_yas537.a5 * a_s_s32[1]) +
+ (yas537_data_mbl.calib_yas537.a6 * a_s_s32[2])))
+ / (8192));
+ /* read hy2*/
+ a_h_s32[2] = ((yas537_data_mbl.calib_yas537.k * (
+ (yas537_data_mbl.calib_yas537.a7 * a_s_s32[0]) +
+ (yas537_data_mbl.calib_yas537.a8 * a_s_s32[1]) +
+ (yas537_data_mbl.calib_yas537.a9 * a_s_s32[2])))
+ / (8192));
+
+ for (i = 0; i < 3; i++) {
+ if (a_h_s32[i] < -8192)
+ a_h_s32[i] = -8192;
+
+ if (8192 < a_h_s32[i])
+ a_h_s32[i] = 8192;
+
+ xy1y2[i] = a_h_s32[i] + 8192;
+
+ }
+ }
+ *v_ouflow_u8 = 0;
+ for (i = 0; i < 3; i++) {
+ if (YAS537_DATA_OVERFLOW <= xy1y2[i])
+ *v_ouflow_u8 |= (1 << (i * 2));
+ if (xy1y2[i] == YAS537_DATA_UNDERFLOW)
+ *v_ouflow_u8 |= (1 << (i * 2 + 1));
+ }
+
+ return com_rslt;
+
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+static SMI130_RETURN_FUNCTION_TYPE invalid_magnetic_field(
+u16 *v_cur_u16, u16 *v_last_u16)
+{
+ s16 invalid_thresh[] = {1500, 1500, 1500};
+ u8 i = SMI130_INIT_VALUE;
+
+ for (i = 0; i < 3; i++)
+ if (invalid_thresh[i] < ABS(v_cur_u16[i] - v_last_u16[i]))
+ return 1;
+ return 0;
+}
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas537_measure_xyz_data(
+u8 *v_ouflow_u8, struct yas_vector *vector_xyz)
+{
+ s32 a_xyz_tmp_s32[SMI130_YAS_TEMP_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ u8 i = SMI130_INIT_VALUE;
+ s8 com_rslt = SMI130_INIT_VALUE;
+ u8 v_busy_u8 = SMI130_INIT_VALUE;
+ u8 v_rcoil_u8 = SMI130_INIT_VALUE;
+ u16 v_temperature_u16 = SMI130_INIT_VALUE;
+ u16 a_xy1y2_u16[SMI130_YAS_XY1Y2_DATA_SIZE] = {
+ SMI130_INIT_VALUE, SMI130_INIT_VALUE, SMI130_INIT_VALUE};
+ *v_ouflow_u8 = 0;
+ /* read the yas537 xy1y2 data*/
+ com_rslt = smi130_bosch_yamaha_yas537_read_xy1y2_data(
+ &v_rcoil_u8, &v_busy_u8,
+ &v_temperature_u16, a_xy1y2_u16, v_ouflow_u8);
+ /* linear calculation*/
+ xy1y2_to_xyz(a_xy1y2_u16, vector_xyz->yas537_vector_xyz);
+ if (yas537_data_mbl.transform != SMI130_NULL) {
+ for (i = 0; i < 3; i++) {
+ a_xyz_tmp_s32[i] = ((
+ yas537_data_mbl.transform[i + 3]
+ * vector_xyz->yas537_vector_xyz[0])
+ + (yas537_data_mbl.transform[
+ i * 3 + 1]
+ * vector_xyz->yas537_vector_xyz[1])
+ + (yas537_data_mbl.transform[
+ i * 3 + 2]
+ * vector_xyz->yas537_vector_xyz[2]));
+ }
+ yas537_set_vector(
+ vector_xyz->yas537_vector_xyz, a_xyz_tmp_s32);
+ }
+ for (i = 0; i < 3; i++) {
+ vector_xyz->yas537_vector_xyz[i] -=
+ vector_xyz->yas537_vector_xyz[i] % 10;
+ if (*v_ouflow_u8 & (1 <<
+ (i * 2)))
+ vector_xyz->yas537_vector_xyz[i] +=
+ 1; /* set overflow */
+ if (*v_ouflow_u8 & (1 << (i * 2 + 1)))
+ /* set underflow */
+ vector_xyz->yas537_vector_xyz[i] += 2;
+ }
+ if (v_busy_u8)
+ return ERROR;
+ switch (yas537_data_mbl.measure_state) {
+ case YAS537_MAG_STATE_INIT_COIL:
+ if (p_smi130->mag_manual_enable != SMI130_MANUAL_ENABLE)
+ com_rslt = smi130_set_mag_manual_enable(
+ SMI130_MANUAL_ENABLE);
+ com_rslt += smi130_set_mag_write_data(YAS537_WRITE_CONFR);
+ p_smi130->delay_msec(SMI130_GEN_READ_WRITE_DELAY);
+ com_rslt += smi130_set_mag_write_addr(YAS537_REG_CONFR);
+ p_smi130->delay_msec(SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY);
+ yas537_data_mbl.measure_state = YAS537_MAG_STATE_RECORD_DATA;
+ if (p_smi130->mag_manual_enable == SMI130_MANUAL_ENABLE)
+ com_rslt = smi130_set_mag_manual_enable(
+ SMI130_MANUAL_DISABLE);
+ break;
+ case YAS537_MAG_STATE_RECORD_DATA:
+ if (v_rcoil_u8)
+ break;
+ yas537_set_vector(yas537_data_mbl.last_after_rcoil, a_xy1y2_u16);
+ yas537_data_mbl.measure_state = YAS537_MAG_STATE_NORMAL;
+ break;
+ case YAS537_MAG_STATE_NORMAL:
+ if (SMI130_INIT_VALUE < v_ouflow_u8
+ || invalid_magnetic_field(a_xy1y2_u16,
+ yas537_data_mbl.last_after_rcoil)) {
+ yas537_data_mbl.measure_state = YAS537_MAG_STATE_INIT_COIL;
+ for (i = 0; i < 3; i++) {
+ if (!*v_ouflow_u8)
+ vector_xyz->yas537_vector_xyz[i] += 3;
+ }
+ }
+ break;
+ }
+
+ return com_rslt;
+}
+/*!
+ * @brief This function used for reading
+ * smi130_t structure
+ *
+ * @return the reference and values of smi130_t
+ *
+ *
+*/
+struct smi130_t *smi130_get_ptr(void)
+{
+ return p_smi130;
+}
diff --git a/drivers/input/sensors/smi130/smi130.h b/drivers/input/sensors/smi130/smi130.h
new file mode 100644
index 000000000000..c62f65cd927e
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130.h
@@ -0,0 +1,11851 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+*
+* smi130.h
+* Date : 2015/04/02
+* @id 836294d
+* Revision : 2.0.9 $
+* @brief
+* The head file of SMI130API
+*
+
+**************************************************************************/
+/*! \file smi130.h
+ \brief SMI130 Sensor Driver Support Header File */
+/* user defined code to be added here ... */
+#ifndef __SMI130_H__
+#define __SMI130_H__
+
+/*!
+* @brief The following definition uses for define the data types
+*
+* @note While porting the API please consider the following
+* @note Please check the version of C standard
+* @note Are you using Linux platform
+*/
+
+/*!
+* @brief For the Linux platform support
+* Please use the types.h for your data types definitions
+*/
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+#else /* ! __KERNEL__ */
+/**********************************************************
+* These definition uses for define the C
+* standard version data types
+***********************************************************/
+# if !defined(__STDC_VERSION__)
+
+/************************************************
+ * compiler is C11 C standard
+************************************************/
+#if (__STDC_VERSION__ == 201112L)
+
+/************************************************/
+#include <stdint.h>
+/************************************************/
+
+/*unsigned integer types*/
+#define u8 uint8_t
+#define u16 uint16_t
+#define u32 uint32_t
+#define u64 uint64_t
+
+/*signed integer types*/
+#define s8 int8_t
+#define s16 int16_t
+#define s32 int32_t
+#define s64 int64_t
+/************************************************
+ * compiler is C99 C standard
+************************************************/
+
+#elif (__STDC_VERSION__ == 199901L)
+
+/* stdint.h is a C99 supported c library.
+which is used to fixed the integer size*/
+/************************************************/
+#include <stdint.h>
+/************************************************/
+
+/*unsigned integer types*/
+#define u8 uint8_t
+#define u16 uint16_t
+#define u32 uint32_t
+#define u64 uint64_t
+
+/*signed integer types*/
+#define s8 int8_t
+#define s16 int16_t
+#define s32 int32_t
+#define s64 int64_t
+/************************************************
+ * compiler is C89 or other C standard
+************************************************/
+#else /* !defined(__STDC_VERSION__) */
+/* By default it is defined as 32 bit machine configuration*/
+/* define the definition based on your machine configuration*/
+/* define the data types based on your
+ machine/compiler/controller configuration*/
+#define MACHINE_32_BIT
+
+/* If your machine support 16 bit
+define the MACHINE_16_BIT*/
+#ifdef MACHINE_16_BIT
+#include <limits.h>
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed long int
+
+#if defined(LONG_MAX) && LONG_MAX == 0x7fffffffffffffffL
+#define s64 long int
+#define u64 unsigned long int
+#elif defined(LLONG_MAX) && (LLONG_MAX == 0x7fffffffffffffffLL)
+#define s64 long long int
+#define u64 unsigned long long int
+#else
+#warning Either the correct data type for signed 64 bit integer \
+could not be found, or 64 bit integers are not supported in your environment.
+#warning If 64 bit integers are supported on your platform, \
+please set s64 manually.
+#endif
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned long int
+
+/* If your machine support 32 bit
+define the MACHINE_32_BIT*/
+#elif defined MACHINE_32_BIT
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed int
+#define s64 signed long long int
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned int
+#define u64 unsigned long long int
+
+/* If your machine support 64 bit
+define the MACHINE_64_BIT*/
+#elif defined MACHINE_64_BIT
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed int
+#define s64 signed long int
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned int
+#define u64 unsigned long int
+
+#else
+#warning The data types defined above which not supported \
+define the data types manually
+#endif
+#endif
+
+/*** This else will execute for the compilers
+ * which are not supported the C standards
+ * Like C89/C99/C11***/
+#else
+/* By default it is defined as 32 bit machine configuration*/
+/* define the definition based on your machine configuration*/
+/* define the data types based on your
+ machine/compiler/controller configuration*/
+#define MACHINE_32_BIT
+
+/* If your machine support 16 bit
+define the MACHINE_16_BIT*/
+#ifdef MACHINE_16_BIT
+#include <limits.h>
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed long int
+
+#if defined(LONG_MAX) && LONG_MAX == 0x7fffffffffffffffL
+#define s64 long int
+#define u64 unsigned long int
+#elif defined(LLONG_MAX) && (LLONG_MAX == 0x7fffffffffffffffLL)
+#define s64 long long int
+#define u64 unsigned long long int
+#else
+#warning Either the correct data type for signed 64 bit integer \
+could not be found, or 64 bit integers are not supported in your environment.
+#warning If 64 bit integers are supported on your platform, \
+please set s64 manually.
+#endif
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned long int
+
+/* If your machine support 32 bit
+define the MACHINE_32_BIT*/
+#elif defined MACHINE_32_BIT
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed int
+#define s64 signed long long int
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned int
+#define u64 unsigned long long int
+
+/* If your machine support 64 bit
+define the MACHINE_64_BIT*/
+#elif defined MACHINE_64_BIT
+/*signed integer types*/
+#define s8 signed char
+#define s16 signed short int
+#define s32 signed int
+#define s64 signed long int
+
+/*unsigned integer types*/
+#define u8 unsigned char
+#define u16 unsigned short int
+#define u32 unsigned int
+#define u64 unsigned long int
+
+#else
+#warning The data types defined above which not supported \
+define the data types manually
+#endif
+#endif
+#endif
+/***************************************************************/
+/**\name BUS READ AND WRITE FUNCTION POINTERS */
+/***************************************************************/
+/*!
+ @brief Define the calling convention of YOUR bus communication routine.
+ @note This includes types of parameters. This example shows the
+ configuration for an SPI bus link.
+
+ If your communication function looks like this:
+
+ write_my_bus_xy(u8 device_addr, u8 register_addr,
+ u8 * data, u8 length);
+
+ The SMI130_WR_FUNC_PTR would equal:
+
+ SMI130_WR_FUNC_PTR s8 (* bus_write)(u8,
+ u8, u8 *, u8)
+
+ Parameters can be mixed as needed refer to the
+ @ref SMI130_BUS_WRITE_FUNC macro.
+
+
+*/
+#define SMI130_WR_FUNC_PTR s8 (*bus_write)(u8, u8,\
+u8 *, u8)
+/**< link macro between API function calls and bus write function
+ @note The bus write function can change since this is a
+ system dependant issue.
+
+ If the bus_write parameter calling order is like: reg_addr,
+ reg_data, wr_len it would be as it is here.
+
+ If the parameters are differently ordered or your communication
+ function like I2C need to know the device address,
+ you can change this macro accordingly.
+
+
+ SMI130_BUS_WRITE_FUNC(dev_addr, reg_addr, reg_data, wr_len)\
+ bus_write(dev_addr, reg_addr, reg_data, wr_len)
+
+ This macro lets all API functions call YOUR communication routine in a
+ way that equals your definition in the
+ @ref SMI130_WR_FUNC_PTR definition.
+
+*/
+#define SMI130_BUS_WRITE_FUNC(dev_addr, reg_addr, reg_data, wr_len)\
+ bus_write(dev_addr, reg_addr, reg_data, wr_len)
+
+/**< Define the calling convention of YOUR bus communication routine.
+ @note This includes types of parameters. This example shows the
+ configuration for an SPI bus link.
+
+ If your communication function looks like this:
+
+ read_my_bus_xy(u8 device_addr, u8 register_addr,
+ u8 * data, u8 length);
+
+ The SMI130_RD_FUNC_PTR would equal:
+
+ SMI130_RD_FUNC_PTR s8 (* bus_read)(u8,
+ u8, u8 *, u8)
+
+ Parameters can be mixed as needed refer to the
+ refer SMI130_BUS_READ_FUNC macro.
+
+*/
+#define SMI130_SPI_RD_MASK (0x80) /* for spi read transactions on SPI the
+ MSB has to be set */
+#define SMI130_RD_FUNC_PTR s8 (*bus_read)(u8,\
+ u8, u8 *, u8)
+
+#define SMI130_BRD_FUNC_PTR s8 \
+(*burst_read)(u8, u8, u8 *, u32)
+
+/**< link macro between API function calls and bus read function
+ @note The bus write function can change since this is a
+ system dependant issue.
+
+ If the bus_read parameter calling order is like: reg_addr,
+ reg_data, wr_len it would be as it is here.
+
+ If the parameters are differently ordered or your communication
+ function like I2C need to know the device address,
+ you can change this macro accordingly.
+
+
+ SMI130_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, wr_len)\
+ bus_read(dev_addr, reg_addr, reg_data, wr_len)
+
+ This macro lets all API functions call YOUR communication routine in a
+ way that equals your definition in the
+ refer SMI130_WR_FUNC_PTR definition.
+
+ @note: this macro also includes the "MSB='1'
+ for reading SMI130 addresses.
+
+*/
+#define SMI130_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, r_len)\
+ bus_read(dev_addr, reg_addr, reg_data, r_len)
+
+#define SMI130_BURST_READ_FUNC(device_addr, \
+register_addr, register_data, rd_len)\
+burst_read(device_addr, register_addr, register_data, rd_len)
+
+
+#define SMI130_MDELAY_DATA_TYPE u32
+
+/***************************************************************/
+/**\name BUS READ AND WRITE FUNCTION POINTERS */
+/***************************************************************/
+#define SMI130_I2C_ADDR1 0x68 /**< I2C Address needs to be changed */
+#define SMI130_I2C_ADDR2 0x69 /**< I2C Address needs to be changed */
+#define SMI130_AUX_BMM150_I2C_ADDRESS (0x10)
+#define SMI130_AUX_YAS532_I2C_ADDRESS (0x2E)
+/**< I2C address of YAS532*/
+#define SMI130_AKM09911_I2C_ADDRESS 0x0C/**< I2C address of AKM09911*/
+/**< I2C address of AKM09911*/
+#define SMI130_AUX_AKM09911_I2C_ADDR_2 (0x0D)
+/**< I2C address of AKM09911*/
+#define SMI130_AUX_AKM09912_I2C_ADDR_1 (0x0C)
+/**< I2C address of AKM09912*/
+#define SMI130_AUX_AKM09912_I2C_ADDR_2 (0x0D)
+/**< I2C address of AKM09912*/
+#define SMI130_AUX_AKM09912_I2C_ADDR_3 (0x0E)
+/**< I2C address of AKM09912*/
+#define SMI130_AKM09912_I2C_ADDRESS 0x0F/**< I2C address of akm09912*/
+
+#define SMI130_YAS532_I2C_ADDRESS 0x2E/**< I2C address of YAS532*/
+/*******************************************/
+/**\name CONSTANTS */
+/******************************************/
+#define SMI130_INIT_VALUE (0)
+#define SMI130_GEN_READ_WRITE_DATA_LENGTH (1)
+#define SMI130_MAXIMUM_TIMEOUT (10)
+/* output data rate condition check*/
+#define SMI130_OUTPUT_DATA_RATE0 (0)
+#define SMI130_OUTPUT_DATA_RATE1 (1)
+#define SMI130_OUTPUT_DATA_RATE2 (2)
+#define SMI130_OUTPUT_DATA_RATE3 (3)
+#define SMI130_OUTPUT_DATA_RATE4 (4)
+#define SMI130_OUTPUT_DATA_RATE5 (5)
+#define SMI130_OUTPUT_DATA_RATE6 (14)
+#define SMI130_OUTPUT_DATA_RATE7 (15)
+/* accel range check*/
+#define SMI130_ACCEL_RANGE0 (3)
+#define SMI130_ACCEL_RANGE1 (5)
+#define SMI130_ACCEL_RANGE3 (8)
+#define SMI130_ACCEL_RANGE4 (12)
+/* check the status of registers*/
+#define SMI130_FOC_STAT_HIGH (1)
+#define SMI130_SIG_MOTION_STAT_HIGH (1)
+#define SMI130_STEP_DET_STAT_HIGH (1)
+
+/*condition check for reading and writing data*/
+#define SMI130_MAX_VALUE_SIGNIFICANT_MOTION (1)
+#define SMI130_MAX_VALUE_FIFO_FILTER (1)
+#define SMI130_MAX_VALUE_FIFO_TIME (1)
+#define SMI130_MAX_VALUE_FIFO_INTR (1)
+#define SMI130_MAX_VALUE_FIFO_HEADER (1)
+#define SMI130_MAX_VALUE_FIFO_MAG (1)
+#define SMI130_MAX_VALUE_FIFO_ACCEL (1)
+#define SMI130_MAX_VALUE_FIFO_GYRO (1)
+#define SMI130_MAX_VALUE_SOURCE_INTR (1)
+#define SMI130_MAX_VALUE_LOW_G_MODE (1)
+#define SMI130_MAX_VALUE_NO_MOTION (1)
+#define SMI130_MAX_VALUE_TAP_SHOCK (1)
+#define SMI130_MAX_VALUE_TAP_QUIET (1)
+#define SMI130_MAX_VALUE_ORIENT_UD (1)
+#define SMI130_MAX_VALUE_ORIENT_AXES (1)
+#define SMI130_MAX_VALUE_NVM_PROG (1)
+#define SMI130_MAX_VALUE_SPI3 (1)
+#define SMI130_MAX_VALUE_PAGE (1)
+#define SMI130_MAX_VALUE_I2C_WDT (1)
+#define SMI130_MAX_VALUE_SLEEP_STATE (1)
+#define SMI130_MAX_VALUE_WAKEUP_INTR (1)
+#define SMI130_MAX_VALUE_SELFTEST_SIGN (1)
+#define SMI130_MAX_VALUE_SELFTEST_AMP (1)
+#define SMI130_MAX_VALUE_SELFTEST_START (1)
+#define SMI130_MAX_GYRO_WAKEUP_TRIGGER (3)
+#define SMI130_MAX_ACCEL_SELFTEST_AXIS (3)
+#define SMI130_MAX_GYRO_STEP_COUNTER (1)
+#define SMI130_MAX_GYRO_BW (3)
+#define SMI130_MAX_ACCEL_BW (7)
+#define SMI130_MAX_ORIENT_MODE (3)
+#define SMI130_MAX_ORIENT_BLOCKING (3)
+#define SMI130_MAX_FLAT_HOLD (3)
+#define SMI130_MAX_ACCEL_FOC (3)
+#define SMI130_MAX_IF_MODE (3)
+#define SMI130_MAX_TARGET_PAGE (3)
+#define SMI130_MAX_GYRO_RANGE (4)
+#define SMI130_MAX_GYRO_SLEEP_TIGGER (7)
+#define SMI130_MAX_TAP_TURN (7)
+#define SMI130_MAX_UNDER_SAMPLING (1)
+#define SMI130_MAX_UNDER_SIG_MOTION (3)
+#define SMI130_MAX_ACCEL_OUTPUT_DATA_RATE (12)
+#define SMI130_MAX_LATCH_INTR (15)
+#define SMI130_MAX_FLAT_HYST (15)
+#define SMI130_MAX_ORIENT_THETA (63)
+#define SMI130_MAX_FLAT_THETA (63)
+
+/* FIFO index definitions*/
+#define SMI130_FIFO_X_LSB_DATA (0)
+#define SMI130_FIFO_X_MSB_DATA (1)
+#define SMI130_FIFO_Y_LSB_DATA (2)
+#define SMI130_FIFO_Y_MSB_DATA (3)
+#define SMI130_FIFO_Z_LSB_DATA (4)
+#define SMI130_FIFO_Z_MSB_DATA (5)
+#define SMI130_FIFO_R_LSB_DATA (6)
+#define SMI130_FIFO_R_MSB_DATA (7)
+/* FIFO gyro definition*/
+#define SMI130_GA_FIFO_G_X_LSB (0)
+#define SMI130_GA_FIFO_G_X_MSB (1)
+#define SMI130_GA_FIFO_G_Y_LSB (2)
+#define SMI130_GA_FIFO_G_Y_MSB (3)
+#define SMI130_GA_FIFO_G_Z_LSB (4)
+#define SMI130_GA_FIFO_G_Z_MSB (5)
+#define SMI130_GA_FIFO_A_X_LSB (6)
+#define SMI130_GA_FIFO_A_X_MSB (7)
+#define SMI130_GA_FIFO_A_Y_LSB (8)
+#define SMI130_GA_FIFO_A_Y_MSB (9)
+#define SMI130_GA_FIFO_A_Z_LSB (10)
+#define SMI130_GA_FIFO_A_Z_MSB (11)
+/* FIFO mag/gyro/accel definition*/
+#define SMI130_MGA_FIFO_M_X_LSB (0)
+#define SMI130_MGA_FIFO_M_X_MSB (1)
+#define SMI130_MGA_FIFO_M_Y_LSB (2)
+#define SMI130_MGA_FIFO_M_Y_MSB (3)
+#define SMI130_MGA_FIFO_M_Z_LSB (4)
+#define SMI130_MGA_FIFO_M_Z_MSB (5)
+#define SMI130_MGA_FIFO_M_R_LSB (6)
+#define SMI130_MGA_FIFO_M_R_MSB (7)
+#define SMI130_MGA_FIFO_G_X_LSB (8)
+#define SMI130_MGA_FIFO_G_X_MSB (9)
+#define SMI130_MGA_FIFO_G_Y_LSB (10)
+#define SMI130_MGA_FIFO_G_Y_MSB (11)
+#define SMI130_MGA_FIFO_G_Z_LSB (12)
+#define SMI130_MGA_FIFO_G_Z_MSB (13)
+#define SMI130_MGA_FIFO_A_X_LSB (14)
+#define SMI130_MGA_FIFO_A_X_MSB (15)
+#define SMI130_MGA_FIFO_A_Y_LSB (16)
+#define SMI130_MGA_FIFO_A_Y_MSB (17)
+#define SMI130_MGA_FIFO_A_Z_LSB (18)
+#define SMI130_MGA_FIFO_A_Z_MSB (19)
+/* FIFO mag definition*/
+#define SMI130_MA_FIFO_M_X_LSB (0)
+#define SMI130_MA_FIFO_M_X_MSB (1)
+#define SMI130_MA_FIFO_M_Y_LSB (2)
+#define SMI130_MA_FIFO_M_Y_MSB (3)
+#define SMI130_MA_FIFO_M_Z_LSB (4)
+#define SMI130_MA_FIFO_M_Z_MSB (5)
+#define SMI130_MA_FIFO_M_R_LSB (6)
+#define SMI130_MA_FIFO_M_R_MSB (7)
+#define SMI130_MA_FIFO_A_X_LSB (8)
+#define SMI130_MA_FIFO_A_X_MSB (9)
+#define SMI130_MA_FIFO_A_Y_LSB (10)
+#define SMI130_MA_FIFO_A_Y_MSB (11)
+#define SMI130_MA_FIFO_A_Z_LSB (12)
+#define SMI130_MA_FIFO_A_Z_MSB (13)
+/* FIFO mag/gyro definition*/
+#define SMI130_MG_FIFO_M_X_LSB (0)
+#define SMI130_MG_FIFO_M_X_MSB (1)
+#define SMI130_MG_FIFO_M_Y_LSB (2)
+#define SMI130_MG_FIFO_M_Y_MSB (3)
+#define SMI130_MG_FIFO_M_Z_LSB (4)
+#define SMI130_MG_FIFO_M_Z_MSB (5)
+#define SMI130_MG_FIFO_M_R_LSB (6)
+#define SMI130_MG_FIFO_M_R_MSB (7)
+#define SMI130_MG_FIFO_G_X_LSB (8)
+#define SMI130_MG_FIFO_G_X_MSB (9)
+#define SMI130_MG_FIFO_G_Y_LSB (10)
+#define SMI130_MG_FIFO_G_Y_MSB (11)
+#define SMI130_MG_FIFO_G_Z_LSB (12)
+#define SMI130_MG_FIFO_G_Z_MSB (13)
+/* FIFO length definitions*/
+#define SMI130_FIFO_SENSOR_TIME_LSB (0)
+#define SMI130_FIFO_SENSOR_TIME_XLSB (1)
+#define SMI130_FIFO_SENSOR_TIME_MSB (2)
+#define SMI130_FIFO_SENSOR_TIME_LENGTH (3)
+#define SMI130_FIFO_A_LENGTH (6)
+#define SMI130_FIFO_G_LENGTH (6)
+#define SMI130_FIFO_M_LENGTH (8)
+#define SMI130_FIFO_AG_LENGTH (12)
+#define SMI130_FIFO_AMG_LENGTH (20)
+#define SMI130_FIFO_MA_OR_MG_LENGTH (14)
+
+/* bus read and write length for mag, accel and gyro*/
+#define SMI130_MAG_X_DATA_LENGTH (2)
+#define SMI130_MAG_Y_DATA_LENGTH (2)
+#define SMI130_MAG_Z_DATA_LENGTH (2)
+#define SMI130_MAG_R_DATA_LENGTH (2)
+#define SMI130_MAG_XYZ_DATA_LENGTH (6)
+#define SMI130_MAG_XYZR_DATA_LENGTH (8)
+#define SMI130_MAG_YAS_DATA_LENGTH (8)
+#define SMI130_GYRO_DATA_LENGTH (2)
+#define SMI130_GYRO_XYZ_DATA_LENGTH (6)
+#define SMI130_ACCEL_DATA_LENGTH (2)
+#define SMI130_ACCEL_XYZ_DATA_LENGTH (6)
+#define SMI130_TEMP_DATA_LENGTH (2)
+#define SMI130_FIFO_DATA_LENGTH (2)
+#define SMI130_STEP_COUNTER_LENGTH (2)
+#define SMI130_SENSOR_TIME_LENGTH (3)
+
+/* Delay definitions*/
+#define SMI130_SEC_INTERFACE_GEN_READ_WRITE_DELAY (5)
+#define SMI130_BMM150_WAKEUP_DELAY1 (2)
+#define SMI130_BMM150_WAKEUP_DELAY2 (3)
+#define SMI130_BMM150_WAKEUP_DELAY3 (1)
+#define SMI130_YAS532_OFFSET_DELAY (2)
+#define SMI130_GEN_READ_WRITE_DELAY (1)
+#define SMI130_YAS532_MEASUREMENT_DELAY (25)
+#define SMI130_YAS_ACQ_COMMAND_DELAY (50)
+#define SMI130_YAS532_SET_INITIAL_VALUE_DELAY (200)
+#define SMI130_AKM_INIT_DELAY (60)
+/****************************************************/
+/**\name ARRAY SIZE DEFINITIONS */
+/***************************************************/
+#define SMI130_ACCEL_X_DATA_SIZE (2)
+#define SMI130_ACCEL_Y_DATA_SIZE (2)
+#define SMI130_ACCEL_Z_DATA_SIZE (2)
+#define SMI130_ACCEL_XYZ_DATA_SIZE (6)
+
+#define SMI130_GYRO_X_DATA_SIZE (2)
+#define SMI130_GYRO_Y_DATA_SIZE (2)
+#define SMI130_GYRO_Z_DATA_SIZE (2)
+#define SMI130_GYRO_XYZ_DATA_SIZE (6)
+
+#define SMI130_MAG_X_DATA_SIZE (2)
+#define SMI130_MAG_Y_DATA_SIZE (2)
+#define SMI130_MAG_Z_DATA_SIZE (2)
+#define SMI130_MAG_R_DATA_SIZE (2)
+#define SMI130_MAG_XYZ_DATA_SIZE (6)
+#define SMI130_MAG_XYZR_DATA_SIZE (8)
+#define SMI130_MAG_TRIM_DATA_SIZE (16)
+
+
+#define SMI130_TEMP_DATA_SIZE (2)
+#define SMI130_FIFO_DATA_SIZE (2)
+#define SMI130_STEP_COUNT_DATA_SIZE (2)
+
+#define SMI130_SENSOR_TIME_DATA_SIZE (3)
+#define SMI130_AKM_SENSITIVITY_DATA_SIZE (3)
+#define SMI130_HARD_OFFSET_DATA_SIZE (3)
+#define SMI130_YAS_XY1Y2_DATA_SIZE (3)
+#define SMI130_YAS_FLAG_DATA_SIZE (3)
+#define SMI130_YAS_TEMP_DATA_SIZE (3)
+#define SMI130_YAS_H_DATA_SIZE (3)
+#define SMI130_YAS_S_DATA_SIZE (3)
+#define SMI130_YAS_CORRECT_DATA_SIZE (5)
+#define SMI130_YAS_XY1Y2T_DATA_SIZE (8)
+#define SMI130_YAS537_CALIB_DATA_SIZE (17)
+#define SMI130_YAS532_CALIB_DATA_SIZE (14)
+/****************************************************/
+/**\name ARRAY PARAMETER DEFINITIONS */
+/***************************************************/
+#define SMI130_SENSOR_TIME_MSB_BYTE (2)
+#define SMI130_SENSOR_TIME_XLSB_BYTE (1)
+#define SMI130_SENSOR_TIME_LSB_BYTE (0)
+
+#define SMI130_MAG_X_LSB_BYTE (0)
+#define SMI130_MAG_X_MSB_BYTE (1)
+#define SMI130_MAG_Y_LSB_BYTE (0)
+#define SMI130_MAG_Y_MSB_BYTE (1)
+#define SMI130_MAG_Z_LSB_BYTE (0)
+#define SMI130_MAG_Z_MSB_BYTE (1)
+#define SMI130_MAG_R_LSB_BYTE (0)
+#define SMI130_MAG_R_MSB_BYTE (1)
+#define SMI130_DATA_FRAME_MAG_X_LSB_BYTE (0)
+#define SMI130_DATA_FRAME_MAG_X_MSB_BYTE (1)
+#define SMI130_DATA_FRAME_MAG_Y_LSB_BYTE (2)
+#define SMI130_DATA_FRAME_MAG_Y_MSB_BYTE (3)
+#define SMI130_DATA_FRAME_MAG_Z_LSB_BYTE (4)
+#define SMI130_DATA_FRAME_MAG_Z_MSB_BYTE (5)
+#define SMI130_DATA_FRAME_MAG_R_LSB_BYTE (6)
+#define SMI130_DATA_FRAME_MAG_R_MSB_BYTE (7)
+
+#define SMI130_GYRO_X_LSB_BYTE (0)
+#define SMI130_GYRO_X_MSB_BYTE (1)
+#define SMI130_GYRO_Y_LSB_BYTE (0)
+#define SMI130_GYRO_Y_MSB_BYTE (1)
+#define SMI130_GYRO_Z_LSB_BYTE (0)
+#define SMI130_GYRO_Z_MSB_BYTE (1)
+#define SMI130_DATA_FRAME_GYRO_X_LSB_BYTE (0)
+#define SMI130_DATA_FRAME_GYRO_X_MSB_BYTE (1)
+#define SMI130_DATA_FRAME_GYRO_Y_LSB_BYTE (2)
+#define SMI130_DATA_FRAME_GYRO_Y_MSB_BYTE (3)
+#define SMI130_DATA_FRAME_GYRO_Z_LSB_BYTE (4)
+#define SMI130_DATA_FRAME_GYRO_Z_MSB_BYTE (5)
+
+#define SMI130_ACCEL_X_LSB_BYTE (0)
+#define SMI130_ACCEL_X_MSB_BYTE (1)
+#define SMI130_ACCEL_Y_LSB_BYTE (0)
+#define SMI130_ACCEL_Y_MSB_BYTE (1)
+#define SMI130_ACCEL_Z_LSB_BYTE (0)
+#define SMI130_ACCEL_Z_MSB_BYTE (1)
+#define SMI130_DATA_FRAME_ACCEL_X_LSB_BYTE (0)
+#define SMI130_DATA_FRAME_ACCEL_X_MSB_BYTE (1)
+#define SMI130_DATA_FRAME_ACCEL_Y_LSB_BYTE (2)
+#define SMI130_DATA_FRAME_ACCEL_Y_MSB_BYTE (3)
+#define SMI130_DATA_FRAME_ACCEL_Z_LSB_BYTE (4)
+#define SMI130_DATA_FRAME_ACCEL_Z_MSB_BYTE (5)
+
+#define SMI130_TEMP_LSB_BYTE (0)
+#define SMI130_TEMP_MSB_BYTE (1)
+
+#define SMI130_FIFO_LENGTH_LSB_BYTE (0)
+#define SMI130_FIFO_LENGTH_MSB_BYTE (1)
+
+#define SMI130_STEP_COUNT_LSB_BYTE (0)
+#define SMI130_STEP_COUNT_MSB_BYTE (1)
+/****************************************************/
+/**\name ERROR CODES */
+/***************************************************/
+
+#define E_SMI130_NULL_PTR ((s8)-127)
+#define E_SMI130_COMM_RES ((s8)-1)
+#define E_SMI130_OUT_OF_RANGE ((s8)-2)
+#define E_SMI130_BUSY ((s8)-3)
+#define SUCCESS ((u8)0)
+#define ERROR ((s8)-1)
+
+/* Constants */
+#define SMI130_NULL (0)
+#define SMI130_DELAY_SETTLING_TIME (5)
+/*This refers SMI130 return type as s8 */
+#define SMI130_RETURN_FUNCTION_TYPE s8
+/****************************************************/
+/**\name REGISTER DEFINITIONS */
+/***************************************************/
+/*******************/
+/**\name CHIP ID */
+/*******************/
+#define SMI130_USER_CHIP_ID_ADDR (0x00)
+/*******************/
+/**\name ERROR STATUS */
+/*******************/
+#define SMI130_USER_ERROR_ADDR (0X02)
+/*******************/
+/**\name POWER MODE STATUS */
+/*******************/
+#define SMI130_USER_PMU_STAT_ADDR (0X03)
+/*******************/
+/**\name MAG DATA REGISTERS */
+/*******************/
+#define SMI130_USER_DATA_0_ADDR (0X04)
+#define SMI130_USER_DATA_1_ADDR (0X05)
+#define SMI130_USER_DATA_2_ADDR (0X06)
+#define SMI130_USER_DATA_3_ADDR (0X07)
+#define SMI130_USER_DATA_4_ADDR (0X08)
+#define SMI130_USER_DATA_5_ADDR (0X09)
+#define SMI130_USER_DATA_6_ADDR (0X0A)
+#define SMI130_USER_DATA_7_ADDR (0X0B)
+/*******************/
+/**\name GYRO DATA REGISTERS */
+/*******************/
+#define SMI130_USER_DATA_8_ADDR (0X0C)
+#define SMI130_USER_DATA_9_ADDR (0X0D)
+#define SMI130_USER_DATA_10_ADDR (0X0E)
+#define SMI130_USER_DATA_11_ADDR (0X0F)
+#define SMI130_USER_DATA_12_ADDR (0X10)
+#define SMI130_USER_DATA_13_ADDR (0X11)
+#define SMI130_USER_DATA_14_ADDR (0X12)
+#define SMI130_USER_DATA_15_ADDR (0X13)
+/*******************/
+/**\name ACCEL DATA REGISTERS */
+/*******************/
+#define SMI130_USER_DATA_16_ADDR (0X14)
+#define SMI130_USER_DATA_17_ADDR (0X15)
+#define SMI130_USER_DATA_18_ADDR (0X16)
+#define SMI130_USER_DATA_19_ADDR (0X17)
+/*******************/
+/**\name SENSOR TIME REGISTERS */
+/*******************/
+#define SMI130_USER_SENSORTIME_0_ADDR (0X18)
+#define SMI130_USER_SENSORTIME_1_ADDR (0X19)
+#define SMI130_USER_SENSORTIME_2_ADDR (0X1A)
+/*******************/
+/**\name STATUS REGISTER FOR SENSOR STATUS FLAG */
+/*******************/
+#define SMI130_USER_STAT_ADDR (0X1B)
+/*******************/
+/**\name INTERRUPY STATUS REGISTERS */
+/*******************/
+#define SMI130_USER_INTR_STAT_0_ADDR (0X1C)
+#define SMI130_USER_INTR_STAT_1_ADDR (0X1D)
+#define SMI130_USER_INTR_STAT_2_ADDR (0X1E)
+#define SMI130_USER_INTR_STAT_3_ADDR (0X1F)
+/*******************/
+/**\name TEMPERATURE REGISTERS */
+/*******************/
+#define SMI130_USER_TEMPERATURE_0_ADDR (0X20)
+#define SMI130_USER_TEMPERATURE_1_ADDR (0X21)
+/*******************/
+/**\name FIFO REGISTERS */
+/*******************/
+#define SMI130_USER_FIFO_LENGTH_0_ADDR (0X22)
+#define SMI130_USER_FIFO_LENGTH_1_ADDR (0X23)
+#define SMI130_USER_FIFO_DATA_ADDR (0X24)
+/***************************************************/
+/**\name ACCEL CONFIG REGISTERS FOR ODR, BANDWIDTH AND UNDERSAMPLING*/
+/******************************************************/
+#define SMI130_USER_ACCEL_CONFIG_ADDR (0X40)
+/*******************/
+/**\name ACCEL RANGE */
+/*******************/
+#define SMI130_USER_ACCEL_RANGE_ADDR (0X41)
+/***************************************************/
+/**\name GYRO CONFIG REGISTERS FOR ODR AND BANDWIDTH */
+/******************************************************/
+#define SMI130_USER_GYRO_CONFIG_ADDR (0X42)
+/*******************/
+/**\name GYRO RANGE */
+/*******************/
+#define SMI130_USER_GYRO_RANGE_ADDR (0X43)
+/***************************************************/
+/**\name MAG CONFIG REGISTERS FOR ODR*/
+/******************************************************/
+#define SMI130_USER_MAG_CONFIG_ADDR (0X44)
+/***************************************************/
+/**\name REGISTER FOR GYRO AND ACCEL DOWNSAMPLING RATES FOR FIFO*/
+/******************************************************/
+#define SMI130_USER_FIFO_DOWN_ADDR (0X45)
+/***************************************************/
+/**\name FIFO CONFIG REGISTERS*/
+/******************************************************/
+#define SMI130_USER_FIFO_CONFIG_0_ADDR (0X46)
+#define SMI130_USER_FIFO_CONFIG_1_ADDR (0X47)
+/***************************************************/
+/**\name MAG INTERFACE REGISTERS*/
+/******************************************************/
+#define SMI130_USER_MAG_IF_0_ADDR (0X4B)
+#define SMI130_USER_MAG_IF_1_ADDR (0X4C)
+#define SMI130_USER_MAG_IF_2_ADDR (0X4D)
+#define SMI130_USER_MAG_IF_3_ADDR (0X4E)
+#define SMI130_USER_MAG_IF_4_ADDR (0X4F)
+/***************************************************/
+/**\name INTERRUPT ENABLE REGISTERS*/
+/******************************************************/
+#define SMI130_USER_INTR_ENABLE_0_ADDR (0X50)
+#define SMI130_USER_INTR_ENABLE_1_ADDR (0X51)
+#define SMI130_USER_INTR_ENABLE_2_ADDR (0X52)
+#define SMI130_USER_INTR_OUT_CTRL_ADDR (0X53)
+/***************************************************/
+/**\name LATCH DURATION REGISTERS*/
+/******************************************************/
+#define SMI130_USER_INTR_LATCH_ADDR (0X54)
+/***************************************************/
+/**\name MAP INTERRUPT 1 and 2 REGISTERS*/
+/******************************************************/
+#define SMI130_USER_INTR_MAP_0_ADDR (0X55)
+#define SMI130_USER_INTR_MAP_1_ADDR (0X56)
+#define SMI130_USER_INTR_MAP_2_ADDR (0X57)
+/***************************************************/
+/**\name DATA SOURCE REGISTERS*/
+/******************************************************/
+#define SMI130_USER_INTR_DATA_0_ADDR (0X58)
+#define SMI130_USER_INTR_DATA_1_ADDR (0X59)
+/***************************************************/
+/**\name
+INTERRUPT THRESHOLD, HYSTERESIS, DURATION, MODE CONFIGURATION REGISTERS*/
+/******************************************************/
+#define SMI130_USER_INTR_LOWHIGH_0_ADDR (0X5A)
+#define SMI130_USER_INTR_LOWHIGH_1_ADDR (0X5B)
+#define SMI130_USER_INTR_LOWHIGH_2_ADDR (0X5C)
+#define SMI130_USER_INTR_LOWHIGH_3_ADDR (0X5D)
+#define SMI130_USER_INTR_LOWHIGH_4_ADDR (0X5E)
+#define SMI130_USER_INTR_MOTION_0_ADDR (0X5F)
+#define SMI130_USER_INTR_MOTION_1_ADDR (0X60)
+#define SMI130_USER_INTR_MOTION_2_ADDR (0X61)
+#define SMI130_USER_INTR_MOTION_3_ADDR (0X62)
+#define SMI130_USER_INTR_TAP_0_ADDR (0X63)
+#define SMI130_USER_INTR_TAP_1_ADDR (0X64)
+#define SMI130_USER_INTR_ORIENT_0_ADDR (0X65)
+#define SMI130_USER_INTR_ORIENT_1_ADDR (0X66)
+#define SMI130_USER_INTR_FLAT_0_ADDR (0X67)
+#define SMI130_USER_INTR_FLAT_1_ADDR (0X68)
+/***************************************************/
+/**\name FAST OFFSET CONFIGURATION REGISTER*/
+/******************************************************/
+#define SMI130_USER_FOC_CONFIG_ADDR (0X69)
+/***************************************************/
+/**\name MISCELLANEOUS CONFIGURATION REGISTER*/
+/******************************************************/
+#define SMI130_USER_CONFIG_ADDR (0X6A)
+/***************************************************/
+/**\name SERIAL INTERFACE SETTINGS REGISTER*/
+/******************************************************/
+#define SMI130_USER_IF_CONFIG_ADDR (0X6B)
+/***************************************************/
+/**\name GYRO POWER MODE TRIGGER REGISTER */
+/******************************************************/
+#define SMI130_USER_PMU_TRIGGER_ADDR (0X6C)
+/***************************************************/
+/**\name SELF_TEST REGISTER*/
+/******************************************************/
+#define SMI130_USER_SELF_TEST_ADDR (0X6D)
+/***************************************************/
+/**\name SPI,I2C SELECTION REGISTER*/
+/******************************************************/
+#define SMI130_USER_NV_CONFIG_ADDR (0x70)
+/***************************************************/
+/**\name ACCEL AND GYRO OFFSET REGISTERS*/
+/******************************************************/
+#define SMI130_USER_OFFSET_0_ADDR (0X71)
+#define SMI130_USER_OFFSET_1_ADDR (0X72)
+#define SMI130_USER_OFFSET_2_ADDR (0X73)
+#define SMI130_USER_OFFSET_3_ADDR (0X74)
+#define SMI130_USER_OFFSET_4_ADDR (0X75)
+#define SMI130_USER_OFFSET_5_ADDR (0X76)
+#define SMI130_USER_OFFSET_6_ADDR (0X77)
+/***************************************************/
+/**\name STEP COUNTER INTERRUPT REGISTERS*/
+/******************************************************/
+#define SMI130_USER_STEP_COUNT_0_ADDR (0X78)
+#define SMI130_USER_STEP_COUNT_1_ADDR (0X79)
+/***************************************************/
+/**\name STEP COUNTER CONFIGURATION REGISTERS*/
+/******************************************************/
+#define SMI130_USER_STEP_CONFIG_0_ADDR (0X7A)
+#define SMI130_USER_STEP_CONFIG_1_ADDR (0X7B)
+/***************************************************/
+/**\name COMMAND REGISTER*/
+/******************************************************/
+#define SMI130_CMD_COMMANDS_ADDR (0X7E)
+/***************************************************/
+/**\name PAGE REGISTERS*/
+/******************************************************/
+#define SMI130_CMD_EXT_MODE_ADDR (0X7F)
+#define SMI130_COM_C_TRIM_FIVE_ADDR (0X05)
+
+/****************************************************/
+/**\name SHIFT VALUE DEFINITION */
+/***************************************************/
+#define SMI130_SHIFT_BIT_POSITION_BY_01_BIT (1)
+#define SMI130_SHIFT_BIT_POSITION_BY_02_BITS (2)
+#define SMI130_SHIFT_BIT_POSITION_BY_03_BITS (3)
+#define SMI130_SHIFT_BIT_POSITION_BY_04_BITS (4)
+#define SMI130_SHIFT_BIT_POSITION_BY_05_BITS (5)
+#define SMI130_SHIFT_BIT_POSITION_BY_06_BITS (6)
+#define SMI130_SHIFT_BIT_POSITION_BY_07_BITS (7)
+#define SMI130_SHIFT_BIT_POSITION_BY_08_BITS (8)
+#define SMI130_SHIFT_BIT_POSITION_BY_09_BITS (9)
+#define SMI130_SHIFT_BIT_POSITION_BY_12_BITS (12)
+#define SMI130_SHIFT_BIT_POSITION_BY_13_BITS (13)
+#define SMI130_SHIFT_BIT_POSITION_BY_14_BITS (14)
+#define SMI130_SHIFT_BIT_POSITION_BY_15_BITS (15)
+#define SMI130_SHIFT_BIT_POSITION_BY_16_BITS (16)
+
+/****************************************************/
+/**\name DEFINITIONS USED FOR YAMAHA-YAS532 */
+/***************************************************/
+#define YAS532_MAG_STATE_NORMAL (0)
+#define YAS532_MAG_STATE_INIT_COIL (1)
+#define YAS532_MAG_STATE_MEASURE_OFFSET (2)
+#define YAS532_MAG_INITCOIL_TIMEOUT (1000)
+#define YAS532_MAG_NOTRANS_POSITION (3)
+#define YAS532_DEFAULT_SENSOR_DELAY (50)
+#define YAS532_DATA_OVERFLOW (8190)
+#define YAS532_DATA_UNDERFLOW (0)
+#define YAS532_MAG_LOG (20)
+#define YAS532_MAG_TEMPERATURE_LOG (10)
+#define YAS532_TEMP20DEGREE_TYPICAL (390)
+#define YAS532_VERSION_AC_COEF_X (850)
+#define YAS532_VERSION_AC_COEF_Y1 (750)
+#define YAS532_VERSION_AC_COEF_Y2 (750)
+#define YAS532_DATA_CENTER (4096)
+/****************************************************/
+/**\name YAMAHA-YAS532 OFFSET DEFINITION */
+/***************************************************/
+static const s8 INVALID_OFFSET[] = {0x7f, 0x7f, 0x7f};
+#define set_vector(to, from) \
+ {int _l; for (_l = 0; _l < 3; _l++) (to)[_l] = (from)[_l]; }
+#define is_valid_offset(a) \
+ (((a)[0] <= 31) && ((a)[1] <= 31) && ((a)[2] <= 31) \
+ && (-31 <= (a)[0]) && (-31 <= (a)[1]) && (-31 <= (a)[2]))
+
+/**************************************************/
+/**\name YAS532 CALIB DATA DEFINITIONS */
+/*************************************************/
+
+
+/* register address of YAS532*/
+#define SMI130_YAS532_TESTR1 (0x88)
+#define SMI130_YAS532_TESTR2 (0x89)
+#define SMI130_YAS532_RCOIL (0x81)
+#define SMI130_YAS532_COMMAND_REGISTER (0x82)
+#define SMI130_YAS532_DATA_REGISTER (0xB0)
+/* calib data register definition*/
+#define SMI130_YAS532_CALIB_CX (0x90)
+#define SMI130_YAS532_CALIB_CY1 (0x91)
+#define SMI130_YAS532_CALIB_CY2 (0x92)
+#define SMI130_YAS532_CALIB1 (0x93)
+#define SMI130_YAS532_CALIB2 (0x94)
+#define SMI130_YAS532_CALIB3 (0x95)
+#define SMI130_YAS532_CALIB4 (0x96)
+#define SMI130_YAS532_CALIB5 (0x97)
+#define SMI130_YAS532_CLAIB6 (0x98)
+#define SMI130_YAS532_CALIB7 (0x99)
+#define SMI130_YAS532_CALIB8 (0x9A)
+#define SMI130_YAS532_CALIIB9 (0x9B)
+#define SMI130_YAS532_CALIB10 (0x9C)
+#define SMI130_YAS532_CALIB11 (0x9D)
+/* offset definition */
+#define SMI130_YAS532_OFFSET_X (0x85)
+#define SMI130_YAS532_OFFSET_Y (0x86)
+#define SMI130_YAS532_OFFSET_Z (0x87)
+/* data to write register for yas532*/
+#define SMI130_YAS532_WRITE_TESTR1 (0x00)
+#define SMI130_YAS532_WRITE_TESTR2 (0x00)
+#define SMI130_YAS532_WRITE_RCOIL (0x00)
+/**************************************************/
+/**\name YAS537 DEFINITION */
+/*************************************************/
+
+#define YAS537_SRSTR_DATA (0x02)
+#define YAS537_WRITE_A_D_CONVERTER (0x03)
+#define YAS537_WRITE_A_D_CONVERTER2 (0xF8)
+#define YAS537_WRITE_FILTER (0x08)
+#define YAS537_WRITE_CONFR (0x08)
+#define YAS537_WRITE_TEMP_CALIB (0xFF)
+#define YAS537_SET_COMMAND_REGISTER (0x01)
+
+/**************************************************/
+/**\name YAS537 REGISTER DEFINITION */
+/*************************************************/
+#define YAS537_REG_SRSTR (0x90)
+#define YAS537_REG_CALR_C0 (0xC0)
+#define YAS537_REG_CALR_C1 (0xC1)
+#define YAS537_REG_CALR_C2 (0xC2)
+#define YAS537_REG_CALR_C3 (0xC3)
+#define YAS537_REG_CALR_C4 (0xC4)
+#define YAS537_REG_CALR_C5 (0xC5)
+#define YAS537_REG_CALR_C6 (0xC6)
+#define YAS537_REG_CALR_C7 (0xC7)
+#define YAS537_REG_CALR_C8 (0xC8)
+#define YAS537_REG_CALR_C9 (0xC9)
+#define YAS537_REG_CALR_CA (0xCA)
+#define YAS537_REG_CALR_CB (0xCB)
+#define YAS537_REG_CALR_CC (0xCC)
+#define YAS537_REG_CALR_CD (0xCD)
+#define YAS537_REG_CALR_CE (0xCE)
+#define YAS537_REG_CALR_CF (0xCF)
+#define YAS537_REG_CALR_DO (0xD0)
+#define YAS537_REG_MTCR (0x93)
+#define YAS537_REG_CONFR (0x82)
+#define SMI130_REG_YAS537_CMDR (0x81)
+#define YAS537_REG_OXR (0x84)
+#define YAS537_REG_AVRR (0x87)
+#define YAS537_REG_HCKR (0x88)
+#define YAS537_REG_LCKR (0x89)
+#define YAS537_REG_ADCCALR (0x91)
+#define YAS537_REG_ADCCALR_ONE (0x92)
+#define YAS537_REG_OCR (0x9E)
+#define YAS537_REG_TRMR (0x9F)
+#define YAS537_REG_TEMPERATURE_0 (0xB0)
+#define YAS537_REG_TEMPERATURE_1 (0xB1)
+#define YAS537_REG_DATA_X_0 (0xB2)
+#define YAS537_REG_DATA_X_1 (0xB3)
+#define YAS537_REG_DATA_Y1_0 (0xB4)
+#define YAS537_REG_DATA_Y1_1 (0xB5)
+#define YAS537_REG_DATA_Y2_0 (0xB6)
+#define YAS537_REG_DATA_Y2_1 (0xB7)
+#define YAS537_MAG_STATE_NORMAL (0)
+#define YAS537_MAG_STATE_INIT_COIL (1)
+#define YAS537_MAG_STATE_RECORD_DATA (2)
+#define YAS537_DATA_UNDERFLOW (0)
+#define YAS537_DATA_OVERFLOW (16383)
+/****************************************************/
+/**\name YAS537_set vector */
+/***************************************************/
+#define yas537_set_vector(to, from) \
+ {int _l; for (_l = 0; _l < 3; _l++) (to)[_l] = (from)[_l]; }
+
+#ifndef ABS
+#define ABS(a) ((a) > 0 ? (a) : -(a)) /*!< Absolute value */
+#endif
+/****************************************************/
+/**\name AKM09911 AND AKM09912 DEFINITION */
+/***************************************************/
+#define AKM09912_SENSITIVITY_DIV (256)
+#define AKM09912_SENSITIVITY (128)
+#define AKM09911_SENSITIVITY_DIV (128)
+#define AKM_ASAX (0)
+#define AKM_ASAY (1)
+#define AKM_ASAZ (2)
+#define AKM_POWER_DOWN_MODE_DATA (0x00)
+#define AKM_FUSE_ROM_MODE (0x1F)
+#define AKM_POWER_MODE_REG (0x31)
+#define AKM_SINGLE_MEASUREMENT_MODE (0x01)
+#define AKM_DATA_REGISTER (0x11)
+/*! AKM09912 Register definition */
+#define AKM09912_CHIP_ID_REG (0x01)
+/****************************************************/
+/**\name BMM150 DEFINITION */
+/***************************************************/
+#define SMI130_BMM150_SET_POWER_CONTROL (0x01)
+#define SMI130_BMM150_MAX_RETRY_WAKEUP (5)
+#define SMI130_BMM150_POWER_ON (0x01)
+#define SMI130_BMM150_POWER_OFF (0x00)
+#define SMI130_BMM150_FORCE_MODE (0x02)
+#define SMI130_BMM150_POWER_ON_SUCCESS (0)
+#define SMI130_BMM150_POWER_ON_FAIL ((s8)-1)
+
+#define SMI130_BMM150_DIG_X1 (0)
+#define SMI130_BMM150_DIG_Y1 (1)
+#define SMI130_BMM150_DIG_X2 (2)
+#define SMI130_BMM150_DIG_Y3 (3)
+#define SMI130_BMM150_DIG_XY1 (4)
+#define SMI130_BMM150_DIG_XY2 (5)
+#define SMI130_BMM150_DIG_Z1_LSB (6)
+#define SMI130_BMM150_DIG_Z1_MSB (7)
+#define SMI130_BMM150_DIG_Z2_LSB (8)
+#define SMI130_BMM150_DIG_Z2_MSB (9)
+#define SMI130_BMM150_DIG_DIG_Z3_LSB (10)
+#define SMI130_BMM150_DIG_DIG_Z3_MSB (11)
+#define SMI130_BMM150_DIG_DIG_Z4_LSB (12)
+#define SMI130_BMM150_DIG_DIG_Z4_MSB (13)
+#define SMI130_BMM150_DIG_DIG_XYZ1_LSB (14)
+#define SMI130_BMM150_DIG_DIG_XYZ1_MSB (15)
+
+/**************************************************************/
+/**\name STRUCTURE DEFINITIONS */
+/**************************************************************/
+/*!
+* @brief smi130 structure
+* This structure holds all relevant information about smi130
+*/
+struct smi130_t {
+u8 chip_id;/**< chip id of SMI130 */
+u8 dev_addr;/**< device address of SMI130 */
+s8 mag_manual_enable;/**< used for check the mag manual/auto mode status */
+SMI130_WR_FUNC_PTR;/**< bus write function pointer */
+SMI130_RD_FUNC_PTR;/**< bus read function pointer */
+SMI130_BRD_FUNC_PTR;/**< burst write function pointer */
+void (*delay_msec)(SMI130_MDELAY_DATA_TYPE);/**< delay function pointer */
+};
+/*!
+ * @brief Structure containing bmm150 and akm09911
+ * magnetometer values for x,y and
+ * z-axis in s16
+ */
+struct smi130_mag_t {
+s16 x;/**< BMM150 and AKM09911 and AKM09912 X raw data*/
+s16 y;/**< BMM150 and AKM09911 and AKM09912 Y raw data*/
+s16 z;/**< BMM150 and AKM09911 and AKM09912 Z raw data*/
+};
+/*!
+ * @brief Structure containing bmm150 xyz data and temperature
+ */
+struct smi130_mag_xyzr_t {
+s16 x;/**< BMM150 X raw data*/
+s16 y;/**< BMM150 Y raw data*/
+s16 z;/**<BMM150 Z raw data*/
+u16 r;/**<BMM150 R raw data*/
+};
+/*!
+ * @brief Structure containing gyro xyz data
+ */
+struct smi130_gyro_t {
+s16 x;/**<gyro X data*/
+s16 y;/**<gyro Y data*/
+s16 z;/**<gyro Z data*/
+};
+/*!
+ * @brief Structure containing accel xyz data
+ */
+struct smi130_accel_t {
+s16 x;/**<accel X data*/
+s16 y;/**<accel Y data*/
+s16 z;/**<accel Z data*/
+};
+/*!
+ * @brief Structure bmm150 mag compensated data with s32 output
+ */
+struct smi130_mag_xyz_s32_t {
+s16 x;/**<BMM150 X compensated data*/
+s16 y;/**<BMM150 Y compensated data*/
+s16 z;/**<BMM150 Z compensated data*/
+};
+/*!
+ * @brief Structure bmm150 mag trim data
+ */
+struct trim_data_t {
+s8 dig_x1;/**<BMM150 trim x1 data*/
+s8 dig_y1;/**<BMM150 trim y1 data*/
+
+s8 dig_x2;/**<BMM150 trim x2 data*/
+s8 dig_y2;/**<BMM150 trim y2 data*/
+
+u16 dig_z1;/**<BMM150 trim z1 data*/
+s16 dig_z2;/**<BMM150 trim z2 data*/
+s16 dig_z3;/**<BMM150 trim z3 data*/
+s16 dig_z4;/**<BMM150 trim z4 data*/
+
+u8 dig_xy1;/**<BMM150 trim xy1 data*/
+s8 dig_xy2;/**<BMM150 trim xy2 data*/
+
+u16 dig_xyz1;/**<BMM150 trim xyz1 data*/
+};
+
+/*!
+* @brief Structure for reading AKM compensating data
+*/
+struct bosch_akm_sensitivity_data_t {
+u8 asax;/**<AKM09911 and AKM09912 X sensitivity data*/
+u8 asay;/**<AKM09911 and AKM09912 Y sensitivity data*/
+u8 asaz;/**<AKM09911 and AKM09912 Z sensitivity data*/
+};
+/*!
+* @brief YAMAHA-YAS532 struct
+* Calibration YAS532 data struct
+*/
+struct bosch_yas532_calib_data_t {
+s32 cx;/**<YAS532 calib cx data */
+s32 cy1;/**<YAS532 calib cy1 data */
+s32 cy2;/**<YAS532 calib cy2 data */
+s32 a2;/**<YAS532 calib a2 data */
+s32 a3;/**<YAS532 calib a3 data */
+s32 a4;/**<YAS532 calib a4 data */
+s32 a5;/**<YAS532 calib a5 data */
+s32 a6;/**<YAS532 calib a6 data */
+s32 a7;/**<YAS532 calib a7 data */
+s32 a8;/**<YAS532 calib a8 data */
+s32 a9;/**<YAS532 calib a9 data */
+s32 k;/**<YAS532 calib k data */
+s8 rxy1y2[3];/**<YAS532 calib rxy1y2 data */
+u8 fxy1y2[3];/**<YAS532 calib fxy1y2 data */
+};
+/*!
+* @brief YAS532 Temperature structure
+*/
+#if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+struct yas_temp_filter_t {
+u16 log[YAS532_MAG_TEMPERATURE_LOG];/**<YAS532 temp log array */
+u8 num;/**< used for increment the index */
+u8 idx;/**< used for increment the index */
+};
+#endif
+/*!
+* @brief YAS532 sensor initialization
+*/
+struct yas532_t {
+struct bosch_yas532_calib_data_t calib_yas532;/**< calib data */
+s8 measure_state;/**< update measure state */
+s8 v_hard_offset_s8[3];/**< offset write array*/
+s32 coef[3];/**< co efficient data */
+s8 overflow;/**< over flow condition check */
+u8 dev_id;/**< device id information */
+const s8 *transform;/**< transform condition check */
+#if YAS532_MAG_LOG < YAS532_MAG_TEMPERATURE_LOG
+struct yas_temp_filter_t temp_data;/**< temp data */
+#endif
+u16 last_raw[4];/**< raw data */
+};
+/*!
+* @brief Used for reading the YAS532 XYZ data
+*/
+struct yas532_vector {
+s32 yas532_vector_xyz[3];/**< YAS532 compensated xyz data*/
+};
+/**
+ * @struct yas_vector
+ * @brief Stores the sensor data
+ */
+struct yas_vector {
+ s32 yas537_vector_xyz[3]; /*!< vector data */
+};
+/*!
+* @brief YAMAHA-YAS532 struct
+* Calibration YAS532 data struct
+*/
+struct bosch_yas537_calib_data_t {
+s8 a2;/**<YAS532 calib a2 data */
+s8 a3;/**<YAS532 calib a3 data */
+s8 a4;/**<YAS532 calib a4 data */
+s16 a5;/**<YAS532 calib a5 data */
+s8 a6;/**<YAS532 calib a6 data */
+s8 a7;/**<YAS532 calib a7 data */
+s8 a8;/**<YAS532 calib a8 data */
+s16 a9;/**<YAS532 calib a9 data */
+u8 k;/**<YAS532 calib k data */
+u8 ver;/**<YAS532 calib ver data*/
+};
+/*!
+* @brief YAS537 sensor initialization
+*/
+struct yas537_t {
+struct bosch_yas537_calib_data_t calib_yas537;/**< calib data */
+s8 measure_state;/**< update measure state */
+s8 hard_offset[3];/**< offset write array*/
+u16 last_after_rcoil[3];/**< rcoil write array*/
+s32 coef[3];/**< co efficient data */
+s8 overflow;/**< over flow condition check */
+u8 dev_id;/**< device id information */
+u8 average;/**<average selection for offset configuration*/
+const s8 *transform;/**< transform condition check */
+u16 last_raw[4];/**< raw data */
+struct yas_vector xyz; /*!< X, Y, Z measurement data of the sensor */
+};
+/**************************************************************/
+/**\name USER DATA REGISTERS DEFINITION START */
+/**************************************************************/
+
+/**************************************************************/
+/**\name CHIP ID LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Chip ID Description - Reg Addr --> (0x00), Bit --> 0...7 */
+#define SMI130_USER_CHIP_ID__POS (0)
+#define SMI130_USER_CHIP_ID__MSK (0xFF)
+#define SMI130_USER_CHIP_ID__LEN (8)
+#define SMI130_USER_CHIP_ID__REG (SMI130_USER_CHIP_ID_ADDR)
+/**************************************************************/
+/**\name ERROR STATUS LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Error Description - Reg Addr --> (0x02), Bit --> 0 */
+#define SMI130_USER_ERR_STAT__POS (0)
+#define SMI130_USER_ERR_STAT__LEN (8)
+#define SMI130_USER_ERR_STAT__MSK (0xFF)
+#define SMI130_USER_ERR_STAT__REG (SMI130_USER_ERROR_ADDR)
+
+#define SMI130_USER_FATAL_ERR__POS (0)
+#define SMI130_USER_FATAL_ERR__LEN (1)
+#define SMI130_USER_FATAL_ERR__MSK (0x01)
+#define SMI130_USER_FATAL_ERR__REG (SMI130_USER_ERROR_ADDR)
+
+/* Error Description - Reg Addr --> (0x02), Bit --> 1...4 */
+#define SMI130_USER_ERR_CODE__POS (1)
+#define SMI130_USER_ERR_CODE__LEN (4)
+#define SMI130_USER_ERR_CODE__MSK (0x1E)
+#define SMI130_USER_ERR_CODE__REG (SMI130_USER_ERROR_ADDR)
+
+/* Error Description - Reg Addr --> (0x02), Bit --> 5 */
+#define SMI130_USER_I2C_FAIL_ERR__POS (5)
+#define SMI130_USER_I2C_FAIL_ERR__LEN (1)
+#define SMI130_USER_I2C_FAIL_ERR__MSK (0x20)
+#define SMI130_USER_I2C_FAIL_ERR__REG (SMI130_USER_ERROR_ADDR)
+
+/* Error Description - Reg Addr --> (0x02), Bit --> 6 */
+#define SMI130_USER_DROP_CMD_ERR__POS (6)
+#define SMI130_USER_DROP_CMD_ERR__LEN (1)
+#define SMI130_USER_DROP_CMD_ERR__MSK (0x40)
+#define SMI130_USER_DROP_CMD_ERR__REG (SMI130_USER_ERROR_ADDR)
+/**************************************************************/
+/**\name MAG DATA READY LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Error Description - Reg Addr --> (0x02), Bit --> 7 */
+#define SMI130_USER_MAG_DADA_RDY_ERR__POS (7)
+#define SMI130_USER_MAG_DADA_RDY_ERR__LEN (1)
+#define SMI130_USER_MAG_DADA_RDY_ERR__MSK (0x80)
+#define SMI130_USER_MAG_DADA_RDY_ERR__REG (SMI130_USER_ERROR_ADDR)
+/**************************************************************/
+/**\name MAG POWER MODE LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* PMU_Status Description of MAG - Reg Addr --> (0x03), Bit --> 1..0 */
+#define SMI130_USER_MAG_POWER_MODE_STAT__POS (0)
+#define SMI130_USER_MAG_POWER_MODE_STAT__LEN (2)
+#define SMI130_USER_MAG_POWER_MODE_STAT__MSK (0x03)
+#define SMI130_USER_MAG_POWER_MODE_STAT__REG \
+(SMI130_USER_PMU_STAT_ADDR)
+/**************************************************************/
+/**\name GYRO POWER MODE LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* PMU_Status Description of GYRO - Reg Addr --> (0x03), Bit --> 3...2 */
+#define SMI130_USER_GYRO_POWER_MODE_STAT__POS (2)
+#define SMI130_USER_GYRO_POWER_MODE_STAT__LEN (2)
+#define SMI130_USER_GYRO_POWER_MODE_STAT__MSK (0x0C)
+#define SMI130_USER_GYRO_POWER_MODE_STAT__REG \
+(SMI130_USER_PMU_STAT_ADDR)
+/**************************************************************/
+/**\name ACCEL POWER MODE LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* PMU_Status Description of ACCEL - Reg Addr --> (0x03), Bit --> 5...4 */
+#define SMI130_USER_ACCEL_POWER_MODE_STAT__POS (4)
+#define SMI130_USER_ACCEL_POWER_MODE_STAT__LEN (2)
+#define SMI130_USER_ACCEL_POWER_MODE_STAT__MSK (0x30)
+#define SMI130_USER_ACCEL_POWER_MODE_STAT__REG \
+(SMI130_USER_PMU_STAT_ADDR)
+/**************************************************************/
+/**\name MAG DATA XYZ LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Mag_X(LSB) Description - Reg Addr --> (0x04), Bit --> 0...7 */
+#define SMI130_USER_DATA_0_MAG_X_LSB__POS (0)
+#define SMI130_USER_DATA_0_MAG_X_LSB__LEN (8)
+#define SMI130_USER_DATA_0_MAG_X_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_0_MAG_X_LSB__REG (SMI130_USER_DATA_0_ADDR)
+
+/* Mag_X(LSB) Description - Reg Addr --> (0x04), Bit --> 3...7 */
+#define SMI130_USER_DATA_MAG_X_LSB__POS (3)
+#define SMI130_USER_DATA_MAG_X_LSB__LEN (5)
+#define SMI130_USER_DATA_MAG_X_LSB__MSK (0xF8)
+#define SMI130_USER_DATA_MAG_X_LSB__REG (SMI130_USER_DATA_0_ADDR)
+
+/* Mag_X(MSB) Description - Reg Addr --> (0x05), Bit --> 0...7 */
+#define SMI130_USER_DATA_1_MAG_X_MSB__POS (0)
+#define SMI130_USER_DATA_1_MAG_X_MSB__LEN (8)
+#define SMI130_USER_DATA_1_MAG_X_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_1_MAG_X_MSB__REG (SMI130_USER_DATA_1_ADDR)
+
+/* Mag_Y(LSB) Description - Reg Addr --> (0x06), Bit --> 0...7 */
+#define SMI130_USER_DATA_2_MAG_Y_LSB__POS (0)
+#define SMI130_USER_DATA_2_MAG_Y_LSB__LEN (8)
+#define SMI130_USER_DATA_2_MAG_Y_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_2_MAG_Y_LSB__REG (SMI130_USER_DATA_2_ADDR)
+
+/* Mag_Y(LSB) Description - Reg Addr --> (0x06), Bit --> 3...7 */
+#define SMI130_USER_DATA_MAG_Y_LSB__POS (3)
+#define SMI130_USER_DATA_MAG_Y_LSB__LEN (5)
+#define SMI130_USER_DATA_MAG_Y_LSB__MSK (0xF8)
+#define SMI130_USER_DATA_MAG_Y_LSB__REG (SMI130_USER_DATA_2_ADDR)
+
+/* Mag_Y(MSB) Description - Reg Addr --> (0x07), Bit --> 0...7 */
+#define SMI130_USER_DATA_3_MAG_Y_MSB__POS (0)
+#define SMI130_USER_DATA_3_MAG_Y_MSB__LEN (8)
+#define SMI130_USER_DATA_3_MAG_Y_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_3_MAG_Y_MSB__REG (SMI130_USER_DATA_3_ADDR)
+
+/* Mag_Z(LSB) Description - Reg Addr --> (0x08), Bit --> 0...7 */
+#define SMI130_USER_DATA_4_MAG_Z_LSB__POS (0)
+#define SMI130_USER_DATA_4_MAG_Z_LSB__LEN (8)
+#define SMI130_USER_DATA_4_MAG_Z_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_4_MAG_Z_LSB__REG (SMI130_USER_DATA_4_ADDR)
+
+/* Mag_X(LSB) Description - Reg Addr --> (0x08), Bit --> 3...7 */
+#define SMI130_USER_DATA_MAG_Z_LSB__POS (1)
+#define SMI130_USER_DATA_MAG_Z_LSB__LEN (7)
+#define SMI130_USER_DATA_MAG_Z_LSB__MSK (0xFE)
+#define SMI130_USER_DATA_MAG_Z_LSB__REG (SMI130_USER_DATA_4_ADDR)
+
+/* Mag_Z(MSB) Description - Reg Addr --> (0x09), Bit --> 0...7 */
+#define SMI130_USER_DATA_5_MAG_Z_MSB__POS (0)
+#define SMI130_USER_DATA_5_MAG_Z_MSB__LEN (8)
+#define SMI130_USER_DATA_5_MAG_Z_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_5_MAG_Z_MSB__REG (SMI130_USER_DATA_5_ADDR)
+
+/* RHALL(LSB) Description - Reg Addr --> (0x0A), Bit --> 0...7 */
+#define SMI130_USER_DATA_6_RHALL_LSB__POS (0)
+#define SMI130_USER_DATA_6_RHALL_LSB__LEN (8)
+#define SMI130_USER_DATA_6_RHALL_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_6_RHALL_LSB__REG (SMI130_USER_DATA_6_ADDR)
+
+/* Mag_R(LSB) Description - Reg Addr --> (0x0A), Bit --> 3...7 */
+#define SMI130_USER_DATA_MAG_R_LSB__POS (2)
+#define SMI130_USER_DATA_MAG_R_LSB__LEN (6)
+#define SMI130_USER_DATA_MAG_R_LSB__MSK (0xFC)
+#define SMI130_USER_DATA_MAG_R_LSB__REG (SMI130_USER_DATA_6_ADDR)
+
+/* RHALL(MSB) Description - Reg Addr --> (0x0B), Bit --> 0...7 */
+#define SMI130_USER_DATA_7_RHALL_MSB__POS (0)
+#define SMI130_USER_DATA_7_RHALL_MSB__LEN (8)
+#define SMI130_USER_DATA_7_RHALL_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_7_RHALL_MSB__REG (SMI130_USER_DATA_7_ADDR)
+/**************************************************************/
+/**\name GYRO DATA XYZ LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* GYR_X (LSB) Description - Reg Addr --> (0x0C), Bit --> 0...7 */
+#define SMI130_USER_DATA_8_GYRO_X_LSB__POS (0)
+#define SMI130_USER_DATA_8_GYRO_X_LSB__LEN (8)
+#define SMI130_USER_DATA_8_GYRO_X_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_8_GYRO_X_LSB__REG (SMI130_USER_DATA_8_ADDR)
+
+/* GYR_X (MSB) Description - Reg Addr --> (0x0D), Bit --> 0...7 */
+#define SMI130_USER_DATA_9_GYRO_X_MSB__POS (0)
+#define SMI130_USER_DATA_9_GYRO_X_MSB__LEN (8)
+#define SMI130_USER_DATA_9_GYRO_X_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_9_GYRO_X_MSB__REG (SMI130_USER_DATA_9_ADDR)
+
+/* GYR_Y (LSB) Description - Reg Addr --> 0x0E, Bit --> 0...7 */
+#define SMI130_USER_DATA_10_GYRO_Y_LSB__POS (0)
+#define SMI130_USER_DATA_10_GYRO_Y_LSB__LEN (8)
+#define SMI130_USER_DATA_10_GYRO_Y_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_10_GYRO_Y_LSB__REG (SMI130_USER_DATA_10_ADDR)
+
+/* GYR_Y (MSB) Description - Reg Addr --> (0x0F), Bit --> 0...7 */
+#define SMI130_USER_DATA_11_GYRO_Y_MSB__POS (0)
+#define SMI130_USER_DATA_11_GYRO_Y_MSB__LEN (8)
+#define SMI130_USER_DATA_11_GYRO_Y_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_11_GYRO_Y_MSB__REG (SMI130_USER_DATA_11_ADDR)
+
+/* GYR_Z (LSB) Description - Reg Addr --> (0x10), Bit --> 0...7 */
+#define SMI130_USER_DATA_12_GYRO_Z_LSB__POS (0)
+#define SMI130_USER_DATA_12_GYRO_Z_LSB__LEN (8)
+#define SMI130_USER_DATA_12_GYRO_Z_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_12_GYRO_Z_LSB__REG (SMI130_USER_DATA_12_ADDR)
+
+/* GYR_Z (MSB) Description - Reg Addr --> (0x11), Bit --> 0...7 */
+#define SMI130_USER_DATA_13_GYRO_Z_MSB__POS (0)
+#define SMI130_USER_DATA_13_GYRO_Z_MSB__LEN (8)
+#define SMI130_USER_DATA_13_GYRO_Z_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_13_GYRO_Z_MSB__REG (SMI130_USER_DATA_13_ADDR)
+/**************************************************************/
+/**\name ACCEL DATA XYZ LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* ACC_X (LSB) Description - Reg Addr --> (0x12), Bit --> 0...7 */
+#define SMI130_USER_DATA_14_ACCEL_X_LSB__POS (0)
+#define SMI130_USER_DATA_14_ACCEL_X_LSB__LEN (8)
+#define SMI130_USER_DATA_14_ACCEL_X_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_14_ACCEL_X_LSB__REG (SMI130_USER_DATA_14_ADDR)
+
+/* ACC_X (MSB) Description - Reg Addr --> 0x13, Bit --> 0...7 */
+#define SMI130_USER_DATA_15_ACCEL_X_MSB__POS (0)
+#define SMI130_USER_DATA_15_ACCEL_X_MSB__LEN (8)
+#define SMI130_USER_DATA_15_ACCEL_X_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_15_ACCEL_X_MSB__REG (SMI130_USER_DATA_15_ADDR)
+
+/* ACC_Y (LSB) Description - Reg Addr --> (0x14), Bit --> 0...7 */
+#define SMI130_USER_DATA_16_ACCEL_Y_LSB__POS (0)
+#define SMI130_USER_DATA_16_ACCEL_Y_LSB__LEN (8)
+#define SMI130_USER_DATA_16_ACCEL_Y_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_16_ACCEL_Y_LSB__REG (SMI130_USER_DATA_16_ADDR)
+
+/* ACC_Y (MSB) Description - Reg Addr --> (0x15), Bit --> 0...7 */
+#define SMI130_USER_DATA_17_ACCEL_Y_MSB__POS (0)
+#define SMI130_USER_DATA_17_ACCEL_Y_MSB__LEN (8)
+#define SMI130_USER_DATA_17_ACCEL_Y_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_17_ACCEL_Y_MSB__REG (SMI130_USER_DATA_17_ADDR)
+
+/* ACC_Z (LSB) Description - Reg Addr --> 0x16, Bit --> 0...7 */
+#define SMI130_USER_DATA_18_ACCEL_Z_LSB__POS (0)
+#define SMI130_USER_DATA_18_ACCEL_Z_LSB__LEN (8)
+#define SMI130_USER_DATA_18_ACCEL_Z_LSB__MSK (0xFF)
+#define SMI130_USER_DATA_18_ACCEL_Z_LSB__REG (SMI130_USER_DATA_18_ADDR)
+
+/* ACC_Z (MSB) Description - Reg Addr --> (0x17), Bit --> 0...7 */
+#define SMI130_USER_DATA_19_ACCEL_Z_MSB__POS (0)
+#define SMI130_USER_DATA_19_ACCEL_Z_MSB__LEN (8)
+#define SMI130_USER_DATA_19_ACCEL_Z_MSB__MSK (0xFF)
+#define SMI130_USER_DATA_19_ACCEL_Z_MSB__REG (SMI130_USER_DATA_19_ADDR)
+/**************************************************************/
+/**\name SENSOR TIME LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* SENSORTIME_0 (LSB) Description - Reg Addr --> (0x18), Bit --> 0...7 */
+#define SMI130_USER_SENSORTIME_0_SENSOR_TIME_LSB__POS (0)
+#define SMI130_USER_SENSORTIME_0_SENSOR_TIME_LSB__LEN (8)
+#define SMI130_USER_SENSORTIME_0_SENSOR_TIME_LSB__MSK (0xFF)
+#define SMI130_USER_SENSORTIME_0_SENSOR_TIME_LSB__REG \
+ (SMI130_USER_SENSORTIME_0_ADDR)
+
+/* SENSORTIME_1 (MSB) Description - Reg Addr --> (0x19), Bit --> 0...7 */
+#define SMI130_USER_SENSORTIME_1_SENSOR_TIME_MSB__POS (0)
+#define SMI130_USER_SENSORTIME_1_SENSOR_TIME_MSB__LEN (8)
+#define SMI130_USER_SENSORTIME_1_SENSOR_TIME_MSB__MSK (0xFF)
+#define SMI130_USER_SENSORTIME_1_SENSOR_TIME_MSB__REG \
+ (SMI130_USER_SENSORTIME_1_ADDR)
+
+/* SENSORTIME_2 (MSB) Description - Reg Addr --> (0x1A), Bit --> 0...7 */
+#define SMI130_USER_SENSORTIME_2_SENSOR_TIME_MSB__POS (0)
+#define SMI130_USER_SENSORTIME_2_SENSOR_TIME_MSB__LEN (8)
+#define SMI130_USER_SENSORTIME_2_SENSOR_TIME_MSB__MSK (0xFF)
+#define SMI130_USER_SENSORTIME_2_SENSOR_TIME_MSB__REG \
+ (SMI130_USER_SENSORTIME_2_ADDR)
+/**************************************************************/
+/**\name GYRO SELF TEST LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 1 */
+#define SMI130_USER_STAT_GYRO_SELFTEST_OK__POS (1)
+#define SMI130_USER_STAT_GYRO_SELFTEST_OK__LEN (1)
+#define SMI130_USER_STAT_GYRO_SELFTEST_OK__MSK (0x02)
+#define SMI130_USER_STAT_GYRO_SELFTEST_OK__REG \
+ (SMI130_USER_STAT_ADDR)
+/**************************************************************/
+/**\name MAG MANUAL OPERATION LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 2 */
+#define SMI130_USER_STAT_MAG_MANUAL_OPERATION__POS (2)
+#define SMI130_USER_STAT_MAG_MANUAL_OPERATION__LEN (1)
+#define SMI130_USER_STAT_MAG_MANUAL_OPERATION__MSK (0x04)
+#define SMI130_USER_STAT_MAG_MANUAL_OPERATION__REG \
+ (SMI130_USER_STAT_ADDR)
+/**************************************************************/
+/**\name FOC STATUS LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 3 */
+#define SMI130_USER_STAT_FOC_RDY__POS (3)
+#define SMI130_USER_STAT_FOC_RDY__LEN (1)
+#define SMI130_USER_STAT_FOC_RDY__MSK (0x08)
+#define SMI130_USER_STAT_FOC_RDY__REG (SMI130_USER_STAT_ADDR)
+/**************************************************************/
+/**\name NVM READY LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 4 */
+#define SMI130_USER_STAT_NVM_RDY__POS (4)
+#define SMI130_USER_STAT_NVM_RDY__LEN (1)
+#define SMI130_USER_STAT_NVM_RDY__MSK (0x10)
+#define SMI130_USER_STAT_NVM_RDY__REG (SMI130_USER_STAT_ADDR)
+/**************************************************************/
+/**\name DATA READY LENGTH, POSITION AND MASK FOR ACCEL, MAG AND GYRO*/
+/**************************************************************/
+/* Status Description - Reg Addr --> 0x1B, Bit --> 5 */
+#define SMI130_USER_STAT_DATA_RDY_MAG__POS (5)
+#define SMI130_USER_STAT_DATA_RDY_MAG__LEN (1)
+#define SMI130_USER_STAT_DATA_RDY_MAG__MSK (0x20)
+#define SMI130_USER_STAT_DATA_RDY_MAG__REG (SMI130_USER_STAT_ADDR)
+
+/* Status Description - Reg Addr --> 0x1B, Bit --> 6 */
+#define SMI130_USER_STAT_DATA_RDY_GYRO__POS (6)
+#define SMI130_USER_STAT_DATA_RDY_GYRO__LEN (1)
+#define SMI130_USER_STAT_DATA_RDY_GYRO__MSK (0x40)
+#define SMI130_USER_STAT_DATA_RDY_GYRO__REG (SMI130_USER_STAT_ADDR)
+
+/* Status Description - Reg Addr --> 0x1B, Bit --> 7 */
+#define SMI130_USER_STAT_DATA_RDY_ACCEL__POS (7)
+#define SMI130_USER_STAT_DATA_RDY_ACCEL__LEN (1)
+#define SMI130_USER_STAT_DATA_RDY_ACCEL__MSK (0x80)
+#define SMI130_USER_STAT_DATA_RDY_ACCEL__REG (SMI130_USER_STAT_ADDR)
+/**************************************************************/
+/**\name INTERRUPT STATUS LENGTH, POSITION AND MASK */
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 0 */
+#define SMI130_USER_INTR_STAT_0_STEP_INTR__POS (0)
+#define SMI130_USER_INTR_STAT_0_STEP_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_0_STEP_INTR__MSK (0x01)
+#define SMI130_USER_INTR_STAT_0_STEP_INTR__REG \
+ (SMI130_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name SIGNIFICANT INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 1 */
+#define SMI130_USER_INTR_STAT_0_SIGNIFICANT_INTR__POS (1)
+#define SMI130_USER_INTR_STAT_0_SIGNIFICANT_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_0_SIGNIFICANT_INTR__MSK (0x02)
+#define SMI130_USER_INTR_STAT_0_SIGNIFICANT_INTR__REG \
+ (SMI130_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name ANY_MOTION INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 2 */
+#define SMI130_USER_INTR_STAT_0_ANY_MOTION__POS (2)
+#define SMI130_USER_INTR_STAT_0_ANY_MOTION__LEN (1)
+#define SMI130_USER_INTR_STAT_0_ANY_MOTION__MSK (0x04)
+#define SMI130_USER_INTR_STAT_0_ANY_MOTION__REG \
+ (SMI130_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name PMU TRIGGER INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 3 */
+#define SMI130_USER_INTR_STAT_0_PMU_TRIGGER__POS 3
+#define SMI130_USER_INTR_STAT_0_PMU_TRIGGER__LEN (1)
+#define SMI130_USER_INTR_STAT_0_PMU_TRIGGER__MSK (0x08)
+#define SMI130_USER_INTR_STAT_0_PMU_TRIGGER__REG \
+ (SMI130_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name DOUBLE TAP INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 4 */
+#define SMI130_USER_INTR_STAT_0_DOUBLE_TAP_INTR__POS 4
+#define SMI130_USER_INTR_STAT_0_DOUBLE_TAP_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_0_DOUBLE_TAP_INTR__MSK (0x10)
+#define SMI130_USER_INTR_STAT_0_DOUBLE_TAP_INTR__REG \
+ (SMI130_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name SINGLE TAP INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 5 */
+#define SMI130_USER_INTR_STAT_0_SINGLE_TAP_INTR__POS 5
+#define SMI130_USER_INTR_STAT_0_SINGLE_TAP_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_0_SINGLE_TAP_INTR__MSK (0x20)
+#define SMI130_USER_INTR_STAT_0_SINGLE_TAP_INTR__REG \
+ (SMI130_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name ORIENT INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 6 */
+#define SMI130_USER_INTR_STAT_0_ORIENT__POS (6)
+#define SMI130_USER_INTR_STAT_0_ORIENT__LEN (1)
+#define SMI130_USER_INTR_STAT_0_ORIENT__MSK (0x40)
+#define SMI130_USER_INTR_STAT_0_ORIENT__REG \
+ (SMI130_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name FLAT INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_0 Description - Reg Addr --> 0x1C, Bit --> 7 */
+#define SMI130_USER_INTR_STAT_0_FLAT__POS (7)
+#define SMI130_USER_INTR_STAT_0_FLAT__LEN (1)
+#define SMI130_USER_INTR_STAT_0_FLAT__MSK (0x80)
+#define SMI130_USER_INTR_STAT_0_FLAT__REG \
+ (SMI130_USER_INTR_STAT_0_ADDR)
+/**************************************************************/
+/**\name HIGH_G INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 2 */
+#define SMI130_USER_INTR_STAT_1_HIGH_G_INTR__POS (2)
+#define SMI130_USER_INTR_STAT_1_HIGH_G_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_1_HIGH_G_INTR__MSK (0x04)
+#define SMI130_USER_INTR_STAT_1_HIGH_G_INTR__REG \
+ (SMI130_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name LOW_G INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 3 */
+#define SMI130_USER_INTR_STAT_1_LOW_G_INTR__POS (3)
+#define SMI130_USER_INTR_STAT_1_LOW_G_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_1_LOW_G_INTR__MSK (0x08)
+#define SMI130_USER_INTR_STAT_1_LOW_G_INTR__REG \
+ (SMI130_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name DATA READY INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 4 */
+#define SMI130_USER_INTR_STAT_1_DATA_RDY_INTR__POS (4)
+#define SMI130_USER_INTR_STAT_1_DATA_RDY_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_1_DATA_RDY_INTR__MSK (0x10)
+#define SMI130_USER_INTR_STAT_1_DATA_RDY_INTR__REG \
+ (SMI130_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name FIFO FULL INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 5 */
+#define SMI130_USER_INTR_STAT_1_FIFO_FULL_INTR__POS (5)
+#define SMI130_USER_INTR_STAT_1_FIFO_FULL_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_1_FIFO_FULL_INTR__MSK (0x20)
+#define SMI130_USER_INTR_STAT_1_FIFO_FULL_INTR__REG \
+ (SMI130_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name FIFO WATERMARK INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 6 */
+#define SMI130_USER_INTR_STAT_1_FIFO_WM_INTR__POS (6)
+#define SMI130_USER_INTR_STAT_1_FIFO_WM_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_1_FIFO_WM_INTR__MSK (0x40)
+#define SMI130_USER_INTR_STAT_1_FIFO_WM_INTR__REG \
+ (SMI130_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name NO MOTION INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_1 Description - Reg Addr --> 0x1D, Bit --> 7 */
+#define SMI130_USER_INTR_STAT_1_NOMOTION_INTR__POS (7)
+#define SMI130_USER_INTR_STAT_1_NOMOTION_INTR__LEN (1)
+#define SMI130_USER_INTR_STAT_1_NOMOTION_INTR__MSK (0x80)
+#define SMI130_USER_INTR_STAT_1_NOMOTION_INTR__REG \
+ (SMI130_USER_INTR_STAT_1_ADDR)
+/**************************************************************/
+/**\name ANY MOTION-XYZ AXIS INTERRUPT STATUS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 0 */
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__POS (0)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__LEN (1)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__MSK (0x01)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_X__REG \
+ (SMI130_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 1 */
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__POS (1)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__LEN (1)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__MSK (0x02)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y__REG \
+ (SMI130_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 2 */
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__POS (2)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__LEN (1)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__MSK (0x04)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z__REG \
+ (SMI130_USER_INTR_STAT_2_ADDR)
+/**************************************************************/
+/**\name ANY MOTION SIGN LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 3 */
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_SIGN__POS (3)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_SIGN__LEN (1)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_SIGN__MSK (0x08)
+#define SMI130_USER_INTR_STAT_2_ANY_MOTION_SIGN__REG \
+ (SMI130_USER_INTR_STAT_2_ADDR)
+/**************************************************************/
+/**\name TAP_XYZ AND SIGN LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 4 */
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_X__POS (4)
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_X__LEN (1)
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_X__MSK (0x10)
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_X__REG \
+ (SMI130_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 5 */
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_Y__POS (5)
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_Y__LEN (1)
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_Y__MSK (0x20)
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_Y__REG \
+ (SMI130_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 6 */
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_Z__POS (6)
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_Z__LEN (1)
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_Z__MSK (0x40)
+#define SMI130_USER_INTR_STAT_2_TAP_FIRST_Z__REG \
+ (SMI130_USER_INTR_STAT_2_ADDR)
+
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 7 */
+#define SMI130_USER_INTR_STAT_2_TAP_SIGN__POS (7)
+#define SMI130_USER_INTR_STAT_2_TAP_SIGN__LEN (1)
+#define SMI130_USER_INTR_STAT_2_TAP_SIGN__MSK (0x80)
+#define SMI130_USER_INTR_STAT_2_TAP_SIGN__REG \
+ (SMI130_USER_INTR_STAT_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT SATAUS FOR WHOLE 0x1E LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_2 Description - Reg Addr --> 0x1E, Bit --> 0...7 */
+#define SMI130_USER_INTR_STAT_2__POS (0)
+#define SMI130_USER_INTR_STAT_2__LEN (8)
+#define SMI130_USER_INTR_STAT_2__MSK (0xFF)
+#define SMI130_USER_INTR_STAT_2__REG \
+ (SMI130_USER_INTR_STAT_2_ADDR)
+/**************************************************************/
+/**\name HIGH_G-XYZ AND SIGN LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 0 */
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_X__POS (0)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_X__LEN (1)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_X__MSK (0x01)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_X__REG \
+ (SMI130_USER_INTR_STAT_3_ADDR)
+
+/* Int_Status_3 Description - Reg Addr --> 0x1E, Bit --> 1 */
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Y__POS (1)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Y__LEN (1)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Y__MSK (0x02)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Y__REG \
+ (SMI130_USER_INTR_STAT_3_ADDR)
+
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 2 */
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Z__POS (2)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Z__LEN (1)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Z__MSK (0x04)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_FIRST_Z__REG \
+ (SMI130_USER_INTR_STAT_3_ADDR)
+
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 3 */
+#define SMI130_USER_INTR_STAT_3_HIGH_G_SIGN__POS (3)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_SIGN__LEN (1)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_SIGN__MSK (0x08)
+#define SMI130_USER_INTR_STAT_3_HIGH_G_SIGN__REG \
+ (SMI130_USER_INTR_STAT_3_ADDR)
+/**************************************************************/
+/**\name ORIENT XY and Z AXIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 4...5 */
+#define SMI130_USER_INTR_STAT_3_ORIENT_XY__POS (4)
+#define SMI130_USER_INTR_STAT_3_ORIENT_XY__LEN (2)
+#define SMI130_USER_INTR_STAT_3_ORIENT_XY__MSK (0x30)
+#define SMI130_USER_INTR_STAT_3_ORIENT_XY__REG \
+ (SMI130_USER_INTR_STAT_3_ADDR)
+
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 6 */
+#define SMI130_USER_INTR_STAT_3_ORIENT_Z__POS (6)
+#define SMI130_USER_INTR_STAT_3_ORIENT_Z__LEN (1)
+#define SMI130_USER_INTR_STAT_3_ORIENT_Z__MSK (0x40)
+#define SMI130_USER_INTR_STAT_3_ORIENT_Z__REG \
+ (SMI130_USER_INTR_STAT_3_ADDR)
+/**************************************************************/
+/**\name FLAT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 7 */
+#define SMI130_USER_INTR_STAT_3_FLAT__POS (7)
+#define SMI130_USER_INTR_STAT_3_FLAT__LEN (1)
+#define SMI130_USER_INTR_STAT_3_FLAT__MSK (0x80)
+#define SMI130_USER_INTR_STAT_3_FLAT__REG \
+ (SMI130_USER_INTR_STAT_3_ADDR)
+/**************************************************************/
+/**\name (0x1F) LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Status_3 Description - Reg Addr --> (0x1F), Bit --> 0...7 */
+#define SMI130_USER_INTR_STAT_3__POS (0)
+#define SMI130_USER_INTR_STAT_3__LEN (8)
+#define SMI130_USER_INTR_STAT_3__MSK (0xFF)
+#define SMI130_USER_INTR_STAT_3__REG \
+ (SMI130_USER_INTR_STAT_3_ADDR)
+/**************************************************************/
+/**\name TEMPERATURE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Temperature Description - LSB Reg Addr --> (0x20), Bit --> 0...7 */
+#define SMI130_USER_TEMP_LSB_VALUE__POS (0)
+#define SMI130_USER_TEMP_LSB_VALUE__LEN (8)
+#define SMI130_USER_TEMP_LSB_VALUE__MSK (0xFF)
+#define SMI130_USER_TEMP_LSB_VALUE__REG \
+ (SMI130_USER_TEMPERATURE_0_ADDR)
+
+/* Temperature Description - LSB Reg Addr --> 0x21, Bit --> 0...7 */
+#define SMI130_USER_TEMP_MSB_VALUE__POS (0)
+#define SMI130_USER_TEMP_MSB_VALUE__LEN (8)
+#define SMI130_USER_TEMP_MSB_VALUE__MSK (0xFF)
+#define SMI130_USER_TEMP_MSB_VALUE__REG \
+ (SMI130_USER_TEMPERATURE_1_ADDR)
+/**************************************************************/
+/**\name FIFO BYTE COUNTER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Length0 Description - Reg Addr --> 0x22, Bit --> 0...7 */
+#define SMI130_USER_FIFO_BYTE_COUNTER_LSB__POS (0)
+#define SMI130_USER_FIFO_BYTE_COUNTER_LSB__LEN (8)
+#define SMI130_USER_FIFO_BYTE_COUNTER_LSB__MSK (0xFF)
+#define SMI130_USER_FIFO_BYTE_COUNTER_LSB__REG \
+ (SMI130_USER_FIFO_LENGTH_0_ADDR)
+
+/*Fifo_Length1 Description - Reg Addr --> 0x23, Bit --> 0...2 */
+#define SMI130_USER_FIFO_BYTE_COUNTER_MSB__POS (0)
+#define SMI130_USER_FIFO_BYTE_COUNTER_MSB__LEN 3
+#define SMI130_USER_FIFO_BYTE_COUNTER_MSB__MSK (0x07)
+#define SMI130_USER_FIFO_BYTE_COUNTER_MSB__REG \
+ (SMI130_USER_FIFO_LENGTH_1_ADDR)
+
+/**************************************************************/
+/**\name FIFO DATA LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Data Description - Reg Addr --> 0x24, Bit --> 0...7 */
+#define SMI130_USER_FIFO_DATA__POS (0)
+#define SMI130_USER_FIFO_DATA__LEN (8)
+#define SMI130_USER_FIFO_DATA__MSK (0xFF)
+#define SMI130_USER_FIFO_DATA__REG (SMI130_USER_FIFO_DATA_ADDR)
+
+/**************************************************************/
+/**\name ACCEL CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Acc_Conf Description - Reg Addr --> (0x40), Bit --> 0...3 */
+#define SMI130_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__POS (0)
+#define SMI130_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__LEN (4)
+#define SMI130_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__MSK (0x0F)
+#define SMI130_USER_ACCEL_CONFIG_OUTPUT_DATA_RATE__REG \
+(SMI130_USER_ACCEL_CONFIG_ADDR)
+
+/* Acc_Conf Description - Reg Addr --> (0x40), Bit --> 4...6 */
+#define SMI130_USER_ACCEL_CONFIG_ACCEL_BW__POS (4)
+#define SMI130_USER_ACCEL_CONFIG_ACCEL_BW__LEN (3)
+#define SMI130_USER_ACCEL_CONFIG_ACCEL_BW__MSK (0x70)
+#define SMI130_USER_ACCEL_CONFIG_ACCEL_BW__REG (SMI130_USER_ACCEL_CONFIG_ADDR)
+
+/* Acc_Conf Description - Reg Addr --> (0x40), Bit --> 7 */
+#define SMI130_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__POS (7)
+#define SMI130_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__LEN (1)
+#define SMI130_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__MSK (0x80)
+#define SMI130_USER_ACCEL_CONFIG_ACCEL_UNDER_SAMPLING__REG \
+(SMI130_USER_ACCEL_CONFIG_ADDR)
+
+/* Acc_Range Description - Reg Addr --> 0x41, Bit --> 0...3 */
+#define SMI130_USER_ACCEL_RANGE__POS (0)
+#define SMI130_USER_ACCEL_RANGE__LEN (4)
+#define SMI130_USER_ACCEL_RANGE__MSK (0x0F)
+#define SMI130_USER_ACCEL_RANGE__REG \
+(SMI130_USER_ACCEL_RANGE_ADDR)
+/**************************************************************/
+/**\name GYRO CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Gyro_Conf Description - Reg Addr --> (0x42), Bit --> 0...3 */
+#define SMI130_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__POS (0)
+#define SMI130_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__LEN (4)
+#define SMI130_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__MSK (0x0F)
+#define SMI130_USER_GYRO_CONFIG_OUTPUT_DATA_RATE__REG \
+(SMI130_USER_GYRO_CONFIG_ADDR)
+
+/* Gyro_Conf Description - Reg Addr --> (0x42), Bit --> 4...5 */
+#define SMI130_USER_GYRO_CONFIG_BW__POS (4)
+#define SMI130_USER_GYRO_CONFIG_BW__LEN (2)
+#define SMI130_USER_GYRO_CONFIG_BW__MSK (0x30)
+#define SMI130_USER_GYRO_CONFIG_BW__REG \
+(SMI130_USER_GYRO_CONFIG_ADDR)
+
+/* Gyr_Range Description - Reg Addr --> 0x43, Bit --> 0...2 */
+#define SMI130_USER_GYRO_RANGE__POS (0)
+#define SMI130_USER_GYRO_RANGE__LEN (3)
+#define SMI130_USER_GYRO_RANGE__MSK (0x07)
+#define SMI130_USER_GYRO_RANGE__REG (SMI130_USER_GYRO_RANGE_ADDR)
+/**************************************************************/
+/**\name MAG CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Mag_Conf Description - Reg Addr --> (0x44), Bit --> 0...3 */
+#define SMI130_USER_MAG_CONFIG_OUTPUT_DATA_RATE__POS (0)
+#define SMI130_USER_MAG_CONFIG_OUTPUT_DATA_RATE__LEN (4)
+#define SMI130_USER_MAG_CONFIG_OUTPUT_DATA_RATE__MSK (0x0F)
+#define SMI130_USER_MAG_CONFIG_OUTPUT_DATA_RATE__REG \
+(SMI130_USER_MAG_CONFIG_ADDR)
+/**************************************************************/
+/**\name FIFO DOWNS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Downs Description - Reg Addr --> 0x45, Bit --> 0...2 */
+#define SMI130_USER_FIFO_DOWN_GYRO__POS (0)
+#define SMI130_USER_FIFO_DOWN_GYRO__LEN (3)
+#define SMI130_USER_FIFO_DOWN_GYRO__MSK (0x07)
+#define SMI130_USER_FIFO_DOWN_GYRO__REG (SMI130_USER_FIFO_DOWN_ADDR)
+/**************************************************************/
+/**\name FIFO FILTER FOR ACCEL AND GYRO LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_filt Description - Reg Addr --> 0x45, Bit --> 3 */
+#define SMI130_USER_FIFO_FILTER_GYRO__POS (3)
+#define SMI130_USER_FIFO_FILTER_GYRO__LEN (1)
+#define SMI130_USER_FIFO_FILTER_GYRO__MSK (0x08)
+#define SMI130_USER_FIFO_FILTER_GYRO__REG (SMI130_USER_FIFO_DOWN_ADDR)
+
+/* Fifo_Downs Description - Reg Addr --> 0x45, Bit --> 4...6 */
+#define SMI130_USER_FIFO_DOWN_ACCEL__POS (4)
+#define SMI130_USER_FIFO_DOWN_ACCEL__LEN (3)
+#define SMI130_USER_FIFO_DOWN_ACCEL__MSK (0x70)
+#define SMI130_USER_FIFO_DOWN_ACCEL__REG (SMI130_USER_FIFO_DOWN_ADDR)
+
+/* Fifo_FILT Description - Reg Addr --> 0x45, Bit --> 7 */
+#define SMI130_USER_FIFO_FILTER_ACCEL__POS (7)
+#define SMI130_USER_FIFO_FILTER_ACCEL__LEN (1)
+#define SMI130_USER_FIFO_FILTER_ACCEL__MSK (0x80)
+#define SMI130_USER_FIFO_FILTER_ACCEL__REG (SMI130_USER_FIFO_DOWN_ADDR)
+/**************************************************************/
+/**\name FIFO WATER MARK LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_0 Description - Reg Addr --> 0x46, Bit --> 0...7 */
+#define SMI130_USER_FIFO_WM__POS (0)
+#define SMI130_USER_FIFO_WM__LEN (8)
+#define SMI130_USER_FIFO_WM__MSK (0xFF)
+#define SMI130_USER_FIFO_WM__REG (SMI130_USER_FIFO_CONFIG_0_ADDR)
+/**************************************************************/
+/**\name FIFO TIME LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 1 */
+#define SMI130_USER_FIFO_TIME_ENABLE__POS (1)
+#define SMI130_USER_FIFO_TIME_ENABLE__LEN (1)
+#define SMI130_USER_FIFO_TIME_ENABLE__MSK (0x02)
+#define SMI130_USER_FIFO_TIME_ENABLE__REG (SMI130_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO TAG INTERRUPT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 2 */
+#define SMI130_USER_FIFO_TAG_INTR2_ENABLE__POS (2)
+#define SMI130_USER_FIFO_TAG_INTR2_ENABLE__LEN (1)
+#define SMI130_USER_FIFO_TAG_INTR2_ENABLE__MSK (0x04)
+#define SMI130_USER_FIFO_TAG_INTR2_ENABLE__REG (SMI130_USER_FIFO_CONFIG_1_ADDR)
+
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 3 */
+#define SMI130_USER_FIFO_TAG_INTR1_ENABLE__POS (3)
+#define SMI130_USER_FIFO_TAG_INTR1_ENABLE__LEN (1)
+#define SMI130_USER_FIFO_TAG_INTR1_ENABLE__MSK (0x08)
+#define SMI130_USER_FIFO_TAG_INTR1_ENABLE__REG (SMI130_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO HEADER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 4 */
+#define SMI130_USER_FIFO_HEADER_ENABLE__POS (4)
+#define SMI130_USER_FIFO_HEADER_ENABLE__LEN (1)
+#define SMI130_USER_FIFO_HEADER_ENABLE__MSK (0x10)
+#define SMI130_USER_FIFO_HEADER_ENABLE__REG \
+(SMI130_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO MAG ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 5 */
+#define SMI130_USER_FIFO_MAG_ENABLE__POS (5)
+#define SMI130_USER_FIFO_MAG_ENABLE__LEN (1)
+#define SMI130_USER_FIFO_MAG_ENABLE__MSK (0x20)
+#define SMI130_USER_FIFO_MAG_ENABLE__REG \
+(SMI130_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO ACCEL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 6 */
+#define SMI130_USER_FIFO_ACCEL_ENABLE__POS (6)
+#define SMI130_USER_FIFO_ACCEL_ENABLE__LEN (1)
+#define SMI130_USER_FIFO_ACCEL_ENABLE__MSK (0x40)
+#define SMI130_USER_FIFO_ACCEL_ENABLE__REG \
+(SMI130_USER_FIFO_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name FIFO GYRO ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Fifo_Config_1 Description - Reg Addr --> 0x47, Bit --> 7 */
+#define SMI130_USER_FIFO_GYRO_ENABLE__POS (7)
+#define SMI130_USER_FIFO_GYRO_ENABLE__LEN (1)
+#define SMI130_USER_FIFO_GYRO_ENABLE__MSK (0x80)
+#define SMI130_USER_FIFO_GYRO_ENABLE__REG \
+(SMI130_USER_FIFO_CONFIG_1_ADDR)
+
+/**************************************************************/
+/**\name MAG I2C ADDRESS SELECTION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+
+/* Mag_IF_0 Description - Reg Addr --> 0x4b, Bit --> 1...7 */
+#define SMI130_USER_I2C_DEVICE_ADDR__POS (1)
+#define SMI130_USER_I2C_DEVICE_ADDR__LEN (7)
+#define SMI130_USER_I2C_DEVICE_ADDR__MSK (0xFE)
+#define SMI130_USER_I2C_DEVICE_ADDR__REG (SMI130_USER_MAG_IF_0_ADDR)
+/**************************************************************/
+/**\name MAG CONFIGURATION FOR SECONDARY
+ INTERFACE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Mag_IF_1 Description - Reg Addr --> 0x4c, Bit --> 0...1 */
+#define SMI130_USER_MAG_BURST__POS (0)
+#define SMI130_USER_MAG_BURST__LEN (2)
+#define SMI130_USER_MAG_BURST__MSK (0x03)
+#define SMI130_USER_MAG_BURST__REG (SMI130_USER_MAG_IF_1_ADDR)
+
+/* Mag_IF_1 Description - Reg Addr --> 0x4c, Bit --> 2...5 */
+#define SMI130_USER_MAG_OFFSET__POS (2)
+#define SMI130_USER_MAG_OFFSET__LEN (4)
+#define SMI130_USER_MAG_OFFSET__MSK (0x3C)
+#define SMI130_USER_MAG_OFFSET__REG (SMI130_USER_MAG_IF_1_ADDR)
+
+/* Mag_IF_1 Description - Reg Addr --> 0x4c, Bit --> 7 */
+#define SMI130_USER_MAG_MANUAL_ENABLE__POS (7)
+#define SMI130_USER_MAG_MANUAL_ENABLE__LEN (1)
+#define SMI130_USER_MAG_MANUAL_ENABLE__MSK (0x80)
+#define SMI130_USER_MAG_MANUAL_ENABLE__REG \
+(SMI130_USER_MAG_IF_1_ADDR)
+
+/* Mag_IF_2 Description - Reg Addr --> 0x4d, Bit -->0... 7 */
+#define SMI130_USER_READ_ADDR__POS (0)
+#define SMI130_USER_READ_ADDR__LEN (8)
+#define SMI130_USER_READ_ADDR__MSK (0xFF)
+#define SMI130_USER_READ_ADDR__REG (SMI130_USER_MAG_IF_2_ADDR)
+
+/* Mag_IF_3 Description - Reg Addr --> 0x4e, Bit -->0... 7 */
+#define SMI130_USER_WRITE_ADDR__POS (0)
+#define SMI130_USER_WRITE_ADDR__LEN (8)
+#define SMI130_USER_WRITE_ADDR__MSK (0xFF)
+#define SMI130_USER_WRITE_ADDR__REG (SMI130_USER_MAG_IF_3_ADDR)
+
+/* Mag_IF_4 Description - Reg Addr --> 0x4f, Bit -->0... 7 */
+#define SMI130_USER_WRITE_DATA__POS (0)
+#define SMI130_USER_WRITE_DATA__LEN (8)
+#define SMI130_USER_WRITE_DATA__MSK (0xFF)
+#define SMI130_USER_WRITE_DATA__REG (SMI130_USER_MAG_IF_4_ADDR)
+/**************************************************************/
+/**\name ANY MOTION XYZ AXIS ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->0 */
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__POS (0)
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__MSK (0x01)
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_X_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_0_ADDR)
+
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->1 */
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__POS (1)
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__MSK (0x02)
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Y_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_0_ADDR)
+
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->2 */
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__POS (2)
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__MSK (0x04)
+#define SMI130_USER_INTR_ENABLE_0_ANY_MOTION_Z_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name DOUBLE TAP ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->4 */
+#define SMI130_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__POS (4)
+#define SMI130_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__MSK (0x10)
+#define SMI130_USER_INTR_ENABLE_0_DOUBLE_TAP_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name SINGLE TAP ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->5 */
+#define SMI130_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__POS (5)
+#define SMI130_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__MSK (0x20)
+#define SMI130_USER_INTR_ENABLE_0_SINGLE_TAP_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name ORIENT ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->6 */
+#define SMI130_USER_INTR_ENABLE_0_ORIENT_ENABLE__POS (6)
+#define SMI130_USER_INTR_ENABLE_0_ORIENT_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_0_ORIENT_ENABLE__MSK (0x40)
+#define SMI130_USER_INTR_ENABLE_0_ORIENT_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name FLAT ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_0 Description - Reg Addr --> 0x50, Bit -->7 */
+#define SMI130_USER_INTR_ENABLE_0_FLAT_ENABLE__POS (7)
+#define SMI130_USER_INTR_ENABLE_0_FLAT_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_0_FLAT_ENABLE__MSK (0x80)
+#define SMI130_USER_INTR_ENABLE_0_FLAT_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_0_ADDR)
+/**************************************************************/
+/**\name HIGH_G XYZ ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->0 */
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__POS (0)
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__MSK (0x01)
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_X_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_1_ADDR)
+
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->1 */
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__POS (1)
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__MSK (0x02)
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_Y_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_1_ADDR)
+
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->2 */
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__POS (2)
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__MSK (0x04)
+#define SMI130_USER_INTR_ENABLE_1_HIGH_G_Z_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_1_ADDR)
+/**************************************************************/
+/**\name LOW_G ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->3 */
+#define SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__POS (3)
+#define SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__MSK (0x08)
+#define SMI130_USER_INTR_ENABLE_1_LOW_G_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_1_ADDR)
+/**************************************************************/
+/**\name DATA READY ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->4 */
+#define SMI130_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__POS (4)
+#define SMI130_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__MSK (0x10)
+#define SMI130_USER_INTR_ENABLE_1_DATA_RDY_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_1_ADDR)
+/**************************************************************/
+/**\name FIFO FULL AND WATER MARK ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->5 */
+#define SMI130_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__POS (5)
+#define SMI130_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__MSK (0x20)
+#define SMI130_USER_INTR_ENABLE_1_FIFO_FULL_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_1_ADDR)
+
+/* Int_En_1 Description - Reg Addr --> (0x51), Bit -->6 */
+#define SMI130_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__POS (6)
+#define SMI130_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__MSK (0x40)
+#define SMI130_USER_INTR_ENABLE_1_FIFO_WM_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_1_ADDR)
+/**************************************************************/
+/**\name NO MOTION XYZ ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_2 Description - Reg Addr --> (0x52), Bit -->0 */
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__POS (0)
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__MSK (0x01)
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_X_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_2_ADDR)
+
+/* Int_En_2 Description - Reg Addr --> (0x52), Bit -->1 */
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__POS (1)
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__MSK (0x02)
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_Y_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_2_ADDR)
+
+/* Int_En_2 Description - Reg Addr --> (0x52), Bit -->2 */
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__POS (2)
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__MSK (0x04)
+#define SMI130_USER_INTR_ENABLE_2_NOMOTION_Z_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_2_ADDR)
+/**************************************************************/
+/**\name STEP DETECTOR ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_En_2 Description - Reg Addr --> (0x52), Bit -->3 */
+#define SMI130_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__POS (3)
+#define SMI130_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__MSK (0x08)
+#define SMI130_USER_INTR_ENABLE_2_STEP_DETECTOR_ENABLE__REG \
+(SMI130_USER_INTR_ENABLE_2_ADDR)
+/**************************************************************/
+/**\name EDGE CONTROL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->0 */
+#define SMI130_USER_INTR1_EDGE_CTRL__POS (0)
+#define SMI130_USER_INTR1_EDGE_CTRL__LEN (1)
+#define SMI130_USER_INTR1_EDGE_CTRL__MSK (0x01)
+#define SMI130_USER_INTR1_EDGE_CTRL__REG \
+(SMI130_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name LEVEL CONTROL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->1 */
+#define SMI130_USER_INTR1_LEVEL__POS (1)
+#define SMI130_USER_INTR1_LEVEL__LEN (1)
+#define SMI130_USER_INTR1_LEVEL__MSK (0x02)
+#define SMI130_USER_INTR1_LEVEL__REG \
+(SMI130_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name OUTPUT TYPE ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->2 */
+#define SMI130_USER_INTR1_OUTPUT_TYPE__POS (2)
+#define SMI130_USER_INTR1_OUTPUT_TYPE__LEN (1)
+#define SMI130_USER_INTR1_OUTPUT_TYPE__MSK (0x04)
+#define SMI130_USER_INTR1_OUTPUT_TYPE__REG \
+(SMI130_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name OUTPUT TYPE ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->3 */
+#define SMI130_USER_INTR1_OUTPUT_ENABLE__POS (3)
+#define SMI130_USER_INTR1_OUTPUT_ENABLE__LEN (1)
+#define SMI130_USER_INTR1_OUTPUT_ENABLE__MSK (0x08)
+#define SMI130_USER_INTR1_OUTPUT_ENABLE__REG \
+(SMI130_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name EDGE CONTROL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->4 */
+#define SMI130_USER_INTR2_EDGE_CTRL__POS (4)
+#define SMI130_USER_INTR2_EDGE_CTRL__LEN (1)
+#define SMI130_USER_INTR2_EDGE_CTRL__MSK (0x10)
+#define SMI130_USER_INTR2_EDGE_CTRL__REG \
+(SMI130_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name LEVEL CONTROL ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->5 */
+#define SMI130_USER_INTR2_LEVEL__POS (5)
+#define SMI130_USER_INTR2_LEVEL__LEN (1)
+#define SMI130_USER_INTR2_LEVEL__MSK (0x20)
+#define SMI130_USER_INTR2_LEVEL__REG \
+(SMI130_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name OUTPUT TYPE ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->6 */
+#define SMI130_USER_INTR2_OUTPUT_TYPE__POS (6)
+#define SMI130_USER_INTR2_OUTPUT_TYPE__LEN (1)
+#define SMI130_USER_INTR2_OUTPUT_TYPE__MSK (0x40)
+#define SMI130_USER_INTR2_OUTPUT_TYPE__REG \
+(SMI130_USER_INTR_OUT_CTRL_ADDR)
+
+/* Int_Out_Ctrl Description - Reg Addr --> 0x53, Bit -->7 */
+#define SMI130_USER_INTR2_OUTPUT_EN__POS (7)
+#define SMI130_USER_INTR2_OUTPUT_EN__LEN (1)
+#define SMI130_USER_INTR2_OUTPUT_EN__MSK (0x80)
+#define SMI130_USER_INTR2_OUTPUT_EN__REG \
+(SMI130_USER_INTR_OUT_CTRL_ADDR)
+/**************************************************************/
+/**\name LATCH INTERRUPT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Latch Description - Reg Addr --> 0x54, Bit -->0...3 */
+#define SMI130_USER_INTR_LATCH__POS (0)
+#define SMI130_USER_INTR_LATCH__LEN (4)
+#define SMI130_USER_INTR_LATCH__MSK (0x0F)
+#define SMI130_USER_INTR_LATCH__REG (SMI130_USER_INTR_LATCH_ADDR)
+/**************************************************************/
+/**\name INPUT ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Latch Description - Reg Addr --> 0x54, Bit -->4 */
+#define SMI130_USER_INTR1_INPUT_ENABLE__POS (4)
+#define SMI130_USER_INTR1_INPUT_ENABLE__LEN (1)
+#define SMI130_USER_INTR1_INPUT_ENABLE__MSK (0x10)
+#define SMI130_USER_INTR1_INPUT_ENABLE__REG \
+(SMI130_USER_INTR_LATCH_ADDR)
+
+/* Int_Latch Description - Reg Addr --> 0x54, Bit -->5*/
+#define SMI130_USER_INTR2_INPUT_ENABLE__POS (5)
+#define SMI130_USER_INTR2_INPUT_ENABLE__LEN (1)
+#define SMI130_USER_INTR2_INPUT_ENABLE__MSK (0x20)
+#define SMI130_USER_INTR2_INPUT_ENABLE__REG \
+(SMI130_USER_INTR_LATCH_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF LOW_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->0 */
+#define SMI130_USER_INTR_MAP_0_INTR1_LOW_G__POS (0)
+#define SMI130_USER_INTR_MAP_0_INTR1_LOW_G__LEN (1)
+#define SMI130_USER_INTR_MAP_0_INTR1_LOW_G__MSK (0x01)
+#define SMI130_USER_INTR_MAP_0_INTR1_LOW_G__REG (SMI130_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF HIGH_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->1 */
+#define SMI130_USER_INTR_MAP_0_INTR1_HIGH_G__POS (1)
+#define SMI130_USER_INTR_MAP_0_INTR1_HIGH_G__LEN (1)
+#define SMI130_USER_INTR_MAP_0_INTR1_HIGH_G__MSK (0x02)
+#define SMI130_USER_INTR_MAP_0_INTR1_HIGH_G__REG \
+(SMI130_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT MAPPIONG OF ANY MOTION_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->2 */
+#define SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION__POS (2)
+#define SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION__LEN (1)
+#define SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION__MSK (0x04)
+#define SMI130_USER_INTR_MAP_0_INTR1_ANY_MOTION__REG \
+(SMI130_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF NO MOTION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->3 */
+#define SMI130_USER_INTR_MAP_0_INTR1_NOMOTION__POS (3)
+#define SMI130_USER_INTR_MAP_0_INTR1_NOMOTION__LEN (1)
+#define SMI130_USER_INTR_MAP_0_INTR1_NOMOTION__MSK (0x08)
+#define SMI130_USER_INTR_MAP_0_INTR1_NOMOTION__REG (SMI130_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF DOUBLE TAP LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->4 */
+#define SMI130_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__POS (4)
+#define SMI130_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__LEN (1)
+#define SMI130_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__MSK (0x10)
+#define SMI130_USER_INTR_MAP_0_INTR1_DOUBLE_TAP__REG \
+(SMI130_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF SINGLE TAP LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->5 */
+#define SMI130_USER_INTR_MAP_0_INTR1_SINGLE_TAP__POS (5)
+#define SMI130_USER_INTR_MAP_0_INTR1_SINGLE_TAP__LEN (1)
+#define SMI130_USER_INTR_MAP_0_INTR1_SINGLE_TAP__MSK (0x20)
+#define SMI130_USER_INTR_MAP_0_INTR1_SINGLE_TAP__REG \
+(SMI130_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF ORIENT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x55, Bit -->6 */
+#define SMI130_USER_INTR_MAP_0_INTR1_ORIENT__POS (6)
+#define SMI130_USER_INTR_MAP_0_INTR1_ORIENT__LEN (1)
+#define SMI130_USER_INTR_MAP_0_INTR1_ORIENT__MSK (0x40)
+#define SMI130_USER_INTR_MAP_0_INTR1_ORIENT__REG \
+(SMI130_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT MAPPIONG OF FLAT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_0 Description - Reg Addr --> 0x56, Bit -->7 */
+#define SMI130_USER_INTR_MAP_0_INTR1_FLAT__POS (7)
+#define SMI130_USER_INTR_MAP_0_INTR1_FLAT__LEN (1)
+#define SMI130_USER_INTR_MAP_0_INTR1_FLAT__MSK (0x80)
+#define SMI130_USER_INTR_MAP_0_INTR1_FLAT__REG (SMI130_USER_INTR_MAP_0_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF PMU TRIGGER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->0 */
+#define SMI130_USER_INTR_MAP_1_INTR2_PMU_TRIG__POS (0)
+#define SMI130_USER_INTR_MAP_1_INTR2_PMU_TRIG__LEN (1)
+#define SMI130_USER_INTR_MAP_1_INTR2_PMU_TRIG__MSK (0x01)
+#define SMI130_USER_INTR_MAP_1_INTR2_PMU_TRIG__REG (SMI130_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF FIFO FULL AND
+ WATER MARK LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->1 */
+#define SMI130_USER_INTR_MAP_1_INTR2_FIFO_FULL__POS (1)
+#define SMI130_USER_INTR_MAP_1_INTR2_FIFO_FULL__LEN (1)
+#define SMI130_USER_INTR_MAP_1_INTR2_FIFO_FULL__MSK (0x02)
+#define SMI130_USER_INTR_MAP_1_INTR2_FIFO_FULL__REG \
+(SMI130_USER_INTR_MAP_1_ADDR)
+
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->2 */
+#define SMI130_USER_INTR_MAP_1_INTR2_FIFO_WM__POS (2)
+#define SMI130_USER_INTR_MAP_1_INTR2_FIFO_WM__LEN (1)
+#define SMI130_USER_INTR_MAP_1_INTR2_FIFO_WM__MSK (0x04)
+#define SMI130_USER_INTR_MAP_1_INTR2_FIFO_WM__REG \
+(SMI130_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF DATA READY LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->3 */
+#define SMI130_USER_INTR_MAP_1_INTR2_DATA_RDY__POS (3)
+#define SMI130_USER_INTR_MAP_1_INTR2_DATA_RDY__LEN (1)
+#define SMI130_USER_INTR_MAP_1_INTR2_DATA_RDY__MSK (0x08)
+#define SMI130_USER_INTR_MAP_1_INTR2_DATA_RDY__REG \
+(SMI130_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF PMU TRIGGER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->4 */
+#define SMI130_USER_INTR_MAP_1_INTR1_PMU_TRIG__POS (4)
+#define SMI130_USER_INTR_MAP_1_INTR1_PMU_TRIG__LEN (1)
+#define SMI130_USER_INTR_MAP_1_INTR1_PMU_TRIG__MSK (0x10)
+#define SMI130_USER_INTR_MAP_1_INTR1_PMU_TRIG__REG (SMI130_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF FIFO FULL AND
+ WATER MARK LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->5 */
+#define SMI130_USER_INTR_MAP_1_INTR1_FIFO_FULL__POS (5)
+#define SMI130_USER_INTR_MAP_1_INTR1_FIFO_FULL__LEN (1)
+#define SMI130_USER_INTR_MAP_1_INTR1_FIFO_FULL__MSK (0x20)
+#define SMI130_USER_INTR_MAP_1_INTR1_FIFO_FULL__REG \
+(SMI130_USER_INTR_MAP_1_ADDR)
+
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->6 */
+#define SMI130_USER_INTR_MAP_1_INTR1_FIFO_WM__POS (6)
+#define SMI130_USER_INTR_MAP_1_INTR1_FIFO_WM__LEN (1)
+#define SMI130_USER_INTR_MAP_1_INTR1_FIFO_WM__MSK (0x40)
+#define SMI130_USER_INTR_MAP_1_INTR1_FIFO_WM__REG \
+(SMI130_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT1 MAPPIONG OF DATA READY LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_1 Description - Reg Addr --> 0x56, Bit -->7 */
+#define SMI130_USER_INTR_MAP_1_INTR1_DATA_RDY__POS (7)
+#define SMI130_USER_INTR_MAP_1_INTR1_DATA_RDY__LEN (1)
+#define SMI130_USER_INTR_MAP_1_INTR1_DATA_RDY__MSK (0x80)
+#define SMI130_USER_INTR_MAP_1_INTR1_DATA_RDY__REG \
+(SMI130_USER_INTR_MAP_1_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF LOW_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->0 */
+#define SMI130_USER_INTR_MAP_2_INTR2_LOW_G__POS (0)
+#define SMI130_USER_INTR_MAP_2_INTR2_LOW_G__LEN (1)
+#define SMI130_USER_INTR_MAP_2_INTR2_LOW_G__MSK (0x01)
+#define SMI130_USER_INTR_MAP_2_INTR2_LOW_G__REG (SMI130_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF HIGH_G LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->1 */
+#define SMI130_USER_INTR_MAP_2_INTR2_HIGH_G__POS (1)
+#define SMI130_USER_INTR_MAP_2_INTR2_HIGH_G__LEN (1)
+#define SMI130_USER_INTR_MAP_2_INTR2_HIGH_G__MSK (0x02)
+#define SMI130_USER_INTR_MAP_2_INTR2_HIGH_G__REG \
+(SMI130_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF ANY MOTION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->2 */
+#define SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION__POS (2)
+#define SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION__LEN (1)
+#define SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION__MSK (0x04)
+#define SMI130_USER_INTR_MAP_2_INTR2_ANY_MOTION__REG \
+(SMI130_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF NO MOTION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->3 */
+#define SMI130_USER_INTR_MAP_2_INTR2_NOMOTION__POS (3)
+#define SMI130_USER_INTR_MAP_2_INTR2_NOMOTION__LEN (1)
+#define SMI130_USER_INTR_MAP_2_INTR2_NOMOTION__MSK (0x08)
+#define SMI130_USER_INTR_MAP_2_INTR2_NOMOTION__REG (SMI130_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF DOUBLE TAP LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->4 */
+#define SMI130_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__POS (4)
+#define SMI130_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__LEN (1)
+#define SMI130_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__MSK (0x10)
+#define SMI130_USER_INTR_MAP_2_INTR2_DOUBLE_TAP__REG \
+(SMI130_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF SINGLE TAP LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->5 */
+#define SMI130_USER_INTR_MAP_2_INTR2_SINGLE_TAP__POS (5)
+#define SMI130_USER_INTR_MAP_2_INTR2_SINGLE_TAP__LEN (1)
+#define SMI130_USER_INTR_MAP_2_INTR2_SINGLE_TAP__MSK (0x20)
+#define SMI130_USER_INTR_MAP_2_INTR2_SINGLE_TAP__REG \
+(SMI130_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF ORIENT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->6 */
+#define SMI130_USER_INTR_MAP_2_INTR2_ORIENT__POS (6)
+#define SMI130_USER_INTR_MAP_2_INTR2_ORIENT__LEN (1)
+#define SMI130_USER_INTR_MAP_2_INTR2_ORIENT__MSK (0x40)
+#define SMI130_USER_INTR_MAP_2_INTR2_ORIENT__REG \
+(SMI130_USER_INTR_MAP_2_ADDR)
+/**************************************************************/
+/**\name INTERRUPT2 MAPPIONG OF FLAT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Map_2 Description - Reg Addr --> 0x57, Bit -->7 */
+#define SMI130_USER_INTR_MAP_2_INTR2_FLAT__POS (7)
+#define SMI130_USER_INTR_MAP_2_INTR2_FLAT__LEN (1)
+#define SMI130_USER_INTR_MAP_2_INTR2_FLAT__MSK (0x80)
+#define SMI130_USER_INTR_MAP_2_INTR2_FLAT__REG (SMI130_USER_INTR_MAP_2_ADDR)
+
+/**************************************************************/
+/**\name TAP SOURCE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Data_0 Description - Reg Addr --> 0x58, Bit --> 3 */
+#define SMI130_USER_INTR_DATA_0_INTR_TAP_SOURCE__POS (3)
+#define SMI130_USER_INTR_DATA_0_INTR_TAP_SOURCE__LEN (1)
+#define SMI130_USER_INTR_DATA_0_INTR_TAP_SOURCE__MSK (0x08)
+#define SMI130_USER_INTR_DATA_0_INTR_TAP_SOURCE__REG \
+(SMI130_USER_INTR_DATA_0_ADDR)
+
+/**************************************************************/
+/**\name HIGH SOURCE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Data_0 Description - Reg Addr --> 0x58, Bit --> 7 */
+#define SMI130_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__POS (7)
+#define SMI130_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__LEN (1)
+#define SMI130_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__MSK (0x80)
+#define SMI130_USER_INTR_DATA_0_INTR_LOW_HIGH_SOURCE__REG \
+(SMI130_USER_INTR_DATA_0_ADDR)
+
+/**************************************************************/
+/**\name MOTION SOURCE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Data_1 Description - Reg Addr --> 0x59, Bit --> 7 */
+#define SMI130_USER_INTR_DATA_1_INTR_MOTION_SOURCE__POS (7)
+#define SMI130_USER_INTR_DATA_1_INTR_MOTION_SOURCE__LEN (1)
+#define SMI130_USER_INTR_DATA_1_INTR_MOTION_SOURCE__MSK (0x80)
+#define SMI130_USER_INTR_DATA_1_INTR_MOTION_SOURCE__REG \
+ (SMI130_USER_INTR_DATA_1_ADDR)
+/**************************************************************/
+/**\name LOW HIGH DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_0 Description - Reg Addr --> 0x5a, Bit --> 0...7 */
+#define SMI130_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__POS (0)
+#define SMI130_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__LEN (8)
+#define SMI130_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__MSK (0xFF)
+#define SMI130_USER_INTR_LOWHIGH_0_INTR_LOW_DURN__REG \
+ (SMI130_USER_INTR_LOWHIGH_0_ADDR)
+/**************************************************************/
+/**\name LOW THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_1 Description - Reg Addr --> 0x5b, Bit --> 0...7 */
+#define SMI130_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__POS (0)
+#define SMI130_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__LEN (8)
+#define SMI130_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__MSK (0xFF)
+#define SMI130_USER_INTR_LOWHIGH_1_INTR_LOW_THRES__REG \
+ (SMI130_USER_INTR_LOWHIGH_1_ADDR)
+/**************************************************************/
+/**\name LOW HYSTERESIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_2 Description - Reg Addr --> 0x5c, Bit --> 0...1 */
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__POS (0)
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__LEN (2)
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__MSK (0x03)
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_HYST__REG \
+ (SMI130_USER_INTR_LOWHIGH_2_ADDR)
+/**************************************************************/
+/**\name LOW MODE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_2 Description - Reg Addr --> 0x5c, Bit --> 2 */
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__POS (2)
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__LEN (1)
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__MSK (0x04)
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_LOW_G_MODE__REG \
+ (SMI130_USER_INTR_LOWHIGH_2_ADDR)
+/**************************************************************/
+/**\name HIGH_G HYSTERESIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_2 Description - Reg Addr --> 0x5c, Bit --> 6...7 */
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__POS (6)
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__LEN (2)
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__MSK (0xC0)
+#define SMI130_USER_INTR_LOWHIGH_2_INTR_HIGH_G_HYST__REG \
+ (SMI130_USER_INTR_LOWHIGH_2_ADDR)
+/**************************************************************/
+/**\name HIGH_G DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_3 Description - Reg Addr --> 0x5d, Bit --> 0...7 */
+#define SMI130_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__POS (0)
+#define SMI130_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__LEN (8)
+#define SMI130_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__MSK (0xFF)
+#define SMI130_USER_INTR_LOWHIGH_3_INTR_HIGH_G_DURN__REG \
+ (SMI130_USER_INTR_LOWHIGH_3_ADDR)
+/**************************************************************/
+/**\name HIGH_G THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_LowHigh_4 Description - Reg Addr --> 0x5e, Bit --> 0...7 */
+#define SMI130_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__POS (0)
+#define SMI130_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__LEN (8)
+#define SMI130_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__MSK (0xFF)
+#define SMI130_USER_INTR_LOWHIGH_4_INTR_HIGH_THRES__REG \
+ (SMI130_USER_INTR_LOWHIGH_4_ADDR)
+/**************************************************************/
+/**\name ANY MOTION DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_0 Description - Reg Addr --> 0x5f, Bit --> 0...1 */
+#define SMI130_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__POS (0)
+#define SMI130_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__LEN (2)
+#define SMI130_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__MSK (0x03)
+#define SMI130_USER_INTR_MOTION_0_INTR_ANY_MOTION_DURN__REG \
+ (SMI130_USER_INTR_MOTION_0_ADDR)
+/**************************************************************/
+/**\name SLOW/NO MOTION DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+ /* Int_Motion_0 Description - Reg Addr --> 0x5f, Bit --> 2...7 */
+#define SMI130_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__POS (2)
+#define SMI130_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__LEN (6)
+#define SMI130_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__MSK (0xFC)
+#define SMI130_USER_INTR_MOTION_0_INTR_SLOW_NO_MOTION_DURN__REG \
+ (SMI130_USER_INTR_MOTION_0_ADDR)
+/**************************************************************/
+/**\name ANY MOTION THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_1 Description - Reg Addr --> (0x60), Bit --> 0...7 */
+#define SMI130_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__POS (0)
+#define SMI130_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__LEN (8)
+#define SMI130_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__MSK (0xFF)
+#define SMI130_USER_INTR_MOTION_1_INTR_ANY_MOTION_THRES__REG \
+ (SMI130_USER_INTR_MOTION_1_ADDR)
+/**************************************************************/
+/**\name SLOW/NO MOTION THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_2 Description - Reg Addr --> 0x61, Bit --> 0...7 */
+#define SMI130_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__POS (0)
+#define SMI130_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__LEN (8)
+#define SMI130_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__MSK (0xFF)
+#define SMI130_USER_INTR_MOTION_2_INTR_SLOW_NO_MOTION_THRES__REG \
+ (SMI130_USER_INTR_MOTION_2_ADDR)
+/**************************************************************/
+/**\name SLOW/NO MOTION SELECT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_3 Description - Reg Addr --> (0x62), Bit --> 0 */
+#define SMI130_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__POS (0)
+#define SMI130_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__LEN (1)
+#define SMI130_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__MSK (0x01)
+#define SMI130_USER_INTR_MOTION_3_INTR_SLOW_NO_MOTION_SELECT__REG \
+(SMI130_USER_INTR_MOTION_3_ADDR)
+/**************************************************************/
+/**\name SIGNIFICANT MOTION SELECT LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Motion_3 Description - Reg Addr --> (0x62), Bit --> 1 */
+#define SMI130_USER_INTR_SIGNIFICATION_MOTION_SELECT__POS (1)
+#define SMI130_USER_INTR_SIGNIFICATION_MOTION_SELECT__LEN (1)
+#define SMI130_USER_INTR_SIGNIFICATION_MOTION_SELECT__MSK (0x02)
+#define SMI130_USER_INTR_SIGNIFICATION_MOTION_SELECT__REG \
+ (SMI130_USER_INTR_MOTION_3_ADDR)
+
+/* Int_Motion_3 Description - Reg Addr --> (0x62), Bit --> 3..2 */
+#define SMI130_USER_INTR_SIGNIFICANT_MOTION_SKIP__POS (2)
+#define SMI130_USER_INTR_SIGNIFICANT_MOTION_SKIP__LEN (2)
+#define SMI130_USER_INTR_SIGNIFICANT_MOTION_SKIP__MSK (0x0C)
+#define SMI130_USER_INTR_SIGNIFICANT_MOTION_SKIP__REG \
+ (SMI130_USER_INTR_MOTION_3_ADDR)
+
+/* Int_Motion_3 Description - Reg Addr --> (0x62), Bit --> 5..4 */
+#define SMI130_USER_INTR_SIGNIFICANT_MOTION_PROOF__POS (4)
+#define SMI130_USER_INTR_SIGNIFICANT_MOTION_PROOF__LEN (2)
+#define SMI130_USER_INTR_SIGNIFICANT_MOTION_PROOF__MSK (0x30)
+#define SMI130_USER_INTR_SIGNIFICANT_MOTION_PROOF__REG \
+ (SMI130_USER_INTR_MOTION_3_ADDR)
+/**************************************************************/
+/**\name TAP DURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* INT_TAP_0 Description - Reg Addr --> (0x63), Bit --> 0..2*/
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_DURN__POS (0)
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_DURN__LEN (3)
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_DURN__MSK (0x07)
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_DURN__REG \
+(SMI130_USER_INTR_TAP_0_ADDR)
+/**************************************************************/
+/**\name TAP SHOCK LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Tap_0 Description - Reg Addr --> (0x63), Bit --> 6 */
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_SHOCK__POS (6)
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_SHOCK__LEN (1)
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_SHOCK__MSK (0x40)
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_SHOCK__REG (SMI130_USER_INTR_TAP_0_ADDR)
+/**************************************************************/
+/**\name TAP QUIET LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Tap_0 Description - Reg Addr --> (0x63), Bit --> 7 */
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_QUIET__POS (7)
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_QUIET__LEN (1)
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_QUIET__MSK (0x80)
+#define SMI130_USER_INTR_TAP_0_INTR_TAP_QUIET__REG (SMI130_USER_INTR_TAP_0_ADDR)
+/**************************************************************/
+/**\name TAP THRESHOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Tap_1 Description - Reg Addr --> (0x64), Bit --> 0...4 */
+#define SMI130_USER_INTR_TAP_1_INTR_TAP_THRES__POS (0)
+#define SMI130_USER_INTR_TAP_1_INTR_TAP_THRES__LEN (5)
+#define SMI130_USER_INTR_TAP_1_INTR_TAP_THRES__MSK (0x1F)
+#define SMI130_USER_INTR_TAP_1_INTR_TAP_THRES__REG (SMI130_USER_INTR_TAP_1_ADDR)
+/**************************************************************/
+/**\name ORIENT MODE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_0 Description - Reg Addr --> (0x65), Bit --> 0...1 */
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__POS (0)
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__LEN (2)
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__MSK (0x03)
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_MODE__REG \
+ (SMI130_USER_INTR_ORIENT_0_ADDR)
+/**************************************************************/
+/**\name ORIENT BLOCKING LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_0 Description - Reg Addr --> (0x65), Bit --> 2...3 */
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__POS (2)
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__LEN (2)
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__MSK (0x0C)
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_BLOCKING__REG \
+ (SMI130_USER_INTR_ORIENT_0_ADDR)
+/**************************************************************/
+/**\name ORIENT HYSTERESIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_0 Description - Reg Addr --> (0x65), Bit --> 4...7 */
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__POS (4)
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__LEN (4)
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__MSK (0xF0)
+#define SMI130_USER_INTR_ORIENT_0_INTR_ORIENT_HYST__REG \
+ (SMI130_USER_INTR_ORIENT_0_ADDR)
+/**************************************************************/
+/**\name ORIENT THETA LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_1 Description - Reg Addr --> 0x66, Bit --> 0...5 */
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__POS (0)
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__LEN (6)
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__MSK (0x3F)
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_THETA__REG \
+ (SMI130_USER_INTR_ORIENT_1_ADDR)
+/**************************************************************/
+/**\name ORIENT UD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_1 Description - Reg Addr --> 0x66, Bit --> 6 */
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__POS (6)
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__LEN (1)
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__MSK (0x40)
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_UD_ENABLE__REG \
+ (SMI130_USER_INTR_ORIENT_1_ADDR)
+/**************************************************************/
+/**\name ORIENT AXIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Orient_1 Description - Reg Addr --> 0x66, Bit --> 7 */
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__POS (7)
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__LEN (1)
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__MSK (0x80)
+#define SMI130_USER_INTR_ORIENT_1_INTR_ORIENT_AXES_EX__REG \
+ (SMI130_USER_INTR_ORIENT_1_ADDR)
+/**************************************************************/
+/**\name FLAT THETA LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Flat_0 Description - Reg Addr --> 0x67, Bit --> 0...5 */
+#define SMI130_USER_INTR_FLAT_0_INTR_FLAT_THETA__POS (0)
+#define SMI130_USER_INTR_FLAT_0_INTR_FLAT_THETA__LEN (6)
+#define SMI130_USER_INTR_FLAT_0_INTR_FLAT_THETA__MSK (0x3F)
+#define SMI130_USER_INTR_FLAT_0_INTR_FLAT_THETA__REG \
+ (SMI130_USER_INTR_FLAT_0_ADDR)
+/**************************************************************/
+/**\name FLAT HYSTERESIS LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Flat_1 Description - Reg Addr --> (0x68), Bit --> 0...3 */
+#define SMI130_USER_INTR_FLAT_1_INTR_FLAT_HYST__POS (0)
+#define SMI130_USER_INTR_FLAT_1_INTR_FLAT_HYST__LEN (4)
+#define SMI130_USER_INTR_FLAT_1_INTR_FLAT_HYST__MSK (0x0F)
+#define SMI130_USER_INTR_FLAT_1_INTR_FLAT_HYST__REG \
+(SMI130_USER_INTR_FLAT_1_ADDR)
+/**************************************************************/
+/**\name FLAT HOLD LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Int_Flat_1 Description - Reg Addr --> (0x68), Bit --> 4...5 */
+#define SMI130_USER_INTR_FLAT_1_INTR_FLAT_HOLD__POS (4)
+#define SMI130_USER_INTR_FLAT_1_INTR_FLAT_HOLD__LEN (2)
+#define SMI130_USER_INTR_FLAT_1_INTR_FLAT_HOLD__MSK (0x30)
+#define SMI130_USER_INTR_FLAT_1_INTR_FLAT_HOLD__REG \
+(SMI130_USER_INTR_FLAT_1_ADDR)
+/**************************************************************/
+/**\name FOC ACCEL XYZ LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Foc_Conf Description - Reg Addr --> (0x69), Bit --> 0...1 */
+#define SMI130_USER_FOC_ACCEL_Z__POS (0)
+#define SMI130_USER_FOC_ACCEL_Z__LEN (2)
+#define SMI130_USER_FOC_ACCEL_Z__MSK (0x03)
+#define SMI130_USER_FOC_ACCEL_Z__REG (SMI130_USER_FOC_CONFIG_ADDR)
+
+/* Foc_Conf Description - Reg Addr --> (0x69), Bit --> 2...3 */
+#define SMI130_USER_FOC_ACCEL_Y__POS (2)
+#define SMI130_USER_FOC_ACCEL_Y__LEN (2)
+#define SMI130_USER_FOC_ACCEL_Y__MSK (0x0C)
+#define SMI130_USER_FOC_ACCEL_Y__REG (SMI130_USER_FOC_CONFIG_ADDR)
+
+/* Foc_Conf Description - Reg Addr --> (0x69), Bit --> 4...5 */
+#define SMI130_USER_FOC_ACCEL_X__POS (4)
+#define SMI130_USER_FOC_ACCEL_X__LEN (2)
+#define SMI130_USER_FOC_ACCEL_X__MSK (0x30)
+#define SMI130_USER_FOC_ACCEL_X__REG (SMI130_USER_FOC_CONFIG_ADDR)
+/**************************************************************/
+/**\name FOC GYRO LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Foc_Conf Description - Reg Addr --> (0x69), Bit --> 6 */
+#define SMI130_USER_FOC_GYRO_ENABLE__POS (6)
+#define SMI130_USER_FOC_GYRO_ENABLE__LEN (1)
+#define SMI130_USER_FOC_GYRO_ENABLE__MSK (0x40)
+#define SMI130_USER_FOC_GYRO_ENABLE__REG \
+(SMI130_USER_FOC_CONFIG_ADDR)
+/**************************************************************/
+/**\name NVM PROGRAM LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* CONF Description - Reg Addr --> (0x6A), Bit --> 1 */
+#define SMI130_USER_CONFIG_NVM_PROG_ENABLE__POS (1)
+#define SMI130_USER_CONFIG_NVM_PROG_ENABLE__LEN (1)
+#define SMI130_USER_CONFIG_NVM_PROG_ENABLE__MSK (0x02)
+#define SMI130_USER_CONFIG_NVM_PROG_ENABLE__REG \
+(SMI130_USER_CONFIG_ADDR)
+
+/*IF_CONF Description - Reg Addr --> (0x6B), Bit --> 0 */
+
+#define SMI130_USER_IF_CONFIG_SPI3__POS (0)
+#define SMI130_USER_IF_CONFIG_SPI3__LEN (1)
+#define SMI130_USER_IF_CONFIG_SPI3__MSK (0x01)
+#define SMI130_USER_IF_CONFIG_SPI3__REG \
+(SMI130_USER_IF_CONFIG_ADDR)
+
+/*IF_CONF Description - Reg Addr --> (0x6B), Bit --> 5..4 */
+#define SMI130_USER_IF_CONFIG_IF_MODE__POS (4)
+#define SMI130_USER_IF_CONFIG_IF_MODE__LEN (2)
+#define SMI130_USER_IF_CONFIG_IF_MODE__MSK (0x30)
+#define SMI130_USER_IF_CONFIG_IF_MODE__REG \
+(SMI130_USER_IF_CONFIG_ADDR)
+/**************************************************************/
+/**\name GYRO SLEEP CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Pmu_Trigger Description - Reg Addr --> 0x6c, Bit --> 0...2 */
+#define SMI130_USER_GYRO_SLEEP_TRIGGER__POS (0)
+#define SMI130_USER_GYRO_SLEEP_TRIGGER__LEN (3)
+#define SMI130_USER_GYRO_SLEEP_TRIGGER__MSK (0x07)
+#define SMI130_USER_GYRO_SLEEP_TRIGGER__REG (SMI130_USER_PMU_TRIGGER_ADDR)
+
+/* Pmu_Trigger Description - Reg Addr --> 0x6c, Bit --> 3...4 */
+#define SMI130_USER_GYRO_WAKEUP_TRIGGER__POS (3)
+#define SMI130_USER_GYRO_WAKEUP_TRIGGER__LEN (2)
+#define SMI130_USER_GYRO_WAKEUP_TRIGGER__MSK (0x18)
+#define SMI130_USER_GYRO_WAKEUP_TRIGGER__REG (SMI130_USER_PMU_TRIGGER_ADDR)
+
+/* Pmu_Trigger Description - Reg Addr --> 0x6c, Bit --> 5 */
+#define SMI130_USER_GYRO_SLEEP_STATE__POS (5)
+#define SMI130_USER_GYRO_SLEEP_STATE__LEN (1)
+#define SMI130_USER_GYRO_SLEEP_STATE__MSK (0x20)
+#define SMI130_USER_GYRO_SLEEP_STATE__REG (SMI130_USER_PMU_TRIGGER_ADDR)
+
+/* Pmu_Trigger Description - Reg Addr --> 0x6c, Bit --> 6 */
+#define SMI130_USER_GYRO_WAKEUP_INTR__POS (6)
+#define SMI130_USER_GYRO_WAKEUP_INTR__LEN (1)
+#define SMI130_USER_GYRO_WAKEUP_INTR__MSK (0x40)
+#define SMI130_USER_GYRO_WAKEUP_INTR__REG (SMI130_USER_PMU_TRIGGER_ADDR)
+/**************************************************************/
+/**\name ACCEL SELF TEST LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Self_Test Description - Reg Addr --> 0x6d, Bit --> 0...1 */
+#define SMI130_USER_ACCEL_SELFTEST_AXIS__POS (0)
+#define SMI130_USER_ACCEL_SELFTEST_AXIS__LEN (2)
+#define SMI130_USER_ACCEL_SELFTEST_AXIS__MSK (0x03)
+#define SMI130_USER_ACCEL_SELFTEST_AXIS__REG (SMI130_USER_SELF_TEST_ADDR)
+
+/* Self_Test Description - Reg Addr --> 0x6d, Bit --> 2 */
+#define SMI130_USER_ACCEL_SELFTEST_SIGN__POS (2)
+#define SMI130_USER_ACCEL_SELFTEST_SIGN__LEN (1)
+#define SMI130_USER_ACCEL_SELFTEST_SIGN__MSK (0x04)
+#define SMI130_USER_ACCEL_SELFTEST_SIGN__REG (SMI130_USER_SELF_TEST_ADDR)
+
+/* Self_Test Description - Reg Addr --> 0x6d, Bit --> 3 */
+#define SMI130_USER_SELFTEST_AMP__POS (3)
+#define SMI130_USER_SELFTEST_AMP__LEN (1)
+#define SMI130_USER_SELFTEST_AMP__MSK (0x08)
+#define SMI130_USER_SELFTEST_AMP__REG (SMI130_USER_SELF_TEST_ADDR)
+/**************************************************************/
+/**\name GYRO SELF TEST LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Self_Test Description - Reg Addr --> 0x6d, Bit --> 4 */
+#define SMI130_USER_GYRO_SELFTEST_START__POS (4)
+#define SMI130_USER_GYRO_SELFTEST_START__LEN (1)
+#define SMI130_USER_GYRO_SELFTEST_START__MSK (0x10)
+#define SMI130_USER_GYRO_SELFTEST_START__REG \
+(SMI130_USER_SELF_TEST_ADDR)
+/**************************************************************/
+/**\name NV_CONFIG LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* NV_CONF Description - Reg Addr --> (0x70), Bit --> 0 */
+#define SMI130_USER_NV_CONFIG_SPI_ENABLE__POS (0)
+#define SMI130_USER_NV_CONFIG_SPI_ENABLE__LEN (1)
+#define SMI130_USER_NV_CONFIG_SPI_ENABLE__MSK (0x01)
+#define SMI130_USER_NV_CONFIG_SPI_ENABLE__REG (SMI130_USER_NV_CONFIG_ADDR)
+
+/*IF_CONF Description - Reg Addr --> (0x70), Bit --> 1 */
+#define SMI130_USER_IF_CONFIG_I2C_WDT_SELECT__POS (1)
+#define SMI130_USER_IF_CONFIG_I2C_WDT_SELECT__LEN (1)
+#define SMI130_USER_IF_CONFIG_I2C_WDT_SELECT__MSK (0x02)
+#define SMI130_USER_IF_CONFIG_I2C_WDT_SELECT__REG \
+(SMI130_USER_NV_CONFIG_ADDR)
+
+/*IF_CONF Description - Reg Addr --> (0x70), Bit --> 2 */
+#define SMI130_USER_IF_CONFIG_I2C_WDT_ENABLE__POS (2)
+#define SMI130_USER_IF_CONFIG_I2C_WDT_ENABLE__LEN (1)
+#define SMI130_USER_IF_CONFIG_I2C_WDT_ENABLE__MSK (0x04)
+#define SMI130_USER_IF_CONFIG_I2C_WDT_ENABLE__REG \
+(SMI130_USER_NV_CONFIG_ADDR)
+
+/* NV_CONF Description - Reg Addr --> (0x70), Bit --> 3 */
+#define SMI130_USER_NV_CONFIG_SPARE0__POS (3)
+#define SMI130_USER_NV_CONFIG_SPARE0__LEN (1)
+#define SMI130_USER_NV_CONFIG_SPARE0__MSK (0x08)
+#define SMI130_USER_NV_CONFIG_SPARE0__REG (SMI130_USER_NV_CONFIG_ADDR)
+
+/* NV_CONF Description - Reg Addr --> (0x70), Bit --> 4...7 */
+#define SMI130_USER_NV_CONFIG_NVM_COUNTER__POS (4)
+#define SMI130_USER_NV_CONFIG_NVM_COUNTER__LEN (4)
+#define SMI130_USER_NV_CONFIG_NVM_COUNTER__MSK (0xF0)
+#define SMI130_USER_NV_CONFIG_NVM_COUNTER__REG (SMI130_USER_NV_CONFIG_ADDR)
+/**************************************************************/
+/**\name ACCEL MANUAL OFFSET LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Offset_0 Description - Reg Addr --> (0x71), Bit --> 0...7 */
+#define SMI130_USER_OFFSET_0_ACCEL_OFF_X__POS (0)
+#define SMI130_USER_OFFSET_0_ACCEL_OFF_X__LEN (8)
+#define SMI130_USER_OFFSET_0_ACCEL_OFF_X__MSK (0xFF)
+#define SMI130_USER_OFFSET_0_ACCEL_OFF_X__REG (SMI130_USER_OFFSET_0_ADDR)
+
+/* Offset_1 Description - Reg Addr --> 0x72, Bit --> 0...7 */
+#define SMI130_USER_OFFSET_1_ACCEL_OFF_Y__POS (0)
+#define SMI130_USER_OFFSET_1_ACCEL_OFF_Y__LEN (8)
+#define SMI130_USER_OFFSET_1_ACCEL_OFF_Y__MSK (0xFF)
+#define SMI130_USER_OFFSET_1_ACCEL_OFF_Y__REG (SMI130_USER_OFFSET_1_ADDR)
+
+/* Offset_2 Description - Reg Addr --> 0x73, Bit --> 0...7 */
+#define SMI130_USER_OFFSET_2_ACCEL_OFF_Z__POS (0)
+#define SMI130_USER_OFFSET_2_ACCEL_OFF_Z__LEN (8)
+#define SMI130_USER_OFFSET_2_ACCEL_OFF_Z__MSK (0xFF)
+#define SMI130_USER_OFFSET_2_ACCEL_OFF_Z__REG (SMI130_USER_OFFSET_2_ADDR)
+/**************************************************************/
+/**\name GYRO MANUAL OFFSET LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Offset_3 Description - Reg Addr --> 0x74, Bit --> 0...7 */
+#define SMI130_USER_OFFSET_3_GYRO_OFF_X__POS (0)
+#define SMI130_USER_OFFSET_3_GYRO_OFF_X__LEN (8)
+#define SMI130_USER_OFFSET_3_GYRO_OFF_X__MSK (0xFF)
+#define SMI130_USER_OFFSET_3_GYRO_OFF_X__REG (SMI130_USER_OFFSET_3_ADDR)
+
+/* Offset_4 Description - Reg Addr --> 0x75, Bit --> 0...7 */
+#define SMI130_USER_OFFSET_4_GYRO_OFF_Y__POS (0)
+#define SMI130_USER_OFFSET_4_GYRO_OFF_Y__LEN (8)
+#define SMI130_USER_OFFSET_4_GYRO_OFF_Y__MSK (0xFF)
+#define SMI130_USER_OFFSET_4_GYRO_OFF_Y__REG (SMI130_USER_OFFSET_4_ADDR)
+
+/* Offset_5 Description - Reg Addr --> 0x76, Bit --> 0...7 */
+#define SMI130_USER_OFFSET_5_GYRO_OFF_Z__POS (0)
+#define SMI130_USER_OFFSET_5_GYRO_OFF_Z__LEN (8)
+#define SMI130_USER_OFFSET_5_GYRO_OFF_Z__MSK (0xFF)
+#define SMI130_USER_OFFSET_5_GYRO_OFF_Z__REG (SMI130_USER_OFFSET_5_ADDR)
+
+
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 0..1 */
+#define SMI130_USER_OFFSET_6_GYRO_OFF_X__POS (0)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_X__LEN (2)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_X__MSK (0x03)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_X__REG (SMI130_USER_OFFSET_6_ADDR)
+
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 2...3 */
+#define SMI130_USER_OFFSET_6_GYRO_OFF_Y__POS (2)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_Y__LEN (2)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_Y__MSK (0x0C)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_Y__REG (SMI130_USER_OFFSET_6_ADDR)
+
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 4...5 */
+#define SMI130_USER_OFFSET_6_GYRO_OFF_Z__POS (4)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_Z__LEN (2)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_Z__MSK (0x30)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_Z__REG (SMI130_USER_OFFSET_6_ADDR)
+/**************************************************************/
+/**\name ACCEL OFFSET ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 6 */
+#define SMI130_USER_OFFSET_6_ACCEL_OFF_ENABLE__POS (6)
+#define SMI130_USER_OFFSET_6_ACCEL_OFF_ENABLE__LEN (1)
+#define SMI130_USER_OFFSET_6_ACCEL_OFF_ENABLE__MSK (0x40)
+#define SMI130_USER_OFFSET_6_ACCEL_OFF_ENABLE__REG \
+(SMI130_USER_OFFSET_6_ADDR)
+/**************************************************************/
+/**\name GYRO OFFSET ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Offset_6 Description - Reg Addr --> 0x77, Bit --> 7 */
+#define SMI130_USER_OFFSET_6_GYRO_OFF_EN__POS (7)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_EN__LEN (1)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_EN__MSK (0x80)
+#define SMI130_USER_OFFSET_6_GYRO_OFF_EN__REG (SMI130_USER_OFFSET_6_ADDR)
+/**************************************************************/
+/**\name STEP COUNTER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* STEP_CNT_0 Description - Reg Addr --> 0x78, Bit --> 0 to 7 */
+#define SMI130_USER_STEP_COUNT_LSB__POS (0)
+#define SMI130_USER_STEP_COUNT_LSB__LEN (7)
+#define SMI130_USER_STEP_COUNT_LSB__MSK (0xFF)
+#define SMI130_USER_STEP_COUNT_LSB__REG (SMI130_USER_STEP_COUNT_0_ADDR)
+
+/* STEP_CNT_1 Description - Reg Addr --> 0x79, Bit --> 0 to 7 */
+#define SMI130_USER_STEP_COUNT_MSB__POS (0)
+#define SMI130_USER_STEP_COUNT_MSB__LEN (7)
+#define SMI130_USER_STEP_COUNT_MSB__MSK (0xFF)
+#define SMI130_USER_STEP_COUNT_MSB__REG (SMI130_USER_STEP_COUNT_1_ADDR)
+/**************************************************************/
+/**\name STEP COUNTER CONFIGURATION LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* STEP_CONFIG_0 Description - Reg Addr --> 0x7A, Bit --> 0 to 7 */
+#define SMI130_USER_STEP_CONFIG_ZERO__POS (0)
+#define SMI130_USER_STEP_CONFIG_ZERO__LEN (7)
+#define SMI130_USER_STEP_CONFIG_ZERO__MSK (0xFF)
+#define SMI130_USER_STEP_CONFIG_ZERO__REG \
+(SMI130_USER_STEP_CONFIG_0_ADDR)
+
+
+/* STEP_CONFIG_1 Description - Reg Addr --> 0x7B, Bit --> 0 to 2 and
+4 to 7 */
+#define SMI130_USER_STEP_CONFIG_ONE_CNF1__POS (0)
+#define SMI130_USER_STEP_CONFIG_ONE_CNF1__LEN (3)
+#define SMI130_USER_STEP_CONFIG_ONE_CNF1__MSK (0x07)
+#define SMI130_USER_STEP_CONFIG_ONE_CNF1__REG \
+(SMI130_USER_STEP_CONFIG_1_ADDR)
+
+#define SMI130_USER_STEP_CONFIG_ONE_CNF2__POS (4)
+#define SMI130_USER_STEP_CONFIG_ONE_CNF2__LEN (4)
+#define SMI130_USER_STEP_CONFIG_ONE_CNF2__MSK (0xF0)
+#define SMI130_USER_STEP_CONFIG_ONE_CNF2__REG \
+(SMI130_USER_STEP_CONFIG_1_ADDR)
+/**************************************************************/
+/**\name STEP COUNTER ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* STEP_CONFIG_1 Description - Reg Addr --> 0x7B, Bit --> 0 to 2 */
+#define SMI130_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__POS (3)
+#define SMI130_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__LEN (1)
+#define SMI130_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__MSK (0x08)
+#define SMI130_USER_STEP_CONFIG_1_STEP_COUNT_ENABLE__REG \
+(SMI130_USER_STEP_CONFIG_1_ADDR)
+
+/* USER REGISTERS DEFINITION END */
+/**************************************************************************/
+/* CMD REGISTERS DEFINITION START */
+/**************************************************************/
+/**\name COMMAND REGISTER LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Command description address - Reg Addr --> 0x7E, Bit --> 0....7 */
+#define SMI130_CMD_COMMANDS__POS (0)
+#define SMI130_CMD_COMMANDS__LEN (8)
+#define SMI130_CMD_COMMANDS__MSK (0xFF)
+#define SMI130_CMD_COMMANDS__REG (SMI130_CMD_COMMANDS_ADDR)
+/**************************************************************/
+/**\name PAGE ENABLE LENGTH, POSITION AND MASK*/
+/**************************************************************/
+/* Target page address - Reg Addr --> 0x7F, Bit --> 4....5 */
+#define SMI130_CMD_TARGET_PAGE__POS (4)
+#define SMI130_CMD_TARGET_PAGE__LEN (2)
+#define SMI130_CMD_TARGET_PAGE__MSK (0x30)
+#define SMI130_CMD_TARGET_PAGE__REG (SMI130_CMD_EXT_MODE_ADDR)
+
+/* Target page address - Reg Addr --> 0x7F, Bit --> 4....5 */
+#define SMI130_CMD_PAGING_EN__POS (7)
+#define SMI130_CMD_PAGING_EN__LEN (1)
+#define SMI130_CMD_PAGING_EN__MSK (0x80)
+#define SMI130_CMD_PAGING_EN__REG (SMI130_CMD_EXT_MODE_ADDR)
+
+/* Target page address - Reg Addr --> 0x7F, Bit --> 4....5 */
+#define SMI130_COM_C_TRIM_FIVE__POS (0)
+#define SMI130_COM_C_TRIM_FIVE__LEN (8)
+#define SMI130_COM_C_TRIM_FIVE__MSK (0xFF)
+#define SMI130_COM_C_TRIM_FIVE__REG (SMI130_COM_C_TRIM_FIVE_ADDR)
+
+/**************************************************************************/
+/* CMD REGISTERS DEFINITION END */
+
+/**************************************************/
+/**\name FIFO FRAME COUNT DEFINITION */
+/*************************************************/
+#define FIFO_FRAME (1024)
+#define FIFO_CONFIG_CHECK1 (0x00)
+#define FIFO_CONFIG_CHECK2 (0x80)
+/**************************************************/
+/**\name MAG SENSOR SELECT */
+/*************************************************/
+#define BST_BMM (0)
+#define BST_AKM (1)
+#define SMI130_YAS537_I2C_ADDRESS (0x2E)
+/**************************************************/
+/**\name ACCEL RANGE */
+/*************************************************/
+#define SMI130_ACCEL_RANGE_2G (0X03)
+#define SMI130_ACCEL_RANGE_4G (0X05)
+#define SMI130_ACCEL_RANGE_8G (0X08)
+#define SMI130_ACCEL_RANGE_16G (0X0C)
+/**************************************************/
+/**\name ACCEL ODR */
+/*************************************************/
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_RESERVED (0x00)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_0_78HZ (0x01)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_1_56HZ (0x02)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_3_12HZ (0x03)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_6_25HZ (0x04)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_12_5HZ (0x05)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_25HZ (0x06)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_50HZ (0x07)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_100HZ (0x08)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_200HZ (0x09)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_400HZ (0x0A)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_800HZ (0x0B)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_1600HZ (0x0C)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_RESERVED0 (0x0D)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_RESERVED1 (0x0E)
+#define SMI130_ACCEL_OUTPUT_DATA_RATE_RESERVED2 (0x0F)
+/**************************************************/
+/**\name ACCEL BANDWIDTH PARAMETER */
+/*************************************************/
+#define SMI130_ACCEL_OSR4_AVG1 (0x00)
+#define SMI130_ACCEL_OSR2_AVG2 (0x01)
+#define SMI130_ACCEL_NORMAL_AVG4 (0x02)
+#define SMI130_ACCEL_CIC_AVG8 (0x03)
+#define SMI130_ACCEL_RES_AVG16 (0x04)
+#define SMI130_ACCEL_RES_AVG32 (0x05)
+#define SMI130_ACCEL_RES_AVG64 (0x06)
+#define SMI130_ACCEL_RES_AVG128 (0x07)
+/**************************************************/
+/**\name GYRO ODR */
+/*************************************************/
+#define SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED (0x00)
+#define SMI130_GYRO_OUTPUT_DATA_RATE_25HZ (0x06)
+#define SMI130_GYRO_OUTPUT_DATA_RATE_50HZ (0x07)
+#define SMI130_GYRO_OUTPUT_DATA_RATE_100HZ (0x08)
+#define SMI130_GYRO_OUTPUT_DATA_RATE_200HZ (0x09)
+#define SMI130_GYRO_OUTPUT_DATA_RATE_400HZ (0x0A)
+#define SMI130_GYRO_OUTPUT_DATA_RATE_800HZ (0x0B)
+#define SMI130_GYRO_OUTPUT_DATA_RATE_1600HZ (0x0C)
+#define SMI130_GYRO_OUTPUT_DATA_RATE_3200HZ (0x0D)
+/**************************************************/
+/**\name GYRO BANDWIDTH PARAMETER */
+/*************************************************/
+#define SMI130_GYRO_OSR4_MODE (0x00)
+#define SMI130_GYRO_OSR2_MODE (0x01)
+#define SMI130_GYRO_NORMAL_MODE (0x02)
+#define SMI130_GYRO_CIC_MODE (0x03)
+/**************************************************/
+/**\name GYROSCOPE RANGE PARAMETER */
+/*************************************************/
+#define SMI130_GYRO_RANGE_2000_DEG_SEC (0x00)
+#define SMI130_GYRO_RANGE_1000_DEG_SEC (0x01)
+#define SMI130_GYRO_RANGE_500_DEG_SEC (0x02)
+#define SMI130_GYRO_RANGE_250_DEG_SEC (0x03)
+#define SMI130_GYRO_RANGE_125_DEG_SEC (0x04)
+/**************************************************/
+/**\name MAG ODR */
+/*************************************************/
+#define SMI130_MAG_OUTPUT_DATA_RATE_RESERVED (0x00)
+#define SMI130_MAG_OUTPUT_DATA_RATE_0_78HZ (0x01)
+#define SMI130_MAG_OUTPUT_DATA_RATE_1_56HZ (0x02)
+#define SMI130_MAG_OUTPUT_DATA_RATE_3_12HZ (0x03)
+#define SMI130_MAG_OUTPUT_DATA_RATE_6_25HZ (0x04)
+#define SMI130_MAG_OUTPUT_DATA_RATE_12_5HZ (0x05)
+#define SMI130_MAG_OUTPUT_DATA_RATE_25HZ (0x06)
+#define SMI130_MAG_OUTPUT_DATA_RATE_50HZ (0x07)
+#define SMI130_MAG_OUTPUT_DATA_RATE_100HZ (0x08)
+#define SMI130_MAG_OUTPUT_DATA_RATE_200HZ (0x09)
+#define SMI130_MAG_OUTPUT_DATA_RATE_400HZ (0x0A)
+#define SMI130_MAG_OUTPUT_DATA_RATE_800HZ (0x0B)
+#define SMI130_MAG_OUTPUT_DATA_RATE_1600HZ (0x0C)
+#define SMI130_MAG_OUTPUT_DATA_RATE_RESERVED0 (0x0D)
+#define SMI130_MAG_OUTPUT_DATA_RATE_RESERVED1 (0x0E)
+#define SMI130_MAG_OUTPUT_DATA_RATE_RESERVED2 (0x0F)
+
+/**************************************************/
+/**\name ENABLE/DISABLE SELECTIONS */
+/*************************************************/
+
+/* Enable accel and gyro offset */
+#define ACCEL_OFFSET_ENABLE (0x01)
+#define GYRO_OFFSET_ENABLE (0x01)
+
+/* command register definition */
+#define START_FOC_ACCEL_GYRO (0X03)
+
+ /* INT ENABLE 1 */
+#define SMI130_ANY_MOTION_X_ENABLE (0)
+#define SMI130_ANY_MOTION_Y_ENABLE (1)
+#define SMI130_ANY_MOTION_Z_ENABLE (2)
+#define SMI130_DOUBLE_TAP_ENABLE (4)
+#define SMI130_SINGLE_TAP_ENABLE (5)
+#define SMI130_ORIENT_ENABLE (6)
+#define SMI130_FLAT_ENABLE (7)
+
+/* INT ENABLE 1 */
+#define SMI130_HIGH_G_X_ENABLE (0)
+#define SMI130_HIGH_G_Y_ENABLE (1)
+#define SMI130_HIGH_G_Z_ENABLE (2)
+#define SMI130_LOW_G_ENABLE (3)
+#define SMI130_DATA_RDY_ENABLE (4)
+#define SMI130_FIFO_FULL_ENABLE (5)
+#define SMI130_FIFO_WM_ENABLE (6)
+
+/* INT ENABLE 2 */
+#define SMI130_NOMOTION_X_ENABLE (0)
+#define SMI130_NOMOTION_Y_ENABLE (1)
+#define SMI130_NOMOTION_Z_ENABLE (2)
+#define SMI130_STEP_DETECTOR_EN (3)
+
+/* FOC axis selection for accel*/
+#define FOC_X_AXIS (0)
+#define FOC_Y_AXIS (1)
+#define FOC_Z_AXIS (2)
+
+/* IN OUT CONTROL */
+#define SMI130_INTR1_EDGE_CTRL (0)
+#define SMI130_INTR2_EDGE_CTRL (1)
+#define SMI130_INTR1_LEVEL (0)
+#define SMI130_INTR2_LEVEL (1)
+#define SMI130_INTR1_OUTPUT_TYPE (0)
+#define SMI130_INTR2_OUTPUT_TYPE (1)
+#define SMI130_INTR1_OUTPUT_ENABLE (0)
+#define SMI130_INTR2_OUTPUT_ENABLE (1)
+
+#define SMI130_INTR1_INPUT_ENABLE (0)
+#define SMI130_INTR2_INPUT_ENABLE (1)
+
+/* INTERRUPT MAPS */
+#define SMI130_INTR1_MAP_LOW_G (0)
+#define SMI130_INTR2_MAP_LOW_G (1)
+#define SMI130_INTR1_MAP_HIGH_G (0)
+#define SMI130_INTR2_MAP_HIGH_G (1)
+#define SMI130_INTR1_MAP_ANY_MOTION (0)
+#define SMI130_INTR2_MAP_ANY_MOTION (1)
+#define SMI130_INTR1_MAP_NOMO (0)
+#define SMI130_INTR2_MAP_NOMO (1)
+#define SMI130_INTR1_MAP_DOUBLE_TAP (0)
+#define SMI130_INTR2_MAP_DOUBLE_TAP (1)
+#define SMI130_INTR1_MAP_SINGLE_TAP (0)
+#define SMI130_INTR2_MAP_SINGLE_TAP (1)
+#define SMI130_INTR1_MAP_ORIENT (0)
+#define SMI130_INTR2_MAP_ORIENT (1)
+#define SMI130_INTR1_MAP_FLAT (0)
+#define SMI130_INTR2_MAP_FLAT (1)
+#define SMI130_INTR1_MAP_DATA_RDY (0)
+#define SMI130_INTR2_MAP_DATA_RDY (1)
+#define SMI130_INTR1_MAP_FIFO_WM (0)
+#define SMI130_INTR2_MAP_FIFO_WM (1)
+#define SMI130_INTR1_MAP_FIFO_FULL (0)
+#define SMI130_INTR2_MAP_FIFO_FULL (1)
+#define SMI130_INTR1_MAP_PMUTRIG (0)
+#define SMI130_INTR2_MAP_PMUTRIG (1)
+
+/* Interrupt mapping*/
+#define SMI130_MAP_INTR1 (0)
+#define SMI130_MAP_INTR2 (1)
+/**************************************************/
+/**\name TAP DURATION */
+/*************************************************/
+#define SMI130_TAP_DURN_50MS (0x00)
+#define SMI130_TAP_DURN_100MS (0x01)
+#define SMI130_TAP_DURN_150MS (0x02)
+#define SMI130_TAP_DURN_200MS (0x03)
+#define SMI130_TAP_DURN_250MS (0x04)
+#define SMI130_TAP_DURN_375MS (0x05)
+#define SMI130_TAP_DURN_500MS (0x06)
+#define SMI130_TAP_DURN_700MS (0x07)
+/**************************************************/
+/**\name TAP SHOCK */
+/*************************************************/
+#define SMI130_TAP_SHOCK_50MS (0x00)
+#define SMI130_TAP_SHOCK_75MS (0x01)
+/**************************************************/
+/**\name TAP QUIET */
+/*************************************************/
+#define SMI130_TAP_QUIET_30MS (0x00)
+#define SMI130_TAP_QUIET_20MS (0x01)
+/**************************************************/
+/**\name STEP DETECTION SELECTION MODES */
+/*************************************************/
+#define SMI130_STEP_NORMAL_MODE (0)
+#define SMI130_STEP_SENSITIVE_MODE (1)
+#define SMI130_STEP_ROBUST_MODE (2)
+/**************************************************/
+/**\name STEP CONFIGURATION SELECT MODE */
+/*************************************************/
+#define STEP_CONFIG_NORMAL (0X315)
+#define STEP_CONFIG_SENSITIVE (0X2D)
+#define STEP_CONFIG_ROBUST (0X71D)
+/**************************************************/
+/**\name BMM150 TRIM DATA DEFINITIONS */
+/*************************************************/
+#define SMI130_MAG_DIG_X1 (0x5D)
+#define SMI130_MAG_DIG_Y1 (0x5E)
+#define SMI130_MAG_DIG_Z4_LSB (0x62)
+#define SMI130_MAG_DIG_Z4_MSB (0x63)
+#define SMI130_MAG_DIG_X2 (0x64)
+#define SMI130_MAG_DIG_Y2 (0x65)
+#define SMI130_MAG_DIG_Z2_LSB (0x68)
+#define SMI130_MAG_DIG_Z2_MSB (0x69)
+#define SMI130_MAG_DIG_Z1_LSB (0x6A)
+#define SMI130_MAG_DIG_Z1_MSB (0x6B)
+#define SMI130_MAG_DIG_XYZ1_LSB (0x6C)
+#define SMI130_MAG_DIG_XYZ1_MSB (0x6D)
+#define SMI130_MAG_DIG_Z3_LSB (0x6E)
+#define SMI130_MAG_DIG_Z3_MSB (0x6F)
+#define SMI130_MAG_DIG_XY2 (0x70)
+#define SMI130_MAG_DIG_XY1 (0x71)
+/**************************************************/
+/**\name BMM150 PRE-SET MODE DEFINITIONS */
+/*************************************************/
+#define SMI130_MAG_PRESETMODE_LOWPOWER (1)
+#define SMI130_MAG_PRESETMODE_REGULAR (2)
+#define SMI130_MAG_PRESETMODE_HIGHACCURACY (3)
+#define SMI130_MAG_PRESETMODE_ENHANCED (4)
+/**************************************************/
+/**\name BMM150 PRESET MODES - DATA RATES */
+/*************************************************/
+#define SMI130_MAG_LOWPOWER_DR (0x02)
+#define SMI130_MAG_REGULAR_DR (0x02)
+#define SMI130_MAG_HIGHACCURACY_DR (0x2A)
+#define SMI130_MAG_ENHANCED_DR (0x02)
+/**************************************************/
+/**\name BMM150 PRESET MODES - REPETITIONS-XY RATES */
+/*************************************************/
+#define SMI130_MAG_LOWPOWER_REPXY (1)
+#define SMI130_MAG_REGULAR_REPXY (4)
+#define SMI130_MAG_HIGHACCURACY_REPXY (23)
+#define SMI130_MAG_ENHANCED_REPXY (7)
+/**************************************************/
+/**\name BMM150 PRESET MODES - REPETITIONS-Z RATES */
+/*************************************************/
+#define SMI130_MAG_LOWPOWER_REPZ (2)
+#define SMI130_MAG_REGULAR_REPZ (14)
+#define SMI130_MAG_HIGHACCURACY_REPZ (82)
+#define SMI130_MAG_ENHANCED_REPZ (26)
+#define SMI130_MAG_NOAMRL_SWITCH_TIMES (5)
+#define MAG_INTERFACE_PMU_ENABLE (1)
+#define MAG_INTERFACE_PMU_DISABLE (0)
+/**************************************************/
+/**\name USED FOR MAG OVERFLOW CHECK FOR BMM150 */
+/*************************************************/
+#define SMI130_MAG_OVERFLOW_OUTPUT ((s16)-32768)
+#define SMI130_MAG_OVERFLOW_OUTPUT_S32 ((s32)(-2147483647-1))
+#define SMI130_MAG_NEGATIVE_SATURATION_Z ((s16)-32767)
+#define SMI130_MAG_POSITIVE_SATURATION_Z ((u16)32767)
+#define SMI130_MAG_FLIP_OVERFLOW_ADCVAL ((s16)-4096)
+#define SMI130_MAG_HALL_OVERFLOW_ADCVAL ((s16)-16384)
+/**************************************************/
+/**\name BMM150 REGISTER DEFINITION */
+/*************************************************/
+#define SMI130_BMM150_CHIP_ID (0x40)
+#define SMI130_BMM150_POWE_CONTROL_REG (0x4B)
+#define SMI130_BMM150_POWE_MODE_REG (0x4C)
+#define SMI130_BMM150_DATA_REG (0x42)
+#define SMI130_BMM150_XY_REP (0x51)
+#define SMI130_BMM150_Z_REP (0x52)
+/**************************************************/
+/**\name AKM COMPENSATING DATA REGISTERS */
+/*************************************************/
+#define SMI130_BST_AKM_ASAX (0x60)
+#define SMI130_BST_AKM_ASAY (0x61)
+#define SMI130_BST_AKM_ASAZ (0x62)
+/**************************************************/
+/**\name AKM POWER MODE SELECTION */
+/*************************************************/
+#define AKM_POWER_DOWN_MODE (0)
+#define AKM_SINGLE_MEAS_MODE (1)
+#define FUSE_ROM_MODE (2)
+/**************************************************/
+/**\name SECONDARY_MAG POWER MODE SELECTION */
+/*************************************************/
+#define SMI130_MAG_FORCE_MODE (0)
+#define SMI130_MAG_SUSPEND_MODE (1)
+/**************************************************/
+/**\name MAG POWER MODE SELECTION */
+/*************************************************/
+#define FORCE_MODE (0)
+#define SUSPEND_MODE (1)
+#define NORMAL_MODE (2)
+#define MAG_SUSPEND_MODE (1)
+/**************************************************/
+/**\name FIFO CONFIGURATIONS */
+/*************************************************/
+#define FIFO_HEADER_ENABLE (0x01)
+#define FIFO_MAG_ENABLE (0x01)
+#define FIFO_ACCEL_ENABLE (0x01)
+#define FIFO_GYRO_ENABLE (0x01)
+#define FIFO_TIME_ENABLE (0x01)
+#define FIFO_STOPONFULL_ENABLE (0x01)
+#define FIFO_WM_INTERRUPT_ENABLE (0x01)
+#define SMI130_FIFO_INDEX_LENGTH (1)
+#define SMI130_FIFO_TAG_INTR_MASK (0xFC)
+
+/**************************************************/
+/**\name ACCEL POWER MODE */
+/*************************************************/
+#define ACCEL_MODE_NORMAL (0x11)
+#define ACCEL_LOWPOWER (0X12)
+#define ACCEL_SUSPEND (0X10)
+/**************************************************/
+/**\name GYRO POWER MODE */
+/*************************************************/
+#define GYRO_MODE_SUSPEND (0x14)
+#define GYRO_MODE_NORMAL (0x15)
+#define GYRO_MODE_FASTSTARTUP (0x17)
+/**************************************************/
+/**\name MAG POWER MODE */
+/*************************************************/
+#define MAG_MODE_SUSPEND (0x18)
+#define MAG_MODE_NORMAL (0x19)
+#define MAG_MODE_LOWPOWER (0x1A)
+/**************************************************/
+/**\name ENABLE/DISABLE BIT VALUES */
+/*************************************************/
+#define SMI130_ENABLE (0x01)
+#define SMI130_DISABLE (0x00)
+/**************************************************/
+/**\name INTERRUPT EDGE TRIGGER ENABLE */
+/*************************************************/
+#define SMI130_EDGE (0x01)
+#define SMI130_LEVEL (0x00)
+/**************************************************/
+/**\name INTERRUPT LEVEL ENABLE */
+/*************************************************/
+#define SMI130_LEVEL_LOW (0x00)
+#define SMI130_LEVEL_HIGH (0x01)
+/**************************************************/
+/**\name INTERRUPT OUTPUT ENABLE */
+/*************************************************/
+#define SMI130_OPEN_DRAIN (0x01)
+#define SMI130_PUSH_PULL (0x00)
+
+/* interrupt output enable*/
+#define SMI130_INPUT (0x01)
+#define SMI130_OUTPUT (0x00)
+
+/**************************************************/
+/**\name INTERRUPT TAP SOURCE ENABLE */
+/*************************************************/
+#define FILTER_DATA (0x00)
+#define UNFILTER_DATA (0x01)
+/**************************************************/
+/**\name SLOW MOTION/ NO MOTION SELECT */
+/*************************************************/
+#define SLOW_MOTION (0x00)
+#define NO_MOTION (0x01)
+/**************************************************/
+/**\name SIGNIFICANT MOTION SELECTION */
+/*************************************************/
+#define ANY_MOTION (0x00)
+#define SIGNIFICANT_MOTION (0x01)
+/**************************************************/
+/**\name LATCH DURATION */
+/*************************************************/
+#define SMI130_LATCH_DUR_NONE (0x00)
+#define SMI130_LATCH_DUR_312_5_MICRO_SEC (0x01)
+#define SMI130_LATCH_DUR_625_MICRO_SEC (0x02)
+#define SMI130_LATCH_DUR_1_25_MILLI_SEC (0x03)
+#define SMI130_LATCH_DUR_2_5_MILLI_SEC (0x04)
+#define SMI130_LATCH_DUR_5_MILLI_SEC (0x05)
+#define SMI130_LATCH_DUR_10_MILLI_SEC (0x06)
+#define SMI130_LATCH_DUR_20_MILLI_SEC (0x07)
+#define SMI130_LATCH_DUR_40_MILLI_SEC (0x08)
+#define SMI130_LATCH_DUR_80_MILLI_SEC (0x09)
+#define SMI130_LATCH_DUR_160_MILLI_SEC (0x0A)
+#define SMI130_LATCH_DUR_320_MILLI_SEC (0x0B)
+#define SMI130_LATCH_DUR_640_MILLI_SEC (0x0C)
+#define SMI130_LATCH_DUR_1_28_SEC (0x0D)
+#define SMI130_LATCH_DUR_2_56_SEC (0x0E)
+#define SMI130_LATCHED (0x0F)
+/**************************************************/
+/**\name GYRO OFFSET MASK DEFINITION */
+/*************************************************/
+#define SMI130_GYRO_MANUAL_OFFSET_0_7 (0x00FF)
+#define SMI130_GYRO_MANUAL_OFFSET_8_9 (0x0300)
+/**************************************************/
+/**\name STEP CONFIGURATION MASK DEFINITION */
+/*************************************************/
+#define SMI130_STEP_CONFIG_0_7 (0x00FF)
+#define SMI130_STEP_CONFIG_8_10 (0x0700)
+#define SMI130_STEP_CONFIG_11_14 (0xF000)
+/**************************************************/
+/**\name DEFINITION USED FOR DIFFERENT WRITE */
+/*************************************************/
+#define SMI130_WRITE_TARGET_PAGE0 (0x00)
+#define SMI130_WRITE_TARGET_PAGE1 (0x01)
+#define SMI130_WRITE_ENABLE_PAGE1 (0x01)
+#define SMI130_MANUAL_DISABLE (0x00)
+#define SMI130_MANUAL_ENABLE (0x01)
+#define SMI130_YAS_DISABLE_RCOIL (0x00)
+#define SMI130_ENABLE_MAG_IF_MODE (0x02)
+#define SMI130_ENABLE_ANY_MOTION_INTR1 (0x04)
+#define SMI130_ENABLE_ANY_MOTION_INTR2 (0x04)
+#define SMI130_MAG_DATA_READ_REG (0x04)
+#define SMI130_BMM_POWER_MODE_REG (0x06)
+#define SMI130_ENABLE_ANY_MOTION_AXIS (0x07)
+#define SMI130_ENABLE_LOW_G (0x08)
+#define SMI130_YAS532_ACQ_START (0x11)
+#define SMI130_YAS_DEVICE_ID_REG (0x80)
+#define SMI130_FIFO_GYRO_ENABLE (0x80)
+#define SMI130_SIG_MOTION_INTR_ENABLE (0x01)
+#define SMI130_STEP_DETECT_INTR_ENABLE (0x01)
+#define SMI130_LOW_G_INTR_STAT (0x01)
+#define SMI130_PULL_UP_DATA (0x30)
+#define SMI130_FIFO_M_G_A_ENABLE (0xE0)
+#define SMI130_FIFO_M_G_ENABLE (0xA0)
+#define SMI130_FIFO_M_A_ENABLE (0x60)
+#define SMI130_FIFO_G_A_ENABLE (0xC0)
+#define SMI130_FIFO_A_ENABLE (0x40)
+#define SMI130_FIFO_M_ENABLE (0x20)
+/**************************************************/
+/**\name MAG INIT DEFINITION */
+/*************************************************/
+#define SMI130_COMMAND_REG_ONE (0x37)
+#define SMI130_COMMAND_REG_TWO (0x9A)
+#define SMI130_COMMAND_REG_THREE (0xC0)
+#define RESET_STEP_COUNTER (0xB2)
+/**************************************************/
+/**\name BIT SLICE GET AND SET FUNCTIONS */
+/*************************************************/
+#define SMI130_GET_BITSLICE(regvar, bitname)\
+ ((regvar & bitname##__MSK) >> bitname##__POS)
+
+
+#define SMI130_SET_BITSLICE(regvar, bitname, val)\
+ ((regvar & ~bitname##__MSK) | \
+ ((val<<bitname##__POS)&bitname##__MSK))
+
+/**************************************************/
+/**\name FUNCTION DECLARATIONS */
+/*************************************************/
+/**************************************************/
+/**\name FUNCTION FOR SMI130 INITIALIZE */
+/*************************************************/
+/*!
+ * @brief
+ * This function is used for initialize
+ * bus read and bus write functions
+ * assign the chip id and device address
+ * chip id is read in the register 0x00 bit from 0 to 7
+ *
+ * @param smi130 : structure pointer
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * While changing the parameter of the smi130_t
+ * consider the following point:
+ * Changing the reference value of the parameter
+ * will changes the local copy or local reference
+ * make sure your changes will not
+ * affect the reference value of the parameter
+ * (Better case don't change the reference value of the parameter)
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_init(struct smi130_t *smi130);
+/**************************************************/
+/**\name FUNCTION FOR READ AND WRITE REGISTERS */
+/*************************************************/
+/*!
+ * @brief
+ * This API write the data to
+ * the given register
+ *
+ *
+ * @param v_addr_u8 -> Address of the register
+ * @param v_data_u8 -> The data from the register
+ * @param v_len_u8 -> no of bytes to read
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_write_reg(u8 v_addr_u8,
+u8 *v_data_u8, u8 v_len_u8);
+/*!
+ * @brief
+ * This API reads the data from
+ * the given register
+ *
+ *
+ * @param v_addr_u8 -> Address of the register
+ * @param v_data_u8 -> The data from the register
+ * @param v_len_u8 -> no of bytes to read
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_read_reg(u8 v_addr_u8,
+u8 *v_data_u8, u8 v_len_u8);
+/**************************************************/
+/**\name FUNCTION FOR ERROR CODES */
+/*************************************************/
+/*!
+ * @brief This API used to reads the fatal error
+ * from the Register 0x02 bit 0
+ * This flag will be reset only by power-on-reset and soft reset
+ *
+ *
+ * @param v_fatal_err_u8 : The status of fatal error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fatal_err(u8
+*v_fatal_err_u8);
+/*!
+ * @brief This API used to read the error code
+ * from register 0x02 bit 1 to 4
+ *
+ *
+ * @param v_err_code_u8 : The status of error codes
+ * error_code | description
+ * ------------|---------------
+ * 0x00 |no error
+ * 0x01 |ACC_CONF error (accel ODR and bandwidth not compatible)
+ * 0x02 |GYR_CONF error (Gyroscope ODR and bandwidth not compatible)
+ * 0x03 |Under sampling mode and interrupt uses pre filtered data
+ * 0x04 |reserved
+ * 0x05 |Selected trigger-readout offset in
+ * - |MAG_IF greater than selected ODR
+ * 0x06 |FIFO configuration error for header less mode
+ * 0x07 |Under sampling mode and pre filtered data as FIFO source
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_err_code(u8
+*v_error_code_u8);
+/*!
+ * @brief This API Reads the i2c error code from the
+ * Register 0x02 bit 5.
+ * This error occurred in I2C master detected
+ *
+ * @param v_i2c_err_code_u8 : The status of i2c fail error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_i2c_fail_err(u8
+*v_i2c_error_code_u8);
+ /*!
+ * @brief This API Reads the dropped command error
+ * from the register 0x02 bit 6
+ *
+ *
+ * @param v_drop_cmd_err_u8 : The status of drop command error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_drop_cmd_err(u8
+*v_drop_cmd_err_u8);
+/*!
+ * @brief This API reads the magnetometer data ready
+ * interrupt not active.
+ * It reads from the error register 0x0x2 bit 7
+ *
+ *
+ *
+ *
+ * @param v_mag_data_rdy_err_u8 : The status of mag data ready interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_dada_rdy_err(u8
+*v_mag_data_rdy_err_u8);
+/*!
+ * @brief This API reads the error status
+ * from the error register 0x02 bit 0 to 7
+ *
+ * @param v_mag_data_rdy_err_u8 : The status of mag data ready interrupt
+ * @param v_fatal_er_u8r : The status of fatal error
+ * @param v_err_code_u8 : The status of error code
+ * @param v_i2c_fail_err_u8 : The status of I2C fail error
+ * @param v_drop_cmd_err_u8 : The status of drop command error
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_error_status(u8 *v_fatal_er_u8r,
+u8 *v_err_code_u8, u8 *v_i2c_fail_err_u8,
+u8 *v_drop_cmd_err_u8, u8 *v_mag_data_rdy_err_u8);
+/******************************************************************/
+/**\name FUNCTIONS FOR MAG,ACCEL AND GYRO POWER MODE STATUS */
+/*****************************************************************/
+/*!
+ * @brief This API reads the magnetometer power mode from
+ * PMU status register 0x03 bit 0 and 1
+ *
+ * @param v_mag_power_mode_stat_u8 : The value of mag power mode
+ * mag_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * LOW POWER | 0x02
+ *
+ *
+ * @note The power mode of mag set by the 0x7E command register
+ * @note using the function "smi130_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x18 | MAG_MODE_SUSPEND
+ * 0x19 | MAG_MODE_NORMAL
+ * 0x1A | MAG_MODE_LOWPOWER
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_power_mode_stat(u8
+*v_mag_power_mode_stat_u8);
+/*!
+ * @brief This API reads the gyroscope power mode from
+ * PMU status register 0x03 bit 2 and 3
+ *
+ * @param v_gyro_power_mode_stat_u8 : The value of gyro power mode
+ * gyro_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * FAST POWER UP | 0x03
+ *
+ * @note The power mode of gyro set by the 0x7E command register
+ * @note using the function "smi130_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x14 | GYRO_MODE_SUSPEND
+ * 0x15 | GYRO_MODE_NORMAL
+ * 0x17 | GYRO_MODE_FASTSTARTUP
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_power_mode_stat(u8
+*v_gyro_power_mode_stat_u8);
+/*!
+ * @brief This API reads the accelerometer power mode from
+ * PMU status register 0x03 bit 4 and 5
+ *
+ *
+ * @param v_accel_power_mode_stat_u8 : The value of accel power mode
+ * accel_powermode | value
+ * ------------------|----------
+ * SUSPEND | 0x00
+ * NORMAL | 0x01
+ * LOW POWER | 0x03
+ *
+ * @note The power mode of accel set by the 0x7E command register
+ * @note using the function "smi130_set_command_register()"
+ * value | mode
+ * ---------|----------------
+ * 0x11 | ACCEL_MODE_NORMAL
+ * 0x12 | ACCEL_LOWPOWER
+ * 0x10 | ACCEL_SUSPEND
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_power_mode_stat(u8
+*v_accel_power_mode_stat_u8);
+/*!
+ * @brief This API switch mag interface to normal mode
+ * and confirm whether the mode switching done successfully or not
+*
+ * @return results of bus communication function and current MAG_PMU result
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_interface_normal(void);
+/**************************************************/
+/**\name FUNCTION FOR Mag XYZ data read */
+/*************************************************/
+/*!
+ * @brief This API reads magnetometer data X values
+ * from the register 0x04 and 0x05
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_x_s16 : The value of mag x
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_x(s16 *v_mag_x_s16,
+u8 v_sensor_select_u8);
+/*!
+ * @brief This API reads magnetometer data Y values
+ * from the register 0x06 and 0x07
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_y_s16 : The value of mag y
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_y(s16 *v_mag_y_s16,
+u8 v_sensor_select_u8);
+/*!
+ * @brief This API reads magnetometer data Z values
+ * from the register 0x08 and 0x09
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param v_mag_z_s16 : The value of mag z
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_z(s16 *v_mag_z_s16,
+u8 v_sensor_select_u8);
+/*!
+ * @brief This API reads magnetometer data RHALL values
+ * from the register 0x0A and 0x0B
+ *
+ *
+ * @param v_mag_r_s16 : The value of BMM150 r data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_r(
+s16 *v_mag_r_s16);
+/*!
+ * @brief This API reads magnetometer data X,Y,Z values
+ * from the register 0x04 to 0x09
+ *
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param mag : The value of mag xyz data
+ * @param v_sensor_select_u8 : Mag selection value
+ * value | sensor
+ * ---------|----------------
+ * 0 | BMM150
+ * 1 | AKM09911 or AKM09912
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_xyz(
+struct smi130_mag_t *mag, u8 v_sensor_select_u8);
+ /*!*
+ * @brief This API reads magnetometer data X,Y,Z,r
+ * values from the register 0x04 to 0x0B
+ *
+ * @brief The mag sensor data read form auxiliary mag
+ *
+ * @param mag : The value of mag-BMM150 xyzr data
+ *
+ * @note For mag data output rate configuration use the following function
+ * @note smi130_set_mag_output_data_rate()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_mag_xyzr(
+struct smi130_mag_xyzr_t *mag);
+/**************************************************/
+/**\name FUNCTION FOR GYRO XYZ DATA READ */
+/*************************************************/
+/*!
+ * @brief This API reads gyro data X values
+ * form the register 0x0C and 0x0D
+ *
+ *
+ *
+ *
+ * @param v_gyro_x_s16 : The value of gyro x data
+ *
+ * @note Gyro Configuration use the following function
+ * @note smi130_set_gyro_output_data_rate()
+ * @note smi130_set_gyro_bw()
+ * @note smi130_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_gyro_x(
+s16 *v_gyro_x_s16);
+/*!
+ * @brief This API reads gyro data Y values
+ * form the register 0x0E and 0x0F
+ *
+ *
+ *
+ *
+ * @param v_gyro_y_s16 : The value of gyro y data
+ *
+ * @note Gyro Configuration use the following function
+ * @note smi130_set_gyro_output_data_rate()
+ * @note smi130_set_gyro_bw()
+ * @note smi130_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error result of communication routines
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_gyro_y(
+s16 *v_gyro_y_s16);
+/*!
+ * @brief This API reads gyro data Z values
+ * form the register 0x10 and 0x11
+ *
+ *
+ *
+ *
+ * @param v_gyro_z_s16 : The value of gyro z data
+ *
+ * @note Gyro Configuration use the following function
+ * @note smi130_set_gyro_output_data_rate()
+ * @note smi130_set_gyro_bw()
+ * @note smi130_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_gyro_z(
+s16 *v_gyro_z_s16);
+/*!
+ * @brief This API reads gyro data X,Y,Z values
+ * from the register 0x0C to 0x11
+ *
+ *
+ *
+ *
+ * @param gyro : The value of gyro xyz
+ *
+ * @note Gyro Configuration use the following function
+ * @note smi130_set_gyro_output_data_rate()
+ * @note smi130_set_gyro_bw()
+ * @note smi130_set_gyro_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_gyro_xyz(
+struct smi130_gyro_t *gyro);
+/**************************************************/
+/**\name FUNCTION FOR ACCEL XYZ DATA READ */
+/*************************************************/
+/*!
+ * @brief This API reads accelerometer data X values
+ * form the register 0x12 and 0x13
+ *
+ *
+ *
+ *
+ * @param v_accel_x_s16 : The value of accel x
+ *
+ * @note For accel configuration use the following functions
+ * @note smi130_set_accel_output_data_rate()
+ * @note smi130_set_accel_bw()
+ * @note smi130_set_accel_under_sampling_parameter()
+ * @note smi130_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_accel_x(
+s16 *v_accel_x_s16);
+/*!
+ * @brief This API reads accelerometer data Y values
+ * form the register 0x14 and 0x15
+ *
+ *
+ *
+ *
+ * @param v_accel_y_s16 : The value of accel y
+ *
+ * @note For accel configuration use the following functions
+ * @note smi130_set_accel_output_data_rate()
+ * @note smi130_set_accel_bw()
+ * @note smi130_set_accel_under_sampling_parameter()
+ * @note smi130_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_accel_y(
+s16 *v_accel_y_s16);
+/*!
+ * @brief This API reads accelerometer data Z values
+ * form the register 0x16 and 0x17
+ *
+ *
+ *
+ *
+ * @param v_accel_z_s16 : The value of accel z
+ *
+ * @note For accel configuration use the following functions
+ * @note smi130_set_accel_output_data_rate()
+ * @note smi130_set_accel_bw()
+ * @note smi130_set_accel_under_sampling_parameter()
+ * @note smi130_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_accel_z(
+s16 *v_accel_z_s16);
+/*!
+ * @brief This API reads accelerometer data X,Y,Z values
+ * from the register 0x12 to 0x17
+ *
+ *
+ *
+ *
+ * @param accel :The value of accel xyz
+ *
+ * @note For accel configuration use the following functions
+ * @note smi130_set_accel_output_data_rate()
+ * @note smi130_set_accel_bw()
+ * @note smi130_set_accel_under_sampling_parameter()
+ * @note smi130_set_accel_range()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_accel_xyz(
+struct smi130_accel_t *accel);
+/**************************************************/
+/**\name FUNCTION FOR SENSOR TIME */
+/*************************************************/
+/*!
+ * @brief This API reads sensor_time from the register
+ * 0x18 to 0x1A
+ *
+ *
+ * @param v_sensor_time_u32 : The value of sensor time
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_sensor_time(
+u32 *v_sensor_time_u32);
+/**************************************************/
+/**\name FUNCTION FOR GYRO SLEF TEST */
+/*************************************************/
+/*!
+ * @brief This API reads the Gyroscope self test
+ * status from the register 0x1B bit 1
+ *
+ *
+ * @param v_gyro_selftest_u8 : The value of gyro self test status
+ * value | status
+ * ---------|----------------
+ * 0 | Gyroscope self test is running or failed
+ * 1 | Gyroscope self test completed successfully
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_selftest(u8
+*v_gyro_selftest_u8);
+/**************************************************/
+/**\name FUNCTION FOR MANUAL INTERFACE */
+/*************************************************/
+/*!
+ * @brief This API reads the status of
+ * mag manual interface operation form the register 0x1B bit 2
+ *
+ *
+ *
+ * @param v_mag_manual_stat_u8 : The value of mag manual operation status
+ * value | status
+ * ---------|----------------
+ * 0 | Indicates no manual magnetometer
+ * - | interface operation is ongoing
+ * 1 | Indicates manual magnetometer
+ * - | interface operation is ongoing
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_manual_operation_stat(u8
+*v_mag_manual_stat_u8);
+/**************************************************/
+/**\name FUNCTION FOR FAST OFFSET READY */
+/*************************************************/
+/*!
+ * @brief This API reads the fast offset compensation
+ * status form the register 0x1B bit 3
+ *
+ *
+ * @param v_foc_rdy_u8 : The status of fast compensation
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_rdy(u8
+*v_foc_rdy_u8);
+/**************************************************/
+/**\name FUNCTION FOR NVM READY */
+/*************************************************/
+/*!
+ * @brief This API Reads the nvm_rdy status from the
+ * resister 0x1B bit 4
+ *
+ *
+ * @param v_nvm_rdy_u8 : The value of NVM ready status
+ * value | status
+ * ---------|----------------
+ * 0 | NVM write operation in progress
+ * 1 | NVM is ready to accept a new write trigger
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_nvm_rdy(u8
+*v_nvm_rdy_u8);
+/**************************************************/
+/**\name FUNCTION FOR DATA READY FOR MAG, GYRO, AND ACCEL */
+/*************************************************/
+/*!
+ * @brief This API reads the status of mag data ready
+ * from the register 0x1B bit 5
+ * The status get reset when one mag data register is read out
+ *
+ * @param v_data_rdy_u8 : The value of mag data ready status
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_data_rdy_mag(u8
+*v_data_rdy_u8);
+/*!
+ * @brief This API reads the status of gyro data ready form the
+ * register 0x1B bit 6
+ * The status get reset when gyro data register read out
+ *
+ *
+ * @param v_data_rdy_u8 : The value of gyro data ready
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_data_rdy(u8
+*v_data_rdy_u8);
+/*!
+ * @brief This API reads the status of accel data ready form the
+ * register 0x1B bit 7
+ * The status get reset when accel data register read out
+ *
+ *
+ * @param v_data_rdy_u8 : The value of accel data ready status
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_data_rdy(u8
+*drdy_acc);
+/**************************************************/
+/**\name FUNCTION FOR STEP INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the step detector interrupt status
+ * from the register 0x1C bit 0
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The status of step detector interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_step_intr(u8
+*v_step_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR SIGNIFICANT INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the
+ * significant motion interrupt status
+ * from the register 0x1C bit 1
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ *
+ * @param v_significant_intr_u8 : The status of step
+ * motion interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_significant_intr(u8
+*sigmot_intr);
+/**************************************************/
+/**\name FUNCTION FOR ANY MOTION INTERRUPT STATUS */
+/*************************************************/
+ /*!
+ * @brief This API reads the any motion interrupt status
+ * from the register 0x1C bit 2
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ * @param v_any_motion_intr_u8 : The status of any-motion interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_any_motion_intr(u8
+*v_any_motion_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR PMU TRIGGER INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the power mode trigger interrupt status
+ * from the register 0x1C bit 3
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ *
+ * @param v_pmu_trigger_intr_u8 : The status of power mode trigger interrupt
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_pmu_trigger_intr(u8
+*v_pmu_trigger_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR DOUBLE TAB STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the double tab status
+ * from the register 0x1C bit 4
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_double_tap_intr_u8 :The status of double tab interrupt
+ *
+ * @note Double tap interrupt can be configured by the following functions
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_double_tap()
+ * @note AXIS MAPPING
+ * @note smi130_get_stat2_tap_first_x()
+ * @note smi130_get_stat2_tap_first_y()
+ * @note smi130_get_stat2_tap_first_z()
+ * @note DURATION
+ * @note smi130_set_intr_tap_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_tap_thres()
+ * @note TAP QUIET
+ * @note smi130_set_intr_tap_quiet()
+ * @note TAP SHOCK
+ * @note smi130_set_intr_tap_shock()
+ * @note TAP SOURCE
+ * @note smi130_set_intr_tap_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_double_tap_intr(u8
+*v_double_tap_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR SINGLE TAB STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the single tab status
+ * from the register 0x1C bit 5
+ * flag is associated with a specific interrupt function.
+ * It is set when the single tab interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt
+ * signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_single_tap_intr_u8 :The status of single tap interrupt
+ *
+ * @note Single tap interrupt can be configured by the following functions
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_single_tap()
+ * @note AXIS MAPPING
+ * @note smi130_get_stat2_tap_first_x()
+ * @note smi130_get_stat2_tap_first_y()
+ * @note smi130_get_stat2_tap_first_z()
+ * @note DURATION
+ * @note smi130_set_intr_tap_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_tap_thres()
+ * @note TAP QUIET
+ * @note smi130_set_intr_tap_quiet()
+ * @note TAP SHOCK
+ * @note smi130_set_intr_tap_shock()
+ * @note TAP SOURCE
+ * @note smi130_set_intr_tap_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_single_tap_intr(u8
+*v_single_tap_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR ORIENT INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the orient_mbl status
+ * from the register 0x1C bit 6
+ * flag is associated with a specific interrupt function.
+ * It is set when the orient_mbl interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_orient_mbl_intr_u8 : The status of orient_mbl interrupt
+ *
+ * @note For orient_mbl interrupt configuration use the following functions
+ * @note STATUS
+ * @note smi130_get_stat0_orient_mbl_intr()
+ * @note AXIS MAPPING
+ * @note smi130_get_stat3_orient_mbl_xy()
+ * @note smi130_get_stat3_orient_mbl_z()
+ * @note smi130_set_intr_orient_mbl_axes_enable()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_orient_mbl()
+ * @note INTERRUPT OUTPUT
+ * @note smi130_set_intr_orient_mbl_ud_enable()
+ * @note THETA
+ * @note smi130_set_intr_orient_mbl_theta()
+ * @note HYSTERESIS
+ * @note smi130_set_intr_orient_mbl_hyst()
+ * @note BLOCKING
+ * @note smi130_set_intr_orient_mbl_blocking()
+ * @note MODE
+ * @note smi130_set_intr_orient_mbl_mode()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_orient_mbl_intr(u8
+*v_orient_mbl_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR FLAT INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the flat interrupt status
+ * from the register 0x1C bit 7
+ * flag is associated with a specific interrupt function.
+ * It is set when the flat interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_flat_intr_u8 : The status of flat interrupt
+ *
+ * @note For flat configuration use the following functions
+ * @note STATS
+ * @note smi130_get_stat0_flat_intr()
+ * @note smi130_get_stat3_flat()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_flat()
+ * @note THETA
+ * @note smi130_set_intr_flat_theta()
+ * @note HOLD TIME
+ * @note smi130_set_intr_flat_hold()
+ * @note HYSTERESIS
+ * @note smi130_set_intr_flat_hyst()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat0_flat_intr(u8
+*v_flat_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR HIGH_G INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the high_g interrupt status
+ * from the register 0x1D bit 2
+ * flag is associated with a specific interrupt function.
+ * It is set when the high g interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be permanently
+ * latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_high_g_intr_u8 : The status of high_g interrupt
+ *
+ * @note High_g interrupt configured by following functions
+ * @note STATUS
+ * @note smi130_get_stat1_high_g_intr()
+ * @note AXIS MAPPING
+ * @note smi130_get_stat3_high_g_first_x()
+ * @note smi130_get_stat3_high_g_first_y()
+ * @note smi130_get_stat3_high_g_first_z()
+ * @note SIGN MAPPING
+ * @note smi130_get_stat3_high_g_first_sign()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_high_g()
+ * @note HYSTERESIS
+ * @note smi130_set_intr_high_g_hyst()
+ * @note DURATION
+ * @note smi130_set_intr_high_g_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_high_g_thres()
+ * @note SOURCE
+ * @note smi130_set_intr_low_high_source()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_high_g_intr(u8
+*v_high_g_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR LOW_G INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads the low g interrupt status
+ * from the register 0x1D bit 3
+ * flag is associated with a specific interrupt function.
+ * It is set when the low g interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_low_g_intr_u8 : The status of low_g interrupt
+ *
+ * @note Low_g interrupt configured by following functions
+ * @note STATUS
+ * @note smi130_get_stat1_low_g_intr()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_low_g()
+ * @note SOURCE
+ * @note smi130_set_intr_low_high_source()
+ * @note DURATION
+ * @note smi130_set_intr_low_g_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_low_g_thres()
+ * @note HYSTERESIS
+ * @note smi130_set_intr_low_g_hyst()
+ * @note MODE
+ * @note smi130_set_intr_low_g_mode()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_low_g_intr(u8
+*v_low_g_intr_u8);
+/**************************************************/
+/**\name FUNCTION FOR DATA READY INTERRUPT STATUS */
+/*************************************************/
+/*!
+ * @brief This API reads data ready interrupt status
+ * from the register 0x1D bit 4
+ * flag is associated with a specific interrupt function.
+ * It is set when the data ready interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_data_rdy_intr_u8 : The status of data ready interrupt
+ *
+ * @note Data ready interrupt configured by following functions
+ * @note STATUS
+ * @note smi130_get_stat1_data_rdy_intr()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_data_rdy()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_data_rdy_intr(u8
+*v_data_rdy_intr_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR FIFO FULL AND WATER MARK INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads data ready FIFO full interrupt status
+ * from the register 0x1D bit 5
+ * flag is associated with a specific interrupt function.
+ * It is set when the FIFO full interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will
+ * be permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_fifo_full_intr_u8 : The status of fifo full interrupt
+ *
+ * @note FIFO full interrupt can be configured by following functions
+ * @note smi130_set_intr_fifo_full()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_fifo_full_intr(u8
+*v_fifo_full_intr_u8);
+/*!
+ * @brief This API reads data
+ * ready FIFO watermark interrupt status
+ * from the register 0x1D bit 6
+ * flag is associated with a specific interrupt function.
+ * It is set when the FIFO watermark interrupt triggers. The
+ * setting of INT_LATCH controls if the
+ * interrupt signal and hence the
+ * respective interrupt flag will be
+ * permanently latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_fifo_wm_intr_u8 : The status of fifo water mark interrupt
+ *
+ * @note FIFO full interrupt can be configured by following functions
+ * @note smi130_set_intr_fifo_wm()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_fifo_wm_intr(u8
+*v_fifo_wm_intr_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR NO MOTION INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads data ready no motion interrupt status
+ * from the register 0x1D bit 7
+ * flag is associated with a specific interrupt function.
+ * It is set when the no motion interrupt triggers. The
+ * setting of INT_LATCH controls if the interrupt signal and hence the
+ * respective interrupt flag will be permanently
+ * latched, temporarily latched
+ * or not latched.
+ *
+ *
+ *
+ *
+ * @param v_nomotion_intr_u8 : The status of no motion interrupt
+ *
+ * @note No motion interrupt can be configured by following function
+ * @note STATUS
+ * @note smi130_get_stat1_nomotion_intr()
+ * @note INTERRUPT MAPPING
+ * @note smi130_set_intr_nomotion()
+ * @note DURATION
+ * @note smi130_set_intr_slow_no_motion_durn()
+ * @note THRESHOLD
+ * @note smi130_set_intr_slow_no_motion_thres()
+ * @note SLOW/NO MOTION SELECT
+ * @note smi130_set_intr_slow_no_motion_select()
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat1_nomotion_intr(u8
+*nomo_intr);
+/**************************************************/
+/**\name FUNCTIONS FOR ANY MOTION FIRST XYZ AND SIGN INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the status of any motion first x
+ * from the register 0x1E bit 0
+ *
+ *
+ * @param v_anymotion_first_x_u8 : The status of any motion first x interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_any_motion_first_x(u8
+*v_anymotion_first_x_u8);
+/*!
+ * @brief This API reads the status of any motion first y interrupt
+ * from the register 0x1E bit 1
+ *
+ *
+ *
+ *@param v_any_motion_first_y_u8 : The status of any motion first y interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_any_motion_first_y(u8
+*v_any_motion_first_y_u8);
+/*!
+ * @brief This API reads the status of any motion first z interrupt
+ * from the register 0x1E bit 2
+ *
+ *
+ *
+ *
+ *@param v_any_motion_first_z_u8 : The status of any motion first z interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_any_motion_first_z(u8
+*v_any_motion_first_z_u8);
+/*!
+ * @brief This API reads the any motion sign status from the
+ * register 0x1E bit 3
+ *
+ *
+ *
+ *
+ * @param v_anymotion_sign_u8 : The status of any motion sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_any_motion_sign(u8
+*v_anymotion_sign_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR TAP FIRST XYZ AND SIGN INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the any motion tap first x status from the
+ * register 0x1E bit 4
+ *
+ *
+ *
+ *
+ * @param v_tap_first_x_u8 :The status of any motion tap first x
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_tap_first_x(u8
+*v_tap_first_x_u8);
+/*!
+ * @brief This API reads the tap first y interrupt status from the
+ * register 0x1E bit 5
+ *
+ *
+ *
+ *
+ * @param v_tap_first_y_u8 :The status of tap first y interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_tap_first_y(u8
+*v_tap_first_y_u8);
+/*!
+ * @brief This API reads the tap first z interrupt status from the
+ * register 0x1E bit 6
+ *
+ *
+ *
+ *
+ * @param v_tap_first_z_u8 :The status of tap first z interrupt
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_tap_first_z(u8
+*v_tap_first_z_u8);
+/*!
+ * @brief This API reads the tap sign status from the
+ * register 0x1E bit 7
+ *
+ *
+ *
+ *
+ * @param v_tap_sign_u8 : The status of tap sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat2_tap_sign(u8
+*tap_sign);
+/**************************************************/
+/**\name FUNCTIONS FOR HIGH_G FIRST XYZ AND SIGN INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the high_g first x status from the
+ * register 0x1F bit 0
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_x_u8 :The status of high_g first x
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_high_g_first_x(u8
+*v_high_g_first_x_u8);
+/*!
+ * @brief This API reads the high_g first y status from the
+ * register 0x1F bit 1
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_y_u8 : The status of high_g first y
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_high_g_first_y(u8
+*v_high_g_first_y_u8);
+/*!
+ * @brief This API reads the high_g first z status from the
+ * register 0x1F bit 3
+ *
+ *
+ *
+ *
+ * @param v_high_g_first_z_u8 : The status of high_g first z
+ * value | status
+ * -----------|-------------
+ * 0 | not triggered
+ * 1 | triggered by z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_high_g_first_z(u8
+*v_high_g_first_z_u8);
+/*!
+ * @brief This API reads the high sign status from the
+ * register 0x1F bit 3
+ *
+ *
+ *
+ *
+ * @param v_high_g_sign_u8 :The status of high sign
+ * value | sign
+ * -----------|-------------
+ * 0 | positive
+ * 1 | negative
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_high_g_sign(u8
+*v_high_g_sign_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR ORIENT XY AND Z INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the status of orient_mbl_xy plane
+ * from the register 0x1F bit 4 and 5
+ *
+ *
+ * @param v_orient_mbl_xy_u8 :The status of orient_mbl_xy plane
+ * value | status
+ * -----------|-------------
+ * 0x00 | portrait upright
+ * 0x01 | portrait upside down
+ * 0x02 | landscape left
+ * 0x03 | landscape right
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_orient_mbl_xy(u8
+*v_orient_mbl_xy_u8);
+/*!
+ * @brief This API reads the status of orient_mbl z plane
+ * from the register 0x1F bit 6
+ *
+ *
+ * @param v_orient_mbl_z_u8 :The status of orient_mbl z
+ * value | status
+ * -----------|-------------
+ * 0x00 | upward looking
+ * 0x01 | downward looking
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_orient_mbl_z(u8
+*v_orient_mbl_z_u8);
+/**************************************************/
+/**\name FUNCTIONS FOR FLAT INTERRUPT STATUS*/
+/*************************************************/
+/*!
+ * @brief This API reads the flat status from the register
+ * 0x1F bit 7
+ *
+ *
+ * @param v_flat_u8 : The status of flat interrupt
+ * value | status
+ * -----------|-------------
+ * 0x00 | non flat
+ * 0x01 | flat position
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_stat3_flat(u8
+*flat);
+/**************************************************/
+/**\name FUNCTION FOR TEMPERATUE READ */
+/*************************************************/
+/*!
+ * @brief This API reads the temperature of the sensor
+ * from the register 0x21 bit 0 to 7
+ *
+ *
+ *
+ * @param v_temp_s16 : The value of temperature
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_temp(s16
+*v_temp_s16);
+/**************************************************/
+/**\name FUNCTION FOR FIFO LENGTH AND FIFO DATA READ */
+/*************************************************/
+/*!
+ * @brief This API reads the of the sensor
+ * form the register 0x23 and 0x24 bit 0 to 7 and 0 to 2
+ * @brief this byte counter is updated each time a complete frame
+ * was read or writtern
+ *
+ *
+ * @param v_fifo_length_u32 : The value of fifo byte counter
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_fifo_length(
+u32 *v_fifo_length_u32);
+/*!
+ * @brief This API reads the fifo data of the sensor
+ * from the register 0x24
+ * @brief Data format depends on the setting of register FIFO_CONFIG
+ *
+ *
+ *
+ * @param v_fifodata_u8 : Pointer holding the fifo data
+ *
+ * @note For reading FIFO data use the following functions
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_fifo_data(
+u8 *v_fifodata_u8, u16 v_fifo_length_u16);
+/**************************************************/
+/**\name FUNCTION FOR ACCEL CONFIGURATIONS */
+/*************************************************/
+/*!
+ * @brief This API is used to get the
+ * accel output date rate form the register 0x40 bit 0 to 3
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of accel output date rate
+ * value | output data rate
+ * -------|--------------------------
+ * 0 | SMI130_ACCEL_OUTPUT_DATA_RATE_RESERVED
+ * 1 | SMI130_ACCEL_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | SMI130_ACCEL_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | SMI130_ACCEL_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | SMI130_ACCEL_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | SMI130_ACCEL_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | SMI130_ACCEL_OUTPUT_DATA_RATE_25HZ
+ * 7 | SMI130_ACCEL_OUTPUT_DATA_RATE_50HZ
+ * 8 | SMI130_ACCEL_OUTPUT_DATA_RATE_100HZ
+ * 9 | SMI130_ACCEL_OUTPUT_DATA_RATE_200HZ
+ * 10 | SMI130_ACCEL_OUTPUT_DATA_RATE_400HZ
+ * 11 | SMI130_ACCEL_OUTPUT_DATA_RATE_800HZ
+ * 12 | SMI130_ACCEL_OUTPUT_DATA_RATE_1600HZ
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_output_data_rate(
+u8 *v_output_data_rate_u8);
+/*!
+ * @brief This API is used to set the
+ * accel output date rate form the register 0x40 bit 0 to 3
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of accel output date rate
+ * value | output data rate
+ * -------|--------------------------
+ * 0 | SMI130_ACCEL_OUTPUT_DATA_RATE_RESERVED
+ * 1 | SMI130_ACCEL_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | SMI130_ACCEL_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | SMI130_ACCEL_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | SMI130_ACCEL_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | SMI130_ACCEL_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | SMI130_ACCEL_OUTPUT_DATA_RATE_25HZ
+ * 7 | SMI130_ACCEL_OUTPUT_DATA_RATE_50HZ
+ * 8 | SMI130_ACCEL_OUTPUT_DATA_RATE_100HZ
+ * 9 | SMI130_ACCEL_OUTPUT_DATA_RATE_200HZ
+ * 10 | SMI130_ACCEL_OUTPUT_DATA_RATE_400HZ
+ * 11 | SMI130_ACCEL_OUTPUT_DATA_RATE_800HZ
+ * 12 | SMI130_ACCEL_OUTPUT_DATA_RATE_1600HZ
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_output_data_rate(u8 odr);
+/*!
+ * @brief This API is used to get the
+ * accel bandwidth from the register 0x40 bit 4 to 6
+ * @brief bandwidth parameter determines filter configuration(acc_us=0)
+ * and averaging for under sampling mode(acc_us=1)
+ *
+ *
+ * @param v_bw_u8 : The value of accel bandwidth
+ *
+ * @note accel bandwidth depends on under sampling parameter
+ * @note under sampling parameter cab be set by the function
+ * "SMI130_SET_ACCEL_UNDER_SAMPLING_PARAMETER"
+ *
+ * @note Filter configuration
+ * accel_us | Filter configuration
+ * -----------|---------------------
+ * 0x00 | OSR4 mode
+ * 0x01 | OSR2 mode
+ * 0x02 | normal mode
+ * 0x03 | CIC mode
+ * 0x04 | Reserved
+ * 0x05 | Reserved
+ * 0x06 | Reserved
+ * 0x07 | Reserved
+ *
+ * @note accel under sampling mode
+ * accel_us | Under sampling mode
+ * -----------|---------------------
+ * 0x00 | no averaging
+ * 0x01 | average 2 samples
+ * 0x02 | average 4 samples
+ * 0x03 | average 8 samples
+ * 0x04 | average 16 samples
+ * 0x05 | average 32 samples
+ * 0x06 | average 64 samples
+ * 0x07 | average 128 samples
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_bw(u8 *v_bw_u8);
+/*!
+ * @brief This API is used to set the
+ * accel bandwidth from the register 0x40 bit 4 to 6
+ * @brief bandwidth parameter determines filter configuration(acc_us=0)
+ * and averaging for under sampling mode(acc_us=1)
+ *
+ *
+ * @param v_bw_u8 : The value of accel bandwidth
+ *
+ * @note accel bandwidth depends on under sampling parameter
+ * @note under sampling parameter cab be set by the function
+ * "SMI130_SET_ACCEL_UNDER_SAMPLING_PARAMETER"
+ *
+ * @note Filter configuration
+ * accel_us | Filter configuration
+ * -----------|---------------------
+ * 0x00 | OSR4 mode
+ * 0x01 | OSR2 mode
+ * 0x02 | normal mode
+ * 0x03 | CIC mode
+ * 0x04 | Reserved
+ * 0x05 | Reserved
+ * 0x06 | Reserved
+ * 0x07 | Reserved
+ *
+ * @note accel under sampling mode
+ * accel_us | Under sampling mode
+ * -----------|---------------------
+ * 0x00 | no averaging
+ * 0x01 | average 2 samples
+ * 0x02 | average 4 samples
+ * 0x03 | average 8 samples
+ * 0x04 | average 16 samples
+ * 0x05 | average 32 samples
+ * 0x06 | average 64 samples
+ * 0x07 | average 128 samples
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_bw(u8 v_bw_u8);
+/*!
+ * @brief This API is used to get the accel
+ * under sampling parameter form the register 0x40 bit 7
+ *
+ *
+ *
+ *
+ * @param v_accel_under_sampling_u8 : The value of accel under sampling
+ * value | under_sampling
+ * ----------|---------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_under_sampling_parameter(
+u8 *v_accel_under_sampling_u8);
+/*!
+ * @brief This API is used to set the accel
+ * under sampling parameter form the register 0x40 bit 7
+ *
+ *
+ *
+ *
+ * @param v_accel_under_sampling_u8 : The value of accel under sampling
+ * value | under_sampling
+ * ----------|---------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_under_sampling_parameter(
+u8 v_accel_under_sampling_u8);
+/*!
+ * @brief This API is used to get the ranges
+ * (g values) of the accel from the register 0x41 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_range_u8 : The value of accel g range
+ * value | g_range
+ * ----------|-----------
+ * 0x03 | SMI130_ACCEL_RANGE_2G
+ * 0x05 | SMI130_ACCEL_RANGE_4G
+ * 0x08 | SMI130_ACCEL_RANGE_8G
+ * 0x0C | SMI130_ACCEL_RANGE_16G
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_range(
+u8 *v_range_u8);
+/*!
+ * @brief This API is used to set the ranges
+ * (g values) of the accel from the register 0x41 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_range_u8 : The value of accel g range
+ * value | g_range
+ * ----------|-----------
+ * 0x03 | SMI130_ACCEL_RANGE_2G
+ * 0x05 | SMI130_ACCEL_RANGE_4G
+ * 0x08 | SMI130_ACCEL_RANGE_8G
+ * 0x0C | SMI130_ACCEL_RANGE_16G
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_range(
+u8 v_range_u8);
+/**************************************************/
+/**\name FUNCTION FOR GYRO CONFIGURATIONS */
+/*************************************************/
+/*!
+ * @brief This API is used to get the
+ * gyroscope output data rate from the register 0x42 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of gyro output data rate
+ * value | gyro output data rate
+ * -----------|-----------------------------
+ * 0x00 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x02 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x03 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x04 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x05 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x06 | SMI130_GYRO_OUTPUT_DATA_RATE_25HZ
+ * 0x07 | SMI130_GYRO_OUTPUT_DATA_RATE_50HZ
+ * 0x08 | SMI130_GYRO_OUTPUT_DATA_RATE_100HZ
+ * 0x09 | SMI130_GYRO_OUTPUT_DATA_RATE_200HZ
+ * 0x0A | SMI130_GYRO_OUTPUT_DATA_RATE_400HZ
+ * 0x0B | SMI130_GYRO_OUTPUT_DATA_RATE_800HZ
+ * 0x0C | SMI130_GYRO_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D | SMI130_GYRO_OUTPUT_DATA_RATE_3200HZ
+ * 0x0E | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x0F | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_output_data_rate(
+u8 *gyro_output_typer);
+/*!
+ * @brief This API is used to set the
+ * gyroscope output data rate from the register 0x42 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rate_u8 :The value of gyro output data rate
+ * value | gyro output data rate
+ * -----------|-----------------------------
+ * 0x00 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x02 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x03 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x04 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x05 | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x06 | SMI130_GYRO_OUTPUT_DATA_RATE_25HZ
+ * 0x07 | SMI130_GYRO_OUTPUT_DATA_RATE_50HZ
+ * 0x08 | SMI130_GYRO_OUTPUT_DATA_RATE_100HZ
+ * 0x09 | SMI130_GYRO_OUTPUT_DATA_RATE_200HZ
+ * 0x0A | SMI130_GYRO_OUTPUT_DATA_RATE_400HZ
+ * 0x0B | SMI130_GYRO_OUTPUT_DATA_RATE_800HZ
+ * 0x0C | SMI130_GYRO_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D | SMI130_GYRO_OUTPUT_DATA_RATE_3200HZ
+ * 0x0E | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ * 0x0F | SMI130_GYRO_OUTPUT_DATA_RATE_RESERVED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_output_data_rate(
+u8 gyro_output_typer);
+/*!
+ * @brief This API is used to get the
+ * data of gyro from the register 0x42 bit 4 to 5
+ *
+ *
+ *
+ *
+ * @param v_bw_u8 : The value of gyro bandwidth
+ * value | gyro bandwidth
+ * ----------|----------------
+ * 0x00 | SMI130_GYRO_OSR4_MODE
+ * 0x01 | SMI130_GYRO_OSR2_MODE
+ * 0x02 | SMI130_GYRO_NORMAL_MODE
+ * 0x03 | SMI130_GYRO_CIC_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_bw(u8 *v_bw_u8);
+/*!
+ * @brief This API is used to set the
+ * data of gyro from the register 0x42 bit 4 to 5
+ *
+ *
+ *
+ *
+ * @param v_bw_u8 : The value of gyro bandwidth
+ * value | gyro bandwidth
+ * ----------|----------------
+ * 0x00 | SMI130_GYRO_OSR4_MODE
+ * 0x01 | SMI130_GYRO_OSR2_MODE
+ * 0x02 | SMI130_GYRO_NORMAL_MODE
+ * 0x03 | SMI130_GYRO_CIC_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_bw(u8 v_bw_u8);
+/*!
+ * @brief This API reads the range
+ * of gyro from the register 0x43 bit 0 to 2
+ *
+ * @param v_range_u8 : The value of gyro range
+ * value | range
+ * ----------|-------------------------------
+ * 0x00 | SMI130_GYRO_RANGE_2000_DEG_SEC
+ * 0x01 | SMI130_GYRO_RANGE_1000_DEG_SEC
+ * 0x02 | SMI130_GYRO_RANGE_500_DEG_SEC
+ * 0x03 | SMI130_GYRO_RANGE_250_DEG_SEC
+ * 0x04 | SMI130_GYRO_RANGE_125_DEG_SEC
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_range(
+u8 *v_range_u8);
+/*!
+ * @brief This API set the range
+ * of gyro from the register 0x43 bit 0 to 2
+ *
+ * @param v_range_u8 : The value of gyro range
+ * value | range
+ * ----------|-------------------------------
+ * 0x00 | SMI130_GYRO_RANGE_2000_DEG_SEC
+ * 0x01 | SMI130_GYRO_RANGE_1000_DEG_SEC
+ * 0x02 | SMI130_GYRO_RANGE_500_DEG_SEC
+ * 0x03 | SMI130_GYRO_RANGE_250_DEG_SEC
+ * 0x04 | SMI130_GYRO_RANGE_125_DEG_SEC
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_range(
+u8 v_range_u8);
+/**************************************************/
+/**\name FUNCTION FOR MAG CONFIGURATIONS */
+/*************************************************/
+/*!
+ * @brief This API is used to get the
+ * output data rate of magnetometer from the register 0x44 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rat_u8e : The value of mag output data rate
+ * value | mag output data rate
+ * ---------|---------------------------
+ * 0x00 |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 |SMI130_MAG_OUTPUT_DATA_RATE_0_78HZ
+ * 0x02 |SMI130_MAG_OUTPUT_DATA_RATE_1_56HZ
+ * 0x03 |SMI130_MAG_OUTPUT_DATA_RATE_3_12HZ
+ * 0x04 |SMI130_MAG_OUTPUT_DATA_RATE_6_25HZ
+ * 0x05 |SMI130_MAG_OUTPUT_DATA_RATE_12_5HZ
+ * 0x06 |SMI130_MAG_OUTPUT_DATA_RATE_25HZ
+ * 0x07 |SMI130_MAG_OUTPUT_DATA_RATE_50HZ
+ * 0x08 |SMI130_MAG_OUTPUT_DATA_RATE_100HZ
+ * 0x09 |SMI130_MAG_OUTPUT_DATA_RATE_200HZ
+ * 0x0A |SMI130_MAG_OUTPUT_DATA_RATE_400HZ
+ * 0x0B |SMI130_MAG_OUTPUT_DATA_RATE_800HZ
+ * 0x0C |SMI130_MAG_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED0
+ * 0x0E |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED1
+ * 0x0F |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED2
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_output_data_rate(u8 *odr);
+/*!
+ * @brief This API is used to set the
+ * output data rate of magnetometer from the register 0x44 bit 0 to 3
+ *
+ *
+ *
+ *
+ * @param v_output_data_rat_u8e : The value of mag output data rate
+ * value | mag output data rate
+ * ---------|---------------------------
+ * 0x00 |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED
+ * 0x01 |SMI130_MAG_OUTPUT_DATA_RATE_0_78HZ
+ * 0x02 |SMI130_MAG_OUTPUT_DATA_RATE_1_56HZ
+ * 0x03 |SMI130_MAG_OUTPUT_DATA_RATE_3_12HZ
+ * 0x04 |SMI130_MAG_OUTPUT_DATA_RATE_6_25HZ
+ * 0x05 |SMI130_MAG_OUTPUT_DATA_RATE_12_5HZ
+ * 0x06 |SMI130_MAG_OUTPUT_DATA_RATE_25HZ
+ * 0x07 |SMI130_MAG_OUTPUT_DATA_RATE_50HZ
+ * 0x08 |SMI130_MAG_OUTPUT_DATA_RATE_100HZ
+ * 0x09 |SMI130_MAG_OUTPUT_DATA_RATE_200HZ
+ * 0x0A |SMI130_MAG_OUTPUT_DATA_RATE_400HZ
+ * 0x0B |SMI130_MAG_OUTPUT_DATA_RATE_800HZ
+ * 0x0C |SMI130_MAG_OUTPUT_DATA_RATE_1600HZ
+ * 0x0D |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED0
+ * 0x0E |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED1
+ * 0x0F |SMI130_MAG_OUTPUT_DATA_RATE_RESERVED2
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_output_data_rate(u8 odr);
+/**************************************************/
+/**\name FUNCTION FOR FIFO CONFIGURATIONS */
+/*************************************************/
+ /*!
+ * @brief This API is used to read Down sampling
+ * for gyro (2**downs_gyro) in the register 0x45 bit 0 to 2
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_gyro_u8 :The value of gyro fifo down
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_down_gyro(
+u8 *v_fifo_down_gyro_u8);
+ /*!
+ * @brief This API is used to set Down sampling
+ * for gyro (2**downs_gyro) in the register 0x45 bit 0 to 2
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_gyro_u8 :The value of gyro fifo down
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_down_gyro(
+u8 v_fifo_down_gyro_u8);
+/*!
+ * @brief This API is used to read gyro fifo filter data
+ * from the register 0x45 bit 3
+ *
+ *
+ *
+ * @param v_gyro_fifo_filter_data_u8 :The value of gyro filter data
+ * value | gyro_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_fifo_filter_data(
+u8 *v_gyro_fifo_filter_data_u8);
+/*!
+ * @brief This API is used to set gyro fifo filter data
+ * from the register 0x45 bit 3
+ *
+ *
+ *
+ * @param v_gyro_fifo_filter_data_u8 :The value of gyro filter data
+ * value | gyro_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_fifo_filter_data(
+u8 v_gyro_fifo_filter_data_u8);
+/*!
+ * @brief This API is used to read Down sampling
+ * for accel (2*downs_accel) from the register 0x45 bit 4 to 6
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_u8 :The value of accel fifo down
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_down_accel(
+u8 *v_fifo_down_u8);
+ /*!
+ * @brief This API is used to set Down sampling
+ * for accel (2*downs_accel) from the register 0x45 bit 4 to 6
+ *
+ *
+ *
+ *
+ * @param v_fifo_down_u8 :The value of accel fifo down
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_down_accel(
+u8 v_fifo_down_u8);
+/*!
+ * @brief This API is used to read accel fifo filter data
+ * from the register 0x45 bit 7
+ *
+ *
+ *
+ * @param v_accel_fifo_filter_u8 :The value of accel filter data
+ * value | accel_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_fifo_filter_data(
+u8 *v_accel_fifo_filter_u8);
+/*!
+ * @brief This API is used to set accel fifo filter data
+ * from the register 0x45 bit 7
+ *
+ *
+ *
+ * @param v_accel_fifo_filter_u8 :The value of accel filter data
+ * value | accel_fifo_filter_data
+ * ------------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_fifo_filter_data(
+u8 v_accel_fifo_filter_u8);
+/**************************************************/
+/**\name FUNCTION FOR FIFO WATER MARK ENABLE */
+/*************************************************/
+/*!
+ * @brief This API is used to Trigger an interrupt
+ * when FIFO contains water mark level from the register 0x46 bit 0 to 7
+ *
+ *
+ *
+ * @param v_fifo_wm_u8 : The value of fifo water mark level
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_wm(
+u8 *v_fifo_wm_u8);
+/*!
+ * @brief This API is used to Trigger an interrupt
+ * when FIFO contains water mark level from the register 0x46 bit 0 to 7
+ *
+ *
+ *
+ * @param v_fifo_wm_u8 : The value of fifo water mark level
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_wm(
+u8 v_fifo_wm_u8);
+/**************************************************/
+/**\name FUNCTION FOR FIFO CONFIGURATIONS */
+/*************************************************/
+/*!
+ * @brief This API reads fifo sensor time
+ * frame after the last valid data frame form the register 0x47 bit 1
+ *
+ *
+ *
+ *
+ * @param v_fifo_time_enable_u8 : The value of sensor time
+ * value | fifo sensor time
+ * ------------|-------------------------
+ * 0x00 | do not return sensortime frame
+ * 0x01 | return sensortime frame
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_time_enable(
+u8 *v_fifo_time_enable_u8);
+/*!
+ * @brief This API set fifo sensor time
+ * frame after the last valid data frame form the register 0x47 bit 1
+ *
+ *
+ *
+ *
+ * @param v_fifo_time_enable_u8 : The value of sensor time
+ * value | fifo sensor time
+ * ------------|-------------------------
+ * 0x00 | do not return sensortime frame
+ * 0x01 | return sensortime frame
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_time_enable(
+u8 v_fifo_time_enable_u8);
+/*!
+ * @brief This API reads FIFO tag interrupt2 enable status
+ * from the resister 0x47 bit 2
+ *
+ * @param v_fifo_tag_intr2_u8 : The value of fifo tag interrupt
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_tag_intr2_enable(
+u8 *v_fifo_tag_intr2_u8);
+/*!
+ * @brief This API set FIFO tag interrupt2 enable status
+ * from the resister 0x47 bit 2
+ *
+ * @param v_fifo_tag_intr2_u8 : The value of fifo tag interrupt
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_tag_intr2_enable(
+u8 v_fifo_tag_intr2_u8);
+/*!
+ * @brief This API get FIFO tag interrupt1 enable status
+ * from the resister 0x47 bit 3
+ *
+ * @param v_fifo_tag_intr1_u8 :The value of fifo tag interrupt1
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_tag_intr1_enable(
+u8 *v_fifo_tag_intr1_u8);
+/*!
+ * @brief This API set FIFO tag interrupt1 enable status
+ * from the resister 0x47 bit 3
+ *
+ * @param v_fifo_tag_intr1_u8 :The value of fifo tag interrupt1
+ * value | fifo tag interrupt
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_tag_intr1_enable(
+u8 v_fifo_tag_intr1_u8);
+/*!
+ * @brief This API reads FIFO frame
+ * header enable from the register 0x47 bit 4
+ *
+ * @param v_fifo_header_u8 :The value of fifo header
+ * value | fifo header
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_header_enable(
+u8 *v_fifo_header_u8);
+/*!
+ * @brief This API set FIFO frame
+ * header enable from the register 0x47 bit 4
+ *
+ * @param v_fifo_header_u8 :The value of fifo header
+ * value | fifo header
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_header_enable(
+u8 v_fifo_header_u8);
+/*!
+ * @brief This API is used to read stored
+ * magnetometer data in FIFO (all 3 axes) from the register 0x47 bit 5
+ *
+ * @param v_fifo_mag_u8 : The value of fifo mag enble
+ * value | fifo mag
+ * ----------|-------------------
+ * 0x00 | no magnetometer data is stored
+ * 0x01 | magnetometer data is stored
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_mag_enable(
+u8 *v_fifo_mag_u8);
+/*!
+ * @brief This API is used to set stored
+ * magnetometer data in FIFO (all 3 axes) from the register 0x47 bit 5
+ *
+ * @param v_fifo_mag_u8 : The value of fifo mag enble
+ * value | fifo mag
+ * ----------|-------------------
+ * 0x00 | no magnetometer data is stored
+ * 0x01 | magnetometer data is stored
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_mag_enable(
+u8 v_fifo_mag_u8);
+/*!
+ * @brief This API is used to read stored
+ * accel data in FIFO (all 3 axes) from the register 0x47 bit 6
+ *
+ * @param v_fifo_accel_u8 : The value of fifo accel enble
+ * value | fifo accel
+ * ----------|-------------------
+ * 0x00 | no accel data is stored
+ * 0x01 | accel data is stored
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_accel_enable(
+u8 *v_fifo_accel_u8);
+/*!
+ * @brief This API is used to set stored
+ * accel data in FIFO (all 3 axes) from the register 0x47 bit 6
+ *
+ * @param v_fifo_accel_u8 : The value of fifo accel enble
+ * value | fifo accel
+ * ----------|-------------------
+ * 0x00 | no accel data is stored
+ * 0x01 | accel data is stored
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_accel_enable(
+u8 v_fifo_accel_u8);
+/*!
+ * @brief This API is used to read stored
+ * gyro data in FIFO (all 3 axes) from the resister 0x47 bit 7
+ *
+ *
+ * @param v_fifo_gyro_u8 : The value of fifo gyro enble
+ * value | fifo gyro
+ * ----------|-------------------
+ * 0x00 | no gyro data is stored
+ * 0x01 | gyro data is stored
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_fifo_gyro_enable(
+u8 *v_fifo_gyro_u8);
+/*!
+ * @brief This API is used to set stored
+ * gyro data in FIFO (all 3 axes) from the resister 0x47 bit 7
+ *
+ *
+ * @param v_fifo_gyro_u8 : The value of fifo gyro enble
+ * value | fifo gyro
+ * ----------|-------------------
+ * 0x00 | no gyro data is stored
+ * 0x01 | gyro data is stored
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_fifo_gyro_enable(
+u8 v_fifo_gyro_u8);
+/***************************************************************/
+/**\name FUNCTION FOR MAG I2C ADDRESS SELECTION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * I2C device address of auxiliary mag from the register 0x4B bit 1 to 7
+ *
+ *
+ *
+ *
+ * @param v_i2c_device_addr_u8 : The value of mag I2C device address
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_i2c_device_addr(
+u8 *v_i2c_device_addr_u8);
+/*!
+ * @brief This API is used to set
+ * I2C device address of auxiliary mag from the register 0x4B bit 1 to 7
+ *
+ *
+ *
+ *
+ * @param v_i2c_device_addr_u8 : The value of mag I2C device address
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_i2c_device_addr(
+u8 v_i2c_device_addr_u8);
+/*!
+ * @brief This API is used to read
+ * Burst data length (1,2,6,8 byte) from the register 0x4C bit 0 to 1
+ *
+ *
+ *
+ *
+ * @param v_mag_burst_u8 : The data of mag burst read lenth
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_burst(
+u8 *v_mag_burst_u8);
+/*!
+ * @brief This API is used to set
+ * Burst data length (1,2,6,8 byte) from the register 0x4C bit 0 to 1
+ *
+ *
+ *
+ *
+ * @param v_mag_burst_u8 : The data of mag burst read lenth
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_burst(
+u8 v_mag_burst_u8);
+/***************************************************************/
+/**\name FUNCTION FOR MAG OFFSET */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * trigger-readout offset in units of 2.5 ms. If set to zero,
+ * the offset is maximum, i.e. after readout a trigger
+ * is issued immediately. from the register 0x4C bit 2 to 5
+ *
+ *
+ *
+ *
+ * @param v_mag_offset_u8 : The value of mag offset
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_offset(
+u8 *v_mag_offset_u8);
+/*!
+ * @brief This API is used to set
+ * trigger-readout offset in units of 2.5 ms. If set to zero,
+ * the offset is maximum, i.e. after readout a trigger
+ * is issued immediately. from the register 0x4C bit 2 to 5
+ *
+ *
+ *
+ *
+ * @param v_mag_offset_u8 : The value of mag offset
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_offset(
+u8 v_mag_offset_u8);
+/***************************************************************/
+/**\name FUNCTION FOR MAG MANUAL/AUTO MODE SELECTION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * Enable register access on MAG_IF[2] or MAG_IF[3] writes.
+ * This implies that the DATA registers are not updated with
+ * magnetometer values. Accessing magnetometer requires
+ * the magnetometer in normal mode in PMU_STATUS.
+ * from the register 0x4C bit 7
+ *
+ *
+ *
+ * @param v_mag_manual_u8 : The value of mag manual enable
+ * value | mag manual
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_manual_enable(
+u8 *v_mag_manual_u8);
+/*!
+ * @brief This API is used to set
+ * Enable register access on MAG_IF[2] or MAG_IF[3] writes.
+ * This implies that the DATA registers are not updated with
+ * magnetometer values. Accessing magnetometer requires
+ * the magnetometer in normal mode in PMU_STATUS.
+ * from the register 0x4C bit 7
+ *
+ *
+ *
+ * @param v_mag_manual_u8 : The value of mag manual enable
+ * value | mag manual
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_manual_enable(
+u8 v_mag_manual_u8);
+/***************************************************************/
+/**\name FUNCTIONS FOR MAG READ, WRITE AND WRITE DATA ADDRESS */
+/***************************************************************/
+/*!
+ * @brief This API is used to read data
+ * magnetometer address to read from the register 0x4D bit 0 to 7
+ * @brief It used to provide mag read address of auxiliary mag
+ *
+ *
+ *
+ *
+ * @param v_mag_read_addr_u8 : The value of address need to be read
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_read_addr(
+u8 *v_mag_read_addr_u8);
+/*!
+ * @brief This API is used to set
+ * magnetometer write address from the register 0x4D bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_read_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_read_addr(
+u8 v_mag_read_addr_u8);
+/*!
+ * @brief This API is used to read
+ * magnetometer write address from the register 0x4E bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_write_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_write_addr(
+u8 *v_mag_write_addr_u8);
+/*!
+ * @brief This API is used to set
+ * magnetometer write address from the register 0x4E bit 0 to 7
+ * @brief mag write address writes the address of auxiliary mag to write
+ *
+ *
+ *
+ * @param v_mag_write_addr_u8:
+ * The data of auxiliary mag address to write data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_write_addr(
+u8 v_mag_write_addr_u8);
+/*!
+ * @brief This API is used to read magnetometer write data
+ * form the resister 0x4F bit 0 to 7
+ * @brief This writes the data will be wrote to mag
+ *
+ *
+ *
+ * @param v_mag_write_data_u8: The value of mag data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_mag_write_data(
+u8 *v_mag_write_data_u8);
+/*!
+ * @brief This API is used to set magnetometer write data
+ * form the resister 0x4F bit 0 to 7
+ * @brief This writes the data will be wrote to mag
+ *
+ *
+ *
+ * @param v_mag_write_data_u8: The value of mag data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_mag_write_data(
+u8 v_mag_write_data_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT ENABLE OF
+ANY-MOTION XYZ, DOUBLE AND SINGLE TAP, ORIENT AND FLAT */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * interrupt enable from the register 0x50 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_ANY_MOTION_X_ENABLE
+ * 1 | SMI130_ANY_MOTION_Y_ENABLE
+ * 2 | SMI130_ANY_MOTION_Z_ENABLE
+ * 3 | SMI130_DOUBLE_TAP_ENABLE
+ * 4 | SMI130_SINGLE_TAP_ENABLE
+ * 5 | SMI130_ORIENT_ENABLE
+ * 6 | SMI130_FLAT_ENABLE
+ *
+ * @param v_intr_enable_zero_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_enable_0(
+u8 enable, u8 *v_intr_enable_zero_u8);
+/*!
+ * @brief This API is used to set
+ * interrupt enable from the register 0x50 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_ANY_MOTION_X_ENABLE
+ * 1 | SMI130_ANY_MOTION_Y_ENABLE
+ * 2 | SMI130_ANY_MOTION_Z_ENABLE
+ * 3 | SMI130_DOUBLE_TAP_ENABLE
+ * 4 | SMI130_SINGLE_TAP_ENABLE
+ * 5 | SMI130_ORIENT_ENABLE
+ * 6 | SMI130_FLAT_ENABLE
+ *
+ * @param v_intr_enable_zero_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_enable_0(
+u8 enable, u8 v_intr_enable_zero_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT ENABLE OF
+HIGH_G XYZ, LOW_G, DATA READY, FIFO FULL AND FIFO WATER MARK */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * interrupt enable byte1 from the register 0x51 bit 0 to 6
+ * @brief It read the high_g_x,high_g_y,high_g_z,low_g_enable
+ * data ready, fifo full and fifo water mark.
+ *
+ *
+ *
+ * @param v_enable_u8 : The value of interrupt enable
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_HIGH_G_X_ENABLE
+ * 1 | SMI130_HIGH_G_Y_ENABLE
+ * 2 | SMI130_HIGH_G_Z_ENABLE
+ * 3 | SMI130_LOW_G_ENABLE
+ * 4 | SMI130_DATA_RDY_ENABLE
+ * 5 | SMI130_FIFO_FULL_ENABLE
+ * 6 | SMI130_FIFO_WM_ENABLE
+ *
+ * @param v_intr_enable_1_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_enable_1(
+u8 enable, u8 *v_intr_enable_1_u8);
+/*!
+ * @brief This API is used to set
+ * interrupt enable byte1 from the register 0x51 bit 0 to 6
+ * @brief It read the high_g_x,high_g_y,high_g_z,low_g_enable
+ * data ready, fifo full and fifo water mark.
+ *
+ *
+ *
+ * @param v_enable_u8 : The value of interrupt enable
+ * @param v_enable_u8 : Value to decided to select interrupt
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_HIGH_G_X_ENABLE
+ * 1 | SMI130_HIGH_G_Y_ENABLE
+ * 2 | SMI130_HIGH_G_Z_ENABLE
+ * 3 | SMI130_LOW_G_ENABLE
+ * 4 | SMI130_DATA_RDY_ENABLE
+ * 5 | SMI130_FIFO_FULL_ENABLE
+ * 6 | SMI130_FIFO_WM_ENABLE
+ *
+ * @param v_intr_enable_1_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_enable_1(
+u8 enable, u8 v_intr_enable_1_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT ENABLE OF
+NO MOTION XYZ */
+/***************************************************************/
+/*!
+ * @brief This API is used to read
+ * interrupt enable byte2 from the register bit 0x52 bit 0 to 3
+ * @brief It reads no motion x,y and z
+ *
+ *
+ *
+ * @param v_enable_u8: The value of interrupt enable
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_NOMOTION_X_ENABLE
+ * 1 | SMI130_NOMOTION_Y_ENABLE
+ * 2 | SMI130_NOMOTION_Z_ENABLE
+ *
+ * @param v_intr_enable_2_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_enable_2(
+u8 enable, u8 *v_intr_enable_2_u8);
+/*!
+ * @brief This API is used to set
+ * interrupt enable byte2 from the register bit 0x52 bit 0 to 3
+ * @brief It reads no motion x,y and z
+ *
+ *
+ *
+ * @param v_enable_u8: The value of interrupt enable
+ * v_enable_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_NOMOTION_X_ENABLE
+ * 1 | SMI130_NOMOTION_Y_ENABLE
+ * 2 | SMI130_NOMOTION_Z_ENABLE
+ *
+ * @param v_intr_enable_2_u8 : The interrupt enable value
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_enable_2(
+u8 enable, u8 v_intr_enable_2_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT ENABLE OF
+ STEP DETECTOR */
+/***************************************************************/
+ /*!
+ * @brief This API is used to read
+ * interrupt enable step detector interrupt from
+ * the register bit 0x52 bit 3
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The value of step detector interrupt enable
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_step_detector_enable(
+u8 *v_step_intr_u8);
+ /*!
+ * @brief This API is used to set
+ * interrupt enable step detector interrupt from
+ * the register bit 0x52 bit 3
+ *
+ *
+ *
+ *
+ * @param v_step_intr_u8 : The value of step detector interrupt enable
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_step_detector_enable(
+u8 v_step_intr_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT CONTROL */
+/***************************************************************/
+/*!
+ * @brief Configure trigger condition of interrupt1
+ * and interrupt2 pin from the register 0x53
+ * @brief interrupt1 - bit 0
+ * @brief interrupt2 - bit 4
+ *
+ * @param v_channel_u8: The value of edge trigger selection
+ * v_channel_u8 | Edge trigger
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_EDGE_CTRL
+ * 1 | SMI130_INTR2_EDGE_CTRL
+ *
+ * @param v_intr_edge_ctrl_u8 : The value of edge trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_EDGE
+ * 0x00 | SMI130_LEVEL
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_edge_ctrl(
+u8 v_channel_u8, u8 *v_intr_edge_ctrl_u8);
+/*!
+ * @brief Configure trigger condition of interrupt1
+ * and interrupt2 pin from the register 0x53
+ * @brief interrupt1 - bit 0
+ * @brief interrupt2 - bit 4
+ *
+ * @param v_channel_u8: The value of edge trigger selection
+ * v_channel_u8 | Edge trigger
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_EDGE_CTRL
+ * 1 | SMI130_INTR2_EDGE_CTRL
+ *
+ * @param v_intr_edge_ctrl_u8 : The value of edge trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_EDGE
+ * 0x00 | SMI130_LEVEL
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_edge_ctrl(
+u8 v_channel_u8, u8 v_intr_edge_ctrl_u8);
+/*!
+ * @brief API used for get the Configure level condition of interrupt1
+ * and interrupt2 pin form the register 0x53
+ * @brief interrupt1 - bit 1
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of level condition selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_LEVEL
+ * 1 | SMI130_INTR2_LEVEL
+ *
+ * @param v_intr_level_u8 : The value of level of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_LEVEL_HIGH
+ * 0x00 | SMI130_LEVEL_LOW
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_level(
+u8 v_channel_u8, u8 *v_intr_level_u8);
+/*!
+ * @brief API used for set the Configure level condition of interrupt1
+ * and interrupt2 pin form the register 0x53
+ * @brief interrupt1 - bit 1
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of level condition selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_LEVEL
+ * 1 | SMI130_INTR2_LEVEL
+ *
+ * @param v_intr_level_u8 : The value of level of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_LEVEL_HIGH
+ * 0x00 | SMI130_LEVEL_LOW
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_level(
+u8 v_channel_u8, u8 v_intr_level_u8);
+/*!
+ * @brief API used to get configured output enable of interrupt1
+ * and interrupt2 from the register 0x53
+ * @brief interrupt1 - bit 2
+ * @brief interrupt2 - bit 6
+ *
+ *
+ * @param v_channel_u8: The value of output type enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_OUTPUT_TYPE
+ * 1 | SMI130_INTR2_OUTPUT_TYPE
+ *
+ * @param v_intr_output_type_u8 :
+ * The value of output type of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_OPEN_DRAIN
+ * 0x00 | SMI130_PUSH_PULL
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_output_type(
+u8 v_channel_u8, u8 *v_intr_output_type_u8);
+/*!
+ * @brief API used to set output enable of interrupt1
+ * and interrupt2 from the register 0x53
+ * @brief interrupt1 - bit 2
+ * @brief interrupt2 - bit 6
+ *
+ *
+ * @param v_channel_u8: The value of output type enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_OUTPUT_TYPE
+ * 1 | SMI130_INTR2_OUTPUT_TYPE
+ *
+ * @param v_intr_output_type_u8 :
+ * The value of output type of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_OPEN_DRAIN
+ * 0x00 | SMI130_PUSH_PULL
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_output_type(
+u8 v_channel_u8, u8 v_intr_output_type_u8);
+ /*!
+ * @brief API used to get the Output enable for interrupt1
+ * and interrupt1 pin from the register 0x53
+ * @brief interrupt1 - bit 3
+ * @brief interrupt2 - bit 7
+ *
+ * @param v_channel_u8: The value of output enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_OUTPUT_TYPE
+ * 1 | SMI130_INTR2_OUTPUT_TYPE
+ *
+ * @param v_output_enable_u8 :
+ * The value of output enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_INPUT
+ * 0x00 | SMI130_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_output_enable(
+u8 v_channel_u8, u8 *v_output_enable_u8);
+ /*!
+ * @brief API used to set the Output enable for interrupt1
+ * and interrupt1 pin from the register 0x53
+ * @brief interrupt1 - bit 3
+ * @brief interrupt2 - bit 7
+ *
+ * @param v_channel_u8: The value of output enable selection
+ * v_channel_u8 | level selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_OUTPUT_TYPE
+ * 1 | SMI130_INTR2_OUTPUT_TYPE
+ *
+ * @param v_output_enable_u8 :
+ * The value of output enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_INPUT
+ * 0x00 | SMI130_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_output_enable(
+u8 v_channel_u8, u8 v_output_enable_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT LATCH INTERRUPT */
+/***************************************************************/
+/*!
+* @brief This API is used to get the latch duration
+* from the register 0x54 bit 0 to 3
+* @brief This latch selection is not applicable for data ready,
+* orient_mblation and flat interrupts.
+*
+*
+*
+* @param v_latch_intr_u8 : The value of latch duration
+* Latch Duration | value
+* --------------------------------------|------------------
+* SMI130_LATCH_DUR_NONE | 0x00
+* SMI130_LATCH_DUR_312_5_MICRO_SEC | 0x01
+* SMI130_LATCH_DUR_625_MICRO_SEC | 0x02
+* SMI130_LATCH_DUR_1_25_MILLI_SEC | 0x03
+* SMI130_LATCH_DUR_2_5_MILLI_SEC | 0x04
+* SMI130_LATCH_DUR_5_MILLI_SEC | 0x05
+* SMI130_LATCH_DUR_10_MILLI_SEC | 0x06
+* SMI130_LATCH_DUR_20_MILLI_SEC | 0x07
+* SMI130_LATCH_DUR_40_MILLI_SEC | 0x08
+* SMI130_LATCH_DUR_80_MILLI_SEC | 0x09
+* SMI130_LATCH_DUR_160_MILLI_SEC | 0x0A
+* SMI130_LATCH_DUR_320_MILLI_SEC | 0x0B
+* SMI130_LATCH_DUR_640_MILLI_SEC | 0x0C
+* SMI130_LATCH_DUR_1_28_SEC | 0x0D
+* SMI130_LATCH_DUR_2_56_SEC | 0x0E
+* SMI130_LATCHED | 0x0F
+*
+*
+*
+* @return results of bus communication function
+* @retval 0 -> Success
+* @retval -1 -> Error
+*
+*
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_latch_intr(
+u8 *v_latch_intr_u8);
+/*!
+* @brief This API is used to set the latch duration
+* from the register 0x54 bit 0 to 3
+* @brief This latch selection is not applicable for data ready,
+* orient_mblation and flat interrupts.
+*
+*
+*
+* @param v_latch_intr_u8 : The value of latch duration
+* Latch Duration | value
+* --------------------------------------|------------------
+* SMI130_LATCH_DUR_NONE | 0x00
+* SMI130_LATCH_DUR_312_5_MICRO_SEC | 0x01
+* SMI130_LATCH_DUR_625_MICRO_SEC | 0x02
+* SMI130_LATCH_DUR_1_25_MILLI_SEC | 0x03
+* SMI130_LATCH_DUR_2_5_MILLI_SEC | 0x04
+* SMI130_LATCH_DUR_5_MILLI_SEC | 0x05
+* SMI130_LATCH_DUR_10_MILLI_SEC | 0x06
+* SMI130_LATCH_DUR_20_MILLI_SEC | 0x07
+* SMI130_LATCH_DUR_40_MILLI_SEC | 0x08
+* SMI130_LATCH_DUR_80_MILLI_SEC | 0x09
+* SMI130_LATCH_DUR_160_MILLI_SEC | 0x0A
+* SMI130_LATCH_DUR_320_MILLI_SEC | 0x0B
+* SMI130_LATCH_DUR_640_MILLI_SEC | 0x0C
+* SMI130_LATCH_DUR_1_28_SEC | 0x0D
+* SMI130_LATCH_DUR_2_56_SEC | 0x0E
+* SMI130_LATCHED | 0x0F
+*
+*
+*
+* @return results of bus communication function
+* @retval 0 -> Success
+* @retval -1 -> Error
+*
+*
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_latch_intr(
+u8 v_latch_intr_u8);
+/*!
+ * @brief API used to get input enable for interrupt1
+ * and interrupt2 pin from the register 0x54
+ * @brief interrupt1 - bit 4
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of input enable selection
+ * v_channel_u8 | input selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_INPUT_ENABLE
+ * 1 | SMI130_INTR2_INPUT_ENABLE
+ *
+ * @param v_input_en_u8 :
+ * The value of input enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_INPUT
+ * 0x00 | SMI130_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_input_enable(
+u8 v_channel_u8, u8 *v_input_en_u8);
+/*!
+ * @brief API used to set input enable for interrupt1
+ * and interrupt2 pin from the register 0x54
+ * @brief interrupt1 - bit 4
+ * @brief interrupt2 - bit 5
+ *
+ * @param v_channel_u8: The value of input enable selection
+ * v_channel_u8 | input selection
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_INPUT_ENABLE
+ * 1 | SMI130_INTR2_INPUT_ENABLE
+ *
+ * @param v_input_en_u8 :
+ * The value of input enable of interrupt enable
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x01 | SMI130_INPUT
+ * 0x00 | SMI130_OUTPUT
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_input_enable(
+u8 v_channel_u8, u8 v_input_en_u8);
+/***************************************************************/
+/**\name FUNCTION FOR INTERRUPT1 AND INTERRUPT2 MAPPING */
+/***************************************************************/
+ /*!
+ * @brief reads the Low g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 0 in the register 0x55
+ * @brief interrupt2 bit 0 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of low_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_LOW_G
+ * 1 | SMI130_INTR2_MAP_LOW_G
+ *
+ * @param v_intr_low_g_u8 : The value of low_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g(
+u8 v_channel_u8, u8 *v_intr_low_g_u8);
+ /*!
+ * @brief set the Low g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 0 in the register 0x55
+ * @brief interrupt2 bit 0 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of low_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_LOW_G
+ * 1 | SMI130_INTR2_MAP_LOW_G
+ *
+ * @param v_intr_low_g_u8 : The value of low_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g(
+u8 v_channel_u8, u8 v_intr_low_g_u8);
+/*!
+ * @brief Reads the HIGH g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 1 in the register 0x55
+ * @brief interrupt2 bit 1 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of high_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_HIGH_G
+ * 1 | SMI130_INTR2_MAP_HIGH_G
+ *
+ * @param v_intr_high_g_u8 : The value of high_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_high_g(
+u8 v_channel_u8, u8 *v_intr_high_g_u8);
+/*!
+ * @brief Write the HIGH g interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 1 in the register 0x55
+ * @brief interrupt2 bit 1 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of high_g selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_HIGH_G
+ * 1 | SMI130_INTR2_MAP_HIGH_G
+ *
+ * @param v_intr_high_g_u8 : The value of high_g enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_high_g(
+u8 v_channel_u8, u8 v_intr_high_g_u8);
+/*!
+ * @brief Reads the Any motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 2 in the register 0x55
+ * @brief interrupt2 bit 2 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of any motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_ANY_MOTION
+ * 1 | SMI130_INTR2_MAP_ANY_MOTION
+ *
+ * @param v_intr_any_motion_u8 : The value of any motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_any_motion(
+u8 v_channel_u8, u8 *v_intr_any_motion_u8);
+/*!
+ * @brief Write the Any motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 2 in the register 0x55
+ * @brief interrupt2 bit 2 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of any motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_ANY_MOTION
+ * 1 | SMI130_INTR2_MAP_ANY_MOTION
+ *
+ * @param v_intr_any_motion_u8 : The value of any motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_any_motion(
+u8 v_channel_u8, u8 v_intr_any_motion_u8);
+/*!
+ * @brief Reads the No motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 3 in the register 0x55
+ * @brief interrupt2 bit 3 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of no motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_NOMO
+ * 1 | SMI130_INTR2_MAP_NOMO
+ *
+ * @param v_intr_nomotion_u8 : The value of no motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_nomotion(
+u8 v_channel_u8, u8 *v_intr_nomotion_u8);
+/*!
+ * @brief Write the No motion interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 3 in the register 0x55
+ * @brief interrupt2 bit 3 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of no motion selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_NOMO
+ * 1 | SMI130_INTR2_MAP_NOMO
+ *
+ * @param v_intr_nomotion_u8 : The value of no motion enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_nomotion(
+u8 v_channel_u8, u8 v_intr_nomotion_u8);
+/*!
+ * @brief Reads the Double Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 4 in the register 0x55
+ * @brief interrupt2 bit 4 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of double tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_DOUBLE_TAP
+ * 1 | SMI130_INTR2_MAP_DOUBLE_TAP
+ *
+ * @param v_intr_double_tap_u8 : The value of double tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_double_tap(
+u8 v_channel_u8, u8 *v_intr_double_tap_u8);
+/*!
+ * @brief Write the Double Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 4 in the register 0x55
+ * @brief interrupt2 bit 4 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of double tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_DOUBLE_TAP
+ * 1 | SMI130_INTR2_MAP_DOUBLE_TAP
+ *
+ * @param v_intr_double_tap_u8 : The value of double tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_double_tap(
+u8 v_channel_u8, u8 v_intr_double_tap_u8);
+/*!
+ * @brief Reads the Single Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 5 in the register 0x55
+ * @brief interrupt2 bit 5 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of single tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_SINGLE_TAP
+ * 1 | SMI130_INTR2_MAP_SINGLE_TAP
+ *
+ * @param v_intr_single_tap_u8 : The value of single tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_single_tap(
+u8 v_channel_u8, u8 *v_intr_single_tap_u8);
+/*!
+ * @brief Write the Single Tap interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 5 in the register 0x55
+ * @brief interrupt2 bit 5 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of single tap interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_SINGLE_TAP
+ * 1 | SMI130_INTR2_MAP_SINGLE_TAP
+ *
+ * @param v_intr_single_tap_u8 : The value of single tap enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_single_tap(
+u8 v_channel_u8, u8 v_intr_single_tap_u8);
+/*!
+ * @brief Reads the Orient interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 6 in the register 0x55
+ * @brief interrupt2 bit 6 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of orient_mbl interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_ORIENT
+ * 1 | SMI130_INTR2_MAP_ORIENT
+ *
+ * @param v_intr_orient_mbl_u8 : The value of orient_mbl enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl(
+u8 v_channel_u8, u8 *v_intr_orient_mbl_u8);
+/*!
+ * @brief Write the Orient interrupt
+ * interrupt mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 6 in the register 0x55
+ * @brief interrupt2 bit 6 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of orient_mbl interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_ORIENT
+ * 1 | SMI130_INTR2_MAP_ORIENT
+ *
+ * @param v_intr_orient_mbl_u8 : The value of orient_mbl enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl(
+u8 v_channel_u8, u8 v_intr_orient_mbl_u8);
+ /*!
+ * @brief Reads the Flat interrupt
+ * mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 7 in the register 0x55
+ * @brief interrupt2 bit 7 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of flat interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FLAT
+ * 1 | SMI130_INTR2_MAP_FLAT
+ *
+ * @param v_intr_flat_u8 : The value of flat enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_flat(
+u8 v_channel_u8, u8 *v_intr_flat_u8);
+ /*!
+ * @brief Write the Flat interrupt
+ * mapped to interrupt1
+ * and interrupt2 from the register 0x55 and 0x57
+ * @brief interrupt1 bit 7 in the register 0x55
+ * @brief interrupt2 bit 7 in the register 0x57
+ *
+ *
+ * @param v_channel_u8: The value of flat interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FLAT
+ * 1 | SMI130_INTR2_MAP_FLAT
+ *
+ * @param v_intr_flat_u8 : The value of flat enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_flat(
+u8 v_channel_u8, u8 v_intr_flat_u8);
+/*!
+ * @brief Reads PMU trigger interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 0 and 4
+ * @brief interrupt1 bit 0 in the register 0x56
+ * @brief interrupt2 bit 4 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of pmu trigger selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_PMUTRIG
+ * 1 | SMI130_INTR2_MAP_PMUTRIG
+ *
+ * @param v_intr_pmu_trig_u8 : The value of pmu trigger enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_pmu_trig(
+u8 v_channel_u8, u8 *v_intr_pmu_trig_u8);
+/*!
+ * @brief Write PMU trigger interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 0 and 4
+ * @brief interrupt1 bit 0 in the register 0x56
+ * @brief interrupt2 bit 4 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of pmu trigger selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_PMUTRIG
+ * 1 | SMI130_INTR2_MAP_PMUTRIG
+ *
+ * @param v_intr_pmu_trig_u8 : The value of pmu trigger enable
+ * value | trigger enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_pmu_trig(
+u8 v_channel_u8, u8 v_intr_pmu_trig_u8);
+/*!
+ * @brief Reads FIFO Full interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 5 and 1
+ * @brief interrupt1 bit 5 in the register 0x56
+ * @brief interrupt2 bit 1 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo full interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FIFO_FULL
+ * 1 | SMI130_INTR2_MAP_FIFO_FULL
+ *
+ * @param v_intr_fifo_full_u8 : The value of fifo full interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_fifo_full(
+u8 v_channel_u8, u8 *v_intr_fifo_full_u8);
+/*!
+ * @brief Write FIFO Full interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 5 and 1
+ * @brief interrupt1 bit 5 in the register 0x56
+ * @brief interrupt2 bit 1 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo full interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FIFO_FULL
+ * 1 | SMI130_INTR2_MAP_FIFO_FULL
+ *
+ * @param v_intr_fifo_full_u8 : The value of fifo full interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_fifo_full(
+u8 v_channel_u8, u8 v_intr_fifo_full_u8);
+/*!
+ * @brief Reads FIFO Watermark interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 6 and 2
+ * @brief interrupt1 bit 6 in the register 0x56
+ * @brief interrupt2 bit 2 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo Watermark interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FIFO_WM
+ * 1 | SMI130_INTR2_MAP_FIFO_WM
+ *
+ * @param v_intr_fifo_wm_u8 : The value of fifo Watermark interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_fifo_wm(
+u8 v_channel_u8, u8 *v_intr_fifo_wm_u8);
+/*!
+ * @brief Write FIFO Watermark interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56 bit 6 and 2
+ * @brief interrupt1 bit 6 in the register 0x56
+ * @brief interrupt2 bit 2 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of fifo Watermark interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_FIFO_WM
+ * 1 | SMI130_INTR2_MAP_FIFO_WM
+ *
+ * @param v_intr_fifo_wm_u8 : The value of fifo Watermark interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_fifo_wm(
+u8 v_channel_u8, u8 v_intr_fifo_wm_u8);
+/*!
+ * @brief Reads Data Ready interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56
+ * @brief interrupt1 bit 7 in the register 0x56
+ * @brief interrupt2 bit 3 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of data ready interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_DATA_RDY
+ * 1 | SMI130_INTR2_MAP_DATA_RDY
+ *
+ * @param v_intr_data_rdy_u8 : The value of data ready interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_data_rdy(
+u8 v_channel_u8, u8 *v_intr_data_rdy_u8);
+/*!
+ * @brief Write Data Ready interrupt mapped to interrupt1
+ * and interrupt2 form the register 0x56
+ * @brief interrupt1 bit 7 in the register 0x56
+ * @brief interrupt2 bit 3 in the register 0x56
+ *
+ *
+ * @param v_channel_u8: The value of data ready interrupt selection
+ * v_channel_u8 | interrupt
+ * ---------------|---------------
+ * 0 | SMI130_INTR1_MAP_DATA_RDY
+ * 1 | SMI130_INTR2_MAP_DATA_RDY
+ *
+ * @param v_intr_data_rdy_u8 : The value of data ready interrupt enable
+ * value | interrupt enable
+ * ----------|-------------------
+ * 0x01 | SMI130_ENABLE
+ * 0x00 | SMI130_DISABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_data_rdy(
+u8 v_channel_u8, u8 v_intr_data_rdy_u8);
+/***************************************************************/
+/**\name FUNCTION FOR TAP SOURCE CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API reads data source for the interrupt
+ * engine for the single and double tap interrupts from the register
+ * 0x58 bit 3
+ *
+ *
+ * @param v_tap_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_source(
+u8 *v_tap_source_u8);
+ /*!
+ * @brief This API write data source for the interrupt
+ * engine for the single and double tap interrupts from the register
+ * 0x58 bit 3
+ *
+ *
+ * @param v_tap_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_source(
+u8 v_tap_source_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G AND HIGH_G SOURCE CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API Reads Data source for the
+ * interrupt engine for the low and high g interrupts
+ * from the register 0x58 bit 7
+ *
+ * @param v_low_high_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_high_source(
+u8 *v_low_high_source_u8);
+ /*!
+ * @brief This API write Data source for the
+ * interrupt engine for the low and high g interrupts
+ * from the register 0x58 bit 7
+ *
+ * @param v_low_high_source_u8 : The value of the tap source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_high_source(
+u8 v_low_high_source_u8);
+/***************************************************************/
+/**\name FUNCTION FOR MOTION SOURCE CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API reads Data source for the
+ * interrupt engine for the nomotion and anymotion interrupts
+ * from the register 0x59 bit 7
+ *
+ * @param v_motion_source_u8 :
+ * The value of the any/no motion interrupt source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_motion_source(
+u8 *v_motion_source_u8);
+ /*!
+ * @brief This API write Data source for the
+ * interrupt engine for the nomotion and anymotion interrupts
+ * from the register 0x59 bit 7
+ *
+ * @param v_motion_source_u8 :
+ * The value of the any/no motion interrupt source
+ * value | Description
+ * ----------|-------------------
+ * 0x01 | UNFILTER_DATA
+ * 0x00 | FILTER_DATA
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_motion_source(
+u8 v_motion_source_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G DURATION CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read the low_g duration from register
+ * 0x5A bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_durn_u8 : The value of low_g duration
+ *
+ * @note Low_g duration trigger trigger delay according to
+ * "(v_low_g_durn_u8 * 2.5)ms" in a range from 2.5ms to 640ms.
+ * the default corresponds delay is 20ms
+ * @note When low_g data source of interrupt is unfiltered
+ * the sensor must not be in low power mode
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g_durn(
+u8 *v_low_durn_u8);
+ /*!
+ * @brief This API is used to write the low_g duration from register
+ * 0x5A bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_durn_u8 : The value of low_g duration
+ *
+ * @note Low_g duration trigger trigger delay according to
+ * "(v_low_g_durn_u8 * 2.5)ms" in a range from 2.5ms to 640ms.
+ * the default corresponds delay is 20ms
+ * @note When low_g data source of interrupt is unfiltered
+ * the sensor must not be in low power mode
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g_durn(
+u8 v_low_durn_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G THRESH CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read Threshold
+ * definition for the low-g interrupt from the register 0x5B bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_thres_u8 : The value of low_g threshold
+ *
+ * @note Low_g interrupt trigger threshold according to
+ * (v_low_g_thres_u8 * 7.81)mg for v_low_g_thres_u8 > 0
+ * 3.91 mg for v_low_g_thres_u8 = 0
+ * The threshold range is form 3.91mg to 2.000mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g_thres(
+u8 *v_low_g_thres_u8);
+/*!
+ * @brief This API is used to write Threshold
+ * definition for the low-g interrupt from the register 0x5B bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_low_g_thres_u8 : The value of low_g threshold
+ *
+ * @note Low_g interrupt trigger threshold according to
+ * (v_low_g_thres_u8 * 7.81)mg for v_low_g_thres_u8 > 0
+ * 3.91 mg for v_low_g_thres_u8 = 0
+ * The threshold range is form 3.91mg to 2.000mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g_thres(
+u8 v_low_g_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G HYSTERESIS CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API Reads Low-g interrupt hysteresis
+ * from the register 0x5C bit 0 to 1
+ *
+ * @param v_low_hyst_u8 :The value of low_g hysteresis
+ *
+ * @note Low_g hysteresis calculated by v_low_hyst_u8*125 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g_hyst(
+u8 *v_low_hyst_u8);
+ /*!
+ * @brief This API write Low-g interrupt hysteresis
+ * from the register 0x5C bit 0 to 1
+ *
+ * @param v_low_hyst_u8 :The value of low_g hysteresis
+ *
+ * @note Low_g hysteresis calculated by v_low_hyst_u8*125 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g_hyst(
+u8 v_low_hyst_u8);
+/***************************************************************/
+/**\name FUNCTION FOR LOW_G MODE CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API reads Low-g interrupt mode
+ * from the register 0x5C bit 2
+ *
+ * @param v_low_g_mode_u8 : The value of low_g mode
+ * Value | Description
+ * ----------|-----------------
+ * 0 | single-axis
+ * 1 | axis-summing
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_low_g_mode(
+u8 *v_low_g_mode_u8);
+/*!
+ * @brief This API write Low-g interrupt mode
+ * from the register 0x5C bit 2
+ *
+ * @param v_low_g_mode_u8 : The value of low_g mode
+ * Value | Description
+ * ----------|-----------------
+ * 0 | single-axis
+ * 1 | axis-summing
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_low_g_mode(
+u8 v_low_g_mode_u8);
+/***************************************************************/
+/**\name FUNCTION FOR HIGH_G HYST CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API reads High-g interrupt hysteresis
+ * from the register 0x5C bit 6 and 7
+ *
+ * @param v_high_g_hyst_u8 : The value of high hysteresis
+ *
+ * @note High_g hysteresis changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g hysteresis
+ * ----------------|---------------------
+ * 2g | high_hy*125 mg
+ * 4g | high_hy*250 mg
+ * 8g | high_hy*500 mg
+ * 16g | high_hy*1000 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_high_g_hyst(
+u8 *v_high_g_hyst_u8);
+/*!
+ * @brief This API write High-g interrupt hysteresis
+ * from the register 0x5C bit 6 and 7
+ *
+ * @param v_high_g_hyst_u8 : The value of high hysteresis
+ *
+ * @note High_g hysteresis changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g hysteresis
+ * ----------------|---------------------
+ * 2g | high_hy*125 mg
+ * 4g | high_hy*250 mg
+ * 8g | high_hy*500 mg
+ * 16g | high_hy*1000 mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_high_g_hyst(
+u8 v_high_g_hyst_u8);
+/***************************************************************/
+/**\name FUNCTION FOR HIGH_G DURATION CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read Delay
+ * time definition for the high-g interrupt from the register
+ * 0x5D bit 0 to 7
+ *
+ *
+ *
+ * @param v_high_g_durn_u8 : The value of high duration
+ *
+ * @note High_g interrupt delay triggered according to
+ * v_high_g_durn_u8 * 2.5ms in a range from 2.5ms to 640ms
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_high_g_durn(
+u8 *v_high_g_durn_u8);
+/*!
+ * @brief This API is used to write Delay
+ * time definition for the high-g interrupt from the register
+ * 0x5D bit 0 to 7
+ *
+ *
+ *
+ * @param v_high_g_durn_u8 : The value of high duration
+ *
+ * @note High_g interrupt delay triggered according to
+ * v_high_g_durn_u8 * 2.5ms in a range from 2.5ms to 640ms
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_high_g_durn(
+u8 v_high_g_durn_u8);
+/***************************************************************/
+/**\name FUNCTION FOR HIGH_G THRESHOLD CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read Threshold
+ * definition for the high-g interrupt from the register 0x5E 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_high_g_thres_u8 : Pointer holding the value of Threshold
+ * @note High_g threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | v_high_g_thres_u8*7.81 mg
+ * 4g | v_high_g_thres_u8*15.63 mg
+ * 8g | v_high_g_thres_u8*31.25 mg
+ * 16g | v_high_g_thres_u8*62.5 mg
+ * @note when v_high_g_thres_u8 = 0
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | 3.91 mg
+ * 4g | 7.81 mg
+ * 8g | 15.63 mg
+ * 16g | 31.25 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_high_g_thres(
+u8 *v_high_g_thres_u8);
+/*!
+ * @brief This API is used to write Threshold
+ * definition for the high-g interrupt from the register 0x5E 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_high_g_thres_u8 : Pointer holding the value of Threshold
+ * @note High_g threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | v_high_g_thres_u8*7.81 mg
+ * 4g | v_high_g_thres_u8*15.63 mg
+ * 8g | v_high_g_thres_u8*31.25 mg
+ * 16g | v_high_g_thres_u8*62.5 mg
+ * @note when v_high_g_thres_u8 = 0
+ * accel_range | high_g threshold
+ * ----------------|---------------------
+ * 2g | 3.91 mg
+ * 4g | 7.81 mg
+ * 8g | 15.63 mg
+ * 16g | 31.25 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_high_g_thres(
+u8 v_high_g_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ANY MOTION DURATION CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API reads any motion duration
+ * from the register 0x5F bit 0 and 1
+ *
+ * @param v_any_motion_durn_u8 : The value of any motion duration
+ *
+ * @note Any motion duration can be calculated by "v_any_motion_durn_u8 + 1"
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_any_motion_durn(
+u8 *v_any_motion_durn_u8);
+/*!
+ * @brief This API write any motion duration
+ * from the register 0x5F bit 0 and 1
+ *
+ * @param v_any_motion_durn_u8 : The value of any motion duration
+ *
+ * @note Any motion duration can be calculated by "v_any_motion_durn_u8 + 1"
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_any_motion_durn(
+u8 nomotion);
+/***************************************************************/
+/**\name FUNCTION FOR SLOW NO MOTION DURATION CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API read Slow/no-motion
+ * interrupt trigger delay duration from the register 0x5F bit 2 to 7
+ *
+ * @param v_slow_no_motion_u8 :The value of slow no motion duration
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * @note v_slow_no_motion_u8(5:4)=0b00 ->
+ * [v_slow_no_motion_u8(3:0) + 1] * 1.28s (1.28s-20.48s)
+ * @note v_slow_no_motion_u8(5:4)=1 ->
+ * [v_slow_no_motion_u8(3:0)+5] * 5.12s (25.6s-102.4s)
+ * @note v_slow_no_motion_u8(5)='1' ->
+ * [(v_slow_no_motion_u8:0)+11] * 10.24s (112.64s-430.08s);
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_slow_no_motion_durn(
+u8 *v_slow_no_motion_u8);
+ /*!
+ * @brief This API write Slow/no-motion
+ * interrupt trigger delay duration from the register 0x5F bit 2 to 7
+ *
+ * @param v_slow_no_motion_u8 :The value of slow no motion duration
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ * @note
+ * @note v_slow_no_motion_u8(5:4)=0b00 ->
+ * [v_slow_no_motion_u8(3:0) + 1] * 1.28s (1.28s-20.48s)
+ * @note v_slow_no_motion_u8(5:4)=1 ->
+ * [v_slow_no_motion_u8(3:0)+5] * 5.12s (25.6s-102.4s)
+ * @note v_slow_no_motion_u8(5)='1' ->
+ * [(v_slow_no_motion_u8:0)+11] * 10.24s (112.64s-430.08s);
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_slow_no_motion_durn(
+u8 v_slow_no_motion_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ANY MOTION THRESHOLD CONFIGURATION */
+/***************************************************************/
+/*!
+ * @brief This API is used to read threshold
+ * definition for the any-motion interrupt
+ * from the register 0x60 bit 0 to 7
+ *
+ *
+ * @param v_any_motion_thres_u8 : The value of any motion threshold
+ *
+ * @note any motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | v_any_motion_thres_u8*3.91 mg
+ * 4g | v_any_motion_thres_u8*7.81 mg
+ * 8g | v_any_motion_thres_u8*15.63 mg
+ * 16g | v_any_motion_thres_u8*31.25 mg
+ * @note when v_any_motion_thres_u8 = 0
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_any_motion_thres(
+u8 *v_any_motion_thres_u8);
+/*!
+ * @brief This API is used to write threshold
+ * definition for the any-motion interrupt
+ * from the register 0x60 bit 0 to 7
+ *
+ *
+ * @param v_any_motion_thres_u8 : The value of any motion threshold
+ *
+ * @note any motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | v_any_motion_thres_u8*3.91 mg
+ * 4g | v_any_motion_thres_u8*7.81 mg
+ * 8g | v_any_motion_thres_u8*15.63 mg
+ * 16g | v_any_motion_thres_u8*31.25 mg
+ * @note when v_any_motion_thres_u8 = 0
+ * accel_range | any motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_any_motion_thres(
+u8 v_any_motion_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR SLO/NO MOTION THRESHOLD CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API is used to read threshold
+ * for the slow/no-motion interrupt
+ * from the register 0x61 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_slow_no_motion_thres_u8 : The value of slow no motion threshold
+ * @note slow no motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | v_slow_no_motion_thres_u8*3.91 mg
+ * 4g | v_slow_no_motion_thres_u8*7.81 mg
+ * 8g | v_slow_no_motion_thres_u8*15.63 mg
+ * 16g | v_slow_no_motion_thres_u8*31.25 mg
+ * @note when v_slow_no_motion_thres_u8 = 0
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_slow_no_motion_thres(
+u8 *v_slow_no_motion_thres_u8);
+ /*!
+ * @brief This API is used to write threshold
+ * for the slow/no-motion interrupt
+ * from the register 0x61 bit 0 to 7
+ *
+ *
+ *
+ *
+ * @param v_slow_no_motion_thres_u8 : The value of slow no motion threshold
+ * @note slow no motion threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | v_slow_no_motion_thres_u8*3.91 mg
+ * 4g | v_slow_no_motion_thres_u8*7.81 mg
+ * 8g | v_slow_no_motion_thres_u8*15.63 mg
+ * 16g | v_slow_no_motion_thres_u8*31.25 mg
+ * @note when v_slow_no_motion_thres_u8 = 0
+ * accel_range | slow no motion threshold
+ * ----------------|---------------------
+ * 2g | 1.95 mg
+ * 4g | 3.91 mg
+ * 8g | 7.81 mg
+ * 16g | 15.63 mg
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_slow_no_motion_thres(
+u8 v_slow_no_motion_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR SLO/NO MOTION SELECT CONFIGURATION */
+/***************************************************************/
+ /*!
+ * @brief This API is used to read
+ * the slow/no-motion selection from the register 0x62 bit 0
+ *
+ *
+ *
+ *
+ * @param v_intr_slow_no_motion_select_u8 :
+ * The value of slow/no-motion select
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SLOW_MOTION
+ * 0x01 | NO_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_slow_no_motion_select(
+u8 *v_intr_slow_no_motion_select_u8);
+ /*!
+ * @brief This API is used to write
+ * the slow/no-motion selection from the register 0x62 bit 0
+ *
+ *
+ *
+ *
+ * @param v_intr_slow_no_motion_select_u8 :
+ * The value of slow/no-motion select
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SLOW_MOTION
+ * 0x01 | NO_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_slow_no_motion_select(
+u8 v_intr_slow_no_motion_select_u8);
+/***************************************************************/
+/**\name FUNCTION FOR SIGNIFICANT MOTION SELECT CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API is used to select
+ * the significant or any motion interrupt from the register 0x62 bit 1
+ *
+ *
+ *
+ *
+ * @param v_intr_significant_motion_select_u8 :
+ * the value of significant or any motion interrupt selection
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | ANY_MOTION
+ * 0x01 | SIGNIFICANT_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_significant_motion_select(
+u8 *int_sig_mot_sel);
+ /*!
+ * @brief This API is used to write, select
+ * the significant or any motion interrupt from the register 0x62 bit 1
+ *
+ *
+ *
+ *
+ * @param v_intr_significant_motion_select_u8 :
+ * the value of significant or any motion interrupt selection
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | ANY_MOTION
+ * 0x01 | SIGNIFICANT_MOTION
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_significant_motion_select(
+u8 int_sig_mot_sel);
+ /*!
+ * @brief This API is used to read
+ * the significant skip time from the register 0x62 bit 2 and 3
+ *
+ *
+ *
+ *
+ * @param v_int_sig_mot_skip_u8 : the value of significant skip time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | skip time 1.5 seconds
+ * 0x01 | skip time 3 seconds
+ * 0x02 | skip time 6 seconds
+ * 0x03 | skip time 12 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_significant_motion_skip(
+u8 *v_int_sig_mot_skip_u8);
+ /*!
+ * @brief This API is used to write
+ * the significant skip time from the register 0x62 bit 2 and 3
+ *
+ *
+ *
+ *
+ * @param v_int_sig_mot_skip_u8 : the value of significant skip time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | skip time 1.5 seconds
+ * 0x01 | skip time 3 seconds
+ * 0x02 | skip time 6 seconds
+ * 0x03 | skip time 12 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_significant_motion_skip(
+u8 v_int_sig_mot_skip_u8);
+ /*!
+ * @brief This API is used to read
+ * the significant proof time from the register 0x62 bit 4 and 5
+ *
+ *
+ *
+ *
+ * @param v_significant_motion_proof_u8 :
+ * the value of significant proof time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | proof time 0.25 seconds
+ * 0x01 | proof time 0.5 seconds
+ * 0x02 | proof time 1 seconds
+ * 0x03 | proof time 2 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_significant_motion_proof(
+u8 *int_sig_mot_proof);
+ /*!
+ * @brief This API is used to write
+ * the significant proof time from the register 0x62 bit 4 and 5
+ *
+ *
+ *
+ *
+ * @param v_significant_motion_proof_u8 :
+ * the value of significant proof time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | proof time 0.25 seconds
+ * 0x01 | proof time 0.5 seconds
+ * 0x02 | proof time 1 seconds
+ * 0x03 | proof time 2 seconds
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_significant_motion_proof(
+u8 int_sig_mot_proof);
+/***************************************************************/
+/**\name FUNCTION FOR TAP DURATION CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API is used to get the tap duration
+ * from the register 0x63 bit 0 to 2
+ *
+ *
+ *
+ * @param v_tap_durn_u8 : The value of tap duration
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_DURN_50MS
+ * 0x01 | SMI130_TAP_DURN_100MS
+ * 0x03 | SMI130_TAP_DURN_150MS
+ * 0x04 | SMI130_TAP_DURN_200MS
+ * 0x05 | SMI130_TAP_DURN_250MS
+ * 0x06 | SMI130_TAP_DURN_375MS
+ * 0x07 | SMI130_TAP_DURN_700MS
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_durn(
+u8 *v_tap_durn_u8);
+/*!
+ * @brief This API is used to write the tap duration
+ * from the register 0x63 bit 0 to 2
+ *
+ *
+ *
+ * @param v_tap_durn_u8 : The value of tap duration
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_DURN_50MS
+ * 0x01 | SMI130_TAP_DURN_100MS
+ * 0x03 | SMI130_TAP_DURN_150MS
+ * 0x04 | SMI130_TAP_DURN_200MS
+ * 0x05 | SMI130_TAP_DURN_250MS
+ * 0x06 | SMI130_TAP_DURN_375MS
+ * 0x07 | SMI130_TAP_DURN_700MS
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_durn(
+u8 v_tap_durn_u8);
+/***************************************************************/
+/**\name FUNCTION FOR TAP SHOCK CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read the
+ * tap shock duration from the register 0x63 bit 2
+ *
+ * @param v_tap_shock_u8 :The value of tap shock
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_SHOCK_50MS
+ * 0x01 | SMI130_TAP_SHOCK_75MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_shock(
+u8 *v_tap_shock_u8);
+ /*!
+ * @brief This API write the
+ * tap shock duration from the register 0x63 bit 2
+ *
+ * @param v_tap_shock_u8 :The value of tap shock
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_SHOCK_50MS
+ * 0x01 | SMI130_TAP_SHOCK_75MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_shock(
+u8 v_tap_shock_u8);
+/***************************************************************/
+/**\name FUNCTION FOR TAP QUIET CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read
+ * tap quiet duration from the register 0x63 bit 7
+ *
+ *
+ * @param v_tap_quiet_u8 : The value of tap quiet
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_QUIET_30MS
+ * 0x01 | SMI130_TAP_QUIET_20MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_quiet(
+u8 *v_tap_quiet_u8);
+/*!
+ * @brief This API write
+ * tap quiet duration from the register 0x63 bit 7
+ *
+ *
+ * @param v_tap_quiet_u8 : The value of tap quiet
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | SMI130_TAP_QUIET_30MS
+ * 0x01 | SMI130_TAP_QUIET_20MS
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_quiet(
+u8 v_tap_quiet_u8);
+/***************************************************************/
+/**\name FUNCTION FOR TAP THRESHOLD CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read Threshold of the
+ * single/double tap interrupt from the register 0x64 bit 0 to 4
+ *
+ *
+ * @param v_tap_thres_u8 : The value of single/double tap threshold
+ *
+ * @note single/double tap threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | single/double tap threshold
+ * ----------------|---------------------
+ * 2g | ((v_tap_thres_u8 + 1) * 62.5)mg
+ * 4g | ((v_tap_thres_u8 + 1) * 125)mg
+ * 8g | ((v_tap_thres_u8 + 1) * 250)mg
+ * 16g | ((v_tap_thres_u8 + 1) * 500)mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_tap_thres(
+u8 *v_tap_thres_u8);
+ /*!
+ * @brief This API write Threshold of the
+ * single/double tap interrupt from the register 0x64 bit 0 to 4
+ *
+ *
+ * @param v_tap_thres_u8 : The value of single/double tap threshold
+ *
+ * @note single/double tap threshold changes according to accel g range
+ * accel g range can be set by the function ""
+ * accel_range | single/double tap threshold
+ * ----------------|---------------------
+ * 2g | ((v_tap_thres_u8 + 1) * 62.5)mg
+ * 4g | ((v_tap_thres_u8 + 1) * 125)mg
+ * 8g | ((v_tap_thres_u8 + 1) * 250)mg
+ * 16g | ((v_tap_thres_u8 + 1) * 500)mg
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_tap_thres(
+u8 v_tap_thres_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT MODE CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read the threshold for orient_mblation interrupt
+ * from the register 0x65 bit 0 and 1
+ *
+ * @param v_orient_mbl_mode_u8 : The value of threshold for orient_mblation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | symmetrical
+ * 0x01 | high-asymmetrical
+ * 0x02 | low-asymmetrical
+ * 0x03 | symmetrical
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_mode(
+u8 *v_orient_mbl_mode_u8);
+ /*!
+ * @brief This API write the threshold for orient_mblation interrupt
+ * from the register 0x65 bit 0 and 1
+ *
+ * @param v_orient_mbl_mode_u8 : The value of threshold for orient_mblation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | symmetrical
+ * 0x01 | high-asymmetrical
+ * 0x02 | low-asymmetrical
+ * 0x03 | symmetrical
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_mode(
+u8 v_orient_mbl_mode_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT BLOCKING CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read the orient_mbl blocking mode
+ * that is used for the generation of the orient_mblation interrupt.
+ * from the register 0x65 bit 2 and 3
+ *
+ * @param v_orient_mbl_blocking_u8 : The value of orient_mbl blocking mode
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | No blocking
+ * 0x01 | Theta blocking or acceleration in any axis > 1.5g
+ * 0x02 | Theta blocking or acceleration slope in any axis >
+ * - | 0.2g or acceleration in any axis > 1.5g
+ * 0x03 | Theta blocking or acceleration slope in any axis >
+ * - | 0.4g or acceleration in any axis >
+ * - | 1.5g and value of orient_mbl is not stable
+ * - | for at least 100 ms
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_blocking(
+u8 *v_orient_mbl_blocking_u8);
+/*!
+ * @brief This API write the orient_mbl blocking mode
+ * that is used for the generation of the orient_mblation interrupt.
+ * from the register 0x65 bit 2 and 3
+ *
+ * @param v_orient_mbl_blocking_u8 : The value of orient_mbl blocking mode
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | No blocking
+ * 0x01 | Theta blocking or acceleration in any axis > 1.5g
+ * 0x02 | Theta blocking or acceleration slope in any axis >
+ * - | 0.2g or acceleration in any axis > 1.5g
+ * 0x03 | Theta blocking or acceleration slope in any axis >
+ * - | 0.4g or acceleration in any axis >
+ * - | 1.5g and value of orient_mbl is not stable
+ * - | for at least 100 ms
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_blocking(
+u8 v_orient_mbl_blocking_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT HYSTERESIS CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read Orient interrupt
+ * hysteresis, from the register 0x64 bit 4 to 7
+ *
+ *
+ *
+ * @param v_orient_mbl_hyst_u8 : The value of orient_mbl hysteresis
+ *
+ * @note 1 LSB corresponds to 62.5 mg,
+ * irrespective of the selected accel range
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_hyst(
+u8 *v_orient_mbl_hyst_u8);
+/*!
+ * @brief This API write Orient interrupt
+ * hysteresis, from the register 0x64 bit 4 to 7
+ *
+ *
+ *
+ * @param v_orient_mbl_hyst_u8 : The value of orient_mbl hysteresis
+ *
+ * @note 1 LSB corresponds to 62.5 mg,
+ * irrespective of the selected accel range
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_hyst(
+u8 v_orient_mbl_hyst_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT THETA CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read Orient
+ * blocking angle (0 to 44.8) from the register 0x66 bit 0 to 5
+ *
+ * @param v_orient_mbl_theta_u8 : The value of Orient blocking angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_theta(
+u8 *v_orient_mbl_theta_u8);
+ /*!
+ * @brief This API write Orient
+ * blocking angle (0 to 44.8) from the register 0x66 bit 0 to 5
+ *
+ * @param v_orient_mbl_theta_u8 : The value of Orient blocking angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_theta(
+u8 v_orient_mbl_theta_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT OUTPUT ENABLE CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read orient_mbl change
+ * of up/down bit from the register 0x66 bit 6
+ *
+ * @param v_orient_mbl_ud_u8 : The value of orient_mbl change of up/down
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | Is ignored
+ * 0x01 | Generates orient_mblation interrupt
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_ud_enable(
+u8 *v_orient_mbl_ud_u8);
+/*!
+ * @brief This API write orient_mbl change
+ * of up/down bit from the register 0x66 bit 6
+ *
+ * @param v_orient_mbl_ud_u8 : The value of orient_mbl change of up/down
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | Is ignored
+ * 0x01 | Generates orient_mblation interrupt
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_ud_enable(
+u8 v_orient_mbl_ud_u8);
+/***************************************************************/
+/**\name FUNCTION FOR ORIENT AXIS ENABLE CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read orient_mblation axes changes
+ * from the register 0x66 bit 7
+ *
+ * @param v_orient_mbl_axes_u8 : The value of orient_mbl axes assignment
+ * value | Behaviour | Name
+ * ----------|--------------------|------
+ * 0x00 | x = x, y = y, z = z|orient_mbl_ax_noex
+ * 0x01 | x = y, y = z, z = x|orient_mbl_ax_ex
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_orient_mbl_axes_enable(
+u8 *v_orient_mbl_axes_u8);
+ /*!
+ * @brief This API write orient_mblation axes changes
+ * from the register 0x66 bit 7
+ *
+ * @param v_orient_mbl_axes_u8 : The value of orient_mbl axes assignment
+ * value | Behaviour | Name
+ * ----------|--------------------|------
+ * 0x00 | x = x, y = y, z = z|orient_mbl_ax_noex
+ * 0x01 | x = y, y = z, z = x|orient_mbl_ax_ex
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_orient_mbl_axes_enable(
+u8 v_orient_mbl_axes_u8);
+/***************************************************************/
+/**\name FUNCTION FOR FLAT THETA CONFIGURATION*/
+/***************************************************************/
+ /*!
+ * @brief This API read Flat angle (0 to 44.8) for flat interrupt
+ * from the register 0x67 bit 0 to 5
+ *
+ * @param v_flat_theta_u8 : The value of flat angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_flat_theta(
+u8 *v_flat_theta_u8);
+ /*!
+ * @brief This API write Flat angle (0 to 44.8) for flat interrupt
+ * from the register 0x67 bit 0 to 5
+ *
+ * @param v_flat_theta_u8 : The value of flat angle
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_flat_theta(
+u8 v_flat_theta_u8);
+/***************************************************************/
+/**\name FUNCTION FOR FLAT HOLD CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read Flat interrupt hold time;
+ * from the register 0x68 bit 4 and 5
+ *
+ * @param v_flat_hold_u8 : The value of flat hold time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | 0ms
+ * 0x01 | 512ms
+ * 0x01 | 1024ms
+ * 0x01 | 2048ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_flat_hold(
+u8 *v_flat_hold_u8);
+/*!
+ * @brief This API write Flat interrupt hold time;
+ * from the register 0x68 bit 4 and 5
+ *
+ * @param v_flat_hold_u8 : The value of flat hold time
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | 0ms
+ * 0x01 | 512ms
+ * 0x01 | 1024ms
+ * 0x01 | 2048ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_flat_hold(
+u8 v_flat_hold_u8);
+/***************************************************************/
+/**\name FUNCTION FOR FLAT HYSTERESIS CONFIGURATION*/
+/***************************************************************/
+/*!
+ * @brief This API read flat interrupt hysteresis
+ * from the register 0x68 bit 0 to 3
+ *
+ * @param v_flat_hyst_u8 : The value of flat hysteresis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_intr_flat_hyst(
+u8 *v_flat_hyst_u8);
+/*!
+ * @brief This API write flat interrupt hysteresis
+ * from the register 0x68 bit 0 to 3
+ *
+ * @param v_flat_hyst_u8 : The value of flat hysteresis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_intr_flat_hyst(
+u8 v_flat_hyst_u8);
+/***************************************************************/
+/**\name FUNCTION FAST OFFSET COMPENSATION FOR ACCEL */
+/***************************************************************/
+ /*!
+ * @brief This API read accel offset compensation
+ * target value for z-axis from the register 0x69 bit 0 and 1
+ *
+ * @param v_foc_accel_z_u8 : the value of accel offset compensation z axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_accel_z(
+u8 *v_foc_accel_z_u8);
+ /*!
+ * @brief This API write accel offset compensation
+ * target value for z-axis from the register 0x69 bit 0 and 1
+ *
+ * @param v_foc_accel_z_u8 : the value of accel offset compensation z axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_foc_accel_z(
+u8 v_foc_accel_z_u8);
+/*!
+ * @brief This API read accel offset compensation
+ * target value for y-axis
+ * from the register 0x69 bit 2 and 3
+ *
+ * @param v_foc_accel_y_u8 : the value of accel offset compensation y axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_accel_y(
+u8 *v_foc_accel_y_u8);
+/*!
+ * @brief This API write accel offset compensation
+ * target value for y-axis
+ * from the register 0x69 bit 2 and 3
+ *
+ * @param v_foc_accel_y_u8 : the value of accel offset compensation y axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_foc_accel_y(
+u8 v_foc_accel_y_u8);
+/*!
+ * @brief This API read accel offset compensation
+ * target value for x-axis is
+ * from the register 0x69 bit 4 and 5
+ *
+ * @param v_foc_accel_x_u8 : the value of accel offset compensation x axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_accel_x(
+u8 *v_foc_accel_x_u8);
+/*!
+ * @brief This API write accel offset compensation
+ * target value for x-axis is
+ * from the register 0x69 bit 4 and 5
+ *
+ * @param v_foc_accel_x_u8 : the value of accel offset compensation x axis
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_foc_accel_x(
+u8 v_foc_accel_x_u8);
+/***************************************************************/
+/**\name FUNCTION FAST OFFSET COMPENSATION FOR GYRO */
+/***************************************************************/
+/*!
+ * @brief This API write gyro fast offset enable
+ * from the register 0x69 bit 6
+ *
+ * @param v_foc_gyro_u8 : The value of gyro fast offset enable
+ * value | Description
+ * ----------|-------------
+ * 0 | fast offset compensation disabled
+ * 1 | fast offset compensation enabled
+ *
+ * @param v_gyro_off_x_s16 : The value of gyro fast offset x axis data
+ * @param v_gyro_off_y_s16 : The value of gyro fast offset y axis data
+ * @param v_gyro_off_z_s16 : The value of gyro fast offset z axis data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_foc_gyro_enable(
+u8 v_foc_gyro_u8, s16 *v_gyro_off_x_s16,
+s16 *v_gyro_off_y_s16, s16 *v_gyro_off_z_s16);
+/***************************************************/
+/**\name FUNCTION FOR NVM*/
+/***************************************************/
+ /*!
+ * @brief This API read NVM program enable
+ * from the register 0x6A bit 1
+ *
+ * @param v_nvm_prog_u8 : The value of NVM program enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_nvm_prog_enable(
+u8 *v_nvm_prog_u8);
+ /*!
+ * @brief This API write NVM program enable
+ * from the register 0x6A bit 1
+ *
+ * @param v_nvm_prog_u8 : The value of NVM program enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_nvm_prog_enable(
+u8 v_nvm_prog_u8);
+/***************************************************/
+/**\name FUNCTION FOR SPI MODE*/
+/***************************************************/
+/*!
+ * @brief This API read to configure SPI
+ * Interface Mode for primary and OIS interface
+ * from the register 0x6B bit 0
+ *
+ * @param v_spi3_u8 : The value of SPI mode selection
+ * Value | Description
+ * --------|-------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_get_spi3(
+u8 *v_spi3_u8);
+/*!
+ * @brief This API write to configure SPI
+ * Interface Mode for primary and OIS interface
+ * from the register 0x6B bit 0
+ *
+ * @param v_spi3_u8 : The value of SPI mode selection
+ * Value | Description
+ * --------|-------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_spi3(
+u8 v_spi3_u8);
+/***************************************************/
+/**\name FUNCTION FOR FOC GYRO */
+/***************************************************/
+/*!
+ * @brief This API read gyro fast offset enable
+ * from the register 0x69 bit 6
+ *
+ * @param v_foc_gyro_u8 : The value of gyro fast offset enable
+ * value | Description
+ * ----------|-------------
+ * 0 | fast offset compensation disabled
+ * 1 | fast offset compensation enabled
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_foc_gyro_enable(
+u8 *v_foc_gyro_u8);
+/***************************************************/
+/**\name FUNCTION FOR I2C WATCHDOG TIMBER */
+/***************************************************/
+/*!
+ * @brief This API read I2C Watchdog timer
+ * from the register 0x70 bit 1
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watch dog timer
+ * Value | Description
+ * --------|-------------
+ * 0 | I2C watchdog v_timeout_u8 after 1 ms
+ * 1 | I2C watchdog v_timeout_u8 after 50 ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_i2c_wdt_select(
+u8 *v_i2c_wdt_u8);
+/*!
+ * @brief This API write I2C Watchdog timer
+ * from the register 0x70 bit 1
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watch dog timer
+ * Value | Description
+ * --------|-------------
+ * 0 | I2C watchdog v_timeout_u8 after 1 ms
+ * 1 | I2C watchdog v_timeout_u8 after 50 ms
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE
+smi130_set_i2c_wdt_select(u8 v_i2c_wdt_u8);
+/*!
+ * @brief This API read I2C watchdog enable
+ * from the register 0x70 bit 2
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watchdog enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_i2c_wdt_enable(
+u8 *v_i2c_wdt_u8);
+/*!
+ * @brief This API write I2C watchdog enable
+ * from the register 0x70 bit 2
+ *
+ * @param v_i2c_wdt_u8 : The value of I2C watchdog enable
+ * Value | Description
+ * --------|-------------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_i2c_wdt_enable(
+u8 v_i2c_wdt_u8);
+/***************************************************/
+/**\name FUNCTION FOR IF MODE*/
+/***************************************************/
+/*!
+ * @brief This API read I2C interface configuration(if) moe
+ * from the register 0x6B bit 4 and 5
+ *
+ * @param v_if_mode_u8 : The value of interface configuration mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Primary interface:autoconfig / secondary interface:off
+ * 0x01 | Primary interface:I2C / secondary interface:OIS
+ * 0x02 | Primary interface:autoconfig/secondary interface:Magnetometer
+ * 0x03 | Reserved
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_if_mode(
+u8 *v_if_mode_u8);
+/*!
+ * @brief This API write I2C interface configuration(if) moe
+ * from the register 0x6B bit 4 and 5
+ *
+ * @param v_if_mode_u8 : The value of interface configuration mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Primary interface:autoconfig / secondary interface:off
+ * 0x01 | Primary interface:I2C / secondary interface:OIS
+ * 0x02 | Primary interface:autoconfig/secondary interface:Magnetometer
+ * 0x03 | Reserved
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_if_mode(
+u8 v_if_mode_u8);
+/***************************************************/
+/**\name FUNCTION FOR GYRO SLEEP TRIGGER INTERRUPT CONFIGURATION*/
+/***************************************************/
+/*!
+ * @brief This API read gyro sleep trigger
+ * from the register 0x6C bit 0 to 2
+ *
+ * @param v_gyro_sleep_trigger_u8 : The value of gyro sleep trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | nomotion: no / Not INT1 pin: no / INT2 pin: no
+ * 0x01 | nomotion: no / Not INT1 pin: no / INT2 pin: yes
+ * 0x02 | nomotion: no / Not INT1 pin: yes / INT2 pin: no
+ * 0x03 | nomotion: no / Not INT1 pin: yes / INT2 pin: yes
+ * 0x04 | nomotion: yes / Not INT1 pin: no / INT2 pin: no
+ * 0x05 | anymotion: yes / Not INT1 pin: no / INT2 pin: yes
+ * 0x06 | anymotion: yes / Not INT1 pin: yes / INT2 pin: no
+ * 0x07 | anymotion: yes / Not INT1 pin: yes / INT2 pin: yes
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_sleep_trigger(
+u8 *v_gyro_sleep_trigger_u8);
+/*!
+ * @brief This API write gyro sleep trigger
+ * from the register 0x6C bit 0 to 2
+ *
+ * @param v_gyro_sleep_trigger_u8 : The value of gyro sleep trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | nomotion: no / Not INT1 pin: no / INT2 pin: no
+ * 0x01 | nomotion: no / Not INT1 pin: no / INT2 pin: yes
+ * 0x02 | nomotion: no / Not INT1 pin: yes / INT2 pin: no
+ * 0x03 | nomotion: no / Not INT1 pin: yes / INT2 pin: yes
+ * 0x04 | nomotion: yes / Not INT1 pin: no / INT2 pin: no
+ * 0x05 | anymotion: yes / Not INT1 pin: no / INT2 pin: yes
+ * 0x06 | anymotion: yes / Not INT1 pin: yes / INT2 pin: no
+ * 0x07 | anymotion: yes / Not INT1 pin: yes / INT2 pin: yes
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_sleep_trigger(
+u8 v_gyro_sleep_trigger_u8);
+/*!
+ * @brief This API read gyro wakeup trigger
+ * from the register 0x6C bit 3 and 4
+ *
+ * @param v_gyro_wakeup_trigger_u8 : The value of gyro wakeup trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | anymotion: no / INT1 pin: no
+ * 0x01 | anymotion: no / INT1 pin: yes
+ * 0x02 | anymotion: yes / INT1 pin: no
+ * 0x03 | anymotion: yes / INT1 pin: yes
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_wakeup_trigger(
+u8 *v_gyro_wakeup_trigger_u8);
+/*!
+ * @brief This API write gyro wakeup trigger
+ * from the register 0x6C bit 3 and 4
+ *
+ * @param v_gyro_wakeup_trigger_u8 : The value of gyro wakeup trigger
+ * Value | Description
+ * --------|-------------
+ * 0x00 | anymotion: no / INT1 pin: no
+ * 0x01 | anymotion: no / INT1 pin: yes
+ * 0x02 | anymotion: yes / INT1 pin: no
+ * 0x03 | anymotion: yes / INT1 pin: yes
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_wakeup_trigger(
+u8 v_gyro_wakeup_trigger_u8);
+/*!
+ * @brief This API read Target state for gyro sleep mode
+ * from the register 0x6C bit 5
+ *
+ * @param v_gyro_sleep_state_u8 : The value of gyro sleep mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Sleep transition to fast wake up state
+ * 0x01 | Sleep transition to suspend state
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_sleep_state(
+u8 *v_gyro_sleep_state_u8);
+/*!
+ * @brief This API write Target state for gyro sleep mode
+ * from the register 0x6C bit 5
+ *
+ * @param v_gyro_sleep_state_u8 : The value of gyro sleep mode
+ * Value | Description
+ * --------|-------------
+ * 0x00 | Sleep transition to fast wake up state
+ * 0x01 | Sleep transition to suspend state
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_sleep_state(
+u8 v_gyro_sleep_state_u8);
+/*!
+ * @brief This API read gyro wakeup interrupt
+ * from the register 0x6C bit 6
+ *
+ * @param v_gyro_wakeup_intr_u8 : The valeu of gyro wakeup interrupt
+ * Value | Description
+ * --------|-------------
+ * 0x00 | DISABLE
+ * 0x01 | ENABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_wakeup_intr(
+u8 *v_gyro_wakeup_intr_u8);
+/*!
+ * @brief This API write gyro wakeup interrupt
+ * from the register 0x6C bit 6
+ *
+ * @param v_gyro_wakeup_intr_u8 : The valeu of gyro wakeup interrupt
+ * Value | Description
+ * --------|-------------
+ * 0x00 | DISABLE
+ * 0x01 | ENABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_wakeup_intr(
+u8 v_gyro_wakeup_intr_u8);
+/***************************************************/
+/**\name FUNCTION FOR ACCEL SELF TEST */
+/***************************************************/
+/*!
+ * @brief This API read accel select axis to be self-test
+ *
+ * @param v_accel_selftest_axis_u8 :
+ * The value of accel self test axis selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | disabled
+ * 0x01 | x-axis
+ * 0x02 | y-axis
+ * 0x03 | z-axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_selftest_axis(
+u8 *acc_selftest_axis);
+/*!
+ * @brief This API write accel select axis to be self-test
+ *
+ * @param v_accel_selftest_axis_u8 :
+ * The value of accel self test axis selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | disabled
+ * 0x01 | x-axis
+ * 0x02 | y-axis
+ * 0x03 | z-axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_selftest_axis(
+u8 acc_selftest_axis);
+/*!
+ * @brief This API read accel self test axis sign
+ * from the register 0x6D bit 2
+ *
+ * @param v_accel_selftest_sign_u8: The value of accel self test axis sign
+ * Value | Description
+ * --------|-------------
+ * 0x00 | negative
+ * 0x01 | positive
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_selftest_sign(
+u8 *acc_selftest_sign);
+/*!
+ * @brief This API write accel self test axis sign
+ * from the register 0x6D bit 2
+ *
+ * @param v_accel_selftest_sign_u8: The value of accel self test axis sign
+ * Value | Description
+ * --------|-------------
+ * 0x00 | negative
+ * 0x01 | positive
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_selftest_sign(
+u8 acc_selftest_sign);
+/*!
+ * @brief This API read accel self test amplitude
+ * from the register 0x6D bit 3
+ * select amplitude of the selftest deflection:
+ *
+ * @param v_accel_selftest_amp_u8 : The value of accel self test amplitude
+ * Value | Description
+ * --------|-------------
+ * 0x00 | LOW
+ * 0x01 | HIGH
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_selftest_amp(
+u8 *acc_selftest_amp);
+/*!
+ * @brief This API write accel self test amplitude
+ * from the register 0x6D bit 3
+ * select amplitude of the selftest deflection:
+ *
+ * @param v_accel_selftest_amp_u8 : The value of accel self test amplitude
+ * Value | Description
+ * --------|-------------
+ * 0x00 | LOW
+ * 0x01 | HIGH
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_selftest_amp(
+u8 acc_selftest_amp);
+/***************************************************/
+/**\name FUNCTION FOR GYRO SELF TEST */
+/***************************************************/
+/*!
+ * @brief This API read gyro self test trigger
+ *
+ * @param v_gyro_selftest_start_u8: The value of gyro self test start
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_selftest_start(
+u8 *v_gyro_selftest_start_u8);
+/*!
+ * @brief This API write gyro self test trigger
+ *
+ * @param v_gyro_selftest_start_u8: The value of gyro self test start
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_selftest_start(
+u8 v_gyro_selftest_start_u8);
+/***************************************************/
+/**\name FUNCTION FOR SPI/I2C ENABLE */
+/***************************************************/
+ /*!
+ * @brief This API read primary interface selection I2C or SPI
+ * from the register 0x70 bit 0
+ *
+ * @param v_spi_enable_u8: The value of Interface selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | I2C Enable
+ * 0x01 | I2C DISBALE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_spi_enable(
+u8 *v_spi_enable_u8);
+ /*!
+ * @brief This API write primary interface selection I2C or SPI
+ * from the register 0x70 bit 0
+ *
+ * @param v_spi_enable_u8: The value of Interface selection
+ * Value | Description
+ * --------|-------------
+ * 0x00 | I2C Enable
+ * 0x01 | I2C DISBALE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_spi_enable(
+u8 v_spi_enable_u8);
+ /*!
+ * @brief This API read the spare zero
+ * form register 0x70 bit 3
+ *
+ *
+ * @param v_spare0_trim_u8: The value of spare zero
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_spare0_trim
+(u8 *v_spare0_trim_u8);
+ /*!
+ * @brief This API write the spare zero
+ * form register 0x70 bit 3
+ *
+ *
+ * @param v_spare0_trim_u8: The value of spare zero
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_spare0_trim
+(u8 v_spare0_trim_u8);
+/***************************************************/
+/**\name FUNCTION FOR NVM COUNTER */
+/***************************************************/
+ /*!
+ * @brief This API read the NVM counter
+ * form register 0x70 bit 4 to 7
+ *
+ *
+ * @param v_nvm_counter_u8: The value of NVM counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_nvm_counter(
+u8 *v_nvm_counter_u8);
+ /*!
+ * @brief This API write the NVM counter
+ * form register 0x70 bit 4 to 7
+ *
+ *
+ * @param v_nvm_counter_u8: The value of NVM counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_nvm_counter(
+u8 v_nvm_counter_u8);
+/***************************************************/
+/**\name FUNCTION FOR ACCEL MANUAL OFFSET COMPENSATION */
+/***************************************************/
+/*!
+ * @brief This API read accel manual offset compensation of x axis
+ * from the register 0x71 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_x_s8:
+ * The value of accel manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_offset_compensation_xaxis(
+s8 *v_accel_off_x_s8);
+/*!
+ * @brief This API write accel manual offset compensation of x axis
+ * from the register 0x71 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_x_s8:
+ * The value of accel manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_offset_compensation_xaxis(
+s8 v_accel_off_x_s8);
+/*!
+ * @brief This API read accel manual offset compensation of y axis
+ * from the register 0x72 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_y_s8:
+ * The value of accel manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_offset_compensation_yaxis(
+s8 *v_accel_off_y_s8);
+/*!
+ * @brief This API write accel manual offset compensation of y axis
+ * from the register 0x72 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_y_s8:
+ * The value of accel manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_offset_compensation_yaxis(
+s8 v_accel_off_y_s8);
+/*!
+ * @brief This API read accel manual offset compensation of z axis
+ * from the register 0x73 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_z_s8:
+ * The value of accel manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_offset_compensation_zaxis(
+s8 *v_accel_off_z_s8);
+/*!
+ * @brief This API write accel manual offset compensation of z axis
+ * from the register 0x73 bit 0 to 7
+ *
+ *
+ *
+ * @param v_accel_off_z_s8:
+ * The value of accel manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_offset_compensation_zaxis(
+s8 v_accel_off_z_s8);
+/***************************************************/
+/**\name FUNCTION FOR GYRO MANUAL OFFSET COMPENSATION */
+/***************************************************/
+/*!
+ * @brief This API read gyro manual offset compensation of x axis
+ * from the register 0x74 bit 0 to 7 and 0x77 bit 0 and 1
+ *
+ *
+ *
+ * @param v_gyro_off_x_s16:
+ * The value of gyro manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_offset_compensation_xaxis(
+s16 *v_gyro_off_x_s16);
+/*!
+ * @brief This API write gyro manual offset compensation of x axis
+ * from the register 0x74 bit 0 to 7 and 0x77 bit 0 and 1
+ *
+ *
+ *
+ * @param v_gyro_off_x_s16:
+ * The value of gyro manual offset compensation of x axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_offset_compensation_xaxis(
+s16 v_gyro_off_x_s16);
+/*!
+ * @brief This API read gyro manual offset compensation of y axis
+ * from the register 0x75 bit 0 to 7 and 0x77 bit 2 and 3
+ *
+ *
+ *
+ * @param v_gyro_off_y_s16:
+ * The value of gyro manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_offset_compensation_yaxis(
+s16 *v_gyro_off_y_s16);
+/*!
+ * @brief This API write gyro manual offset compensation of y axis
+ * from the register 0x75 bit 0 to 7 and 0x77 bit 2 and 3
+ *
+ *
+ *
+ * @param v_gyro_off_y_s16:
+ * The value of gyro manual offset compensation of y axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_offset_compensation_yaxis(
+s16 v_gyro_off_y_s16);
+/*!
+ * @brief This API read gyro manual offset compensation of z axis
+ * from the register 0x76 bit 0 to 7 and 0x77 bit 4 and 5
+ *
+ *
+ *
+ * @param v_gyro_off_z_s16:
+ * The value of gyro manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_offset_compensation_zaxis(
+s16 *v_gyro_off_z_s16);
+/*!
+ * @brief This API write gyro manual offset compensation of z axis
+ * from the register 0x76 bit 0 to 7 and 0x77 bit 4 and 5
+ *
+ *
+ *
+ * @param v_gyro_off_z_s16:
+ * The value of gyro manual offset compensation of z axis
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_offset_compensation_zaxis(
+s16 v_gyro_off_z_s16);
+/*!
+ * @brief This API writes accel fast offset compensation
+ * from the register 0x69 bit 0 to 5
+ * @brief This API writes each axis individually
+ * FOC_X_AXIS - bit 4 and 5
+ * FOC_Y_AXIS - bit 2 and 3
+ * FOC_Z_AXIS - bit 0 and 1
+ *
+ * @param v_foc_accel_u8: The value of accel offset compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_axis_u8: The value of accel offset axis selection
+ * value | axis
+ * ----------|-------------------
+ * 0 | FOC_X_AXIS
+ * 1 | FOC_Y_AXIS
+ * 2 | FOC_Z_AXIS
+ *
+ * @param v_accel_offset_s8: The accel offset value
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_foc_trigger(u8 axis,
+u8 foc_acc, s8 *accel_offset);
+/*!
+ * @brief This API write fast accel offset compensation
+ * it writes all axis together.To the register 0x69 bit 0 to 5
+ * FOC_X_AXIS - bit 4 and 5
+ * FOC_Y_AXIS - bit 2 and 3
+ * FOC_Z_AXIS - bit 0 and 1
+ *
+ * @param v_foc_accel_x_u8: The value of accel offset x compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_foc_accel_y_u8: The value of accel offset y compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_foc_accel_z_u8: The value of accel offset z compensation
+ * value | Behaviour
+ * ----------|-------------------
+ * 0x00 | disable
+ * 0x01 | +1g
+ * 0x01 | -1g
+ * 0x01 | 0g
+ *
+ * @param v_accel_off_x_s8: The value of accel offset x axis
+ * @param v_accel_off_y_s8: The value of accel offset y axis
+ * @param v_accel_off_z_s8: The value of accel offset z axis
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_accel_foc_trigger_xyz(u8 v_foc_accel_x_u8,
+u8 v_foc_accel_y_u8, u8 v_foc_accel_z_u8,
+s8 *acc_off_x, s8 *acc_off_y, s8 *acc_off_z);
+/***************************************************/
+/**\name FUNCTION FOR ACEL AND GYRO OFFSET ENABLE */
+/***************************************************/
+/*!
+ * @brief This API read the accel offset enable bit
+ * from the register 0x77 bit 6
+ *
+ *
+ *
+ * @param v_accel_off_enable_u8: The value of accel offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_accel_offset_enable(
+u8 *acc_off_en);
+/*!
+ * @brief This API write the accel offset enable bit
+ * from the register 0x77 bit 6
+ *
+ *
+ *
+ * @param v_accel_off_enable_u8: The value of accel offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_accel_offset_enable(
+u8 acc_off_en);
+/*!
+ * @brief This API read the accel offset enable bit
+ * from the register 0x77 bit 7
+ *
+ *
+ *
+ * @param v_gyro_off_enable_u8: The value of gyro offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_gyro_offset_enable(
+u8 *v_gyro_off_enable_u8);
+/*!
+ * @brief This API write the accel offset enable bit
+ * from the register 0x77 bit 7
+ *
+ *
+ *
+ * @param v_gyro_off_enable_u8: The value of gyro offset enable
+ * value | Description
+ * ----------|--------------
+ * 0x01 | ENABLE
+ * 0x00 | DISABLE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_gyro_offset_enable(
+u8 v_gyro_off_enable_u8);
+/***************************************************/
+/**\name FUNCTION FOR STEP COUNTER INTERRUPT */
+/***************************************************/
+/*!
+ * @brief This API reads step counter value
+ * form the register 0x78 and 0x79
+ *
+ *
+ *
+ *
+ * @param v_step_cnt_s16 : The value of step counter
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_read_step_count(u16 *v_step_cnt_s16);
+ /*!
+ * @brief This API Reads
+ * step counter configuration
+ * from the register 0x7A bit 0 to 7
+ * and from the register 0x7B bit 0 to 2 and 4 to 7
+ *
+ *
+ * @param v_step_config_u16 : The value of step configuration
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_step_config(
+u16 *v_step_config_u16);
+ /*!
+ * @brief This API write
+ * step counter configuration
+ * from the register 0x7A bit 0 to 7
+ * and from the register 0x7B bit 0 to 2 and 4 to 7
+ *
+ *
+ * @param v_step_config_u16 :
+ * the value of Enable step configuration
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_step_config(
+u16 v_step_config_u16);
+ /*!
+ * @brief This API read enable step counter
+ * from the register 0x7B bit 3
+ *
+ *
+ * @param v_step_counter_u8 : The value of step counter enable
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_step_counter_enable(
+u8 *v_step_counter_u8);
+ /*!
+ * @brief This API write enable step counter
+ * from the register 0x7B bit 3
+ *
+ *
+ * @param v_step_counter_u8 : The value of step counter enable
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_step_counter_enable(
+u8 v_step_counter_u8);
+ /*!
+ * @brief This API set Step counter modes
+ *
+ *
+ * @param v_step_mode_u8 : The value of step counter mode
+ * value | mode
+ * ----------|-----------
+ * 0 | SMI130_STEP_NORMAL_MODE
+ * 1 | SMI130_STEP_SENSITIVE_MODE
+ * 2 | SMI130_STEP_ROBUST_MODE
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_step_mode(u8 v_step_mode_u8);
+/*!
+ * @brief This API used to trigger the signification motion
+ * interrupt
+ *
+ *
+ * @param v_significant_u8 : The value of interrupt selection
+ * value | interrupt
+ * ----------|-----------
+ * 0 | SMI130_MAP_INTR1
+ * 1 | SMI130_MAP_INTR2
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_map_significant_motion_intr(
+u8 v_significant_u8);
+/*!
+ * @brief This API used to trigger the step detector
+ * interrupt
+ *
+ *
+ * @param v_step_detector_u8 : The value of interrupt selection
+ * value | interrupt
+ * ----------|-----------
+ * 0 | SMI130_MAP_INTR1
+ * 1 | SMI130_MAP_INTR2
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_map_step_detector_intr(
+u8 v_step_detector_u8);
+ /*!
+ * @brief This API used to clear the step counter interrupt
+ * interrupt
+ *
+ *
+ * @param : None
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_clear_step_counter(void);
+/***************************************************/
+/**\name FUNCTION FOR STEP COMMAND REGISTER WRITE */
+/***************************************************/
+ /*!
+ * @brief This API writes value to the register 0x7E bit 0 to 7
+ *
+ *
+ * @param v_command_reg_u8 : The value to write command register
+ * value | Description
+ * ---------|--------------------------------------------------------
+ * 0x00 | Reserved
+ * 0x03 | Starts fast offset calibration for the accel and gyro
+ * 0x10 | Sets the PMU mode for the Accelerometer to suspend
+ * 0x11 | Sets the PMU mode for the Accelerometer to normal
+ * 0x12 | Sets the PMU mode for the Accelerometer Lowpower
+ * 0x14 | Sets the PMU mode for the Gyroscope to suspend
+ * 0x15 | Sets the PMU mode for the Gyroscope to normal
+ * 0x16 | Reserved
+ * 0x17 | Sets the PMU mode for the Gyroscope to fast start-up
+ * 0x18 | Sets the PMU mode for the Magnetometer to suspend
+ * 0x19 | Sets the PMU mode for the Magnetometer to normal
+ * 0x1A | Sets the PMU mode for the Magnetometer to Lowpower
+ * 0xB0 | Clears all data in the FIFO
+ * 0xB1 | Resets the interrupt engine
+ * 0xB2 | step_cnt_clr Clears the step counter
+ * 0xB6 | Triggers a reset
+ * 0x37 | See extmode_en_last
+ * 0x9A | See extmode_en_last
+ * 0xC0 | Enable the extended mode
+ * 0xC4 | Erase NVM cell
+ * 0xC8 | Load NVM cell
+ * 0xF0 | Reset acceleration data path
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_command_register(
+u8 v_command_reg_u8);
+/***************************************************/
+/**\name FUNCTION FOR PAGE ENABLE */
+/***************************************************/
+ /*!
+ * @brief This API read target page from the register 0x7F bit 4 and 5
+ *
+ * @param v_target_page_u8: The value of target page
+ * value | page
+ * ---------|-----------
+ * 0 | User data/configure page
+ * 1 | Chip level trim/test page
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_target_page(
+u8 *v_target_page_u8);
+ /*!
+ * @brief This API write target page from the register 0x7F bit 4 and 5
+ *
+ * @param v_target_page_u8: The value of target page
+ * value | page
+ * ---------|-----------
+ * 0 | User data/configure page
+ * 1 | Chip level trim/test page
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_target_page(
+u8 v_target_page_u8);
+ /*!
+ * @brief This API read page enable from the register 0x7F bit 7
+ *
+ *
+ *
+ * @param v_page_enable_u8: The value of page enable
+ * value | page
+ * ---------|-----------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_paging_enable(
+u8 *v_page_enable_u8);
+ /*!
+ * @brief This API write page enable from the register 0x7F bit 7
+ *
+ *
+ *
+ * @param v_page_enable_u8: The value of page enable
+ * value | page
+ * ---------|-----------
+ * 0 | DISABLE
+ * 1 | ENABLE
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_paging_enable(
+u8 v_page_enable_u8);
+ /*!
+ * @brief This API read
+ * pull up configuration from the register 0X85 bit 4 an 5
+ *
+ *
+ *
+ * @param v_control_pullup_u8: The value of pull up register
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_get_pullup_configuration(
+u8 *v_control_pullup_u8);
+ /*!
+ * @brief This API write
+ * pull up configuration from the register 0X85 bit 4 an 5
+ *
+ *
+ *
+ * @param v_control_pullup_u8: The value of pull up register
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_pullup_configuration(
+u8 v_control_pullup_u8);
+/***************************************************/
+/**\name FUNCTION FOR BMM150 */
+/***************************************************/
+ /*!
+ * @brief This function used for initialize the bmm150 sensor
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_interface_init(void);
+ /*!
+ * @brief This function used for set the mag power control
+ * bit enable
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_wakeup(void);
+ /*!
+ * @brief This function used for read the trim values of magnetometer
+ *
+ * @note
+ * Before reading the mag trimming values
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_bmm150_mag_trim_mbl(void);
+ /*!
+ * @brief This function used for read the compensated value of mag
+ * Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_compensate_xyz(
+struct smi130_mag_xyz_s32_t *mag_comp_xyz);
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_compensate_xyz_raw(
+struct smi130_mag_xyz_s32_t *mag_comp_xyz, struct smi130_mag_xyzr_t mag_xyzr);
+
+/*!
+ * @brief This API used to get the compensated BMM150-X data
+ * the out put of X as s32
+ * Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_x_s16 : The value of mag raw X data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 smi130_bmm150_mag_compensate_X(s16 v_mag_data_x_s16, u16 v_data_r_u16);
+/*!
+ * @brief This API used to get the compensated BMM150-Y data
+ * the out put of Y as s32
+ * Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_y_s16 : The value of mag raw Y data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated Y data value output as s32
+ */
+s32 smi130_bmm150_mag_compensate_Y(s16 v_mag_data_y_s16, u16 v_data_r_u16);
+/*!
+ * @brief This API used to get the compensated BMM150-Z data
+ * the out put of Z as s32
+ * Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ *
+ * @param v_mag_data_z_s16 : The value of mag raw Z data
+ * @param v_data_r_u16 : The value of mag R data
+ *
+ * @return results of compensated Z data value output as s32
+ */
+s32 smi130_bmm150_mag_compensate_Z(s16 v_mag_data_z_s16, u16 v_data_r_u16);
+/*!
+ * @brief This API used to set the pre-set modes of bmm150
+ * The pre-set mode setting is depend on data rate and xy and z repetitions
+ *
+ * @note
+ * Before set the mag preset mode
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_mode_u8: The value of pre-set mode selection value
+ * value | pre_set mode
+ * ----------|------------
+ * 1 | SMI130_MAG_PRESETMODE_LOWPOWER
+ * 2 | SMI130_MAG_PRESETMODE_REGULAR
+ * 3 | SMI130_MAG_PRESETMODE_HIGHACCURACY
+ * 4 | SMI130_MAG_PRESETMODE_ENHANCED
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_set_bmm150_mag_presetmode(u8 mode);
+/*!
+ * @brief This function used for set the magnetometer
+ * power mode.
+ * @note
+ * Before set the mag power mode
+ * make sure the following two points are addressed
+ * @note
+ * 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note
+ * 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @param v_mag_pow_mode_u8 : The value of mag power mode
+ * value | mode
+ * ----------|------------
+ * 0 | FORCE_MODE
+ * 1 | SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bmm150_mag_set_power_mode(u8 mag_pow_mode);
+ /*!
+ * @brief This function used for set the magnetometer
+ * power mode.
+ * @note
+ * Before set the mag power mode
+ * make sure the following two point is addressed
+ * Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ *
+ * @param v_mag_sec_if_pow_mode_u8 : The value of mag power mode
+ * value | mode
+ * ----------|------------
+ * 0 | SMI130_MAG_FORCE_MODE
+ * 1 | SMI130_MAG_SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_bmm150_mag_and_secondary_if_power_mode(
+u8 v_mag_sec_if_pow_mode_u8);
+/***************************************************/
+/**\name FUNCTIONS FOR AKM09911 AND AKM09912*/
+/***************************************************/
+ /*!
+ * @brief This function used for initialize
+ * the AKM09911 and AKM09912 sensor
+ *
+ *
+ * @param v_akm_i2c_address_u8: The value of device address
+ * AKM sensor | Slave address
+ * --------------|---------------------
+ * AKM09911 | AKM09911_I2C_ADDR_1
+ * - | and AKM09911_I2C_ADDR_2
+ * AKM09912 | AKM09912_I2C_ADDR_1
+ * - | AKM09912_I2C_ADDR_2
+ * - | AKM09912_I2C_ADDR_3
+ * - | AKM09912_I2C_ADDR_4
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm_mag_interface_init(
+u8 v_akm_i2c_address_u8);
+ /*!
+ * @brief This function used for read the sensitivity data of
+ * AKM09911 and AKM09912
+ *
+ * @note Before reading the mag sensitivity values
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_read_bosch_akm_sensitivity_data(void);
+/*!
+ * @brief This API used to get the compensated X data
+ * of AKM09911 the out put of X as s32
+ * @note Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_x_s16 : The value of X data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09911_compensate_X(s16 v_bosch_akm_x_s16);
+/*!
+ * @brief This API used to get the compensated Y data
+ * of AKM09911 the out put of Y as s32
+ * @note Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_y_s16 : The value of Y data
+ *
+ * @return results of compensated Y data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09911_compensate_Y(s16 v_bosch_akm_y_s16);
+/*!
+ * @brief This API used to get the compensated Z data
+ * of AKM09911 the out put of Z as s32
+ * @note Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_z_s16 : The value of Z data
+ *
+ * @return results of compensated Z data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09911_compensate_Z(s16 v_bosch_akm_z_s16);
+/*!
+ * @brief This API used to get the compensated X data
+ * of AKM09912 the out put of X as s32
+ * @note Before start reading the mag compensated X data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_x_s16 : The value of X data
+ *
+ * @return results of compensated X data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09912_compensate_X(s16 v_bosch_akm_x_s16);
+/*!
+ * @brief This API used to get the compensated Y data
+ * of AKM09912 the out put of Y as s32
+ * @note Before start reading the mag compensated Y data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_y_s16 : The value of Y data
+ *
+ * @return results of compensated Y data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09912_compensate_Y(s16 v_bosch_akm_y_s16);
+/*!
+ * @brief This API used to get the compensated Z data
+ * of AKM09912 the out put of Z as s32
+ * @note Before start reading the mag compensated Z data
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ *
+ * @param v_bosch_akm_z_s16 : The value of Z data
+ *
+ * @return results of compensated Z data value output as s32
+ *
+ */
+s32 smi130_bosch_akm09912_compensate_Z(s16 v_bosch_akm_z_s16);
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09911
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm09911_compensate_xyz(
+struct smi130_mag_xyz_s32_t *bosch_akm_xyz);
+ /*!
+ * @brief This function used for read the compensated value of
+ * AKM09912
+ * @note Before start reading the mag compensated data's
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm09912_compensate_xyz(
+struct smi130_mag_xyz_s32_t *bosch_akm_xyz);
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm09912_compensate_xyz_raw(
+struct smi130_mag_xyz_s32_t *bosch_akm_xyz);
+/*!
+ * @brief This function used for set the AKM09911 and AKM09912
+ * power mode.
+ * @note Before set the AKM power mode
+ * make sure the following two points are addressed
+ * @note 1. Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ * @note 2. And also confirm the secondary-interface power mode
+ * is not in the SUSPEND mode.
+ * by using the function smi130_get_mag_pmu_status().
+ * If the secondary-interface power mode is in SUSPEND mode
+ * set the value of 0x19(NORMAL mode)by using the
+ * smi130_set_command_register(0x19) function.
+ *
+ * @param v_akm_pow_mode_u8 : The value of akm power mode
+ * value | Description
+ * ---------|--------------------
+ * 0 | AKM_POWER_DOWN_MODE
+ * 1 | AKM_SINGLE_MEAS_MODE
+ * 2 | FUSE_ROM_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_akm_set_powermode(u8 v_akm_pow_mode_u8);
+ /*!
+ * @brief This function used for set the magnetometer
+ * power mode of AKM09911 and AKM09912
+ * @note Before set the mag power mode
+ * make sure the following two point is addressed
+ * Make sure the mag interface is enabled or not,
+ * by using the smi130_get_if_mode() function.
+ * If mag interface is not enabled set the value of 0x02
+ * to the function smi130_get_if_mode(0x02)
+ *
+ * @param v_mag_sec_if_pow_mode_u8 : The value of secondary if power mode
+ * value | Description
+ * ---------|--------------------
+ * 0 | SMI130_MAG_FORCE_MODE
+ * 1 | SMI130_MAG_SUSPEND_MODE
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_set_bosch_akm_and_secondary_if_powermode(
+u8 v_mag_sec_if_pow_mode_u8);
+/***************************************************/
+/**\name FUNCTIONS FOR YAMAH-YAS532 */
+/***************************************************/
+/*!
+ * @brief This function used for read the YAMAH-YAS532 init
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas532_mag_interface_init(
+void);
+/*!
+ * @brief This function used to set the YAS532 initial values
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_set_initial_values(void);
+/*!
+ * @brief This function used for YAS532 offset correction
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_magnetic_measure_set_offset(
+void);
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS532 calibration data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas532_calib_values(void);
+/*!
+ * @brief This function used for calculate the
+ * YAS532 read the linear data
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_xy1y2_to_linear(
+u16 *v_xy1y2_u16, s32 *xy1y2_linear);
+/*!
+ * @brief This function used for read the YAS532 sensor data
+ * @param v_acquisition_command_u8: used to set the data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ * @param v_busy_u8 : used to get the busy flay for sensor data read
+ * @param v_temp_u16 : used to get the temperature data
+ * @param v_xy1y2_u16 : used to get the sensor xy1y2 data
+ * @param v_overflow_u8 : used to get the overflow data
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_normal_measurement_data(
+u8 v_acquisition_command_u8, u8 *v_busy_u8,
+u16 *v_temp_u16, u16 *v_xy1y2_u16, u8 *v_overflow_u8);
+/*!
+ * @brief This function used for YAS532 sensor data
+ * @param v_acquisition_command_u8 : the value of CMDR
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ * @param xyz_data : the vector xyz output
+ * @param v_overflow_s8 : the value of overflow
+ * @param v_temp_correction_u8 : the value of temperate correction enable
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_measurement_xyz_data(
+struct yas532_vector *xyz_data, u8 *v_overflow_s8, u8 v_temp_correction_u8,
+u8 v_acquisition_command_u8);
+/*!
+ * @brief This function used for YAS532 write data acquisition
+ * command register write
+ * @param v_command_reg_data_u8 : the value of data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_acquisition_command_register(
+u8 v_command_reg_data_u8);
+/*!
+ * @brief This function used write offset of YAS532
+ *
+ * @param p_offset_s8 : The value of offset to write
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas532_set_offset(
+const s8 *p_offset_s8);
+/*!
+ * @brief This function used to init the YAMAH-YAS537
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+*/
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas537_mag_interface_init(
+void);
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 calibration data
+ *
+ *
+ * @param v_rcoil_u8 : The value of r coil
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas537_calib_values(
+u8 v_rcoil_u8);
+/*!
+ * @brief This function used for YAS537 write data acquisition
+ * command register write
+ * @param v_command_reg_data_u8 : the value of data acquisition
+ * acquisition_command | operation
+ * ---------------------|-------------------------
+ * 0x17 | turn on the acquisition coil
+ * - | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Deferred acquisition mode
+ * 0x07 | turn on the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as minus(-))
+ * _ | Normal acquisition mode
+ * 0x11 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Deferred acquisition mode
+ * 0x01 | turn OFF the acquisition coil
+ * _ | set direction of the coil
+ * _ | (x and y as plus(+))
+ * _ | Normal acquisition mode
+ *
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yas537_acquisition_command_register(
+u8 v_command_reg_data_u8);
+
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_coil_stat_u8: The value of R coil status
+ * @param v_busy_u8: The value of busy status
+ * @param v_temperature_u16: The value of temperature
+ * @param xy1y2: The value of raw xy1y2 data
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas537_read_xy1y2_data(
+u8 *v_coil_stat_u8, u8 *v_busy_u8,
+u16 *v_temperature_u16, u16 *xy1y2, u8 *v_ouflow_u8);
+/*!
+ * @brief This function used for read the
+ * YAMAHA YAS537 xy1y2 data
+ *
+ * @param v_ouflow_u8: The value of overflow
+ *
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_bosch_yamaha_yas537_measure_xyz_data(
+u8 *v_ouflow_u8, struct yas_vector *vector_xyz);
+
+/***************************************************/
+/**\name FUNCTIONS FOR FIFO DATA READ */
+/***************************************************/
+/*!
+ * @brief This function used for reading the
+ * fifo data of header less mode
+ *
+ *
+ *
+ * @note Configure the below functions for FIFO header less mode
+ * @note 1. smi130_set_fifo_down_gyro
+ * @note 2. smi130_set_gyro_fifo_filter_data
+ * @note 3. smi130_set_fifo_down_accel
+ * @note 4. smi130_set_accel_fifo_filter_dat
+ * @note 5. smi130_set_fifo_mag_enable
+ * @note 6. smi130_set_fifo_accel_enable
+ * @note 7. smi130_set_fifo_gyro_enable
+ * @note For interrupt configuration
+ * @note 1. smi130_set_intr_fifo_full
+ * @note 2. smi130_set_intr_fifo_wm
+ * @note 3. smi130_set_fifo_tag_intr2_enable
+ * @note 4. smi130_set_fifo_tag_intr1_enable
+ *
+ * @note The fifo reads the whole 1024 bytes
+ * and processing the data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_read_fifo_headerless_mode(
+void);
+/*!
+ * @brief This function used for reading the
+ * fifo data of header less mode for using user defined length
+ *
+ *
+ * @param v_fifo_user_length_u16: The value of length of fifo read data
+ *
+ * @note Configure the below functions for FIFO header less mode
+ * @note 1. smi130_set_fifo_down_gyro
+ * @note 2. smi130_set_gyro_fifo_filter_data
+ * @note 3. smi130_set_fifo_down_accel
+ * @note 4. smi130_set_accel_fifo_filter_dat
+ * @note 5. smi130_set_fifo_mag_enable
+ * @note 6. smi130_set_fifo_accel_enable
+ * @note 7. smi130_set_fifo_gyro_enable
+ * @note For interrupt configuration
+ * @note 1. smi130_set_intr_fifo_full
+ * @note 2. smi130_set_intr_fifo_wm
+ * @note 3. smi130_set_fifo_tag_intr2_enable
+ * @note 4. smi130_set_fifo_tag_intr1_enable
+ *
+ * @note The fifo reads the whole 1024 bytes
+ * and processing the data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE
+smi130_read_fifo_headerless_mode_user_defined_length(
+u16 v_fifo_user_length_u16);
+/*!
+ * @brief This function used for reading the
+ * fifo data of header mode
+ *
+ *
+ * @note Configure the below functions for FIFO header mode
+ * @note 1. smi130_set_fifo_down_gyro()
+ * @note 2. smi130_set_gyro_fifo_filter_data()
+ * @note 3. smi130_set_fifo_down_accel()
+ * @note 4. smi130_set_accel_fifo_filter_dat()
+ * @note 5. smi130_set_fifo_mag_enable()
+ * @note 6. smi130_set_fifo_accel_enable()
+ * @note 7. smi130_set_fifo_gyro_enable()
+ * @note 8. smi130_set_fifo_header_enable()
+ * @note For interrupt configuration
+ * @note 1. smi130_set_intr_fifo_full()
+ * @note 2. smi130_set_intr_fifo_wm()
+ * @note 3. smi130_set_fifo_tag_intr2_enable()
+ * @note 4. smi130_set_fifo_tag_intr1_enable()
+ *
+ * @note The fifo reads the whole 1024 bytes
+ * and processing the data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_read_fifo_header_data(
+void);
+/*!
+ * @brief This function used for reading the
+ * fifo data of header mode for using user defined length
+ *
+ *
+ * @note Configure the below functions for FIFO header mode
+ * @note 1. smi130_set_fifo_down_gyro()
+ * @note 2. smi130_set_gyro_fifo_filter_data()
+ * @note 3. smi130_set_fifo_down_accel()
+ * @note 4. smi130_set_accel_fifo_filter_dat()
+ * @note 5. smi130_set_fifo_mag_enable()
+ * @note 6. smi130_set_fifo_accel_enable()
+ * @note 7. smi130_set_fifo_gyro_enable()
+ * @note 8. smi130_set_fifo_header_enable()
+ * @note For interrupt configuration
+ * @note 1. smi130_set_intr_fifo_full()
+ * @note 2. smi130_set_intr_fifo_wm()
+ * @note 3. smi130_set_fifo_tag_intr2_enable()
+ * @note 4. smi130_set_fifo_tag_intr1_enable()
+ *
+ * @note The fifo reads the whole 1024 bytes
+ * and processing the data
+ *
+ * @return results of bus communication function
+ * @retval 0 -> Success
+ * @retval -1 -> Error
+ *
+ *
+ */
+SMI130_RETURN_FUNCTION_TYPE smi130_read_fifo_header_data_user_defined_length(
+u16 v_fifo_user_length_u16);
+/*!
+ * @brief This function used for reading
+ * smi130_t structure
+ *
+ * @return the reference and values of smi130_t
+ *
+ *
+*/
+struct smi130_t *smi130_get_ptr(void);
+
+#endif
+
diff --git a/drivers/input/sensors/smi130/smi130_acc.c b/drivers/input/sensors/smi130/smi130_acc.c
new file mode 100644
index 000000000000..4828b397eb6f
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130_acc.c
@@ -0,0 +1,7507 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename smi130_acc.c
+ * @date 2015/11/17 10:32
+ * @Modification Date 2018/08/28 18:20
+ * @id "836294d"
+ * @version 2.1.2
+ *
+ * @brief
+ * This file contains all function implementations for the SMI_ACC2X2 in linux
+*/
+
+#ifdef CONFIG_SIG_MOTION
+#undef CONFIG_HAS_EARLYSUSPEND
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/irq.h>
+#include <linux/math64.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+#include "boschclass.h"
+#include "bs_log.h"
+#define DRIVER_VERSION "0.0.53.0"
+#define ACC_NAME "ACC"
+#define SMI_ACC2X2_ENABLE_INT1 1
+#define CONFIG_SMI_ACC_ENABLE_NEWDATA_INT 1
+
+#define SENSOR_NAME "smi130_acc"
+#define SMI130_ACC_USE_BASIC_I2C_FUNC 1
+
+#define MSC_TIME 6
+#define ABSMIN -512
+#define ABSMAX 512
+#define SLOPE_THRESHOLD_VALUE 32
+#define SLOPE_DURATION_VALUE 1
+#define INTERRUPT_LATCH_MODE 13
+#define INTERRUPT_ENABLE 1
+#define INTERRUPT_DISABLE 0
+#define MAP_SLOPE_INTERRUPT 2
+#define SLOPE_X_INDEX 5
+#define SLOPE_Y_INDEX 6
+#define SLOPE_Z_INDEX 7
+#define SMI_ACC2X2_MAX_DELAY 200
+#define SMI_ACC2X2_RANGE_SET 3 /* +/- 2G */
+#define SMI_ACC2X2_BW_SET 12 /* 125HZ */
+
+#define LOW_G_INTERRUPT REL_Z
+#define HIGH_G_INTERRUPT REL_HWHEEL
+#define SLOP_INTERRUPT REL_DIAL
+#define DOUBLE_TAP_INTERRUPT REL_WHEEL
+#define SINGLE_TAP_INTERRUPT REL_MISC
+#define ORIENT_INTERRUPT ABS_PRESSURE
+#define FLAT_INTERRUPT ABS_DISTANCE
+#define SLOW_NO_MOTION_INTERRUPT REL_Y
+
+#define HIGH_G_INTERRUPT_X_HAPPENED 1
+#define HIGH_G_INTERRUPT_Y_HAPPENED 2
+#define HIGH_G_INTERRUPT_Z_HAPPENED 3
+#define HIGH_G_INTERRUPT_X_NEGATIVE_HAPPENED 4
+#define HIGH_G_INTERRUPT_Y_NEGATIVE_HAPPENED 5
+#define HIGH_G_INTERRUPT_Z_NEGATIVE_HAPPENED 6
+#define SLOPE_INTERRUPT_X_HAPPENED 7
+#define SLOPE_INTERRUPT_Y_HAPPENED 8
+#define SLOPE_INTERRUPT_Z_HAPPENED 9
+#define SLOPE_INTERRUPT_X_NEGATIVE_HAPPENED 10
+#define SLOPE_INTERRUPT_Y_NEGATIVE_HAPPENED 11
+#define SLOPE_INTERRUPT_Z_NEGATIVE_HAPPENED 12
+#define DOUBLE_TAP_INTERRUPT_HAPPENED 13
+#define SINGLE_TAP_INTERRUPT_HAPPENED 14
+#define UPWARD_PORTRAIT_UP_INTERRUPT_HAPPENED 15
+#define UPWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED 16
+#define UPWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED 17
+#define UPWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED 18
+#define DOWNWARD_PORTRAIT_UP_INTERRUPT_HAPPENED 19
+#define DOWNWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED 20
+#define DOWNWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED 21
+#define DOWNWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED 22
+#define FLAT_INTERRUPT_TURE_HAPPENED 23
+#define FLAT_INTERRUPT_FALSE_HAPPENED 24
+#define LOW_G_INTERRUPT_HAPPENED 25
+#define SLOW_NO_MOTION_INTERRUPT_HAPPENED 26
+
+#define PAD_LOWG 0
+#define PAD_HIGHG 1
+#define PAD_SLOP 2
+#define PAD_DOUBLE_TAP 3
+#define PAD_SINGLE_TAP 4
+#define PAD_ORIENT 5
+#define PAD_FLAT 6
+#define PAD_SLOW_NO_MOTION 7
+
+#define SMI_ACC2X2_EEP_OFFSET 0x16
+#define SMI_ACC2X2_IMAGE_BASE 0x38
+#define SMI_ACC2X2_IMAGE_LEN 22
+
+#define SMI_ACC2X2_CHIP_ID_REG 0x00
+#define SMI_ACC2X2_VERSION_REG 0x01
+#define SMI_ACC2X2_X_AXIS_LSB_REG 0x02
+#define SMI_ACC2X2_X_AXIS_MSB_REG 0x03
+#define SMI_ACC2X2_Y_AXIS_LSB_REG 0x04
+#define SMI_ACC2X2_Y_AXIS_MSB_REG 0x05
+#define SMI_ACC2X2_Z_AXIS_LSB_REG 0x06
+#define SMI_ACC2X2_Z_AXIS_MSB_REG 0x07
+#define SMI_ACC2X2_TEMPERATURE_REG 0x08
+#define SMI_ACC2X2_STATUS1_REG 0x09
+#define SMI_ACC2X2_STATUS2_REG 0x0A
+#define SMI_ACC2X2_STATUS_TAP_SLOPE_REG 0x0B
+#define SMI_ACC2X2_STATUS_ORIENT_HIGH_REG 0x0C
+#define SMI_ACC2X2_STATUS_FIFO_REG 0x0E
+#define SMI_ACC2X2_RANGE_SEL_REG 0x0F
+#define SMI_ACC2X2_BW_SEL_REG 0x10
+#define SMI_ACC2X2_MODE_CTRL_REG 0x11
+#define SMI_ACC2X2_LOW_NOISE_CTRL_REG 0x12
+#define SMI_ACC2X2_DATA_CTRL_REG 0x13
+#define SMI_ACC2X2_RESET_REG 0x14
+#define SMI_ACC2X2_INT_ENABLE1_REG 0x16
+#define SMI_ACC2X2_INT_ENABLE2_REG 0x17
+#define SMI_ACC2X2_INT_SLO_NO_MOT_REG 0x18
+#define SMI_ACC2X2_INT1_PAD_SEL_REG 0x19
+#define SMI_ACC2X2_INT_DATA_SEL_REG 0x1A
+#define SMI_ACC2X2_INT2_PAD_SEL_REG 0x1B
+#define SMI_ACC2X2_INT_SRC_REG 0x1E
+#define SMI_ACC2X2_INT_SET_REG 0x20
+#define SMI_ACC2X2_INT_CTRL_REG 0x21
+#define SMI_ACC2X2_LOW_DURN_REG 0x22
+#define SMI_ACC2X2_LOW_THRES_REG 0x23
+#define SMI_ACC2X2_LOW_HIGH_HYST_REG 0x24
+#define SMI_ACC2X2_HIGH_DURN_REG 0x25
+#define SMI_ACC2X2_HIGH_THRES_REG 0x26
+#define SMI_ACC2X2_SLOPE_DURN_REG 0x27
+#define SMI_ACC2X2_SLOPE_THRES_REG 0x28
+#define SMI_ACC2X2_SLO_NO_MOT_THRES_REG 0x29
+#define SMI_ACC2X2_TAP_PARAM_REG 0x2A
+#define SMI_ACC2X2_TAP_THRES_REG 0x2B
+#define SMI_ACC2X2_ORIENT_PARAM_REG 0x2C
+#define SMI_ACC2X2_THETA_BLOCK_REG 0x2D
+#define SMI_ACC2X2_THETA_FLAT_REG 0x2E
+#define SMI_ACC2X2_FLAT_HOLD_TIME_REG 0x2F
+#define SMI_ACC2X2_FIFO_WML_TRIG 0x30
+#define SMI_ACC2X2_SELF_TEST_REG 0x32
+#define SMI_ACC2X2_EEPROM_CTRL_REG 0x33
+#define SMI_ACC2X2_SERIAL_CTRL_REG 0x34
+#define SMI_ACC2X2_EXTMODE_CTRL_REG 0x35
+#define SMI_ACC2X2_OFFSET_CTRL_REG 0x36
+#define SMI_ACC2X2_OFFSET_PARAMS_REG 0x37
+#define SMI_ACC2X2_OFFSET_X_AXIS_REG 0x38
+#define SMI_ACC2X2_OFFSET_Y_AXIS_REG 0x39
+#define SMI_ACC2X2_OFFSET_Z_AXIS_REG 0x3A
+#define SMI_ACC2X2_GP0_REG 0x3B
+#define SMI_ACC2X2_GP1_REG 0x3C
+#define SMI_ACC2X2_FIFO_MODE_REG 0x3E
+#define SMI_ACC2X2_FIFO_DATA_OUTPUT_REG 0x3F
+
+#define SMI_ACC2X2_CHIP_ID__POS 0
+#define SMI_ACC2X2_CHIP_ID__MSK 0xFF
+#define SMI_ACC2X2_CHIP_ID__LEN 8
+#define SMI_ACC2X2_CHIP_ID__REG SMI_ACC2X2_CHIP_ID_REG
+
+#define SMI_ACC2X2_VERSION__POS 0
+#define SMI_ACC2X2_VERSION__LEN 8
+#define SMI_ACC2X2_VERSION__MSK 0xFF
+#define SMI_ACC2X2_VERSION__REG SMI_ACC2X2_VERSION_REG
+
+#define SMI130_ACC_SLO_NO_MOT_DUR__POS 2
+#define SMI130_ACC_SLO_NO_MOT_DUR__LEN 6
+#define SMI130_ACC_SLO_NO_MOT_DUR__MSK 0xFC
+#define SMI130_ACC_SLO_NO_MOT_DUR__REG SMI_ACC2X2_SLOPE_DURN_REG
+
+#define SMI_ACC2X2_NEW_DATA_X__POS 0
+#define SMI_ACC2X2_NEW_DATA_X__LEN 1
+#define SMI_ACC2X2_NEW_DATA_X__MSK 0x01
+#define SMI_ACC2X2_NEW_DATA_X__REG SMI_ACC2X2_X_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_X14_LSB__POS 2
+#define SMI_ACC2X2_ACC_X14_LSB__LEN 6
+#define SMI_ACC2X2_ACC_X14_LSB__MSK 0xFC
+#define SMI_ACC2X2_ACC_X14_LSB__REG SMI_ACC2X2_X_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_X12_LSB__POS 4
+#define SMI_ACC2X2_ACC_X12_LSB__LEN 4
+#define SMI_ACC2X2_ACC_X12_LSB__MSK 0xF0
+#define SMI_ACC2X2_ACC_X12_LSB__REG SMI_ACC2X2_X_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_X10_LSB__POS 6
+#define SMI_ACC2X2_ACC_X10_LSB__LEN 2
+#define SMI_ACC2X2_ACC_X10_LSB__MSK 0xC0
+#define SMI_ACC2X2_ACC_X10_LSB__REG SMI_ACC2X2_X_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_X8_LSB__POS 0
+#define SMI_ACC2X2_ACC_X8_LSB__LEN 0
+#define SMI_ACC2X2_ACC_X8_LSB__MSK 0x00
+#define SMI_ACC2X2_ACC_X8_LSB__REG SMI_ACC2X2_X_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_X_MSB__POS 0
+#define SMI_ACC2X2_ACC_X_MSB__LEN 8
+#define SMI_ACC2X2_ACC_X_MSB__MSK 0xFF
+#define SMI_ACC2X2_ACC_X_MSB__REG SMI_ACC2X2_X_AXIS_MSB_REG
+
+#define SMI_ACC2X2_NEW_DATA_Y__POS 0
+#define SMI_ACC2X2_NEW_DATA_Y__LEN 1
+#define SMI_ACC2X2_NEW_DATA_Y__MSK 0x01
+#define SMI_ACC2X2_NEW_DATA_Y__REG SMI_ACC2X2_Y_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Y14_LSB__POS 2
+#define SMI_ACC2X2_ACC_Y14_LSB__LEN 6
+#define SMI_ACC2X2_ACC_Y14_LSB__MSK 0xFC
+#define SMI_ACC2X2_ACC_Y14_LSB__REG SMI_ACC2X2_Y_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Y12_LSB__POS 4
+#define SMI_ACC2X2_ACC_Y12_LSB__LEN 4
+#define SMI_ACC2X2_ACC_Y12_LSB__MSK 0xF0
+#define SMI_ACC2X2_ACC_Y12_LSB__REG SMI_ACC2X2_Y_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Y10_LSB__POS 6
+#define SMI_ACC2X2_ACC_Y10_LSB__LEN 2
+#define SMI_ACC2X2_ACC_Y10_LSB__MSK 0xC0
+#define SMI_ACC2X2_ACC_Y10_LSB__REG SMI_ACC2X2_Y_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Y8_LSB__POS 0
+#define SMI_ACC2X2_ACC_Y8_LSB__LEN 0
+#define SMI_ACC2X2_ACC_Y8_LSB__MSK 0x00
+#define SMI_ACC2X2_ACC_Y8_LSB__REG SMI_ACC2X2_Y_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Y_MSB__POS 0
+#define SMI_ACC2X2_ACC_Y_MSB__LEN 8
+#define SMI_ACC2X2_ACC_Y_MSB__MSK 0xFF
+#define SMI_ACC2X2_ACC_Y_MSB__REG SMI_ACC2X2_Y_AXIS_MSB_REG
+
+#define SMI_ACC2X2_NEW_DATA_Z__POS 0
+#define SMI_ACC2X2_NEW_DATA_Z__LEN 1
+#define SMI_ACC2X2_NEW_DATA_Z__MSK 0x01
+#define SMI_ACC2X2_NEW_DATA_Z__REG SMI_ACC2X2_Z_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Z14_LSB__POS 2
+#define SMI_ACC2X2_ACC_Z14_LSB__LEN 6
+#define SMI_ACC2X2_ACC_Z14_LSB__MSK 0xFC
+#define SMI_ACC2X2_ACC_Z14_LSB__REG SMI_ACC2X2_Z_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Z12_LSB__POS 4
+#define SMI_ACC2X2_ACC_Z12_LSB__LEN 4
+#define SMI_ACC2X2_ACC_Z12_LSB__MSK 0xF0
+#define SMI_ACC2X2_ACC_Z12_LSB__REG SMI_ACC2X2_Z_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Z10_LSB__POS 6
+#define SMI_ACC2X2_ACC_Z10_LSB__LEN 2
+#define SMI_ACC2X2_ACC_Z10_LSB__MSK 0xC0
+#define SMI_ACC2X2_ACC_Z10_LSB__REG SMI_ACC2X2_Z_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Z8_LSB__POS 0
+#define SMI_ACC2X2_ACC_Z8_LSB__LEN 0
+#define SMI_ACC2X2_ACC_Z8_LSB__MSK 0x00
+#define SMI_ACC2X2_ACC_Z8_LSB__REG SMI_ACC2X2_Z_AXIS_LSB_REG
+
+#define SMI_ACC2X2_ACC_Z_MSB__POS 0
+#define SMI_ACC2X2_ACC_Z_MSB__LEN 8
+#define SMI_ACC2X2_ACC_Z_MSB__MSK 0xFF
+#define SMI_ACC2X2_ACC_Z_MSB__REG SMI_ACC2X2_Z_AXIS_MSB_REG
+
+#define SMI_ACC2X2_TEMPERATURE__POS 0
+#define SMI_ACC2X2_TEMPERATURE__LEN 8
+#define SMI_ACC2X2_TEMPERATURE__MSK 0xFF
+#define SMI_ACC2X2_TEMPERATURE__REG SMI_ACC2X2_TEMP_RD_REG
+
+#define SMI_ACC2X2_LOWG_INT_S__POS 0
+#define SMI_ACC2X2_LOWG_INT_S__LEN 1
+#define SMI_ACC2X2_LOWG_INT_S__MSK 0x01
+#define SMI_ACC2X2_LOWG_INT_S__REG SMI_ACC2X2_STATUS1_REG
+
+#define SMI_ACC2X2_HIGHG_INT_S__POS 1
+#define SMI_ACC2X2_HIGHG_INT_S__LEN 1
+#define SMI_ACC2X2_HIGHG_INT_S__MSK 0x02
+#define SMI_ACC2X2_HIGHG_INT_S__REG SMI_ACC2X2_STATUS1_REG
+
+#define SMI_ACC2X2_SLOPE_INT_S__POS 2
+#define SMI_ACC2X2_SLOPE_INT_S__LEN 1
+#define SMI_ACC2X2_SLOPE_INT_S__MSK 0x04
+#define SMI_ACC2X2_SLOPE_INT_S__REG SMI_ACC2X2_STATUS1_REG
+
+
+#define SMI_ACC2X2_SLO_NO_MOT_INT_S__POS 3
+#define SMI_ACC2X2_SLO_NO_MOT_INT_S__LEN 1
+#define SMI_ACC2X2_SLO_NO_MOT_INT_S__MSK 0x08
+#define SMI_ACC2X2_SLO_NO_MOT_INT_S__REG SMI_ACC2X2_STATUS1_REG
+
+#define SMI_ACC2X2_DOUBLE_TAP_INT_S__POS 4
+#define SMI_ACC2X2_DOUBLE_TAP_INT_S__LEN 1
+#define SMI_ACC2X2_DOUBLE_TAP_INT_S__MSK 0x10
+#define SMI_ACC2X2_DOUBLE_TAP_INT_S__REG SMI_ACC2X2_STATUS1_REG
+
+#define SMI_ACC2X2_SINGLE_TAP_INT_S__POS 5
+#define SMI_ACC2X2_SINGLE_TAP_INT_S__LEN 1
+#define SMI_ACC2X2_SINGLE_TAP_INT_S__MSK 0x20
+#define SMI_ACC2X2_SINGLE_TAP_INT_S__REG SMI_ACC2X2_STATUS1_REG
+
+#define SMI_ACC2X2_ORIENT_INT_S__POS 6
+#define SMI_ACC2X2_ORIENT_INT_S__LEN 1
+#define SMI_ACC2X2_ORIENT_INT_S__MSK 0x40
+#define SMI_ACC2X2_ORIENT_INT_S__REG SMI_ACC2X2_STATUS1_REG
+
+#define SMI_ACC2X2_FLAT_INT_S__POS 7
+#define SMI_ACC2X2_FLAT_INT_S__LEN 1
+#define SMI_ACC2X2_FLAT_INT_S__MSK 0x80
+#define SMI_ACC2X2_FLAT_INT_S__REG SMI_ACC2X2_STATUS1_REG
+
+#define SMI_ACC2X2_FIFO_FULL_INT_S__POS 5
+#define SMI_ACC2X2_FIFO_FULL_INT_S__LEN 1
+#define SMI_ACC2X2_FIFO_FULL_INT_S__MSK 0x20
+#define SMI_ACC2X2_FIFO_FULL_INT_S__REG SMI_ACC2X2_STATUS2_REG
+
+#define SMI_ACC2X2_FIFO_WM_INT_S__POS 6
+#define SMI_ACC2X2_FIFO_WM_INT_S__LEN 1
+#define SMI_ACC2X2_FIFO_WM_INT_S__MSK 0x40
+#define SMI_ACC2X2_FIFO_WM_INT_S__REG SMI_ACC2X2_STATUS2_REG
+
+#define SMI_ACC2X2_DATA_INT_S__POS 7
+#define SMI_ACC2X2_DATA_INT_S__LEN 1
+#define SMI_ACC2X2_DATA_INT_S__MSK 0x80
+#define SMI_ACC2X2_DATA_INT_S__REG SMI_ACC2X2_STATUS2_REG
+
+#define SMI_ACC2X2_SLOPE_FIRST_X__POS 0
+#define SMI_ACC2X2_SLOPE_FIRST_X__LEN 1
+#define SMI_ACC2X2_SLOPE_FIRST_X__MSK 0x01
+#define SMI_ACC2X2_SLOPE_FIRST_X__REG SMI_ACC2X2_STATUS_TAP_SLOPE_REG
+
+#define SMI_ACC2X2_SLOPE_FIRST_Y__POS 1
+#define SMI_ACC2X2_SLOPE_FIRST_Y__LEN 1
+#define SMI_ACC2X2_SLOPE_FIRST_Y__MSK 0x02
+#define SMI_ACC2X2_SLOPE_FIRST_Y__REG SMI_ACC2X2_STATUS_TAP_SLOPE_REG
+
+#define SMI_ACC2X2_SLOPE_FIRST_Z__POS 2
+#define SMI_ACC2X2_SLOPE_FIRST_Z__LEN 1
+#define SMI_ACC2X2_SLOPE_FIRST_Z__MSK 0x04
+#define SMI_ACC2X2_SLOPE_FIRST_Z__REG SMI_ACC2X2_STATUS_TAP_SLOPE_REG
+
+#define SMI_ACC2X2_SLOPE_SIGN_S__POS 3
+#define SMI_ACC2X2_SLOPE_SIGN_S__LEN 1
+#define SMI_ACC2X2_SLOPE_SIGN_S__MSK 0x08
+#define SMI_ACC2X2_SLOPE_SIGN_S__REG SMI_ACC2X2_STATUS_TAP_SLOPE_REG
+
+#define SMI_ACC2X2_TAP_FIRST_X__POS 4
+#define SMI_ACC2X2_TAP_FIRST_X__LEN 1
+#define SMI_ACC2X2_TAP_FIRST_X__MSK 0x10
+#define SMI_ACC2X2_TAP_FIRST_X__REG SMI_ACC2X2_STATUS_TAP_SLOPE_REG
+
+#define SMI_ACC2X2_TAP_FIRST_Y__POS 5
+#define SMI_ACC2X2_TAP_FIRST_Y__LEN 1
+#define SMI_ACC2X2_TAP_FIRST_Y__MSK 0x20
+#define SMI_ACC2X2_TAP_FIRST_Y__REG SMI_ACC2X2_STATUS_TAP_SLOPE_REG
+
+#define SMI_ACC2X2_TAP_FIRST_Z__POS 6
+#define SMI_ACC2X2_TAP_FIRST_Z__LEN 1
+#define SMI_ACC2X2_TAP_FIRST_Z__MSK 0x40
+#define SMI_ACC2X2_TAP_FIRST_Z__REG SMI_ACC2X2_STATUS_TAP_SLOPE_REG
+
+#define SMI_ACC2X2_TAP_SIGN_S__POS 7
+#define SMI_ACC2X2_TAP_SIGN_S__LEN 1
+#define SMI_ACC2X2_TAP_SIGN_S__MSK 0x80
+#define SMI_ACC2X2_TAP_SIGN_S__REG SMI_ACC2X2_STATUS_TAP_SLOPE_REG
+
+#define SMI_ACC2X2_HIGHG_FIRST_X__POS 0
+#define SMI_ACC2X2_HIGHG_FIRST_X__LEN 1
+#define SMI_ACC2X2_HIGHG_FIRST_X__MSK 0x01
+#define SMI_ACC2X2_HIGHG_FIRST_X__REG SMI_ACC2X2_STATUS_ORIENT_HIGH_REG
+
+#define SMI_ACC2X2_HIGHG_FIRST_Y__POS 1
+#define SMI_ACC2X2_HIGHG_FIRST_Y__LEN 1
+#define SMI_ACC2X2_HIGHG_FIRST_Y__MSK 0x02
+#define SMI_ACC2X2_HIGHG_FIRST_Y__REG SMI_ACC2X2_STATUS_ORIENT_HIGH_REG
+
+#define SMI_ACC2X2_HIGHG_FIRST_Z__POS 2
+#define SMI_ACC2X2_HIGHG_FIRST_Z__LEN 1
+#define SMI_ACC2X2_HIGHG_FIRST_Z__MSK 0x04
+#define SMI_ACC2X2_HIGHG_FIRST_Z__REG SMI_ACC2X2_STATUS_ORIENT_HIGH_REG
+
+#define SMI_ACC2X2_HIGHG_SIGN_S__POS 3
+#define SMI_ACC2X2_HIGHG_SIGN_S__LEN 1
+#define SMI_ACC2X2_HIGHG_SIGN_S__MSK 0x08
+#define SMI_ACC2X2_HIGHG_SIGN_S__REG SMI_ACC2X2_STATUS_ORIENT_HIGH_REG
+
+#define SMI_ACC2X2_ORIENT_S__POS 4
+#define SMI_ACC2X2_ORIENT_S__LEN 3
+#define SMI_ACC2X2_ORIENT_S__MSK 0x70
+#define SMI_ACC2X2_ORIENT_S__REG SMI_ACC2X2_STATUS_ORIENT_HIGH_REG
+
+#define SMI_ACC2X2_FLAT_S__POS 7
+#define SMI_ACC2X2_FLAT_S__LEN 1
+#define SMI_ACC2X2_FLAT_S__MSK 0x80
+#define SMI_ACC2X2_FLAT_S__REG SMI_ACC2X2_STATUS_ORIENT_HIGH_REG
+
+#define SMI_ACC2X2_FIFO_FRAME_COUNTER_S__POS 0
+#define SMI_ACC2X2_FIFO_FRAME_COUNTER_S__LEN 7
+#define SMI_ACC2X2_FIFO_FRAME_COUNTER_S__MSK 0x7F
+#define SMI_ACC2X2_FIFO_FRAME_COUNTER_S__REG SMI_ACC2X2_STATUS_FIFO_REG
+
+#define SMI_ACC2X2_FIFO_OVERRUN_S__POS 7
+#define SMI_ACC2X2_FIFO_OVERRUN_S__LEN 1
+#define SMI_ACC2X2_FIFO_OVERRUN_S__MSK 0x80
+#define SMI_ACC2X2_FIFO_OVERRUN_S__REG SMI_ACC2X2_STATUS_FIFO_REG
+
+#define SMI_ACC2X2_RANGE_SEL__POS 0
+#define SMI_ACC2X2_RANGE_SEL__LEN 4
+#define SMI_ACC2X2_RANGE_SEL__MSK 0x0F
+#define SMI_ACC2X2_RANGE_SEL__REG SMI_ACC2X2_RANGE_SEL_REG
+
+#define SMI_ACC2X2_BANDWIDTH__POS 0
+#define SMI_ACC2X2_BANDWIDTH__LEN 5
+#define SMI_ACC2X2_BANDWIDTH__MSK 0x1F
+#define SMI_ACC2X2_BANDWIDTH__REG SMI_ACC2X2_BW_SEL_REG
+
+#define SMI_ACC2X2_SLEEP_DUR__POS 1
+#define SMI_ACC2X2_SLEEP_DUR__LEN 4
+#define SMI_ACC2X2_SLEEP_DUR__MSK 0x1E
+#define SMI_ACC2X2_SLEEP_DUR__REG SMI_ACC2X2_MODE_CTRL_REG
+
+#define SMI_ACC2X2_MODE_CTRL__POS 5
+#define SMI_ACC2X2_MODE_CTRL__LEN 3
+#define SMI_ACC2X2_MODE_CTRL__MSK 0xE0
+#define SMI_ACC2X2_MODE_CTRL__REG SMI_ACC2X2_MODE_CTRL_REG
+
+#define SMI_ACC2X2_DEEP_SUSPEND__POS 5
+#define SMI_ACC2X2_DEEP_SUSPEND__LEN 1
+#define SMI_ACC2X2_DEEP_SUSPEND__MSK 0x20
+#define SMI_ACC2X2_DEEP_SUSPEND__REG SMI_ACC2X2_MODE_CTRL_REG
+
+#define SMI_ACC2X2_EN_LOW_POWER__POS 6
+#define SMI_ACC2X2_EN_LOW_POWER__LEN 1
+#define SMI_ACC2X2_EN_LOW_POWER__MSK 0x40
+#define SMI_ACC2X2_EN_LOW_POWER__REG SMI_ACC2X2_MODE_CTRL_REG
+
+#define SMI_ACC2X2_EN_SUSPEND__POS 7
+#define SMI_ACC2X2_EN_SUSPEND__LEN 1
+#define SMI_ACC2X2_EN_SUSPEND__MSK 0x80
+#define SMI_ACC2X2_EN_SUSPEND__REG SMI_ACC2X2_MODE_CTRL_REG
+
+#define SMI_ACC2X2_SLEEP_TIMER__POS 5
+#define SMI_ACC2X2_SLEEP_TIMER__LEN 1
+#define SMI_ACC2X2_SLEEP_TIMER__MSK 0x20
+#define SMI_ACC2X2_SLEEP_TIMER__REG SMI_ACC2X2_LOW_NOISE_CTRL_REG
+
+#define SMI_ACC2X2_LOW_POWER_MODE__POS 6
+#define SMI_ACC2X2_LOW_POWER_MODE__LEN 1
+#define SMI_ACC2X2_LOW_POWER_MODE__MSK 0x40
+#define SMI_ACC2X2_LOW_POWER_MODE__REG SMI_ACC2X2_LOW_NOISE_CTRL_REG
+
+#define SMI_ACC2X2_EN_LOW_NOISE__POS 7
+#define SMI_ACC2X2_EN_LOW_NOISE__LEN 1
+#define SMI_ACC2X2_EN_LOW_NOISE__MSK 0x80
+#define SMI_ACC2X2_EN_LOW_NOISE__REG SMI_ACC2X2_LOW_NOISE_CTRL_REG
+
+#define SMI_ACC2X2_DIS_SHADOW_PROC__POS 6
+#define SMI_ACC2X2_DIS_SHADOW_PROC__LEN 1
+#define SMI_ACC2X2_DIS_SHADOW_PROC__MSK 0x40
+#define SMI_ACC2X2_DIS_SHADOW_PROC__REG SMI_ACC2X2_DATA_CTRL_REG
+
+#define SMI_ACC2X2_EN_DATA_HIGH_BW__POS 7
+#define SMI_ACC2X2_EN_DATA_HIGH_BW__LEN 1
+#define SMI_ACC2X2_EN_DATA_HIGH_BW__MSK 0x80
+#define SMI_ACC2X2_EN_DATA_HIGH_BW__REG SMI_ACC2X2_DATA_CTRL_REG
+
+#define SMI_ACC2X2_EN_SOFT_RESET__POS 0
+#define SMI_ACC2X2_EN_SOFT_RESET__LEN 8
+#define SMI_ACC2X2_EN_SOFT_RESET__MSK 0xFF
+#define SMI_ACC2X2_EN_SOFT_RESET__REG SMI_ACC2X2_RESET_REG
+
+#define SMI_ACC2X2_EN_SOFT_RESET_VALUE 0xB6
+
+#define SMI_ACC2X2_EN_SLOPE_X_INT__POS 0
+#define SMI_ACC2X2_EN_SLOPE_X_INT__LEN 1
+#define SMI_ACC2X2_EN_SLOPE_X_INT__MSK 0x01
+#define SMI_ACC2X2_EN_SLOPE_X_INT__REG SMI_ACC2X2_INT_ENABLE1_REG
+
+#define SMI_ACC2X2_EN_SLOPE_Y_INT__POS 1
+#define SMI_ACC2X2_EN_SLOPE_Y_INT__LEN 1
+#define SMI_ACC2X2_EN_SLOPE_Y_INT__MSK 0x02
+#define SMI_ACC2X2_EN_SLOPE_Y_INT__REG SMI_ACC2X2_INT_ENABLE1_REG
+
+#define SMI_ACC2X2_EN_SLOPE_Z_INT__POS 2
+#define SMI_ACC2X2_EN_SLOPE_Z_INT__LEN 1
+#define SMI_ACC2X2_EN_SLOPE_Z_INT__MSK 0x04
+#define SMI_ACC2X2_EN_SLOPE_Z_INT__REG SMI_ACC2X2_INT_ENABLE1_REG
+
+#define SMI_ACC2X2_EN_DOUBLE_TAP_INT__POS 4
+#define SMI_ACC2X2_EN_DOUBLE_TAP_INT__LEN 1
+#define SMI_ACC2X2_EN_DOUBLE_TAP_INT__MSK 0x10
+#define SMI_ACC2X2_EN_DOUBLE_TAP_INT__REG SMI_ACC2X2_INT_ENABLE1_REG
+
+#define SMI_ACC2X2_EN_SINGLE_TAP_INT__POS 5
+#define SMI_ACC2X2_EN_SINGLE_TAP_INT__LEN 1
+#define SMI_ACC2X2_EN_SINGLE_TAP_INT__MSK 0x20
+#define SMI_ACC2X2_EN_SINGLE_TAP_INT__REG SMI_ACC2X2_INT_ENABLE1_REG
+
+#define SMI_ACC2X2_EN_ORIENT_INT__POS 6
+#define SMI_ACC2X2_EN_ORIENT_INT__LEN 1
+#define SMI_ACC2X2_EN_ORIENT_INT__MSK 0x40
+#define SMI_ACC2X2_EN_ORIENT_INT__REG SMI_ACC2X2_INT_ENABLE1_REG
+
+#define SMI_ACC2X2_EN_FLAT_INT__POS 7
+#define SMI_ACC2X2_EN_FLAT_INT__LEN 1
+#define SMI_ACC2X2_EN_FLAT_INT__MSK 0x80
+#define SMI_ACC2X2_EN_FLAT_INT__REG SMI_ACC2X2_INT_ENABLE1_REG
+
+#define SMI_ACC2X2_EN_HIGHG_X_INT__POS 0
+#define SMI_ACC2X2_EN_HIGHG_X_INT__LEN 1
+#define SMI_ACC2X2_EN_HIGHG_X_INT__MSK 0x01
+#define SMI_ACC2X2_EN_HIGHG_X_INT__REG SMI_ACC2X2_INT_ENABLE2_REG
+
+#define SMI_ACC2X2_EN_HIGHG_Y_INT__POS 1
+#define SMI_ACC2X2_EN_HIGHG_Y_INT__LEN 1
+#define SMI_ACC2X2_EN_HIGHG_Y_INT__MSK 0x02
+#define SMI_ACC2X2_EN_HIGHG_Y_INT__REG SMI_ACC2X2_INT_ENABLE2_REG
+
+#define SMI_ACC2X2_EN_HIGHG_Z_INT__POS 2
+#define SMI_ACC2X2_EN_HIGHG_Z_INT__LEN 1
+#define SMI_ACC2X2_EN_HIGHG_Z_INT__MSK 0x04
+#define SMI_ACC2X2_EN_HIGHG_Z_INT__REG SMI_ACC2X2_INT_ENABLE2_REG
+
+#define SMI_ACC2X2_EN_LOWG_INT__POS 3
+#define SMI_ACC2X2_EN_LOWG_INT__LEN 1
+#define SMI_ACC2X2_EN_LOWG_INT__MSK 0x08
+#define SMI_ACC2X2_EN_LOWG_INT__REG SMI_ACC2X2_INT_ENABLE2_REG
+
+#define SMI_ACC2X2_EN_NEW_DATA_INT__POS 4
+#define SMI_ACC2X2_EN_NEW_DATA_INT__LEN 1
+#define SMI_ACC2X2_EN_NEW_DATA_INT__MSK 0x10
+#define SMI_ACC2X2_EN_NEW_DATA_INT__REG SMI_ACC2X2_INT_ENABLE2_REG
+
+#define SMI_ACC2X2_INT_FFULL_EN_INT__POS 5
+#define SMI_ACC2X2_INT_FFULL_EN_INT__LEN 1
+#define SMI_ACC2X2_INT_FFULL_EN_INT__MSK 0x20
+#define SMI_ACC2X2_INT_FFULL_EN_INT__REG SMI_ACC2X2_INT_ENABLE2_REG
+
+#define SMI_ACC2X2_INT_FWM_EN_INT__POS 6
+#define SMI_ACC2X2_INT_FWM_EN_INT__LEN 1
+#define SMI_ACC2X2_INT_FWM_EN_INT__MSK 0x40
+#define SMI_ACC2X2_INT_FWM_EN_INT__REG SMI_ACC2X2_INT_ENABLE2_REG
+
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_X_INT__POS 0
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_X_INT__LEN 1
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_X_INT__MSK 0x01
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_X_INT__REG SMI_ACC2X2_INT_SLO_NO_MOT_REG
+
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_Y_INT__POS 1
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_Y_INT__LEN 1
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_Y_INT__MSK 0x02
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_Y_INT__REG SMI_ACC2X2_INT_SLO_NO_MOT_REG
+
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_Z_INT__POS 2
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_Z_INT__LEN 1
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_Z_INT__MSK 0x04
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_Z_INT__REG SMI_ACC2X2_INT_SLO_NO_MOT_REG
+
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_SEL_INT__POS 3
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_SEL_INT__LEN 1
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_SEL_INT__MSK 0x08
+#define SMI_ACC2X2_INT_SLO_NO_MOT_EN_SEL_INT__REG SMI_ACC2X2_INT_SLO_NO_MOT_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_LOWG__POS 0
+#define SMI_ACC2X2_EN_INT1_PAD_LOWG__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_LOWG__MSK 0x01
+#define SMI_ACC2X2_EN_INT1_PAD_LOWG__REG SMI_ACC2X2_INT1_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_HIGHG__POS 1
+#define SMI_ACC2X2_EN_INT1_PAD_HIGHG__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_HIGHG__MSK 0x02
+#define SMI_ACC2X2_EN_INT1_PAD_HIGHG__REG SMI_ACC2X2_INT1_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_SLOPE__POS 2
+#define SMI_ACC2X2_EN_INT1_PAD_SLOPE__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_SLOPE__MSK 0x04
+#define SMI_ACC2X2_EN_INT1_PAD_SLOPE__REG SMI_ACC2X2_INT1_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_SLO_NO_MOT__POS 3
+#define SMI_ACC2X2_EN_INT1_PAD_SLO_NO_MOT__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_SLO_NO_MOT__MSK 0x08
+#define SMI_ACC2X2_EN_INT1_PAD_SLO_NO_MOT__REG SMI_ACC2X2_INT1_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_DB_TAP__POS 4
+#define SMI_ACC2X2_EN_INT1_PAD_DB_TAP__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_DB_TAP__MSK 0x10
+#define SMI_ACC2X2_EN_INT1_PAD_DB_TAP__REG SMI_ACC2X2_INT1_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_SNG_TAP__POS 5
+#define SMI_ACC2X2_EN_INT1_PAD_SNG_TAP__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_SNG_TAP__MSK 0x20
+#define SMI_ACC2X2_EN_INT1_PAD_SNG_TAP__REG SMI_ACC2X2_INT1_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_ORIENT__POS 6
+#define SMI_ACC2X2_EN_INT1_PAD_ORIENT__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_ORIENT__MSK 0x40
+#define SMI_ACC2X2_EN_INT1_PAD_ORIENT__REG SMI_ACC2X2_INT1_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_FLAT__POS 7
+#define SMI_ACC2X2_EN_INT1_PAD_FLAT__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_FLAT__MSK 0x80
+#define SMI_ACC2X2_EN_INT1_PAD_FLAT__REG SMI_ACC2X2_INT1_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_LOWG__POS 0
+#define SMI_ACC2X2_EN_INT2_PAD_LOWG__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_LOWG__MSK 0x01
+#define SMI_ACC2X2_EN_INT2_PAD_LOWG__REG SMI_ACC2X2_INT2_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_HIGHG__POS 1
+#define SMI_ACC2X2_EN_INT2_PAD_HIGHG__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_HIGHG__MSK 0x02
+#define SMI_ACC2X2_EN_INT2_PAD_HIGHG__REG SMI_ACC2X2_INT2_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_SLOPE__POS 2
+#define SMI_ACC2X2_EN_INT2_PAD_SLOPE__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_SLOPE__MSK 0x04
+#define SMI_ACC2X2_EN_INT2_PAD_SLOPE__REG SMI_ACC2X2_INT2_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_SLO_NO_MOT__POS 3
+#define SMI_ACC2X2_EN_INT2_PAD_SLO_NO_MOT__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_SLO_NO_MOT__MSK 0x08
+#define SMI_ACC2X2_EN_INT2_PAD_SLO_NO_MOT__REG SMI_ACC2X2_INT2_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_DB_TAP__POS 4
+#define SMI_ACC2X2_EN_INT2_PAD_DB_TAP__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_DB_TAP__MSK 0x10
+#define SMI_ACC2X2_EN_INT2_PAD_DB_TAP__REG SMI_ACC2X2_INT2_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_SNG_TAP__POS 5
+#define SMI_ACC2X2_EN_INT2_PAD_SNG_TAP__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_SNG_TAP__MSK 0x20
+#define SMI_ACC2X2_EN_INT2_PAD_SNG_TAP__REG SMI_ACC2X2_INT2_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_ORIENT__POS 6
+#define SMI_ACC2X2_EN_INT2_PAD_ORIENT__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_ORIENT__MSK 0x40
+#define SMI_ACC2X2_EN_INT2_PAD_ORIENT__REG SMI_ACC2X2_INT2_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_FLAT__POS 7
+#define SMI_ACC2X2_EN_INT2_PAD_FLAT__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_FLAT__MSK 0x80
+#define SMI_ACC2X2_EN_INT2_PAD_FLAT__REG SMI_ACC2X2_INT2_PAD_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_NEWDATA__POS 0
+#define SMI_ACC2X2_EN_INT1_PAD_NEWDATA__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_NEWDATA__MSK 0x01
+#define SMI_ACC2X2_EN_INT1_PAD_NEWDATA__REG SMI_ACC2X2_INT_DATA_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_FWM__POS 1
+#define SMI_ACC2X2_EN_INT1_PAD_FWM__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_FWM__MSK 0x02
+#define SMI_ACC2X2_EN_INT1_PAD_FWM__REG SMI_ACC2X2_INT_DATA_SEL_REG
+
+#define SMI_ACC2X2_EN_INT1_PAD_FFULL__POS 2
+#define SMI_ACC2X2_EN_INT1_PAD_FFULL__LEN 1
+#define SMI_ACC2X2_EN_INT1_PAD_FFULL__MSK 0x04
+#define SMI_ACC2X2_EN_INT1_PAD_FFULL__REG SMI_ACC2X2_INT_DATA_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_FFULL__POS 5
+#define SMI_ACC2X2_EN_INT2_PAD_FFULL__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_FFULL__MSK 0x20
+#define SMI_ACC2X2_EN_INT2_PAD_FFULL__REG SMI_ACC2X2_INT_DATA_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_FWM__POS 6
+#define SMI_ACC2X2_EN_INT2_PAD_FWM__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_FWM__MSK 0x40
+#define SMI_ACC2X2_EN_INT2_PAD_FWM__REG SMI_ACC2X2_INT_DATA_SEL_REG
+
+#define SMI_ACC2X2_EN_INT2_PAD_NEWDATA__POS 7
+#define SMI_ACC2X2_EN_INT2_PAD_NEWDATA__LEN 1
+#define SMI_ACC2X2_EN_INT2_PAD_NEWDATA__MSK 0x80
+#define SMI_ACC2X2_EN_INT2_PAD_NEWDATA__REG SMI_ACC2X2_INT_DATA_SEL_REG
+
+#define SMI_ACC2X2_UNFILT_INT_SRC_LOWG__POS 0
+#define SMI_ACC2X2_UNFILT_INT_SRC_LOWG__LEN 1
+#define SMI_ACC2X2_UNFILT_INT_SRC_LOWG__MSK 0x01
+#define SMI_ACC2X2_UNFILT_INT_SRC_LOWG__REG SMI_ACC2X2_INT_SRC_REG
+
+#define SMI_ACC2X2_UNFILT_INT_SRC_HIGHG__POS 1
+#define SMI_ACC2X2_UNFILT_INT_SRC_HIGHG__LEN 1
+#define SMI_ACC2X2_UNFILT_INT_SRC_HIGHG__MSK 0x02
+#define SMI_ACC2X2_UNFILT_INT_SRC_HIGHG__REG SMI_ACC2X2_INT_SRC_REG
+
+#define SMI_ACC2X2_UNFILT_INT_SRC_SLOPE__POS 2
+#define SMI_ACC2X2_UNFILT_INT_SRC_SLOPE__LEN 1
+#define SMI_ACC2X2_UNFILT_INT_SRC_SLOPE__MSK 0x04
+#define SMI_ACC2X2_UNFILT_INT_SRC_SLOPE__REG SMI_ACC2X2_INT_SRC_REG
+
+#define SMI_ACC2X2_UNFILT_INT_SRC_SLO_NO_MOT__POS 3
+#define SMI_ACC2X2_UNFILT_INT_SRC_SLO_NO_MOT__LEN 1
+#define SMI_ACC2X2_UNFILT_INT_SRC_SLO_NO_MOT__MSK 0x08
+#define SMI_ACC2X2_UNFILT_INT_SRC_SLO_NO_MOT__REG SMI_ACC2X2_INT_SRC_REG
+
+#define SMI_ACC2X2_UNFILT_INT_SRC_TAP__POS 4
+#define SMI_ACC2X2_UNFILT_INT_SRC_TAP__LEN 1
+#define SMI_ACC2X2_UNFILT_INT_SRC_TAP__MSK 0x10
+#define SMI_ACC2X2_UNFILT_INT_SRC_TAP__REG SMI_ACC2X2_INT_SRC_REG
+
+#define SMI_ACC2X2_UNFILT_INT_SRC_DATA__POS 5
+#define SMI_ACC2X2_UNFILT_INT_SRC_DATA__LEN 1
+#define SMI_ACC2X2_UNFILT_INT_SRC_DATA__MSK 0x20
+#define SMI_ACC2X2_UNFILT_INT_SRC_DATA__REG SMI_ACC2X2_INT_SRC_REG
+
+#define SMI_ACC2X2_INT1_PAD_ACTIVE_LEVEL__POS 0
+#define SMI_ACC2X2_INT1_PAD_ACTIVE_LEVEL__LEN 1
+#define SMI_ACC2X2_INT1_PAD_ACTIVE_LEVEL__MSK 0x01
+#define SMI_ACC2X2_INT1_PAD_ACTIVE_LEVEL__REG SMI_ACC2X2_INT_SET_REG
+
+#define SMI_ACC2X2_INT2_PAD_ACTIVE_LEVEL__POS 2
+#define SMI_ACC2X2_INT2_PAD_ACTIVE_LEVEL__LEN 1
+#define SMI_ACC2X2_INT2_PAD_ACTIVE_LEVEL__MSK 0x04
+#define SMI_ACC2X2_INT2_PAD_ACTIVE_LEVEL__REG SMI_ACC2X2_INT_SET_REG
+
+#define SMI_ACC2X2_INT1_PAD_OUTPUT_TYPE__POS 1
+#define SMI_ACC2X2_INT1_PAD_OUTPUT_TYPE__LEN 1
+#define SMI_ACC2X2_INT1_PAD_OUTPUT_TYPE__MSK 0x02
+#define SMI_ACC2X2_INT1_PAD_OUTPUT_TYPE__REG SMI_ACC2X2_INT_SET_REG
+
+#define SMI_ACC2X2_INT2_PAD_OUTPUT_TYPE__POS 3
+#define SMI_ACC2X2_INT2_PAD_OUTPUT_TYPE__LEN 1
+#define SMI_ACC2X2_INT2_PAD_OUTPUT_TYPE__MSK 0x08
+#define SMI_ACC2X2_INT2_PAD_OUTPUT_TYPE__REG SMI_ACC2X2_INT_SET_REG
+
+#define SMI_ACC2X2_INT_MODE_SEL__POS 0
+#define SMI_ACC2X2_INT_MODE_SEL__LEN 4
+#define SMI_ACC2X2_INT_MODE_SEL__MSK 0x0F
+#define SMI_ACC2X2_INT_MODE_SEL__REG SMI_ACC2X2_INT_CTRL_REG
+
+#define SMI_ACC2X2_RESET_INT__POS 7
+#define SMI_ACC2X2_RESET_INT__LEN 1
+#define SMI_ACC2X2_RESET_INT__MSK 0x80
+#define SMI_ACC2X2_RESET_INT__REG SMI_ACC2X2_INT_CTRL_REG
+
+#define SMI_ACC2X2_LOWG_DUR__POS 0
+#define SMI_ACC2X2_LOWG_DUR__LEN 8
+#define SMI_ACC2X2_LOWG_DUR__MSK 0xFF
+#define SMI_ACC2X2_LOWG_DUR__REG SMI_ACC2X2_LOW_DURN_REG
+
+#define SMI_ACC2X2_LOWG_THRES__POS 0
+#define SMI_ACC2X2_LOWG_THRES__LEN 8
+#define SMI_ACC2X2_LOWG_THRES__MSK 0xFF
+#define SMI_ACC2X2_LOWG_THRES__REG SMI_ACC2X2_LOW_THRES_REG
+
+#define SMI_ACC2X2_LOWG_HYST__POS 0
+#define SMI_ACC2X2_LOWG_HYST__LEN 2
+#define SMI_ACC2X2_LOWG_HYST__MSK 0x03
+#define SMI_ACC2X2_LOWG_HYST__REG SMI_ACC2X2_LOW_HIGH_HYST_REG
+
+#define SMI_ACC2X2_LOWG_INT_MODE__POS 2
+#define SMI_ACC2X2_LOWG_INT_MODE__LEN 1
+#define SMI_ACC2X2_LOWG_INT_MODE__MSK 0x04
+#define SMI_ACC2X2_LOWG_INT_MODE__REG SMI_ACC2X2_LOW_HIGH_HYST_REG
+
+#define SMI_ACC2X2_HIGHG_DUR__POS 0
+#define SMI_ACC2X2_HIGHG_DUR__LEN 8
+#define SMI_ACC2X2_HIGHG_DUR__MSK 0xFF
+#define SMI_ACC2X2_HIGHG_DUR__REG SMI_ACC2X2_HIGH_DURN_REG
+
+#define SMI_ACC2X2_HIGHG_THRES__POS 0
+#define SMI_ACC2X2_HIGHG_THRES__LEN 8
+#define SMI_ACC2X2_HIGHG_THRES__MSK 0xFF
+#define SMI_ACC2X2_HIGHG_THRES__REG SMI_ACC2X2_HIGH_THRES_REG
+
+#define SMI_ACC2X2_HIGHG_HYST__POS 6
+#define SMI_ACC2X2_HIGHG_HYST__LEN 2
+#define SMI_ACC2X2_HIGHG_HYST__MSK 0xC0
+#define SMI_ACC2X2_HIGHG_HYST__REG SMI_ACC2X2_LOW_HIGH_HYST_REG
+
+#define SMI_ACC2X2_SLOPE_DUR__POS 0
+#define SMI_ACC2X2_SLOPE_DUR__LEN 2
+#define SMI_ACC2X2_SLOPE_DUR__MSK 0x03
+#define SMI_ACC2X2_SLOPE_DUR__REG SMI_ACC2X2_SLOPE_DURN_REG
+
+#define SMI_ACC2X2_SLO_NO_MOT_DUR__POS 2
+#define SMI_ACC2X2_SLO_NO_MOT_DUR__LEN 6
+#define SMI_ACC2X2_SLO_NO_MOT_DUR__MSK 0xFC
+#define SMI_ACC2X2_SLO_NO_MOT_DUR__REG SMI_ACC2X2_SLOPE_DURN_REG
+
+#define SMI_ACC2X2_SLOPE_THRES__POS 0
+#define SMI_ACC2X2_SLOPE_THRES__LEN 8
+#define SMI_ACC2X2_SLOPE_THRES__MSK 0xFF
+#define SMI_ACC2X2_SLOPE_THRES__REG SMI_ACC2X2_SLOPE_THRES_REG
+
+#define SMI_ACC2X2_SLO_NO_MOT_THRES__POS 0
+#define SMI_ACC2X2_SLO_NO_MOT_THRES__LEN 8
+#define SMI_ACC2X2_SLO_NO_MOT_THRES__MSK 0xFF
+#define SMI_ACC2X2_SLO_NO_MOT_THRES__REG SMI_ACC2X2_SLO_NO_MOT_THRES_REG
+
+#define SMI_ACC2X2_TAP_DUR__POS 0
+#define SMI_ACC2X2_TAP_DUR__LEN 3
+#define SMI_ACC2X2_TAP_DUR__MSK 0x07
+#define SMI_ACC2X2_TAP_DUR__REG SMI_ACC2X2_TAP_PARAM_REG
+
+#define SMI_ACC2X2_TAP_SHOCK_DURN__POS 6
+#define SMI_ACC2X2_TAP_SHOCK_DURN__LEN 1
+#define SMI_ACC2X2_TAP_SHOCK_DURN__MSK 0x40
+#define SMI_ACC2X2_TAP_SHOCK_DURN__REG SMI_ACC2X2_TAP_PARAM_REG
+
+#define SMI_ACC2X2_ADV_TAP_INT__POS 5
+#define SMI_ACC2X2_ADV_TAP_INT__LEN 1
+#define SMI_ACC2X2_ADV_TAP_INT__MSK 0x20
+#define SMI_ACC2X2_ADV_TAP_INT__REG SMI_ACC2X2_TAP_PARAM_REG
+
+#define SMI_ACC2X2_TAP_QUIET_DURN__POS 7
+#define SMI_ACC2X2_TAP_QUIET_DURN__LEN 1
+#define SMI_ACC2X2_TAP_QUIET_DURN__MSK 0x80
+#define SMI_ACC2X2_TAP_QUIET_DURN__REG SMI_ACC2X2_TAP_PARAM_REG
+
+#define SMI_ACC2X2_TAP_THRES__POS 0
+#define SMI_ACC2X2_TAP_THRES__LEN 5
+#define SMI_ACC2X2_TAP_THRES__MSK 0x1F
+#define SMI_ACC2X2_TAP_THRES__REG SMI_ACC2X2_TAP_THRES_REG
+
+#define SMI_ACC2X2_TAP_SAMPLES__POS 6
+#define SMI_ACC2X2_TAP_SAMPLES__LEN 2
+#define SMI_ACC2X2_TAP_SAMPLES__MSK 0xC0
+#define SMI_ACC2X2_TAP_SAMPLES__REG SMI_ACC2X2_TAP_THRES_REG
+
+#define SMI_ACC2X2_ORIENT_MODE__POS 0
+#define SMI_ACC2X2_ORIENT_MODE__LEN 2
+#define SMI_ACC2X2_ORIENT_MODE__MSK 0x03
+#define SMI_ACC2X2_ORIENT_MODE__REG SMI_ACC2X2_ORIENT_PARAM_REG
+
+#define SMI_ACC2X2_ORIENT_BLOCK__POS 2
+#define SMI_ACC2X2_ORIENT_BLOCK__LEN 2
+#define SMI_ACC2X2_ORIENT_BLOCK__MSK 0x0C
+#define SMI_ACC2X2_ORIENT_BLOCK__REG SMI_ACC2X2_ORIENT_PARAM_REG
+
+#define SMI_ACC2X2_ORIENT_HYST__POS 4
+#define SMI_ACC2X2_ORIENT_HYST__LEN 3
+#define SMI_ACC2X2_ORIENT_HYST__MSK 0x70
+#define SMI_ACC2X2_ORIENT_HYST__REG SMI_ACC2X2_ORIENT_PARAM_REG
+
+#define SMI_ACC2X2_ORIENT_AXIS__POS 7
+#define SMI_ACC2X2_ORIENT_AXIS__LEN 1
+#define SMI_ACC2X2_ORIENT_AXIS__MSK 0x80
+#define SMI_ACC2X2_ORIENT_AXIS__REG SMI_ACC2X2_THETA_BLOCK_REG
+
+#define SMI_ACC2X2_ORIENT_UD_EN__POS 6
+#define SMI_ACC2X2_ORIENT_UD_EN__LEN 1
+#define SMI_ACC2X2_ORIENT_UD_EN__MSK 0x40
+#define SMI_ACC2X2_ORIENT_UD_EN__REG SMI_ACC2X2_THETA_BLOCK_REG
+
+#define SMI_ACC2X2_THETA_BLOCK__POS 0
+#define SMI_ACC2X2_THETA_BLOCK__LEN 6
+#define SMI_ACC2X2_THETA_BLOCK__MSK 0x3F
+#define SMI_ACC2X2_THETA_BLOCK__REG SMI_ACC2X2_THETA_BLOCK_REG
+
+#define SMI_ACC2X2_THETA_FLAT__POS 0
+#define SMI_ACC2X2_THETA_FLAT__LEN 6
+#define SMI_ACC2X2_THETA_FLAT__MSK 0x3F
+#define SMI_ACC2X2_THETA_FLAT__REG SMI_ACC2X2_THETA_FLAT_REG
+
+#define SMI_ACC2X2_FLAT_HOLD_TIME__POS 4
+#define SMI_ACC2X2_FLAT_HOLD_TIME__LEN 2
+#define SMI_ACC2X2_FLAT_HOLD_TIME__MSK 0x30
+#define SMI_ACC2X2_FLAT_HOLD_TIME__REG SMI_ACC2X2_FLAT_HOLD_TIME_REG
+
+#define SMI_ACC2X2_FLAT_HYS__POS 0
+#define SMI_ACC2X2_FLAT_HYS__LEN 3
+#define SMI_ACC2X2_FLAT_HYS__MSK 0x07
+#define SMI_ACC2X2_FLAT_HYS__REG SMI_ACC2X2_FLAT_HOLD_TIME_REG
+
+#define SMI_ACC2X2_FIFO_WML_TRIG_RETAIN__POS 0
+#define SMI_ACC2X2_FIFO_WML_TRIG_RETAIN__LEN 6
+#define SMI_ACC2X2_FIFO_WML_TRIG_RETAIN__MSK 0x3F
+#define SMI_ACC2X2_FIFO_WML_TRIG_RETAIN__REG SMI_ACC2X2_FIFO_WML_TRIG
+
+#define SMI_ACC2X2_EN_SELF_TEST__POS 0
+#define SMI_ACC2X2_EN_SELF_TEST__LEN 2
+#define SMI_ACC2X2_EN_SELF_TEST__MSK 0x03
+#define SMI_ACC2X2_EN_SELF_TEST__REG SMI_ACC2X2_SELF_TEST_REG
+
+#define SMI_ACC2X2_NEG_SELF_TEST__POS 2
+#define SMI_ACC2X2_NEG_SELF_TEST__LEN 1
+#define SMI_ACC2X2_NEG_SELF_TEST__MSK 0x04
+#define SMI_ACC2X2_NEG_SELF_TEST__REG SMI_ACC2X2_SELF_TEST_REG
+
+#define SMI_ACC2X2_SELF_TEST_AMP__POS 4
+#define SMI_ACC2X2_SELF_TEST_AMP__LEN 1
+#define SMI_ACC2X2_SELF_TEST_AMP__MSK 0x10
+#define SMI_ACC2X2_SELF_TEST_AMP__REG SMI_ACC2X2_SELF_TEST_REG
+
+
+#define SMI_ACC2X2_UNLOCK_EE_PROG_MODE__POS 0
+#define SMI_ACC2X2_UNLOCK_EE_PROG_MODE__LEN 1
+#define SMI_ACC2X2_UNLOCK_EE_PROG_MODE__MSK 0x01
+#define SMI_ACC2X2_UNLOCK_EE_PROG_MODE__REG SMI_ACC2X2_EEPROM_CTRL_REG
+
+#define SMI_ACC2X2_START_EE_PROG_TRIG__POS 1
+#define SMI_ACC2X2_START_EE_PROG_TRIG__LEN 1
+#define SMI_ACC2X2_START_EE_PROG_TRIG__MSK 0x02
+#define SMI_ACC2X2_START_EE_PROG_TRIG__REG SMI_ACC2X2_EEPROM_CTRL_REG
+
+#define SMI_ACC2X2_EE_PROG_READY__POS 2
+#define SMI_ACC2X2_EE_PROG_READY__LEN 1
+#define SMI_ACC2X2_EE_PROG_READY__MSK 0x04
+#define SMI_ACC2X2_EE_PROG_READY__REG SMI_ACC2X2_EEPROM_CTRL_REG
+
+#define SMI_ACC2X2_UPDATE_IMAGE__POS 3
+#define SMI_ACC2X2_UPDATE_IMAGE__LEN 1
+#define SMI_ACC2X2_UPDATE_IMAGE__MSK 0x08
+#define SMI_ACC2X2_UPDATE_IMAGE__REG SMI_ACC2X2_EEPROM_CTRL_REG
+
+#define SMI_ACC2X2_EE_REMAIN__POS 4
+#define SMI_ACC2X2_EE_REMAIN__LEN 4
+#define SMI_ACC2X2_EE_REMAIN__MSK 0xF0
+#define SMI_ACC2X2_EE_REMAIN__REG SMI_ACC2X2_EEPROM_CTRL_REG
+
+#define SMI_ACC2X2_EN_SPI_MODE_3__POS 0
+#define SMI_ACC2X2_EN_SPI_MODE_3__LEN 1
+#define SMI_ACC2X2_EN_SPI_MODE_3__MSK 0x01
+#define SMI_ACC2X2_EN_SPI_MODE_3__REG SMI_ACC2X2_SERIAL_CTRL_REG
+
+#define SMI_ACC2X2_I2C_WATCHDOG_PERIOD__POS 1
+#define SMI_ACC2X2_I2C_WATCHDOG_PERIOD__LEN 1
+#define SMI_ACC2X2_I2C_WATCHDOG_PERIOD__MSK 0x02
+#define SMI_ACC2X2_I2C_WATCHDOG_PERIOD__REG SMI_ACC2X2_SERIAL_CTRL_REG
+
+#define SMI_ACC2X2_EN_I2C_WATCHDOG__POS 2
+#define SMI_ACC2X2_EN_I2C_WATCHDOG__LEN 1
+#define SMI_ACC2X2_EN_I2C_WATCHDOG__MSK 0x04
+#define SMI_ACC2X2_EN_I2C_WATCHDOG__REG SMI_ACC2X2_SERIAL_CTRL_REG
+
+#define SMI_ACC2X2_EXT_MODE__POS 7
+#define SMI_ACC2X2_EXT_MODE__LEN 1
+#define SMI_ACC2X2_EXT_MODE__MSK 0x80
+#define SMI_ACC2X2_EXT_MODE__REG SMI_ACC2X2_EXTMODE_CTRL_REG
+
+#define SMI_ACC2X2_ALLOW_UPPER__POS 6
+#define SMI_ACC2X2_ALLOW_UPPER__LEN 1
+#define SMI_ACC2X2_ALLOW_UPPER__MSK 0x40
+#define SMI_ACC2X2_ALLOW_UPPER__REG SMI_ACC2X2_EXTMODE_CTRL_REG
+
+#define SMI_ACC2X2_MAP_2_LOWER__POS 5
+#define SMI_ACC2X2_MAP_2_LOWER__LEN 1
+#define SMI_ACC2X2_MAP_2_LOWER__MSK 0x20
+#define SMI_ACC2X2_MAP_2_LOWER__REG SMI_ACC2X2_EXTMODE_CTRL_REG
+
+#define SMI_ACC2X2_MAGIC_NUMBER__POS 0
+#define SMI_ACC2X2_MAGIC_NUMBER__LEN 5
+#define SMI_ACC2X2_MAGIC_NUMBER__MSK 0x1F
+#define SMI_ACC2X2_MAGIC_NUMBER__REG SMI_ACC2X2_EXTMODE_CTRL_REG
+
+#define SMI_ACC2X2_UNLOCK_EE_WRITE_TRIM__POS 4
+#define SMI_ACC2X2_UNLOCK_EE_WRITE_TRIM__LEN 4
+#define SMI_ACC2X2_UNLOCK_EE_WRITE_TRIM__MSK 0xF0
+#define SMI_ACC2X2_UNLOCK_EE_WRITE_TRIM__REG SMI_ACC2X2_CTRL_UNLOCK_REG
+
+#define SMI_ACC2X2_EN_SLOW_COMP_X__POS 0
+#define SMI_ACC2X2_EN_SLOW_COMP_X__LEN 1
+#define SMI_ACC2X2_EN_SLOW_COMP_X__MSK 0x01
+#define SMI_ACC2X2_EN_SLOW_COMP_X__REG SMI_ACC2X2_OFFSET_CTRL_REG
+
+#define SMI_ACC2X2_EN_SLOW_COMP_Y__POS 1
+#define SMI_ACC2X2_EN_SLOW_COMP_Y__LEN 1
+#define SMI_ACC2X2_EN_SLOW_COMP_Y__MSK 0x02
+#define SMI_ACC2X2_EN_SLOW_COMP_Y__REG SMI_ACC2X2_OFFSET_CTRL_REG
+
+#define SMI_ACC2X2_EN_SLOW_COMP_Z__POS 2
+#define SMI_ACC2X2_EN_SLOW_COMP_Z__LEN 1
+#define SMI_ACC2X2_EN_SLOW_COMP_Z__MSK 0x04
+#define SMI_ACC2X2_EN_SLOW_COMP_Z__REG SMI_ACC2X2_OFFSET_CTRL_REG
+
+#define SMI_ACC2X2_FAST_CAL_RDY_S__POS 4
+#define SMI_ACC2X2_FAST_CAL_RDY_S__LEN 1
+#define SMI_ACC2X2_FAST_CAL_RDY_S__MSK 0x10
+#define SMI_ACC2X2_FAST_CAL_RDY_S__REG SMI_ACC2X2_OFFSET_CTRL_REG
+
+#define SMI_ACC2X2_CAL_TRIGGER__POS 5
+#define SMI_ACC2X2_CAL_TRIGGER__LEN 2
+#define SMI_ACC2X2_CAL_TRIGGER__MSK 0x60
+#define SMI_ACC2X2_CAL_TRIGGER__REG SMI_ACC2X2_OFFSET_CTRL_REG
+
+#define SMI_ACC2X2_RESET_OFFSET_REGS__POS 7
+#define SMI_ACC2X2_RESET_OFFSET_REGS__LEN 1
+#define SMI_ACC2X2_RESET_OFFSET_REGS__MSK 0x80
+#define SMI_ACC2X2_RESET_OFFSET_REGS__REG SMI_ACC2X2_OFFSET_CTRL_REG
+
+#define SMI_ACC2X2_COMP_CUTOFF__POS 0
+#define SMI_ACC2X2_COMP_CUTOFF__LEN 1
+#define SMI_ACC2X2_COMP_CUTOFF__MSK 0x01
+#define SMI_ACC2X2_COMP_CUTOFF__REG SMI_ACC2X2_OFFSET_PARAMS_REG
+
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_X__POS 1
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_X__LEN 2
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_X__MSK 0x06
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_X__REG SMI_ACC2X2_OFFSET_PARAMS_REG
+
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_Y__POS 3
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_Y__LEN 2
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_Y__MSK 0x18
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_Y__REG SMI_ACC2X2_OFFSET_PARAMS_REG
+
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_Z__POS 5
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_Z__LEN 2
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_Z__MSK 0x60
+#define SMI_ACC2X2_COMP_TARGET_OFFSET_Z__REG SMI_ACC2X2_OFFSET_PARAMS_REG
+
+#define SMI_ACC2X2_FIFO_DATA_SELECT__POS 0
+#define SMI_ACC2X2_FIFO_DATA_SELECT__LEN 2
+#define SMI_ACC2X2_FIFO_DATA_SELECT__MSK 0x03
+#define SMI_ACC2X2_FIFO_DATA_SELECT__REG SMI_ACC2X2_FIFO_MODE_REG
+
+#define SMI_ACC2X2_FIFO_TRIGGER_SOURCE__POS 2
+#define SMI_ACC2X2_FIFO_TRIGGER_SOURCE__LEN 2
+#define SMI_ACC2X2_FIFO_TRIGGER_SOURCE__MSK 0x0C
+#define SMI_ACC2X2_FIFO_TRIGGER_SOURCE__REG SMI_ACC2X2_FIFO_MODE_REG
+
+#define SMI_ACC2X2_FIFO_TRIGGER_ACTION__POS 4
+#define SMI_ACC2X2_FIFO_TRIGGER_ACTION__LEN 2
+#define SMI_ACC2X2_FIFO_TRIGGER_ACTION__MSK 0x30
+#define SMI_ACC2X2_FIFO_TRIGGER_ACTION__REG SMI_ACC2X2_FIFO_MODE_REG
+
+#define SMI_ACC2X2_FIFO_MODE__POS 6
+#define SMI_ACC2X2_FIFO_MODE__LEN 2
+#define SMI_ACC2X2_FIFO_MODE__MSK 0xC0
+#define SMI_ACC2X2_FIFO_MODE__REG SMI_ACC2X2_FIFO_MODE_REG
+
+
+#define SMI_ACC2X2_STATUS1 0
+#define SMI_ACC2X2_STATUS2 1
+#define SMI_ACC2X2_STATUS3 2
+#define SMI_ACC2X2_STATUS4 3
+#define SMI_ACC2X2_STATUS5 4
+
+
+#define SMI_ACC2X2_RANGE_2G 3
+#define SMI_ACC2X2_RANGE_4G 5
+#define SMI_ACC2X2_RANGE_8G 8
+#define SMI_ACC2X2_RANGE_16G 12
+
+
+#define SMI_ACC2X2_BW_7_81HZ 0x08
+#define SMI_ACC2X2_BW_15_63HZ 0x09
+#define SMI_ACC2X2_BW_31_25HZ 0x0A
+#define SMI_ACC2X2_BW_62_50HZ 0x0B
+#define SMI_ACC2X2_BW_125HZ 0x0C
+#define SMI_ACC2X2_BW_250HZ 0x0D
+#define SMI_ACC2X2_BW_500HZ 0x0E
+#define SMI_ACC2X2_BW_1000HZ 0x0F
+
+#define SMI_ACC2X2_SLEEP_DUR_0_5MS 0x05
+#define SMI_ACC2X2_SLEEP_DUR_1MS 0x06
+#define SMI_ACC2X2_SLEEP_DUR_2MS 0x07
+#define SMI_ACC2X2_SLEEP_DUR_4MS 0x08
+#define SMI_ACC2X2_SLEEP_DUR_6MS 0x09
+#define SMI_ACC2X2_SLEEP_DUR_10MS 0x0A
+#define SMI_ACC2X2_SLEEP_DUR_25MS 0x0B
+#define SMI_ACC2X2_SLEEP_DUR_50MS 0x0C
+#define SMI_ACC2X2_SLEEP_DUR_100MS 0x0D
+#define SMI_ACC2X2_SLEEP_DUR_500MS 0x0E
+#define SMI_ACC2X2_SLEEP_DUR_1S 0x0F
+
+#define SMI_ACC2X2_LATCH_DUR_NON_LATCH 0x00
+#define SMI_ACC2X2_LATCH_DUR_250MS 0x01
+#define SMI_ACC2X2_LATCH_DUR_500MS 0x02
+#define SMI_ACC2X2_LATCH_DUR_1S 0x03
+#define SMI_ACC2X2_LATCH_DUR_2S 0x04
+#define SMI_ACC2X2_LATCH_DUR_4S 0x05
+#define SMI_ACC2X2_LATCH_DUR_8S 0x06
+#define SMI_ACC2X2_LATCH_DUR_LATCH 0x07
+#define SMI_ACC2X2_LATCH_DUR_NON_LATCH1 0x08
+#define SMI_ACC2X2_LATCH_DUR_250US 0x09
+#define SMI_ACC2X2_LATCH_DUR_500US 0x0A
+#define SMI_ACC2X2_LATCH_DUR_1MS 0x0B
+#define SMI_ACC2X2_LATCH_DUR_12_5MS 0x0C
+#define SMI_ACC2X2_LATCH_DUR_25MS 0x0D
+#define SMI_ACC2X2_LATCH_DUR_50MS 0x0E
+#define SMI_ACC2X2_LATCH_DUR_LATCH1 0x0F
+
+#define SMI_ACC2X2_MODE_NORMAL 0
+#define SMI_ACC2X2_MODE_LOWPOWER1 1
+#define SMI_ACC2X2_MODE_SUSPEND 2
+#define SMI_ACC2X2_MODE_DEEP_SUSPEND 3
+#define SMI_ACC2X2_MODE_LOWPOWER2 4
+#define SMI_ACC2X2_MODE_STANDBY 5
+
+#define SMI_ACC2X2_X_AXIS 0
+#define SMI_ACC2X2_Y_AXIS 1
+#define SMI_ACC2X2_Z_AXIS 2
+
+#define SMI_ACC2X2_Low_G_Interrupt 0
+#define SMI_ACC2X2_High_G_X_Interrupt 1
+#define SMI_ACC2X2_High_G_Y_Interrupt 2
+#define SMI_ACC2X2_High_G_Z_Interrupt 3
+#define SMI_ACC2X2_DATA_EN 4
+#define SMI_ACC2X2_Slope_X_Interrupt 5
+#define SMI_ACC2X2_Slope_Y_Interrupt 6
+#define SMI_ACC2X2_Slope_Z_Interrupt 7
+#define SMI_ACC2X2_Single_Tap_Interrupt 8
+#define SMI_ACC2X2_Double_Tap_Interrupt 9
+#define SMI_ACC2X2_Orient_Interrupt 10
+#define SMI_ACC2X2_Flat_Interrupt 11
+#define SMI_ACC2X2_FFULL_INTERRUPT 12
+#define SMI_ACC2X2_FWM_INTERRUPT 13
+
+#define SMI_ACC2X2_INT1_LOWG 0
+#define SMI_ACC2X2_INT2_LOWG 1
+#define SMI_ACC2X2_INT1_HIGHG 0
+#define SMI_ACC2X2_INT2_HIGHG 1
+#define SMI_ACC2X2_INT1_SLOPE 0
+#define SMI_ACC2X2_INT2_SLOPE 1
+#define SMI_ACC2X2_INT1_SLO_NO_MOT 0
+#define SMI_ACC2X2_INT2_SLO_NO_MOT 1
+#define SMI_ACC2X2_INT1_DTAP 0
+#define SMI_ACC2X2_INT2_DTAP 1
+#define SMI_ACC2X2_INT1_STAP 0
+#define SMI_ACC2X2_INT2_STAP 1
+#define SMI_ACC2X2_INT1_ORIENT 0
+#define SMI_ACC2X2_INT2_ORIENT 1
+#define SMI_ACC2X2_INT1_FLAT 0
+#define SMI_ACC2X2_INT2_FLAT 1
+#define SMI_ACC2X2_INT1_NDATA 0
+#define SMI_ACC2X2_INT2_NDATA 1
+#define SMI_ACC2X2_INT1_FWM 0
+#define SMI_ACC2X2_INT2_FWM 1
+#define SMI_ACC2X2_INT1_FFULL 0
+#define SMI_ACC2X2_INT2_FFULL 1
+
+#define SMI_ACC2X2_SRC_LOWG 0
+#define SMI_ACC2X2_SRC_HIGHG 1
+#define SMI_ACC2X2_SRC_SLOPE 2
+#define SMI_ACC2X2_SRC_SLO_NO_MOT 3
+#define SMI_ACC2X2_SRC_TAP 4
+#define SMI_ACC2X2_SRC_DATA 5
+
+#define SMI_ACC2X2_INT1_OUTPUT 0
+#define SMI_ACC2X2_INT2_OUTPUT 1
+#define SMI_ACC2X2_INT1_LEVEL 0
+#define SMI_ACC2X2_INT2_LEVEL 1
+
+#define SMI_ACC2X2_LOW_DURATION 0
+#define SMI_ACC2X2_HIGH_DURATION 1
+#define SMI_ACC2X2_SLOPE_DURATION 2
+#define SMI_ACC2X2_SLO_NO_MOT_DURATION 3
+
+#define SMI_ACC2X2_LOW_THRESHOLD 0
+#define SMI_ACC2X2_HIGH_THRESHOLD 1
+#define SMI_ACC2X2_SLOPE_THRESHOLD 2
+#define SMI_ACC2X2_SLO_NO_MOT_THRESHOLD 3
+
+
+#define SMI_ACC2X2_LOWG_HYST 0
+#define SMI_ACC2X2_HIGHG_HYST 1
+
+#define SMI_ACC2X2_ORIENT_THETA 0
+#define SMI_ACC2X2_FLAT_THETA 1
+
+#define SMI_ACC2X2_I2C_SELECT 0
+#define SMI_ACC2X2_I2C_EN 1
+
+#define SMI_ACC2X2_SLOW_COMP_X 0
+#define SMI_ACC2X2_SLOW_COMP_Y 1
+#define SMI_ACC2X2_SLOW_COMP_Z 2
+
+#define SMI_ACC2X2_CUT_OFF 0
+#define SMI_ACC2X2_OFFSET_TRIGGER_X 1
+#define SMI_ACC2X2_OFFSET_TRIGGER_Y 2
+#define SMI_ACC2X2_OFFSET_TRIGGER_Z 3
+
+#define SMI_ACC2X2_GP0 0
+#define SMI_ACC2X2_GP1 1
+
+#define SMI_ACC2X2_SLO_NO_MOT_EN_X 0
+#define SMI_ACC2X2_SLO_NO_MOT_EN_Y 1
+#define SMI_ACC2X2_SLO_NO_MOT_EN_Z 2
+#define SMI_ACC2X2_SLO_NO_MOT_EN_SEL 3
+
+#define SMI_ACC2X2_WAKE_UP_DUR_20MS 0
+#define SMI_ACC2X2_WAKE_UP_DUR_80MS 1
+#define SMI_ACC2X2_WAKE_UP_DUR_320MS 2
+#define SMI_ACC2X2_WAKE_UP_DUR_2560MS 3
+
+#define SMI_ACC2X2_SELF_TEST0_ON 1
+#define SMI_ACC2X2_SELF_TEST1_ON 2
+
+#define SMI_ACC2X2_EE_W_OFF 0
+#define SMI_ACC2X2_EE_W_ON 1
+
+#define SMI_ACC2X2_LOW_TH_IN_G(gthres, range) ((256 * gthres) / range)
+
+
+#define SMI_ACC2X2_HIGH_TH_IN_G(gthres, range) ((256 * gthres) / range)
+
+
+#define SMI_ACC2X2_LOW_HY_IN_G(ghyst, range) ((32 * ghyst) / range)
+
+
+#define SMI_ACC2X2_HIGH_HY_IN_G(ghyst, range) ((32 * ghyst) / range)
+
+
+#define SMI_ACC2X2_SLOPE_TH_IN_G(gthres, range) ((128 * gthres) / range)
+
+
+#define SMI_ACC2X2_GET_BITSLICE(regvar, bitname)\
+ ((regvar & bitname##__MSK) >> bitname##__POS)
+
+
+#define SMI_ACC2X2_SET_BITSLICE(regvar, bitname, val)\
+ ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK))
+
+#define CHECK_CHIP_ID_TIME_MAX 5
+#define SMI_ACC255_CHIP_ID 0XFA
+#define SMI_ACC250E_CHIP_ID 0XF9
+#define SMI_ACC222E_CHIP_ID 0XF8
+#define SMI_ACC280_CHIP_ID 0XFB
+#define SMI_ACC355_CHIP_ID 0XEA
+
+#define SMI_ACC255_TYPE 0
+#define SMI_ACC250E_TYPE 1
+#define SMI_ACC222E_TYPE 2
+#define SMI_ACC280_TYPE 3
+
+#define MAX_FIFO_F_LEVEL 32
+#define MAX_FIFO_F_BYTES 6
+#define SMI_ACC_MAX_RETRY_I2C_XFER (100)
+
+#ifdef CONFIG_DOUBLE_TAP
+#define DEFAULT_TAP_JUDGE_PERIOD 1000 /* default judge in 1 second */
+#endif
+
+/*! Bosch sensor unknown place*/
+#define BOSCH_SENSOR_PLACE_UNKNOWN (-1)
+/*! Bosch sensor remapping table size P0~P7*/
+#define MAX_AXIS_REMAP_TAB_SZ 8
+
+/* How was SMI_ACC enabled(set to operation mode) */
+#define SMI_ACC_ENABLED_ALL 0
+#define SMI_ACC_ENABLED_SGM 1
+#define SMI_ACC_ENABLED_DTAP 2
+#define SMI_ACC_ENABLED_INPUT 3
+#define SMI_ACC_ENABLED_BSX 4
+
+
+/*!
+ * @brief:BMI058 feature
+ * macro definition
+*/
+
+#define SMI_ACC2X2_FIFO_DAT_SEL_X 1
+#define SMI_ACC2X2_FIFO_DAT_SEL_Y 2
+#define SMI_ACC2X2_FIFO_DAT_SEL_Z 3
+
+#ifdef CONFIG_SENSORS_BMI058
+#define C_BMI058_One_U8X 1
+#define C_BMI058_Two_U8X 2
+#define BMI058_OFFSET_TRIGGER_X SMI_ACC2X2_OFFSET_TRIGGER_Y
+#define BMI058_OFFSET_TRIGGER_Y SMI_ACC2X2_OFFSET_TRIGGER_X
+
+/*! BMI058 X AXIS OFFSET REG definition*/
+#define BMI058_OFFSET_X_AXIS_REG SMI_ACC2X2_OFFSET_Y_AXIS_REG
+/*! BMI058 Y AXIS OFFSET REG definition*/
+#define BMI058_OFFSET_Y_AXIS_REG SMI_ACC2X2_OFFSET_X_AXIS_REG
+
+#define BMI058_FIFO_DAT_SEL_X SMI_ACC2X2_FIFO_DAT_SEL_Y
+#define BMI058_FIFO_DAT_SEL_Y SMI_ACC2X2_FIFO_DAT_SEL_X
+
+/*! SMI130_ACC common slow no motion X interrupt type definition*/
+#define SMI_ACC2X2_SLOW_NO_MOT_X_INT 12
+/*! SMI130_ACC common slow no motion Y interrupt type definition*/
+#define SMI_ACC2X2_SLOW_NO_MOT_Y_INT 13
+/*! SMI130_ACC common High G X interrupt type definition*/
+#define SMI_ACC2X2_HIGHG_X_INT 1
+/*! SMI130_ACC common High G Y interrupt type definition*/
+#define SMI_ACC2X2_HIGHG_Y_INT 2
+/*! SMI130_ACC common slope X interrupt type definition*/
+#define SMI_ACC2X2_SLOPE_X_INT 5
+/*! SMI130_ACC common slope Y interrupt type definition*/
+#define SMI_ACC2X2_SLOPE_Y_INT 6
+
+/*! this structure holds some interrupt types difference
+**between SMI130_ACC and BMI058.
+*/
+struct interrupt_map_t {
+ int x;
+ int y;
+};
+/*!*Need to use SMI130_ACC Common interrupt type definition to
+* instead of Some of BMI058 reversed Interrupt type
+* because of HW Register.
+* The reversed Interrupt types contain:
+* slow_no_mot_x_int && slow_not_mot_y_int
+* highg_x_int && highg_y_int
+* slope_x_int && slope_y_int
+**/
+static const struct interrupt_map_t int_map[] = {
+ {SMI_ACC2X2_SLOW_NO_MOT_X_INT, SMI_ACC2X2_SLOW_NO_MOT_Y_INT},
+ {SMI_ACC2X2_HIGHG_X_INT, SMI_ACC2X2_HIGHG_Y_INT},
+ {SMI_ACC2X2_SLOPE_X_INT, SMI_ACC2X2_SLOPE_Y_INT}
+};
+
+/*! high g or slope interrupt type definition for BMI058*/
+/*! High G interrupt of x, y, z axis happened */
+#define HIGH_G_INTERRUPT_X HIGH_G_INTERRUPT_Y_HAPPENED
+#define HIGH_G_INTERRUPT_Y HIGH_G_INTERRUPT_X_HAPPENED
+#define HIGH_G_INTERRUPT_Z HIGH_G_INTERRUPT_Z_HAPPENED
+/*! High G interrupt of x, y, z negative axis happened */
+#define HIGH_G_INTERRUPT_X_N HIGH_G_INTERRUPT_Y_NEGATIVE_HAPPENED
+#define HIGH_G_INTERRUPT_Y_N HIGH_G_INTERRUPT_X_NEGATIVE_HAPPENED
+#define HIGH_G_INTERRUPT_Z_N HIGH_G_INTERRUPT_Z_NEGATIVE_HAPPENED
+/*! Slope interrupt of x, y, z axis happened */
+#define SLOPE_INTERRUPT_X SLOPE_INTERRUPT_Y_HAPPENED
+#define SLOPE_INTERRUPT_Y SLOPE_INTERRUPT_X_HAPPENED
+#define SLOPE_INTERRUPT_Z SLOPE_INTERRUPT_Z_HAPPENED
+/*! Slope interrupt of x, y, z negative axis happened */
+#define SLOPE_INTERRUPT_X_N SLOPE_INTERRUPT_Y_NEGATIVE_HAPPENED
+#define SLOPE_INTERRUPT_Y_N SLOPE_INTERRUPT_X_NEGATIVE_HAPPENED
+#define SLOPE_INTERRUPT_Z_N SLOPE_INTERRUPT_Z_NEGATIVE_HAPPENED
+
+
+#else
+
+/*! high g or slope interrupt type definition*/
+/*! High G interrupt of x, y, z axis happened */
+#define HIGH_G_INTERRUPT_X HIGH_G_INTERRUPT_X_HAPPENED
+#define HIGH_G_INTERRUPT_Y HIGH_G_INTERRUPT_Y_HAPPENED
+#define HIGH_G_INTERRUPT_Z HIGH_G_INTERRUPT_Z_HAPPENED
+/*! High G interrupt of x, y, z negative axis happened */
+#define HIGH_G_INTERRUPT_X_N HIGH_G_INTERRUPT_X_NEGATIVE_HAPPENED
+#define HIGH_G_INTERRUPT_Y_N HIGH_G_INTERRUPT_Y_NEGATIVE_HAPPENED
+#define HIGH_G_INTERRUPT_Z_N HIGH_G_INTERRUPT_Z_NEGATIVE_HAPPENED
+/*! Slope interrupt of x, y, z axis happened */
+#define SLOPE_INTERRUPT_X SLOPE_INTERRUPT_X_HAPPENED
+#define SLOPE_INTERRUPT_Y SLOPE_INTERRUPT_Y_HAPPENED
+#define SLOPE_INTERRUPT_Z SLOPE_INTERRUPT_Z_HAPPENED
+/*! Slope interrupt of x, y, z negative axis happened */
+#define SLOPE_INTERRUPT_X_N SLOPE_INTERRUPT_X_NEGATIVE_HAPPENED
+#define SLOPE_INTERRUPT_Y_N SLOPE_INTERRUPT_Y_NEGATIVE_HAPPENED
+#define SLOPE_INTERRUPT_Z_N SLOPE_INTERRUPT_Z_NEGATIVE_HAPPENED
+
+
+#endif/*End of CONFIG_SENSORS_BMI058*/
+
+/*! A workaroud mask definition with complete resolution exists
+* aim at writing operation FIFO_CONFIG_1, 0x3E register */
+#define FIFO_WORKAROUNDS_MSK SMI_ACC2X2_FIFO_TRIGGER_SOURCE__MSK
+
+struct smi130_acc_type_map_t {
+
+ /*! smi130_acc sensor chip id */
+ uint16_t chip_id;
+
+ /*! smi130_acc sensor type */
+ uint16_t sensor_type;
+
+ /*! smi130_acc sensor name */
+ const char *sensor_name;
+};
+
+static const struct smi130_acc_type_map_t sensor_type_map[] = {
+
+ {SMI_ACC255_CHIP_ID, SMI_ACC255_TYPE, "SMI_ACC255/254"},
+ {SMI_ACC355_CHIP_ID, SMI_ACC255_TYPE, "SMI_ACC355"},
+ {SMI_ACC250E_CHIP_ID, SMI_ACC250E_TYPE, "SMI_ACC250E"},
+ {SMI_ACC222E_CHIP_ID, SMI_ACC222E_TYPE, "SMI_ACC222E"},
+ {SMI_ACC280_CHIP_ID, SMI_ACC280_TYPE, "SMI_ACC280"},
+
+};
+
+/*!
+* Bst sensor common definition,
+* please give parameters in BSP file.
+*/
+struct bosch_sensor_specific {
+ char *name;
+ /* 0 to 7 */
+ int place;
+ int irq;
+ int (*irq_gpio_cfg)(void);
+};
+
+
+/*!
+ * we use a typedef to hide the detail,
+ * because this type might be changed
+ */
+struct bosch_sensor_axis_remap {
+ /* src means which source will be mapped to target x, y, z axis */
+ /* if an target OS axis is remapped from (-)x,
+ * src is 0, sign_* is (-)1 */
+ /* if an target OS axis is remapped from (-)y,
+ * src is 1, sign_* is (-)1 */
+ /* if an target OS axis is remapped from (-)z,
+ * src is 2, sign_* is (-)1 */
+ int src_x:3;
+ int src_y:3;
+ int src_z:3;
+
+ int sign_x:2;
+ int sign_y:2;
+ int sign_z:2;
+};
+
+struct bosch_sensor_data {
+ union {
+ int16_t v[3];
+ struct {
+ int16_t x;
+ int16_t y;
+ int16_t z;
+ };
+ };
+};
+
+struct smi130_accacc {
+ s16 x;
+ s16 y;
+ s16 z;
+};
+
+struct smi130_acc_data {
+ struct i2c_client *smi130_acc_client;
+ atomic_t delay;
+ atomic_t enable;
+ atomic_t selftest_result;
+ unsigned int chip_id;
+ unsigned int fifo_count;
+ unsigned char fifo_datasel;
+ unsigned char mode;
+ signed char sensor_type;
+ uint64_t timestamp;
+ uint64_t fifo_time;
+ uint64_t base_time;
+ uint64_t acc_count;
+ uint64_t time_odr;
+ uint8_t debug_level;
+ struct work_struct report_data_work;
+ int is_timer_running;
+ struct hrtimer timer;
+ ktime_t work_delay_kt;
+ struct input_dev *input;
+
+ struct bosch_dev *bosch_acc;
+
+ struct smi130_accacc value;
+ struct mutex value_mutex;
+ struct mutex enable_mutex;
+ struct mutex mode_mutex;
+ struct delayed_work work;
+ struct work_struct irq_work;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ int16_t IRQ;
+ struct bosch_sensor_specific *bosch_pd;
+
+ int smi_acc_mode_enabled;
+ struct input_dev *dev_interrupt;
+
+#ifdef CONFIG_SIG_MOTION
+ struct class *g_sensor_class;
+ struct device *g_sensor_dev;
+
+ /*struct smi_acc250_platform_data *pdata;*/
+ atomic_t en_sig_motion;
+#endif
+
+#ifdef CONFIG_DOUBLE_TAP
+ struct class *g_sensor_class_doubletap;
+ struct device *g_sensor_dev_doubletap;
+ atomic_t en_double_tap;
+ unsigned char tap_times;
+ struct mutex tap_mutex;
+ struct timer_list tap_timer;
+ int tap_time_period;
+#endif
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void smi130_acc_early_suspend(struct early_suspend *h);
+static void smi130_acc_late_resume(struct early_suspend *h);
+#endif
+
+static int smi130_acc_set_mode(struct i2c_client *client,
+ u8 mode, u8 enabled_mode);
+static int smi130_acc_get_mode(struct i2c_client *client, u8 *mode);
+static int smi130_acc_get_fifo_mode(struct i2c_client *client, u8 *fifo_mode);
+static int smi130_acc_set_fifo_mode(struct i2c_client *client, u8 fifo_mode);
+static int smi130_acc_normal_to_suspend(struct smi130_acc_data *smi130_acc,
+ unsigned char data1, unsigned char data2);
+
+static void smi130_acc_delay(u32 msec)
+{
+ if (msec <= 20)
+ usleep_range(msec * 1000, msec * 1000);
+ else
+ msleep(msec);
+}
+/*Remapping for SMI_ACC2X2*/
+static const struct bosch_sensor_axis_remap
+bosch_axis_remap_tab_dft[MAX_AXIS_REMAP_TAB_SZ] = {
+ /* src_x src_y src_z sign_x sign_y sign_z */
+ { 0, 1, 2, 1, 1, 1 }, /* P0 */
+ { 1, 0, 2, 1, -1, 1 }, /* P1 */
+ { 0, 1, 2, -1, -1, 1 }, /* P2 */
+ { 1, 0, 2, -1, 1, 1 }, /* P3 */
+
+ { 0, 1, 2, -1, 1, -1 }, /* P4 */
+ { 1, 0, 2, -1, -1, -1 }, /* P5 */
+ { 0, 1, 2, 1, -1, -1 }, /* P6 */
+ { 1, 0, 2, 1, 1, -1 }, /* P7 */
+};
+
+
+static void bosch_remap_sensor_data(struct bosch_sensor_data *data,
+ const struct bosch_sensor_axis_remap *remap)
+{
+ struct bosch_sensor_data tmp;
+
+ tmp.x = data->v[remap->src_x] * remap->sign_x;
+ tmp.y = data->v[remap->src_y] * remap->sign_y;
+ tmp.z = data->v[remap->src_z] * remap->sign_z;
+
+ memcpy(data, &tmp, sizeof(*data));
+}
+
+
+static void bosch_remap_sensor_data_dft_tab(struct bosch_sensor_data *data,
+ int place)
+{
+ /* sensor with place 0 needs not to be remapped */
+ if ((place <= 0) || (place >= MAX_AXIS_REMAP_TAB_SZ))
+ return;
+
+ bosch_remap_sensor_data(data, &bosch_axis_remap_tab_dft[place]);
+}
+
+static void smi130_acc_remap_sensor_data(struct smi130_accacc *val,
+ struct smi130_acc_data *client_data)
+{
+ struct bosch_sensor_data bsd;
+ int place;
+
+ if ((NULL == client_data->bosch_pd) || (BOSCH_SENSOR_PLACE_UNKNOWN
+ == client_data->bosch_pd->place))
+ place = BOSCH_SENSOR_PLACE_UNKNOWN;
+ else
+ place = client_data->bosch_pd->place;
+
+#ifdef CONFIG_SENSORS_BMI058
+/*x,y need to be invesed becase of HW Register for BMI058*/
+ bsd.y = val->x;
+ bsd.x = val->y;
+ bsd.z = val->z;
+#else
+ bsd.x = val->x;
+ bsd.y = val->y;
+ bsd.z = val->z;
+#endif
+
+ bosch_remap_sensor_data_dft_tab(&bsd, place);
+
+ val->x = bsd.x;
+ val->y = bsd.y;
+ val->z = bsd.z;
+
+}
+
+
+static int smi130_acc_smbus_read_byte(struct i2c_client *client,
+ unsigned char reg_addr, unsigned char *data)
+{
+#if !defined SMI130_ACC_USE_BASIC_I2C_FUNC
+ s32 dummy;
+ int len = 1;
+ if (NULL == client)
+ return -ENODEV;
+
+ while (0 != len--) {
+#ifdef SMI130_ACC_SMBUS
+ dummy = i2c_smbus_read_byte_data(client, reg_addr);
+ if (dummy < 0) {
+ PERR("i2c bus read error");
+ return -EIO;
+ }
+ *data = (u8)(dummy & 0xff);
+#else
+ dummy = i2c_master_send(client, (char *)&reg_addr, 1);
+ if (dummy < 0)
+ return -EIO;
+
+ dummy = i2c_master_recv(client, (char *)data, 1);
+ if (dummy < 0)
+ return -EIO;
+#endif
+ reg_addr++;
+ data++;
+ }
+ return 0;
+#else
+ int retry;
+ int len = 1;
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ for (retry = 0; retry < SMI_ACC_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ smi130_acc_delay(1);
+ }
+
+ if (SMI_ACC_MAX_RETRY_I2C_XFER <= retry) {
+ PERR("I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+#endif
+}
+
+static int smi130_acc_smbus_write_byte(struct i2c_client *client,
+ unsigned char reg_addr, unsigned char *data)
+{
+#if !defined SMI130_ACC_USE_BASIC_I2C_FUNC
+ s32 dummy;
+ int len = 1;
+#ifndef SMI130_ACC_SMBUS
+ u8 buffer[2];
+#endif
+ if (NULL == client)
+ return -ENODEV;
+
+ while (0 != len--) {
+#ifdef SMI130_ACC_SMBUS
+ dummy = i2c_smbus_write_byte_data(client, reg_addr, *data);
+#else
+ buffer[0] = reg_addr;
+ buffer[1] = *data;
+ dummy = i2c_master_send(client, (char *)buffer, 2);
+#endif
+ reg_addr++;
+ data++;
+ if (dummy < 0) {
+ PERR("error writing i2c bus");
+ return -EIO;
+ }
+
+ }
+ return 0;
+#else
+ u8 buffer[2];
+ int retry;
+ int len = 1;
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = buffer,
+ },
+ };
+ while (0 != len--) {
+ buffer[0] = reg_addr;
+ buffer[1] = *data;
+ for (retry = 0; retry < SMI_ACC_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg,
+ ARRAY_SIZE(msg)) > 0) {
+ break;
+ } else {
+ smi130_acc_delay(1);
+ }
+ }
+ if (SMI_ACC_MAX_RETRY_I2C_XFER <= retry) {
+ PERR("I2C xfer error");
+ return -EIO;
+ }
+ reg_addr++;
+ data++;
+ }
+
+ return 0;
+#endif
+}
+
+static int smi130_acc_smbus_read_byte_block(struct i2c_client *client,
+ unsigned char reg_addr, unsigned char *data, unsigned char len)
+{
+ int retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ for (retry = 0; retry < SMI_ACC_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ smi130_acc_delay(1);
+ }
+
+ if (SMI_ACC_MAX_RETRY_I2C_XFER <= retry) {
+ PERR("I2C xfer error");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int smi_acc_i2c_burst_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u16 len)
+{
+ int retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ for (retry = 0; retry < SMI_ACC_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ smi130_acc_delay(1);
+ }
+
+ if (SMI_ACC_MAX_RETRY_I2C_XFER <= retry) {
+ PINFO("I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int smi130_acc_check_chip_id(struct i2c_client *client,
+ struct smi130_acc_data *data)
+{
+ int i = 0;
+ int err = 0;
+ unsigned char chip_id = 0;
+ unsigned char read_count = 0;
+ unsigned char smi130_acc_sensor_type_count = 0;
+
+ smi130_acc_sensor_type_count =
+ sizeof(sensor_type_map) / sizeof(struct smi130_acc_type_map_t);
+
+ while (read_count++ < CHECK_CHIP_ID_TIME_MAX) {
+ if (smi130_acc_smbus_read_byte(client, SMI_ACC2X2_CHIP_ID_REG,
+ &chip_id) < 0) {
+ PERR("Bosch Sensortec Device not found\n\n"
+ "i2c bus read error, read chip_id:%d\n", chip_id);
+ continue;
+ } else {
+ for (i = 0; i < smi130_acc_sensor_type_count; i++) {
+ if (sensor_type_map[i].chip_id == chip_id) {
+ data->sensor_type =
+ sensor_type_map[i].sensor_type;
+ data->chip_id = chip_id;
+ PINFO("Bosch Sensortec Device detected,\n\n"
+ " HW IC name: %s\n",
+ sensor_type_map[i].sensor_name);
+ return err;
+ }
+ }
+ if (i < smi130_acc_sensor_type_count)
+ return err;
+ else {
+ if (read_count == CHECK_CHIP_ID_TIME_MAX) {
+ PERR("Failed! Bosch Sensortec Device\n\n"
+ " not found, mismatch chip_id:%d\n",
+ chip_id);
+ err = -ENODEV;
+ return err;
+ }
+ }
+ smi130_acc_delay(1);
+ }
+ }
+ return err;
+}
+
+#ifdef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+static int smi130_acc_set_newdata(struct i2c_client *client,
+ unsigned char channel, unsigned char int_newdata)
+{
+
+ unsigned char data = 0;
+ int comres = 0;
+
+ switch (channel) {
+ case SMI_ACC2X2_INT1_NDATA:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_NEWDATA__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data,
+ SMI_ACC2X2_EN_INT1_PAD_NEWDATA, int_newdata);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_NEWDATA__REG, &data);
+ break;
+ case SMI_ACC2X2_INT2_NDATA:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_NEWDATA__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data,
+ SMI_ACC2X2_EN_INT2_PAD_NEWDATA, int_newdata);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_NEWDATA__REG, &data);
+ break;
+ default:
+ comres = -1;
+ break;
+ }
+
+ return comres;
+
+}
+#endif /* CONFIG_SMI_ACC_ENABLE_NEWDATA_INT */
+
+#ifdef SMI_ACC2X2_ENABLE_INT1
+static int smi130_acc_set_int1_pad_sel(struct i2c_client *client, unsigned char
+ int1sel)
+{
+ int comres = 0;
+ unsigned char data = 0;
+ unsigned char state;
+ state = 0x01;
+
+
+ switch (int1sel) {
+ case 0:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_LOWG__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT1_PAD_LOWG,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_LOWG__REG, &data);
+ break;
+ case 1:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_HIGHG__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT1_PAD_HIGHG,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_HIGHG__REG, &data);
+ break;
+ case 2:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_SLOPE__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT1_PAD_SLOPE,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_SLOPE__REG, &data);
+ break;
+ case 3:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_DB_TAP__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT1_PAD_DB_TAP,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_DB_TAP__REG, &data);
+ break;
+ case 4:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_SNG_TAP__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT1_PAD_SNG_TAP,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_SNG_TAP__REG, &data);
+ break;
+ case 5:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_ORIENT__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT1_PAD_ORIENT,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_ORIENT__REG, &data);
+ break;
+ case 6:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_FLAT__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT1_PAD_FLAT,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_FLAT__REG, &data);
+ break;
+ case 7:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_SLO_NO_MOT__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT1_PAD_SLO_NO_MOT,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT1_PAD_SLO_NO_MOT__REG, &data);
+ break;
+
+ default:
+ break;
+ }
+
+ return comres;
+}
+#endif /* SMI_ACC2X2_ENABLE_INT1 */
+
+#ifdef SMI_ACC2X2_ENABLE_INT2
+static int smi130_acc_set_int2_pad_sel(struct i2c_client *client, unsigned char
+ int2sel)
+{
+ int comres = 0;
+ unsigned char data = 0;
+ unsigned char state;
+ state = 0x01;
+
+
+ switch (int2sel) {
+ case 0:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_LOWG__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT2_PAD_LOWG,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_LOWG__REG, &data);
+ break;
+ case 1:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_HIGHG__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT2_PAD_HIGHG,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_HIGHG__REG, &data);
+ break;
+ case 2:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_SLOPE__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT2_PAD_SLOPE,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_SLOPE__REG, &data);
+ break;
+ case 3:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_DB_TAP__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT2_PAD_DB_TAP,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_DB_TAP__REG, &data);
+ break;
+ case 4:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_SNG_TAP__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT2_PAD_SNG_TAP,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_SNG_TAP__REG, &data);
+ break;
+ case 5:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_ORIENT__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT2_PAD_ORIENT,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_ORIENT__REG, &data);
+ break;
+ case 6:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_FLAT__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT2_PAD_FLAT,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_FLAT__REG, &data);
+ break;
+ case 7:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_SLO_NO_MOT__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_INT2_PAD_SLO_NO_MOT,
+ state);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_EN_INT2_PAD_SLO_NO_MOT__REG, &data);
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+#endif /* SMI_ACC2X2_ENABLE_INT2 */
+
+static int smi130_acc_set_Int_Enable(struct i2c_client *client, unsigned char
+ InterruptType , unsigned char value)
+{
+ int comres = 0;
+ unsigned char data1 = 0;
+ unsigned char data2 = 0;
+
+ if ((11 < InterruptType) && (InterruptType < 16)) {
+ switch (InterruptType) {
+ case 12:
+ /* slow/no motion X Interrupt */
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_X_INT__REG, &data1);
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_X_INT, value);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_X_INT__REG, &data1);
+ break;
+ case 13:
+ /* slow/no motion Y Interrupt */
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_Y_INT__REG, &data1);
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_Y_INT, value);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_Y_INT__REG, &data1);
+ break;
+ case 14:
+ /* slow/no motion Z Interrupt */
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_Z_INT__REG, &data1);
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_Z_INT, value);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_Z_INT__REG, &data1);
+ break;
+ case 15:
+ /* slow / no motion Interrupt select */
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_SEL_INT__REG, &data1);
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_SEL_INT, value);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_INT_SLO_NO_MOT_EN_SEL_INT__REG, &data1);
+ }
+
+ return comres;
+ }
+
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_INT_ENABLE1_REG, &data1);
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_INT_ENABLE2_REG, &data2);
+
+ value = value & 1;
+ switch (InterruptType) {
+ case 0:
+ /* Low G Interrupt */
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2, SMI_ACC2X2_EN_LOWG_INT, value);
+ break;
+
+ case 1:
+ /* High G X Interrupt */
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2, SMI_ACC2X2_EN_HIGHG_X_INT,
+ value);
+ break;
+
+ case 2:
+ /* High G Y Interrupt */
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2, SMI_ACC2X2_EN_HIGHG_Y_INT,
+ value);
+ break;
+
+ case 3:
+ /* High G Z Interrupt */
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2, SMI_ACC2X2_EN_HIGHG_Z_INT,
+ value);
+ break;
+
+ case 4:
+ /* New Data Interrupt */
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2, SMI_ACC2X2_EN_NEW_DATA_INT,
+ value);
+ break;
+
+ case 5:
+ /* Slope X Interrupt */
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1, SMI_ACC2X2_EN_SLOPE_X_INT,
+ value);
+ break;
+
+ case 6:
+ /* Slope Y Interrupt */
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1, SMI_ACC2X2_EN_SLOPE_Y_INT,
+ value);
+ break;
+
+ case 7:
+ /* Slope Z Interrupt */
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1, SMI_ACC2X2_EN_SLOPE_Z_INT,
+ value);
+ break;
+
+ case 8:
+ /* Single Tap Interrupt */
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1, SMI_ACC2X2_EN_SINGLE_TAP_INT,
+ value);
+ break;
+
+ case 9:
+ /* Double Tap Interrupt */
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1, SMI_ACC2X2_EN_DOUBLE_TAP_INT,
+ value);
+ break;
+
+ case 10:
+ /* Orient Interrupt */
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1, SMI_ACC2X2_EN_ORIENT_INT, value);
+ break;
+
+ case 11:
+ /* Flat Interrupt */
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1, SMI_ACC2X2_EN_FLAT_INT, value);
+ break;
+
+ default:
+ break;
+ }
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_INT_ENABLE1_REG,
+ &data1);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_INT_ENABLE2_REG,
+ &data2);
+
+ return comres;
+}
+
+
+#if defined(SMI_ACC2X2_ENABLE_INT1) || defined(SMI_ACC2X2_ENABLE_INT2)
+static int smi130_acc_get_interruptstatus1(struct i2c_client *client, unsigned char
+ *intstatus)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_STATUS1_REG, &data);
+ *intstatus = data;
+
+ return comres;
+}
+
+#ifdef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+/*
+static int smi130_acc_get_interruptstatus2(struct i2c_client *client, unsigned char
+ *intstatus)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_STATUS2_REG, &data);
+ *intstatus = data;
+
+ return comres;
+}
+*/
+#endif
+
+static int smi130_acc_get_HIGH_first(struct i2c_client *client, unsigned char
+ param, unsigned char *intstatus)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ switch (param) {
+ case 0:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_STATUS_ORIENT_HIGH_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_HIGHG_FIRST_X);
+ *intstatus = data;
+ break;
+ case 1:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_STATUS_ORIENT_HIGH_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_HIGHG_FIRST_Y);
+ *intstatus = data;
+ break;
+ case 2:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_STATUS_ORIENT_HIGH_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_HIGHG_FIRST_Z);
+ *intstatus = data;
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_get_HIGH_sign(struct i2c_client *client, unsigned char
+ *intstatus)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_STATUS_ORIENT_HIGH_REG,
+ &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_HIGHG_SIGN_S);
+ *intstatus = data;
+
+ return comres;
+}
+
+#ifndef CONFIG_SIG_MOTION
+static int smi130_acc_get_slope_first(struct i2c_client *client, unsigned char
+ param, unsigned char *intstatus)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ switch (param) {
+ case 0:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_STATUS_TAP_SLOPE_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_SLOPE_FIRST_X);
+ *intstatus = data;
+ break;
+ case 1:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_STATUS_TAP_SLOPE_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_SLOPE_FIRST_Y);
+ *intstatus = data;
+ break;
+ case 2:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_STATUS_TAP_SLOPE_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_SLOPE_FIRST_Z);
+ *intstatus = data;
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_get_slope_sign(struct i2c_client *client, unsigned char
+ *intstatus)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_STATUS_TAP_SLOPE_REG,
+ &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_SLOPE_SIGN_S);
+ *intstatus = data;
+
+ return comres;
+}
+#endif
+
+static int smi130_acc_get_orient_mbl_status(struct i2c_client *client, unsigned char
+ *intstatus)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_STATUS_ORIENT_HIGH_REG,
+ &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_ORIENT_S);
+ *intstatus = data;
+
+ return comres;
+}
+
+static int smi130_acc_get_orient_mbl_flat_status(struct i2c_client *client, unsigned
+ char *intstatus)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_STATUS_ORIENT_HIGH_REG,
+ &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_FLAT_S);
+ *intstatus = data;
+
+ return comres;
+}
+#endif /* defined(SMI_ACC2X2_ENABLE_INT1)||defined(SMI_ACC2X2_ENABLE_INT2) */
+
+static int smi130_acc_set_Int_Mode(struct i2c_client *client, unsigned char Mode)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_INT_MODE_SEL__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_INT_MODE_SEL, Mode);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_INT_MODE_SEL__REG, &data);
+
+
+ return comres;
+}
+
+static int smi130_acc_get_Int_Mode(struct i2c_client *client, unsigned char *Mode)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_INT_MODE_SEL__REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_INT_MODE_SEL);
+ *Mode = data;
+
+
+ return comres;
+}
+static int smi130_acc_set_slope_duration(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_SLOPE_DUR__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_SLOPE_DUR, duration);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_SLOPE_DUR__REG, &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_slope_duration(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_SLOPE_DURN_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_SLOPE_DUR);
+ *status = data;
+
+
+ return comres;
+}
+
+static int smi130_acc_set_slope_no_mot_duration(struct i2c_client *client,
+ unsigned char duration)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI130_ACC_SLO_NO_MOT_DUR__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI130_ACC_SLO_NO_MOT_DUR, duration);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI130_ACC_SLO_NO_MOT_DUR__REG, &data);
+
+
+ return comres;
+}
+
+static int smi130_acc_get_slope_no_mot_duration(struct i2c_client *client,
+ unsigned char *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI130_ACC_SLO_NO_MOT_DUR__REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI130_ACC_SLO_NO_MOT_DUR);
+ *status = data;
+
+
+ return comres;
+}
+
+static int smi130_acc_set_slope_threshold(struct i2c_client *client,
+ unsigned char threshold)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ data = threshold;
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_SLOPE_THRES__REG, &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_slope_threshold(struct i2c_client *client,
+ unsigned char *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_SLOPE_THRES_REG, &data);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_slope_no_mot_threshold(struct i2c_client *client,
+ unsigned char threshold)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ data = threshold;
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_SLO_NO_MOT_THRES_REG, &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_slope_no_mot_threshold(struct i2c_client *client,
+ unsigned char *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_SLO_NO_MOT_THRES_REG, &data);
+ *status = data;
+
+ return comres;
+}
+
+
+static int smi130_acc_set_low_g_duration(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_LOWG_DUR__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_LOWG_DUR, duration);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_LOWG_DUR__REG, &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_low_g_duration(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_LOW_DURN_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_LOWG_DUR);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_low_g_threshold(struct i2c_client *client, unsigned char
+ threshold)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_LOWG_THRES__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_LOWG_THRES, threshold);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_LOWG_THRES__REG, &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_low_g_threshold(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_LOW_THRES_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_LOWG_THRES);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_high_g_duration(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_HIGHG_DUR__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_HIGHG_DUR, duration);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_HIGHG_DUR__REG, &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_high_g_duration(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_HIGH_DURN_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_HIGHG_DUR);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_high_g_threshold(struct i2c_client *client, unsigned char
+ threshold)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_HIGHG_THRES__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_HIGHG_THRES, threshold);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_HIGHG_THRES__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_high_g_threshold(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_HIGH_THRES_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_HIGHG_THRES);
+ *status = data;
+
+ return comres;
+}
+
+
+static int smi130_acc_set_tap_duration(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_DUR__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_TAP_DUR, duration);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_TAP_DUR__REG, &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_tap_duration(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_PARAM_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_TAP_DUR);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_tap_shock(struct i2c_client *client, unsigned char setval)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_SHOCK_DURN__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_TAP_SHOCK_DURN, setval);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_TAP_SHOCK_DURN__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_tap_shock(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_PARAM_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_TAP_SHOCK_DURN);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_tap_quiet(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_QUIET_DURN__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_TAP_QUIET_DURN, duration);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_TAP_QUIET_DURN__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_tap_quiet(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_PARAM_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_TAP_QUIET_DURN);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_tap_threshold(struct i2c_client *client, unsigned char
+ threshold)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_THRES__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_TAP_THRES, threshold);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_TAP_THRES__REG, &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_tap_threshold(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_THRES_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_TAP_THRES);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_tap_samp(struct i2c_client *client, unsigned char samp)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_SAMPLES__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_TAP_SAMPLES, samp);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_TAP_SAMPLES__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_tap_samp(struct i2c_client *client, unsigned char *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TAP_THRES_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_TAP_SAMPLES);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_orient_mbl_mode(struct i2c_client *client, unsigned char mode)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_ORIENT_MODE__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_ORIENT_MODE, mode);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_ORIENT_MODE__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_orient_mbl_mode(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_ORIENT_PARAM_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_ORIENT_MODE);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_orient_mbl_blocking(struct i2c_client *client, unsigned char
+ samp)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_ORIENT_BLOCK__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_ORIENT_BLOCK, samp);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_ORIENT_BLOCK__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_orient_mbl_blocking(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_ORIENT_PARAM_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_ORIENT_BLOCK);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_orient_mbl_hyst(struct i2c_client *client, unsigned char
+ orient_mblhyst)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_ORIENT_HYST__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_ORIENT_HYST, orient_mblhyst);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_ORIENT_HYST__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_orient_mbl_hyst(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_ORIENT_PARAM_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_ORIENT_HYST);
+ *status = data;
+
+ return comres;
+}
+static int smi130_acc_set_theta_blocking(struct i2c_client *client, unsigned char
+ thetablk)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_THETA_BLOCK__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_THETA_BLOCK, thetablk);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_THETA_BLOCK__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_theta_blocking(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_THETA_BLOCK_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_THETA_BLOCK);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_theta_flat(struct i2c_client *client, unsigned char
+ thetaflat)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_THETA_FLAT__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_THETA_FLAT, thetaflat);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_THETA_FLAT__REG, &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_theta_flat(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_THETA_FLAT_REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_THETA_FLAT);
+ *status = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_flat_hold_time(struct i2c_client *client, unsigned char
+ holdtime)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_FLAT_HOLD_TIME__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_FLAT_HOLD_TIME, holdtime);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_FLAT_HOLD_TIME__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_flat_hold_time(struct i2c_client *client, unsigned char
+ *holdtime)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_FLAT_HOLD_TIME_REG,
+ &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_FLAT_HOLD_TIME);
+ *holdtime = data;
+
+ return comres;
+}
+
+/*!
+ * brief: smi130_acc switch from normal to suspend mode
+ * @param[i] smi130_acc
+ * @param[i] data1, write to PMU_LPW
+ * @param[i] data2, write to PMU_LOW_NOSIE
+ *
+ * @return zero success, none-zero failed
+ */
+static int smi130_acc_normal_to_suspend(struct smi130_acc_data *smi130_acc,
+ unsigned char data1, unsigned char data2)
+{
+ unsigned char current_fifo_mode;
+ unsigned char current_op_mode;
+ if (smi130_acc == NULL)
+ return -ENODEV;
+ /* get current op mode from mode register */
+ if (smi130_acc_get_mode(smi130_acc->smi130_acc_client, &current_op_mode) < 0)
+ return -EIO;
+ /* only aimed at operatiom mode chang from normal/lpw1 mode
+ * to suspend state.
+ */
+ if (current_op_mode == SMI_ACC2X2_MODE_NORMAL ||
+ current_op_mode == SMI_ACC2X2_MODE_LOWPOWER1) {
+ /* get current fifo mode from fifo config register */
+ if (smi130_acc_get_fifo_mode(smi130_acc->smi130_acc_client,
+ &current_fifo_mode) < 0)
+ return -EIO;
+ else {
+ smi130_acc_smbus_write_byte(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_LOW_NOISE_CTRL_REG, &data2);
+ smi130_acc_smbus_write_byte(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_MODE_CTRL_REG, &data1);
+ /*! Aim at fifo workarounds with FIFO_CONFIG_1 */
+ current_fifo_mode |= FIFO_WORKAROUNDS_MSK;
+ smi130_acc_smbus_write_byte(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_FIFO_MODE__REG, &current_fifo_mode);
+ smi130_acc_delay(3);
+ return 0;
+ }
+ } else {
+ smi130_acc_smbus_write_byte(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_LOW_NOISE_CTRL_REG, &data2);
+ smi130_acc_smbus_write_byte(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_MODE_CTRL_REG, &data1);
+ smi130_acc_delay(3);
+ return 0;
+ }
+
+}
+
+static int smi130_acc_set_mode(struct i2c_client *client, unsigned char mode,
+ unsigned char enabled_mode)
+{
+ int comres = 0;
+ unsigned char data1 = 0;
+ unsigned char data2 = 0;
+ int ret = 0;
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ mutex_lock(&smi130_acc->mode_mutex);
+ if (SMI_ACC2X2_MODE_SUSPEND == mode) {
+ if (enabled_mode != SMI_ACC_ENABLED_ALL) {
+ if ((smi130_acc->smi_acc_mode_enabled &
+ (1<<enabled_mode)) == 0) {
+ /* sensor is already closed in this mode */
+ mutex_unlock(&smi130_acc->mode_mutex);
+ return 0;
+ } else {
+ smi130_acc->smi_acc_mode_enabled &= ~(1<<enabled_mode);
+ }
+ } else {
+ /* shut down, close all and force do it*/
+ smi130_acc->smi_acc_mode_enabled = 0;
+ }
+ } else if (SMI_ACC2X2_MODE_NORMAL == mode) {
+ if ((smi130_acc->smi_acc_mode_enabled & (1<<enabled_mode)) != 0) {
+ /* sensor is already enabled in this mode */
+ mutex_unlock(&smi130_acc->mode_mutex);
+ return 0;
+ } else {
+ smi130_acc->smi_acc_mode_enabled |= (1<<enabled_mode);
+ }
+ } else {
+ /* other mode, close all and force do it*/
+ smi130_acc->smi_acc_mode_enabled = 0;
+ }
+ mutex_unlock(&smi130_acc->mode_mutex);
+
+ if (mode < 6) {
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_MODE_CTRL_REG,
+ &data1);
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_LOW_NOISE_CTRL_REG,
+ &data2);
+ switch (mode) {
+ case SMI_ACC2X2_MODE_NORMAL:
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_MODE_CTRL, 0);
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2,
+ SMI_ACC2X2_LOW_POWER_MODE, 0);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_MODE_CTRL_REG, &data1);
+ smi130_acc_delay(3);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_LOW_NOISE_CTRL_REG, &data2);
+ break;
+ case SMI_ACC2X2_MODE_LOWPOWER1:
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_MODE_CTRL, 2);
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2,
+ SMI_ACC2X2_LOW_POWER_MODE, 0);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_MODE_CTRL_REG, &data1);
+ smi130_acc_delay(3);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_LOW_NOISE_CTRL_REG, &data2);
+ break;
+ case SMI_ACC2X2_MODE_SUSPEND:
+ if (smi130_acc->smi_acc_mode_enabled != 0) {
+ PERR("smi_acc still working");
+ return 0;
+ }
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_MODE_CTRL, 4);
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2,
+ SMI_ACC2X2_LOW_POWER_MODE, 0);
+ /*aimed at anomaly resolution when switch to suspend*/
+ ret = smi130_acc_normal_to_suspend(smi130_acc, data1, data2);
+ if (ret < 0)
+ PERR("Error switching to suspend");
+ break;
+ case SMI_ACC2X2_MODE_DEEP_SUSPEND:
+ if (smi130_acc->smi_acc_mode_enabled != 0) {
+ PERR("smi_acc still working");
+ return 0;
+ }
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_MODE_CTRL, 1);
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2,
+ SMI_ACC2X2_LOW_POWER_MODE, 1);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_MODE_CTRL_REG, &data1);
+ smi130_acc_delay(3);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_LOW_NOISE_CTRL_REG, &data2);
+ break;
+ case SMI_ACC2X2_MODE_LOWPOWER2:
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_MODE_CTRL, 2);
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2,
+ SMI_ACC2X2_LOW_POWER_MODE, 1);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_MODE_CTRL_REG, &data1);
+ smi130_acc_delay(3);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_LOW_NOISE_CTRL_REG, &data2);
+ break;
+ case SMI_ACC2X2_MODE_STANDBY:
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_MODE_CTRL, 4);
+ data2 = SMI_ACC2X2_SET_BITSLICE(data2,
+ SMI_ACC2X2_LOW_POWER_MODE, 1);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_LOW_NOISE_CTRL_REG, &data2);
+ smi130_acc_delay(3);
+ smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_MODE_CTRL_REG, &data1);
+ break;
+ }
+ } else {
+ comres = -1;
+ }
+
+ return comres;
+}
+
+
+static int smi130_acc_get_mode(struct i2c_client *client, unsigned char *mode)
+{
+ int comres = 0;
+ unsigned char data1 = 0;
+ unsigned char data2 = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_MODE_CTRL_REG, &data1);
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_LOW_NOISE_CTRL_REG,
+ &data2);
+
+ data1 = (data1 & 0xE0) >> 5;
+ data2 = (data2 & 0x40) >> 6;
+
+
+ if ((data1 == 0x00) && (data2 == 0x00)) {
+ *mode = SMI_ACC2X2_MODE_NORMAL;
+ } else {
+ if ((data1 == 0x02) && (data2 == 0x00)) {
+ *mode = SMI_ACC2X2_MODE_LOWPOWER1;
+ } else {
+ if ((data1 == 0x04 || data1 == 0x06) &&
+ (data2 == 0x00)) {
+ *mode = SMI_ACC2X2_MODE_SUSPEND;
+ } else {
+ if (((data1 & 0x01) == 0x01)) {
+ *mode = SMI_ACC2X2_MODE_DEEP_SUSPEND;
+ } else {
+ if ((data1 == 0x02) &&
+ (data2 == 0x01)) {
+ *mode = SMI_ACC2X2_MODE_LOWPOWER2;
+ } else {
+ if ((data1 == 0x04) && (data2 ==
+ 0x01)) {
+ *mode =
+ SMI_ACC2X2_MODE_STANDBY;
+ } else {
+ *mode =
+ SMI_ACC2X2_MODE_DEEP_SUSPEND;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return comres;
+}
+
+static int smi130_acc_set_range(struct i2c_client *client, unsigned char Range)
+{
+ int comres = 0;
+ unsigned char data1 = 0;
+
+ if ((Range == 3) || (Range == 5) || (Range == 8) || (Range == 12)) {
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_RANGE_SEL_REG,
+ &data1);
+ switch (Range) {
+ case SMI_ACC2X2_RANGE_2G:
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_RANGE_SEL, 3);
+ break;
+ case SMI_ACC2X2_RANGE_4G:
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_RANGE_SEL, 5);
+ break;
+ case SMI_ACC2X2_RANGE_8G:
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_RANGE_SEL, 8);
+ break;
+ case SMI_ACC2X2_RANGE_16G:
+ data1 = SMI_ACC2X2_SET_BITSLICE(data1,
+ SMI_ACC2X2_RANGE_SEL, 12);
+ break;
+ default:
+ break;
+ }
+ comres += smi130_acc_smbus_write_byte(client, SMI_ACC2X2_RANGE_SEL_REG,
+ &data1);
+ } else {
+ comres = -1;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_get_range(struct i2c_client *client, unsigned char *Range)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_RANGE_SEL__REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_RANGE_SEL);
+ *Range = data;
+
+ return comres;
+}
+
+
+static int smi130_acc_set_bandwidth(struct i2c_client *client, unsigned char BW)
+{
+ int comres = 0;
+ unsigned char data = 0;
+ int Bandwidth = 0;
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (BW > 7 && BW < 16) {
+ switch (BW) {
+ case SMI_ACC2X2_BW_7_81HZ:
+ Bandwidth = SMI_ACC2X2_BW_7_81HZ;
+ smi130_acc->time_odr = 64000000;
+
+ /* 7.81 Hz 64000 uS */
+ break;
+ case SMI_ACC2X2_BW_15_63HZ:
+ Bandwidth = SMI_ACC2X2_BW_15_63HZ;
+ smi130_acc->time_odr = 32000000;
+ /* 15.63 Hz 32000 uS */
+ break;
+ case SMI_ACC2X2_BW_31_25HZ:
+ Bandwidth = SMI_ACC2X2_BW_31_25HZ;
+ smi130_acc->time_odr = 16000000;
+ /* 31.25 Hz 16000 uS */
+ break;
+ case SMI_ACC2X2_BW_62_50HZ:
+ Bandwidth = SMI_ACC2X2_BW_62_50HZ;
+ smi130_acc->time_odr = 8000000;
+ /* 62.50 Hz 8000 uS */
+ break;
+ case SMI_ACC2X2_BW_125HZ:
+ Bandwidth = SMI_ACC2X2_BW_125HZ;
+ smi130_acc->time_odr = 4000000;
+ /* 125 Hz 4000 uS */
+ break;
+ case SMI_ACC2X2_BW_250HZ:
+ Bandwidth = SMI_ACC2X2_BW_250HZ;
+ smi130_acc->time_odr = 2000000;
+ /* 250 Hz 2000 uS */
+ break;
+ case SMI_ACC2X2_BW_500HZ:
+ Bandwidth = SMI_ACC2X2_BW_500HZ;
+ smi130_acc->time_odr = 1000000;
+ /* 500 Hz 1000 uS */
+ break;
+ case SMI_ACC2X2_BW_1000HZ:
+ Bandwidth = SMI_ACC2X2_BW_1000HZ;
+ smi130_acc->time_odr = 500000;
+ /* 1000 Hz 500 uS */
+ break;
+ default:
+ break;
+ }
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_BANDWIDTH__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_BANDWIDTH, Bandwidth);
+ comres += smi130_acc_smbus_write_byte(client, SMI_ACC2X2_BANDWIDTH__REG,
+ &data);
+ } else {
+ comres = -1;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_get_bandwidth(struct i2c_client *client, unsigned char *BW)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_BANDWIDTH__REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_BANDWIDTH);
+ *BW = data;
+
+ return comres;
+}
+
+int smi130_acc_get_sleep_duration(struct i2c_client *client, unsigned char
+ *sleep_dur)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_SLEEP_DUR__REG, &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_SLEEP_DUR);
+ *sleep_dur = data;
+
+ return comres;
+}
+
+int smi130_acc_set_sleep_duration(struct i2c_client *client, unsigned char
+ sleep_dur)
+{
+ int comres = 0;
+ unsigned char data = 0;
+ int sleep_duration = 0;
+
+ if (sleep_dur > 4 && sleep_dur < 16) {
+ switch (sleep_dur) {
+ case SMI_ACC2X2_SLEEP_DUR_0_5MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_0_5MS;
+
+ /* 0.5 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_1MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_1MS;
+
+ /* 1 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_2MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_2MS;
+
+ /* 2 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_4MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_4MS;
+
+ /* 4 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_6MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_6MS;
+
+ /* 6 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_10MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_10MS;
+
+ /* 10 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_25MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_25MS;
+
+ /* 25 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_50MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_50MS;
+
+ /* 50 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_100MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_100MS;
+
+ /* 100 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_500MS:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_500MS;
+
+ /* 500 MS */
+ break;
+ case SMI_ACC2X2_SLEEP_DUR_1S:
+ sleep_duration = SMI_ACC2X2_SLEEP_DUR_1S;
+
+ /* 1 SECS */
+ break;
+ default:
+ break;
+ }
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_SLEEP_DUR__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_SLEEP_DUR,
+ sleep_duration);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_SLEEP_DUR__REG,
+ &data);
+ } else {
+ comres = -1;
+ }
+
+
+ return comres;
+}
+
+static int smi130_acc_get_fifo_mode(struct i2c_client *client, unsigned char
+ *fifo_mode)
+{
+ int comres;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_FIFO_MODE__REG, &data);
+ *fifo_mode = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_FIFO_MODE);
+
+ return comres;
+}
+
+static int smi130_acc_set_fifo_mode(struct i2c_client *client, unsigned char
+ fifo_mode)
+{
+ unsigned char data = 0;
+ int comres = 0;
+
+ if (fifo_mode < 4) {
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_FIFO_MODE__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_FIFO_MODE, fifo_mode);
+ /*! Aim at fifo workarounds with FIFO_CONFIG_1 */
+ data |= FIFO_WORKAROUNDS_MSK;
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_FIFO_MODE__REG,
+ &data);
+ } else {
+ comres = -1;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_get_fifo_trig(struct i2c_client *client, unsigned char
+ *fifo_trig)
+{
+ int comres;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_FIFO_TRIGGER_ACTION__REG, &data);
+ *fifo_trig = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_FIFO_TRIGGER_ACTION);
+
+ return comres;
+}
+
+static int smi130_acc_set_fifo_trig(struct i2c_client *client, unsigned char
+ fifo_trig)
+{
+ unsigned char data = 0;
+ int comres = 0;
+
+ if (fifo_trig < 4) {
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_FIFO_TRIGGER_ACTION__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_FIFO_TRIGGER_ACTION,
+ fifo_trig);
+ /*! Aim at fifo workarounds with FIFO_CONFIG_1 */
+ data |= FIFO_WORKAROUNDS_MSK;
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_FIFO_TRIGGER_ACTION__REG, &data);
+ } else {
+ comres = -1;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_get_fifo_trig_src(struct i2c_client *client, unsigned char
+ *trig_src)
+{
+ int comres;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_FIFO_TRIGGER_SOURCE__REG, &data);
+ *trig_src = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_FIFO_TRIGGER_SOURCE);
+
+ return comres;
+}
+
+static int smi130_acc_set_fifo_trig_src(struct i2c_client *client, unsigned char
+ trig_src)
+{
+ unsigned char data = 0;
+ int comres = 0;
+
+ if (trig_src < 4) {
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_FIFO_TRIGGER_SOURCE__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_FIFO_TRIGGER_SOURCE,
+ trig_src);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_FIFO_TRIGGER_SOURCE__REG, &data);
+ } else {
+ comres = -1;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_get_fifo_framecount(struct i2c_client *client, unsigned char
+ *framecount)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_FIFO_FRAME_COUNTER_S__REG, &data);
+ *framecount = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_FIFO_FRAME_COUNTER_S);
+
+ return comres;
+}
+
+static int smi130_acc_get_fifo_data_sel(struct i2c_client *client, unsigned char
+ *data_sel)
+{
+ int comres;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_FIFO_DATA_SELECT__REG, &data);
+ *data_sel = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_FIFO_DATA_SELECT);
+
+ return comres;
+}
+
+static int smi130_acc_set_fifo_data_sel(struct i2c_client *client, unsigned char
+ data_sel)
+{
+ unsigned char data = 0;
+ int comres = 0;
+
+ if (data_sel < 4) {
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_FIFO_DATA_SELECT__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_FIFO_DATA_SELECT,
+ data_sel);
+ /*! Aim at fifo workarounds with FIFO_CONFIG_1 */
+ data |= FIFO_WORKAROUNDS_MSK;
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_FIFO_DATA_SELECT__REG,
+ &data);
+ } else {
+ comres = -1;
+ }
+
+ return comres;
+}
+
+
+static int smi130_acc_get_offset_target(struct i2c_client *client, unsigned char
+ channel, unsigned char *offset)
+{
+ unsigned char data = 0;
+ int comres = 0;
+
+ switch (channel) {
+ case SMI_ACC2X2_CUT_OFF:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_COMP_CUTOFF__REG, &data);
+ *offset = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_COMP_CUTOFF);
+ break;
+ case SMI_ACC2X2_OFFSET_TRIGGER_X:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_X__REG, &data);
+ *offset = SMI_ACC2X2_GET_BITSLICE(data,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_X);
+ break;
+ case SMI_ACC2X2_OFFSET_TRIGGER_Y:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Y__REG, &data);
+ *offset = SMI_ACC2X2_GET_BITSLICE(data,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Y);
+ break;
+ case SMI_ACC2X2_OFFSET_TRIGGER_Z:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Z__REG, &data);
+ *offset = SMI_ACC2X2_GET_BITSLICE(data,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Z);
+ break;
+ default:
+ comres = -1;
+ break;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_set_offset_target(struct i2c_client *client, unsigned char
+ channel, unsigned char offset)
+{
+ unsigned char data = 0;
+ int comres = 0;
+
+ switch (channel) {
+ case SMI_ACC2X2_CUT_OFF:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_COMP_CUTOFF__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_COMP_CUTOFF,
+ offset);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_COMP_CUTOFF__REG, &data);
+ break;
+ case SMI_ACC2X2_OFFSET_TRIGGER_X:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_X__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_X,
+ offset);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_X__REG,
+ &data);
+ break;
+ case SMI_ACC2X2_OFFSET_TRIGGER_Y:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Y__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Y,
+ offset);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Y__REG,
+ &data);
+ break;
+ case SMI_ACC2X2_OFFSET_TRIGGER_Z:
+ comres = smi130_acc_smbus_read_byte(client,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Z__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Z,
+ offset);
+ comres = smi130_acc_smbus_write_byte(client,
+ SMI_ACC2X2_COMP_TARGET_OFFSET_Z__REG,
+ &data);
+ break;
+ default:
+ comres = -1;
+ break;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_get_cal_ready(struct i2c_client *client,
+ unsigned char *calrdy)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_FAST_CAL_RDY_S__REG,
+ &data);
+ data = SMI_ACC2X2_GET_BITSLICE(data, SMI_ACC2X2_FAST_CAL_RDY_S);
+ *calrdy = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_cal_trigger(struct i2c_client *client, unsigned char
+ caltrigger)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_CAL_TRIGGER__REG, &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_CAL_TRIGGER, caltrigger);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_CAL_TRIGGER__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_write_reg(struct i2c_client *client, unsigned char addr,
+ unsigned char *data)
+{
+ int comres = 0;
+ comres = smi130_acc_smbus_write_byte(client, addr, data);
+
+ return comres;
+}
+
+
+static int smi130_acc_set_offset_x(struct i2c_client *client, unsigned char
+ offsetfilt)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ data = offsetfilt;
+
+#ifdef CONFIG_SENSORS_BMI058
+ comres = smi130_acc_smbus_write_byte(client, BMI058_OFFSET_X_AXIS_REG,
+ &data);
+#else
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_OFFSET_X_AXIS_REG,
+ &data);
+#endif
+
+ return comres;
+}
+
+
+static int smi130_acc_get_offset_x(struct i2c_client *client, unsigned char
+ *offsetfilt)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+#ifdef CONFIG_SENSORS_BMI058
+ comres = smi130_acc_smbus_read_byte(client, BMI058_OFFSET_X_AXIS_REG,
+ &data);
+#else
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_OFFSET_X_AXIS_REG,
+ &data);
+#endif
+ *offsetfilt = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_offset_y(struct i2c_client *client, unsigned char
+ offsetfilt)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ data = offsetfilt;
+
+#ifdef CONFIG_SENSORS_BMI058
+ comres = smi130_acc_smbus_write_byte(client, BMI058_OFFSET_Y_AXIS_REG,
+ &data);
+#else
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_OFFSET_Y_AXIS_REG,
+ &data);
+#endif
+ return comres;
+}
+
+static int smi130_acc_get_offset_y(struct i2c_client *client, unsigned char
+ *offsetfilt)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+#ifdef CONFIG_SENSORS_BMI058
+ comres = smi130_acc_smbus_read_byte(client, BMI058_OFFSET_Y_AXIS_REG,
+ &data);
+#else
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_OFFSET_Y_AXIS_REG,
+ &data);
+#endif
+ *offsetfilt = data;
+
+ return comres;
+}
+
+static int smi130_acc_set_offset_z(struct i2c_client *client, unsigned char
+ offsetfilt)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ data = offsetfilt;
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_OFFSET_Z_AXIS_REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_get_offset_z(struct i2c_client *client, unsigned char
+ *offsetfilt)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_OFFSET_Z_AXIS_REG,
+ &data);
+ *offsetfilt = data;
+
+ return comres;
+}
+
+
+static int smi130_acc_set_selftest_st(struct i2c_client *client, unsigned char
+ selftest)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_EN_SELF_TEST__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_EN_SELF_TEST, selftest);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_EN_SELF_TEST__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_set_selftest_stn(struct i2c_client *client, unsigned char stn)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_NEG_SELF_TEST__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_NEG_SELF_TEST, stn);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_NEG_SELF_TEST__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_set_selftest_amp(struct i2c_client *client, unsigned char amp)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_SELF_TEST_AMP__REG,
+ &data);
+ data = SMI_ACC2X2_SET_BITSLICE(data, SMI_ACC2X2_SELF_TEST_AMP, amp);
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_SELF_TEST_AMP__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_read_accel_x(struct i2c_client *client,
+ signed char sensor_type, short *a_x)
+{
+ int comres = 0;
+ unsigned char data[2];
+
+ switch (sensor_type) {
+ case 0:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_X12_LSB__REG, data, 2);
+ *a_x = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_X12_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_X_MSB)<<(SMI_ACC2X2_ACC_X12_LSB__LEN));
+ *a_x = *a_x << (sizeof(short)*8-(SMI_ACC2X2_ACC_X12_LSB__LEN
+ + SMI_ACC2X2_ACC_X_MSB__LEN));
+ *a_x = *a_x >> (sizeof(short)*8-(SMI_ACC2X2_ACC_X12_LSB__LEN
+ + SMI_ACC2X2_ACC_X_MSB__LEN));
+ break;
+ case 1:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_X10_LSB__REG, data, 2);
+ *a_x = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_X10_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_X_MSB)<<(SMI_ACC2X2_ACC_X10_LSB__LEN));
+ *a_x = *a_x << (sizeof(short)*8-(SMI_ACC2X2_ACC_X10_LSB__LEN
+ + SMI_ACC2X2_ACC_X_MSB__LEN));
+ *a_x = *a_x >> (sizeof(short)*8-(SMI_ACC2X2_ACC_X10_LSB__LEN
+ + SMI_ACC2X2_ACC_X_MSB__LEN));
+ break;
+ case 2:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_X8_LSB__REG, data, 2);
+ *a_x = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_X8_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_X_MSB)<<(SMI_ACC2X2_ACC_X8_LSB__LEN));
+ *a_x = *a_x << (sizeof(short)*8-(SMI_ACC2X2_ACC_X8_LSB__LEN
+ + SMI_ACC2X2_ACC_X_MSB__LEN));
+ *a_x = *a_x >> (sizeof(short)*8-(SMI_ACC2X2_ACC_X8_LSB__LEN
+ + SMI_ACC2X2_ACC_X_MSB__LEN));
+ break;
+ case 3:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_X14_LSB__REG, data, 2);
+ *a_x = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_X14_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_X_MSB)<<(SMI_ACC2X2_ACC_X14_LSB__LEN));
+ *a_x = *a_x << (sizeof(short)*8-(SMI_ACC2X2_ACC_X14_LSB__LEN
+ + SMI_ACC2X2_ACC_X_MSB__LEN));
+ *a_x = *a_x >> (sizeof(short)*8-(SMI_ACC2X2_ACC_X14_LSB__LEN
+ + SMI_ACC2X2_ACC_X_MSB__LEN));
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_soft_reset(struct i2c_client *client)
+{
+ int comres = 0;
+ unsigned char data = SMI_ACC2X2_EN_SOFT_RESET_VALUE;
+
+ comres = smi130_acc_smbus_write_byte(client, SMI_ACC2X2_EN_SOFT_RESET__REG,
+ &data);
+
+ return comres;
+}
+
+static int smi130_acc_read_accel_y(struct i2c_client *client,
+ signed char sensor_type, short *a_y)
+{
+ int comres = 0;
+ unsigned char data[2];
+
+ switch (sensor_type) {
+ case 0:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_Y12_LSB__REG, data, 2);
+ *a_y = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_Y12_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_Y_MSB)<<(SMI_ACC2X2_ACC_Y12_LSB__LEN));
+ *a_y = *a_y << (sizeof(short)*8-(SMI_ACC2X2_ACC_Y12_LSB__LEN
+ + SMI_ACC2X2_ACC_Y_MSB__LEN));
+ *a_y = *a_y >> (sizeof(short)*8-(SMI_ACC2X2_ACC_Y12_LSB__LEN
+ + SMI_ACC2X2_ACC_Y_MSB__LEN));
+ break;
+ case 1:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_Y10_LSB__REG, data, 2);
+ *a_y = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_Y10_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_Y_MSB)<<(SMI_ACC2X2_ACC_Y10_LSB__LEN));
+ *a_y = *a_y << (sizeof(short)*8-(SMI_ACC2X2_ACC_Y10_LSB__LEN
+ + SMI_ACC2X2_ACC_Y_MSB__LEN));
+ *a_y = *a_y >> (sizeof(short)*8-(SMI_ACC2X2_ACC_Y10_LSB__LEN
+ + SMI_ACC2X2_ACC_Y_MSB__LEN));
+ break;
+ case 2:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_Y8_LSB__REG, data, 2);
+ *a_y = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_Y8_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_Y_MSB)<<(SMI_ACC2X2_ACC_Y8_LSB__LEN));
+ *a_y = *a_y << (sizeof(short)*8-(SMI_ACC2X2_ACC_Y8_LSB__LEN
+ + SMI_ACC2X2_ACC_Y_MSB__LEN));
+ *a_y = *a_y >> (sizeof(short)*8-(SMI_ACC2X2_ACC_Y8_LSB__LEN
+ + SMI_ACC2X2_ACC_Y_MSB__LEN));
+ break;
+ case 3:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_Y14_LSB__REG, data, 2);
+ *a_y = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_Y14_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_Y_MSB)<<(SMI_ACC2X2_ACC_Y14_LSB__LEN));
+ *a_y = *a_y << (sizeof(short)*8-(SMI_ACC2X2_ACC_Y14_LSB__LEN
+ + SMI_ACC2X2_ACC_Y_MSB__LEN));
+ *a_y = *a_y >> (sizeof(short)*8-(SMI_ACC2X2_ACC_Y14_LSB__LEN
+ + SMI_ACC2X2_ACC_Y_MSB__LEN));
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+static int smi130_acc_read_accel_z(struct i2c_client *client,
+ signed char sensor_type, short *a_z)
+{
+ int comres = 0;
+ unsigned char data[2];
+
+ switch (sensor_type) {
+ case 0:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_Z12_LSB__REG, data, 2);
+ *a_z = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_Z12_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_Z_MSB)<<(SMI_ACC2X2_ACC_Z12_LSB__LEN));
+ *a_z = *a_z << (sizeof(short)*8-(SMI_ACC2X2_ACC_Z12_LSB__LEN
+ + SMI_ACC2X2_ACC_Z_MSB__LEN));
+ *a_z = *a_z >> (sizeof(short)*8-(SMI_ACC2X2_ACC_Z12_LSB__LEN
+ + SMI_ACC2X2_ACC_Z_MSB__LEN));
+ break;
+ case 1:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_Z10_LSB__REG, data, 2);
+ *a_z = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_Z10_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_Z_MSB)<<(SMI_ACC2X2_ACC_Z10_LSB__LEN));
+ *a_z = *a_z << (sizeof(short)*8-(SMI_ACC2X2_ACC_Z10_LSB__LEN
+ + SMI_ACC2X2_ACC_Z_MSB__LEN));
+ *a_z = *a_z >> (sizeof(short)*8-(SMI_ACC2X2_ACC_Z10_LSB__LEN
+ + SMI_ACC2X2_ACC_Z_MSB__LEN));
+ break;
+ case 2:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_Z8_LSB__REG, data, 2);
+ *a_z = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_Z8_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_Z_MSB)<<(SMI_ACC2X2_ACC_Z8_LSB__LEN));
+ *a_z = *a_z << (sizeof(short)*8-(SMI_ACC2X2_ACC_Z8_LSB__LEN
+ + SMI_ACC2X2_ACC_Z_MSB__LEN));
+ *a_z = *a_z >> (sizeof(short)*8-(SMI_ACC2X2_ACC_Z8_LSB__LEN
+ + SMI_ACC2X2_ACC_Z_MSB__LEN));
+ break;
+ case 3:
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_Z14_LSB__REG, data, 2);
+ *a_z = SMI_ACC2X2_GET_BITSLICE(data[0], SMI_ACC2X2_ACC_Z14_LSB)|
+ (SMI_ACC2X2_GET_BITSLICE(data[1],
+ SMI_ACC2X2_ACC_Z_MSB)<<(SMI_ACC2X2_ACC_Z14_LSB__LEN));
+ *a_z = *a_z << (sizeof(short)*8-(SMI_ACC2X2_ACC_Z14_LSB__LEN
+ + SMI_ACC2X2_ACC_Z_MSB__LEN));
+ *a_z = *a_z >> (sizeof(short)*8-(SMI_ACC2X2_ACC_Z14_LSB__LEN
+ + SMI_ACC2X2_ACC_Z_MSB__LEN));
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+
+static int smi130_acc_read_temperature(struct i2c_client *client,
+ signed char *temperature)
+{
+ unsigned char data = 0;
+ int comres = 0;
+
+ comres = smi130_acc_smbus_read_byte(client, SMI_ACC2X2_TEMPERATURE_REG, &data);
+ *temperature = (signed char)data;
+
+ return comres;
+}
+
+static ssize_t smi130_acc_enable_int_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int type, value;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+#ifdef CONFIG_SENSORS_BMI058
+ int i;
+#endif
+
+ sscanf(buf, "%3d %3d", &type, &value);
+
+#ifdef CONFIG_SENSORS_BMI058
+ for (i = 0; i < sizeof(int_map) / sizeof(struct interrupt_map_t); i++) {
+ if (int_map[i].x == type) {
+ type = int_map[i].y;
+ break;
+ }
+ if (int_map[i].y == type) {
+ type = int_map[i].x;
+ break;
+ }
+ }
+#endif
+
+ if (smi130_acc_set_Int_Enable(smi130_acc->smi130_acc_client, type, value) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+static ssize_t smi130_acc_int_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_Int_Mode(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_acc_int_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_Int_Mode(smi130_acc->smi130_acc_client, (unsigned char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t smi130_acc_slope_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_slope_duration(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_slope_duration_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_slope_duration(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_slope_no_mot_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_slope_no_mot_duration(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_slope_no_mot_duration_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_slope_no_mot_duration(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+static ssize_t smi130_acc_slope_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_slope_threshold(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_slope_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_slope_threshold(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_slope_no_mot_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_slope_no_mot_threshold(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_slope_no_mot_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_slope_no_mot_threshold(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_high_g_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_high_g_duration(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_high_g_duration_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_high_g_duration(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_high_g_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_high_g_threshold(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_high_g_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_high_g_threshold(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_low_g_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_low_g_duration(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_low_g_duration_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_low_g_duration(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_low_g_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_low_g_threshold(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_low_g_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_low_g_threshold(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t smi130_acc_tap_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_tap_threshold(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_tap_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_tap_threshold(smi130_acc->smi130_acc_client, (unsigned char)data)
+ < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t smi130_acc_tap_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_tap_duration(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_tap_duration_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_tap_duration(smi130_acc->smi130_acc_client, (unsigned char)data)
+ < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t smi130_acc_tap_quiet_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_tap_quiet(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_tap_quiet_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_tap_quiet(smi130_acc->smi130_acc_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_tap_shock_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_tap_shock(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_tap_shock_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_tap_shock(smi130_acc->smi130_acc_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_tap_samp_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_tap_samp(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_tap_samp_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_tap_samp(smi130_acc->smi130_acc_client, (unsigned char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_orient_mbl_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_orient_mbl_mode(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_orient_mbl_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_orient_mbl_mode(smi130_acc->smi130_acc_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_orient_mbl_blocking_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_orient_mbl_blocking(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_orient_mbl_blocking_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_orient_mbl_blocking(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t smi130_acc_orient_mbl_hyst_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_orient_mbl_hyst(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_orient_mbl_hyst_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_orient_mbl_hyst(smi130_acc->smi130_acc_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_orient_mbl_theta_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_theta_blocking(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_orient_mbl_theta_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_theta_blocking(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_flat_theta_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_theta_flat(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_flat_theta_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_theta_flat(smi130_acc->smi130_acc_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t smi130_acc_flat_hold_time_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_flat_hold_time(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+static ssize_t smi130_acc_selftest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&smi130_acc->selftest_result));
+
+}
+
+static ssize_t smi130_acc_softreset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_soft_reset(smi130_acc->smi130_acc_client) < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t smi130_acc_selftest_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ unsigned long data;
+ unsigned char clear_value = 0;
+ int error;
+ short value1 = 0;
+ short value2 = 0;
+ short diff = 0;
+ unsigned long result = 0;
+ unsigned char test_result_branch = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ smi130_acc_soft_reset(smi130_acc->smi130_acc_client);
+ smi130_acc_delay(5);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (data != 1)
+ return -EINVAL;
+
+ smi130_acc_write_reg(smi130_acc->smi130_acc_client, 0x32, &clear_value);
+
+ if ((smi130_acc->sensor_type == SMI_ACC280_TYPE) ||
+ (smi130_acc->sensor_type == SMI_ACC255_TYPE)) {
+#ifdef CONFIG_SENSORS_BMI058
+ /*set self test amp */
+ if (smi130_acc_set_selftest_amp(smi130_acc->smi130_acc_client, 1) < 0)
+ return -EINVAL;
+ /* set to 8 G range */
+ if (smi130_acc_set_range(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_RANGE_8G) < 0)
+ return -EINVAL;
+#else
+ /* set to 4 G range */
+ if (smi130_acc_set_range(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_RANGE_4G) < 0)
+ return -EINVAL;
+#endif
+ }
+
+ if ((smi130_acc->sensor_type == SMI_ACC250E_TYPE) ||
+ (smi130_acc->sensor_type == SMI_ACC222E_TYPE)) {
+ /* set to 8 G range */
+ if (smi130_acc_set_range(smi130_acc->smi130_acc_client, 8) < 0)
+ return -EINVAL;
+ if (smi130_acc_set_selftest_amp(smi130_acc->smi130_acc_client, 1) < 0)
+ return -EINVAL;
+ }
+
+ /* 1 for x-axis(but BMI058 is 1 for y-axis )*/
+ smi130_acc_set_selftest_st(smi130_acc->smi130_acc_client, 1);
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 0);
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_x(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value1);
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 1);
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_x(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value2);
+ diff = value1-value2;
+
+#ifdef CONFIG_SENSORS_BMI058
+ PINFO("diff y is %d,value1 is %d, value2 is %d\n", diff,
+ value1, value2);
+ test_result_branch = 2;
+#else
+ PINFO("diff x is %d,value1 is %d, value2 is %d\n", diff,
+ value1, value2);
+ test_result_branch = 1;
+#endif
+
+ if (smi130_acc->sensor_type == SMI_ACC280_TYPE) {
+#ifdef CONFIG_SENSORS_BMI058
+ if (abs(diff) < 819)
+ result |= test_result_branch;
+#else
+ if (abs(diff) < 1638)
+ result |= test_result_branch;
+#endif
+ }
+ if (smi130_acc->sensor_type == SMI_ACC255_TYPE) {
+ if (abs(diff) < 409)
+ result |= 1;
+ }
+ if (smi130_acc->sensor_type == SMI_ACC250E_TYPE) {
+ if (abs(diff) < 51)
+ result |= 1;
+ }
+ if (smi130_acc->sensor_type == SMI_ACC222E_TYPE) {
+ if (abs(diff) < 12)
+ result |= 1;
+ }
+
+ /* 2 for y-axis but BMI058 is 1*/
+ smi130_acc_set_selftest_st(smi130_acc->smi130_acc_client, 2);
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 0);
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_y(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value1);
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 1);
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_y(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value2);
+ diff = value1-value2;
+
+#ifdef CONFIG_SENSORS_BMI058
+ PINFO("diff x is %d,value1 is %d, value2 is %d\n", diff,
+ value1, value2);
+ test_result_branch = 1;
+#else
+ PINFO("diff y is %d,value1 is %d, value2 is %d\n", diff,
+ value1, value2);
+ test_result_branch = 2;
+#endif
+
+ if (smi130_acc->sensor_type == SMI_ACC280_TYPE) {
+#ifdef CONFIG_SENSORS_BMI058
+ if (abs(diff) < 819)
+ result |= test_result_branch;
+#else
+ if (abs(diff) < 1638)
+ result |= test_result_branch;
+#endif
+ }
+ if (smi130_acc->sensor_type == SMI_ACC255_TYPE) {
+ if (abs(diff) < 409)
+ result |= test_result_branch;
+ }
+ if (smi130_acc->sensor_type == SMI_ACC250E_TYPE) {
+ if (abs(diff) < 51)
+ result |= test_result_branch;
+ }
+ if (smi130_acc->sensor_type == SMI_ACC222E_TYPE) {
+ if (abs(diff) < 12)
+ result |= test_result_branch;
+ }
+
+
+ smi130_acc_set_selftest_st(smi130_acc->smi130_acc_client, 3); /* 3 for z-axis*/
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 0);
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_z(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value1);
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 1);
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_z(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value2);
+ diff = value1-value2;
+
+ PINFO("diff z is %d,value1 is %d, value2 is %d\n", diff,
+ value1, value2);
+
+ if (smi130_acc->sensor_type == SMI_ACC280_TYPE) {
+#ifdef CONFIG_SENSORS_BMI058
+ if (abs(diff) < 409)
+ result |= 4;
+#else
+ if (abs(diff) < 819)
+ result |= 4;
+#endif
+ }
+ if (smi130_acc->sensor_type == SMI_ACC255_TYPE) {
+ if (abs(diff) < 204)
+ result |= 4;
+ }
+ if (smi130_acc->sensor_type == SMI_ACC250E_TYPE) {
+ if (abs(diff) < 25)
+ result |= 4;
+ }
+ if (smi130_acc->sensor_type == SMI_ACC222E_TYPE) {
+ if (abs(diff) < 6)
+ result |= 4;
+ }
+
+ /* self test for smi_acc254 */
+ if ((smi130_acc->sensor_type == SMI_ACC255_TYPE) && (result > 0)) {
+ result = 0;
+ smi130_acc_soft_reset(smi130_acc->smi130_acc_client);
+ smi130_acc_delay(5);
+ smi130_acc_write_reg(smi130_acc->smi130_acc_client, 0x32, &clear_value);
+ /* set to 8 G range */
+ if (smi130_acc_set_range(smi130_acc->smi130_acc_client, 8) < 0)
+ return -EINVAL;
+ if (smi130_acc_set_selftest_amp(smi130_acc->smi130_acc_client, 1) < 0)
+ return -EINVAL;
+
+ smi130_acc_set_selftest_st(smi130_acc->smi130_acc_client, 1); /* 1
+ for x-axis*/
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 0); /*
+ positive direction*/
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_x(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value1);
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 1); /*
+ negative direction*/
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_x(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value2);
+ diff = value1-value2;
+
+ PINFO("diff x is %d,value1 is %d, value2 is %d\n",
+ diff, value1, value2);
+ if (abs(diff) < 204)
+ result |= 1;
+
+ smi130_acc_set_selftest_st(smi130_acc->smi130_acc_client, 2); /* 2
+ for y-axis*/
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 0); /*
+ positive direction*/
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_y(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value1);
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 1); /*
+ negative direction*/
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_y(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value2);
+ diff = value1-value2;
+ PINFO("diff y is %d,value1 is %d, value2 is %d\n",
+ diff, value1, value2);
+
+ if (abs(diff) < 204)
+ result |= 2;
+
+ smi130_acc_set_selftest_st(smi130_acc->smi130_acc_client, 3); /* 3
+ for z-axis*/
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 0); /*
+ positive direction*/
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_z(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value1);
+ smi130_acc_set_selftest_stn(smi130_acc->smi130_acc_client, 1); /*
+ negative direction*/
+ smi130_acc_delay(10);
+ smi130_acc_read_accel_z(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &value2);
+ diff = value1-value2;
+
+ PINFO("diff z is %d,value1 is %d, value2 is %d\n",
+ diff, value1, value2);
+ if (abs(diff) < 102)
+ result |= 4;
+ }
+
+ atomic_set(&smi130_acc->selftest_result, (unsigned int)result);
+
+ smi130_acc_soft_reset(smi130_acc->smi130_acc_client);
+ smi130_acc_delay(5);
+ PINFO("self test finished\n");
+
+ return count;
+}
+
+
+
+static ssize_t smi130_acc_flat_hold_time_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_flat_hold_time(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+const int smi130_acc_sensor_bitwidth[] = {
+ 12, 10, 8, 14
+};
+
+static int smi130_acc_read_accel_xyz(struct i2c_client *client,
+ signed char sensor_type, struct smi130_accacc *acc)
+{
+ int comres = 0;
+ unsigned char data[6];
+ struct smi130_acc_data *client_data = i2c_get_clientdata(client);
+#ifndef SMI_ACC2X2_SENSOR_IDENTIFICATION_ENABLE
+ int bitwidth;
+#endif
+ comres = smi130_acc_smbus_read_byte_block(client,
+ SMI_ACC2X2_ACC_X12_LSB__REG, data, 6);
+ if (sensor_type >= 4)
+ return -EINVAL;
+
+ acc->x = (data[1]<<8)|data[0];
+ acc->y = (data[3]<<8)|data[2];
+ acc->z = (data[5]<<8)|data[4];
+
+#ifndef SMI_ACC2X2_SENSOR_IDENTIFICATION_ENABLE
+ bitwidth = smi130_acc_sensor_bitwidth[sensor_type];
+
+ acc->x = (acc->x >> (16 - bitwidth));
+ acc->y = (acc->y >> (16 - bitwidth));
+ acc->z = (acc->z >> (16 - bitwidth));
+#endif
+
+ smi130_acc_remap_sensor_data(acc, client_data);
+ return comres;
+}
+
+#ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+static void smi130_acc_work_func(struct work_struct *work)
+{
+ struct smi130_acc_data *smi130_acc = container_of((struct delayed_work *)work,
+ struct smi130_acc_data, work);
+ static struct smi130_accacc acc;
+ unsigned long delay = msecs_to_jiffies(atomic_read(&smi130_acc->delay));
+
+ smi130_acc_read_accel_xyz(smi130_acc->smi130_acc_client, smi130_acc->sensor_type, &acc);
+ input_report_abs(smi130_acc->input, ABS_X, acc.x);
+ input_report_abs(smi130_acc->input, ABS_Y, acc.y);
+ input_report_abs(smi130_acc->input, ABS_Z, acc.z);
+ input_sync(smi130_acc->input);
+ mutex_lock(&smi130_acc->value_mutex);
+ smi130_acc->value = acc;
+ mutex_unlock(&smi130_acc->value_mutex);
+ schedule_delayed_work(&smi130_acc->work, delay);
+}
+#endif
+static struct workqueue_struct *reportdata_wq;
+
+uint64_t smi130_acc_get_alarm_timestamp(void)
+{
+ uint64_t ts_ap;
+ struct timespec tmp_time;
+ get_monotonic_boottime(&tmp_time);
+ ts_ap = (uint64_t)tmp_time.tv_sec * 1000000000 + tmp_time.tv_nsec;
+ return ts_ap;
+}
+
+#define ABS(x) ((x) > 0 ? (x) : -(x))
+
+static void smi130_acc_timer_work_fun(struct work_struct *work)
+{
+ struct smi130_acc_data *smi130_acc =
+ container_of(work,
+ struct smi130_acc_data, report_data_work);
+ int i;
+ unsigned char count = 0;
+ unsigned char mode = 0;
+ signed char fifo_data_out[MAX_FIFO_F_LEVEL * MAX_FIFO_F_BYTES] = {0};
+ unsigned char f_len = 0;
+ uint64_t del = 0;
+ uint64_t time_internal = 0;
+ int64_t drift_time = 0;
+ static uint64_t time_odr;
+ struct smi130_accacc acc_lsb;
+ struct timespec ts;
+ static uint32_t data_cnt;
+ static uint32_t pre_data_cnt;
+ static int64_t sample_drift_offset;
+
+ if (smi130_acc->fifo_datasel) {
+ /*Select one axis data output for every fifo frame*/
+ f_len = 2;
+ } else {
+ /*Select X Y Z axis data output for every fifo frame*/
+ f_len = 6;
+ }
+ if (smi130_acc_get_fifo_framecount(smi130_acc->smi130_acc_client, &count) < 0) {
+ PERR("smi130_acc_get_fifo_framecount err\n");
+ return;
+ }
+ if (count == 0) {
+ PERR("smi130_acc_get_fifo_framecount zero\n");
+ return;
+ }
+ if (count > MAX_FIFO_F_LEVEL) {
+ if (smi130_acc_get_mode(smi130_acc->smi130_acc_client, &mode) < 0) {
+ PERR("smi130_acc_get_mode err\n");
+ return;
+ }
+ if (SMI_ACC2X2_MODE_NORMAL == mode) {
+ PERR("smi130_acc fifo_count: %d abnormal, op_mode: %d\n",
+ count, mode);
+ count = MAX_FIFO_F_LEVEL;
+ } else {
+ /*chip already suspend or shutdown*/
+ count = 0;
+ return;
+ }
+ }
+ if (smi_acc_i2c_burst_read(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_FIFO_DATA_OUTPUT_REG, fifo_data_out,
+ count * f_len) < 0) {
+ PERR("smi130_acc read fifo err\n");
+ return;
+ }
+ smi130_acc->fifo_time = smi130_acc_get_alarm_timestamp();
+ if (smi130_acc->acc_count == 0)
+ smi130_acc->base_time = smi130_acc->timestamp =
+ smi130_acc->fifo_time - (count-1) * smi130_acc->time_odr;
+
+ smi130_acc->acc_count += count;
+ del = smi130_acc->fifo_time - smi130_acc->base_time;
+ time_internal = div64_u64(del, smi130_acc->acc_count);
+
+ data_cnt++;
+ if (data_cnt == 1)
+ time_odr = smi130_acc->time_odr;
+
+ if (time_internal > time_odr) {
+ if (time_internal - time_odr > div64_u64 (time_odr, 200))
+ time_internal = time_odr + div64_u64(time_odr, 200);
+ } else {
+ if (time_odr - time_internal > div64_u64(time_odr, 200))
+ time_internal = time_odr - div64_u64(time_odr, 200);
+ }
+/* please give attation for the fifo output data format*/
+ if (f_len == 6) {
+ /* Select X Y Z axis data output for every frame */
+ for (i = 0; i < count; i++) {
+ if (smi130_acc->debug_level & 0x01)
+ printk(KERN_INFO "smi_acc time =%llu fifo_time =%llu smi_acc->count=%llu time_internal =%lld time_odr = %lld ",
+ smi130_acc->timestamp, smi130_acc->fifo_time,
+ smi130_acc->acc_count, time_internal, time_odr);
+
+ ts = ns_to_timespec(smi130_acc->timestamp);
+ acc_lsb.x =
+ ((unsigned char)fifo_data_out[i * f_len + 1] << 8 |
+ (unsigned char)fifo_data_out[i * f_len + 0]);
+ acc_lsb.y =
+ ((unsigned char)fifo_data_out[i * f_len + 3] << 8 |
+ (unsigned char)fifo_data_out[i * f_len + 2]);
+ acc_lsb.z =
+ ((unsigned char)fifo_data_out[i * f_len + 5] << 8 |
+ (unsigned char)fifo_data_out[i * f_len + 4]);
+#ifndef SMI_ACC2X2_SENSOR_IDENTIFICATION_ENABLE
+ acc_lsb.x >>=
+ (16 - smi130_acc_sensor_bitwidth[smi130_acc->sensor_type]);
+ acc_lsb.y >>=
+ (16 - smi130_acc_sensor_bitwidth[smi130_acc->sensor_type]);
+ acc_lsb.z >>=
+ (16 - smi130_acc_sensor_bitwidth[smi130_acc->sensor_type]);
+#endif
+ smi130_acc_remap_sensor_data(&acc_lsb, smi130_acc);
+ input_event(smi130_acc->input, EV_MSC, MSC_TIME,
+ ts.tv_sec);
+ input_event(smi130_acc->input, EV_MSC, MSC_TIME,
+ ts.tv_nsec);
+ input_event(smi130_acc->input, EV_MSC,
+ MSC_GESTURE, acc_lsb.x);
+ input_event(smi130_acc->input, EV_MSC,
+ MSC_RAW, acc_lsb.y);
+ input_event(smi130_acc->input, EV_MSC,
+ MSC_SCAN, acc_lsb.z);
+ input_sync(smi130_acc->input);
+ smi130_acc->timestamp +=
+ time_internal - sample_drift_offset;
+ }
+ }
+ drift_time = smi130_acc->timestamp - smi130_acc->fifo_time;
+ if (data_cnt % 20 == 0) {
+ if (ABS(drift_time) > div64_u64(time_odr, 5)) {
+ sample_drift_offset =
+ div64_s64(drift_time, smi130_acc->acc_count - pre_data_cnt);
+ pre_data_cnt = smi130_acc->acc_count;
+ time_odr = time_internal;
+ }
+ }
+
+}
+
+static enum hrtimer_restart reportdata_timer_fun(
+ struct hrtimer *hrtimer)
+{
+ struct smi130_acc_data *client_data =
+ container_of(hrtimer, struct smi130_acc_data, timer);
+ int32_t delay = 0;
+ delay = 8;
+ queue_work(reportdata_wq, &(client_data->report_data_work));
+ /*set delay 8ms*/
+ client_data->work_delay_kt = ns_to_ktime(delay*1000000);
+ hrtimer_forward(hrtimer, ktime_get(), client_data->work_delay_kt);
+
+ return HRTIMER_RESTART;
+}
+
+static ssize_t smi130_acc_enable_timer_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ return snprintf(buf, 16, "%d\n", smi130_acc->is_timer_running);
+}
+
+static ssize_t smi130_acc_enable_timer_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (data) {
+ if (0 == smi130_acc->is_timer_running) {
+ hrtimer_start(&smi130_acc->timer,
+ ns_to_ktime(1000000),
+ HRTIMER_MODE_REL);
+ smi130_acc->base_time = 0;
+ smi130_acc->timestamp = 0;
+ smi130_acc->is_timer_running = 1;
+ }
+ } else {
+ if (1 == smi130_acc->is_timer_running) {
+ hrtimer_cancel(&smi130_acc->timer);
+ smi130_acc->is_timer_running = 0;
+ smi130_acc->base_time = 0;
+ smi130_acc->timestamp = 0;
+ smi130_acc->fifo_time = 0;
+ smi130_acc->acc_count = 0;
+ }
+ }
+ return count;
+}
+
+static ssize_t smi130_acc_debug_level_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+ err = snprintf(buf, 8, "%d\n", smi130_acc->debug_level);
+ return err;
+}
+static ssize_t smi130_acc_debug_level_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int32_t ret = 0;
+ unsigned long data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ ret = kstrtoul(buf, 16, &data);
+ if (ret)
+ return ret;
+ smi130_acc->debug_level = (uint8_t)data;
+ return count;
+}
+
+static ssize_t smi130_acc_register_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int address, value;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ sscanf(buf, "%3d %3d", &address, &value);
+ if (smi130_acc_write_reg(smi130_acc->smi130_acc_client, (unsigned char)address,
+ (unsigned char *)&value) < 0)
+ return -EINVAL;
+ return count;
+}
+static ssize_t smi130_acc_register_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ size_t count = 0;
+ u8 reg[0x40];
+ int i;
+
+ for (i = 0; i < 0x40; i++) {
+ smi130_acc_smbus_read_byte(smi130_acc->smi130_acc_client, i, reg+i);
+
+ count += snprintf(&buf[count], 32, "0x%x: %d\n", i, reg[i]);
+ }
+ return count;
+
+
+}
+
+static ssize_t smi130_acc_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_range(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_acc_range_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_range(smi130_acc->smi130_acc_client, (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_bandwidth_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_bandwidth(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_bandwidth_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc->sensor_type == SMI_ACC280_TYPE)
+ if ((unsigned char) data > 14)
+ return -EINVAL;
+
+ if (smi130_acc_set_bandwidth(smi130_acc->smi130_acc_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+ smi130_acc->base_time = 0;
+ smi130_acc->acc_count = 0;
+
+ return count;
+}
+
+static ssize_t smi130_acc_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_mode(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 32, "%d %d\n", data, smi130_acc->smi_acc_mode_enabled);
+}
+
+static ssize_t smi130_acc_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_mode(smi130_acc->smi130_acc_client,
+ (unsigned char) data, SMI_ACC_ENABLED_BSX) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_value_cache_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi130_acc_data *smi130_acc = input_get_drvdata(input);
+ struct smi130_accacc acc_value;
+
+ mutex_lock(&smi130_acc->value_mutex);
+ acc_value = smi130_acc->value;
+ mutex_unlock(&smi130_acc->value_mutex);
+
+ return snprintf(buf, 96, "%d %d %d\n", acc_value.x, acc_value.y,
+ acc_value.z);
+}
+
+static ssize_t smi130_acc_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi130_acc_data *smi130_acc = input_get_drvdata(input);
+ struct smi130_accacc acc_value;
+
+ smi130_acc_read_accel_xyz(smi130_acc->smi130_acc_client, smi130_acc->sensor_type,
+ &acc_value);
+
+ return snprintf(buf, 96, "%d %d %d\n", acc_value.x, acc_value.y,
+ acc_value.z);
+}
+
+static ssize_t smi130_acc_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&smi130_acc->delay));
+
+}
+
+static ssize_t smi130_acc_chip_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ return snprintf(buf, 16, "%u\n", smi130_acc->chip_id);
+
+}
+
+
+static ssize_t smi130_acc_place_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+ int place = BOSCH_SENSOR_PLACE_UNKNOWN;
+
+ if (NULL != smi130_acc->bosch_pd)
+ place = smi130_acc->bosch_pd->place;
+
+ return snprintf(buf, 16, "%d\n", place);
+}
+
+
+static ssize_t smi130_acc_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (data > SMI_ACC2X2_MAX_DELAY)
+ data = SMI_ACC2X2_MAX_DELAY;
+ atomic_set(&smi130_acc->delay, (unsigned int) data);
+
+ return count;
+}
+
+
+static ssize_t smi130_acc_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&smi130_acc->enable));
+
+}
+
+static void smi130_acc_set_enable(struct device *dev, int enable)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+ int pre_enable = atomic_read(&smi130_acc->enable);
+
+ mutex_lock(&smi130_acc->enable_mutex);
+ if (enable) {
+ if (pre_enable == 0) {
+ smi130_acc_set_mode(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_MODE_NORMAL, SMI_ACC_ENABLED_INPUT);
+
+ #ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ schedule_delayed_work(&smi130_acc->work,
+ msecs_to_jiffies(atomic_read(&smi130_acc->delay)));
+#endif
+ atomic_set(&smi130_acc->enable, 1);
+ }
+
+ } else {
+ if (pre_enable == 1) {
+ smi130_acc_set_mode(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_MODE_SUSPEND, SMI_ACC_ENABLED_INPUT);
+
+ #ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ cancel_delayed_work_sync(&smi130_acc->work);
+#endif
+ atomic_set(&smi130_acc->enable, 0);
+ }
+ }
+ mutex_unlock(&smi130_acc->enable_mutex);
+
+}
+
+static ssize_t smi130_acc_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if ((data == 0) || (data == 1))
+ smi130_acc_set_enable(dev, data);
+
+ return count;
+}
+static ssize_t smi130_acc_fast_calibration_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+#ifdef CONFIG_SENSORS_BMI058
+ if (smi130_acc_get_offset_target(smi130_acc->smi130_acc_client,
+ BMI058_OFFSET_TRIGGER_X, &data) < 0)
+ return -EINVAL;
+#else
+ if (smi130_acc_get_offset_target(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_OFFSET_TRIGGER_X, &data) < 0)
+ return -EINVAL;
+#endif
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_fast_calibration_x_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ signed char tmp;
+ unsigned char timeout = 0;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+#ifdef CONFIG_SENSORS_BMI058
+ if (smi130_acc_set_offset_target(smi130_acc->smi130_acc_client,
+ BMI058_OFFSET_TRIGGER_X, (unsigned char)data) < 0)
+ return -EINVAL;
+#else
+ if (smi130_acc_set_offset_target(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_OFFSET_TRIGGER_X, (unsigned char)data) < 0)
+ return -EINVAL;
+#endif
+
+ if (smi130_acc_set_cal_trigger(smi130_acc->smi130_acc_client, 1) < 0)
+ return -EINVAL;
+
+ do {
+ smi130_acc_delay(2);
+ smi130_acc_get_cal_ready(smi130_acc->smi130_acc_client, &tmp);
+
+ /*PINFO("wait 2ms cal ready flag is %d\n", tmp); */
+ timeout++;
+ if (timeout == 50) {
+ PINFO("get fast calibration ready error\n");
+ return -EINVAL;
+ };
+
+ } while (tmp == 0);
+
+ PINFO("x axis fast calibration finished\n");
+ return count;
+}
+
+static ssize_t smi130_acc_fast_calibration_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+#ifdef CONFIG_SENSORS_BMI058
+ if (smi130_acc_get_offset_target(smi130_acc->smi130_acc_client,
+ BMI058_OFFSET_TRIGGER_Y, &data) < 0)
+ return -EINVAL;
+#else
+ if (smi130_acc_get_offset_target(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_OFFSET_TRIGGER_Y, &data) < 0)
+ return -EINVAL;
+#endif
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_fast_calibration_y_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ signed char tmp;
+ unsigned char timeout = 0;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+#ifdef CONFIG_SENSORS_BMI058
+ if (smi130_acc_set_offset_target(smi130_acc->smi130_acc_client,
+ BMI058_OFFSET_TRIGGER_Y, (unsigned char)data) < 0)
+ return -EINVAL;
+#else
+ if (smi130_acc_set_offset_target(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_OFFSET_TRIGGER_Y, (unsigned char)data) < 0)
+ return -EINVAL;
+#endif
+
+ if (smi130_acc_set_cal_trigger(smi130_acc->smi130_acc_client, 2) < 0)
+ return -EINVAL;
+
+ do {
+ smi130_acc_delay(2);
+ smi130_acc_get_cal_ready(smi130_acc->smi130_acc_client, &tmp);
+
+ /*PINFO("wait 2ms cal ready flag is %d\n", tmp);*/
+ timeout++;
+ if (timeout == 50) {
+ PINFO("get fast calibration ready error\n");
+ return -EINVAL;
+ };
+
+ } while (tmp == 0);
+
+ PINFO("y axis fast calibration finished\n");
+ return count;
+}
+
+static ssize_t smi130_acc_fast_calibration_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_offset_target(smi130_acc->smi130_acc_client, 3, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_fast_calibration_z_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ signed char tmp;
+ unsigned char timeout = 0;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_offset_target(smi130_acc->smi130_acc_client, 3, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ if (smi130_acc_set_cal_trigger(smi130_acc->smi130_acc_client, 3) < 0)
+ return -EINVAL;
+
+ do {
+ smi130_acc_delay(2);
+ smi130_acc_get_cal_ready(smi130_acc->smi130_acc_client, &tmp);
+
+ /*PINFO("wait 2ms cal ready flag is %d\n", tmp);*/
+ timeout++;
+ if (timeout == 50) {
+ PINFO("get fast calibration ready error\n");
+ return -EINVAL;
+ };
+
+ } while (tmp == 0);
+
+ PINFO("z axis fast calibration finished\n");
+ return count;
+}
+
+
+static ssize_t smi130_acc_SleepDur_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_sleep_duration(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_SleepDur_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_sleep_duration(smi130_acc->smi130_acc_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_fifo_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_fifo_mode(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_fifo_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_fifo_mode(smi130_acc->smi130_acc_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+ return count;
+}
+
+
+
+static ssize_t smi130_acc_fifo_trig_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_fifo_trig(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_fifo_trig_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_fifo_trig(smi130_acc->smi130_acc_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+
+static ssize_t smi130_acc_fifo_trig_src_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_fifo_trig_src(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_fifo_trig_src_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (smi130_acc_set_fifo_trig_src(smi130_acc->smi130_acc_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+/*!
+ * @brief show fifo_data_sel axis definition(Android definition, not sensor HW reg).
+ * 0--> x, y, z axis fifo data for every frame
+ * 1--> only x axis fifo data for every frame
+ * 2--> only y axis fifo data for every frame
+ * 3--> only z axis fifo data for every frame
+ */
+static ssize_t smi130_acc_fifo_data_sel_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+ signed char place = BOSCH_SENSOR_PLACE_UNKNOWN;
+ if (smi130_acc_get_fifo_data_sel(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+#ifdef CONFIG_SENSORS_BMI058
+/*Update BMI058 fifo_data_sel to the SMI130_ACC common definition*/
+ if (BMI058_FIFO_DAT_SEL_X == data)
+ data = SMI_ACC2X2_FIFO_DAT_SEL_X;
+ else if (BMI058_FIFO_DAT_SEL_Y == data)
+ data = SMI_ACC2X2_FIFO_DAT_SEL_Y;
+#endif
+
+ /*remaping fifo_dat_sel if define virtual place in BSP files*/
+ if ((NULL != smi130_acc->bosch_pd) &&
+ (BOSCH_SENSOR_PLACE_UNKNOWN != smi130_acc->bosch_pd->place)) {
+ place = smi130_acc->bosch_pd->place;
+ /* sensor with place 0 needs not to be remapped */
+ if ((place > 0) && (place < MAX_AXIS_REMAP_TAB_SZ)) {
+ /* SMI_ACC2X2_FIFO_DAT_SEL_X: 1, Y:2, Z:3;
+ * but bosch_axis_remap_tab_dft[i].src_x:0, y:1, z:2
+ * so we need to +1*/
+ if (SMI_ACC2X2_FIFO_DAT_SEL_X == data)
+ data = bosch_axis_remap_tab_dft[place].src_x + 1;
+ else if (SMI_ACC2X2_FIFO_DAT_SEL_Y == data)
+ data = bosch_axis_remap_tab_dft[place].src_y + 1;
+ }
+ }
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_fifo_framecount_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ unsigned char mode;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_fifo_framecount(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ if (data > MAX_FIFO_F_LEVEL) {
+
+ if (smi130_acc_get_mode(smi130_acc->smi130_acc_client, &mode) < 0)
+ return -EINVAL;
+
+ if (SMI_ACC2X2_MODE_NORMAL == mode) {
+ PERR("smi130_acc fifo_count: %d abnormal, op_mode: %d",
+ data, mode);
+ data = MAX_FIFO_F_LEVEL;
+ } else {
+ /*chip already suspend or shutdown*/
+ data = 0;
+ }
+ }
+
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_acc_fifo_framecount_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ smi130_acc->fifo_count = (unsigned int) data;
+
+ return count;
+}
+
+static ssize_t smi130_acc_temperature_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_read_temperature(smi130_acc->smi130_acc_client, &data) < 0)
+ return -EINVAL;
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+/*!
+ * @brief store fifo_data_sel axis definition(Android definition, not sensor HW reg).
+ * 0--> x, y, z axis fifo data for every frame
+ * 1--> only x axis fifo data for every frame
+ * 2--> only y axis fifo data for every frame
+ * 3--> only z axis fifo data for every frame
+ */
+static ssize_t smi130_acc_fifo_data_sel_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+ signed char place;
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ /*save fifo_data_sel(android definition)*/
+ smi130_acc->fifo_datasel = (unsigned char) data;
+
+ /*remaping fifo_dat_sel if define virtual place*/
+ if ((NULL != smi130_acc->bosch_pd) &&
+ (BOSCH_SENSOR_PLACE_UNKNOWN != smi130_acc->bosch_pd->place)) {
+ place = smi130_acc->bosch_pd->place;
+ /* sensor with place 0 needs not to be remapped */
+ if ((place > 0) && (place < MAX_AXIS_REMAP_TAB_SZ)) {
+ /*Need X Y axis revesal sensor place: P1, P3, P5, P7 */
+ /* SMI_ACC2X2_FIFO_DAT_SEL_X: 1, Y:2, Z:3;
+ * but bosch_axis_remap_tab_dft[i].src_x:0, y:1, z:2
+ * so we need to +1*/
+ if (SMI_ACC2X2_FIFO_DAT_SEL_X == data)
+ data = bosch_axis_remap_tab_dft[place].src_x + 1;
+ else if (SMI_ACC2X2_FIFO_DAT_SEL_Y == data)
+ data = bosch_axis_remap_tab_dft[place].src_y + 1;
+ }
+ }
+#ifdef CONFIG_SENSORS_BMI058
+ /*Update BMI058 fifo_data_sel to the SMI130_ACC common definition*/
+ if (SMI_ACC2X2_FIFO_DAT_SEL_X == data)
+ data = BMI058_FIFO_DAT_SEL_X;
+ else if (SMI_ACC2X2_FIFO_DAT_SEL_Y == data)
+ data = BMI058_FIFO_DAT_SEL_Y;
+
+#endif
+ if (smi130_acc_set_fifo_data_sel(smi130_acc->smi130_acc_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_fifo_data_out_frame_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char f_len = 0;
+ unsigned char count = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+ if (smi130_acc->fifo_datasel) {
+ /*Select one axis data output for every fifo frame*/
+ f_len = 2;
+ } else {
+ /*Select X Y Z axis data output for every fifo frame*/
+ f_len = 6;
+ }
+ if (smi130_acc_get_fifo_framecount(smi130_acc->smi130_acc_client, &count) < 0) {
+ PERR("smi130_acc_get_fifo_framecount err\n");
+ return -EINVAL;
+ }
+ if (count == 0)
+ return 0;
+ if (smi_acc_i2c_burst_read(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_FIFO_DATA_OUTPUT_REG, buf,
+ count * f_len) < 0)
+ return -EINVAL;
+
+ return count * f_len;
+}
+
+static ssize_t smi130_acc_offset_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_offset_x(smi130_acc->smi130_acc_client, &data) < 0)
+ return snprintf(buf, 48, "Read error\n");
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_offset_x_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_offset_x(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_offset_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_offset_y(smi130_acc->smi130_acc_client, &data) < 0)
+ return snprintf(buf, 48, "Read error\n");
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_offset_y_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_offset_y(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_offset_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ if (smi130_acc_get_offset_z(smi130_acc->smi130_acc_client, &data) < 0)
+ return snprintf(buf, 48, "Read error\n");
+
+ return snprintf(buf, 16, "%d\n", data);
+
+}
+
+static ssize_t smi130_acc_offset_z_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (smi130_acc_set_offset_z(smi130_acc->smi130_acc_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi130_acc_driver_version_show(struct device *dev
+ , struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+ int ret;
+
+ if (smi130_acc == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+
+ ret = snprintf(buf, 128, "Driver version: %s\n",
+ DRIVER_VERSION);
+ return ret;
+}
+
+#ifdef CONFIG_SIG_MOTION
+static int smi130_acc_set_en_slope_int(struct smi130_acc_data *smi130_acc,
+ int en)
+{
+ int err;
+ struct i2c_client *client = smi130_acc->smi130_acc_client;
+
+ if (en) {
+ /* Set the related parameters which needs to be fine tuned by
+ * interfaces: slope_threshold and slope_duration
+ */
+ /*dur: 192 samples ~= 3s*/
+ err = smi130_acc_set_slope_duration(client, 0x0);
+ err += smi130_acc_set_slope_threshold(client, 0x16);
+
+ /*Enable the interrupts*/
+ err += smi130_acc_set_Int_Enable(client, 5, 1);/*Slope X*/
+ err += smi130_acc_set_Int_Enable(client, 6, 1);/*Slope Y*/
+ err += smi130_acc_set_Int_Enable(client, 7, 1);/*Slope Z*/
+ #ifdef SMI_ACC2X2_ENABLE_INT1
+ /* TODO: SLOPE can now only be routed to INT1 pin*/
+ err += smi130_acc_set_int1_pad_sel(client, PAD_SLOP);
+ #else
+ /* err += smi130_acc_set_int2_pad_sel(client, PAD_SLOP); */
+ #endif
+ } else {
+ err = smi130_acc_set_Int_Enable(client, 5, 0);/*Slope X*/
+ err += smi130_acc_set_Int_Enable(client, 6, 0);/*Slope Y*/
+ err += smi130_acc_set_Int_Enable(client, 7, 0);/*Slope Z*/
+ }
+ return err;
+}
+
+static ssize_t smi130_acc_en_sig_motion_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&smi130_acc->en_sig_motion));
+}
+
+static int smi130_acc_set_en_sig_motion(struct smi130_acc_data *smi130_acc,
+ int en)
+{
+ int err = 0;
+
+ en = (en >= 1) ? 1 : 0; /* set sig motion sensor status */
+
+ if (atomic_read(&smi130_acc->en_sig_motion) != en) {
+ if (en) {
+ err = smi130_acc_set_mode(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_MODE_NORMAL, SMI_ACC_ENABLED_SGM);
+ err = smi130_acc_set_en_slope_int(smi130_acc, en);
+ enable_irq_wake(smi130_acc->IRQ);
+ } else {
+ disable_irq_wake(smi130_acc->IRQ);
+ err = smi130_acc_set_en_slope_int(smi130_acc, en);
+ err = smi130_acc_set_mode(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_MODE_SUSPEND, SMI_ACC_ENABLED_SGM);
+ }
+ atomic_set(&smi130_acc->en_sig_motion, en);
+ }
+ return err;
+}
+
+static ssize_t smi130_acc_en_sig_motion_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if ((data == 0) || (data == 1))
+ smi130_acc_set_en_sig_motion(smi130_acc, data);
+
+ return count;
+}
+#endif
+
+#ifdef CONFIG_DOUBLE_TAP
+static int smi130_acc_set_en_single_tap_int(struct smi130_acc_data *smi130_acc, int en)
+{
+ int err;
+ struct i2c_client *client = smi130_acc->smi130_acc_client;
+
+ if (en) {
+ /* set tap interruption parameter here if needed.
+ smi130_acc_set_tap_duration(client, 0xc0);
+ smi130_acc_set_tap_threshold(client, 0x16);
+ */
+
+ /*Enable the single tap interrupts*/
+ err = smi130_acc_set_Int_Enable(client, 8, 1);
+ #ifdef SMI_ACC2X2_ENABLE_INT1
+ err += smi130_acc_set_int1_pad_sel(client, PAD_SINGLE_TAP);
+ #else
+ err += smi130_acc_set_int2_pad_sel(client, PAD_SINGLE_TAP);
+ #endif
+ } else {
+ err = smi130_acc_set_Int_Enable(client, 8, 0);
+ }
+ return err;
+}
+
+static ssize_t smi130_acc_tap_time_period_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ return snprintf(buf, 16, "%d\n", smi130_acc->tap_time_period);
+}
+
+static ssize_t smi130_acc_tap_time_period_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ smi130_acc->tap_time_period = data;
+
+ return count;
+}
+
+static ssize_t smi130_acc_en_double_tap_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&smi130_acc->en_double_tap));
+}
+
+static int smi130_acc_set_en_double_tap(struct smi130_acc_data *smi130_acc,
+ int en)
+{
+ int err = 0;
+
+ en = (en >= 1) ? 1 : 0;
+
+ if (atomic_read(&smi130_acc->en_double_tap) != en) {
+ if (en) {
+ err = smi130_acc_set_mode(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_MODE_NORMAL, SMI_ACC_ENABLED_DTAP);
+ err = smi130_acc_set_en_single_tap_int(smi130_acc, en);
+ } else {
+ err = smi130_acc_set_en_single_tap_int(smi130_acc, en);
+ err = smi130_acc_set_mode(smi130_acc->smi130_acc_client,
+ SMI_ACC2X2_MODE_SUSPEND, SMI_ACC_ENABLED_DTAP);
+ }
+ atomic_set(&smi130_acc->en_double_tap, en);
+ }
+ return err;
+}
+
+static ssize_t smi130_acc_en_double_tap_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
+
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if ((data == 0) || (data == 1))
+ smi130_acc_set_en_double_tap(smi130_acc, data);
+
+ return count;
+}
+
+static void smi130_acc_tap_timeout_handle(unsigned long data)
+{
+ struct smi130_acc_data *smi130_acc = (struct smi130_acc_data *)data;
+
+ PINFO("tap interrupt handle, timeout\n");
+ mutex_lock(&smi130_acc->tap_mutex);
+ smi130_acc->tap_times = 0;
+ mutex_unlock(&smi130_acc->tap_mutex);
+
+ /* if a single tap need to report, open the define */
+#ifdef REPORT_SINGLE_TAP_WHEN_DOUBLE_TAP_SENSOR_ENABLED
+ input_report_rel(smi130_acc->dev_interrupt,
+ SINGLE_TAP_INTERRUPT,
+ SINGLE_TAP_INTERRUPT_HAPPENED);
+ input_sync(smi130_acc->dev_interrupt);
+#endif
+
+}
+#endif
+
+static DEVICE_ATTR(range, S_IRUGO | S_IWUSR,
+ smi130_acc_range_show, smi130_acc_range_store);
+static DEVICE_ATTR(bandwidth, S_IRUGO | S_IWUSR,
+ smi130_acc_bandwidth_show, smi130_acc_bandwidth_store);
+static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR,
+ smi130_acc_mode_show, smi130_acc_mode_store);
+static DEVICE_ATTR(value, S_IRUSR,
+ smi130_acc_value_show, NULL);
+static DEVICE_ATTR(value_cache, S_IRUSR,
+ smi130_acc_value_cache_show, NULL);
+static DEVICE_ATTR(delay, S_IRUGO | S_IWUSR,
+ smi130_acc_delay_show, smi130_acc_delay_store);
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
+ smi130_acc_enable_show, smi130_acc_enable_store);
+static DEVICE_ATTR(SleepDur, S_IRUGO | S_IWUSR,
+ smi130_acc_SleepDur_show, smi130_acc_SleepDur_store);
+static DEVICE_ATTR(fast_calibration_x, S_IRUGO | S_IWUSR,
+ smi130_acc_fast_calibration_x_show,
+ smi130_acc_fast_calibration_x_store);
+static DEVICE_ATTR(fast_calibration_y, S_IRUGO | S_IWUSR,
+ smi130_acc_fast_calibration_y_show,
+ smi130_acc_fast_calibration_y_store);
+static DEVICE_ATTR(fast_calibration_z, S_IRUGO | S_IWUSR,
+ smi130_acc_fast_calibration_z_show,
+ smi130_acc_fast_calibration_z_store);
+static DEVICE_ATTR(fifo_mode, S_IRUGO | S_IWUSR,
+ smi130_acc_fifo_mode_show, smi130_acc_fifo_mode_store);
+static DEVICE_ATTR(fifo_framecount, S_IRUGO | S_IWUSR,
+ smi130_acc_fifo_framecount_show, smi130_acc_fifo_framecount_store);
+static DEVICE_ATTR(fifo_trig, S_IRUGO | S_IWUSR,
+ smi130_acc_fifo_trig_show, smi130_acc_fifo_trig_store);
+static DEVICE_ATTR(fifo_trig_src, S_IRUGO | S_IWUSR,
+ smi130_acc_fifo_trig_src_show, smi130_acc_fifo_trig_src_store);
+static DEVICE_ATTR(fifo_data_sel, S_IRUGO | S_IWUSR,
+ smi130_acc_fifo_data_sel_show, smi130_acc_fifo_data_sel_store);
+static DEVICE_ATTR(fifo_data_frame, S_IRUGO,
+ smi130_acc_fifo_data_out_frame_show, NULL);
+static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
+ smi130_acc_register_show, smi130_acc_register_store);
+static DEVICE_ATTR(chip_id, S_IRUSR,
+ smi130_acc_chip_id_show, NULL);
+static DEVICE_ATTR(offset_x, S_IRUGO | S_IWUSR,
+ smi130_acc_offset_x_show,
+ smi130_acc_offset_x_store);
+static DEVICE_ATTR(offset_y, S_IRUGO | S_IWUSR,
+ smi130_acc_offset_y_show,
+ smi130_acc_offset_y_store);
+static DEVICE_ATTR(offset_z, S_IRUGO | S_IWUSR,
+ smi130_acc_offset_z_show,
+ smi130_acc_offset_z_store);
+static DEVICE_ATTR(enable_int, S_IWUSR,
+ NULL, smi130_acc_enable_int_store);
+static DEVICE_ATTR(int_mode, S_IRUGO | S_IWUSR,
+ smi130_acc_int_mode_show, smi130_acc_int_mode_store);
+static DEVICE_ATTR(slope_duration, S_IRUGO | S_IWUSR,
+ smi130_acc_slope_duration_show, smi130_acc_slope_duration_store);
+static DEVICE_ATTR(slope_threshold, S_IRUGO | S_IWUSR,
+ smi130_acc_slope_threshold_show, smi130_acc_slope_threshold_store);
+static DEVICE_ATTR(slope_no_mot_duration, S_IRUGO | S_IWUSR,
+ smi130_acc_slope_no_mot_duration_show,
+ smi130_acc_slope_no_mot_duration_store);
+static DEVICE_ATTR(slope_no_mot_threshold, S_IRUGO | S_IWUSR,
+ smi130_acc_slope_no_mot_threshold_show,
+ smi130_acc_slope_no_mot_threshold_store);
+static DEVICE_ATTR(high_g_duration, S_IRUGO | S_IWUSR,
+ smi130_acc_high_g_duration_show, smi130_acc_high_g_duration_store);
+static DEVICE_ATTR(high_g_threshold, S_IRUGO | S_IWUSR,
+ smi130_acc_high_g_threshold_show, smi130_acc_high_g_threshold_store);
+static DEVICE_ATTR(low_g_duration, S_IRUGO | S_IWUSR,
+ smi130_acc_low_g_duration_show, smi130_acc_low_g_duration_store);
+static DEVICE_ATTR(low_g_threshold, S_IRUGO | S_IWUSR,
+ smi130_acc_low_g_threshold_show, smi130_acc_low_g_threshold_store);
+static DEVICE_ATTR(tap_duration, S_IRUGO | S_IWUSR,
+ smi130_acc_tap_duration_show, smi130_acc_tap_duration_store);
+static DEVICE_ATTR(tap_threshold, S_IRUGO | S_IWUSR,
+ smi130_acc_tap_threshold_show, smi130_acc_tap_threshold_store);
+static DEVICE_ATTR(tap_quiet, S_IRUGO | S_IWUSR,
+ smi130_acc_tap_quiet_show, smi130_acc_tap_quiet_store);
+static DEVICE_ATTR(tap_shock, S_IRUGO | S_IWUSR,
+ smi130_acc_tap_shock_show, smi130_acc_tap_shock_store);
+static DEVICE_ATTR(tap_samp, S_IRUGO | S_IWUSR,
+ smi130_acc_tap_samp_show, smi130_acc_tap_samp_store);
+static DEVICE_ATTR(orient_mbl_mode, S_IRUGO | S_IWUSR,
+ smi130_acc_orient_mbl_mode_show, smi130_acc_orient_mbl_mode_store);
+static DEVICE_ATTR(orient_mbl_blocking, S_IRUGO | S_IWUSR,
+ smi130_acc_orient_mbl_blocking_show, smi130_acc_orient_mbl_blocking_store);
+static DEVICE_ATTR(orient_mbl_hyst, S_IRUGO | S_IWUSR,
+ smi130_acc_orient_mbl_hyst_show, smi130_acc_orient_mbl_hyst_store);
+static DEVICE_ATTR(orient_mbl_theta, S_IRUGO | S_IWUSR,
+ smi130_acc_orient_mbl_theta_show, smi130_acc_orient_mbl_theta_store);
+static DEVICE_ATTR(flat_theta, S_IRUGO | S_IWUSR,
+ smi130_acc_flat_theta_show, smi130_acc_flat_theta_store);
+static DEVICE_ATTR(flat_hold_time, S_IRUGO | S_IWUSR,
+ smi130_acc_flat_hold_time_show, smi130_acc_flat_hold_time_store);
+static DEVICE_ATTR(selftest, S_IRUGO | S_IWUSR,
+ smi130_acc_selftest_show, smi130_acc_selftest_store);
+static DEVICE_ATTR(softreset, S_IWUSR,
+ NULL, smi130_acc_softreset_store);
+static DEVICE_ATTR(enable_timer, S_IRUGO | S_IWUSR,
+ smi130_acc_enable_timer_show, smi130_acc_enable_timer_store);
+static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
+ smi130_acc_debug_level_show, smi130_acc_debug_level_store);
+static DEVICE_ATTR(temperature, S_IRUSR,
+ smi130_acc_temperature_show, NULL);
+static DEVICE_ATTR(place, S_IRUSR,
+ smi130_acc_place_show, NULL);
+static DEVICE_ATTR(driver_version, S_IRUSR,
+ smi130_acc_driver_version_show, NULL);
+
+#ifdef CONFIG_SIG_MOTION
+static DEVICE_ATTR(en_sig_motion, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ smi130_acc_en_sig_motion_show, smi130_acc_en_sig_motion_store);
+#endif
+#ifdef CONFIG_DOUBLE_TAP
+static DEVICE_ATTR(tap_time_period, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ smi130_acc_tap_time_period_show, smi130_acc_tap_time_period_store);
+static DEVICE_ATTR(en_double_tap, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ smi130_acc_en_double_tap_show, smi130_acc_en_double_tap_store);
+#endif
+
+static struct attribute *smi130_acc_attributes[] = {
+ &dev_attr_range.attr,
+ &dev_attr_bandwidth.attr,
+ &dev_attr_op_mode.attr,
+ &dev_attr_value.attr,
+ &dev_attr_value_cache.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_enable.attr,
+ &dev_attr_SleepDur.attr,
+ &dev_attr_reg.attr,
+ &dev_attr_fast_calibration_x.attr,
+ &dev_attr_fast_calibration_y.attr,
+ &dev_attr_fast_calibration_z.attr,
+ &dev_attr_fifo_mode.attr,
+ &dev_attr_fifo_framecount.attr,
+ &dev_attr_fifo_trig.attr,
+ &dev_attr_fifo_trig_src.attr,
+ &dev_attr_fifo_data_sel.attr,
+ &dev_attr_fifo_data_frame.attr,
+ &dev_attr_chip_id.attr,
+ &dev_attr_offset_x.attr,
+ &dev_attr_offset_y.attr,
+ &dev_attr_offset_z.attr,
+ &dev_attr_enable_int.attr,
+ &dev_attr_enable_timer.attr,
+ &dev_attr_debug_level.attr,
+ &dev_attr_int_mode.attr,
+ &dev_attr_slope_duration.attr,
+ &dev_attr_slope_threshold.attr,
+ &dev_attr_slope_no_mot_duration.attr,
+ &dev_attr_slope_no_mot_threshold.attr,
+ &dev_attr_high_g_duration.attr,
+ &dev_attr_high_g_threshold.attr,
+ &dev_attr_low_g_duration.attr,
+ &dev_attr_low_g_threshold.attr,
+ &dev_attr_tap_threshold.attr,
+ &dev_attr_tap_duration.attr,
+ &dev_attr_tap_quiet.attr,
+ &dev_attr_tap_shock.attr,
+ &dev_attr_tap_samp.attr,
+ &dev_attr_orient_mbl_mode.attr,
+ &dev_attr_orient_mbl_blocking.attr,
+ &dev_attr_orient_mbl_hyst.attr,
+ &dev_attr_orient_mbl_theta.attr,
+ &dev_attr_flat_theta.attr,
+ &dev_attr_flat_hold_time.attr,
+ &dev_attr_selftest.attr,
+ &dev_attr_softreset.attr,
+ &dev_attr_temperature.attr,
+ &dev_attr_place.attr,
+ &dev_attr_driver_version.attr,
+#ifdef CONFIG_SIG_MOTION
+ &dev_attr_en_sig_motion.attr,
+#endif
+#ifdef CONFIG_DOUBLE_TAP
+ &dev_attr_en_double_tap.attr,
+#endif
+
+ NULL
+};
+
+static struct attribute_group smi130_acc_attribute_group = {
+ .attrs = smi130_acc_attributes
+};
+
+#ifdef CONFIG_SIG_MOTION
+static struct attribute *smi130_acc_sig_motion_attributes[] = {
+ &dev_attr_slope_duration.attr,
+ &dev_attr_slope_threshold.attr,
+ &dev_attr_en_sig_motion.attr,
+ NULL
+};
+static struct attribute_group smi130_acc_sig_motion_attribute_group = {
+ .attrs = smi130_acc_sig_motion_attributes
+};
+#endif
+
+#ifdef CONFIG_DOUBLE_TAP
+static struct attribute *smi130_acc_double_tap_attributes[] = {
+ &dev_attr_tap_threshold.attr,
+ &dev_attr_tap_duration.attr,
+ &dev_attr_tap_quiet.attr,
+ &dev_attr_tap_shock.attr,
+ &dev_attr_tap_samp.attr,
+ &dev_attr_tap_time_period.attr,
+ &dev_attr_en_double_tap.attr,
+ NULL
+};
+static struct attribute_group smi130_acc_double_tap_attribute_group = {
+ .attrs = smi130_acc_double_tap_attributes
+};
+#endif
+
+
+#if defined(SMI_ACC2X2_ENABLE_INT1) || defined(SMI_ACC2X2_ENABLE_INT2)
+unsigned char *orient_mbl[] = {"upward looking portrait upright",
+ "upward looking portrait upside-down",
+ "upward looking landscape left",
+ "upward looking landscape right",
+ "downward looking portrait upright",
+ "downward looking portrait upside-down",
+ "downward looking landscape left",
+ "downward looking landscape right"};
+
+
+static void smi130_acc_high_g_interrupt_handle(struct smi130_acc_data *smi130_acc)
+{
+ unsigned char first_value = 0;
+ unsigned char sign_value = 0;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ smi130_acc_get_HIGH_first(smi130_acc->smi130_acc_client, i, &first_value);
+ if (first_value == 1) {
+ smi130_acc_get_HIGH_sign(smi130_acc->smi130_acc_client,
+ &sign_value);
+ if (sign_value == 1) {
+ if (i == 0)
+ input_report_rel(smi130_acc->dev_interrupt,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_X_N);
+ if (i == 1)
+ input_report_rel(smi130_acc->dev_interrupt,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_Y_N);
+ if (i == 2)
+ input_report_rel(smi130_acc->dev_interrupt,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_Z_N);
+ } else {
+ if (i == 0)
+ input_report_rel(smi130_acc->dev_interrupt,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_X);
+ if (i == 1)
+ input_report_rel(smi130_acc->dev_interrupt,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_Y);
+ if (i == 2)
+ input_report_rel(smi130_acc->dev_interrupt,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_Z);
+ }
+ }
+
+ PINFO("High G interrupt happened,exis is %d,\n\n"
+ "first is %d,sign is %d\n", i,
+ first_value, sign_value);
+ }
+
+
+}
+
+#ifndef CONFIG_SIG_MOTION
+static void smi130_acc_slope_interrupt_handle(struct smi130_acc_data *smi130_acc)
+{
+ unsigned char first_value = 0;
+ unsigned char sign_value = 0;
+ int i;
+ for (i = 0; i < 3; i++) {
+ smi130_acc_get_slope_first(smi130_acc->smi130_acc_client, i, &first_value);
+ if (first_value == 1) {
+ smi130_acc_get_slope_sign(smi130_acc->smi130_acc_client,
+ &sign_value);
+ if (sign_value == 1) {
+ if (i == 0)
+ input_report_rel(smi130_acc->dev_interrupt,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_X_N);
+ if (i == 1)
+ input_report_rel(smi130_acc->dev_interrupt,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_Y_N);
+ if (i == 2)
+ input_report_rel(smi130_acc->dev_interrupt,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_Z_N);
+ } else {
+ if (i == 0)
+ input_report_rel(smi130_acc->dev_interrupt,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_X);
+ if (i == 1)
+ input_report_rel(smi130_acc->dev_interrupt,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_Y);
+ if (i == 2)
+ input_report_rel(smi130_acc->dev_interrupt,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_Z);
+
+ }
+ }
+
+ PINFO("Slop interrupt happened,exis is %d,\n\n"
+ "first is %d,sign is %d\n", i,
+ first_value, sign_value);
+ }
+}
+#endif
+
+static void smi130_acc_irq_work_func(struct work_struct *work)
+{
+ struct smi130_acc_data *smi130_acc = container_of((struct work_struct *)work,
+ struct smi130_acc_data, irq_work);
+#ifdef CONFIG_DOUBLE_TAP
+ struct i2c_client *client = smi130_acc->smi130_acc_client;
+#endif
+
+ unsigned char status = 0;
+ unsigned char first_value = 0;
+ unsigned char sign_value = 0;
+
+#ifdef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ static struct smi130_accacc acc;
+ struct timespec ts;
+ /*
+ do not use this function judge new data interrupt
+ smi130_acc_get_interruptstatus2(smi130_acc->smi130_acc_client, &status);
+ use the
+ x-axis value bit new_data_x
+ y-axis value bit new_data_y
+ z-axis value bit new_data_z
+ judge if this is the new data
+ */
+ /* PINFO("New data interrupt happened\n");*/
+ smi130_acc_read_accel_xyz(smi130_acc->smi130_acc_client,
+ smi130_acc->sensor_type, &acc);
+ ts = ns_to_timespec(smi130_acc->timestamp);
+ //if ((acc.x & SMI_ACC2X2_NEW_DATA_X__MSK) &&
+ // (acc.y & SMI_ACC2X2_NEW_DATA_Y__MSK) &&
+ // (acc.x & SMI_ACC2X2_NEW_DATA_Z__MSK))
+ {
+ input_event(smi130_acc->input, EV_MSC, MSC_TIME,
+ ts.tv_sec);
+ input_event(smi130_acc->input, EV_MSC, MSC_TIME,
+ ts.tv_nsec);
+ input_event(smi130_acc->input, EV_MSC,
+ MSC_GESTURE, acc.x);
+ input_event(smi130_acc->input, EV_MSC,
+ MSC_RAW, acc.y);
+ input_event(smi130_acc->input, EV_MSC,
+ MSC_SCAN, acc.z);
+ input_sync(smi130_acc->input);
+ mutex_lock(&smi130_acc->value_mutex);
+ smi130_acc->value = acc;
+ mutex_unlock(&smi130_acc->value_mutex);
+ }
+#endif
+
+ smi130_acc_get_interruptstatus1(smi130_acc->smi130_acc_client, &status);
+ PINFO("smi130_acc_irq_work_func, status = 0x%x\n", status);
+
+#ifdef CONFIG_SIG_MOTION
+ if (status & 0x04) {
+ if (atomic_read(&smi130_acc->en_sig_motion) == 1) {
+ PINFO("Significant motion interrupt happened\n");
+ /* close sig sensor,
+ it will be open again if APP wants */
+ smi130_acc_set_en_sig_motion(smi130_acc, 0);
+
+ input_report_rel(smi130_acc->dev_interrupt,
+ SLOP_INTERRUPT, 1);
+ input_sync(smi130_acc->dev_interrupt);
+ }
+ }
+#endif
+
+#ifdef CONFIG_DOUBLE_TAP
+ if (status & 0x20) {
+ if (atomic_read(&smi130_acc->en_double_tap) == 1) {
+ PINFO("single tap interrupt happened\n");
+ smi130_acc_set_Int_Enable(client, 8, 0);
+ if (smi130_acc->tap_times == 0) {
+ mod_timer(&smi130_acc->tap_timer, jiffies +
+ msecs_to_jiffies(smi130_acc->tap_time_period));
+ smi130_acc->tap_times = 1;
+ } else {
+ /* only double tap is judged */
+ PINFO("double tap\n");
+ mutex_lock(&smi130_acc->tap_mutex);
+ smi130_acc->tap_times = 0;
+ del_timer(&smi130_acc->tap_timer);
+ mutex_unlock(&smi130_acc->tap_mutex);
+ input_report_rel(smi130_acc->dev_interrupt,
+ DOUBLE_TAP_INTERRUPT,
+ DOUBLE_TAP_INTERRUPT_HAPPENED);
+ input_sync(smi130_acc->dev_interrupt);
+ }
+ smi130_acc_set_Int_Enable(client, 8, 1);
+ }
+ }
+#endif
+
+ switch (status) {
+
+ case 0x01:
+ PINFO("Low G interrupt happened\n");
+ input_report_rel(smi130_acc->dev_interrupt, LOW_G_INTERRUPT,
+ LOW_G_INTERRUPT_HAPPENED);
+ break;
+
+ case 0x02:
+ smi130_acc_high_g_interrupt_handle(smi130_acc);
+ break;
+
+#ifndef CONFIG_SIG_MOTION
+ case 0x04:
+ smi130_acc_slope_interrupt_handle(smi130_acc);
+ break;
+#endif
+
+ case 0x08:
+ PINFO("slow/ no motion interrupt happened\n");
+ input_report_rel(smi130_acc->dev_interrupt,
+ SLOW_NO_MOTION_INTERRUPT,
+ SLOW_NO_MOTION_INTERRUPT_HAPPENED);
+ break;
+
+#ifndef CONFIG_DOUBLE_TAP
+ case 0x10:
+ PINFO("double tap interrupt happened\n");
+ input_report_rel(smi130_acc->dev_interrupt,
+ DOUBLE_TAP_INTERRUPT,
+ DOUBLE_TAP_INTERRUPT_HAPPENED);
+ break;
+ case 0x20:
+ PINFO("single tap interrupt happened\n");
+ input_report_rel(smi130_acc->dev_interrupt,
+ SINGLE_TAP_INTERRUPT,
+ SINGLE_TAP_INTERRUPT_HAPPENED);
+ break;
+#endif
+
+ case 0x40:
+ smi130_acc_get_orient_mbl_status(smi130_acc->smi130_acc_client,
+ &first_value);
+ PINFO("orient_mbl interrupt happened,%s\n",
+ orient_mbl[first_value]);
+ if (first_value == 0)
+ input_report_abs(smi130_acc->dev_interrupt,
+ ORIENT_INTERRUPT,
+ UPWARD_PORTRAIT_UP_INTERRUPT_HAPPENED);
+ else if (first_value == 1)
+ input_report_abs(smi130_acc->dev_interrupt,
+ ORIENT_INTERRUPT,
+ UPWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED);
+ else if (first_value == 2)
+ input_report_abs(smi130_acc->dev_interrupt,
+ ORIENT_INTERRUPT,
+ UPWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED);
+ else if (first_value == 3)
+ input_report_abs(smi130_acc->dev_interrupt,
+ ORIENT_INTERRUPT,
+ UPWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED);
+ else if (first_value == 4)
+ input_report_abs(smi130_acc->dev_interrupt,
+ ORIENT_INTERRUPT,
+ DOWNWARD_PORTRAIT_UP_INTERRUPT_HAPPENED);
+ else if (first_value == 5)
+ input_report_abs(smi130_acc->dev_interrupt,
+ ORIENT_INTERRUPT,
+ DOWNWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED);
+ else if (first_value == 6)
+ input_report_abs(smi130_acc->dev_interrupt,
+ ORIENT_INTERRUPT,
+ DOWNWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED);
+ else if (first_value == 7)
+ input_report_abs(smi130_acc->dev_interrupt,
+ ORIENT_INTERRUPT,
+ DOWNWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED);
+ break;
+ case 0x80:
+ smi130_acc_get_orient_mbl_flat_status(smi130_acc->smi130_acc_client,
+ &sign_value);
+ PINFO("flat interrupt happened,flat status is %d\n",
+ sign_value);
+ if (sign_value == 1) {
+ input_report_abs(smi130_acc->dev_interrupt,
+ FLAT_INTERRUPT,
+ FLAT_INTERRUPT_TURE_HAPPENED);
+ } else {
+ input_report_abs(smi130_acc->dev_interrupt,
+ FLAT_INTERRUPT,
+ FLAT_INTERRUPT_FALSE_HAPPENED);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static irqreturn_t smi130_acc_irq_handler(int irq, void *handle)
+{
+ struct smi130_acc_data *data = handle;
+
+ if (data == NULL)
+ return IRQ_HANDLED;
+ if (data->smi130_acc_client == NULL)
+ return IRQ_HANDLED;
+ data->timestamp = smi130_acc_get_alarm_timestamp();
+
+ schedule_work(&data->irq_work);
+
+ return IRQ_HANDLED;
+}
+#endif /* defined(SMI_ACC2X2_ENABLE_INT1)||defined(SMI_ACC2X2_ENABLE_INT2) */
+
+
+static int smi130_acc_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct smi130_acc_data *data;
+ struct input_dev *dev;
+ struct bosch_dev *dev_acc;
+#if defined(SMI_ACC2X2_ENABLE_INT1) || defined(SMI_ACC2X2_ENABLE_INT2)
+ struct bosch_sensor_specific *pdata;
+#endif
+ struct input_dev *dev_interrupt;
+
+ PINFO("smi130_acc_probe start\n");
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ PERR("i2c_check_functionality error\n");
+ err = -EIO;
+ goto exit;
+ }
+ data = kzalloc(sizeof(struct smi130_acc_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* read and check chip id */
+ if (smi130_acc_check_chip_id(client, data) < 0) {
+ err = -EINVAL;
+ goto kfree_exit;
+ }
+
+ /* do soft reset */
+ smi130_acc_delay(5);
+ if (smi130_acc_soft_reset(client) < 0) {
+ PERR("i2c bus write error, pls check HW connection\n");
+ err = -EINVAL;
+ goto kfree_exit;
+ }
+ smi130_acc_delay(20);
+
+ i2c_set_clientdata(client, data);
+ data->smi130_acc_client = client;
+ mutex_init(&data->value_mutex);
+ mutex_init(&data->mode_mutex);
+ mutex_init(&data->enable_mutex);
+ smi130_acc_set_bandwidth(client, SMI_ACC2X2_BW_SET);
+ smi130_acc_set_range(client, SMI_ACC2X2_RANGE_SET);
+
+#if defined(SMI_ACC2X2_ENABLE_INT1) || defined(SMI_ACC2X2_ENABLE_INT2)
+
+ pdata = client->dev.platform_data;
+ if (pdata) {
+ if (pdata->irq_gpio_cfg && (pdata->irq_gpio_cfg() < 0)) {
+ PERR("IRQ GPIO conf. error %d\n",
+ client->irq);
+ }
+ }
+
+#ifdef SMI_ACC2X2_ENABLE_INT1
+ /* maps interrupt to INT1 pin */
+ smi130_acc_set_int1_pad_sel(client, PAD_LOWG);
+ smi130_acc_set_int1_pad_sel(client, PAD_HIGHG);
+ smi130_acc_set_int1_pad_sel(client, PAD_SLOP);
+ smi130_acc_set_int1_pad_sel(client, PAD_DOUBLE_TAP);
+ smi130_acc_set_int1_pad_sel(client, PAD_SINGLE_TAP);
+ smi130_acc_set_int1_pad_sel(client, PAD_ORIENT);
+ smi130_acc_set_int1_pad_sel(client, PAD_FLAT);
+ smi130_acc_set_int1_pad_sel(client, PAD_SLOW_NO_MOTION);
+#ifdef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ smi130_acc_set_newdata(client, SMI_ACC2X2_INT1_NDATA, 1);
+ smi130_acc_set_newdata(client, SMI_ACC2X2_INT2_NDATA, 0);
+#endif
+#endif
+
+#ifdef SMI_ACC2X2_ENABLE_INT2
+ /* maps interrupt to INT2 pin */
+ smi130_acc_set_int2_pad_sel(client, PAD_LOWG);
+ smi130_acc_set_int2_pad_sel(client, PAD_HIGHG);
+ smi130_acc_set_int2_pad_sel(client, PAD_SLOP);
+ smi130_acc_set_int2_pad_sel(client, PAD_DOUBLE_TAP);
+ smi130_acc_set_int2_pad_sel(client, PAD_SINGLE_TAP);
+ smi130_acc_set_int2_pad_sel(client, PAD_ORIENT);
+ smi130_acc_set_int2_pad_sel(client, PAD_FLAT);
+ smi130_acc_set_int2_pad_sel(client, PAD_SLOW_NO_MOTION);
+#ifdef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ smi130_acc_set_newdata(client, SMI_ACC2X2_INT1_NDATA, 0);
+ smi130_acc_set_newdata(client, SMI_ACC2X2_INT2_NDATA, 1);
+#endif
+#endif
+
+ smi130_acc_set_Int_Mode(client, 1);/*latch interrupt 250ms*/
+
+ /* do not open any interrupt here */
+ /*10,orient_mbl
+ 11,flat*/
+ /* smi130_acc_set_Int_Enable(client, 10, 1); */
+ /* smi130_acc_set_Int_Enable(client, 11, 1); */
+
+#ifdef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ /* enable new data interrupt */
+ smi130_acc_set_Int_Enable(client, 4, 1);
+#endif
+
+#ifdef CONFIG_SIG_MOTION
+ enable_irq_wake(data->IRQ);
+#endif
+ if (err)
+ PERR("could not request irq\n");
+
+ INIT_WORK(&data->irq_work, smi130_acc_irq_work_func);
+#endif
+
+#ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ INIT_DELAYED_WORK(&data->work, smi130_acc_work_func);
+#endif
+ atomic_set(&data->delay, SMI_ACC2X2_MAX_DELAY);
+ atomic_set(&data->enable, 0);
+
+ dev = input_allocate_device();
+ if (!dev)
+ return -ENOMEM;
+
+ dev_interrupt = input_allocate_device();
+ if (!dev_interrupt) {
+ kfree(data);
+ input_free_device(dev); /*free the successful dev and return*/
+ return -ENOMEM;
+ }
+
+ /* only value events reported */
+ dev->name = SENSOR_NAME;
+ dev->id.bustype = BUS_I2C;
+ input_set_capability(dev, EV_ABS, ABS_MISC);
+ input_set_abs_params(dev, ABS_X, ABSMIN, ABSMAX, 0, 0);
+ input_set_abs_params(dev, ABS_Y, ABSMIN, ABSMAX, 0, 0);
+ input_set_abs_params(dev, ABS_Z, ABSMIN, ABSMAX, 0, 0);
+ input_set_capability(dev, EV_MSC, MSC_GESTURE);
+ input_set_capability(dev, EV_MSC, MSC_RAW);
+ input_set_capability(dev, EV_MSC, MSC_SCAN);
+ input_set_capability(dev, EV_MSC, MSC_TIME);
+ input_set_drvdata(dev, data);
+ err = input_register_device(dev);
+ if (err < 0)
+ goto err_register_input_device;
+
+ /* all interrupt generated events are moved to interrupt input devices*/
+ dev_interrupt->name = "smi_acc_interrupt";
+ dev_interrupt->id.bustype = BUS_I2C;
+ input_set_capability(dev_interrupt, EV_REL,
+ SLOW_NO_MOTION_INTERRUPT);
+ input_set_capability(dev_interrupt, EV_REL,
+ LOW_G_INTERRUPT);
+ input_set_capability(dev_interrupt, EV_REL,
+ HIGH_G_INTERRUPT);
+ input_set_capability(dev_interrupt, EV_REL,
+ SLOP_INTERRUPT);
+ input_set_capability(dev_interrupt, EV_REL,
+ DOUBLE_TAP_INTERRUPT);
+ input_set_capability(dev_interrupt, EV_REL,
+ SINGLE_TAP_INTERRUPT);
+ input_set_capability(dev_interrupt, EV_ABS,
+ ORIENT_INTERRUPT);
+ input_set_capability(dev_interrupt, EV_ABS,
+ FLAT_INTERRUPT);
+ input_set_drvdata(dev_interrupt, data);
+
+ err = input_register_device(dev_interrupt);
+ if (err < 0)
+ goto err_register_input_device_interrupt;
+
+ data->dev_interrupt = dev_interrupt;
+ data->input = dev;
+
+#ifdef CONFIG_SIG_MOTION
+ data->g_sensor_class = class_create(THIS_MODULE, "sig_sensor");
+ if (IS_ERR(data->g_sensor_class)) {
+ err = PTR_ERR(data->g_sensor_class);
+ data->g_sensor_class = NULL;
+ PERR("could not allocate g_sensor_class\n");
+ goto err_create_class;
+ }
+
+ data->g_sensor_dev = device_create(data->g_sensor_class,
+ NULL, 0, "%s", "g_sensor");
+ if (unlikely(IS_ERR(data->g_sensor_dev))) {
+ err = PTR_ERR(data->g_sensor_dev);
+ data->g_sensor_dev = NULL;
+
+ PERR("could not allocate g_sensor_dev\n");
+ goto err_create_g_sensor_device;
+ }
+
+ dev_set_drvdata(data->g_sensor_dev, data);
+
+ err = sysfs_create_group(&data->g_sensor_dev->kobj,
+ &smi130_acc_sig_motion_attribute_group);
+ if (err < 0)
+ goto error_sysfs;
+#endif
+
+#ifdef CONFIG_DOUBLE_TAP
+ data->g_sensor_class_doubletap =
+ class_create(THIS_MODULE, "dtap_sensor");
+ if (IS_ERR(data->g_sensor_class_doubletap)) {
+ err = PTR_ERR(data->g_sensor_class_doubletap);
+ data->g_sensor_class_doubletap = NULL;
+ PERR("could not allocate g_sensor_class_doubletap\n");
+ goto err_create_class;
+ }
+
+ data->g_sensor_dev_doubletap = device_create(
+ data->g_sensor_class_doubletap,
+ NULL, 0, "%s", "g_sensor");
+ if (unlikely(IS_ERR(data->g_sensor_dev_doubletap))) {
+ err = PTR_ERR(data->g_sensor_dev_doubletap);
+ data->g_sensor_dev_doubletap = NULL;
+
+ PERR("could not allocate g_sensor_dev_doubletap\n");
+ goto err_create_g_sensor_device_double_tap;
+ }
+
+ dev_set_drvdata(data->g_sensor_dev_doubletap, data);
+
+ err = sysfs_create_group(&data->g_sensor_dev_doubletap->kobj,
+ &smi130_acc_double_tap_attribute_group);
+ if (err < 0)
+ goto error_sysfs;
+#endif
+
+ err = sysfs_create_group(&data->input->dev.kobj,
+ &smi130_acc_attribute_group);
+ if (err < 0)
+ goto error_sysfs;
+
+ dev_acc = bosch_allocate_device();
+ if (!dev_acc) {
+ err = -ENOMEM;
+ goto error_sysfs;
+ }
+ dev_acc->name = ACC_NAME;
+
+ bosch_set_drvdata(dev_acc, data);
+
+ err = bosch_register_device(dev_acc);
+ if (err < 0)
+ goto bosch_free_acc_exit;
+
+ data->bosch_acc = dev_acc;
+ err = sysfs_create_group(&data->bosch_acc->dev.kobj,
+ &smi130_acc_attribute_group);
+
+ if (err < 0)
+ goto bosch_free_exit;
+
+ if (NULL != client->dev.platform_data) {
+ data->bosch_pd = kzalloc(sizeof(*data->bosch_pd),
+ GFP_KERNEL);
+
+ if (NULL != data->bosch_pd) {
+ memcpy(data->bosch_pd, client->dev.platform_data,
+ sizeof(*data->bosch_pd));
+ PINFO("%s sensor driver set place: p%d",
+ data->bosch_pd->name, data->bosch_pd->place);
+ }
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ data->early_suspend.suspend = smi130_acc_early_suspend;
+ data->early_suspend.resume = smi130_acc_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+ INIT_WORK(&data->report_data_work,
+ smi130_acc_timer_work_fun);
+ reportdata_wq = create_singlethread_workqueue("smi130_acc_wq");
+ if (NULL == reportdata_wq)
+ PERR("fail to create the reportdta_wq");
+ hrtimer_init(&data->timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ data->timer.function = reportdata_timer_fun;
+ data->work_delay_kt = ns_to_ktime(4000000);
+ data->is_timer_running = 0;
+ data->timestamp = 0;
+ data->time_odr = 4000000;/*default bandwidth 125HZ*/
+ data->smi_acc_mode_enabled = 0;
+ data->fifo_datasel = 0;
+ data->fifo_count = 0;
+ data->acc_count = 0;
+
+#ifdef CONFIG_SIG_MOTION
+ atomic_set(&data->en_sig_motion, 0);
+#endif
+#ifdef CONFIG_DOUBLE_TAP
+ atomic_set(&data->en_double_tap, 0);
+ data->tap_times = 0;
+ data->tap_time_period = DEFAULT_TAP_JUDGE_PERIOD;
+ mutex_init(&data->tap_mutex);
+ setup_timer(&data->tap_timer, smi130_acc_tap_timeout_handle,
+ (unsigned long)data);
+#endif
+ if (smi130_acc_set_mode(client, SMI_ACC2X2_MODE_SUSPEND, SMI_ACC_ENABLED_ALL) < 0)
+ return -EINVAL;
+ data->IRQ = client->irq;
+ PDEBUG("data->IRQ = %d", data->IRQ);
+ err = request_irq(data->IRQ, smi130_acc_irq_handler, IRQF_TRIGGER_RISING,
+ "smi130_acc", data);
+ PINFO("SMI130_ACC driver probe successfully");
+
+ return 0;
+
+bosch_free_exit:
+ bosch_unregister_device(dev_acc);
+
+bosch_free_acc_exit:
+ bosch_free_device(dev_acc);
+
+error_sysfs:
+ input_unregister_device(data->input);
+
+#ifdef CONFIG_DOUBLE_TAP
+err_create_g_sensor_device_double_tap:
+ class_destroy(data->g_sensor_class_doubletap);
+#endif
+
+#ifdef CONFIG_SIG_MOTION
+err_create_g_sensor_device:
+ class_destroy(data->g_sensor_class);
+#endif
+
+#if defined(CONFIG_SIG_MOTION) || defined(CONFIG_DOUBLE_TAP)
+err_create_class:
+ input_unregister_device(data->dev_interrupt);
+#endif
+
+err_register_input_device_interrupt:
+ input_free_device(dev_interrupt);
+ input_unregister_device(data->input);
+
+err_register_input_device:
+ input_free_device(dev);
+
+kfree_exit:
+ if ((NULL != data) && (NULL != data->bosch_pd)) {
+ kfree(data->bosch_pd);
+ data->bosch_pd = NULL;
+ }
+ kfree(data);
+exit:
+ return err;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void smi130_acc_early_suspend(struct early_suspend *h)
+{
+ struct smi130_acc_data *data =
+ container_of(h, struct smi130_acc_data, early_suspend);
+
+ mutex_lock(&data->enable_mutex);
+ if (atomic_read(&data->enable) == 1) {
+ smi130_acc_set_mode(data->smi130_acc_client,
+ SMI_ACC2X2_MODE_SUSPEND, SMI_ACC_ENABLED_INPUT);
+#ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ cancel_delayed_work_sync(&data->work);
+#endif
+ }
+ if (data->is_timer_running) {
+ /*diable fifo_mode when close timer*/
+ if (smi130_acc_set_fifo_mode(data->smi130_acc_client, 0) < 0)
+ PERR("set fifo_mode falied");
+ hrtimer_cancel(&data->timer);
+ data->base_time = 0;
+ data->timestamp = 0;
+ data->fifo_time = 0;
+ data->acc_count = 0;
+ }
+ mutex_unlock(&data->enable_mutex);
+}
+
+static void smi130_acc_late_resume(struct early_suspend *h)
+{
+ struct smi130_acc_data *data =
+ container_of(h, struct smi130_acc_data, early_suspend);
+ if (NULL == data)
+ return;
+
+ mutex_lock(&data->enable_mutex);
+ if (atomic_read(&data->enable) == 1) {
+ smi130_acc_set_mode(data->smi130_acc_client,
+ SMI_ACC2X2_MODE_NORMAL, SMI_ACC_ENABLED_INPUT);
+#ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ schedule_delayed_work(&data->work,
+ msecs_to_jiffies(atomic_read(&data->delay)));
+#endif
+ }
+ if (data->is_timer_running) {
+ hrtimer_start(&data->timer,
+ ns_to_ktime(data->time_odr),
+ HRTIMER_MODE_REL);
+ /*enable fifo_mode when init*/
+ if (smi130_acc_set_fifo_mode(data->smi130_acc_client, 2) < 0)
+ PERR("set fifo_mode falied");
+ data->base_time = 0;
+ data->timestamp = 0;
+ data->is_timer_running = 1;
+ data->acc_count = 0;
+ }
+ mutex_unlock(&data->enable_mutex);
+}
+#endif
+
+static int smi130_acc_remove(struct i2c_client *client)
+{
+ struct smi130_acc_data *data = i2c_get_clientdata(client);
+
+ if (NULL == data)
+ return 0;
+
+ smi130_acc_set_enable(&client->dev, 0);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&data->early_suspend);
+#endif
+ sysfs_remove_group(&data->input->dev.kobj, &smi130_acc_attribute_group);
+ input_unregister_device(data->input);
+
+ if (NULL != data->bosch_pd) {
+ kfree(data->bosch_pd);
+ data->bosch_pd = NULL;
+ }
+
+ kfree(data);
+ return 0;
+}
+
+void smi130_acc_shutdown(struct i2c_client *client)
+{
+ struct smi130_acc_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->enable_mutex);
+ smi130_acc_set_mode(data->smi130_acc_client,
+ SMI_ACC2X2_MODE_DEEP_SUSPEND, SMI_ACC_ENABLED_ALL);
+ mutex_unlock(&data->enable_mutex);
+}
+
+#ifdef CONFIG_PM
+static int smi130_acc_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ struct smi130_acc_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->enable_mutex);
+ if (atomic_read(&data->enable) == 1) {
+ smi130_acc_set_mode(data->smi130_acc_client,
+ SMI_ACC2X2_MODE_SUSPEND, SMI_ACC_ENABLED_INPUT);
+#ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ cancel_delayed_work_sync(&data->work);
+#endif
+ }
+ if (data->is_timer_running) {
+ hrtimer_cancel(&data->timer);
+ data->base_time = 0;
+ data->timestamp = 0;
+ data->fifo_time = 0;
+ data->acc_count = 0;
+ }
+ mutex_unlock(&data->enable_mutex);
+
+ return 0;
+}
+
+static int smi130_acc_resume(struct i2c_client *client)
+{
+ struct smi130_acc_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->enable_mutex);
+ if (atomic_read(&data->enable) == 1) {
+ smi130_acc_set_mode(data->smi130_acc_client,
+ SMI_ACC2X2_MODE_NORMAL, SMI_ACC_ENABLED_INPUT);
+#ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
+ schedule_delayed_work(&data->work,
+ msecs_to_jiffies(atomic_read(&data->delay)));
+#endif
+ }
+ if (data->is_timer_running) {
+ hrtimer_start(&data->timer,
+ ns_to_ktime(data->time_odr),
+ HRTIMER_MODE_REL);
+ data->base_time = 0;
+ data->timestamp = 0;
+ data->is_timer_running = 1;
+ }
+ mutex_unlock(&data->enable_mutex);
+
+ return 0;
+}
+
+#else
+
+#define smi130_acc_suspend NULL
+#define smi130_acc_resume NULL
+
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id smi130_acc_id[] = {
+ { SENSOR_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, smi130_acc_id);
+static const struct of_device_id smi130_acc_of_match[] = {
+ { .compatible = "smi130_acc", },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, smi130_acc_of_match);
+
+static struct i2c_driver smi130_acc_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+ .of_match_table = smi130_acc_of_match,
+ },
+ //.suspend = smi130_acc_suspend,
+ //.resume = smi130_acc_resume,
+ .id_table = smi130_acc_id,
+ .probe = smi130_acc_probe,
+ .remove = smi130_acc_remove,
+ .shutdown = smi130_acc_shutdown,
+};
+
+static int __init SMI_ACC2X2_init(void)
+{
+ return i2c_add_driver(&smi130_acc_driver);
+}
+
+static void __exit SMI_ACC2X2_exit(void)
+{
+ i2c_del_driver(&smi130_acc_driver);
+}
+
+MODULE_AUTHOR("contact@bosch-sensortec.com");
+MODULE_DESCRIPTION("SMI_ACC2X2 ACCELEROMETER SENSOR DRIVER");
+MODULE_LICENSE("GPL v2");
+
+module_init(SMI_ACC2X2_init);
+module_exit(SMI_ACC2X2_exit);
+
diff --git a/drivers/input/sensors/smi130/smi130_driver.c b/drivers/input/sensors/smi130/smi130_driver.c
new file mode 100644
index 000000000000..42a0a5717ef0
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130_driver.c
@@ -0,0 +1,4121 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename smi130_driver.c
+ * @date 2016/08/01 14:40
+ * @Modification Date 2018/08/28 18:20
+ * @id "b5ff23a"
+ * @version 1.3
+ *
+ * @brief
+ * The core code of SMI130 device driver
+ *
+ * @detail
+ * This file implements the core code of SMI130 device driver,
+ * which includes hardware related functions, input device register,
+ * device attribute files, etc.
+*/
+
+#include "smi130.h"
+#include "smi130_driver.h"
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+
+
+#define DRIVER_VERSION "0.0.53.0"
+#define I2C_BURST_READ_MAX_LEN (256)
+#define SMI130_STORE_COUNT (6000)
+#define LMADA (1)
+uint64_t g_current_apts_us_mbl;
+
+
+enum SMI_SENSOR_INT_T {
+ /* Interrupt enable0*/
+ SMI_ANYMO_X_INT = 0,
+ SMI_ANYMO_Y_INT,
+ SMI_ANYMO_Z_INT,
+ SMI_D_TAP_INT,
+ SMI_S_TAP_INT,
+ SMI_ORIENT_INT,
+ SMI_FLAT_INT,
+ /* Interrupt enable1*/
+ SMI_HIGH_X_INT,
+ SMI_HIGH_Y_INT,
+ SMI_HIGH_Z_INT,
+ SMI_LOW_INT,
+ SMI_DRDY_INT,
+ SMI_FFULL_INT,
+ SMI_FWM_INT,
+ /* Interrupt enable2 */
+ SMI_NOMOTION_X_INT,
+ SMI_NOMOTION_Y_INT,
+ SMI_NOMOTION_Z_INT,
+ SMI_STEP_DETECTOR_INT,
+ INT_TYPE_MAX
+};
+
+/*smi fifo sensor type combination*/
+enum SMI_SENSOR_FIFO_COMBINATION {
+ SMI_FIFO_A = 0,
+ SMI_FIFO_G,
+ SMI_FIFO_M,
+ SMI_FIFO_G_A,
+ SMI_FIFO_M_A,
+ SMI_FIFO_M_G,
+ SMI_FIFO_M_G_A,
+ SMI_FIFO_COM_MAX
+};
+
+/*smi fifo analyse return err status*/
+enum SMI_FIFO_ANALYSE_RETURN_T {
+ FIFO_OVER_READ_RETURN = -10,
+ FIFO_SENSORTIME_RETURN = -9,
+ FIFO_SKIP_OVER_LEN = -8,
+ FIFO_M_G_A_OVER_LEN = -7,
+ FIFO_M_G_OVER_LEN = -6,
+ FIFO_M_A_OVER_LEN = -5,
+ FIFO_G_A_OVER_LEN = -4,
+ FIFO_M_OVER_LEN = -3,
+ FIFO_G_OVER_LEN = -2,
+ FIFO_A_OVER_LEN = -1
+};
+
+/*!smi sensor generic power mode enum */
+enum SMI_DEV_OP_MODE {
+ SENSOR_PM_NORMAL = 0,
+ SENSOR_PM_LP1,
+ SENSOR_PM_SUSPEND,
+ SENSOR_PM_LP2
+};
+
+/*! smi acc sensor power mode enum */
+enum SMI_ACC_PM_TYPE {
+ SMI_ACC_PM_NORMAL = 0,
+ SMI_ACC_PM_LP1,
+ SMI_ACC_PM_SUSPEND,
+ SMI_ACC_PM_LP2,
+ SMI_ACC_PM_MAX
+};
+
+/*! smi gyro sensor power mode enum */
+enum SMI_GYRO_PM_TYPE {
+ SMI_GYRO_PM_NORMAL = 0,
+ SMI_GYRO_PM_FAST_START,
+ SMI_GYRO_PM_SUSPEND,
+ SMI_GYRO_PM_MAX
+};
+
+/*! smi mag sensor power mode enum */
+enum SMI_MAG_PM_TYPE {
+ SMI_MAG_PM_NORMAL = 0,
+ SMI_MAG_PM_LP1,
+ SMI_MAG_PM_SUSPEND,
+ SMI_MAG_PM_LP2,
+ SMI_MAG_PM_MAX
+};
+
+
+/*! smi sensor support type*/
+enum SMI_SENSOR_TYPE {
+ SMI_ACC_SENSOR,
+ SMI_GYRO_SENSOR,
+ SMI_MAG_SENSOR,
+ SMI_SENSOR_TYPE_MAX
+};
+
+/*!smi sensor generic power mode enum */
+enum SMI_AXIS_TYPE {
+ X_AXIS = 0,
+ Y_AXIS,
+ Z_AXIS,
+ AXIS_MAX
+};
+
+/*!smi sensor generic intterrupt enum */
+enum SMI_INT_TYPE {
+ SMI130_INT0 = 0,
+ SMI130_INT1,
+ SMI130_INT_MAX
+};
+
+/*! smi sensor time resolution definition*/
+enum SMI_SENSOR_TIME_RS_TYPE {
+ TS_0_78_HZ = 1,/*0.78HZ*/
+ TS_1_56_HZ,/*1.56HZ*/
+ TS_3_125_HZ,/*3.125HZ*/
+ TS_6_25_HZ,/*6.25HZ*/
+ TS_12_5_HZ,/*12.5HZ*/
+ TS_25_HZ,/*25HZ, odr=6*/
+ TS_50_HZ,/*50HZ*/
+ TS_100_HZ,/*100HZ*/
+ TS_200_HZ,/*200HZ*/
+ TS_400_HZ,/*400HZ*/
+ TS_800_HZ,/*800HZ*/
+ TS_1600_HZ,/*1600HZ*/
+ TS_MAX_HZ
+};
+
+/*! smi sensor interface mode */
+enum SMI_SENSOR_IF_MODE_TYPE {
+ /*primary interface:autoconfig/secondary interface off*/
+ P_AUTO_S_OFF = 0,
+ /*primary interface:I2C/secondary interface:OIS*/
+ P_I2C_S_OIS,
+ /*primary interface:autoconfig/secondary interface:Magnetometer*/
+ P_AUTO_S_MAG,
+ /*interface mode reseved*/
+ IF_MODE_RESEVED
+
+};
+
+/*! smi130 acc/gyro calibration status in H/W layer */
+enum SMI_CALIBRATION_STATUS_TYPE {
+ /*SMI FAST Calibration ready x/y/z status*/
+ SMI_ACC_X_FAST_CALI_RDY = 0,
+ SMI_ACC_Y_FAST_CALI_RDY,
+ SMI_ACC_Z_FAST_CALI_RDY
+};
+
+unsigned int reg_op_addr_mbl;
+
+static const int smi_pmu_cmd_acc_arr[SMI_ACC_PM_MAX] = {
+ /*!smi pmu for acc normal, low power1,
+ * suspend, low power2 mode command */
+ CMD_PMU_ACC_NORMAL,
+ CMD_PMU_ACC_LP1,
+ CMD_PMU_ACC_SUSPEND,
+ CMD_PMU_ACC_LP2
+};
+
+static const int smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_MAX] = {
+ /*!smi pmu for gyro normal, fast startup,
+ * suspend mode command */
+ CMD_PMU_GYRO_NORMAL,
+ CMD_PMU_GYRO_FASTSTART,
+ CMD_PMU_GYRO_SUSPEND
+};
+
+static const int smi_pmu_cmd_mag_arr[SMI_MAG_PM_MAX] = {
+ /*!smi pmu for mag normal, low power1,
+ * suspend, low power2 mode command */
+ CMD_PMU_MAG_NORMAL,
+ CMD_PMU_MAG_LP1,
+ CMD_PMU_MAG_SUSPEND,
+ CMD_PMU_MAG_LP2
+};
+
+static const char *smi_axis_name[AXIS_MAX] = {"x", "y", "z"};
+
+static const int smi_interrupt_type[] = {
+ /*!smi interrupt type */
+ /* Interrupt enable0 , index=0~6*/
+ SMI130_ANY_MOTION_X_ENABLE,
+ SMI130_ANY_MOTION_Y_ENABLE,
+ SMI130_ANY_MOTION_Z_ENABLE,
+ SMI130_DOUBLE_TAP_ENABLE,
+ SMI130_SINGLE_TAP_ENABLE,
+ SMI130_ORIENT_ENABLE,
+ SMI130_FLAT_ENABLE,
+ /* Interrupt enable1, index=7~13*/
+ SMI130_HIGH_G_X_ENABLE,
+ SMI130_HIGH_G_Y_ENABLE,
+ SMI130_HIGH_G_Z_ENABLE,
+ SMI130_LOW_G_ENABLE,
+ SMI130_DATA_RDY_ENABLE,
+ SMI130_FIFO_FULL_ENABLE,
+ SMI130_FIFO_WM_ENABLE,
+ /* Interrupt enable2, index = 14~17*/
+ SMI130_NOMOTION_X_ENABLE,
+ SMI130_NOMOTION_Y_ENABLE,
+ SMI130_NOMOTION_Z_ENABLE,
+ SMI130_STEP_DETECTOR_EN
+};
+
+/*! smi sensor time depend on ODR*/
+struct smi_sensor_time_odr_tbl {
+ u32 ts_duration_lsb;
+ u32 ts_duration_us;
+ u32 ts_delat;/*sub current delat fifo_time*/
+};
+
+struct smi130_axis_data_t {
+ s16 x;
+ s16 y;
+ s16 z;
+};
+
+struct smi130_type_mapping_type {
+
+ /*! smi16x sensor chip id */
+ uint16_t chip_id;
+
+ /*! smi16x chip revision code */
+ uint16_t revision_id;
+
+ /*! smi130_acc sensor name */
+ const char *sensor_name;
+};
+
+struct smi130_store_info_t {
+ uint8_t current_frm_cnt;
+ uint64_t current_apts_us[2];
+ uint8_t fifo_ts_total_frmcnt;
+ uint64_t fifo_time;
+};
+
+uint64_t get_current_timestamp_mbl(void)
+{
+ uint64_t ts_ap;
+ struct timespec tmp_time;
+ get_monotonic_boottime(&tmp_time);
+ ts_ap = (uint64_t)tmp_time.tv_sec * 1000000000 + tmp_time.tv_nsec;
+ return ts_ap;
+
+}
+
+/*! sensor support type map */
+static const struct smi130_type_mapping_type sensor_type_map[] = {
+
+ {SENSOR_CHIP_ID_SMI, SENSOR_CHIP_REV_ID_SMI, "SMI130/162AB"},
+ {SENSOR_CHIP_ID_SMI_C2, SENSOR_CHIP_REV_ID_SMI, "SMI130C2"},
+ {SENSOR_CHIP_ID_SMI_C3, SENSOR_CHIP_REV_ID_SMI, "SMI130C3"},
+
+};
+
+/*!smi130 sensor time depends on ODR */
+static const struct smi_sensor_time_odr_tbl
+ sensortime_duration_tbl[TS_MAX_HZ] = {
+ {0x010000, 2560000, 0x00ffff},/*2560ms, 0.39hz, odr=resver*/
+ {0x008000, 1280000, 0x007fff},/*1280ms, 0.78hz, odr_acc=1*/
+ {0x004000, 640000, 0x003fff},/*640ms, 1.56hz, odr_acc=2*/
+ {0x002000, 320000, 0x001fff},/*320ms, 3.125hz, odr_acc=3*/
+ {0x001000, 160000, 0x000fff},/*160ms, 6.25hz, odr_acc=4*/
+ {0x000800, 80000, 0x0007ff},/*80ms, 12.5hz*/
+ {0x000400, 40000, 0x0003ff},/*40ms, 25hz, odr_acc = odr_gyro =6*/
+ {0x000200, 20000, 0x0001ff},/*20ms, 50hz, odr = 7*/
+ {0x000100, 10000, 0x0000ff},/*10ms, 100hz, odr=8*/
+ {0x000080, 5000, 0x00007f},/*5ms, 200hz, odr=9*/
+ {0x000040, 2500, 0x00003f},/*2.5ms, 400hz, odr=10*/
+ {0x000020, 1250, 0x00001f},/*1.25ms, 800hz, odr=11*/
+ {0x000010, 625, 0x00000f},/*0.625ms, 1600hz, odr=12*/
+
+};
+
+#if defined(CONFIG_USE_QUALCOMM_HAL)
+#define POLL_INTERVAL_MIN_MS 10
+#define POLL_INTERVAL_MAX_MS 4000
+#define POLL_DEFAULT_INTERVAL_MS 200
+#define SMI130_ACCEL_MIN_VALUE -32768
+#define SMI130_ACCEL_MAX_VALUE 32767
+#define SMI130_GYRO_MIN_VALUE -32768
+#define SMI130_GYRO_MAX_VALUE 32767
+#define SMI130_ACCEL_DEFAULT_POLL_INTERVAL_MS 200
+#define SMI130_GYRO_DEFAULT_POLL_INTERVAL_MS 200
+#define SMI130_ACCEL_MIN_POLL_INTERVAL_MS 10
+#define SMI130_ACCEL_MAX_POLL_INTERVAL_MS 5000
+#define SMI130_GYRO_MIN_POLL_INTERVAL_MS 10
+#define SMI130_GYRO_MAX_POLL_INTERVAL_MS 5000
+static struct sensors_classdev smi130_accel_cdev = {
+ .name = "smi130-accel",
+ .vendor = "bosch",
+ .version = 1,
+ .handle = SENSORS_ACCELERATION_HANDLE,
+ .type = SENSOR_TYPE_ACCELEROMETER,
+ .max_range = "156.8", /* 16g */
+ .resolution = "0.153125", /* 15.6mg */
+ .sensor_power = "0.13", /* typical value */
+ .min_delay = POLL_INTERVAL_MIN_MS * 1000, /* in microseconds */
+ .max_delay = POLL_INTERVAL_MAX_MS,
+ .delay_msec = POLL_DEFAULT_INTERVAL_MS, /* in millisecond */
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+ .enabled = 0,
+ .max_latency = 0,
+ .flags = 0,
+ .sensors_enable = NULL,
+ .sensors_poll_delay = NULL,
+ .sensors_set_latency = NULL,
+ .sensors_flush = NULL,
+ .sensors_self_test = NULL,
+};
+static struct sensors_classdev smi130_gyro_cdev = {
+ .name = "smi130-gyro",
+ .vendor = "bosch",
+ .version = 1,
+ .handle = SENSORS_GYROSCOPE_HANDLE,
+ .type = SENSOR_TYPE_GYROSCOPE,
+ .max_range = "34.906586", /* rad/s */
+ .resolution = "0.0010681152", /* rad/s */
+ .sensor_power = "3.6", /* 3.6 mA */
+ .min_delay = SMI130_GYRO_MIN_POLL_INTERVAL_MS * 1000,
+ .max_delay = SMI130_GYRO_MAX_POLL_INTERVAL_MS,
+ .delay_msec = SMI130_GYRO_DEFAULT_POLL_INTERVAL_MS,
+ .fifo_reserved_event_count = 0,
+ .fifo_max_event_count = 0,
+ .enabled = 0,
+ .max_latency = 0,
+ .flags = 0, /* SENSOR_FLAG_CONTINUOUS_MODE */
+ .sensors_enable = NULL,
+ .sensors_poll_delay = NULL,
+ .sensors_enable_wakeup = NULL,
+ .sensors_set_latency = NULL,
+ .sensors_flush = NULL,
+};
+#endif
+static void smi_delay(u32 msec)
+{
+ if (msec <= 20)
+ usleep_range(msec * 1000, msec * 1000);
+ else
+ msleep(msec);
+}
+
+static void smi_dump_reg(struct smi_client_data *client_data)
+{
+ #define REG_MAX0 0x24
+ #define REG_MAX1 0x56
+ int i;
+ u8 dbg_buf0[REG_MAX0];
+ u8 dbg_buf1[REG_MAX1];
+ u8 dbg_buf_str0[REG_MAX0 * 3 + 1] = "";
+ u8 dbg_buf_str1[REG_MAX1 * 3 + 1] = "";
+
+ dev_notice(client_data->dev, "\nFrom 0x00:\n");
+
+ client_data->device.bus_read(client_data->device.dev_addr,
+ SMI_REG_NAME(USER_CHIP_ID), dbg_buf0, REG_MAX0);
+ for (i = 0; i < REG_MAX0; i++) {
+ snprintf(dbg_buf_str0 + i * 3, 16, "%02x%c", dbg_buf0[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ dev_notice(client_data->dev, "%s\n", dbg_buf_str0);
+
+ client_data->device.bus_read(client_data->device.dev_addr,
+ SMI130_USER_ACCEL_CONFIG_ADDR, dbg_buf1, REG_MAX1);
+ dev_notice(client_data->dev, "\nFrom 0x40:\n");
+ for (i = 0; i < REG_MAX1; i++) {
+ snprintf(dbg_buf_str1 + i * 3, 16, "%02x%c", dbg_buf1[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ dev_notice(client_data->dev, "\n%s\n", dbg_buf_str1);
+ }
+
+
+void smi_fifo_frame_bytes_extend_calc(
+ struct smi_client_data *client_data,
+ unsigned int *fifo_frmbytes_extend)
+{
+
+ switch (client_data->fifo_data_sel) {
+ case SMI_FIFO_A_SEL:
+ case SMI_FIFO_G_SEL:
+ *fifo_frmbytes_extend = 7;
+ break;
+ case SMI_FIFO_G_A_SEL:
+ *fifo_frmbytes_extend = 13;
+ break;
+ case SMI_FIFO_M_SEL:
+ *fifo_frmbytes_extend = 9;
+ break;
+ case SMI_FIFO_M_A_SEL:
+ case SMI_FIFO_M_G_SEL:
+ /*8(mag) + 6(gyro or acc) +1(head) = 15*/
+ *fifo_frmbytes_extend = 15;
+ break;
+ case SMI_FIFO_M_G_A_SEL:
+ /*8(mag) + 6(gyro or acc) + 6 + 1 = 21*/
+ *fifo_frmbytes_extend = 21;
+ break;
+ default:
+ *fifo_frmbytes_extend = 0;
+ break;
+
+ };
+
+}
+
+static int smi_input_init(struct smi_client_data *client_data)
+{
+ struct input_dev *dev;
+ int err = 0;
+
+ dev = input_allocate_device();
+ if (NULL == dev)
+ return -ENOMEM;
+#if defined(CONFIG_USE_QUALCOMM_HAL)
+ dev->name = "smi130-accel";
+#else
+ dev->name = SENSOR_NAME;
+#endif
+ dev->id.bustype = BUS_I2C;
+
+ input_set_capability(dev, EV_MSC, MSC_GESTURE);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_SGM);
+
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_FAST_GYRO_CALIB_DONE);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_STEP_DETECTOR);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_FAST_ACC_CALIB_DONE);
+
+
+ input_set_capability(dev, EV_REL, REL_X);
+ input_set_capability(dev, EV_REL, REL_Y);
+ input_set_capability(dev, EV_REL, REL_Z);
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ input_set_capability(dev, EV_ABS, ABS_MISC);
+ input_set_abs_params(dev, ABS_X,
+ SMI130_ACCEL_MIN_VALUE, SMI130_ACCEL_MAX_VALUE,
+ 0, 0);
+ input_set_abs_params(dev, ABS_Y,
+ SMI130_ACCEL_MIN_VALUE, SMI130_ACCEL_MAX_VALUE,
+ 0, 0);
+ input_set_abs_params(dev, ABS_Z,
+ SMI130_ACCEL_MIN_VALUE, SMI130_ACCEL_MAX_VALUE,
+ 0, 0);
+ #endif
+ input_set_drvdata(dev, client_data);
+
+ err = input_register_device(dev);
+ if (err < 0) {
+ input_free_device(dev);
+ dev_notice(client_data->dev, "smi130 input free!\n");
+ return err;
+ }
+ client_data->input = dev;
+ dev_notice(client_data->dev,
+ "smi130 input register successfully, %s!\n",
+ client_data->input->name);
+ return err;
+}
+
+//#if defined(CONFIG_USE_QUALCOMM_HAL)
+static int smi_gyro_input_init(struct smi_client_data *client_data)
+{
+ struct input_dev *dev;
+ int err = 0;
+
+ dev = input_allocate_device();
+ if (NULL == dev)
+ return -ENOMEM;
+ dev->name = "smi130-gyro";
+ dev->id.bustype = BUS_I2C;
+ input_set_capability(dev, EV_ABS, ABS_MISC);
+ input_set_capability(dev, EV_MSC, MSC_GESTURE);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_SGM);
+
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_FAST_GYRO_CALIB_DONE);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_STEP_DETECTOR);
+ input_set_capability(dev, EV_MSC, INPUT_EVENT_FAST_ACC_CALIB_DONE);
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ input_set_abs_params(dev, ABS_RX,
+ SMI130_ACCEL_MIN_VALUE, SMI130_ACCEL_MAX_VALUE,
+ 0, 0);
+ input_set_abs_params(dev, ABS_RY,
+ SMI130_ACCEL_MIN_VALUE, SMI130_ACCEL_MAX_VALUE,
+ 0, 0);
+ input_set_abs_params(dev, ABS_RZ,
+ SMI130_ACCEL_MIN_VALUE, SMI130_ACCEL_MAX_VALUE,
+ 0, 0);
+ #endif
+ input_set_drvdata(dev, client_data);
+ err = input_register_device(dev);
+ if (err < 0) {
+ input_free_device(dev);
+ dev_notice(client_data->dev, "smi130 input free!\n");
+ return err;
+ }
+ client_data->gyro_input = dev;
+ dev_notice(client_data->dev,
+ "smi130 input register successfully, %s!\n",
+ client_data->gyro_input->name);
+ return err;
+}
+//#endif
+static void smi_input_destroy(struct smi_client_data *client_data)
+{
+ struct input_dev *dev = client_data->input;
+
+ input_unregister_device(dev);
+ input_free_device(dev);
+}
+
+static int smi_check_chip_id(struct smi_client_data *client_data)
+{
+ int8_t err = 0;
+ int8_t i = 0;
+ uint8_t chip_id = 0;
+ uint8_t read_count = 0;
+ u8 smi_sensor_cnt = sizeof(sensor_type_map)
+ / sizeof(struct smi130_type_mapping_type);
+ /* read and check chip id */
+ while (read_count++ < CHECK_CHIP_ID_TIME_MAX) {
+ if (client_data->device.bus_read(client_data->device.dev_addr,
+ SMI_REG_NAME(USER_CHIP_ID), &chip_id, 1) < 0) {
+
+ dev_err(client_data->dev,
+ "Bosch Sensortec Device not found"
+ "read chip_id:%d\n", chip_id);
+ continue;
+ } else {
+ for (i = 0; i < smi_sensor_cnt; i++) {
+ if (sensor_type_map[i].chip_id == chip_id) {
+ client_data->chip_id = chip_id;
+ dev_notice(client_data->dev,
+ "Bosch Sensortec Device detected, "
+ "HW IC name: %s\n", sensor_type_map[i].sensor_name);
+ break;
+ }
+ }
+ if (i < smi_sensor_cnt)
+ break;
+ else {
+ if (read_count == CHECK_CHIP_ID_TIME_MAX) {
+ dev_err(client_data->dev,
+ "Failed!Bosch Sensortec Device not found"
+ " mismatch chip_id:%d\n", chip_id);
+ err = -ENODEV;
+ return err;
+ }
+ }
+ smi_delay(1);
+ }
+ }
+ return err;
+
+}
+
+static int smi_pmu_set_suspend(struct smi_client_data *client_data)
+{
+ int err = 0;
+ if (client_data == NULL)
+ return -EINVAL;
+ else {
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_acc_arr[SENSOR_PM_SUSPEND]);
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SENSOR_PM_SUSPEND]);
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_mag_arr[SENSOR_PM_SUSPEND]);
+ client_data->pw.acc_pm = SMI_ACC_PM_SUSPEND;
+ client_data->pw.gyro_pm = SMI_GYRO_PM_SUSPEND;
+ client_data->pw.mag_pm = SMI_MAG_PM_SUSPEND;
+ }
+
+ return err;
+}
+
+static int smi_get_err_status(struct smi_client_data *client_data)
+{
+ int err = 0;
+
+ err = SMI_CALL_API(get_error_status)(&client_data->err_st.fatal_err,
+ &client_data->err_st.err_code, &client_data->err_st.i2c_fail,
+ &client_data->err_st.drop_cmd, &client_data->err_st.mag_drdy_err);
+ return err;
+}
+
+static void smi_work_func(struct work_struct *work)
+{
+ struct smi_client_data *client_data =
+ container_of((struct delayed_work *)work,
+ struct smi_client_data, work);
+ unsigned long delay =
+ msecs_to_jiffies(atomic_read(&client_data->delay));
+ struct smi130_accel_t data;
+ int err;
+
+ err = SMI_CALL_API(read_accel_xyz)(&data);
+ if (err < 0)
+ return;
+
+ /*report current frame via input event*/
+ input_event(client_data->input, EV_REL, REL_X, data.x);
+ input_event(client_data->input, EV_REL, REL_Y, data.y);
+ input_event(client_data->input, EV_REL, REL_Z, data.z);
+ input_sync(client_data->input);
+
+ schedule_delayed_work(&client_data->work, delay);
+}
+
+static ssize_t smi130_chip_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "0x%x\n", client_data->chip_id);
+}
+
+static ssize_t smi130_err_st_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err = 0;
+ err = smi_get_err_status(client_data);
+ if (err)
+ return err;
+ else {
+ return snprintf(buf, 128, "fatal_err:0x%x, err_code:%d,\n\n"
+ "i2c_fail_err:%d, drop_cmd_err:%d, mag_drdy_err:%d\n",
+ client_data->err_st.fatal_err,
+ client_data->err_st.err_code,
+ client_data->err_st.i2c_fail,
+ client_data->err_st.drop_cmd,
+ client_data->err_st.mag_drdy_err);
+
+ }
+}
+
+static ssize_t smi130_sensor_time_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ u32 sensor_time;
+ err = SMI_CALL_API(get_sensor_time)(&sensor_time);
+ if (err)
+ return err;
+ else
+ return snprintf(buf, 16, "0x%x\n", (unsigned int)sensor_time);
+}
+
+static ssize_t smi130_fifo_flush_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long enable;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &enable);
+ if (err)
+ return err;
+ if (enable)
+ err = SMI_CALL_API(set_command_register)(CMD_CLR_FIFO_DATA);
+
+ if (err)
+ dev_err(client_data->dev, "fifo flush failed!\n");
+
+ return count;
+
+}
+
+
+static ssize_t smi130_fifo_bytecount_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned int fifo_bytecount = 0;
+
+ SMI_CALL_API(fifo_length)(&fifo_bytecount);
+ err = snprintf(buf, 16, "%u\n", fifo_bytecount);
+ return err;
+}
+
+static ssize_t smi130_fifo_bytecount_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ client_data->fifo_bytecount = (unsigned int) data;
+
+ return count;
+}
+
+int smi130_fifo_data_sel_get(struct smi_client_data *client_data)
+{
+ int err = 0;
+ unsigned char fifo_acc_en, fifo_gyro_en, fifo_mag_en;
+ unsigned char fifo_datasel;
+
+ err += SMI_CALL_API(get_fifo_accel_enable)(&fifo_acc_en);
+ err += SMI_CALL_API(get_fifo_gyro_enable)(&fifo_gyro_en);
+ err += SMI_CALL_API(get_fifo_mag_enable)(&fifo_mag_en);
+
+ if (err)
+ return err;
+
+ fifo_datasel = (fifo_acc_en << SMI_ACC_SENSOR) |
+ (fifo_gyro_en << SMI_GYRO_SENSOR) |
+ (fifo_mag_en << SMI_MAG_SENSOR);
+
+ client_data->fifo_data_sel = fifo_datasel;
+
+ return err;
+
+
+}
+
+static ssize_t smi130_fifo_data_sel_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ err = smi130_fifo_data_sel_get(client_data);
+ if (err) {
+ dev_err(client_data->dev, "get fifo_sel failed!\n");
+ return -EINVAL;
+ }
+ return snprintf(buf, 16, "%d\n", client_data->fifo_data_sel);
+}
+
+/* write any value to clear all the fifo data. */
+static ssize_t smi130_fifo_data_sel_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+ unsigned char fifo_datasel;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /* data format: aimed 0b0000 0x(m)x(g)x(a), x:1 enable, 0:disable*/
+ if (data > 7)
+ return -EINVAL;
+
+
+ fifo_datasel = (unsigned char)data;
+
+
+ err += SMI_CALL_API(set_fifo_accel_enable)
+ ((fifo_datasel & (1 << SMI_ACC_SENSOR)) ? 1 : 0);
+ err += SMI_CALL_API(set_fifo_gyro_enable)
+ (fifo_datasel & (1 << SMI_GYRO_SENSOR) ? 1 : 0);
+ err += SMI_CALL_API(set_fifo_mag_enable)
+ ((fifo_datasel & (1 << SMI_MAG_SENSOR)) ? 1 : 0);
+
+ err += SMI_CALL_API(set_command_register)(CMD_CLR_FIFO_DATA);
+ if (err)
+ return -EIO;
+ else {
+ dev_notice(client_data->dev, "FIFO A_en:%d, G_en:%d, M_en:%d\n",
+ (fifo_datasel & (1 << SMI_ACC_SENSOR)) ? 1 : 0,
+ (fifo_datasel & (1 << SMI_GYRO_SENSOR) ? 1 : 0),
+ ((fifo_datasel & (1 << SMI_MAG_SENSOR)) ? 1 : 0));
+ client_data->fifo_data_sel = fifo_datasel;
+ }
+ return count;
+}
+
+static ssize_t smi130_fifo_data_out_frame_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ int err = 0;
+ uint32_t fifo_bytecount = 0;
+
+ err = SMI_CALL_API(fifo_length)(&fifo_bytecount);
+ if (err < 0) {
+ dev_err(client_data->dev, "read fifo_length err");
+ return -EINVAL;
+ }
+ if (fifo_bytecount == 0)
+ return 0;
+ err = smi_burst_read_wrapper(client_data->device.dev_addr,
+ SMI130_USER_FIFO_DATA__REG, buf,
+ fifo_bytecount);
+ if (err) {
+ dev_err(client_data->dev, "read fifo err");
+ SMI_CALL_API(set_command_register)(CMD_CLR_FIFO_DATA);
+ return -EINVAL;
+ }
+ return fifo_bytecount;
+
+}
+
+static ssize_t smi130_fifo_watermark_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char data = 0xff;
+
+ err = SMI_CALL_API(get_fifo_wm)(&data);
+
+ if (err)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_fifo_watermark_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long data;
+ unsigned char fifo_watermark;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ fifo_watermark = (unsigned char)data;
+ err = SMI_CALL_API(set_fifo_wm)(fifo_watermark);
+ if (err)
+ return -EIO;
+
+ return count;
+}
+
+
+static ssize_t smi130_fifo_header_en_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char data = 0xff;
+
+ err = SMI_CALL_API(get_fifo_header_enable)(&data);
+
+ if (err)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_fifo_header_en_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+ unsigned char fifo_header_en;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ if (data > 1)
+ return -ENOENT;
+
+ fifo_header_en = (unsigned char)data;
+ err = SMI_CALL_API(set_fifo_header_enable)(fifo_header_en);
+ if (err)
+ return -EIO;
+
+ client_data->fifo_head_en = fifo_header_en;
+
+ return count;
+}
+
+static ssize_t smi130_fifo_time_en_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char data = 0;
+
+ err = SMI_CALL_API(get_fifo_time_enable)(&data);
+
+ if (!err)
+ err = snprintf(buf, 16, "%d\n", data);
+
+ return err;
+}
+
+static ssize_t smi130_fifo_time_en_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long data;
+ unsigned char fifo_ts_en;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ fifo_ts_en = (unsigned char)data;
+
+ err = SMI_CALL_API(set_fifo_time_enable)(fifo_ts_en);
+ if (err)
+ return -EIO;
+
+ return count;
+}
+
+static ssize_t smi130_fifo_int_tag_en_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ unsigned char fifo_tag_int1 = 0;
+ unsigned char fifo_tag_int2 = 0;
+ unsigned char fifo_tag_int;
+
+ err += SMI_CALL_API(get_fifo_tag_intr1_enable)(&fifo_tag_int1);
+ err += SMI_CALL_API(get_fifo_tag_intr2_enable)(&fifo_tag_int2);
+
+ fifo_tag_int = (fifo_tag_int1 << SMI130_INT0) |
+ (fifo_tag_int2 << SMI130_INT1);
+
+ if (!err)
+ err = snprintf(buf, 16, "%d\n", fifo_tag_int);
+
+ return err;
+}
+
+static ssize_t smi130_fifo_int_tag_en_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+ unsigned char fifo_tag_int_en;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ if (data > 3)
+ return -EINVAL;
+
+ fifo_tag_int_en = (unsigned char)data;
+
+ err += SMI_CALL_API(set_fifo_tag_intr1_enable)
+ ((fifo_tag_int_en & (1 << SMI130_INT0)) ? 1 : 0);
+ err += SMI_CALL_API(set_fifo_tag_intr2_enable)
+ ((fifo_tag_int_en & (1 << SMI130_INT1)) ? 1 : 0);
+
+ if (err) {
+ dev_err(client_data->dev, "fifo int tag en err:%d\n", err);
+ return -EIO;
+ }
+ client_data->fifo_int_tag_en = fifo_tag_int_en;
+
+ return count;
+}
+
+static int smi130_set_acc_op_mode(struct smi_client_data *client_data,
+ unsigned long op_mode)
+{
+ int err = 0;
+ unsigned char stc_enable;
+ unsigned char std_enable;
+ mutex_lock(&client_data->mutex_op_mode);
+
+ if (op_mode < SMI_ACC_PM_MAX) {
+ switch (op_mode) {
+ case SMI_ACC_PM_NORMAL:
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_acc_arr[SMI_ACC_PM_NORMAL]);
+ client_data->pw.acc_pm = SMI_ACC_PM_NORMAL;
+ smi_delay(10);
+ break;
+ case SMI_ACC_PM_LP1:
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_acc_arr[SMI_ACC_PM_LP1]);
+ client_data->pw.acc_pm = SMI_ACC_PM_LP1;
+ smi_delay(3);
+ break;
+ case SMI_ACC_PM_SUSPEND:
+ SMI_CALL_API(get_step_counter_enable)(&stc_enable);
+ SMI_CALL_API(get_step_detector_enable)(&std_enable);
+ if ((stc_enable == 0) && (std_enable == 0) &&
+ (client_data->sig_flag == 0)) {
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_acc_arr[SMI_ACC_PM_SUSPEND]);
+ client_data->pw.acc_pm = SMI_ACC_PM_SUSPEND;
+ smi_delay(10);
+ }
+ break;
+ case SMI_ACC_PM_LP2:
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_acc_arr[SMI_ACC_PM_LP2]);
+ client_data->pw.acc_pm = SMI_ACC_PM_LP2;
+ smi_delay(3);
+ break;
+ default:
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ } else {
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ return err;
+
+
+}
+
+static ssize_t smi130_temperature_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ s16 temp = 0xff;
+
+ err = SMI_CALL_API(get_temp)(&temp);
+
+ if (!err)
+ err = snprintf(buf, 16, "0x%x\n", temp);
+
+ return err;
+}
+
+static ssize_t smi130_place_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int place = BOSCH_SENSOR_PLACE_UNKNOWN;
+
+ if (NULL != client_data->bosch_pd)
+ place = client_data->bosch_pd->place;
+
+ return snprintf(buf, 16, "%d\n", place);
+}
+
+static ssize_t smi130_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&client_data->delay));
+
+}
+
+static ssize_t smi130_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long data;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ if (data == 0) {
+ err = -EINVAL;
+ return err;
+ }
+
+ if (data < SMI_DELAY_MIN)
+ data = SMI_DELAY_MIN;
+
+ atomic_set(&client_data->delay, (unsigned int)data);
+
+ return count;
+}
+
+static ssize_t smi130_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&client_data->wkqueue_en));
+
+}
+
+static ssize_t smi130_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long enable;
+ int pre_enable = atomic_read(&client_data->wkqueue_en);
+
+ err = kstrtoul(buf, 10, &enable);
+ if (err)
+ return err;
+
+ enable = enable ? 1 : 0;
+ mutex_lock(&client_data->mutex_enable);
+ if (enable) {
+ if (pre_enable == 0) {
+ smi130_set_acc_op_mode(client_data,
+ SMI_ACC_PM_NORMAL);
+ schedule_delayed_work(&client_data->work,
+ msecs_to_jiffies(atomic_read(&client_data->delay)));
+ atomic_set(&client_data->wkqueue_en, 1);
+ }
+
+ } else {
+ if (pre_enable == 1) {
+ smi130_set_acc_op_mode(client_data,
+ SMI_ACC_PM_SUSPEND);
+
+ cancel_delayed_work_sync(&client_data->work);
+ atomic_set(&client_data->wkqueue_en, 0);
+ }
+ }
+
+ mutex_unlock(&client_data->mutex_enable);
+
+ return count;
+}
+
+#if defined(SMI130_ENABLE_INT1) || defined(SMI130_ENABLE_INT2)
+/* accel sensor part */
+static ssize_t smi130_anymot_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char data;
+
+ err = SMI_CALL_API(get_intr_any_motion_durn)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_anymot_duration_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_intr_any_motion_durn)((unsigned char)data);
+ if (err < 0)
+ return -EIO;
+
+ return count;
+}
+
+static ssize_t smi130_anymot_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = SMI_CALL_API(get_intr_any_motion_thres)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_anymot_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_intr_any_motion_thres)((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_step_detector_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data = 0;
+ u8 step_det;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ err = SMI_CALL_API(get_step_detector_enable)(&step_det);
+ /*smi130_get_status0_step_int*/
+ if (err < 0)
+ return err;
+/*client_data->std will be updated in smi_stepdetector_interrupt_handle */
+ if ((step_det == 1) && (client_data->std == 1)) {
+ data = 1;
+ client_data->std = 0;
+ }
+ else {
+ data = 0;
+ }
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_step_detector_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = SMI_CALL_API(get_step_detector_enable)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_step_detector_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_step_detector_enable)((unsigned char)data);
+ if (err < 0)
+ return -EIO;
+ if (data == 0)
+ client_data->pedo_data.wkar_step_detector_status = 0;
+ return count;
+}
+
+static ssize_t smi130_signification_motion_enable_store(
+ struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /*0x62 (bit 1) INT_MOTION_3 int_sig_mot_sel*/
+ err = SMI_CALL_API(set_intr_significant_motion_select)(
+ (unsigned char)data);
+ if (err < 0)
+ return -EIO;
+ if (data == 1) {
+ err = SMI_CALL_API(set_intr_enable_0)
+ (SMI130_ANY_MOTION_X_ENABLE, 1);
+ err += SMI_CALL_API(set_intr_enable_0)
+ (SMI130_ANY_MOTION_Y_ENABLE, 1);
+ err += SMI_CALL_API(set_intr_enable_0)
+ (SMI130_ANY_MOTION_Z_ENABLE, 1);
+ if (err < 0)
+ return -EIO;
+ enable_irq_wake(client_data->IRQ);
+ client_data->sig_flag = 1;
+ } else {
+ err = SMI_CALL_API(set_intr_enable_0)
+ (SMI130_ANY_MOTION_X_ENABLE, 0);
+ err += SMI_CALL_API(set_intr_enable_0)
+ (SMI130_ANY_MOTION_Y_ENABLE, 0);
+ err += SMI_CALL_API(set_intr_enable_0)
+ (SMI130_ANY_MOTION_Z_ENABLE, 0);
+ if (err < 0)
+ return -EIO;
+ disable_irq_wake(client_data->IRQ);
+ client_data->sig_flag = 0;
+ }
+ return count;
+}
+
+static ssize_t smi130_signification_motion_enable_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+ /*0x62 (bit 1) INT_MOTION_3 int_sig_mot_sel*/
+ err = SMI_CALL_API(get_intr_significant_motion_select)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static int sigmotion_init_interrupts(u8 sig_map_int_pin)
+{
+ int ret = 0;
+/*0x60 */
+ ret += smi130_set_intr_any_motion_thres(0x1e);
+/* 0x62(bit 3~2) 0=1.5s */
+ ret += smi130_set_intr_significant_motion_skip(0);
+/*0x62(bit 5~4) 1=0.5s*/
+ ret += smi130_set_intr_significant_motion_proof(1);
+/*0x50 (bit 0, 1, 2) INT_EN_0 anymo x y z*/
+ ret += smi130_map_significant_motion_intr(sig_map_int_pin);
+/*0x62 (bit 1) INT_MOTION_3 int_sig_mot_sel
+close the signification_motion*/
+ ret += smi130_set_intr_significant_motion_select(0);
+/*close the anymotion interrupt*/
+ ret += SMI_CALL_API(set_intr_enable_0)
+ (SMI130_ANY_MOTION_X_ENABLE, 0);
+ ret += SMI_CALL_API(set_intr_enable_0)
+ (SMI130_ANY_MOTION_Y_ENABLE, 0);
+ ret += SMI_CALL_API(set_intr_enable_0)
+ (SMI130_ANY_MOTION_Z_ENABLE, 0);
+ if (ret)
+ printk(KERN_ERR "smi130 sig motion failed setting,%d!\n", ret);
+ return ret;
+
+}
+#endif
+
+static ssize_t smi130_acc_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char range;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = SMI_CALL_API(get_accel_range)(&range);
+ if (err)
+ return err;
+
+ client_data->range.acc_range = range;
+ return snprintf(buf, 16, "%d\n", range);
+}
+
+static ssize_t smi130_acc_range_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long range;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+
+ err = kstrtoul(buf, 10, &range);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_accel_range)(range);
+ if (err)
+ return -EIO;
+
+ client_data->range.acc_range = range;
+ return count;
+}
+
+static ssize_t smi130_acc_odr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char acc_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = SMI_CALL_API(get_accel_output_data_rate)(&acc_odr);
+ if (err)
+ return err;
+
+ client_data->odr.acc_odr = acc_odr;
+ return snprintf(buf, 16, "%d\n", acc_odr);
+}
+
+static ssize_t smi130_acc_odr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long acc_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &acc_odr);
+ if (err)
+ return err;
+
+ if (acc_odr < 1 || acc_odr > 12)
+ return -EIO;
+
+ if (acc_odr < 5)
+ err = SMI_CALL_API(set_accel_under_sampling_parameter)(1);
+ else
+ err = SMI_CALL_API(set_accel_under_sampling_parameter)(0);
+
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_accel_output_data_rate)(acc_odr);
+ if (err)
+ return -EIO;
+ client_data->odr.acc_odr = acc_odr;
+ return count;
+}
+
+static ssize_t smi130_acc_op_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err = 0;
+ u8 accel_pmu_status = 0;
+ err = SMI_CALL_API(get_accel_power_mode_stat)(
+ &accel_pmu_status);
+
+ if (err)
+ return err;
+ else
+ return snprintf(buf, 32, "reg:%d, val:%d\n", accel_pmu_status,
+ client_data->pw.acc_pm);
+}
+
+static ssize_t smi130_acc_op_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err;
+ unsigned long op_mode;
+ err = kstrtoul(buf, 10, &op_mode);
+ if (err)
+ return err;
+
+ err = smi130_set_acc_op_mode(client_data, op_mode);
+ if (err)
+ return err;
+ else
+ return count;
+
+}
+
+static ssize_t smi130_acc_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct smi130_accel_t data;
+
+ int err;
+
+ err = SMI_CALL_API(read_accel_xyz)(&data);
+ if (err < 0)
+ return err;
+
+ return snprintf(buf, 48, "%hd %hd %hd\n",
+ data.x, data.y, data.z);
+}
+
+static ssize_t smi130_acc_fast_calibration_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = SMI_CALL_API(get_foc_accel_x)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_acc_fast_calibration_x_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ s8 accel_offset_x = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /* 0: disable, 1: +1g, 2: -1g, 3: 0g */
+ if (data > 3)
+ return -EINVAL;
+
+ err = SMI_CALL_API(set_accel_foc_trigger)(X_AXIS,
+ data, &accel_offset_x);
+ if (err)
+ return -EIO;
+ else
+ client_data->calib_status |=
+ SMI_FAST_CALI_TRUE << SMI_ACC_X_FAST_CALI_RDY;
+ return count;
+}
+
+static ssize_t smi130_acc_fast_calibration_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = SMI_CALL_API(get_foc_accel_y)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_acc_fast_calibration_y_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ s8 accel_offset_y = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /* 0: disable, 1: +1g, 2: -1g, 3: 0g */
+ if (data > 3)
+ return -EINVAL;
+
+ err = SMI_CALL_API(set_accel_foc_trigger)(Y_AXIS,
+ data, &accel_offset_y);
+ if (err)
+ return -EIO;
+ else
+ client_data->calib_status |=
+ SMI_FAST_CALI_TRUE << SMI_ACC_Y_FAST_CALI_RDY;
+ return count;
+}
+
+static ssize_t smi130_acc_fast_calibration_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = SMI_CALL_API(get_foc_accel_z)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_acc_fast_calibration_z_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ s8 accel_offset_z = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ unsigned char data1[3] = {0};
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+ /* 0: disable, 1: +1g, 2: -1g, 3: 0g */
+ if (data > 3)
+ return -EINVAL;
+
+ err = SMI_CALL_API(set_accel_foc_trigger)(Z_AXIS,
+ data, &accel_offset_z);
+ if (err)
+ return -EIO;
+ else
+ client_data->calib_status |=
+ SMI_FAST_CALI_TRUE << SMI_ACC_Z_FAST_CALI_RDY;
+
+ if (client_data->calib_status == SMI_FAST_CALI_ALL_RDY) {
+ err = SMI_CALL_API(get_accel_offset_compensation_xaxis)(
+ &data1[0]);
+ err += SMI_CALL_API(get_accel_offset_compensation_yaxis)(
+ &data1[1]);
+ err += SMI_CALL_API(get_accel_offset_compensation_zaxis)(
+ &data1[2]);
+ dev_info(client_data->dev, "accx %d, accy %d, accz %d\n",
+ data1[0], data1[1], data1[2]);
+ if (err)
+ return -EIO;
+ input_event(client_data->input, EV_MSC,
+ INPUT_EVENT_FAST_ACC_CALIB_DONE,
+ (data1[0] | (data1[1] << 8) | (data1[2] << 16)));
+ input_sync(client_data->input);
+ client_data->calib_status = 0;
+ }
+
+ return count;
+}
+
+static ssize_t smi130_acc_offset_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = SMI_CALL_API(get_accel_offset_compensation_xaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+
+static ssize_t smi130_acc_offset_x_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_accel_offset_compensation_xaxis)
+ ((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_acc_offset_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = SMI_CALL_API(get_accel_offset_compensation_yaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_acc_offset_y_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_accel_offset_compensation_yaxis)
+ ((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_acc_offset_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = SMI_CALL_API(get_accel_offset_compensation_zaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_acc_offset_z_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_accel_offset_compensation_zaxis)
+ ((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_test_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ u8 raw_data[15] = {0};
+ unsigned int sensor_time = 0;
+
+ int err;
+ memset(raw_data, 0, sizeof(raw_data));
+
+ err = client_data->device.bus_read(client_data->device.dev_addr,
+ SMI130_USER_DATA_8_GYRO_X_LSB__REG, raw_data, 15);
+ if (err)
+ return err;
+
+ udelay(10);
+ sensor_time = (u32)(raw_data[14] << 16 | raw_data[13] << 8
+ | raw_data[12]);
+
+ return snprintf(buf, 128, "%d %d %d %d %d %d %u",
+ (s16)(raw_data[1] << 8 | raw_data[0]),
+ (s16)(raw_data[3] << 8 | raw_data[2]),
+ (s16)(raw_data[5] << 8 | raw_data[4]),
+ (s16)(raw_data[7] << 8 | raw_data[6]),
+ (s16)(raw_data[9] << 8 | raw_data[8]),
+ (s16)(raw_data[11] << 8 | raw_data[10]),
+ sensor_time);
+
+}
+
+static ssize_t smi130_step_counter_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = SMI_CALL_API(get_step_counter_enable)(&data);
+
+ client_data->stc_enable = data;
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_step_counter_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_step_counter_enable)((unsigned char)data);
+
+ client_data->stc_enable = data;
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+
+static ssize_t smi130_step_counter_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_step_mode)((unsigned char)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_step_counter_clc_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = smi130_clear_step_counter();
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_step_counter_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u16 data;
+ int err;
+ static u16 last_stc_value;
+
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = SMI_CALL_API(read_step_count)(&data);
+
+ if (err < 0)
+ return err;
+ if (data >= last_stc_value) {
+ client_data->pedo_data.last_step_counter_value += (
+ data - last_stc_value);
+ last_stc_value = data;
+ } else
+ last_stc_value = data;
+ return snprintf(buf, 16, "%d\n",
+ client_data->pedo_data.last_step_counter_value);
+}
+
+static ssize_t smi130_smi_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ u8 raw_data[12] = {0};
+
+ int err;
+ memset(raw_data, 0, sizeof(raw_data));
+
+ err = client_data->device.bus_read(client_data->device.dev_addr,
+ SMI130_USER_DATA_8_GYRO_X_LSB__REG, raw_data, 12);
+ if (err)
+ return err;
+ /*output:gyro x y z acc x y z*/
+ return snprintf(buf, 96, "%hd %d %hd %hd %hd %hd\n",
+ (s16)(raw_data[1] << 8 | raw_data[0]),
+ (s16)(raw_data[3] << 8 | raw_data[2]),
+ (s16)(raw_data[5] << 8 | raw_data[4]),
+ (s16)(raw_data[7] << 8 | raw_data[6]),
+ (s16)(raw_data[9] << 8 | raw_data[8]),
+ (s16)(raw_data[11] << 8 | raw_data[10]));
+
+}
+
+
+static ssize_t smi130_selftest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "0x%x\n",
+ atomic_read(&client_data->selftest_result));
+}
+
+static int smi_restore_hw_cfg(struct smi_client_data *client);
+
+/*!
+ * @brief store selftest result which make up of acc and gyro
+ * format: 0b 0000 xxxx x:1 failed, 0 success
+ * bit3: gyro_self
+ * bit2..0: acc_self z y x
+ */
+static ssize_t smi130_selftest_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err = 0;
+ int i = 0;
+
+ u8 acc_selftest = 0;
+ u8 gyro_selftest = 0;
+ u8 smi_selftest = 0;
+ s16 axis_p_value, axis_n_value;
+ u16 diff_axis[3] = {0xff, 0xff, 0xff};
+ u8 acc_odr, range, acc_selftest_amp, acc_selftest_sign;
+
+ dev_notice(client_data->dev, "Selftest for SMI16x starting.\n");
+
+ client_data->selftest = 1;
+
+ /*soft reset*/
+ err = SMI_CALL_API(set_command_register)(CMD_RESET_USER_REG);
+ msleep(70);
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_acc_arr[SMI_ACC_PM_NORMAL]);
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_NORMAL]);
+ err += SMI_CALL_API(set_accel_under_sampling_parameter)(0);
+ err += SMI_CALL_API(set_accel_output_data_rate)(
+ SMI130_ACCEL_OUTPUT_DATA_RATE_1600HZ);
+
+ /* set to 8G range*/
+ err += SMI_CALL_API(set_accel_range)(SMI130_ACCEL_RANGE_8G);
+ /* set to self amp high */
+ err += SMI_CALL_API(set_accel_selftest_amp)(SMI_SELFTEST_AMP_HIGH);
+
+
+ err += SMI_CALL_API(get_accel_output_data_rate)(&acc_odr);
+ err += SMI_CALL_API(get_accel_range)(&range);
+ err += SMI_CALL_API(get_accel_selftest_amp)(&acc_selftest_amp);
+ err += SMI_CALL_API(read_accel_x)(&axis_n_value);
+
+ dev_info(client_data->dev,
+ "acc_odr:%d, acc_range:%d, acc_selftest_amp:%d, acc_x:%d\n",
+ acc_odr, range, acc_selftest_amp, axis_n_value);
+
+ for (i = X_AXIS; i < AXIS_MAX; i++) {
+ axis_n_value = 0;
+ axis_p_value = 0;
+ /* set every selftest axis */
+ /*set_acc_selftest_axis(param),param x:1, y:2, z:3
+ * but X_AXIS:0, Y_AXIS:1, Z_AXIS:2
+ * so we need to +1*/
+ err += SMI_CALL_API(set_accel_selftest_axis)(i + 1);
+ msleep(50);
+ switch (i) {
+ case X_AXIS:
+ /* set negative sign */
+ err += SMI_CALL_API(set_accel_selftest_sign)(0);
+ err += SMI_CALL_API(get_accel_selftest_sign)(
+ &acc_selftest_sign);
+
+ msleep(60);
+ err += SMI_CALL_API(read_accel_x)(&axis_n_value);
+ dev_info(client_data->dev,
+ "acc_x_selftest_sign:%d, axis_n_value:%d\n",
+ acc_selftest_sign, axis_n_value);
+
+ /* set postive sign */
+ err += SMI_CALL_API(set_accel_selftest_sign)(1);
+ err += SMI_CALL_API(get_accel_selftest_sign)(
+ &acc_selftest_sign);
+
+ msleep(60);
+ err += SMI_CALL_API(read_accel_x)(&axis_p_value);
+ dev_info(client_data->dev,
+ "acc_x_selftest_sign:%d, axis_p_value:%d\n",
+ acc_selftest_sign, axis_p_value);
+ diff_axis[i] = abs(axis_p_value - axis_n_value);
+ break;
+
+ case Y_AXIS:
+ /* set negative sign */
+ err += SMI_CALL_API(set_accel_selftest_sign)(0);
+ msleep(60);
+ err += SMI_CALL_API(read_accel_y)(&axis_n_value);
+ /* set postive sign */
+ err += SMI_CALL_API(set_accel_selftest_sign)(1);
+ msleep(60);
+ err += SMI_CALL_API(read_accel_y)(&axis_p_value);
+ diff_axis[i] = abs(axis_p_value - axis_n_value);
+ break;
+
+ case Z_AXIS:
+ /* set negative sign */
+ err += SMI_CALL_API(set_accel_selftest_sign)(0);
+ msleep(60);
+ err += SMI_CALL_API(read_accel_z)(&axis_n_value);
+ /* set postive sign */
+ err += SMI_CALL_API(set_accel_selftest_sign)(1);
+ msleep(60);
+ err += SMI_CALL_API(read_accel_z)(&axis_p_value);
+ /* also start gyro self test */
+ err += SMI_CALL_API(set_gyro_selftest_start)(1);
+ msleep(60);
+ err += SMI_CALL_API(get_gyro_selftest)(&gyro_selftest);
+
+ diff_axis[i] = abs(axis_p_value - axis_n_value);
+ break;
+ default:
+ err += -EINVAL;
+ break;
+ }
+ if (err) {
+ dev_err(client_data->dev,
+ "Failed selftest axis:%s, p_val=%d, n_val=%d\n",
+ smi_axis_name[i], axis_p_value, axis_n_value);
+ client_data->selftest = 0;
+ return -EINVAL;
+ }
+
+ /*400mg for acc z axis*/
+ if (Z_AXIS == i) {
+ if (diff_axis[i] < 1639) {
+ acc_selftest |= 1 << i;
+ dev_err(client_data->dev,
+ "Over selftest minimum for "
+ "axis:%s,diff=%d,p_val=%d, n_val=%d\n",
+ smi_axis_name[i], diff_axis[i],
+ axis_p_value, axis_n_value);
+ }
+ } else {
+ /*800mg for x or y axis*/
+ if (diff_axis[i] < 3277) {
+ acc_selftest |= 1 << i;
+
+ if (smi_get_err_status(client_data) < 0)
+ return err;
+ dev_err(client_data->dev,
+ "Over selftest minimum for "
+ "axis:%s,diff=%d, p_val=%d, n_val=%d\n",
+ smi_axis_name[i], diff_axis[i],
+ axis_p_value, axis_n_value);
+ dev_err(client_data->dev, "err_st:0x%x\n",
+ client_data->err_st.err_st_all);
+
+ }
+ }
+
+ }
+ /* gyro_selftest==1,gyro selftest successfully,
+ * but smi_result bit4 0 is successful, 1 is failed*/
+ smi_selftest = (acc_selftest & 0x0f) | ((!gyro_selftest) << AXIS_MAX);
+ atomic_set(&client_data->selftest_result, smi_selftest);
+ /*soft reset*/
+ err = SMI_CALL_API(set_command_register)(CMD_RESET_USER_REG);
+ if (err) {
+ client_data->selftest = 0;
+ return err;
+ }
+ msleep(50);
+
+ smi_restore_hw_cfg(client_data);
+
+ client_data->selftest = 0;
+ dev_notice(client_data->dev, "Selftest for SMI16x finished\n");
+
+ return count;
+}
+
+/* gyro sensor part */
+static ssize_t smi130_gyro_op_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int err = 0;
+ u8 gyro_pmu_status = 0;
+
+ err = SMI_CALL_API(get_gyro_power_mode_stat)(
+ &gyro_pmu_status);
+
+ if (err)
+ return err;
+ else
+ return snprintf(buf, 32, "reg:%d, val:%d\n", gyro_pmu_status,
+ client_data->pw.gyro_pm);
+}
+
+static ssize_t smi130_gyro_op_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ unsigned long op_mode;
+ int err;
+
+ err = kstrtoul(buf, 10, &op_mode);
+ if (err)
+ return err;
+
+ mutex_lock(&client_data->mutex_op_mode);
+
+ if (op_mode < SMI_GYRO_PM_MAX) {
+ switch (op_mode) {
+ case SMI_GYRO_PM_NORMAL:
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_NORMAL]);
+ client_data->pw.gyro_pm = SMI_GYRO_PM_NORMAL;
+ smi_delay(60);
+ break;
+ case SMI_GYRO_PM_FAST_START:
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_FAST_START]);
+ client_data->pw.gyro_pm = SMI_GYRO_PM_FAST_START;
+ smi_delay(60);
+ break;
+ case SMI_GYRO_PM_SUSPEND:
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_SUSPEND]);
+ client_data->pw.gyro_pm = SMI_GYRO_PM_SUSPEND;
+ smi_delay(60);
+ break;
+ default:
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ } else {
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ if (err)
+ return err;
+ else
+ return count;
+
+}
+
+static ssize_t smi130_gyro_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct smi130_gyro_t data;
+ int err;
+
+ err = SMI_CALL_API(read_gyro_xyz)(&data);
+ if (err < 0)
+ return err;
+
+
+ return snprintf(buf, 48, "%hd %hd %hd\n", data.x,
+ data.y, data.z);
+}
+
+static ssize_t smi130_gyro_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char range;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = SMI_CALL_API(get_gyro_range)(&range);
+ if (err)
+ return err;
+
+ client_data->range.gyro_range = range;
+ return snprintf(buf, 16, "%d\n", range);
+}
+
+static ssize_t smi130_gyro_range_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long range;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &range);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_gyro_range)(range);
+ if (err)
+ return -EIO;
+
+ client_data->range.gyro_range = range;
+ return count;
+}
+
+static ssize_t smi130_gyro_odr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char gyro_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = SMI_CALL_API(get_gyro_output_data_rate)(&gyro_odr);
+ if (err)
+ return err;
+
+ client_data->odr.gyro_odr = gyro_odr;
+ return snprintf(buf, 16, "%d\n", gyro_odr);
+}
+
+static ssize_t smi130_gyro_odr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long gyro_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &gyro_odr);
+ if (err)
+ return err;
+
+ if (gyro_odr < 6 || gyro_odr > 13)
+ return -EIO;
+
+ err = SMI_CALL_API(set_gyro_output_data_rate)(gyro_odr);
+ if (err)
+ return -EIO;
+
+ client_data->odr.gyro_odr = gyro_odr;
+ return count;
+}
+
+static ssize_t smi130_gyro_fast_calibration_en_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err;
+
+ err = SMI_CALL_API(get_foc_gyro_enable)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_gyro_fast_calibration_en_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long enable;
+ s8 err;
+ s16 gyr_off_x;
+ s16 gyr_off_y;
+ s16 gyr_off_z;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &enable);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_foc_gyro_enable)((u8)enable,
+ &gyr_off_x, &gyr_off_y, &gyr_off_z);
+
+ if (err < 0)
+ return -EIO;
+ else {
+ input_event(client_data->input, EV_MSC,
+ INPUT_EVENT_FAST_GYRO_CALIB_DONE, 1);
+ input_sync(client_data->input);
+ }
+ return count;
+}
+
+static ssize_t smi130_gyro_offset_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s16 data = 0;
+ s8 err = 0;
+
+ err = SMI_CALL_API(get_gyro_offset_compensation_xaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_gyro_offset_x_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ s8 err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_gyro_offset_compensation_xaxis)((s16)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_gyro_offset_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s16 data = 0;
+ s8 err = 0;
+
+ err = SMI_CALL_API(get_gyro_offset_compensation_yaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_gyro_offset_y_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ s8 err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_gyro_offset_compensation_yaxis)((s16)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_gyro_offset_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s16 data = 0;
+ int err = 0;
+
+ err = SMI_CALL_API(get_gyro_offset_compensation_zaxis)(&data);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "%d\n", data);
+}
+
+static ssize_t smi130_gyro_offset_z_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err = SMI_CALL_API(set_gyro_offset_compensation_zaxis)((s16)data);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+
+/* mag sensor part */
+#ifdef SMI130_MAG_INTERFACE_SUPPORT
+static ssize_t smi130_mag_op_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ u8 mag_op_mode;
+ s8 err;
+ err = smi130_get_mag_power_mode_stat(&mag_op_mode);
+ if (err) {
+ dev_err(client_data->dev,
+ "Failed to get SMI130 mag power mode:%d\n", err);
+ return err;
+ } else
+ return snprintf(buf, 32, "%d, reg:%d\n",
+ client_data->pw.mag_pm, mag_op_mode);
+}
+
+static ssize_t smi130_mag_op_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ unsigned long op_mode;
+ int err;
+
+ err = kstrtoul(buf, 10, &op_mode);
+ if (err)
+ return err;
+
+ if (op_mode == client_data->pw.mag_pm)
+ return count;
+
+ mutex_lock(&client_data->mutex_op_mode);
+
+
+ if (op_mode < SMI_MAG_PM_MAX) {
+ switch (op_mode) {
+ case SMI_MAG_PM_NORMAL:
+ /* need to modify as mag sensor connected,
+ * set write address to 0x4c and triggers
+ * write operation
+ * 0x4c(op mode control reg)
+ * enables normal mode in magnetometer */
+#if defined(SMI130_AKM09912_SUPPORT)
+ err = smi130_set_bosch_akm_and_secondary_if_powermode(
+ SMI130_MAG_FORCE_MODE);
+#else
+ err = smi130_set_bmm150_mag_and_secondary_if_power_mode(
+ SMI130_MAG_FORCE_MODE);
+#endif
+ client_data->pw.mag_pm = SMI_MAG_PM_NORMAL;
+ smi_delay(5);
+ break;
+ case SMI_MAG_PM_LP1:
+ /* need to modify as mag sensor connected,
+ * set write address to 0x4 band triggers
+ * write operation
+ * 0x4b(bmm150, power control reg, bit0)
+ * enables power in magnetometer*/
+#if defined(SMI130_AKM09912_SUPPORT)
+ err = smi130_set_bosch_akm_and_secondary_if_powermode(
+ SMI130_MAG_FORCE_MODE);
+#else
+ err = smi130_set_bmm150_mag_and_secondary_if_power_mode(
+ SMI130_MAG_FORCE_MODE);
+#endif
+ client_data->pw.mag_pm = SMI_MAG_PM_LP1;
+ smi_delay(5);
+ break;
+ case SMI_MAG_PM_SUSPEND:
+ case SMI_MAG_PM_LP2:
+#if defined(SMI130_AKM09912_SUPPORT)
+ err = smi130_set_bosch_akm_and_secondary_if_powermode(
+ SMI130_MAG_SUSPEND_MODE);
+#else
+ err = smi130_set_bmm150_mag_and_secondary_if_power_mode(
+ SMI130_MAG_SUSPEND_MODE);
+#endif
+ client_data->pw.mag_pm = op_mode;
+ smi_delay(5);
+ break;
+ default:
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ } else {
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ if (err) {
+ dev_err(client_data->dev,
+ "Failed to switch SMI130 mag power mode:%d\n",
+ client_data->pw.mag_pm);
+ return err;
+ } else
+ return count;
+
+}
+
+static ssize_t smi130_mag_odr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ unsigned char mag_odr = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = SMI_CALL_API(get_mag_output_data_rate)(&mag_odr);
+ if (err)
+ return err;
+
+ client_data->odr.mag_odr = mag_odr;
+ return snprintf(buf, 16, "%d\n", mag_odr);
+}
+
+static ssize_t smi130_mag_odr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long mag_odr;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &mag_odr);
+ if (err)
+ return err;
+ /*1~25/32hz,..6(25hz),7(50hz),... */
+ err = SMI_CALL_API(set_mag_output_data_rate)(mag_odr);
+ if (err)
+ return -EIO;
+
+ client_data->odr.mag_odr = mag_odr;
+ return count;
+}
+
+static ssize_t smi130_mag_i2c_address_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data;
+ s8 err;
+
+ err = SMI_CALL_API(set_mag_manual_enable)(1);
+ err += SMI_CALL_API(get_i2c_device_addr)(&data);
+ err += SMI_CALL_API(set_mag_manual_enable)(0);
+
+ if (err < 0)
+ return err;
+ return snprintf(buf, 16, "0x%x\n", data);
+}
+
+static ssize_t smi130_mag_i2c_address_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err += SMI_CALL_API(set_mag_manual_enable)(1);
+ if (!err)
+ err += SMI_CALL_API(set_i2c_device_addr)((unsigned char)data);
+ err += SMI_CALL_API(set_mag_manual_enable)(0);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_mag_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ struct smi130_mag_xyz_s32_t data;
+ int err;
+ /* raw data with compensation */
+#if defined(SMI130_AKM09912_SUPPORT)
+ err = smi130_bosch_akm09912_compensate_xyz(&data);
+#else
+ err = smi130_bmm150_mag_compensate_xyz(&data);
+#endif
+
+ if (err < 0) {
+ memset(&data, 0, sizeof(data));
+ dev_err(client_data->dev, "mag not ready!\n");
+ }
+ return snprintf(buf, 48, "%hd %hd %hd\n", data.x,
+ data.y, data.z);
+}
+static ssize_t smi130_mag_offset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ unsigned char mag_offset;
+ err = SMI_CALL_API(get_mag_offset)(&mag_offset);
+ if (err)
+ return err;
+
+ return snprintf(buf, 16, "%d\n", mag_offset);
+
+}
+
+static ssize_t smi130_mag_offset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ err += SMI_CALL_API(set_mag_manual_enable)(1);
+ if (err == 0)
+ err += SMI_CALL_API(set_mag_offset)((unsigned char)data);
+ err += SMI_CALL_API(set_mag_manual_enable)(0);
+
+ if (err < 0)
+ return -EIO;
+ return count;
+}
+
+static ssize_t smi130_mag_chip_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s8 err = 0;
+ u8 mag_chipid;
+
+ err = smi130_set_mag_manual_enable(0x01);
+ /* read mag chip_id value */
+#if defined(SMI130_AKM09912_SUPPORT)
+ err += smi130_set_mag_read_addr(AKM09912_CHIP_ID_REG);
+ /* 0x04 is mag_x lsb register */
+ err += smi130_read_reg(SMI130_USER_DATA_0_MAG_X_LSB__REG,
+ &mag_chipid, 1);
+
+ /* Must add this commands to re-set data register addr of mag sensor */
+ err += smi130_set_mag_read_addr(AKM_DATA_REGISTER);
+#else
+ err += smi130_set_mag_read_addr(SMI130_BMM150_CHIP_ID);
+ /* 0x04 is mag_x lsb register */
+ err += smi130_read_reg(SMI130_USER_DATA_0_MAG_X_LSB__REG,
+ &mag_chipid, 1);
+
+ /* Must add this commands to re-set data register addr of mag sensor */
+ /* 0x42 is bmm150 data register address */
+ err += smi130_set_mag_read_addr(SMI130_BMM150_DATA_REG);
+#endif
+
+ err += smi130_set_mag_manual_enable(0x00);
+
+ if (err)
+ return err;
+
+ return snprintf(buf, 16, "%x\n", mag_chipid);
+
+}
+
+static ssize_t smi130_mag_chip_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 mag_chipid = 0;
+#if defined(SMI130_AKM09912_SUPPORT)
+ mag_chipid = 15;
+#else
+ mag_chipid = 150;
+#endif
+ return snprintf(buf, 16, "%d\n", mag_chipid);
+}
+
+struct smi130_mag_xyz_s32_t mag_compensate;
+static ssize_t smi130_mag_compensate_xyz_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ memcpy(buf, &mag_compensate, sizeof(mag_compensate));
+ return sizeof(mag_compensate);
+}
+static ssize_t smi130_mag_compensate_xyz_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct smi130_mag_xyzr_t mag_raw;
+ memset(&mag_compensate, 0, sizeof(mag_compensate));
+ memset(&mag_raw, 0, sizeof(mag_raw));
+ mag_raw.x = (buf[1] << 8 | buf[0]);
+ mag_raw.y = (buf[3] << 8 | buf[2]);
+ mag_raw.z = (buf[5] << 8 | buf[4]);
+ mag_raw.r = (buf[7] << 8 | buf[6]);
+ mag_raw.x = mag_raw.x >> 3;
+ mag_raw.y = mag_raw.y >> 3;
+ mag_raw.z = mag_raw.z >> 1;
+ mag_raw.r = mag_raw.r >> 2;
+ smi130_bmm150_mag_compensate_xyz_raw(
+ &mag_compensate, mag_raw);
+ return count;
+}
+
+#endif
+
+#if defined(SMI130_ENABLE_INT1) || defined(SMI130_ENABLE_INT2)
+static ssize_t smi_enable_int_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int interrupt_type, value;
+
+ sscanf(buf, "%3d %3d", &interrupt_type, &value);
+
+ if (interrupt_type < 0 || interrupt_type > 16)
+ return -EINVAL;
+
+ if (interrupt_type <= SMI_FLAT_INT) {
+ if (SMI_CALL_API(set_intr_enable_0)
+ (smi_interrupt_type[interrupt_type], value) < 0)
+ return -EINVAL;
+ } else if (interrupt_type <= SMI_FWM_INT) {
+ if (SMI_CALL_API(set_intr_enable_1)
+ (smi_interrupt_type[interrupt_type], value) < 0)
+ return -EINVAL;
+ } else {
+ if (SMI_CALL_API(set_intr_enable_2)
+ (smi_interrupt_type[interrupt_type], value) < 0)
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+#endif
+
+static ssize_t smi130_show_reg_sel(struct device *dev
+ , struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+
+ return snprintf(buf, 64, "reg=0X%02X, len=%d\n",
+ client_data->reg_sel, client_data->reg_len);
+}
+
+static ssize_t smi130_store_reg_sel(struct device *dev
+ , struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ ssize_t ret;
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+ ret = sscanf(buf, "%11X %11d",
+ &client_data->reg_sel, &client_data->reg_len);
+ if (ret != 2) {
+ dev_err(client_data->dev, "Invalid argument");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t smi130_show_reg_val(struct device *dev
+ , struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+
+ ssize_t ret;
+ u8 reg_data[128], i;
+ int pos;
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+
+ ret = smi_burst_read_wrapper(client_data->device.dev_addr,
+ client_data->reg_sel,
+ reg_data, client_data->reg_len);
+ if (ret < 0) {
+ dev_err(client_data->dev, "Reg op failed");
+ return ret;
+ }
+
+ pos = 0;
+ for (i = 0; i < client_data->reg_len; ++i) {
+ pos += snprintf(buf + pos, 16, "%02X", reg_data[i]);
+ buf[pos++] = (i + 1) % 16 == 0 ? '\n' : ' ';
+ }
+ if (buf[pos - 1] == ' ')
+ buf[pos - 1] = '\n';
+
+ return pos;
+}
+
+static ssize_t smi130_store_reg_val(struct device *dev
+ , struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ ssize_t ret;
+ u8 reg_data[32];
+ int i, j, status, digit;
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+ status = 0;
+ for (i = j = 0; i < count && j < client_data->reg_len; ++i) {
+ if (buf[i] == ' ' || buf[i] == '\n' || buf[i] == '\t' ||
+ buf[i] == '\r') {
+ status = 0;
+ ++j;
+ continue;
+ }
+ digit = buf[i] & 0x10 ? (buf[i] & 0xF) : ((buf[i] & 0xF) + 9);
+ printk(KERN_INFO "digit is %d", digit);
+ switch (status) {
+ case 2:
+ ++j; /* Fall thru */
+ case 0:
+ reg_data[j] = digit;
+ status = 1;
+ break;
+ case 1:
+ reg_data[j] = reg_data[j] * 16 + digit;
+ status = 2;
+ break;
+ }
+ }
+ if (status > 0)
+ ++j;
+ if (j > client_data->reg_len)
+ j = client_data->reg_len;
+ else if (j < client_data->reg_len) {
+ dev_err(client_data->dev, "Invalid argument");
+ return -EINVAL;
+ }
+ printk(KERN_INFO "Reg data read as");
+ for (i = 0; i < j; ++i)
+ printk(KERN_INFO "%d", reg_data[i]);
+
+ ret = SMI_CALL_API(write_reg)(
+ client_data->reg_sel,
+ reg_data, client_data->reg_len);
+ if (ret < 0) {
+ dev_err(client_data->dev, "Reg op failed");
+ return ret;
+ }
+
+ return count;
+}
+
+static ssize_t smi130_driver_version_show(struct device *dev
+ , struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_client_data *client_data = input_get_drvdata(input);
+ int ret;
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+
+ ret = snprintf(buf, 128, "Driver version: %s\n",
+ DRIVER_VERSION);
+
+ return ret;
+}
+static DEVICE_ATTR(chip_id, S_IRUGO,
+ smi130_chip_id_show, NULL);
+static DEVICE_ATTR(err_st, S_IRUGO,
+ smi130_err_st_show, NULL);
+static DEVICE_ATTR(sensor_time, S_IRUGO,
+ smi130_sensor_time_show, NULL);
+
+static DEVICE_ATTR(selftest, S_IRUGO | S_IWUSR,
+ smi130_selftest_show, smi130_selftest_store);
+static DEVICE_ATTR(fifo_flush, S_IRUGO | S_IWUSR,
+ NULL, smi130_fifo_flush_store);
+static DEVICE_ATTR(fifo_bytecount, S_IRUGO | S_IWUSR,
+ smi130_fifo_bytecount_show, smi130_fifo_bytecount_store);
+static DEVICE_ATTR(fifo_data_sel, S_IRUGO | S_IWUSR,
+ smi130_fifo_data_sel_show, smi130_fifo_data_sel_store);
+static DEVICE_ATTR(fifo_data_frame, S_IRUGO,
+ smi130_fifo_data_out_frame_show, NULL);
+
+static DEVICE_ATTR(fifo_watermark, S_IRUGO | S_IWUSR,
+ smi130_fifo_watermark_show, smi130_fifo_watermark_store);
+
+static DEVICE_ATTR(fifo_header_en, S_IRUGO | S_IWUSR,
+ smi130_fifo_header_en_show, smi130_fifo_header_en_store);
+static DEVICE_ATTR(fifo_time_en, S_IRUGO | S_IWUSR,
+ smi130_fifo_time_en_show, smi130_fifo_time_en_store);
+static DEVICE_ATTR(fifo_int_tag_en, S_IRUGO | S_IWUSR,
+ smi130_fifo_int_tag_en_show, smi130_fifo_int_tag_en_store);
+
+static DEVICE_ATTR(temperature, S_IRUGO,
+ smi130_temperature_show, NULL);
+static DEVICE_ATTR(place, S_IRUGO,
+ smi130_place_show, NULL);
+static DEVICE_ATTR(delay, S_IRUGO | S_IWUSR,
+ smi130_delay_show, smi130_delay_store);
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
+ smi130_enable_show, smi130_enable_store);
+static DEVICE_ATTR(acc_range, S_IRUGO | S_IWUSR,
+ smi130_acc_range_show, smi130_acc_range_store);
+static DEVICE_ATTR(acc_odr, S_IRUGO | S_IWUSR,
+ smi130_acc_odr_show, smi130_acc_odr_store);
+static DEVICE_ATTR(acc_op_mode, S_IRUGO | S_IWUSR,
+ smi130_acc_op_mode_show, smi130_acc_op_mode_store);
+static DEVICE_ATTR(acc_value, S_IRUGO,
+ smi130_acc_value_show, NULL);
+static DEVICE_ATTR(acc_fast_calibration_x, S_IRUGO | S_IWUSR,
+ smi130_acc_fast_calibration_x_show,
+ smi130_acc_fast_calibration_x_store);
+static DEVICE_ATTR(acc_fast_calibration_y, S_IRUGO | S_IWUSR,
+ smi130_acc_fast_calibration_y_show,
+ smi130_acc_fast_calibration_y_store);
+static DEVICE_ATTR(acc_fast_calibration_z, S_IRUGO | S_IWUSR,
+ smi130_acc_fast_calibration_z_show,
+ smi130_acc_fast_calibration_z_store);
+static DEVICE_ATTR(acc_offset_x, S_IRUGO | S_IWUSR,
+ smi130_acc_offset_x_show,
+ smi130_acc_offset_x_store);
+static DEVICE_ATTR(acc_offset_y, S_IRUGO | S_IWUSR,
+ smi130_acc_offset_y_show,
+ smi130_acc_offset_y_store);
+static DEVICE_ATTR(acc_offset_z, S_IRUGO | S_IWUSR,
+ smi130_acc_offset_z_show,
+ smi130_acc_offset_z_store);
+static DEVICE_ATTR(test, S_IRUGO,
+ smi130_test_show, NULL);
+static DEVICE_ATTR(stc_enable, S_IRUGO | S_IWUSR,
+ smi130_step_counter_enable_show,
+ smi130_step_counter_enable_store);
+static DEVICE_ATTR(stc_mode, S_IRUGO | S_IWUSR,
+ NULL, smi130_step_counter_mode_store);
+static DEVICE_ATTR(stc_clc, S_IRUGO | S_IWUSR,
+ NULL, smi130_step_counter_clc_store);
+static DEVICE_ATTR(stc_value, S_IRUGO,
+ smi130_step_counter_value_show, NULL);
+static DEVICE_ATTR(reg_sel, S_IRUGO | S_IWUSR,
+ smi130_show_reg_sel, smi130_store_reg_sel);
+static DEVICE_ATTR(reg_val, S_IRUGO | S_IWUSR,
+ smi130_show_reg_val, smi130_store_reg_val);
+static DEVICE_ATTR(driver_version, S_IRUGO,
+ smi130_driver_version_show, NULL);
+/* gyro part */
+static DEVICE_ATTR(gyro_op_mode, S_IRUGO | S_IWUSR,
+ smi130_gyro_op_mode_show, smi130_gyro_op_mode_store);
+static DEVICE_ATTR(gyro_value, S_IRUGO,
+ smi130_gyro_value_show, NULL);
+static DEVICE_ATTR(gyro_range, S_IRUGO | S_IWUSR,
+ smi130_gyro_range_show, smi130_gyro_range_store);
+static DEVICE_ATTR(gyro_odr, S_IRUGO | S_IWUSR,
+ smi130_gyro_odr_show, smi130_gyro_odr_store);
+static DEVICE_ATTR(gyro_fast_calibration_en, S_IRUGO | S_IWUSR,
+smi130_gyro_fast_calibration_en_show, smi130_gyro_fast_calibration_en_store);
+static DEVICE_ATTR(gyro_offset_x, S_IRUGO | S_IWUSR,
+smi130_gyro_offset_x_show, smi130_gyro_offset_x_store);
+static DEVICE_ATTR(gyro_offset_y, S_IRUGO | S_IWUSR,
+smi130_gyro_offset_y_show, smi130_gyro_offset_y_store);
+static DEVICE_ATTR(gyro_offset_z, S_IRUGO | S_IWUSR,
+smi130_gyro_offset_z_show, smi130_gyro_offset_z_store);
+
+#ifdef SMI130_MAG_INTERFACE_SUPPORT
+static DEVICE_ATTR(mag_op_mode, S_IRUGO | S_IWUSR,
+ smi130_mag_op_mode_show, smi130_mag_op_mode_store);
+static DEVICE_ATTR(mag_odr, S_IRUGO | S_IWUSR,
+ smi130_mag_odr_show, smi130_mag_odr_store);
+static DEVICE_ATTR(mag_i2c_addr, S_IRUGO | S_IWUSR,
+ smi130_mag_i2c_address_show, smi130_mag_i2c_address_store);
+static DEVICE_ATTR(mag_value, S_IRUGO,
+ smi130_mag_value_show, NULL);
+static DEVICE_ATTR(mag_offset, S_IRUGO | S_IWUSR,
+ smi130_mag_offset_show, smi130_mag_offset_store);
+static DEVICE_ATTR(mag_chip_id, S_IRUGO,
+ smi130_mag_chip_id_show, NULL);
+static DEVICE_ATTR(mag_chip_name, S_IRUGO,
+ smi130_mag_chip_name_show, NULL);
+static DEVICE_ATTR(mag_compensate, S_IRUGO | S_IWUSR,
+ smi130_mag_compensate_xyz_show,
+ smi130_mag_compensate_xyz_store);
+#endif
+
+
+#if defined(SMI130_ENABLE_INT1) || defined(SMI130_ENABLE_INT2)
+static DEVICE_ATTR(enable_int, S_IRUGO | S_IWUSR,
+ NULL, smi_enable_int_store);
+static DEVICE_ATTR(anymot_duration, S_IRUGO | S_IWUSR,
+ smi130_anymot_duration_show, smi130_anymot_duration_store);
+static DEVICE_ATTR(anymot_threshold, S_IRUGO | S_IWUSR,
+ smi130_anymot_threshold_show, smi130_anymot_threshold_store);
+static DEVICE_ATTR(std_stu, S_IRUGO,
+ smi130_step_detector_status_show, NULL);
+static DEVICE_ATTR(std_en, S_IRUGO | S_IWUSR,
+ smi130_step_detector_enable_show,
+ smi130_step_detector_enable_store);
+static DEVICE_ATTR(sig_en, S_IRUGO | S_IWUSR,
+ smi130_signification_motion_enable_show,
+ smi130_signification_motion_enable_store);
+
+#endif
+
+
+
+static DEVICE_ATTR(smi_value, S_IRUGO,
+ smi130_smi_value_show, NULL);
+
+
+static struct attribute *smi130_attributes[] = {
+ &dev_attr_chip_id.attr,
+ &dev_attr_err_st.attr,
+ &dev_attr_sensor_time.attr,
+ &dev_attr_selftest.attr,
+ &dev_attr_driver_version.attr,
+ &dev_attr_test.attr,
+ &dev_attr_fifo_flush.attr,
+ &dev_attr_fifo_header_en.attr,
+ &dev_attr_fifo_time_en.attr,
+ &dev_attr_fifo_int_tag_en.attr,
+ &dev_attr_fifo_bytecount.attr,
+ &dev_attr_fifo_data_sel.attr,
+ &dev_attr_fifo_data_frame.attr,
+
+ &dev_attr_fifo_watermark.attr,
+
+ &dev_attr_enable.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_temperature.attr,
+ &dev_attr_place.attr,
+
+ &dev_attr_acc_range.attr,
+ &dev_attr_acc_odr.attr,
+ &dev_attr_acc_op_mode.attr,
+ &dev_attr_acc_value.attr,
+
+ &dev_attr_acc_fast_calibration_x.attr,
+ &dev_attr_acc_fast_calibration_y.attr,
+ &dev_attr_acc_fast_calibration_z.attr,
+ &dev_attr_acc_offset_x.attr,
+ &dev_attr_acc_offset_y.attr,
+ &dev_attr_acc_offset_z.attr,
+
+ &dev_attr_stc_enable.attr,
+ &dev_attr_stc_mode.attr,
+ &dev_attr_stc_clc.attr,
+ &dev_attr_stc_value.attr,
+
+ &dev_attr_gyro_op_mode.attr,
+ &dev_attr_gyro_value.attr,
+ &dev_attr_gyro_range.attr,
+ &dev_attr_gyro_odr.attr,
+ &dev_attr_gyro_fast_calibration_en.attr,
+ &dev_attr_gyro_offset_x.attr,
+ &dev_attr_gyro_offset_y.attr,
+ &dev_attr_gyro_offset_z.attr,
+
+#ifdef SMI130_MAG_INTERFACE_SUPPORT
+ &dev_attr_mag_chip_id.attr,
+ &dev_attr_mag_op_mode.attr,
+ &dev_attr_mag_odr.attr,
+ &dev_attr_mag_i2c_addr.attr,
+ &dev_attr_mag_chip_name.attr,
+ &dev_attr_mag_value.attr,
+ &dev_attr_mag_offset.attr,
+ &dev_attr_mag_compensate.attr,
+#endif
+
+#if defined(SMI130_ENABLE_INT1) || defined(SMI130_ENABLE_INT2)
+ &dev_attr_enable_int.attr,
+
+ &dev_attr_anymot_duration.attr,
+ &dev_attr_anymot_threshold.attr,
+ &dev_attr_std_stu.attr,
+ &dev_attr_std_en.attr,
+ &dev_attr_sig_en.attr,
+
+#endif
+ &dev_attr_reg_sel.attr,
+ &dev_attr_reg_val.attr,
+ &dev_attr_smi_value.attr,
+ NULL
+};
+
+static struct attribute_group smi130_attribute_group = {
+ .attrs = smi130_attributes
+};
+
+#if defined(SMI130_ENABLE_INT1) || defined(SMI130_ENABLE_INT2)
+static void smi_slope_interrupt_handle(struct smi_client_data *client_data)
+{
+ /* anym_first[0..2]: x, y, z */
+ u8 anym_first[3] = {0};
+ u8 status2;
+ u8 anym_sign;
+ u8 i = 0;
+
+ client_data->device.bus_read(client_data->device.dev_addr,
+ SMI130_USER_INTR_STAT_2_ADDR, &status2, 1);
+ anym_first[0] = SMI130_GET_BITSLICE(status2,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_X);
+ anym_first[1] = SMI130_GET_BITSLICE(status2,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Y);
+ anym_first[2] = SMI130_GET_BITSLICE(status2,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_FIRST_Z);
+ anym_sign = SMI130_GET_BITSLICE(status2,
+ SMI130_USER_INTR_STAT_2_ANY_MOTION_SIGN);
+
+ for (i = 0; i < 3; i++) {
+ if (anym_first[i]) {
+ /*1: negative*/
+ if (anym_sign)
+ dev_notice(client_data->dev,
+ "Anymotion interrupt happend!"
+ "%s axis, negative sign\n", smi_axis_name[i]);
+ else
+ dev_notice(client_data->dev,
+ "Anymotion interrupt happend!"
+ "%s axis, postive sign\n", smi_axis_name[i]);
+ }
+ }
+
+
+}
+
+static void smi_fifo_watermark_interrupt_handle
+ (struct smi_client_data *client_data)
+{
+ int err = 0;
+ unsigned int fifo_len0 = 0;
+ unsigned int fifo_frmbytes_ext = 0;
+ unsigned char *fifo_data = NULL;
+ fifo_data = kzalloc(FIFO_DATA_BUFSIZE, GFP_KERNEL);
+ /*TO DO*/
+ if (NULL == fifo_data) {
+ dev_err(client_data->dev, "no memory available");
+ err = -ENOMEM;
+ }
+ smi_fifo_frame_bytes_extend_calc(client_data, &fifo_frmbytes_ext);
+
+ if (client_data->pw.acc_pm == 2 && client_data->pw.gyro_pm == 2
+ && client_data->pw.mag_pm == 2)
+ printk(KERN_INFO "pw_acc: %d, pw_gyro: %d\n",
+ client_data->pw.acc_pm, client_data->pw.gyro_pm);
+ if (!client_data->fifo_data_sel)
+ printk(KERN_INFO "no selsect sensor fifo, fifo_data_sel:%d\n",
+ client_data->fifo_data_sel);
+
+ err = SMI_CALL_API(fifo_length)(&fifo_len0);
+ client_data->fifo_bytecount = fifo_len0;
+
+ if (client_data->fifo_bytecount == 0 || err)
+ return;
+
+ if (client_data->fifo_bytecount + fifo_frmbytes_ext > FIFO_DATA_BUFSIZE)
+ client_data->fifo_bytecount = FIFO_DATA_BUFSIZE;
+ /* need give attention for the time of burst read*/
+ if (!err) {
+ err = smi_burst_read_wrapper(client_data->device.dev_addr,
+ SMI130_USER_FIFO_DATA__REG, fifo_data,
+ client_data->fifo_bytecount + fifo_frmbytes_ext);
+ } else
+ dev_err(client_data->dev, "read fifo leght err");
+
+ if (err)
+ dev_err(client_data->dev, "brust read fifo err\n");
+ /*err = smi_fifo_analysis_handle(client_data, fifo_data,
+ client_data->fifo_bytecount + 20, fifo_out_data);*/
+ if (fifo_data != NULL) {
+ kfree(fifo_data);
+ fifo_data = NULL;
+ }
+
+}
+static void smi_data_ready_interrupt_handle(
+ struct smi_client_data *client_data, uint8_t status)
+{
+ uint8_t data12[12] = {0};
+ struct smi130_accel_t accel;
+ struct smi130_gyro_t gyro;
+ struct timespec ts;
+ client_data->device.bus_read(client_data->device.dev_addr,
+ SMI130_USER_DATA_8_ADDR, data12, 12);
+ if (status & 0x80)
+ {
+ /*report acc data*/
+ /* Data X */
+ accel.x = (s16)((((s32)((s8)data12[7])) << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[6]));
+ /* Data Y */
+ accel.y = (s16)((((s32)((s8)data12[9])) << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[8]));
+ /* Data Z */
+ accel.z = (s16)((((s32)((s8)data12[11]))<< SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[10]));
+ ts = ns_to_timespec(client_data->timestamp);
+ input_event(client_data->input, EV_MSC, 6, ts.tv_sec);
+ input_event(client_data->input, EV_MSC, 6, ts.tv_nsec);
+ input_event(client_data->input, EV_MSC, MSC_GESTURE, accel.x);
+ input_event(client_data->input, EV_MSC, MSC_RAW, accel.y);
+ input_event(client_data->input, EV_MSC, MSC_SCAN, accel.z);
+ input_sync(client_data->input);
+ }
+ if (status & 0x40)
+ {
+ /*report gyro data*/
+ /* Data X */
+ gyro.x = (s16)((((s32)((s8)data12[1])) << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[0]));
+ /* Data Y */
+ gyro.y = (s16)((((s32)((s8)data12[3])) << SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[2]));
+ /* Data Z */
+ gyro.z = (s16)((((s32)((s8)data12[5]))<< SMI130_SHIFT_BIT_POSITION_BY_08_BITS) | (data12[4]));
+ ts = ns_to_timespec(client_data->timestamp);
+ input_event(client_data->gyro_input, EV_MSC, 6, ts.tv_sec);
+ input_event(client_data->gyro_input, EV_MSC, 6, ts.tv_nsec);
+ input_event(client_data->gyro_input, EV_MSC, MSC_GESTURE, gyro.x);
+ input_event(client_data->gyro_input, EV_MSC, MSC_RAW, gyro.y);
+ input_event(client_data->gyro_input, EV_MSC, MSC_SCAN, gyro.z);
+ input_sync(client_data->gyro_input);
+ }
+}
+
+static void smi_signification_motion_interrupt_handle(
+ struct smi_client_data *client_data)
+{
+ printk(KERN_INFO "smi_signification_motion_interrupt_handle\n");
+ input_event(client_data->input, EV_MSC, INPUT_EVENT_SGM, 1);
+/*input_report_rel(client_data->input,INPUT_EVENT_SGM,1);*/
+ input_sync(client_data->input);
+ smi130_set_command_register(CMD_RESET_INT_ENGINE);
+
+}
+static void smi_stepdetector_interrupt_handle(
+ struct smi_client_data *client_data)
+{
+ u8 current_step_dector_st = 0;
+ client_data->pedo_data.wkar_step_detector_status++;
+ current_step_dector_st =
+ client_data->pedo_data.wkar_step_detector_status;
+ client_data->std = ((current_step_dector_st == 1) ? 0 : 1);
+
+ input_event(client_data->input, EV_MSC, INPUT_EVENT_STEP_DETECTOR, 1);
+ input_sync(client_data->input);
+}
+
+static void smi_irq_work_func(struct work_struct *work)
+{
+ struct smi_client_data *client_data =
+ container_of((struct work_struct *)work,
+ struct smi_client_data, irq_work);
+
+ unsigned char int_status[4] = {0, 0, 0, 0};
+ uint8_t status = 0;
+
+ //client_data->device.bus_read(client_data->device.dev_addr,
+ // SMI130_USER_INTR_STAT_0_ADDR, int_status, 4);
+ client_data->device.bus_read(client_data->device.dev_addr,
+ SMI130_USER_STAT_ADDR, &status, 1);
+ printk("status = 0x%x", status);
+ if (SMI130_GET_BITSLICE(int_status[0],
+ SMI130_USER_INTR_STAT_0_ANY_MOTION))
+ smi_slope_interrupt_handle(client_data);
+
+ if (SMI130_GET_BITSLICE(int_status[0],
+ SMI130_USER_INTR_STAT_0_STEP_INTR))
+ smi_stepdetector_interrupt_handle(client_data);
+ if (SMI130_GET_BITSLICE(int_status[1],
+ SMI130_USER_INTR_STAT_1_FIFO_WM_INTR))
+ smi_fifo_watermark_interrupt_handle(client_data);
+ if ((status & 0x80) || (status & 0x40))
+ smi_data_ready_interrupt_handle(client_data, status);
+ /* Clear ALL inputerrupt status after handler sig mition*/
+ /* Put this commads intot the last one*/
+ if (SMI130_GET_BITSLICE(int_status[0],
+ SMI130_USER_INTR_STAT_0_SIGNIFICANT_INTR))
+ smi_signification_motion_interrupt_handle(client_data);
+
+}
+
+static void smi130_delay_sigmo_work_func(struct work_struct *work)
+{
+ struct smi_client_data *client_data =
+ container_of(work, struct smi_client_data,
+ delay_work_sig.work);
+ unsigned char int_status[4] = {0, 0, 0, 0};
+
+ client_data->device.bus_read(client_data->device.dev_addr,
+ SMI130_USER_INTR_STAT_0_ADDR, int_status, 4);
+ if (SMI130_GET_BITSLICE(int_status[0],
+ SMI130_USER_INTR_STAT_0_SIGNIFICANT_INTR))
+ smi_signification_motion_interrupt_handle(client_data);
+}
+
+static irqreturn_t smi_irq_handler(int irq, void *handle)
+{
+ struct smi_client_data *client_data = handle;
+ int in_suspend_copy;
+ in_suspend_copy = atomic_read(&client_data->in_suspend);
+
+ if (client_data == NULL)
+ return IRQ_HANDLED;
+ if (client_data->dev == NULL)
+ return IRQ_HANDLED;
+ /*this only deal with SIG_motion CTS test*/
+ if ((in_suspend_copy == 1) &&
+ (client_data->sig_flag == 1)) {
+ /*wake_lock_timeout(&client_data->wakelock, HZ);*/
+ schedule_delayed_work(&client_data->delay_work_sig,
+ msecs_to_jiffies(50));
+ }
+ schedule_work(&client_data->irq_work);
+
+ return IRQ_HANDLED;
+}
+#endif /* defined(SMI_ENABLE_INT1)||defined(SMI_ENABLE_INT2) */
+
+static int smi_restore_hw_cfg(struct smi_client_data *client)
+{
+ int err = 0;
+
+ if ((client->fifo_data_sel) & (1 << SMI_ACC_SENSOR)) {
+ err += SMI_CALL_API(set_accel_range)(client->range.acc_range);
+ err += SMI_CALL_API(set_accel_output_data_rate)
+ (client->odr.acc_odr);
+ err += SMI_CALL_API(set_fifo_accel_enable)(1);
+ }
+ if ((client->fifo_data_sel) & (1 << SMI_GYRO_SENSOR)) {
+ err += SMI_CALL_API(set_gyro_range)(client->range.gyro_range);
+ err += SMI_CALL_API(set_gyro_output_data_rate)
+ (client->odr.gyro_odr);
+ err += SMI_CALL_API(set_fifo_gyro_enable)(1);
+ }
+ if ((client->fifo_data_sel) & (1 << SMI_MAG_SENSOR)) {
+ err += SMI_CALL_API(set_mag_output_data_rate)
+ (client->odr.mag_odr);
+ err += SMI_CALL_API(set_fifo_mag_enable)(1);
+ }
+ err += SMI_CALL_API(set_command_register)(CMD_CLR_FIFO_DATA);
+
+ mutex_lock(&client->mutex_op_mode);
+ if (client->pw.acc_pm != SMI_ACC_PM_SUSPEND) {
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_acc_arr[SMI_ACC_PM_NORMAL]);
+ smi_delay(3);
+ }
+ mutex_unlock(&client->mutex_op_mode);
+
+ mutex_lock(&client->mutex_op_mode);
+ if (client->pw.gyro_pm != SMI_GYRO_PM_SUSPEND) {
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_NORMAL]);
+ smi_delay(3);
+ }
+ mutex_unlock(&client->mutex_op_mode);
+
+ mutex_lock(&client->mutex_op_mode);
+
+ if (client->pw.mag_pm != SMI_MAG_PM_SUSPEND) {
+#ifdef SMI130_AKM09912_SUPPORT
+ err += smi130_set_bosch_akm_and_secondary_if_powermode
+ (SMI130_MAG_FORCE_MODE);
+#else
+ err += smi130_set_bmm150_mag_and_secondary_if_power_mode
+ (SMI130_MAG_FORCE_MODE);
+#endif
+ smi_delay(3);
+ }
+ mutex_unlock(&client->mutex_op_mode);
+
+ return err;
+}
+
+#if defined(CONFIG_USE_QUALCOMM_HAL)
+static void smi130_accel_work_fn(struct work_struct *work)
+{
+ struct smi_client_data *sensor;
+ ktime_t timestamp;
+ struct smi130_accel_t data;
+ int err;
+ sensor = container_of((struct delayed_work *)work,
+ struct smi_client_data, accel_poll_work);
+ timestamp = ktime_get();
+ err = SMI_CALL_API(read_accel_xyz)(&data);
+ if (err)
+ dev_err(sensor->dev, "read data err");
+ input_report_abs(sensor->input, ABS_X,
+ (data.x));
+ input_report_abs(sensor->input, ABS_Y,
+ (data.y));
+ input_report_abs(sensor->input, ABS_Z,
+ (data.z));
+ input_event(sensor->input,
+ EV_SYN, SYN_TIME_SEC,
+ ktime_to_timespec(timestamp).tv_sec);
+ input_event(sensor->input, EV_SYN,
+ SYN_TIME_NSEC,
+ ktime_to_timespec(timestamp).tv_nsec);
+ input_sync(sensor->input);
+ if (atomic_read(&sensor->accel_en))
+ queue_delayed_work(sensor->data_wq,
+ &sensor->accel_poll_work,
+ msecs_to_jiffies(sensor->accel_poll_ms));
+}
+static void smi130_gyro_work_fn(struct work_struct *work)
+{
+ struct smi_client_data *sensor;
+ ktime_t timestamp;
+ struct smi130_gyro_t data;
+ int err;
+ sensor = container_of((struct delayed_work *)work,
+ struct smi_client_data, gyro_poll_work);
+ timestamp = ktime_get();
+ err = SMI_CALL_API(read_gyro_xyz)(&data);
+ if (err)
+ dev_err(sensor->dev, "read data err");
+ input_report_abs(sensor->gyro_input, ABS_RX,
+ (data.x));
+ input_report_abs(sensor->gyro_input, ABS_RY,
+ (data.y));
+ input_report_abs(sensor->gyro_input, ABS_RZ,
+ (data.z));
+ input_event(sensor->gyro_input,
+ EV_SYN, SYN_TIME_SEC,
+ ktime_to_timespec(timestamp).tv_sec);
+ input_event(sensor->gyro_input, EV_SYN,
+ SYN_TIME_NSEC,
+ ktime_to_timespec(timestamp).tv_nsec);
+ input_sync(sensor->gyro_input);
+ if (atomic_read(&sensor->gyro_en))
+ queue_delayed_work(sensor->data_wq,
+ &sensor->gyro_poll_work,
+ msecs_to_jiffies(sensor->gyro_poll_ms));
+}
+static int smi130_set_gyro_op_mode(struct smi_client_data *client_data,
+ unsigned long op_mode)
+{
+ int err = 0;
+ mutex_lock(&client_data->mutex_op_mode);
+ if (op_mode < SMI_GYRO_PM_MAX) {
+ switch (op_mode) {
+ case SMI_GYRO_PM_NORMAL:
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_NORMAL]);
+ client_data->pw.gyro_pm = SMI_GYRO_PM_NORMAL;
+ smi_delay(60);
+ break;
+ case SMI_GYRO_PM_FAST_START:
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_FAST_START]);
+ client_data->pw.gyro_pm = SMI_GYRO_PM_FAST_START;
+ smi_delay(60);
+ break;
+ case SMI_GYRO_PM_SUSPEND:
+ err = SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_SUSPEND]);
+ client_data->pw.gyro_pm = SMI_GYRO_PM_SUSPEND;
+ smi_delay(60);
+ break;
+ default:
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ } else {
+ mutex_unlock(&client_data->mutex_op_mode);
+ return -EINVAL;
+ }
+ mutex_unlock(&client_data->mutex_op_mode);
+ return err;
+}
+static int smi130_accel_set_enable(
+ struct smi_client_data *client_data, bool enable)
+{
+ int ret = 0;
+ dev_notice(client_data->dev,
+ "smi130_accel_set_enable enable=%d\n", enable);
+ if (enable) {
+ ret = smi130_set_acc_op_mode(client_data, 0);
+ if (ret) {
+ dev_err(client_data->dev,
+ "Fail to enable accel engine ret=%d\n", ret);
+ ret = -EBUSY;
+ goto exit;
+ }
+ queue_delayed_work(client_data->data_wq,
+ &client_data->accel_poll_work,
+ msecs_to_jiffies(client_data->accel_poll_ms));
+ atomic_set(&client_data->accel_en, 1);
+ } else {
+ atomic_set(&client_data->accel_en, 0);
+ cancel_delayed_work_sync(&client_data->accel_poll_work);
+ ret = smi130_set_acc_op_mode(client_data, 2);
+ if (ret) {
+ dev_err(client_data->dev,
+ "Fail to disable accel engine ret=%d\n", ret);
+ ret = -EBUSY;
+ goto exit;
+ }
+ }
+exit:
+ return ret;
+}
+static int smi130_accel_set_poll_delay(struct smi_client_data *client_data,
+ unsigned long delay)
+{
+ dev_info(client_data->dev,
+ "smi130_accel_set_poll_delay delay_ms=%ld\n", delay);
+ if (delay < SMI130_ACCEL_MIN_POLL_INTERVAL_MS)
+ delay = SMI130_ACCEL_MIN_POLL_INTERVAL_MS;
+ if (delay > SMI130_ACCEL_MAX_POLL_INTERVAL_MS)
+ delay = SMI130_ACCEL_MAX_POLL_INTERVAL_MS;
+ client_data->accel_poll_ms = delay;
+ if (!atomic_read(&client_data->accel_en))
+ goto exit;
+ cancel_delayed_work_sync(&client_data->accel_poll_work);
+ queue_delayed_work(client_data->data_wq,
+ &client_data->accel_poll_work,
+ msecs_to_jiffies(client_data->accel_poll_ms));
+exit:
+ return 0;
+}
+static int smi130_gyro_set_enable(
+ struct smi_client_data *client_data, bool enable)
+{
+ int ret = 0;
+ dev_notice(client_data->dev,
+ "smi130_gyro_set_enable enable=%d\n", enable);
+ if (enable) {
+ ret = smi130_set_gyro_op_mode(client_data, 0);
+ if (ret) {
+ dev_err(client_data->dev,
+ "Fail to enable gyro engine ret=%d\n", ret);
+ ret = -EBUSY;
+ goto exit;
+ }
+ queue_delayed_work(client_data->data_wq,
+ &client_data->gyro_poll_work,
+ msecs_to_jiffies(client_data->gyro_poll_ms));
+ atomic_set(&client_data->gyro_en, 1);
+ } else {
+ atomic_set(&client_data->gyro_en, 0);
+ cancel_delayed_work_sync(&client_data->gyro_poll_work);
+ ret = smi130_set_gyro_op_mode(client_data, 2);
+ if (ret) {
+ dev_err(client_data->dev,
+ "Fail to disable accel engine ret=%d\n", ret);
+ ret = -EBUSY;
+ goto exit;
+ }
+ }
+exit:
+ return ret;
+}
+static int smi130_gyro_set_poll_delay(struct smi_client_data *client_data,
+ unsigned long delay)
+{
+ dev_info(client_data->dev,
+ "smi130_accel_set_poll_delay delay_ms=%ld\n", delay);
+ if (delay < SMI130_GYRO_MIN_POLL_INTERVAL_MS)
+ delay = SMI130_GYRO_MIN_POLL_INTERVAL_MS;
+ if (delay > SMI130_GYRO_MAX_POLL_INTERVAL_MS)
+ delay = SMI130_GYRO_MAX_POLL_INTERVAL_MS;
+ client_data->gyro_poll_ms = delay;
+ if (!atomic_read(&client_data->gyro_en))
+ goto exit;
+ cancel_delayed_work_sync(&client_data->gyro_poll_work);
+ queue_delayed_work(client_data->data_wq,
+ &client_data->gyro_poll_work,
+ msecs_to_jiffies(client_data->gyro_poll_ms));
+exit:
+ return 0;
+}
+static int smi130_accel_cdev_enable(struct sensors_classdev *sensors_cdev,
+ unsigned int enable)
+{
+ struct smi_client_data *sensor = container_of(sensors_cdev,
+ struct smi_client_data, accel_cdev);
+ return smi130_accel_set_enable(sensor, enable);
+}
+static int smi130_accel_cdev_poll_delay(struct sensors_classdev *sensors_cdev,
+ unsigned int delay_ms)
+{
+ struct smi_client_data *sensor = container_of(sensors_cdev,
+ struct smi_client_data, accel_cdev);
+
+ return smi130_accel_set_poll_delay(sensor, delay_ms);
+}
+
+static int smi130_gyro_cdev_enable(struct sensors_classdev *sensors_cdev,
+ unsigned int enable)
+{
+ struct smi_client_data *sensor = container_of(sensors_cdev,
+ struct smi_client_data, gyro_cdev);
+
+ return smi130_gyro_set_enable(sensor, enable);
+}
+
+static int smi130_gyro_cdev_poll_delay(struct sensors_classdev *sensors_cdev,
+ unsigned int delay_ms)
+{
+ struct smi_client_data *sensor = container_of(sensors_cdev,
+ struct smi_client_data, gyro_cdev);
+
+ return smi130_gyro_set_poll_delay(sensor, delay_ms);
+}
+#endif
+
+int smi_probe(struct smi_client_data *client_data, struct device *dev)
+{
+ int err = 0;
+#ifdef SMI130_MAG_INTERFACE_SUPPORT
+ u8 mag_dev_addr;
+ u8 mag_urst_len;
+ u8 mag_op_mode;
+#endif
+ /* check chip id */
+ err = smi_check_chip_id(client_data);
+ if (err)
+ goto exit_err_clean;
+
+ dev_set_drvdata(dev, client_data);
+ client_data->dev = dev;
+
+ mutex_init(&client_data->mutex_enable);
+ mutex_init(&client_data->mutex_op_mode);
+
+ /* input device init */
+ err = smi_input_init(client_data);
+ if (err < 0)
+ goto exit_err_clean;
+
+ /* sysfs node creation */
+ err = sysfs_create_group(&client_data->input->dev.kobj,
+ &smi130_attribute_group);
+
+ if (err < 0)
+ goto exit_err_sysfs;
+
+ if (NULL != dev->platform_data) {
+ client_data->bosch_pd = kzalloc(sizeof(*client_data->bosch_pd),
+ GFP_KERNEL);
+
+ if (NULL != client_data->bosch_pd) {
+ memcpy(client_data->bosch_pd, dev->platform_data,
+ sizeof(*client_data->bosch_pd));
+ dev_notice(dev, "%s sensor driver set place: p%d\n",
+ client_data->bosch_pd->name,
+ client_data->bosch_pd->place);
+ }
+ }
+
+ if (NULL != client_data->bosch_pd) {
+ memcpy(client_data->bosch_pd, dev->platform_data,
+ sizeof(*client_data->bosch_pd));
+ dev_notice(dev, "%s sensor driver set place: p%d\n",
+ client_data->bosch_pd->name,
+ client_data->bosch_pd->place);
+ }
+
+
+ /* workqueue init */
+ INIT_DELAYED_WORK(&client_data->work, smi_work_func);
+ atomic_set(&client_data->delay, SMI_DELAY_DEFAULT);
+ atomic_set(&client_data->wkqueue_en, 0);
+
+ /* h/w init */
+ client_data->device.delay_msec = smi_delay;
+ err = SMI_CALL_API(init)(&client_data->device);
+
+ smi_dump_reg(client_data);
+
+ /*power on detected*/
+ /*or softrest(cmd 0xB6) */
+ /*fatal err check*/
+ /*soft reset*/
+ err += SMI_CALL_API(set_command_register)(CMD_RESET_USER_REG);
+ smi_delay(3);
+ if (err)
+ dev_err(dev, "Failed soft reset, er=%d", err);
+ /*usr data config page*/
+ err += SMI_CALL_API(set_target_page)(USER_DAT_CFG_PAGE);
+ if (err)
+ dev_err(dev, "Failed cffg page, er=%d", err);
+ err += smi_get_err_status(client_data);
+ if (err) {
+ dev_err(dev, "Failed to smi16x init!err_st=0x%x\n",
+ client_data->err_st.err_st_all);
+ goto exit_err_sysfs;
+ }
+
+#ifdef SMI130_MAG_INTERFACE_SUPPORT
+ err += smi130_set_command_register(MAG_MODE_NORMAL);
+ smi_delay(2);
+ err += smi130_get_mag_power_mode_stat(&mag_op_mode);
+ smi_delay(2);
+ err += SMI_CALL_API(get_i2c_device_addr)(&mag_dev_addr);
+ smi_delay(2);
+#if defined(SMI130_AKM09912_SUPPORT)
+ err += SMI_CALL_API(set_i2c_device_addr)(SMI130_AKM09912_I2C_ADDRESS);
+ smi130_bosch_akm_mag_interface_init(SMI130_AKM09912_I2C_ADDRESS);
+#else
+ err += SMI_CALL_API(set_i2c_device_addr)(
+ SMI130_AUX_BMM150_I2C_ADDRESS);
+ smi130_bmm150_mag_interface_init();
+#endif
+
+ err += smi130_set_mag_burst(3);
+ err += smi130_get_mag_burst(&mag_urst_len);
+ if (err)
+ dev_err(client_data->dev, "Failed cffg mag, er=%d", err);
+ dev_info(client_data->dev,
+ "SMI130 mag_urst_len:%d, mag_add:0x%x, mag_op_mode:%d\n",
+ mag_urst_len, mag_dev_addr, mag_op_mode);
+#endif
+ if (err < 0)
+ goto exit_err_sysfs;
+
+
+#if defined(SMI130_ENABLE_INT1) || defined(SMI130_ENABLE_INT2)
+ /*wake_lock_init(&client_data->wakelock,
+ WAKE_LOCK_SUSPEND, "smi130");*/
+ client_data->gpio_pin = of_get_named_gpio_flags(dev->of_node,
+ "smi,gpio_irq", 0, NULL);
+ dev_info(client_data->dev, "SMI130 qpio number:%d\n",
+ client_data->gpio_pin);
+ err += gpio_request_one(client_data->gpio_pin,
+ GPIOF_IN, "smi130_int");
+ err += gpio_direction_input(client_data->gpio_pin);
+ client_data->IRQ = gpio_to_irq(client_data->gpio_pin);
+ if (err) {
+ dev_err(client_data->dev,
+ "can not request gpio to irq number\n");
+ client_data->gpio_pin = 0;
+ }
+ INIT_DELAYED_WORK(&client_data->delay_work_sig,
+ smi130_delay_sigmo_work_func);
+#ifdef SMI130_ENABLE_INT1
+ /* maps interrupt to INT1/InT2 pin */
+ SMI_CALL_API(set_intr_any_motion)(SMI_INT0, ENABLE);
+ SMI_CALL_API(set_intr_fifo_wm)(SMI_INT0, ENABLE);
+ SMI_CALL_API(set_intr_data_rdy)(SMI_INT0, ENABLE);
+
+ /*Set interrupt trige level way */
+ SMI_CALL_API(set_intr_edge_ctrl)(SMI_INT0, SMI_INT_LEVEL);
+ smi130_set_intr_level(SMI_INT0, 1);
+ /*set interrupt latch temporary, 5 ms*/
+ /*smi130_set_latch_int(5);*/
+
+ SMI_CALL_API(set_output_enable)(
+ SMI130_INTR1_OUTPUT_ENABLE, ENABLE);
+ sigmotion_init_interrupts(SMI130_MAP_INTR1);
+ SMI_CALL_API(map_step_detector_intr)(SMI130_MAP_INTR1);
+ /*close step_detector in init function*/
+ SMI_CALL_API(set_step_detector_enable)(0);
+#endif
+
+#ifdef SMI130_ENABLE_INT2
+ /* maps interrupt to INT1/InT2 pin */
+ SMI_CALL_API(set_intr_any_motion)(SMI_INT1, ENABLE);
+ SMI_CALL_API(set_intr_fifo_wm)(SMI_INT1, ENABLE);
+ SMI_CALL_API(set_intr_data_rdy)(SMI_INT1, ENABLE);
+
+ /*Set interrupt trige level way */
+ SMI_CALL_API(set_intr_edge_ctrl)(SMI_INT1, SMI_INT_LEVEL);
+ smi130_set_intr_level(SMI_INT1, 1);
+ /*set interrupt latch temporary, 5 ms*/
+ /*smi130_set_latch_int(5);*/
+
+ SMI_CALL_API(set_output_enable)(
+ SMI130_INTR2_OUTPUT_ENABLE, ENABLE);
+ sigmotion_init_interrupts(SMI130_MAP_INTR2);
+ SMI_CALL_API(map_step_detector_intr)(SMI130_MAP_INTR2);
+ /*close step_detector in init function*/
+ SMI_CALL_API(set_step_detector_enable)(0);
+#endif
+ err = request_irq(client_data->IRQ, smi_irq_handler,
+ IRQF_TRIGGER_RISING, "smi130", client_data);
+ if (err)
+ dev_err(client_data->dev, "could not request irq\n");
+
+ INIT_WORK(&client_data->irq_work, smi_irq_work_func);
+#endif
+
+ client_data->selftest = 0;
+
+ client_data->fifo_data_sel = 0;
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ SMI_CALL_API(set_accel_output_data_rate)(9);/*defalut odr 200HZ*/
+ SMI_CALL_API(set_gyro_output_data_rate)(9);/*defalut odr 200HZ*/
+ #endif
+ SMI_CALL_API(get_accel_output_data_rate)(&client_data->odr.acc_odr);
+ SMI_CALL_API(get_gyro_output_data_rate)(&client_data->odr.gyro_odr);
+ SMI_CALL_API(get_mag_output_data_rate)(&client_data->odr.mag_odr);
+ SMI_CALL_API(set_fifo_time_enable)(1);
+ SMI_CALL_API(get_accel_range)(&client_data->range.acc_range);
+ SMI_CALL_API(get_gyro_range)(&client_data->range.gyro_range);
+ /* now it's power on which is considered as resuming from suspend */
+
+ /* gyro input device init */
+ err = smi_gyro_input_init(client_data);
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ /* gyro input device init */
+ err = smi_gyro_input_init(client_data);
+ if (err < 0)
+ goto exit_err_clean;
+ client_data->accel_poll_ms = SMI130_ACCEL_DEFAULT_POLL_INTERVAL_MS;
+ client_data->gyro_poll_ms = SMI130_GYRO_DEFAULT_POLL_INTERVAL_MS;
+ client_data->data_wq = create_freezable_workqueue("smi130_data_work");
+ if (!client_data->data_wq) {
+ dev_err(dev, "Cannot create workqueue!\n");
+ goto exit_err_clean;
+ }
+ INIT_DELAYED_WORK(&client_data->accel_poll_work,
+ smi130_accel_work_fn);
+ client_data->accel_cdev = smi130_accel_cdev;
+ client_data->accel_cdev.delay_msec = client_data->accel_poll_ms;
+ client_data->accel_cdev.sensors_enable = smi130_accel_cdev_enable;
+ client_data->accel_cdev.sensors_poll_delay =
+ smi130_accel_cdev_poll_delay;
+ err = sensors_classdev_register(dev, &client_data->accel_cdev);
+ if (err) {
+ dev_err(dev,
+ "create accel class device file failed!\n");
+ goto exit_err_clean;
+ }
+ INIT_DELAYED_WORK(&client_data->gyro_poll_work, smi130_gyro_work_fn);
+ client_data->gyro_cdev = smi130_gyro_cdev;
+ client_data->gyro_cdev.delay_msec = client_data->gyro_poll_ms;
+ client_data->gyro_cdev.sensors_enable = smi130_gyro_cdev_enable;
+ client_data->gyro_cdev.sensors_poll_delay = smi130_gyro_cdev_poll_delay;
+ err = sensors_classdev_register(dev, &client_data->gyro_cdev);
+ if (err) {
+ dev_err(dev,
+ "create accel class device file failed!\n");
+ goto exit_err_clean;
+ }
+ #endif
+ /* set sensor PMU into suspend power mode for all */
+ if (smi_pmu_set_suspend(client_data) < 0) {
+ dev_err(dev, "Failed to set SMI130 to suspend power mode\n");
+ goto exit_err_sysfs;
+ }
+ /*enable the data ready interrupt*/
+ SMI_CALL_API(set_intr_enable_1)(SMI130_DATA_RDY_ENABLE, 1);
+ dev_notice(dev, "sensor_time:%d, %d, %d",
+ sensortime_duration_tbl[0].ts_delat,
+ sensortime_duration_tbl[0].ts_duration_lsb,
+ sensortime_duration_tbl[0].ts_duration_us);
+ dev_notice(dev, "sensor %s probed successfully", SENSOR_NAME);
+
+ return 0;
+
+exit_err_sysfs:
+ if (err)
+ smi_input_destroy(client_data);
+
+exit_err_clean:
+ if (err) {
+ if (client_data != NULL) {
+ if (NULL != client_data->bosch_pd) {
+ kfree(client_data->bosch_pd);
+ client_data->bosch_pd = NULL;
+ }
+ }
+ }
+ return err;
+}
+EXPORT_SYMBOL(smi_probe);
+
+/*!
+ * @brief remove smi client
+ *
+ * @param dev the pointer of device
+ *
+ * @return zero
+ * @retval zero
+*/
+int smi_remove(struct device *dev)
+{
+ int err = 0;
+ struct smi_client_data *client_data = dev_get_drvdata(dev);
+
+ if (NULL != client_data) {
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&client_data->early_suspend_handler);
+#endif
+ mutex_lock(&client_data->mutex_enable);
+ if (SMI_ACC_PM_NORMAL == client_data->pw.acc_pm ||
+ SMI_GYRO_PM_NORMAL == client_data->pw.gyro_pm ||
+ SMI_MAG_PM_NORMAL == client_data->pw.mag_pm) {
+ cancel_delayed_work_sync(&client_data->work);
+ }
+ mutex_unlock(&client_data->mutex_enable);
+
+ err = smi_pmu_set_suspend(client_data);
+
+ smi_delay(5);
+
+ sysfs_remove_group(&client_data->input->dev.kobj,
+ &smi130_attribute_group);
+ smi_input_destroy(client_data);
+
+ if (NULL != client_data->bosch_pd) {
+ kfree(client_data->bosch_pd);
+ client_data->bosch_pd = NULL;
+ }
+ kfree(client_data);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(smi_remove);
+
+static int smi_post_resume(struct smi_client_data *client_data)
+{
+ int err = 0;
+
+ mutex_lock(&client_data->mutex_enable);
+
+ if (atomic_read(&client_data->wkqueue_en) == 1) {
+ smi130_set_acc_op_mode(client_data, SMI_ACC_PM_NORMAL);
+ schedule_delayed_work(&client_data->work,
+ msecs_to_jiffies(
+ atomic_read(&client_data->delay)));
+ }
+ mutex_unlock(&client_data->mutex_enable);
+
+ return err;
+}
+
+
+int smi_suspend(struct device *dev)
+{
+ int err = 0;
+ struct smi_client_data *client_data = dev_get_drvdata(dev);
+ unsigned char stc_enable;
+ unsigned char std_enable;
+ dev_err(client_data->dev, "smi suspend function entrance");
+
+ atomic_set(&client_data->in_suspend, 1);
+ if (atomic_read(&client_data->wkqueue_en) == 1) {
+ smi130_set_acc_op_mode(client_data, SMI_ACC_PM_SUSPEND);
+ cancel_delayed_work_sync(&client_data->work);
+ }
+ SMI_CALL_API(get_step_counter_enable)(&stc_enable);
+ SMI_CALL_API(get_step_detector_enable)(&std_enable);
+ if (client_data->pw.acc_pm != SMI_ACC_PM_SUSPEND &&
+ (stc_enable != 1) && (std_enable != 1) &&
+ (client_data->sig_flag != 1)) {
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_acc_arr[SMI_ACC_PM_SUSPEND]);
+ smi_delay(3);
+ }
+ if (client_data->pw.gyro_pm != SMI_GYRO_PM_SUSPEND) {
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_SUSPEND]);
+ smi_delay(3);
+ }
+
+ if (client_data->pw.mag_pm != SMI_MAG_PM_SUSPEND) {
+#if defined(SMI130_AKM09912_SUPPORT)
+ err += smi130_set_bosch_akm_and_secondary_if_powermode(
+ SMI130_MAG_SUSPEND_MODE);
+#else
+ err += smi130_set_bmm150_mag_and_secondary_if_power_mode(
+ SMI130_MAG_SUSPEND_MODE);
+#endif
+ smi_delay(3);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(smi_suspend);
+
+int smi_resume(struct device *dev)
+{
+ int err = 0;
+ struct smi_client_data *client_data = dev_get_drvdata(dev);
+ atomic_set(&client_data->in_suspend, 0);
+ if (client_data->pw.acc_pm != SMI_ACC_PM_SUSPEND) {
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_acc_arr[SMI_ACC_PM_NORMAL]);
+ smi_delay(3);
+ }
+ if (client_data->pw.gyro_pm != SMI_GYRO_PM_SUSPEND) {
+ err += SMI_CALL_API(set_command_register)
+ (smi_pmu_cmd_gyro_arr[SMI_GYRO_PM_NORMAL]);
+ smi_delay(3);
+ }
+
+ if (client_data->pw.mag_pm != SMI_MAG_PM_SUSPEND) {
+#if defined(SMI130_AKM09912_SUPPORT)
+ err += smi130_set_bosch_akm_and_secondary_if_powermode
+ (SMI130_MAG_FORCE_MODE);
+#else
+ err += smi130_set_bmm150_mag_and_secondary_if_power_mode
+ (SMI130_MAG_FORCE_MODE);
+#endif
+ smi_delay(3);
+ }
+ /* post resume operation */
+ err += smi_post_resume(client_data);
+
+ return err;
+}
+EXPORT_SYMBOL(smi_resume);
+
diff --git a/drivers/input/sensors/smi130/smi130_driver.h b/drivers/input/sensors/smi130/smi130_driver.h
new file mode 100644
index 000000000000..4307ae55fd69
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130_driver.h
@@ -0,0 +1,512 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename smi130_driver.h
+ * @date 2015/08/17 14:40
+ * @Modification Date 2018/08/28 18:20
+ * @id "e90a329"
+ * @version 1.3
+ *
+ * @brief
+ * The head file of SMI130 device driver core code
+*/
+#ifndef _SMI130_DRIVER_H
+#define _SMI130_DRIVER_H
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/unistd.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/ktime.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include "smi130.h"
+
+#if defined(CONFIG_USE_QUALCOMM_HAL)
+#include <linux/sensors.h>
+#endif
+/* sensor specific */
+#define SENSOR_NAME "smi130"
+#define SMI130_ENABLE_INT1 1
+#define SMI130_ENABLE_INT2 1
+/*#define SMI130_MAG_INTERFACE_SUPPORT 1*/
+
+/*#define SMI130_AKM09912_SUPPORT 1*/
+#define SMI_USE_BASIC_I2C_FUNC 1
+#define SENSOR_CHIP_ID_SMI (0xD0)
+#define SENSOR_CHIP_ID_SMI_C2 (0xD1)
+#define SENSOR_CHIP_ID_SMI_C3 (0xD3)
+
+#define SENSOR_CHIP_REV_ID_SMI (0x00)
+
+#define CHECK_CHIP_ID_TIME_MAX 5
+
+#define SMI_REG_NAME(name) SMI130_##name##__REG
+#define SMI_VAL_NAME(name) SMI130_##name
+#define SMI_CALL_API(name) smi130_##name
+
+#define SMI_I2C_WRITE_DELAY_TIME (1)
+
+/* generic */
+#define SMI_MAX_RETRY_I2C_XFER (10)
+#define SMI_MAX_RETRY_WAKEUP (5)
+#define SMI_MAX_RETRY_WAIT_DRDY (100)
+
+#define SMI_DELAY_MIN (1)
+#define SMI_DELAY_DEFAULT (200)
+
+#define SMI_VALUE_MAX (32767)
+#define SMI_VALUE_MIN (-32768)
+
+#define BYTES_PER_LINE (16)
+
+#define BUF_SIZE_PRINT (16)
+
+#define SMI_FAST_CALI_TRUE (1)
+#define SMI_FAST_CALI_ALL_RDY (7)
+
+/*! FIFO 1024 byte, max fifo frame count not over 150 */
+#define FIFO_FRAME_CNT 170
+#define FIFO_DATA_BUFSIZE 1024
+
+
+#define FRAME_LEN_ACC 6
+#define FRAME_LEN_GYRO 6
+#define FRAME_LEN_MAG 8
+
+/*! SMI Self test */
+#define SMI_SELFTEST_AMP_HIGH 1
+
+/* CMD */
+#define CMD_FOC_START 0x03
+#define CMD_PMU_ACC_SUSPEND 0x10
+#define CMD_PMU_ACC_NORMAL 0x11
+#define CMD_PMU_ACC_LP1 0x12
+#define CMD_PMU_ACC_LP2 0x13
+#define CMD_PMU_GYRO_SUSPEND 0x14
+#define CMD_PMU_GYRO_NORMAL 0x15
+#define CMD_PMU_GYRO_FASTSTART 0x17
+#define CMD_PMU_MAG_SUSPEND 0x18
+#define CMD_PMU_MAG_NORMAL 0x19
+#define CMD_PMU_MAG_LP1 0x1A
+#define CMD_PMU_MAG_LP2 0x1B
+#define CMD_CLR_FIFO_DATA 0xB0
+#define CMD_RESET_INT_ENGINE 0xB1
+#define CMD_RESET_USER_REG 0xB6
+
+#define USER_DAT_CFG_PAGE 0x00
+
+/*! FIFO Head definition*/
+#define FIFO_HEAD_A 0x84
+#define FIFO_HEAD_G 0x88
+#define FIFO_HEAD_M 0x90
+
+#define FIFO_HEAD_G_A (FIFO_HEAD_G | FIFO_HEAD_A)
+#define FIFO_HEAD_M_A (FIFO_HEAD_M | FIFO_HEAD_A)
+#define FIFO_HEAD_M_G (FIFO_HEAD_M | FIFO_HEAD_G)
+
+#define FIFO_HEAD_M_G_A (FIFO_HEAD_M | FIFO_HEAD_G | FIFO_HEAD_A)
+
+#define FIFO_HEAD_SENSOR_TIME 0x44
+#define FIFO_HEAD_SKIP_FRAME 0x40
+#define FIFO_HEAD_OVER_READ_LSB 0x80
+#define FIFO_HEAD_OVER_READ_MSB 0x00
+
+/*! FIFO head mode Frame bytes number definition */
+#define A_BYTES_FRM 6
+#define G_BYTES_FRM 6
+#define M_BYTES_FRM 8
+#define GA_BYTES_FRM 12
+#define MG_BYTES_FRM 14
+#define MA_BYTES_FRM 14
+#define MGA_BYTES_FRM 20
+
+#define ACC_FIFO_HEAD "acc"
+#define GYRO_FIFO_HEAD "gyro"
+#define MAG_FIFO_HEAD "mag"
+
+/*! Bosch sensor unknown place*/
+#define BOSCH_SENSOR_PLACE_UNKNOWN (-1)
+/*! Bosch sensor remapping table size P0~P7*/
+#define MAX_AXIS_REMAP_TAB_SZ 8
+
+#define ENABLE 1
+#define DISABLE 0
+
+/* smi sensor HW interrupt pin number */
+#define SMI_INT0 0
+#define SMI_INT1 1
+
+#define SMI_INT_LEVEL 0
+#define SMI_INT_EDGE 1
+
+/*! SMI mag interface */
+
+
+/* compensated output value returned if sensor had overflow */
+#define BMM050_OVERFLOW_OUTPUT -32768
+#define BMM050_OVERFLOW_OUTPUT_S32 ((s32)(-2147483647-1))
+
+/* Trim Extended Registers */
+#define BMM050_DIG_X1 0x5D
+#define BMM050_DIG_Y1 0x5E
+#define BMM050_DIG_Z4_LSB 0x62
+#define BMM050_DIG_Z4_MSB 0x63
+#define BMM050_DIG_X2 0x64
+#define BMM050_DIG_Y2 0x65
+#define BMM050_DIG_Z2_LSB 0x68
+#define BMM050_DIG_Z2_MSB 0x69
+#define BMM050_DIG_Z1_LSB 0x6A
+#define BMM050_DIG_Z1_MSB 0x6B
+#define BMM050_DIG_XYZ1_LSB 0x6C
+#define BMM050_DIG_XYZ1_MSB 0x6D
+#define BMM050_DIG_Z3_LSB 0x6E
+#define BMM050_DIG_Z3_MSB 0x6F
+#define BMM050_DIG_XY2 0x70
+#define BMM050_DIG_XY1 0x71
+
+struct smi130mag_compensate_t {
+ signed char dig_x1;
+ signed char dig_y1;
+
+ signed char dig_x2;
+ signed char dig_y2;
+
+ u16 dig_z1;
+ s16 dig_z2;
+ s16 dig_z3;
+ s16 dig_z4;
+
+ unsigned char dig_xy1;
+ signed char dig_xy2;
+
+ u16 dig_xyz1;
+};
+
+/*smi fifo sensor type combination*/
+enum SMI_FIFO_DATA_SELECT_T {
+ SMI_FIFO_A_SEL = 1,
+ SMI_FIFO_G_SEL,
+ SMI_FIFO_G_A_SEL,
+ SMI_FIFO_M_SEL,
+ SMI_FIFO_M_A_SEL,
+ SMI_FIFO_M_G_SEL,
+ SMI_FIFO_M_G_A_SEL,
+ SMI_FIFO_DATA_SEL_MAX
+};
+
+/*smi interrupt about step_detector and sgm*/
+#define INPUT_EVENT_STEP_DETECTOR 5
+#define INPUT_EVENT_SGM 3/*7*/
+#define INPUT_EVENT_FAST_ACC_CALIB_DONE 6
+#define INPUT_EVENT_FAST_GYRO_CALIB_DONE 4
+
+
+/*!
+* Bst sensor common definition,
+* please give parameters in BSP file.
+*/
+struct bosch_sensor_specific {
+ char *name;
+ /* 0 to 7 */
+ unsigned int place:3;
+ int irq;
+ int (*irq_gpio_cfg)(void);
+};
+
+/*! smi130 sensor spec of power mode */
+struct pw_mode {
+ u8 acc_pm;
+ u8 gyro_pm;
+ u8 mag_pm;
+};
+
+/*! smi130 sensor spec of odr */
+struct odr_t {
+ u8 acc_odr;
+ u8 gyro_odr;
+ u8 mag_odr;
+};
+
+/*! smi130 sensor spec of range */
+struct range_t {
+ u8 acc_range;
+ u8 gyro_range;
+};
+
+/*! smi130 sensor error status */
+struct err_status {
+ u8 fatal_err;
+ u8 err_code;
+ u8 i2c_fail;
+ u8 drop_cmd;
+ u8 mag_drdy_err;
+ u8 err_st_all;
+};
+
+/*! smi130 fifo frame for all sensors */
+struct fifo_frame_t {
+ struct smi130_accel_t *acc_farr;
+ struct smi130_gyro_t *gyro_farr;
+ struct smi130_mag_xyz_s32_t *mag_farr;
+
+ unsigned char acc_frame_cnt;
+ unsigned char gyro_frame_cnt;
+ unsigned char mag_frame_cnt;
+
+ u32 acc_lastf_ts;
+ u32 gyro_lastf_ts;
+ u32 mag_lastf_ts;
+};
+
+/*! smi130 fifo sensor time */
+struct fifo_sensor_time_t {
+ u32 acc_ts;
+ u32 gyro_ts;
+ u32 mag_ts;
+};
+
+struct pedometer_data_t {
+ /*! Fix step detector misinformation for the first time*/
+ u8 wkar_step_detector_status;
+ u_int32_t last_step_counter_value;
+};
+
+struct smi_client_data {
+ struct smi130_t device;
+ struct device *dev;
+ struct input_dev *input;/*acc_device*/
+ struct input_dev *gyro_input;
+ #if defined(CONFIG_USE_QUALCOMM_HAL)
+ struct input_dev *gyro_input;
+ struct sensors_classdev accel_cdev;
+ struct sensors_classdev gyro_cdev;
+ struct delayed_work accel_poll_work;
+ struct delayed_work gyro_poll_work;
+ u32 accel_poll_ms;
+ u32 gyro_poll_ms;
+ u32 accel_latency_ms;
+ u32 gyro_latency_ms;
+ atomic_t accel_en;
+ atomic_t gyro_en;
+ struct workqueue_struct *data_wq;
+ #endif
+ struct delayed_work work;
+ struct work_struct irq_work;
+
+ u8 chip_id;
+
+ struct pw_mode pw;
+ struct odr_t odr;
+ struct range_t range; /*TO DO*/
+ struct err_status err_st;
+ struct pedometer_data_t pedo_data;
+ s8 place;
+ u8 selftest;
+ /*struct wake_lock wakelock;*/
+ struct delayed_work delay_work_sig;
+ atomic_t in_suspend;
+
+ atomic_t wkqueue_en; /*TO DO acc gyro mag*/
+ atomic_t delay;
+ atomic_t selftest_result;
+
+ u8 fifo_data_sel;
+ u16 fifo_bytecount;
+ u8 fifo_head_en;
+ unsigned char fifo_int_tag_en;
+ struct fifo_frame_t fifo_frame;
+
+ unsigned char *fifo_data;
+ u64 fifo_time;
+ u8 stc_enable;
+ uint16_t gpio_pin;
+ u8 std;
+ u8 sig_flag;
+ unsigned char calib_status;
+ struct mutex mutex_op_mode;
+ struct mutex mutex_enable;
+ struct bosch_sensor_specific *bosch_pd;
+ int IRQ;
+ int reg_sel;
+ int reg_len;
+ uint64_t timestamp;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend_handler;
+#endif
+};
+
+
+/*!
+ * we use a typedef to hide the detail,
+ * because this type might be changed
+ */
+struct bosch_sensor_axis_remap {
+ /* src means which source will be mapped to target x, y, z axis */
+ /* if an target OS axis is remapped from (-)x,
+ * src is 0, sign_* is (-)1 */
+ /* if an target OS axis is remapped from (-)y,
+ * src is 1, sign_* is (-)1 */
+ /* if an target OS axis is remapped from (-)z,
+ * src is 2, sign_* is (-)1 */
+ int src_x:3;
+ int src_y:3;
+ int src_z:3;
+
+ int sign_x:2;
+ int sign_y:2;
+ int sign_z:2;
+};
+
+
+struct bosch_sensor_data {
+ union {
+ int16_t v[3];
+ struct {
+ int16_t x;
+ int16_t y;
+ int16_t z;
+ };
+ };
+};
+
+s8 smi_burst_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u16 len);
+int smi_probe(struct smi_client_data *client_data, struct device *dev);
+int smi_remove(struct device *dev);
+int smi_suspend(struct device *dev);
+int smi_resume(struct device *dev);
+
+
+
+
+#endif/*_SMI130_DRIVER_H*/
+/*@}*/
+
diff --git a/drivers/input/sensors/smi130/smi130_gyro.c b/drivers/input/sensors/smi130/smi130_gyro.c
new file mode 100644
index 000000000000..ef3fc38fb68b
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130_gyro.c
@@ -0,0 +1,7422 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ * @filename smi130_gyro.c
+ * @date 2013/11/25
+ * @Modification Date 2018/08/28 18:20
+ * @id "8fcde22"
+ * @version 1.5
+ *
+ * @brief SMI130_GYROAPI
+*/
+
+#include "smi130_gyro.h"
+static struct smi130_gyro_t *p_smi130_gyro;
+
+
+/*****************************************************************************
+ * Description: *//**brief API Initialization routine
+ *
+ *
+ *
+ *
+* \param smi130_gyro_t *smi130_gyro
+ * Pointer to a structure.
+ *
+ * structure members are
+ *
+ * unsigned char chip_id;
+ * unsigned char dev_addr;
+ * SMI130_GYRO_BRD_FUNC_PTR;
+ * SMI130_GYRO_WR_FUNC_PTR;
+ * SMI130_GYRO_RD_FUNC_PTR;
+ * void(*delay_msec)( SMI130_GYRO_MDELAY_DATA_TYPE );
+ *
+ *
+ *
+ *
+ *
+ * \return result of communication routines
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_init(struct smi130_gyro_t *smi130_gyro)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char a_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ p_smi130_gyro = smi130_gyro;
+
+ p_smi130_gyro->dev_addr = SMI130_GYRO_I2C_ADDR;
+
+ /*Read CHIP_ID */
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_CHIP_ID_ADDR, &a_data_u8r, 1);
+ p_smi130_gyro->chip_id = a_data_u8r;
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads Rate dataX from location 02h and 03h
+ * registers
+ *
+ *
+ *
+ *
+ * \param
+ * SMI130_GYRO_S16 *data_x : Address of data_x
+ *
+ *
+ * \return
+ * result of communication routines
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataX(SMI130_GYRO_S16 *data_x)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char a_data_u8r[2] = {0, 0};
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATE_X_LSB_VALUEX__REG, a_data_u8r, 2);
+ a_data_u8r[0] = SMI130_GYRO_GET_BITSLICE(a_data_u8r[0],
+ SMI130_GYRO_RATE_X_LSB_VALUEX);
+ *data_x = (SMI130_GYRO_S16)
+ ((((SMI130_GYRO_S16)((signed char)a_data_u8r[1])) <<
+ SMI130_GYRO_SHIFT_8_POSITION) | (a_data_u8r[0]));
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads rate dataY from location 04h and 05h
+ * registers
+ *
+ *
+ *
+ *
+ * \param
+ * SMI130_GYRO_S16 *data_y : Address of data_y
+ *
+ *
+ * \return
+ * result of communication routines
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataY(SMI130_GYRO_S16 *data_y)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char a_data_u8r[2] = {0, 0};
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATE_Y_LSB_VALUEY__REG, a_data_u8r, 2);
+ a_data_u8r[0] = SMI130_GYRO_GET_BITSLICE(a_data_u8r[0],
+ SMI130_GYRO_RATE_Y_LSB_VALUEY);
+ *data_y = (SMI130_GYRO_S16)
+ ((((SMI130_GYRO_S16)((signed char)a_data_u8r[1]))
+ << SMI130_GYRO_SHIFT_8_POSITION) | (a_data_u8r[0]));
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads rate dataZ from location 06h and 07h
+ * registers
+ *
+ *
+ *
+ *
+ * \param
+ * SMI130_GYRO_S16 *data_z : Address of data_z
+ *
+ *
+ * \return
+ * result of communication routines
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataZ(SMI130_GYRO_S16 *data_z)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char a_data_u8r[2] = {0, 0};
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATE_Z_LSB_VALUEZ__REG, a_data_u8r, 2);
+ a_data_u8r[0] = SMI130_GYRO_GET_BITSLICE(a_data_u8r[0],
+ SMI130_GYRO_RATE_Z_LSB_VALUEZ);
+ *data_z = (SMI130_GYRO_S16)
+ ((((SMI130_GYRO_S16)((signed char)a_data_u8r[1]))
+ << SMI130_GYRO_SHIFT_8_POSITION) | (a_data_u8r[0]));
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads data X,Y and Z from location 02h to 07h
+ *
+ *
+ *
+ *
+ * \param
+ * smi130_gyro_data_t *data : Address of smi130_gyro_data_t
+ *
+ *
+ * \return
+ * result of communication routines
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataXYZ(struct smi130_gyro_data_t *data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char a_data_u8r[6] = {0, 0, 0, 0, 0, 0};
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATE_X_LSB_VALUEX__REG, a_data_u8r, 6);
+ /* Data X */
+ a_data_u8r[0] =
+ SMI130_GYRO_GET_BITSLICE(a_data_u8r[0], SMI130_GYRO_RATE_X_LSB_VALUEX);
+ data->datax = (SMI130_GYRO_S16)
+ ((((SMI130_GYRO_S16)((signed char)a_data_u8r[1]))
+ << SMI130_GYRO_SHIFT_8_POSITION) | (a_data_u8r[0]));
+ /* Data Y */
+ a_data_u8r[2] = SMI130_GYRO_GET_BITSLICE(a_data_u8r[2],
+ SMI130_GYRO_RATE_Y_LSB_VALUEY);
+ data->datay = (SMI130_GYRO_S16)
+ ((((SMI130_GYRO_S16)((signed char)a_data_u8r[3]))
+ << SMI130_GYRO_SHIFT_8_POSITION) | (a_data_u8r[2]));
+ /* Data Z */
+ a_data_u8r[4] = SMI130_GYRO_GET_BITSLICE(a_data_u8r[4],
+ SMI130_GYRO_RATE_Z_LSB_VALUEZ);
+ data->dataz = (SMI130_GYRO_S16)
+ ((((SMI130_GYRO_S16)((signed char)a_data_u8r[5]))
+ << SMI130_GYRO_SHIFT_8_POSITION) | (a_data_u8r[4]));
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads data X,Y,Z and Interrupts
+ * from location 02h to 07h
+ *
+ *
+ *
+ *
+ * \param
+ * smi130_gyro_data_t *data : Address of smi130_gyro_data_t
+ *
+ *
+ * \return
+ * result of communication routines
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataXYZI(struct smi130_gyro_data_t *data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char a_data_u8r[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATE_X_LSB_VALUEX__REG, a_data_u8r, 12);
+ /* Data X */
+ a_data_u8r[0] = SMI130_GYRO_GET_BITSLICE(a_data_u8r[0],
+ SMI130_GYRO_RATE_X_LSB_VALUEX);
+ data->datax = (SMI130_GYRO_S16)
+ ((((SMI130_GYRO_S16)((signed char)a_data_u8r[1]))
+ << SMI130_GYRO_SHIFT_8_POSITION) | (a_data_u8r[0]));
+ /* Data Y */
+ a_data_u8r[2] = SMI130_GYRO_GET_BITSLICE(a_data_u8r[2],
+ SMI130_GYRO_RATE_Y_LSB_VALUEY);
+ data->datay = (SMI130_GYRO_S16)
+ ((((SMI130_GYRO_S16)((signed char)a_data_u8r[3]))
+ << SMI130_GYRO_SHIFT_8_POSITION) | (a_data_u8r[2]));
+ /* Data Z */
+ a_data_u8r[4] = SMI130_GYRO_GET_BITSLICE(a_data_u8r[4],
+ SMI130_GYRO_RATE_Z_LSB_VALUEZ);
+ data->dataz = (SMI130_GYRO_S16)
+ ((((SMI130_GYRO_S16)((signed char)a_data_u8r[5]))
+ << SMI130_GYRO_SHIFT_8_POSITION) | (a_data_u8r[4]));
+ data->intstatus[0] = a_data_u8r[7];
+ data->intstatus[1] = a_data_u8r[8];
+ data->intstatus[2] = a_data_u8r[9];
+ data->intstatus[3] = a_data_u8r[10];
+ data->intstatus[4] = a_data_u8r[11];
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads Temperature from location 08h
+ *
+ *
+ *
+ *
+ * \param
+ * unsigned char *temp : Address of temperature
+ *
+ *
+ * \return
+ * result of communication routines
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_Temperature(unsigned char *temperature)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TEMP_ADDR, &v_data_u8r, 1);
+ *temperature = v_data_u8r;
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API reads the data from the given register
+ *
+ *
+ *
+ *
+ *\param unsigned char addr, unsigned char *data unsigned char len
+ * addr -> Address of the register
+ * data -> address of the variable, read value will be
+ * kept
+ * len -> No of byte to be read.
+ * \return results of bus communication function
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_read_register(unsigned char addr,
+unsigned char *data, unsigned char len)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr, addr, data, len);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API reads the data from the given register
+ *
+ *
+ *
+ *
+ *\param unsigned char addr, unsigned char *data SMI130_GYRO_S32 len
+ * addr -> Address of the register
+ * data -> address of the variable, read value will be
+ * kept
+ * len -> No of byte to be read.
+ * \return results of bus communication function
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_burst_read(unsigned char addr,
+unsigned char *data, SMI130_GYRO_S32 len)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BURST_READ_FUNC(p_smi130_gyro->dev_addr,
+ addr, data, len);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API given data to the given register
+ *
+ *
+ *
+ *
+ *\param unsigned char addr, unsigned char data,unsigned char len
+ * addr -> Address of the register
+ * data -> Data to be written to the register
+ * len -> No of byte to be read.
+ *
+ * \return Results of bus communication function
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_write_register(unsigned char addr,
+unsigned char *data, unsigned char len)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr, addr, data, len);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads interrupt status 0 register byte from 09h
+ *
+ *
+ *
+ *
+ * \param
+ * unsigned char *status0_data : Address of status 0 register
+ *
+ *
+ * \return
+ * Result of bus communication function
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_interrupt_status_reg_0(
+unsigned char *status0_data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_STATUSZERO__REG, &v_data_u8r, 1);
+ *status0_data =
+ SMI130_GYRO_GET_BITSLICE(v_data_u8r, SMI130_GYRO_INT_STATUSZERO);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads interrupt status 1 register byte from 0Ah
+ *
+ *
+ *
+ *
+ * \param
+ * unsigned char *status1_data : Address of status register
+ *
+ *
+ * \return
+ * Result of bus communication function
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_interrupt_status_reg_1(
+unsigned char *status1_data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr, SMI130_GYRO_INT_STATUSONE__REG,
+ &v_data_u8r, 1);
+ *status1_data =
+ SMI130_GYRO_GET_BITSLICE(v_data_u8r, SMI130_GYRO_INT_STATUSONE);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads interrupt status register byte from 0Bh
+ *
+ *
+ *
+ *
+ * \param
+ * unsigned char *status2_data : Address of status 2 register
+ *
+ *
+ * \return
+ * Result of bus communication function
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_interrupt_status_reg_2(
+unsigned char *status2_data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_STATUSTWO__REG, &v_data_u8r, 1);
+ *status2_data =
+ SMI130_GYRO_GET_BITSLICE(v_data_u8r, SMI130_GYRO_INT_STATUSTWO);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads interrupt status 3 register byte from 0Ch
+ *
+ *
+ *
+ *
+ * \param
+ * unsigned char *status3_data : Address of status 3 register
+ *
+ *
+ * \return
+ * Result of bus communication function
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_interrupt_status_reg_3(
+unsigned char *status3_data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_STATUSTHREE__REG, &v_data_u8r, 1);
+ *status3_data =
+ SMI130_GYRO_GET_BITSLICE(v_data_u8r, SMI130_GYRO_INT_STATUSTHREE);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API reads the range from register 0x0Fh of
+ * (0 to 2) bits
+ *
+ *
+ *
+ *
+ *\param unsigned char *range
+ * Range[0....7]
+ * 0 2000/s
+ * 1 1000/s
+ * 2 500/s
+ * 3 250/s
+ * 4 125/s
+ *
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_range_reg(unsigned char *range)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RANGE_ADDR_RANGE__REG, &v_data_u8r, 1);
+ *range =
+ SMI130_GYRO_GET_BITSLICE(v_data_u8r, SMI130_GYRO_RANGE_ADDR_RANGE);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API sets the range register 0x0Fh
+ * (0 to 2 bits)
+ *
+ *
+ *
+ *
+ *\param unsigned char range
+ *
+ * Range[0....7]
+ * 0 2000/s
+ * 1 1000/s
+ * 2 500/s
+ * 3 250/s
+ * 4 125/s
+ *
+ *
+ *
+ *
+ * \return Communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_range_reg(unsigned char range)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (range < C_SMI130_GYRO_Five_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RANGE_ADDR_RANGE__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RANGE_ADDR_RANGE,
+ range);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RANGE_ADDR_RANGE__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API reads the high resolution bit of 0x10h
+ * Register 7th bit
+ *
+ *
+ *
+ *
+ *\param unsigned char *high_res
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_res(unsigned char *high_res)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BW_ADDR_HIGH_RES__REG, &v_data_u8r, 1);
+ *high_res =
+ SMI130_GYRO_GET_BITSLICE(v_data_u8r, SMI130_GYRO_BW_ADDR_HIGH_RES);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API reads the bandwidth register of 0x10h 0 to
+ * 3 bits
+ *
+ *
+ *
+ *
+* \param unsigned char *bandwidth
+ * pointer to a variable passed as a parameter
+ *
+ * 0 no filter(523 Hz)
+ * 1 230Hz
+ * 2 116Hz
+ * 3 47Hz
+ * 4 23Hz
+ * 5 12Hz
+ * 6 64Hz
+ * 7 32Hz
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_bw(unsigned char *bandwidth)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr, SMI130_GYRO_BW_ADDR__REG, &v_data_u8r, 1);
+ *bandwidth = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_BW_ADDR);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API writes the Bandwidth register (0x10h of 0
+ * to 3 bits)
+ *
+ *
+ *
+ *
+ *\param unsigned char bandwidth,
+ * The bandwidth to be set passed as a parameter
+ *
+ * 0 no filter(523 Hz)
+ * 1 230Hz
+ * 2 116Hz
+ * 3 47Hz
+ * 4 23Hz
+ * 5 12Hz
+ * 6 64Hz
+ * 7 32Hz
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_bw(unsigned char bandwidth)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_mode_u8r = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_autosleepduration = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (bandwidth < C_SMI130_GYRO_Eight_U8X) {
+ smi130_gyro_get_mode(&v_mode_u8r);
+ if (v_mode_u8r == SMI130_GYRO_MODE_ADVANCEDPOWERSAVING) {
+ smi130_gyro_get_autosleepdur(&v_autosleepduration);
+ smi130_gyro_set_autosleepdur(v_autosleepduration,
+ bandwidth);
+ }
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BW_ADDR__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_BW_ADDR, bandwidth);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BW_ADDR__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API reads the status of External Trigger
+ * selection bits (4 and 5) of 0x12h registers
+ *
+ *
+ *
+ *
+ *\param unsigned char *pwu_ext_tri_sel
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return Communication Results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_pmu_ext_tri_sel(
+unsigned char *pwu_ext_tri_sel)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR_EXT_TRI_SEL__REG, &v_data_u8r, 1);
+ *pwu_ext_tri_sel = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MODE_LPM2_ADDR_EXT_TRI_SEL);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API writes the External Trigger selection
+ * bits (4 and 5) of 0x12h registers
+ *
+ *
+ *
+ *
+ *\param unsigned char pwu_ext_tri_sel
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return Communication Results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_pmu_ext_tri_sel(
+unsigned char pwu_ext_tri_sel)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR_EXT_TRI_SEL__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MODE_LPM2_ADDR_EXT_TRI_SEL, pwu_ext_tri_sel);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR_EXT_TRI_SEL__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get data high bandwidth
+ *
+ *
+ *
+ *
+ *\param unsigned char *high_bw : Address of high_bw
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_bw(unsigned char *high_bw)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATED_HBW_ADDR_DATA_HIGHBW__REG, &v_data_u8r, 1);
+ *high_bw = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RATED_HBW_ADDR_DATA_HIGHBW);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set data high bandwidth
+ *
+ *
+ *
+ *
+ *\param unsigned char high_bw:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_bw(unsigned char high_bw)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (high_bw < C_SMI130_GYRO_Two_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATED_HBW_ADDR_DATA_HIGHBW__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RATED_HBW_ADDR_DATA_HIGHBW, high_bw);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATED_HBW_ADDR_DATA_HIGHBW__REG,
+ &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get shadow dis
+ *
+ *
+ *
+ *
+ *\param unsigned char *shadow_dis : Address of shadow_dis
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_shadow_dis(unsigned char *shadow_dis)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATED_HBW_ADDR_SHADOW_DIS__REG, &v_data_u8r, 1);
+ *shadow_dis = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RATED_HBW_ADDR_SHADOW_DIS);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set shadow dis
+ *
+ *
+ *
+ *
+ *\param unsigned char shadow_dis
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_shadow_dis(unsigned char shadow_dis)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (shadow_dis < C_SMI130_GYRO_Two_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATED_HBW_ADDR_SHADOW_DIS__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RATED_HBW_ADDR_SHADOW_DIS, shadow_dis);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RATED_HBW_ADDR_SHADOW_DIS__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief
+ * This function is used for the soft reset
+ * The soft reset register will be written with 0xB6.
+ *
+ *
+ *
+* \param None
+ *
+ *
+ *
+ * \return Communication results.
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_soft_reset()
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_SoftReset_u8r = C_SMI130_GYRO_Zero_U8X;
+ v_SoftReset_u8r = 0xB6;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SOFTRESET_ADDR, &v_SoftReset_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get data enable data
+ *
+ *
+ *
+ *
+ *\param unsigned char *data_en : Address of data_en
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_data_enable(unsigned char *data_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE0_DATAEN__REG, &v_data_u8r, 1);
+ *data_en = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE0_DATAEN);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set data enable data
+ *
+ *
+ *
+ *
+ * \param unsigned char data_en:
+ * Value to be written passed as a \parameter
+ * 0 --> Disable
+ * 1 --> Enable
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_data_en(unsigned char data_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE0_DATAEN__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE0_DATAEN, data_en);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE0_DATAEN__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get fifo enable bit
+ *
+ *
+ *
+ *
+ * \param unsigned char *fifo_en : Address of fifo_en
+ * Pointer to a variable passed as a parameter
+
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_enable(unsigned char *fifo_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE0_FIFOEN__REG, &v_data_u8r, 1);
+ *fifo_en = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE0_FIFOEN);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set fifo enable bit
+ *
+ *
+ *
+ *
+ * \param unsigned char fifo_en:
+ * Value to be written passed as a parameter
+ * 0 --> Disable
+ * 1 --> Enable
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_enable(unsigned char fifo_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (fifo_en < C_SMI130_GYRO_Two_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE0_FIFOEN__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE0_FIFOEN, fifo_en);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE0_FIFOEN__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API reads the status of the Auto offset
+ * Enable bit
+ * (0x15 Reg 3rd Bit)
+ *
+ *
+ *
+ *
+ * \param unsigned char *offset_en
+ * address of a variable,
+ *
+ *
+ *
+ * \return Communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_auto_offset_en(
+unsigned char *offset_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE0_AUTO_OFFSETEN__REG, &v_data_u8r, 1);
+ *offset_en = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE0_AUTO_OFFSETEN);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API sets the Auto offset enable bit
+ * (Reg 0x15 3rd Bit)
+ *
+ *
+ *
+ *
+ * \param unsigned char offset_en
+ * 0 --> Disable
+ * 1 --> Enable
+ *
+ * \return Communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_auto_offset_en(unsigned char offset_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE0_AUTO_OFFSETEN__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE0_AUTO_OFFSETEN, offset_en);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE0_AUTO_OFFSETEN__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the output type status
+ *
+ *
+ *
+ *
+ * \param unsigned char channel,unsigned char *int_od
+ * SMI130_GYRO_INT1 -> 0
+ * SMI130_GYRO_INT2 -> 1
+ * int_od : open drain -> 1
+ * push pull -> 0
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int_od(unsigned char param,
+unsigned char *int_od)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_INT1:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT1_OD__REG, &v_data_u8r, 1);
+ *int_od = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE1_IT1_OD);
+ break;
+ case SMI130_GYRO_INT2:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT2_OD__REG, &v_data_u8r, 1);
+ *int_od = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE1_IT2_OD);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the output type status
+ *
+ *
+ *
+ *
+ * \param unsigned char channel,unsigned char *int_od
+ * SMI130_GYRO_INT1 -> 0
+ * SMI130_GYRO_INT2 -> 1
+ * int_od : open drain -> 1
+ * push pull -> 0
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int_od(unsigned char param,
+unsigned char int_od)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_INT1:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT1_OD__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE1_IT1_OD, int_od);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT1_OD__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_INT2:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT2_OD__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE1_IT2_OD, int_od);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT2_OD__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Active Level status
+ *
+ *
+ *
+ *
+ * \param unsigned char channel,unsigned char *int_lvl
+ * SMI130_GYRO_INT1 -> 0
+ * SMI130_GYRO_INT2 -> 1
+ * int_lvl : Active HI -> 1
+ * Active LO -> 0
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int_lvl(unsigned char param,
+unsigned char *int_lvl)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_INT1:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT1_LVL__REG, &v_data_u8r, 1);
+ *int_lvl = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE1_IT1_LVL);
+ break;
+ case SMI130_GYRO_INT2:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT2_LVL__REG, &v_data_u8r, 1);
+ *int_lvl = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE1_IT2_LVL);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Active Level status
+ *
+ *
+ *
+ *
+ * \param unsigned char channel,unsigned char *int_lvl
+ * SMI130_GYRO_INT1 -> 0
+ * SMI130_GYRO_INT2 -> 1
+ * int_lvl : Active HI -> 1
+ * Active LO -> 0
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int_lvl(unsigned char param,
+unsigned char int_lvl)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_INT1:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT1_LVL__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE1_IT1_LVL, int_lvl);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT1_LVL__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_INT2:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT2_LVL__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_ENABLE1_IT2_LVL, int_lvl);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_ENABLE1_IT2_LVL__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get High Interrupt1
+ *
+ *
+ *
+ *
+ * \param unsigned char *int1_high : Address of high_bw
+ * Pointer to a variable passed as a parameter
+
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int1_high(unsigned char *int1_high)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_0_INT1_HIGH__REG, &v_data_u8r, 1);
+ *int1_high = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_MAP_0_INT1_HIGH);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set High Interrupt1
+ *
+ *
+ *
+ *
+ * \param unsigned char int1_high
+ * 0 -> Disable
+ * 1 -> Enable
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int1_high(unsigned char int1_high)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_0_INT1_HIGH__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_MAP_0_INT1_HIGH, int1_high);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_0_INT1_HIGH__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Any Interrupt1
+ *
+ *
+ *
+ *
+ * \param unsigned char *int1_any : Address of high_bw
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int1_any(unsigned char *int1_any)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_0_INT1_ANY__REG, &v_data_u8r, 1);
+ *int1_any = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_MAP_0_INT1_ANY);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Any Interrupt1
+ *
+ *
+ *
+ *
+ *\param unsigned char int1_any
+ * 0 -> Disable
+ * 1 -> Enable
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int1_any(unsigned char int1_any)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_0_INT1_ANY__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_MAP_0_INT1_ANY, int1_any);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_0_INT1_ANY__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get data Interrupt1 and data
+ * Interrupt2
+ *
+ *
+ *
+ *
+ * \param unsigned char axis,unsigned char *int_data
+ * axis :
+ * SMI130_GYRO_INT1_DATA -> 0
+ * SMI130_GYRO_INT2_DATA -> 1
+ * int_data :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int_data(unsigned char axis,
+unsigned char *int_data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (axis) {
+ case SMI130_GYRO_INT1_DATA:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_DATA__REG, &v_data_u8r, 1);
+ *int_data = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT1_DATA);
+ break;
+ case SMI130_GYRO_INT2_DATA:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_DATA__REG, &v_data_u8r, 1);
+ *int_data = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT2_DATA);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set data Interrupt1 and data
+ * Interrupt2
+ *
+ *
+ *
+ *
+ * \param unsigned char axis,unsigned char *int_data
+ * axis :
+ * SMI130_GYRO_INT1_DATA -> 0
+ * SMI130_GYRO_INT2_DATA -> 1
+ * int_data :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int_data(unsigned char axis,
+unsigned char int_data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (axis) {
+ case SMI130_GYRO_INT1_DATA:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_DATA__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT1_DATA, int_data);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_DATA__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_INT2_DATA:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_DATA__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT2_DATA, int_data);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_DATA__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+ }
+
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get fast offset and auto
+ * offset Interrupt2
+ *
+ *
+ *
+ *
+ *\param unsigned char axis,unsigned char *int2_offset
+ * axis :
+ * SMI130_GYRO_AUTO_OFFSET -> 1
+ * SMI130_GYRO_FAST_OFFSET -> 2
+ * int2_offset :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int2_offset(unsigned char axis,
+unsigned char *int2_offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (axis) {
+ case SMI130_GYRO_FAST_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_FAST_OFFSET__REG, &v_data_u8r, 1);
+ *int2_offset = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT2_FAST_OFFSET);
+ break;
+ case SMI130_GYRO_AUTO_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_AUTO_OFFSET__REG, &v_data_u8r, 1);
+ *int2_offset = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT2_AUTO_OFFSET);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set fast offset and auto
+ * offset Interrupt2
+ *
+ *
+ *
+ *
+ *\param unsigned char axis,unsigned char *int2_offset
+ * axis :
+ * SMI130_GYRO_AUTO_OFFSET -> 1
+ * SMI130_GYRO_FAST_OFFSET -> 2
+ * int2_offset :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int2_offset(unsigned char axis,
+unsigned char int2_offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (axis) {
+ case SMI130_GYRO_FAST_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_FAST_OFFSET__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT2_FAST_OFFSET, int2_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_FAST_OFFSET__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_AUTO_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_AUTO_OFFSET__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT2_AUTO_OFFSET, int2_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_AUTO_OFFSET__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get fast offset and auto
+ * offset Interrupt1
+ *
+ *
+ *
+ *
+ *\param unsigned char axis,unsigned char *int1_offset
+ * axis :
+ * SMI130_GYRO_AUTO_OFFSET -> 1
+ * SMI130_GYRO_FAST_OFFSET -> 2
+ * int2_offset :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int1_offset(unsigned char axis,
+unsigned char *int1_offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (axis) {
+ case SMI130_GYRO_FAST_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_FAST_OFFSET__REG, &v_data_u8r, 1);
+ *int1_offset = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT1_FAST_OFFSET);
+ break;
+ case SMI130_GYRO_AUTO_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_AUTO_OFFSET__REG, &v_data_u8r, 1);
+ *int1_offset = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT1_AUTO_OFFSET);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set fast offset and auto
+ * offset Interrupt1
+ *
+ *
+ *
+ *
+ *\param unsigned char axis,unsigned char *int1_offset
+ * axis :
+ * SMI130_GYRO_AUTO_OFFSET -> 1
+ * SMI130_GYRO_FAST_OFFSET -> 2
+ * int2_offset :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int1_offset(unsigned char axis,
+unsigned char int1_offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (axis) {
+ case SMI130_GYRO_FAST_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_FAST_OFFSET__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT1_FAST_OFFSET, int1_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_FAST_OFFSET__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_AUTO_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_AUTO_OFFSET__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT1_AUTO_OFFSET, int1_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_AUTO_OFFSET__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get status of FIFO Interrupt
+ *
+ *
+ *
+ *
+ *\param unsigned char *int_fifo : Address of int_fifo
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int_fifo(unsigned char *int_fifo)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_STATUS1_FIFO_INT__REG, &v_data_u8r, 1);
+ *int_fifo = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_STATUS1_FIFO_INT);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get FIFO Interrupt2
+ *
+ *
+ *
+ *
+ *\param unsigned char *int_fifo
+ * int_fifo :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int2_fifo(unsigned char *int_fifo)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_FIFO__REG, &v_data_u8r, 1);
+ *int_fifo = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT2_FIFO);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get FIFO Interrupt1
+ *
+ *
+ *
+ *
+ *\param unsigned char *int_fifo
+ * int_fifo :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int1_fifo(unsigned char *int_fifo)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_FIFO__REG, &v_data_u8r, 1);
+ *int_fifo = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT1_FIFO);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int_fifo(unsigned char axis,
+unsigned char int_fifo)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (axis) {
+ case SMI130_GYRO_INT1:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_FIFO__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT1_FIFO, int_fifo);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_FIFO__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_INT2:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_FIFO__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT2_FIFO, int_fifo);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_FIFO__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set FIFO Interrupt1
+ *
+ *
+ *
+ *
+ *\param unsigned char *fifo_int1
+ * fifo_int1 :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int1_fifo(unsigned char fifo_int1)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (fifo_int1 < C_SMI130_GYRO_Two_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_FIFO__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT1_FIFO, fifo_int1);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT1_FIFO__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set FIFO Interrupt2
+ *
+ *
+ *
+ *
+ *\param unsigned char *fifo_int2
+ * fifo_int2 :
+ * Disable -> 0
+ * Enable -> 1
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int2_fifo(unsigned char fifo_int2)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (fifo_int2 < C_SMI130_GYRO_Two_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_FIFO__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MAP_1_INT2_FIFO, fifo_int2);
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MAP_1_INT2_FIFO__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get High Interrupt2
+ *
+ *
+ *
+ *
+ *\param unsigned char *int2_high : Address of int2_high
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int2_high(unsigned char *int2_high)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_2_INT2_HIGH__REG, &v_data_u8r, 1);
+ *int2_high = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_MAP_2_INT2_HIGH);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get High Interrupt2
+ *
+ *
+ *
+ *
+ *\param unsigned char int2_high
+ * 0 -> Disable
+ * 1 -> Enable
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int2_high(unsigned char int2_high)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_2_INT2_HIGH__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_MAP_2_INT2_HIGH, int2_high);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_2_INT2_HIGH__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Any Interrupt2
+ *
+ *
+ *
+ *
+ *\param unsigned char *int2_any : Address of int2_any
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int2_any(unsigned char *int2_any)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_2_INT2_ANY__REG, &v_data_u8r, 1);
+ *int2_any = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_MAP_2_INT2_ANY);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Any Interrupt2
+ *
+ *
+ *
+ *
+ *\param unsigned char int2_any
+ * 0 -> Disable
+ * 1 -> Enable
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int2_any(unsigned char int2_any)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_2_INT2_ANY__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_MAP_2_INT2_ANY, int2_any);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_MAP_2_INT2_ANY__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get slow offset and fast
+ * offset unfilt data
+ *
+ *
+ *
+ *\param unsigned char param,unsigned char *offset_unfilt
+ * param :
+ * SMI130_GYRO_SLOW_OFFSET -> 0
+ * SMI130_GYRO_FAST_OFFSET -> 2
+ * offset_unfilt: Enable -> 1
+ * Disable -> 0
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_offset_unfilt(unsigned char param,
+unsigned char *offset_unfilt)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_SLOW_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_0_ADDR_SLOW_OFFSET_UNFILT__REG,
+ &v_data_u8r, 1);
+ *offset_unfilt = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_0_ADDR_SLOW_OFFSET_UNFILT);
+ break;
+ case SMI130_GYRO_FAST_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_1_ADDR_FAST_OFFSET_UNFILT__REG,
+ &v_data_u8r, 1);
+ *offset_unfilt = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_1_ADDR_FAST_OFFSET_UNFILT);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set slow offset and fast
+ * offset unfilt data
+ *
+ *
+ *
+ *
+ *\param unsigned char param,unsigned char *offset_unfilt
+ * param :
+ * SMI130_GYRO_SLOW_OFFSET -> 0
+ * SMI130_GYRO_FAST_OFFSET -> 2
+ * offset_unfilt: Enable -> 1
+ * Disable -> 0
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_offset_unfilt(unsigned char param,
+unsigned char offset_unfilt)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_SLOW_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_0_ADDR_SLOW_OFFSET_UNFILT__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_0_ADDR_SLOW_OFFSET_UNFILT, offset_unfilt);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_0_ADDR_SLOW_OFFSET_UNFILT__REG,
+ &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_FAST_OFFSET:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_1_ADDR_FAST_OFFSET_UNFILT__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_1_ADDR_FAST_OFFSET_UNFILT, offset_unfilt);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_1_ADDR_FAST_OFFSET_UNFILT__REG,
+ &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Tap, High, Constant, Any,
+ * Shake unfilt data
+ *
+ *
+ *
+ *
+ *\param unsigned char param,unsigned char *unfilt_data
+ * param :
+ *
+ * SMI130_GYRO_HIGH_UNFILT_DATA -> 1
+ * SMI130_GYRO_ANY_UNFILT_DATA -> 3
+ *
+ * unfilt_data: Enable -> 1
+ * Disable -> 0
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_unfilt_data(unsigned char param,
+unsigned char *unfilt_data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_HIGH_UNFILT_DATA:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_0_ADDR_HIGH_UNFILT_DATA__REG,
+ &v_data_u8r, 1);
+ *unfilt_data = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_0_ADDR_HIGH_UNFILT_DATA);
+ break;
+ case SMI130_GYRO_ANY_UNFILT_DATA:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_0_ADDR_ANY_UNFILT_DATA__REG, &v_data_u8r, 1);
+ *unfilt_data = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_0_ADDR_ANY_UNFILT_DATA);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Tap, High, Constant, Any,
+ * Shake unfilt data
+ *
+ *
+ *
+ *
+ *\param unsigned char param,unsigned char *unfilt_data
+ * param :
+ *
+ * SMI130_GYRO_HIGH_UNFILT_DATA -> 1
+ * SMI130_GYRO_ANY_UNFILT_DATA -> 3
+ *
+ * unfilt_data: Enable -> 1
+ * Disable -> 0
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_unfilt_data(unsigned char param,
+unsigned char unfilt_data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_HIGH_UNFILT_DATA:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_0_ADDR_HIGH_UNFILT_DATA__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_0_ADDR_HIGH_UNFILT_DATA, unfilt_data);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_0_ADDR_HIGH_UNFILT_DATA__REG,
+ &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_ANY_UNFILT_DATA:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_0_ADDR_ANY_UNFILT_DATA__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_0_ADDR_ANY_UNFILT_DATA, unfilt_data);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_0_ADDR_ANY_UNFILT_DATA__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Any Threshold
+ *
+ *
+ *
+ *
+ *\param unsigned char *any_th : Address of any_th
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_any_th(unsigned char *any_th)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_1_ADDR_ANY_TH__REG, &v_data_u8r, 1);
+ *any_th = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_1_ADDR_ANY_TH);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Any Threshold
+ *
+ *
+ *
+ *
+ *\param unsigned char any_th:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_any_th(unsigned char any_th)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_1_ADDR_ANY_TH__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_1_ADDR_ANY_TH, any_th);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_1_ADDR_ANY_TH__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Awake Duration
+ *
+ *
+ *
+ *
+ *\param unsigned char *awake_dur : Address of awake_dur
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_awake_dur(unsigned char *awake_dur)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_AWAKE_DUR__REG, &v_data_u8r, 1);
+ *awake_dur = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_AWAKE_DUR);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Awake Duration
+ *
+ *
+ *
+ *
+ *\param unsigned char awake_dur:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************
+ * Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_awake_dur(unsigned char awake_dur)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_AWAKE_DUR__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_AWAKE_DUR, awake_dur);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_AWAKE_DUR__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Any Duration Sample
+ *
+ *
+ *
+ *
+ *\param unsigned char *dursample : Address of dursample
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_any_dursample(unsigned char *dursample)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_DURSAMPLE__REG, &v_data_u8r, 1);
+ *dursample = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_ANY_DURSAMPLE);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Any Duration Sample
+ *
+ *
+ *
+ *
+ *\param unsigned char dursample:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_any_dursample(unsigned char dursample)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_DURSAMPLE__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_ANY_DURSAMPLE, dursample);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_DURSAMPLE__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of Any Enable
+ * Channel X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *data
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * data :
+ * Enable -> 1
+ * disable -> 0
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_any_en_ch(unsigned char channel,
+unsigned char *data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_X__REG, &v_data_u8r, 1);
+ *data = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_X);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Y__REG, &v_data_u8r, 1);
+ *data = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Y);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Z__REG, &v_data_u8r, 1);
+ *data = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Z);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of Any Enable
+ * Channel X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *data
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * data :
+ * Enable -> 1
+ * disable -> 0
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_any_en_ch(unsigned char channel,
+unsigned char data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_X__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_X, data);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_X__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Y__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Y, data);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Y__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Z__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Z, data);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_2_ADDR_ANY_EN_Z__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of FIFO WM
+ * Enable
+ *
+ *
+ *
+ *
+ *\param unsigned char *fifo_wn_en
+ * Enable -> 1
+ * Disable -> 0
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_watermark_enable(
+unsigned char *fifo_wn_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_4_FIFO_WM_EN__REG, &v_data_u8r, 1);
+ *fifo_wn_en = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_4_FIFO_WM_EN);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set FIFO WM Enable
+ *
+ *
+ *
+ *
+ *\param unsigned char *fifo_wn_en
+ * Enable -> 1
+ * Disable -> 0
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_watermark_enable(
+unsigned char fifo_wn_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (fifo_wn_en < C_SMI130_GYRO_Two_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_4_FIFO_WM_EN__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_INT_4_FIFO_WM_EN, fifo_wn_en);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_INT_4_FIFO_WM_EN__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the Interrupt Reset
+ *
+ *
+ *
+ *
+ *\param unsigned char reset_int
+ * 1 -> Reset All Interrupts
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_reset_int(unsigned char reset_int)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_RESET_INT__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RST_LATCH_ADDR_RESET_INT, reset_int);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_RESET_INT__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the Offset Reset
+ *
+ *
+ *
+ *
+ *\param unsigned char offset_reset
+ * 1 -> Resets All the Offsets
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_offset_reset(
+unsigned char offset_reset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_OFFSET_RESET__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RST_LATCH_ADDR_OFFSET_RESET, offset_reset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_OFFSET_RESET__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the Latch Status
+ *
+ *
+ *
+ *
+ *\param unsigned char *latch_status : Address of latch_status
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_latch_status(
+unsigned char *latch_status)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_STATUS__REG, &v_data_u8r, 1);
+ *latch_status = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_STATUS);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the Latch Status
+ *
+ *
+ *
+ *
+ *\param unsigned char latch_status:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_latch_status(
+unsigned char latch_status)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_STATUS__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_STATUS, latch_status);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_STATUS__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the Latch Interrupt
+ *
+ *
+ *
+ *
+ *\param unsigned char *latch_int : Address of latch_int
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_latch_int(unsigned char *latch_int)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_INT__REG, &v_data_u8r, 1);
+ *latch_int = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_INT);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the Latch Interrupt
+ *
+ *
+ *
+ *
+ *\param unsigned char latch_int:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_latch_int(unsigned char latch_int)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_INT__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_INT, latch_int);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_RST_LATCH_ADDR_LATCH_INT__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of High
+ * Hysteresis X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *high_hy
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * high_hy :
+ * Enable -> 1
+ * disable -> 0
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_hy(unsigned char channel,
+unsigned char *high_hy)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_HY_X__REG, &v_data_u8r, 1);
+ *high_hy = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_HY_X);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_HY_Y__REG, &v_data_u8r, 1);
+ *high_hy = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_HY_Y);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_HY_Z__REG, &v_data_u8r, 1);
+ *high_hy = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_HY_Z);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of High
+ * Hysteresis X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *high_hy
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * high_hy :
+ * Enable -> 1
+ * disable -> 0
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_hy(unsigned char channel,
+unsigned char high_hy)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_HY_X__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_HY_X, high_hy);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_HY_X__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_HY_Y__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_HY_Y, high_hy);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_HY_Y__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_HY_Z__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_HY_Z, high_hy);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_HY_Z__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of High
+ * Threshold X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *high_th
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * high_th :
+ * Enable -> 1
+ * disable -> 0
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_th(unsigned char channel,
+unsigned char *high_th)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_TH_X__REG, &v_data_u8r, 1);
+ *high_th = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_TH_X);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_TH_Y__REG, &v_data_u8r, 1);
+ *high_th = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_TH_Y);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_TH_Z__REG, &v_data_u8r, 1);
+ *high_th = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_TH_Z);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of High
+ * Threshold X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *high_th
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * high_th :
+ * Enable -> 1
+ * disable -> 0
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_th(unsigned char channel,
+unsigned char high_th)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_TH_X__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_TH_X, high_th);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_TH_X__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_TH_Y__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_TH_Y, high_th);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_TH_Y__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_TH_Z__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_TH_Z, high_th);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_TH_Z__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of High Enable
+ * Channel X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *high_en
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * high_en :
+ * Enable -> 1
+ * disable -> 0
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_en_ch(unsigned char channel,
+unsigned char *high_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_EN_X__REG, &v_data_u8r, 1);
+ *high_en = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_EN_X);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_EN_Y__REG, &v_data_u8r, 1);
+ *high_en = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_EN_Y);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_EN_Z__REG, &v_data_u8r, 1);
+ *high_en = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_EN_Z);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of High Enable
+ * Channel X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *high_en
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * high_en :
+ * Enable -> 1
+ * disable -> 0
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_en_ch(unsigned char channel,
+unsigned char high_en)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_EN_X__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_EN_X, high_en);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_EN_X__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_EN_Y__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_EN_Y, high_en);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_EN_Y__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_EN_Z__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_HIGH_EN_Z, high_en);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_EN_Z__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get High Duration
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *high_dur
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * *high_dur : Address of high_bw
+ * Pointer to a variable passed as a
+ * parameter
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_dur_ch(unsigned char channel,
+unsigned char *high_dur)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_DUR_X_ADDR, &v_data_u8r, 1);
+ *high_dur = v_data_u8r;
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_DUR_Y_ADDR, &v_data_u8r, 1);
+ *high_dur = v_data_u8r;
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_DUR_Z_ADDR, &v_data_u8r, 1);
+ *high_dur = v_data_u8r;
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set High Duration
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *high_dur
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * high_dur : Value to be written passed as a parameter
+ *
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_dur_ch(unsigned char channel,
+unsigned char high_dur)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ v_data_u8r = high_dur;
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_DUR_X_ADDR, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ v_data_u8r = high_dur;
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_DUR_Y_ADDR, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ v_data_u8r = high_dur;
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_HIGH_DUR_Z_ADDR, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Slow Offset Threshold
+ *
+ *
+ *
+ *
+ *\param unsigned char *offset_th : Address of offset_th
+ * Pointer to a variable passed as a parameter
+
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_slow_offset_th(
+unsigned char *offset_th)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_TH__REG, &v_data_u8r, 1);
+ *offset_th = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_TH);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Slow Offset Threshold
+ *
+ *
+ *
+ *
+ *\param unsigned char offset_th:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_slow_offset_th(unsigned char offset_th)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_TH__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_TH, offset_th);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_TH__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Slow Offset Duration
+ *
+ *
+ *
+ *
+ *\param unsigned char *offset_dur : Address of offset_dur
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_slow_offset_dur(
+unsigned char *offset_dur)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_DUR__REG, &v_data_u8r, 1);
+ *offset_dur = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_DUR);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Slow Offset Duration
+ *
+ *
+ *
+ *
+ *\param unsigned char offset_dur:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_slow_offset_dur(
+unsigned char offset_dur)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_DUR__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_DUR, offset_dur);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_DUR__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Slow Offset Enable channel
+ * X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *slow_offset
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * slow_offset :
+ * Enable -> 1
+ * disable -> 0
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_slow_offset_en_ch(
+unsigned char channel, unsigned char *slow_offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_EN_X__REG, &v_data_u8r, 1);
+ *slow_offset = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_EN_X);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_EN_Y__REG, &v_data_u8r, 1);
+ *slow_offset = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_EN_Y);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_EN_Z__REG, &v_data_u8r, 1);
+ *slow_offset = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_EN_Z);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Slow Offset Enable channel
+ * X,Y,Z
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *slow_offset
+ * channel :
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * slow_offset :
+ * Enable -> 1
+ * disable -> 0
+ *
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_slow_offset_en_ch(
+unsigned char channel, unsigned char slow_offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_EN_X__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_EN_X, slow_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_EN_X__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_EN_Y__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_EN_Y, slow_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_EN_Y__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_EN_Z__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_SLOW_OFFSET_EN_Z,
+ slow_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SLOW_OFFSET_EN_Z__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Fast Offset WordLength and
+ * Auto Offset WordLength
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *offset_wl
+ * channel :
+ * SMI130_GYRO_AUTO_OFFSET_WL -> 0
+ * SMI130_GYRO_FAST_OFFSET_WL -> 1
+ * *offset_wl : Address of high_bw
+ * Pointer to a variable passed as a
+ * parameter
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_offset_wl(unsigned char channel,
+unsigned char *offset_wl)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_AUTO_OFFSET_WL:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_AUTO_OFFSET_WL__REG, &v_data_u8r, 1);
+ *offset_wl = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_AUTO_OFFSET_WL);
+ break;
+ case SMI130_GYRO_FAST_OFFSET_WL:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_WL__REG, &v_data_u8r, 1);
+ *offset_wl = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FAST_OFFSET_WL);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Fast Offset WordLength and
+ * Auto Offset WordLength
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *offset_wl
+ * channel :
+ * SMI130_GYRO_AUTO_OFFSET_WL -> 0
+ * SMI130_GYRO_FAST_OFFSET_WL -> 1
+ * offset_wl : Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_offset_wl(
+unsigned char channel, unsigned char offset_wl)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_AUTO_OFFSET_WL:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_AUTO_OFFSET_WL__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_AUTO_OFFSET_WL, offset_wl);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_AUTO_OFFSET_WL__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_FAST_OFFSET_WL:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_WL__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FAST_OFFSET_WL, offset_wl);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_WL__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to enable fast offset
+ *
+ *
+ *
+ *
+* \param smi130_gyro_enable_fast_offset
+ * Enable -> 1
+ * Disable -> 0
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_enable_fast_offset()
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_EN__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FAST_OFFSET_EN, 1);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_EN__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API read the Fast offset en status from the
+ * 0x32h of 0 to 2 bits.
+ *
+ *
+ *
+ *
+ *\param unsigned char *fast_offset
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return Communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fast_offset_en_ch(
+unsigned char *fast_offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_EN_XYZ__REG, &v_data_u8r, 1);
+ *fast_offset = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FAST_OFFSET_EN_XYZ);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API writes the Fast offset enable bit based
+ * on the Channel selection 0x32h of (0 to 2 bits)
+ *
+ *
+ *
+ *
+* \param unsigned char channel,unsigned char fast_offset
+ *
+ * channel --> SMI130_GYRO_X_AXIS,SMI130_GYRO_Y_AXIS,SMI130_GYRO_Z_AXIS
+ * fast_offset --> 0 - Disable
+ * 1 - Enable
+ *
+ *
+ *
+ * \return Communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fast_offset_en_ch(
+unsigned char channel, unsigned char fast_offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (channel) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_EN_X__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FAST_OFFSET_EN_X, fast_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_EN_X__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_EN_Y__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FAST_OFFSET_EN_Y, fast_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_EN_Y__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_EN_Z__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FAST_OFFSET_EN_Z, fast_offset);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FAST_OFFSET_EN_Z__REG, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of nvm program
+ * remain
+ *
+ *
+ *
+ *
+ *\param unsigned char *nvm_remain
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_nvm_remain(unsigned char *nvm_remain)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_REMAIN__REG, &v_data_u8r, 1);
+ *nvm_remain = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_REMAIN);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of nvm load
+ *
+ *
+ *
+ *
+ *\param unsigned char nvm_load
+ * 1 -> load offset value from NVM
+ * 0 -> no action
+ *
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_nvm_load(unsigned char nvm_load)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_LOAD__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_LOAD, nvm_load);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_LOAD__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of nvmprogram
+ * ready
+ *
+ *
+ *
+ *
+ *\param unsigned char *nvm_rdy
+ * 1 -> program seq finished
+ * 0 -> program seq in progress
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_nvm_rdy(unsigned char *nvm_rdy)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_RDY__REG, &v_data_u8r, 1);
+ *nvm_rdy = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_RDY);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of nvm program
+ * trigger
+ *
+ *
+ *
+ *
+ *\param unsigned char trig
+ * 1 -> trig program seq (wo)
+ * 0 -> No Action
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_nvm_prog_trig(unsigned char prog_trig)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_TRIG__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_TRIG, prog_trig);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_TRIG__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of nvm program
+ * mode
+ *
+ *
+ *
+ *
+* \param unsigned char *prog_mode : Address of *prog_mode
+ * 1 -> Enable program mode
+ * 0 -> Disable program mode
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_nvm_prog_mode(unsigned char *prog_mode)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_MODE__REG, &v_data_u8r, 1);
+ *prog_mode = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_MODE);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/******************************************************************************
+ * Description: *//**brief This API is used to set the status of nvmprogram
+ * mode
+ *
+ *
+ *
+ *
+* \param(unsigned char prog_mode)
+ * 1 -> Enable program mode
+ * 0 -> Disable program mode
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_nvm_prog_mode(unsigned char prog_mode)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_MODE__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_MODE, prog_mode);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_MODE__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of i2c wdt
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char *prog_mode
+ * SMI130_GYRO_I2C_WDT_SEL 1
+ * SMI130_GYRO_I2C_WDT_EN 0
+ * *prog_mode : Address of prog_mode
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_i2c_wdt(unsigned char i2c_wdt,
+unsigned char *prog_mode)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (i2c_wdt) {
+ case SMI130_GYRO_I2C_WDT_EN:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_EN__REG,
+ &v_data_u8r, 1);
+ *prog_mode = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_EN);
+ break;
+ case SMI130_GYRO_I2C_WDT_SEL:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_SEL__REG,
+ &v_data_u8r, 1);
+ *prog_mode = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_SEL);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of i2c wdt
+ *
+ *
+ *
+ *
+ *\param unsigned char channel,unsigned char prog_mode
+ * SMI130_GYRO_I2C_WDT_SEL 1
+ * SMI130_GYRO_I2C_WDT_EN 0
+ * prog_mode : Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_i2c_wdt(unsigned char i2c_wdt,
+unsigned char prog_mode)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (i2c_wdt) {
+ case SMI130_GYRO_I2C_WDT_EN:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_EN__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_EN, prog_mode);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_EN__REG,
+ &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_I2C_WDT_SEL:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_SEL__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_SEL, prog_mode);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_SEL__REG,
+ &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of spi3
+ *
+ *
+ *
+ *
+* \param unsigned char *spi3 : Address of spi3
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_spi3(unsigned char *spi3)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_SPI3__REG, &v_data_u8r, 1);
+ *spi3 = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_SPI3);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of spi3
+ *
+ *
+ *
+ *
+ *\param unsigned char spi3
+ *
+ *
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_spi3(unsigned char spi3)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_SPI3__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_SPI3, spi3);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_BGW_SPI3_WDT_ADDR_SPI3__REG, &v_data_u8r, 1);
+ }
+ return comres;
+}
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_tag(unsigned char *tag)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF1_ADDR_TAG__REG, &v_data_u8r, 1);
+ *tag = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_CGF1_ADDR_TAG);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of Tag
+ *
+ *
+ *
+ *
+ *\param unsigned char tag
+ * Enable -> 1
+ * Disable -> 0
+ *
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_tag(unsigned char tag)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (tag < C_SMI130_GYRO_Two_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF1_ADDR_TAG__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_CGF1_ADDR_TAG, tag);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF1_ADDR_TAG__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get Water Mark Level
+ *
+ *
+ *
+ *
+ *\param unsigned char *water_mark_level : Address of water_mark_level
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_watermarklevel(
+unsigned char *water_mark_level)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF1_ADDR_WML__REG, &v_data_u8r, 1);
+ *water_mark_level = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_CGF1_ADDR_WML);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set Water Mark Level
+ *
+ *
+ *
+ *
+ *\param unsigned char water_mark_level:
+ * Value to be written passed as a parameter
+
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_watermarklevel(
+unsigned char water_mark_level)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (water_mark_level < C_SMI130_GYRO_OneTwentyEight_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF1_ADDR_WML__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_CGF1_ADDR_WML, water_mark_level);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF1_ADDR_WML__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of offset
+ *
+ *
+ *
+ *
+ *\param unsigned char axis,unsigned char *offset
+ * axis ->
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * offset -> Any valid value
+ *
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_offset(unsigned char axis,
+SMI130_GYRO_S16 *offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data1_u8r = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data2_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (axis) {
+ case SMI130_GYRO_X_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_X__REG, &v_data1_u8r, 1);
+ v_data1_u8r = SMI130_GYRO_GET_BITSLICE(v_data1_u8r,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_X);
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_X__REG, &v_data2_u8r, 1);
+ v_data2_u8r = SMI130_GYRO_GET_BITSLICE(v_data2_u8r,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_X);
+ v_data2_u8r = ((v_data2_u8r <<
+ SMI130_GYRO_SHIFT_2_POSITION) | v_data1_u8r);
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr, SMI130_GYRO_OFC2_ADDR, &v_data1_u8r, 1);
+ *offset = (SMI130_GYRO_S16)((((SMI130_GYRO_S16)
+ ((signed char)v_data1_u8r))
+ << SMI130_GYRO_SHIFT_4_POSITION) | (v_data2_u8r));
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Y__REG, &v_data1_u8r, 1);
+ v_data1_u8r = SMI130_GYRO_GET_BITSLICE(v_data1_u8r,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Y);
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_Y__REG, &v_data2_u8r, 1);
+ v_data2_u8r = SMI130_GYRO_GET_BITSLICE(v_data2_u8r,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_Y);
+ v_data2_u8r = ((v_data2_u8r <<
+ SMI130_GYRO_SHIFT_1_POSITION) | v_data1_u8r);
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC3_ADDR, &v_data1_u8r, 1);
+ *offset = (SMI130_GYRO_S16)((((SMI130_GYRO_S16)
+ ((signed char)v_data1_u8r))
+ << SMI130_GYRO_SHIFT_4_POSITION) | (v_data2_u8r));
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Z__REG, &v_data1_u8r, 1);
+ v_data1_u8r = SMI130_GYRO_GET_BITSLICE(v_data1_u8r,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Z);
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_Z__REG, &v_data2_u8r, 1);
+ v_data2_u8r = SMI130_GYRO_GET_BITSLICE(v_data2_u8r,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_Z);
+ v_data2_u8r = ((v_data2_u8r << SMI130_GYRO_SHIFT_1_POSITION)
+ | v_data1_u8r);
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC4_ADDR, &v_data1_u8r, 1);
+ *offset = (SMI130_GYRO_S16)((((SMI130_GYRO_S16)
+ ((signed char)v_data1_u8r))
+ << SMI130_GYRO_SHIFT_4_POSITION) | (v_data2_u8r));
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of offset
+ *
+ *
+ *
+ *
+ *\param unsigned char axis,unsigned char offset
+ * axis ->
+ * SMI130_GYRO_X_AXIS -> 0
+ * SMI130_GYRO_Y_AXIS -> 1
+ * SMI130_GYRO_Z_AXIS -> 2
+ * offset -> Any valid value
+ *
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_offset(
+unsigned char axis, SMI130_GYRO_S16 offset)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data1_u8r = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data2_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (axis) {
+ case SMI130_GYRO_X_AXIS:
+ v_data1_u8r = ((signed char) (offset & 0x0FF0))
+ >> SMI130_GYRO_SHIFT_4_POSITION;
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC2_ADDR, &v_data1_u8r, 1);
+
+ v_data1_u8r = (unsigned char) (offset & 0x000C);
+ v_data2_u8r = SMI130_GYRO_SET_BITSLICE(v_data2_u8r,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_X, v_data1_u8r);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_X__REG, &v_data2_u8r, 1);
+
+ v_data1_u8r = (unsigned char) (offset & 0x0003);
+ v_data2_u8r = SMI130_GYRO_SET_BITSLICE(v_data2_u8r,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_X, v_data1_u8r);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_X__REG, &v_data2_u8r, 1);
+ break;
+ case SMI130_GYRO_Y_AXIS:
+ v_data1_u8r = ((signed char) (offset & 0x0FF0)) >>
+ SMI130_GYRO_SHIFT_4_POSITION;
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC3_ADDR, &v_data1_u8r, 1);
+
+ v_data1_u8r = (unsigned char) (offset & 0x000E);
+ v_data2_u8r = SMI130_GYRO_SET_BITSLICE(v_data2_u8r,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_Y, v_data1_u8r);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_Y__REG, &v_data2_u8r, 1);
+
+ v_data1_u8r = (unsigned char) (offset & 0x0001);
+ v_data2_u8r = SMI130_GYRO_SET_BITSLICE(v_data2_u8r,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Y, v_data1_u8r);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Y__REG, &v_data2_u8r, 1);
+ break;
+ case SMI130_GYRO_Z_AXIS:
+ v_data1_u8r = ((signed char) (offset & 0x0FF0)) >>
+ SMI130_GYRO_SHIFT_4_POSITION;
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC4_ADDR, &v_data1_u8r, 1);
+
+ v_data1_u8r = (unsigned char) (offset & 0x000E);
+ v_data2_u8r = SMI130_GYRO_SET_BITSLICE(v_data2_u8r,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_Z, v_data1_u8r);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_OFC1_ADDR_OFFSET_Z__REG, &v_data2_u8r, 1);
+
+ v_data1_u8r = (unsigned char) (offset & 0x0001);
+ v_data2_u8r = SMI130_GYRO_SET_BITSLICE(v_data2_u8r,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Z, v_data1_u8r);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Z__REG, &v_data2_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of general
+ * purpose register
+ *
+ *
+ *
+ *
+ *\param unsigned char param,unsigned char *value
+ * param ->
+ * SMI130_GYRO_GP0 0
+ * SMI130_GYRO_GP0 1
+ * *value -> Address of high_bw
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_gp(unsigned char param,
+unsigned char *value)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_GP0:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP0_ADDR_GP0__REG, &v_data_u8r, 1);
+ *value = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_TRIM_GP0_ADDR_GP0);
+ break;
+ case SMI130_GYRO_GP1:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP1_ADDR, &v_data_u8r, 1);
+ *value = v_data_u8r;
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of general
+ * purpose register
+ *
+ *
+ *
+ *
+ *\param unsigned char param,unsigned char value
+ * param ->
+ * SMI130_GYRO_GP0 0
+ * SMI130_GYRO_GP0 1
+ * value -> Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_gp(unsigned char param,
+unsigned char value)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ switch (param) {
+ case SMI130_GYRO_GP0:
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP0_ADDR_GP0__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_TRIM_GP0_ADDR_GP0, value);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP0_ADDR_GP0__REG, &v_data_u8r, 1);
+ break;
+ case SMI130_GYRO_GP1:
+ v_data_u8r = value;
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_TRIM_GP1_ADDR, &v_data_u8r, 1);
+ break;
+ default:
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads FIFI data from location 3Fh
+ *
+ *
+ *
+ *
+ * \param
+ * unsigned char *fifo_data : Address of FIFO data bits
+ *
+ *
+ *
+ *
+ * \return result of communication routines
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_FIFO_data_reg(unsigned char *fifo_data)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_DATA_ADDR, &v_data_u8r, 1);
+ *fifo_data = v_data_u8r;
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads interrupt fifo status register byte from 0Eh
+ *
+ *
+ *
+ *
+ * \param
+ * unsigned char *fifo_status : Address of Fifo status register
+ *
+ *
+ * \return
+ * Result of bus communication function
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifostatus_reg(
+unsigned char *fifo_status)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_STATUS_ADDR, fifo_status, 1);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads interrupt fifo status register byte from 0Eh
+ *
+ *
+ *
+ *
+ * \param
+ * unsigned char *fifo_framecount: Address of FIFO status register
+ *
+ *
+ * \return
+ * Result of bus communication function
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_framecount(
+unsigned char *fifo_framecount)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_STATUS_FRAME_COUNTER__REG, &v_data_u8r, 1);
+ *fifo_framecount = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_STATUS_FRAME_COUNTER);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief Reads interrupt fifo status register byte from 0Eh
+ *
+ *
+ *
+ *
+ * \param
+ * unsigned char *fifo_overrun: Address of FIFO status register
+ *
+ *
+ * \return
+ * Result of bus communication function
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_overrun(
+unsigned char *fifo_overrun)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_STATUS_OVERRUN__REG, &v_data_u8r, 1);
+ *fifo_overrun = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_STATUS_OVERRUN);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of fifo mode
+ *
+ *
+ *
+ *
+ *\param unsigned char *mode : Address of mode
+ * fifo_mode 0 --> Bypass
+ * 1 --> FIFO
+ * 2 --> Stream
+ * 3 --> Reserved
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_mode(unsigned char *mode)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF0_ADDR_MODE__REG, &v_data_u8r, 1);
+ *mode = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_CGF0_ADDR_MODE);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used set to FIFO mode
+ *
+ *
+ *
+ *
+* \param 0 --> BYPASS
+ * 1 --> FIFO
+ * 2 --> STREAM
+ *
+ *
+ * \return Communication Results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_mode(unsigned char mode)
+{
+ int comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (mode < C_SMI130_GYRO_Four_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF0_ADDR_MODE__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_CGF0_ADDR_MODE, mode);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF0_ADDR_MODE__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the status of fifo data
+ * sel
+ *
+ *
+ *
+ *
+ *\param unsigned char *data_sel : Address of data_sel
+ * data_sel --> [0:3]
+ * 0 --> X,Y and Z (DEFAULT)
+ * 1 --> X only
+ * 2 --> Y only
+ * 3 --> Z only
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_data_sel(unsigned char *data_sel)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF0_ADDR_DATA_SEL__REG, &v_data_u8r, 1);
+ *data_sel = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_CGF0_ADDR_DATA_SEL);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the status of fifo data
+ * sel
+ *
+ *
+ *
+ *
+ *\param unsigned char data_sel
+ * data_sel --> [0:3]
+ * 0 --> X,Y and Z (DEFAULT)
+ * 1 --> X only
+ * 2 --> Y only
+ * 3 --> Z only
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_data_sel(unsigned char data_sel)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (data_sel < C_SMI130_GYRO_Four_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF0_ADDR_DATA_SEL__REG, &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_FIFO_CGF0_ADDR_DATA_SEL, data_sel);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_FIFO_CGF0_ADDR_DATA_SEL__REG, &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get the operating modes of the
+ * sensor
+ *
+ *
+ *
+ *
+ *\param unsigned char * mode : Address of mode
+ * 0 -> NORMAL
+ * 1 -> SUSPEND
+ * 2 -> DEEP SUSPEND
+ * 3 -> FAST POWERUP
+ * 4 -> ADVANCED POWERSAVING
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_mode(unsigned char *mode)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char data1 = C_SMI130_GYRO_Zero_U8X;
+ unsigned char data2 = C_SMI130_GYRO_Zero_U8X;
+ unsigned char data3 = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == C_SMI130_GYRO_Zero_U8X) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM1_ADDR, &data1, C_SMI130_GYRO_One_U8X);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR, &data2, C_SMI130_GYRO_One_U8X);
+ data1 = (data1 & 0xA0) >> 5;
+ data3 = (data2 & 0x40) >> 6;
+ data2 = (data2 & 0x80) >> 7;
+ if (data3 == 0x01) {
+ *mode = SMI130_GYRO_MODE_ADVANCEDPOWERSAVING;
+ } else {
+ if ((data1 == 0x00) && (data2 == 0x00)) {
+ *mode = SMI130_GYRO_MODE_NORMAL;
+ } else {
+ if ((data1 == 0x01) || (data1 == 0x05)) {
+ *mode = SMI130_GYRO_MODE_DEEPSUSPEND;
+ } else {
+ if ((data1 == 0x04) &&
+ (data2 == 0x00)) {
+ *mode = SMI130_GYRO_MODE_SUSPEND;
+ } else {
+ if ((data1 == 0x04) &&
+ (data2 == 0x01))
+ *mode =
+ SMI130_GYRO_MODE_FASTPOWERUP;
+ }
+ }
+ }
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set the operating Modes of the
+ * sensor
+ *
+ *
+ *
+ *
+ *\param unsigned char Mode
+ * 0 -> NORMAL
+ * 1 -> DEEPSUSPEND
+ * 2 -> SUSPEND
+ * 3 -> Fast Powerup
+ * 4 -> Advance Powerup
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_mode(unsigned char mode)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char data1 = C_SMI130_GYRO_Zero_U8X;
+ unsigned char data2 = C_SMI130_GYRO_Zero_U8X;
+ unsigned char data3 = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_autosleepduration = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_bw_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == C_SMI130_GYRO_Zero_U8X) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (mode < C_SMI130_GYRO_Five_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM1_ADDR, &data1, C_SMI130_GYRO_One_U8X);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR, &data2, C_SMI130_GYRO_One_U8X);
+ switch (mode) {
+ case SMI130_GYRO_MODE_NORMAL:
+ data1 = SMI130_GYRO_SET_BITSLICE(data1,
+ SMI130_GYRO_MODE_LPM1, C_SMI130_GYRO_Zero_U8X);
+ data2 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_FAST_POWERUP,
+ C_SMI130_GYRO_Zero_U8X);
+ data3 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_ADV_POWERSAVING,
+ C_SMI130_GYRO_Zero_U8X);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM1_ADDR, &data1, C_SMI130_GYRO_One_U8X);
+ p_smi130_gyro->delay_msec(1);/*A minimum delay of atleast
+ 450us is required for Multiple write.*/
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR, &data3, C_SMI130_GYRO_One_U8X);
+ break;
+ case SMI130_GYRO_MODE_DEEPSUSPEND:
+ data1 = SMI130_GYRO_SET_BITSLICE(data1,
+ SMI130_GYRO_MODE_LPM1, C_SMI130_GYRO_One_U8X);
+ data2 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_FAST_POWERUP,
+ C_SMI130_GYRO_Zero_U8X);
+ data3 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_ADV_POWERSAVING,
+ C_SMI130_GYRO_Zero_U8X);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM1_ADDR, &data1, C_SMI130_GYRO_One_U8X);
+ p_smi130_gyro->delay_msec(1);/*A minimum delay of atleast
+ 450us is required for Multiple write.*/
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR, &data3, C_SMI130_GYRO_One_U8X);
+ break;
+ case SMI130_GYRO_MODE_SUSPEND:
+ data1 = SMI130_GYRO_SET_BITSLICE(data1,
+ SMI130_GYRO_MODE_LPM1, C_SMI130_GYRO_Four_U8X);
+ data2 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_FAST_POWERUP,
+ C_SMI130_GYRO_Zero_U8X);
+ data3 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_ADV_POWERSAVING,
+ C_SMI130_GYRO_Zero_U8X);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM1_ADDR, &data1, C_SMI130_GYRO_One_U8X);
+ p_smi130_gyro->delay_msec(1);/*A minimum delay of atleast
+ 450us is required for Multiple write.*/
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR, &data3, C_SMI130_GYRO_One_U8X);
+ break;
+ case SMI130_GYRO_MODE_FASTPOWERUP:
+ data1 = SMI130_GYRO_SET_BITSLICE(data1,
+ SMI130_GYRO_MODE_LPM1, C_SMI130_GYRO_Four_U8X);
+ data2 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_FAST_POWERUP,
+ C_SMI130_GYRO_One_U8X);
+ data3 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_ADV_POWERSAVING,
+ C_SMI130_GYRO_Zero_U8X);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM1_ADDR, &data1, C_SMI130_GYRO_One_U8X);
+ p_smi130_gyro->delay_msec(1);/*A minimum delay of atleast
+ 450us is required for Multiple write.*/
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR, &data3, C_SMI130_GYRO_One_U8X);
+ break;
+ case SMI130_GYRO_MODE_ADVANCEDPOWERSAVING:
+ /* Configuring the proper settings for auto
+ sleep duration */
+ smi130_gyro_get_bw(&v_bw_u8r);
+ smi130_gyro_get_autosleepdur(&v_autosleepduration);
+ smi130_gyro_set_autosleepdur(v_autosleepduration,
+ v_bw_u8r);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR, &data2,
+ C_SMI130_GYRO_One_U8X);
+ /* Configuring the advanced power saving mode*/
+ data1 = SMI130_GYRO_SET_BITSLICE(data1,
+ SMI130_GYRO_MODE_LPM1, C_SMI130_GYRO_Zero_U8X);
+ data2 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_FAST_POWERUP,
+ C_SMI130_GYRO_Zero_U8X);
+ data3 = SMI130_GYRO_SET_BITSLICE(data2,
+ SMI130_GYRO_MODE_LPM2_ADDR_ADV_POWERSAVING,
+ C_SMI130_GYRO_One_U8X);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM1_ADDR, &data1, C_SMI130_GYRO_One_U8X);
+ p_smi130_gyro->delay_msec(1);/*A minimum delay of atleast
+ 450us is required for Multiple write.*/
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR, &data3, C_SMI130_GYRO_One_U8X);
+ break;
+ }
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to to do selftest to sensor
+ * sensor
+ *
+ *
+ *
+ *
+ *\param unsigned char *result
+ *
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_selftest(unsigned char *result)
+ {
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char data1 = C_SMI130_GYRO_Zero_U8X;
+ unsigned char data2 = C_SMI130_GYRO_Zero_U8X;
+
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SELF_TEST_ADDR, &data1, C_SMI130_GYRO_One_U8X);
+ data2 = SMI130_GYRO_GET_BITSLICE(data1, SMI130_GYRO_SELF_TEST_ADDR_RATEOK);
+ data1 = SMI130_GYRO_SET_BITSLICE(data1, SMI130_GYRO_SELF_TEST_ADDR_TRIGBIST,
+ C_SMI130_GYRO_One_U8X);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SELF_TEST_ADDR_TRIGBIST__REG, &data1, C_SMI130_GYRO_One_U8X);
+
+ /* Waiting time to complete the selftest process */
+ p_smi130_gyro->delay_msec(10);
+
+ /* Reading Selftest result bir bist_failure */
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_SELF_TEST_ADDR_BISTFAIL__REG, &data1, C_SMI130_GYRO_One_U8X);
+ data1 = SMI130_GYRO_GET_BITSLICE(data1, SMI130_GYRO_SELF_TEST_ADDR_BISTFAIL);
+ if ((data1 == 0x00) && (data2 == 0x01))
+ *result = C_SMI130_GYRO_SUCCESS;
+ else
+ *result = C_SMI130_GYRO_FAILURE;
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get data auto sleep duration
+ *
+ *
+ *
+ *
+ *\param unsigned char *duration : Address of auto sleep duration
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_autosleepdur(unsigned char *duration)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR_AUTOSLEEPDUR__REG, &v_data_u8r, 1);
+ *duration = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MODE_LPM2_ADDR_AUTOSLEEPDUR);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set duration
+ *
+ *
+ *
+ *
+ *\param unsigned char duration:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_autosleepdur(unsigned char duration,
+unsigned char bandwith)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_autosleepduration_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR_AUTOSLEEPDUR__REG,
+ &v_data_u8r, 1);
+ if (duration < C_SMI130_GYRO_Eight_U8X) {
+ switch (bandwith) {
+ case C_SMI130_GYRO_No_Filter_U8X:
+ if (duration >
+ C_SMI130_GYRO_4ms_AutoSleepDur_U8X)
+ v_autosleepduration_u8r =
+ duration;
+ else
+ v_autosleepduration_u8r =
+ C_SMI130_GYRO_4ms_AutoSleepDur_U8X;
+ break;
+ case C_SMI130_GYRO_BW_230Hz_U8X:
+ if (duration >
+ C_SMI130_GYRO_4ms_AutoSleepDur_U8X)
+ v_autosleepduration_u8r =
+ duration;
+ else
+ v_autosleepduration_u8r =
+ C_SMI130_GYRO_4ms_AutoSleepDur_U8X;
+ break;
+ case C_SMI130_GYRO_BW_116Hz_U8X:
+ if (duration >
+ C_SMI130_GYRO_4ms_AutoSleepDur_U8X)
+ v_autosleepduration_u8r =
+ duration;
+ else
+ v_autosleepduration_u8r =
+ C_SMI130_GYRO_4ms_AutoSleepDur_U8X;
+ break;
+ case C_SMI130_GYRO_BW_47Hz_U8X:
+ if (duration >
+ C_SMI130_GYRO_5ms_AutoSleepDur_U8X)
+ v_autosleepduration_u8r =
+ duration;
+ else
+ v_autosleepduration_u8r =
+ C_SMI130_GYRO_5ms_AutoSleepDur_U8X;
+ break;
+ case C_SMI130_GYRO_BW_23Hz_U8X:
+ if (duration >
+ C_SMI130_GYRO_10ms_AutoSleepDur_U8X)
+ v_autosleepduration_u8r =
+ duration;
+ else
+ v_autosleepduration_u8r =
+ C_SMI130_GYRO_10ms_AutoSleepDur_U8X;
+ break;
+ case C_SMI130_GYRO_BW_12Hz_U8X:
+ if (duration >
+ C_SMI130_GYRO_20ms_AutoSleepDur_U8X)
+ v_autosleepduration_u8r =
+ duration;
+ else
+ v_autosleepduration_u8r =
+ C_SMI130_GYRO_20ms_AutoSleepDur_U8X;
+ break;
+ case C_SMI130_GYRO_BW_64Hz_U8X:
+ if (duration >
+ C_SMI130_GYRO_10ms_AutoSleepDur_U8X)
+ v_autosleepduration_u8r =
+ duration;
+ else
+ v_autosleepduration_u8r =
+ C_SMI130_GYRO_10ms_AutoSleepDur_U8X;
+ break;
+ case C_SMI130_GYRO_BW_32Hz_U8X:
+ if (duration >
+ C_SMI130_GYRO_20ms_AutoSleepDur_U8X)
+ v_autosleepduration_u8r =
+ duration;
+ else
+ v_autosleepduration_u8r =
+ C_SMI130_GYRO_20ms_AutoSleepDur_U8X;
+ break;
+ default:
+ if (duration >
+ C_SMI130_GYRO_4ms_AutoSleepDur_U8X)
+ v_autosleepduration_u8r =
+ duration;
+ else
+ v_autosleepduration_u8r =
+ C_SMI130_GYRO_4ms_AutoSleepDur_U8X;
+ break;
+ }
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MODE_LPM2_ADDR_AUTOSLEEPDUR,
+ v_autosleepduration_u8r);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODE_LPM2_ADDR_AUTOSLEEPDUR__REG,
+ &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to get data sleep duration
+ *
+ *
+ *
+ *
+ *\param unsigned char *duration : Address of sleep duration
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_sleepdur(unsigned char *duration)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC(p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODELPM1_ADDR_SLEEPDUR__REG, &v_data_u8r, 1);
+ *duration = SMI130_GYRO_GET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MODELPM1_ADDR_SLEEPDUR);
+ }
+ return comres;
+}
+/* Compiler Switch if applicable
+#ifdef
+
+#endif
+*/
+/*****************************************************************************
+ * Description: *//**brief This API is used to set duration
+ *
+ *
+ *
+ *
+ *\param unsigned char duration:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_sleepdur(unsigned char duration)
+{
+ SMI130_GYRO_RETURN_FUNCTION_TYPE comres = C_SMI130_GYRO_Zero_U8X;
+ unsigned char v_data_u8r = C_SMI130_GYRO_Zero_U8X;
+ if (p_smi130_gyro == SMI130_GYRO_NULL) {
+ return E_SMI130_GYRO_NULL_PTR;
+ } else {
+ if (duration < C_SMI130_GYRO_Eight_U8X) {
+ comres = p_smi130_gyro->SMI130_GYRO_BUS_READ_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODELPM1_ADDR_SLEEPDUR__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = SMI130_GYRO_SET_BITSLICE(v_data_u8r,
+ SMI130_GYRO_MODELPM1_ADDR_SLEEPDUR, duration);
+ comres += p_smi130_gyro->SMI130_GYRO_BUS_WRITE_FUNC
+ (p_smi130_gyro->dev_addr,
+ SMI130_GYRO_MODELPM1_ADDR_SLEEPDUR__REG,
+ &v_data_u8r, 1);
+ } else {
+ comres = E_SMI130_GYRO_OUT_OF_RANGE;
+ }
+ }
+ return comres;
+}
+
diff --git a/drivers/input/sensors/smi130/smi130_gyro.h b/drivers/input/sensors/smi130/smi130_gyro.h
new file mode 100644
index 000000000000..38e52acc304f
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130_gyro.h
@@ -0,0 +1,4705 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename smi130_gyro.h
+ * @date 2013/11/25
+ * @Modification Date 2018/08/28 18:20
+ * @id "8fcde22"
+ * @version 1.5
+ *
+ * @brief Header of SMI130_GYRO API
+*/
+
+/* user defined code to be added here ... */
+#ifndef __SMI130_GYRO_H__
+#define __SMI130_GYRO_H__
+
+#ifdef __KERNEL__
+#define SMI130_GYRO_U16 unsigned short /* 16 bit achieved with short */
+#define SMI130_GYRO_S16 signed short
+#define SMI130_GYRO_S32 signed int /* 32 bit achieved with int */
+#else
+#include <limits.h> /*needed to test integer limits */
+
+
+/* find correct data type for signed/unsigned 16 bit variables \
+by checking max of unsigned variant */
+#if USHRT_MAX == 0xFFFF
+ /* 16 bit achieved with short */
+ #define SMI130_GYRO_U16 unsigned short
+ #define SMI130_GYRO_S16 signed short
+#elif UINT_MAX == 0xFFFF
+ /* 16 bit achieved with int */
+ #define SMI130_GYRO_U16 unsigned int
+ #define SMI130_GYRO_S16 signed int
+#else
+ #error SMI130_GYRO_U16 and SMI130_GYRO_S16 could not be
+ #error defined automatically, please do so manually
+#endif
+
+/* find correct data type for signed 32 bit variables */
+#if INT_MAX == 0x7FFFFFFF
+ /* 32 bit achieved with int */
+ #define SMI130_GYRO_S32 signed int
+#elif LONG_MAX == 0x7FFFFFFF
+ /* 32 bit achieved with long int */
+ #define SMI130_GYRO_S32 signed long int
+#else
+ #error SMI130_GYRO_S32 could not be
+ #error defined automatically, please do so manually
+#endif
+#endif
+
+/**\brief defines the calling parameter types of the SMI130_GYRO_WR_FUNCTION */
+#define SMI130_GYRO_BUS_WR_RETURN_TYPE char
+
+/**\brief links the order of parameters defined in
+SMI130_GYRO_BUS_WR_PARAM_TYPE to function calls used inside the API*/
+#define SMI130_GYRO_BUS_WR_PARAM_TYPES unsigned char, unsigned char,\
+unsigned char *, unsigned char
+
+/**\brief links the order of parameters defined in
+SMI130_GYRO_BUS_WR_PARAM_TYPE to function calls used inside the API*/
+#define SMI130_GYRO_BUS_WR_PARAM_ORDER(device_addr, register_addr,\
+register_data, wr_len)
+
+/* never change this line */
+#define SMI130_GYRO_BUS_WRITE_FUNC(device_addr, register_addr,\
+register_data, wr_len) bus_write(device_addr, register_addr,\
+register_data, wr_len)
+/**\brief defines the return parameter type of the SMI130_GYRO_RD_FUNCTION
+*/
+#define SMI130_GYRO_BUS_RD_RETURN_TYPE char
+/**\brief defines the calling parameter types of the SMI130_GYRO_RD_FUNCTION
+*/
+#define SMI130_GYRO_BUS_RD_PARAM_TYPES unsigned char, unsigned char,\
+unsigned char *, unsigned char
+/**\brief links the order of parameters defined in \
+SMI130_GYRO_BUS_RD_PARAM_TYPE to function calls used inside the API
+*/
+#define SMI130_GYRO_BUS_RD_PARAM_ORDER (device_addr, register_addr,\
+register_data)
+/* never change this line */
+#define SMI130_GYRO_BUS_READ_FUNC(device_addr, register_addr,\
+register_data, rd_len)bus_read(device_addr, register_addr,\
+register_data, rd_len)
+/**\brief defines the return parameter type of the SMI130_GYRO_RD_FUNCTION
+*/
+#define SMI130_GYRO_BURST_RD_RETURN_TYPE char
+/**\brief defines the calling parameter types of the SMI130_GYRO_RD_FUNCTION
+*/
+#define SMI130_GYRO_BURST_RD_PARAM_TYPES unsigned char,\
+unsigned char, unsigned char *, signed int
+/**\brief links the order of parameters defined in \
+SMI130_GYRO_BURST_RD_PARAM_TYPE to function calls used inside the API
+*/
+#define SMI130_GYRO_BURST_RD_PARAM_ORDER (device_addr, register_addr,\
+register_data)
+/* never change this line */
+#define SMI130_GYRO_BURST_READ_FUNC(device_addr, register_addr,\
+register_data, rd_len)burst_read(device_addr, \
+register_addr, register_data, rd_len)
+/**\brief defines the return parameter type of the SMI130_GYRO_DELAY_FUNCTION
+*/
+#define SMI130_GYRO_DELAY_RETURN_TYPE void
+/* never change this line */
+#define SMI130_GYRO_DELAY_FUNC(delay_in_msec)\
+ delay_func(delay_in_msec)
+#define SMI130_GYRO_RETURN_FUNCTION_TYPE int
+/**< This refers SMI130_GYRO return type as char */
+
+#define SMI130_GYRO_I2C_ADDR1 0x68
+#define SMI130_GYRO_I2C_ADDR SMI130_GYRO_I2C_ADDR1
+#define SMI130_GYRO_I2C_ADDR2 0x69
+
+
+
+/*Define of registers*/
+
+/* Hard Wired */
+#define SMI130_GYRO_CHIP_ID_ADDR 0x00
+/**<Address of Chip ID Register*/
+
+
+/* Data Register */
+#define SMI130_GYRO_RATE_X_LSB_ADDR 0x02
+/**< Address of X axis Rate LSB Register */
+#define SMI130_GYRO_RATE_X_MSB_ADDR 0x03
+/**< Address of X axis Rate MSB Register */
+#define SMI130_GYRO_RATE_Y_LSB_ADDR 0x04
+/**< Address of Y axis Rate LSB Register */
+#define SMI130_GYRO_RATE_Y_MSB_ADDR 0x05
+/**< Address of Y axis Rate MSB Register */
+#define SMI130_GYRO_RATE_Z_LSB_ADDR 0x06
+/**< Address of Z axis Rate LSB Register */
+#define SMI130_GYRO_RATE_Z_MSB_ADDR 0x07
+/**< Address of Z axis Rate MSB Register */
+#define SMI130_GYRO_TEMP_ADDR 0x08
+/**< Address of Temperature Data LSB Register */
+
+/* Status Register */
+#define SMI130_GYRO_INT_STATUS0_ADDR 0x09
+/**< Address of Interrupt status Register 0 */
+#define SMI130_GYRO_INT_STATUS1_ADDR 0x0A
+/**< Address of Interrupt status Register 1 */
+#define SMI130_GYRO_INT_STATUS2_ADDR 0x0B
+/**< Address of Interrupt status Register 2 */
+#define SMI130_GYRO_INT_STATUS3_ADDR 0x0C
+/**< Address of Interrupt status Register 3 */
+#define SMI130_GYRO_FIFO_STATUS_ADDR 0x0E
+/**< Address of FIFO status Register */
+
+/* Control Register */
+#define SMI130_GYRO_RANGE_ADDR 0x0F
+/**< Address of Range address Register */
+#define SMI130_GYRO_BW_ADDR 0x10
+/**< Address of Bandwidth Register */
+#define SMI130_GYRO_MODE_LPM1_ADDR 0x11
+/**< Address of Mode LPM1 Register */
+#define SMI130_GYRO_MODE_LPM2_ADDR 0x12
+/**< Address of Mode LPM2 Register */
+#define SMI130_GYRO_RATED_HBW_ADDR 0x13
+/**< Address of Rate HBW Register */
+#define SMI130_GYRO_BGW_SOFTRESET_ADDR 0x14
+/**< Address of BGW Softreset Register */
+#define SMI130_GYRO_INT_ENABLE0_ADDR 0x15
+/**< Address of Interrupt Enable 0 */
+#define SMI130_GYRO_INT_ENABLE1_ADDR 0x16
+/**< Address of Interrupt Enable 1 */
+#define SMI130_GYRO_INT_MAP_0_ADDR 0x17
+/**< Address of Interrupt MAP 0 */
+#define SMI130_GYRO_INT_MAP_1_ADDR 0x18
+/**< Address of Interrupt MAP 1 */
+#define SMI130_GYRO_INT_MAP_2_ADDR 0x19
+/**< Address of Interrupt MAP 2 */
+#define SMI130_GYRO_INT_0_ADDR 0x1A
+/**< Address of Interrupt 0 register */
+#define SMI130_GYRO_INT_1_ADDR 0x1B
+/**< Address of Interrupt 1 register */
+#define SMI130_GYRO_INT_2_ADDR 0x1C
+/**< Address of Interrupt 2 register */
+#define SMI130_GYRO_INT_4_ADDR 0x1E
+/**< Address of Interrupt 4 register */
+#define SMI130_GYRO_RST_LATCH_ADDR 0x21
+/**< Address of Reset Latch Register */
+#define SMI130_GYRO_HIGH_TH_X_ADDR 0x22
+/**< Address of High Th x Address register */
+#define SMI130_GYRO_HIGH_DUR_X_ADDR 0x23
+/**< Address of High Dur x Address register */
+#define SMI130_GYRO_HIGH_TH_Y_ADDR 0x24
+/**< Address of High Th y Address register */
+#define SMI130_GYRO_HIGH_DUR_Y_ADDR 0x25
+/**< Address of High Dur y Address register */
+#define SMI130_GYRO_HIGH_TH_Z_ADDR 0x26
+/**< Address of High Th z Address register */
+#define SMI130_GYRO_HIGH_DUR_Z_ADDR 0x27
+/**< Address of High Dur z Address register */
+#define SMI130_GYRO_SOC_ADDR 0x31
+/**< Address of SOC register */
+#define SMI130_GYRO_A_FOC_ADDR 0x32
+/**< Address of A_FOC Register */
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR 0x33
+/**< Address of Trim NVM control register */
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR 0x34
+/**< Address of BGW SPI3,WDT Register */
+
+
+/* Trim Register */
+#define SMI130_GYRO_OFC1_ADDR 0x36
+/**< Address of OFC1 Register */
+#define SMI130_GYRO_OFC2_ADDR 0x37
+/**< Address of OFC2 Register */
+#define SMI130_GYRO_OFC3_ADDR 0x38
+/**< Address of OFC3 Register */
+#define SMI130_GYRO_OFC4_ADDR 0x39
+/**< Address of OFC4 Register */
+#define SMI130_GYRO_TRIM_GP0_ADDR 0x3A
+/**< Address of Trim GP0 Register */
+#define SMI130_GYRO_TRIM_GP1_ADDR 0x3B
+/**< Address of Trim GP1 Register */
+#define SMI130_GYRO_SELF_TEST_ADDR 0x3C
+/**< Address of BGW Self test Register */
+
+/* Control Register */
+#define SMI130_GYRO_FIFO_CGF1_ADDR 0x3D
+/**< Address of FIFO CGF0 Register */
+#define SMI130_GYRO_FIFO_CGF0_ADDR 0x3E
+/**< Address of FIFO CGF1 Register */
+
+/* Data Register */
+#define SMI130_GYRO_FIFO_DATA_ADDR 0x3F
+/**< Address of FIFO Data Register */
+
+/* Rate X LSB Register */
+#define SMI130_GYRO_RATE_X_LSB_VALUEX__POS 0
+
+/**< Last 8 bits of RateX LSB Registers */
+#define SMI130_GYRO_RATE_X_LSB_VALUEX__LEN 8
+#define SMI130_GYRO_RATE_X_LSB_VALUEX__MSK 0xFF
+#define SMI130_GYRO_RATE_X_LSB_VALUEX__REG SMI130_GYRO_RATE_X_LSB_ADDR
+
+/* Rate Y LSB Register */
+/**< Last 8 bits of RateY LSB Registers */
+#define SMI130_GYRO_RATE_Y_LSB_VALUEY__POS 0
+#define SMI130_GYRO_RATE_Y_LSB_VALUEY__LEN 8
+#define SMI130_GYRO_RATE_Y_LSB_VALUEY__MSK 0xFF
+#define SMI130_GYRO_RATE_Y_LSB_VALUEY__REG SMI130_GYRO_RATE_Y_LSB_ADDR
+
+/* Rate Z LSB Register */
+/**< Last 8 bits of RateZ LSB Registers */
+#define SMI130_GYRO_RATE_Z_LSB_VALUEZ__POS 0
+#define SMI130_GYRO_RATE_Z_LSB_VALUEZ__LEN 8
+#define SMI130_GYRO_RATE_Z_LSB_VALUEZ__MSK 0xFF
+#define SMI130_GYRO_RATE_Z_LSB_VALUEZ__REG SMI130_GYRO_RATE_Z_LSB_ADDR
+
+/* Interrupt status 0 Register */
+ /**< 2th bit of Interrupt status 0 register */
+#define SMI130_GYRO_INT_STATUS0_ANY_INT__POS 2
+#define SMI130_GYRO_INT_STATUS0_ANY_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS0_ANY_INT__MSK 0x04
+#define SMI130_GYRO_INT_STATUS0_ANY_INT__REG SMI130_GYRO_INT_STATUS0_ADDR
+
+/**< 1st bit of Interrupt status 0 register */
+#define SMI130_GYRO_INT_STATUS0_HIGH_INT__POS 1
+#define SMI130_GYRO_INT_STATUS0_HIGH_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS0_HIGH_INT__MSK 0x02
+#define SMI130_GYRO_INT_STATUS0_HIGH_INT__REG SMI130_GYRO_INT_STATUS0_ADDR
+
+ /**< 1st and 2nd bit of Interrupt status 0 register */
+#define SMI130_GYRO_INT_STATUSZERO__POS 1
+#define SMI130_GYRO_INT_STATUSZERO__LEN 2
+#define SMI130_GYRO_INT_STATUSZERO__MSK 0x06
+#define SMI130_GYRO_INT_STATUSZERO__REG SMI130_GYRO_INT_STATUS0_ADDR
+
+/* Interrupt status 1 Register */
+/**< 7th bit of Interrupt status 1 register */
+#define SMI130_GYRO_INT_STATUS1_DATA_INT__POS 7
+#define SMI130_GYRO_INT_STATUS1_DATA_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS1_DATA_INT__MSK 0x80
+#define SMI130_GYRO_INT_STATUS1_DATA_INT__REG SMI130_GYRO_INT_STATUS1_ADDR
+
+ /**< 6th bit of Interrupt status 1 register */
+#define SMI130_GYRO_INT_STATUS1_AUTO_OFFSET_INT__POS 6
+#define SMI130_GYRO_INT_STATUS1_AUTO_OFFSET_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS1_AUTO_OFFSET_INT__MSK 0x40
+#define SMI130_GYRO_INT_STATUS1_AUTO_OFFSET_INT__REG SMI130_GYRO_INT_STATUS1_ADDR
+
+/**< 5th bit of Interrupt status 1 register */
+#define SMI130_GYRO_INT_STATUS1_FAST_OFFSET_INT__POS 5
+#define SMI130_GYRO_INT_STATUS1_FAST_OFFSET_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS1_FAST_OFFSET_INT__MSK 0x20
+#define SMI130_GYRO_INT_STATUS1_FAST_OFFSET_INT__REG SMI130_GYRO_INT_STATUS1_ADDR
+
+/**< 4th bit of Interrupt status 1 register */
+#define SMI130_GYRO_INT_STATUS1_FIFO_INT__POS 4
+#define SMI130_GYRO_INT_STATUS1_FIFO_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS1_FIFO_INT__MSK 0x10
+#define SMI130_GYRO_INT_STATUS1_FIFO_INT__REG SMI130_GYRO_INT_STATUS1_ADDR
+
+/**< MSB 4 bits of Interrupt status1 register */
+#define SMI130_GYRO_INT_STATUSONE__POS 4
+#define SMI130_GYRO_INT_STATUSONE__LEN 4
+#define SMI130_GYRO_INT_STATUSONE__MSK 0xF0
+#define SMI130_GYRO_INT_STATUSONE__REG SMI130_GYRO_INT_STATUS1_ADDR
+
+/* Interrupt status 2 Register */
+/**< 3th bit of Interrupt status 2 register */
+#define SMI130_GYRO_INT_STATUS2_ANY_SIGN_INT__POS 3
+#define SMI130_GYRO_INT_STATUS2_ANY_SIGN_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS2_ANY_SIGN_INT__MSK 0x08
+#define SMI130_GYRO_INT_STATUS2_ANY_SIGN_INT__REG SMI130_GYRO_INT_STATUS2_ADDR
+
+/**< 2th bit of Interrupt status 2 register */
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTZ_INT__POS 2
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTZ_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTZ_INT__MSK 0x04
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTZ_INT__REG SMI130_GYRO_INT_STATUS2_ADDR
+
+/**< 1st bit of Interrupt status 2 register */
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTY_INT__POS 1
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTY_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTY_INT__MSK 0x02
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTY_INT__REG SMI130_GYRO_INT_STATUS2_ADDR
+
+/**< 0th bit of Interrupt status 2 register */
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTX_INT__POS 0
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTX_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTX_INT__MSK 0x01
+#define SMI130_GYRO_INT_STATUS2_ANY_FIRSTX_INT__REG SMI130_GYRO_INT_STATUS2_ADDR
+
+/**< 4 bits of Interrupt status 2 register */
+#define SMI130_GYRO_INT_STATUSTWO__POS 0
+#define SMI130_GYRO_INT_STATUSTWO__LEN 4
+#define SMI130_GYRO_INT_STATUSTWO__MSK 0x0F
+#define SMI130_GYRO_INT_STATUSTWO__REG SMI130_GYRO_INT_STATUS2_ADDR
+
+/* Interrupt status 3 Register */
+/**< 3th bit of Interrupt status 3 register */
+#define SMI130_GYRO_INT_STATUS3_HIGH_SIGN_INT__POS 3
+#define SMI130_GYRO_INT_STATUS3_HIGH_SIGN_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS3_HIGH_SIGN_INT__MSK 0x08
+#define SMI130_GYRO_INT_STATUS3_HIGH_SIGN_INT__REG SMI130_GYRO_INT_STATUS3_ADDR
+
+/**< 2th bit of Interrupt status 3 register */
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTZ_INT__POS 2
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTZ_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTZ_INT__MSK 0x04
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTZ_INT__REG SMI130_GYRO_INT_STATUS3_ADDR
+
+/**< 1st bit of Interrupt status 3 register */
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTY_INT__POS 1
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTY_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTY_INT__MSK 0x02
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTY_INT__REG SMI130_GYRO_INT_STATUS3_ADDR
+
+/**< 0th bit of Interrupt status 3 register */
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTX_INT__POS 0
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTX_INT__LEN 1
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTX_INT__MSK 0x01
+#define SMI130_GYRO_INT_STATUS3_HIGH_FIRSTX_INT__REG SMI130_GYRO_INT_STATUS3_ADDR
+
+/**< LSB 4 bits of Interrupt status 3 register */
+#define SMI130_GYRO_INT_STATUSTHREE__POS 0
+#define SMI130_GYRO_INT_STATUSTHREE__LEN 4
+#define SMI130_GYRO_INT_STATUSTHREE__MSK 0x0F
+#define SMI130_GYRO_INT_STATUSTHREE__REG SMI130_GYRO_INT_STATUS3_ADDR
+
+/* SMI130_GYRO FIFO Status Register */
+/**< 7th bit of FIFO status Register */
+#define SMI130_GYRO_FIFO_STATUS_OVERRUN__POS 7
+#define SMI130_GYRO_FIFO_STATUS_OVERRUN__LEN 1
+#define SMI130_GYRO_FIFO_STATUS_OVERRUN__MSK 0x80
+#define SMI130_GYRO_FIFO_STATUS_OVERRUN__REG SMI130_GYRO_FIFO_STATUS_ADDR
+
+/**< First 7 bits of FIFO status Register */
+#define SMI130_GYRO_FIFO_STATUS_FRAME_COUNTER__POS 0
+#define SMI130_GYRO_FIFO_STATUS_FRAME_COUNTER__LEN 7
+#define SMI130_GYRO_FIFO_STATUS_FRAME_COUNTER__MSK 0x7F
+#define SMI130_GYRO_FIFO_STATUS_FRAME_COUNTER__REG SMI130_GYRO_FIFO_STATUS_ADDR
+
+/**< First 3 bits of range Registers */
+#define SMI130_GYRO_RANGE_ADDR_RANGE__POS 0
+#define SMI130_GYRO_RANGE_ADDR_RANGE__LEN 3
+#define SMI130_GYRO_RANGE_ADDR_RANGE__MSK 0x07
+#define SMI130_GYRO_RANGE_ADDR_RANGE__REG SMI130_GYRO_RANGE_ADDR
+
+/**< Last bit of Bandwidth Registers */
+#define SMI130_GYRO_BW_ADDR_HIGH_RES__POS 7
+#define SMI130_GYRO_BW_ADDR_HIGH_RES__LEN 1
+#define SMI130_GYRO_BW_ADDR_HIGH_RES__MSK 0x80
+#define SMI130_GYRO_BW_ADDR_HIGH_RES__REG SMI130_GYRO_BW_ADDR
+
+/**< First 3 bits of Bandwidth Registers */
+#define SMI130_GYRO_BW_ADDR__POS 0
+#define SMI130_GYRO_BW_ADDR__LEN 3
+#define SMI130_GYRO_BW_ADDR__MSK 0x07
+#define SMI130_GYRO_BW_ADDR__REG SMI130_GYRO_BW_ADDR
+
+/**< 6th bit of Bandwidth Registers */
+#define SMI130_GYRO_BW_ADDR_IMG_STB__POS 6
+#define SMI130_GYRO_BW_ADDR_IMG_STB__LEN 1
+#define SMI130_GYRO_BW_ADDR_IMG_STB__MSK 0x40
+#define SMI130_GYRO_BW_ADDR_IMG_STB__REG SMI130_GYRO_BW_ADDR
+
+/**< 5th and 7th bit of LPM1 Register */
+#define SMI130_GYRO_MODE_LPM1__POS 5
+#define SMI130_GYRO_MODE_LPM1__LEN 3
+#define SMI130_GYRO_MODE_LPM1__MSK 0xA0
+#define SMI130_GYRO_MODE_LPM1__REG SMI130_GYRO_MODE_LPM1_ADDR
+
+/**< 1st to 3rd bit of LPM1 Register */
+#define SMI130_GYRO_MODELPM1_ADDR_SLEEPDUR__POS 1
+#define SMI130_GYRO_MODELPM1_ADDR_SLEEPDUR__LEN 3
+#define SMI130_GYRO_MODELPM1_ADDR_SLEEPDUR__MSK 0x0E
+#define SMI130_GYRO_MODELPM1_ADDR_SLEEPDUR__REG SMI130_GYRO_MODE_LPM1_ADDR
+
+/**< 7th bit of Mode LPM2 Register */
+#define SMI130_GYRO_MODE_LPM2_ADDR_FAST_POWERUP__POS 7
+#define SMI130_GYRO_MODE_LPM2_ADDR_FAST_POWERUP__LEN 1
+#define SMI130_GYRO_MODE_LPM2_ADDR_FAST_POWERUP__MSK 0x80
+#define SMI130_GYRO_MODE_LPM2_ADDR_FAST_POWERUP__REG SMI130_GYRO_MODE_LPM2_ADDR
+
+/**< 6th bit of Mode LPM2 Register */
+#define SMI130_GYRO_MODE_LPM2_ADDR_ADV_POWERSAVING__POS 6
+#define SMI130_GYRO_MODE_LPM2_ADDR_ADV_POWERSAVING__LEN 1
+#define SMI130_GYRO_MODE_LPM2_ADDR_ADV_POWERSAVING__MSK 0x40
+#define SMI130_GYRO_MODE_LPM2_ADDR_ADV_POWERSAVING__REG SMI130_GYRO_MODE_LPM2_ADDR
+
+/**< 4th & 5th bit of Mode LPM2 Register */
+#define SMI130_GYRO_MODE_LPM2_ADDR_EXT_TRI_SEL__POS 4
+#define SMI130_GYRO_MODE_LPM2_ADDR_EXT_TRI_SEL__LEN 2
+#define SMI130_GYRO_MODE_LPM2_ADDR_EXT_TRI_SEL__MSK 0x30
+#define SMI130_GYRO_MODE_LPM2_ADDR_EXT_TRI_SEL__REG SMI130_GYRO_MODE_LPM2_ADDR
+
+/**< 0th to 2nd bit of LPM2 Register */
+#define SMI130_GYRO_MODE_LPM2_ADDR_AUTOSLEEPDUR__POS 0
+#define SMI130_GYRO_MODE_LPM2_ADDR_AUTOSLEEPDUR__LEN 3
+#define SMI130_GYRO_MODE_LPM2_ADDR_AUTOSLEEPDUR__MSK 0x07
+#define SMI130_GYRO_MODE_LPM2_ADDR_AUTOSLEEPDUR__REG SMI130_GYRO_MODE_LPM2_ADDR
+
+/**< 7th bit of HBW Register */
+#define SMI130_GYRO_RATED_HBW_ADDR_DATA_HIGHBW__POS 7
+#define SMI130_GYRO_RATED_HBW_ADDR_DATA_HIGHBW__LEN 1
+#define SMI130_GYRO_RATED_HBW_ADDR_DATA_HIGHBW__MSK 0x80
+#define SMI130_GYRO_RATED_HBW_ADDR_DATA_HIGHBW__REG SMI130_GYRO_RATED_HBW_ADDR
+
+/**< 6th bit of HBW Register */
+#define SMI130_GYRO_RATED_HBW_ADDR_SHADOW_DIS__POS 6
+#define SMI130_GYRO_RATED_HBW_ADDR_SHADOW_DIS__LEN 1
+#define SMI130_GYRO_RATED_HBW_ADDR_SHADOW_DIS__MSK 0x40
+#define SMI130_GYRO_RATED_HBW_ADDR_SHADOW_DIS__REG SMI130_GYRO_RATED_HBW_ADDR
+
+/**< 7th bit of Interrupt Enable 0 Registers */
+#define SMI130_GYRO_INT_ENABLE0_DATAEN__POS 7
+#define SMI130_GYRO_INT_ENABLE0_DATAEN__LEN 1
+#define SMI130_GYRO_INT_ENABLE0_DATAEN__MSK 0x80
+#define SMI130_GYRO_INT_ENABLE0_DATAEN__REG SMI130_GYRO_INT_ENABLE0_ADDR
+
+/**< 6th bit of Interrupt Enable 0 Registers */
+#define SMI130_GYRO_INT_ENABLE0_FIFOEN__POS 6
+#define SMI130_GYRO_INT_ENABLE0_FIFOEN__LEN 1
+#define SMI130_GYRO_INT_ENABLE0_FIFOEN__MSK 0x40
+#define SMI130_GYRO_INT_ENABLE0_FIFOEN__REG SMI130_GYRO_INT_ENABLE0_ADDR
+
+/**< 2nd bit of Interrupt Enable 0 Registers */
+#define SMI130_GYRO_INT_ENABLE0_AUTO_OFFSETEN__POS 2
+#define SMI130_GYRO_INT_ENABLE0_AUTO_OFFSETEN__LEN 1
+#define SMI130_GYRO_INT_ENABLE0_AUTO_OFFSETEN__MSK 0x04
+#define SMI130_GYRO_INT_ENABLE0_AUTO_OFFSETEN__REG SMI130_GYRO_INT_ENABLE0_ADDR
+
+/**< 3rd bit of Interrupt Enable 1 Registers */
+#define SMI130_GYRO_INT_ENABLE1_IT2_OD__POS 3
+#define SMI130_GYRO_INT_ENABLE1_IT2_OD__LEN 1
+#define SMI130_GYRO_INT_ENABLE1_IT2_OD__MSK 0x08
+#define SMI130_GYRO_INT_ENABLE1_IT2_OD__REG SMI130_GYRO_INT_ENABLE1_ADDR
+
+/**< 2nd bit of Interrupt Enable 1 Registers */
+#define SMI130_GYRO_INT_ENABLE1_IT2_LVL__POS 2
+#define SMI130_GYRO_INT_ENABLE1_IT2_LVL__LEN 1
+#define SMI130_GYRO_INT_ENABLE1_IT2_LVL__MSK 0x04
+#define SMI130_GYRO_INT_ENABLE1_IT2_LVL__REG SMI130_GYRO_INT_ENABLE1_ADDR
+
+/**< 1st bit of Interrupt Enable 1 Registers */
+#define SMI130_GYRO_INT_ENABLE1_IT1_OD__POS 1
+#define SMI130_GYRO_INT_ENABLE1_IT1_OD__LEN 1
+#define SMI130_GYRO_INT_ENABLE1_IT1_OD__MSK 0x02
+#define SMI130_GYRO_INT_ENABLE1_IT1_OD__REG SMI130_GYRO_INT_ENABLE1_ADDR
+
+/**< 0th bit of Interrupt Enable 1 Registers */
+#define SMI130_GYRO_INT_ENABLE1_IT1_LVL__POS 0
+#define SMI130_GYRO_INT_ENABLE1_IT1_LVL__LEN 1
+#define SMI130_GYRO_INT_ENABLE1_IT1_LVL__MSK 0x01
+#define SMI130_GYRO_INT_ENABLE1_IT1_LVL__REG SMI130_GYRO_INT_ENABLE1_ADDR
+
+/**< 3rd bit of Interrupt MAP 0 Registers */
+#define SMI130_GYRO_INT_MAP_0_INT1_HIGH__POS 3
+#define SMI130_GYRO_INT_MAP_0_INT1_HIGH__LEN 1
+#define SMI130_GYRO_INT_MAP_0_INT1_HIGH__MSK 0x08
+#define SMI130_GYRO_INT_MAP_0_INT1_HIGH__REG SMI130_GYRO_INT_MAP_0_ADDR
+
+/**< 1st bit of Interrupt MAP 0 Registers */
+#define SMI130_GYRO_INT_MAP_0_INT1_ANY__POS 1
+#define SMI130_GYRO_INT_MAP_0_INT1_ANY__LEN 1
+#define SMI130_GYRO_INT_MAP_0_INT1_ANY__MSK 0x02
+#define SMI130_GYRO_INT_MAP_0_INT1_ANY__REG SMI130_GYRO_INT_MAP_0_ADDR
+
+/**< 7th bit of MAP_1Registers */
+#define SMI130_GYRO_MAP_1_INT2_DATA__POS 7
+#define SMI130_GYRO_MAP_1_INT2_DATA__LEN 1
+#define SMI130_GYRO_MAP_1_INT2_DATA__MSK 0x80
+#define SMI130_GYRO_MAP_1_INT2_DATA__REG SMI130_GYRO_INT_MAP_1_ADDR
+
+/**< 6th bit of MAP_1Registers */
+#define SMI130_GYRO_MAP_1_INT2_FAST_OFFSET__POS 6
+#define SMI130_GYRO_MAP_1_INT2_FAST_OFFSET__LEN 1
+#define SMI130_GYRO_MAP_1_INT2_FAST_OFFSET__MSK 0x40
+#define SMI130_GYRO_MAP_1_INT2_FAST_OFFSET__REG SMI130_GYRO_INT_MAP_1_ADDR
+
+/**< 5th bit of MAP_1Registers */
+#define SMI130_GYRO_MAP_1_INT2_FIFO__POS 5
+#define SMI130_GYRO_MAP_1_INT2_FIFO__LEN 1
+#define SMI130_GYRO_MAP_1_INT2_FIFO__MSK 0x20
+#define SMI130_GYRO_MAP_1_INT2_FIFO__REG SMI130_GYRO_INT_MAP_1_ADDR
+
+/**< 4th bit of MAP_1Registers */
+#define SMI130_GYRO_MAP_1_INT2_AUTO_OFFSET__POS 4
+#define SMI130_GYRO_MAP_1_INT2_AUTO_OFFSET__LEN 1
+#define SMI130_GYRO_MAP_1_INT2_AUTO_OFFSET__MSK 0x10
+#define SMI130_GYRO_MAP_1_INT2_AUTO_OFFSET__REG SMI130_GYRO_INT_MAP_1_ADDR
+
+/**< 3rd bit of MAP_1Registers */
+#define SMI130_GYRO_MAP_1_INT1_AUTO_OFFSET__POS 3
+#define SMI130_GYRO_MAP_1_INT1_AUTO_OFFSET__LEN 1
+#define SMI130_GYRO_MAP_1_INT1_AUTO_OFFSET__MSK 0x08
+#define SMI130_GYRO_MAP_1_INT1_AUTO_OFFSET__REG SMI130_GYRO_INT_MAP_1_ADDR
+
+/**< 2nd bit of MAP_1Registers */
+#define SMI130_GYRO_MAP_1_INT1_FIFO__POS 2
+#define SMI130_GYRO_MAP_1_INT1_FIFO__LEN 1
+#define SMI130_GYRO_MAP_1_INT1_FIFO__MSK 0x04
+#define SMI130_GYRO_MAP_1_INT1_FIFO__REG SMI130_GYRO_INT_MAP_1_ADDR
+
+/**< 1st bit of MAP_1Registers */
+#define SMI130_GYRO_MAP_1_INT1_FAST_OFFSET__POS 1
+#define SMI130_GYRO_MAP_1_INT1_FAST_OFFSET__LEN 1
+#define SMI130_GYRO_MAP_1_INT1_FAST_OFFSET__MSK 0x02
+#define SMI130_GYRO_MAP_1_INT1_FAST_OFFSET__REG SMI130_GYRO_INT_MAP_1_ADDR
+
+/**< 0th bit of MAP_1Registers */
+#define SMI130_GYRO_MAP_1_INT1_DATA__POS 0
+#define SMI130_GYRO_MAP_1_INT1_DATA__LEN 1
+#define SMI130_GYRO_MAP_1_INT1_DATA__MSK 0x01
+#define SMI130_GYRO_MAP_1_INT1_DATA__REG SMI130_GYRO_INT_MAP_1_ADDR
+
+/**< 3rd bit of Interrupt Map 2 Registers */
+#define SMI130_GYRO_INT_MAP_2_INT2_HIGH__POS 3
+#define SMI130_GYRO_INT_MAP_2_INT2_HIGH__LEN 1
+#define SMI130_GYRO_INT_MAP_2_INT2_HIGH__MSK 0x08
+#define SMI130_GYRO_INT_MAP_2_INT2_HIGH__REG SMI130_GYRO_INT_MAP_2_ADDR
+
+/**< 1st bit of Interrupt Map 2 Registers */
+#define SMI130_GYRO_INT_MAP_2_INT2_ANY__POS 1
+#define SMI130_GYRO_INT_MAP_2_INT2_ANY__LEN 1
+#define SMI130_GYRO_INT_MAP_2_INT2_ANY__MSK 0x02
+#define SMI130_GYRO_INT_MAP_2_INT2_ANY__REG SMI130_GYRO_INT_MAP_2_ADDR
+
+/**< 5th bit of Interrupt 0 Registers */
+#define SMI130_GYRO_INT_0_ADDR_SLOW_OFFSET_UNFILT__POS 5
+#define SMI130_GYRO_INT_0_ADDR_SLOW_OFFSET_UNFILT__LEN 1
+#define SMI130_GYRO_INT_0_ADDR_SLOW_OFFSET_UNFILT__MSK 0x20
+#define SMI130_GYRO_INT_0_ADDR_SLOW_OFFSET_UNFILT__REG SMI130_GYRO_INT_0_ADDR
+
+/**< 3rd bit of Interrupt 0 Registers */
+#define SMI130_GYRO_INT_0_ADDR_HIGH_UNFILT_DATA__POS 3
+#define SMI130_GYRO_INT_0_ADDR_HIGH_UNFILT_DATA__LEN 1
+#define SMI130_GYRO_INT_0_ADDR_HIGH_UNFILT_DATA__MSK 0x08
+#define SMI130_GYRO_INT_0_ADDR_HIGH_UNFILT_DATA__REG SMI130_GYRO_INT_0_ADDR
+
+/**< 1st bit of Interrupt 0 Registers */
+#define SMI130_GYRO_INT_0_ADDR_ANY_UNFILT_DATA__POS 1
+#define SMI130_GYRO_INT_0_ADDR_ANY_UNFILT_DATA__LEN 1
+#define SMI130_GYRO_INT_0_ADDR_ANY_UNFILT_DATA__MSK 0x02
+#define SMI130_GYRO_INT_0_ADDR_ANY_UNFILT_DATA__REG SMI130_GYRO_INT_0_ADDR
+
+/**< 7th bit of INT_1 Registers */
+#define SMI130_GYRO_INT_1_ADDR_FAST_OFFSET_UNFILT__POS 7
+#define SMI130_GYRO_INT_1_ADDR_FAST_OFFSET_UNFILT__LEN 1
+#define SMI130_GYRO_INT_1_ADDR_FAST_OFFSET_UNFILT__MSK 0x80
+#define SMI130_GYRO_INT_1_ADDR_FAST_OFFSET_UNFILT__REG SMI130_GYRO_INT_1_ADDR
+
+/**< First 7 bits of INT_1 Registers */
+#define SMI130_GYRO_INT_1_ADDR_ANY_TH__POS 0
+#define SMI130_GYRO_INT_1_ADDR_ANY_TH__LEN 7
+#define SMI130_GYRO_INT_1_ADDR_ANY_TH__MSK 0x7F
+#define SMI130_GYRO_INT_1_ADDR_ANY_TH__REG SMI130_GYRO_INT_1_ADDR
+
+/**< Last 2 bits of INT 2Registers */
+#define SMI130_GYRO_INT_2_ADDR_AWAKE_DUR__POS 6
+#define SMI130_GYRO_INT_2_ADDR_AWAKE_DUR__LEN 2
+#define SMI130_GYRO_INT_2_ADDR_AWAKE_DUR__MSK 0xC0
+#define SMI130_GYRO_INT_2_ADDR_AWAKE_DUR__REG SMI130_GYRO_INT_2_ADDR
+
+/**< 4th & 5th bit of INT 2Registers */
+#define SMI130_GYRO_INT_2_ADDR_ANY_DURSAMPLE__POS 4
+#define SMI130_GYRO_INT_2_ADDR_ANY_DURSAMPLE__LEN 2
+#define SMI130_GYRO_INT_2_ADDR_ANY_DURSAMPLE__MSK 0x30
+#define SMI130_GYRO_INT_2_ADDR_ANY_DURSAMPLE__REG SMI130_GYRO_INT_2_ADDR
+
+/**< 2nd bit of INT 2Registers */
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_Z__POS 2
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_Z__LEN 1
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_Z__MSK 0x04
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_Z__REG SMI130_GYRO_INT_2_ADDR
+
+/**< 1st bit of INT 2Registers */
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_Y__POS 1
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_Y__LEN 1
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_Y__MSK 0x02
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_Y__REG SMI130_GYRO_INT_2_ADDR
+
+/**< 0th bit of INT 2Registers */
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_X__POS 0
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_X__LEN 1
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_X__MSK 0x01
+#define SMI130_GYRO_INT_2_ADDR_ANY_EN_X__REG SMI130_GYRO_INT_2_ADDR
+
+/**< Last bit of INT 4 Registers */
+#define SMI130_GYRO_INT_4_FIFO_WM_EN__POS 7
+#define SMI130_GYRO_INT_4_FIFO_WM_EN__LEN 1
+#define SMI130_GYRO_INT_4_FIFO_WM_EN__MSK 0x80
+#define SMI130_GYRO_INT_4_FIFO_WM_EN__REG SMI130_GYRO_INT_4_ADDR
+
+/**< Last bit of Reset Latch Registers */
+#define SMI130_GYRO_RST_LATCH_ADDR_RESET_INT__POS 7
+#define SMI130_GYRO_RST_LATCH_ADDR_RESET_INT__LEN 1
+#define SMI130_GYRO_RST_LATCH_ADDR_RESET_INT__MSK 0x80
+#define SMI130_GYRO_RST_LATCH_ADDR_RESET_INT__REG SMI130_GYRO_RST_LATCH_ADDR
+
+/**< 6th bit of Reset Latch Registers */
+#define SMI130_GYRO_RST_LATCH_ADDR_OFFSET_RESET__POS 6
+#define SMI130_GYRO_RST_LATCH_ADDR_OFFSET_RESET__LEN 1
+#define SMI130_GYRO_RST_LATCH_ADDR_OFFSET_RESET__MSK 0x40
+#define SMI130_GYRO_RST_LATCH_ADDR_OFFSET_RESET__REG SMI130_GYRO_RST_LATCH_ADDR
+
+/**< 4th bit of Reset Latch Registers */
+#define SMI130_GYRO_RST_LATCH_ADDR_LATCH_STATUS__POS 4
+#define SMI130_GYRO_RST_LATCH_ADDR_LATCH_STATUS__LEN 1
+#define SMI130_GYRO_RST_LATCH_ADDR_LATCH_STATUS__MSK 0x10
+#define SMI130_GYRO_RST_LATCH_ADDR_LATCH_STATUS__REG SMI130_GYRO_RST_LATCH_ADDR
+
+/**< First 4 bits of Reset Latch Registers */
+#define SMI130_GYRO_RST_LATCH_ADDR_LATCH_INT__POS 0
+#define SMI130_GYRO_RST_LATCH_ADDR_LATCH_INT__LEN 4
+#define SMI130_GYRO_RST_LATCH_ADDR_LATCH_INT__MSK 0x0F
+#define SMI130_GYRO_RST_LATCH_ADDR_LATCH_INT__REG SMI130_GYRO_RST_LATCH_ADDR
+
+/**< Last 2 bits of HIGH_TH_X Registers */
+#define SMI130_GYRO_HIGH_HY_X__POS 6
+#define SMI130_GYRO_HIGH_HY_X__LEN 2
+#define SMI130_GYRO_HIGH_HY_X__MSK 0xC0
+#define SMI130_GYRO_HIGH_HY_X__REG SMI130_GYRO_HIGH_TH_X_ADDR
+
+/**< 5 bits of HIGH_TH_X Registers */
+#define SMI130_GYRO_HIGH_TH_X__POS 1
+#define SMI130_GYRO_HIGH_TH_X__LEN 5
+#define SMI130_GYRO_HIGH_TH_X__MSK 0x3E
+#define SMI130_GYRO_HIGH_TH_X__REG SMI130_GYRO_HIGH_TH_X_ADDR
+
+/**< 0th bit of HIGH_TH_X Registers */
+#define SMI130_GYRO_HIGH_EN_X__POS 0
+#define SMI130_GYRO_HIGH_EN_X__LEN 1
+#define SMI130_GYRO_HIGH_EN_X__MSK 0x01
+#define SMI130_GYRO_HIGH_EN_X__REG SMI130_GYRO_HIGH_TH_X_ADDR
+
+/**< Last 2 bits of HIGH_TH_Y Registers */
+#define SMI130_GYRO_HIGH_HY_Y__POS 6
+#define SMI130_GYRO_HIGH_HY_Y__LEN 2
+#define SMI130_GYRO_HIGH_HY_Y__MSK 0xC0
+#define SMI130_GYRO_HIGH_HY_Y__REG SMI130_GYRO_HIGH_TH_Y_ADDR
+
+/**< 5 bits of HIGH_TH_Y Registers */
+#define SMI130_GYRO_HIGH_TH_Y__POS 1
+#define SMI130_GYRO_HIGH_TH_Y__LEN 5
+#define SMI130_GYRO_HIGH_TH_Y__MSK 0x3E
+#define SMI130_GYRO_HIGH_TH_Y__REG SMI130_GYRO_HIGH_TH_Y_ADDR
+
+/**< 0th bit of HIGH_TH_Y Registers */
+#define SMI130_GYRO_HIGH_EN_Y__POS 0
+#define SMI130_GYRO_HIGH_EN_Y__LEN 1
+#define SMI130_GYRO_HIGH_EN_Y__MSK 0x01
+#define SMI130_GYRO_HIGH_EN_Y__REG SMI130_GYRO_HIGH_TH_Y_ADDR
+
+/**< Last 2 bits of HIGH_TH_Z Registers */
+#define SMI130_GYRO_HIGH_HY_Z__POS 6
+#define SMI130_GYRO_HIGH_HY_Z__LEN 2
+#define SMI130_GYRO_HIGH_HY_Z__MSK 0xC0
+#define SMI130_GYRO_HIGH_HY_Z__REG SMI130_GYRO_HIGH_TH_Z_ADDR
+
+/**< 5 bits of HIGH_TH_Z Registers */
+#define SMI130_GYRO_HIGH_TH_Z__POS 1
+#define SMI130_GYRO_HIGH_TH_Z__LEN 5
+#define SMI130_GYRO_HIGH_TH_Z__MSK 0x3E
+#define SMI130_GYRO_HIGH_TH_Z__REG SMI130_GYRO_HIGH_TH_Z_ADDR
+
+/**< 0th bit of HIGH_TH_Z Registers */
+#define SMI130_GYRO_HIGH_EN_Z__POS 0
+#define SMI130_GYRO_HIGH_EN_Z__LEN 1
+#define SMI130_GYRO_HIGH_EN_Z__MSK 0x01
+#define SMI130_GYRO_HIGH_EN_Z__REG SMI130_GYRO_HIGH_TH_Z_ADDR
+
+/**< Last 3 bits of INT OFF0 Registers */
+#define SMI130_GYRO_SLOW_OFFSET_TH__POS 6
+#define SMI130_GYRO_SLOW_OFFSET_TH__LEN 2
+#define SMI130_GYRO_SLOW_OFFSET_TH__MSK 0xC0
+#define SMI130_GYRO_SLOW_OFFSET_TH__REG SMI130_GYRO_SOC_ADDR
+
+/**< 2 bits of INT OFF0 Registers */
+#define SMI130_GYRO_SLOW_OFFSET_DUR__POS 3
+#define SMI130_GYRO_SLOW_OFFSET_DUR__LEN 3
+#define SMI130_GYRO_SLOW_OFFSET_DUR__MSK 0x38
+#define SMI130_GYRO_SLOW_OFFSET_DUR__REG SMI130_GYRO_SOC_ADDR
+
+/**< 2nd bit of INT OFF0 Registers */
+#define SMI130_GYRO_SLOW_OFFSET_EN_Z__POS 2
+#define SMI130_GYRO_SLOW_OFFSET_EN_Z__LEN 1
+#define SMI130_GYRO_SLOW_OFFSET_EN_Z__MSK 0x04
+#define SMI130_GYRO_SLOW_OFFSET_EN_Z__REG SMI130_GYRO_SOC_ADDR
+
+/**< 1st bit of INT OFF0 Registers */
+#define SMI130_GYRO_SLOW_OFFSET_EN_Y__POS 1
+#define SMI130_GYRO_SLOW_OFFSET_EN_Y__LEN 1
+#define SMI130_GYRO_SLOW_OFFSET_EN_Y__MSK 0x02
+#define SMI130_GYRO_SLOW_OFFSET_EN_Y__REG SMI130_GYRO_SOC_ADDR
+
+/**< 0th bit of INT OFF0 Registers */
+#define SMI130_GYRO_SLOW_OFFSET_EN_X__POS 0
+#define SMI130_GYRO_SLOW_OFFSET_EN_X__LEN 1
+#define SMI130_GYRO_SLOW_OFFSET_EN_X__MSK 0x01
+#define SMI130_GYRO_SLOW_OFFSET_EN_X__REG SMI130_GYRO_SOC_ADDR
+
+/**< Last 2 bits of INT OFF1 Registers */
+#define SMI130_GYRO_AUTO_OFFSET_WL__POS 6
+#define SMI130_GYRO_AUTO_OFFSET_WL__LEN 2
+#define SMI130_GYRO_AUTO_OFFSET_WL__MSK 0xC0
+#define SMI130_GYRO_AUTO_OFFSET_WL__REG SMI130_GYRO_A_FOC_ADDR
+
+/**< 2 bits of INT OFF1 Registers */
+#define SMI130_GYRO_FAST_OFFSET_WL__POS 4
+#define SMI130_GYRO_FAST_OFFSET_WL__LEN 2
+#define SMI130_GYRO_FAST_OFFSET_WL__MSK 0x30
+#define SMI130_GYRO_FAST_OFFSET_WL__REG SMI130_GYRO_A_FOC_ADDR
+
+/**< 3nd bit of INT OFF1 Registers */
+#define SMI130_GYRO_FAST_OFFSET_EN__POS 3
+#define SMI130_GYRO_FAST_OFFSET_EN__LEN 1
+#define SMI130_GYRO_FAST_OFFSET_EN__MSK 0x08
+#define SMI130_GYRO_FAST_OFFSET_EN__REG SMI130_GYRO_A_FOC_ADDR
+
+/**< 2nd bit of INT OFF1 Registers */
+#define SMI130_GYRO_FAST_OFFSET_EN_Z__POS 2
+#define SMI130_GYRO_FAST_OFFSET_EN_Z__LEN 1
+#define SMI130_GYRO_FAST_OFFSET_EN_Z__MSK 0x04
+#define SMI130_GYRO_FAST_OFFSET_EN_Z__REG SMI130_GYRO_A_FOC_ADDR
+
+/**< 1st bit of INT OFF1 Registers */
+#define SMI130_GYRO_FAST_OFFSET_EN_Y__POS 1
+#define SMI130_GYRO_FAST_OFFSET_EN_Y__LEN 1
+#define SMI130_GYRO_FAST_OFFSET_EN_Y__MSK 0x02
+#define SMI130_GYRO_FAST_OFFSET_EN_Y__REG SMI130_GYRO_A_FOC_ADDR
+
+/**< 0th bit of INT OFF1 Registers */
+#define SMI130_GYRO_FAST_OFFSET_EN_X__POS 0
+#define SMI130_GYRO_FAST_OFFSET_EN_X__LEN 1
+#define SMI130_GYRO_FAST_OFFSET_EN_X__MSK 0x01
+#define SMI130_GYRO_FAST_OFFSET_EN_X__REG SMI130_GYRO_A_FOC_ADDR
+
+/**< 0 to 2 bits of INT OFF1 Registers */
+#define SMI130_GYRO_FAST_OFFSET_EN_XYZ__POS 0
+#define SMI130_GYRO_FAST_OFFSET_EN_XYZ__LEN 3
+#define SMI130_GYRO_FAST_OFFSET_EN_XYZ__MSK 0x07
+#define SMI130_GYRO_FAST_OFFSET_EN_XYZ__REG SMI130_GYRO_A_FOC_ADDR
+
+/**< Last 4 bits of Trim NVM control Registers */
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_REMAIN__POS 4
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_REMAIN__LEN 4
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_REMAIN__MSK 0xF0
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_REMAIN__REG \
+SMI130_GYRO_TRIM_NVM_CTRL_ADDR
+
+/**< 3rd bit of Trim NVM control Registers */
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_LOAD__POS 3
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_LOAD__LEN 1
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_LOAD__MSK 0x08
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_LOAD__REG \
+SMI130_GYRO_TRIM_NVM_CTRL_ADDR
+
+/**< 2nd bit of Trim NVM control Registers */
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_RDY__POS 2
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_RDY__LEN 1
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_RDY__MSK 0x04
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_RDY__REG \
+SMI130_GYRO_TRIM_NVM_CTRL_ADDR
+
+ /**< 1st bit of Trim NVM control Registers */
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_TRIG__POS 1
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_TRIG__LEN 1
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_TRIG__MSK 0x02
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_TRIG__REG \
+SMI130_GYRO_TRIM_NVM_CTRL_ADDR
+
+/**< 0th bit of Trim NVM control Registers */
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_MODE__POS 0
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_MODE__LEN 1
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_MODE__MSK 0x01
+#define SMI130_GYRO_TRIM_NVM_CTRL_ADDR_NVM_PROG_MODE__REG \
+SMI130_GYRO_TRIM_NVM_CTRL_ADDR
+
+ /**< 2nd bit of SPI3 WDT Registers */
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_EN__POS 2
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_EN__LEN 1
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_EN__MSK 0x04
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_EN__REG \
+SMI130_GYRO_BGW_SPI3_WDT_ADDR
+
+ /**< 1st bit of SPI3 WDT Registers */
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_SEL__POS 1
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_SEL__LEN 1
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_SEL__MSK 0x02
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_I2C_WDT_SEL__REG \
+SMI130_GYRO_BGW_SPI3_WDT_ADDR
+
+/**< 0th bit of SPI3 WDT Registers */
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_SPI3__POS 0
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_SPI3__LEN 1
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_SPI3__MSK 0x01
+#define SMI130_GYRO_BGW_SPI3_WDT_ADDR_SPI3__REG \
+SMI130_GYRO_BGW_SPI3_WDT_ADDR
+
+/**< 4th bit of Self test Registers */
+#define SMI130_GYRO_SELF_TEST_ADDR_RATEOK__POS 4
+#define SMI130_GYRO_SELF_TEST_ADDR_RATEOK__LEN 1
+#define SMI130_GYRO_SELF_TEST_ADDR_RATEOK__MSK 0x10
+#define SMI130_GYRO_SELF_TEST_ADDR_RATEOK__REG \
+SMI130_GYRO_SELF_TEST_ADDR
+
+/**< 2nd bit of Self test Registers */
+#define SMI130_GYRO_SELF_TEST_ADDR_BISTFAIL__POS 2
+#define SMI130_GYRO_SELF_TEST_ADDR_BISTFAIL__LEN 1
+#define SMI130_GYRO_SELF_TEST_ADDR_BISTFAIL__MSK 0x04
+#define SMI130_GYRO_SELF_TEST_ADDR_BISTFAIL__REG \
+SMI130_GYRO_SELF_TEST_ADDR
+
+/**< 1st bit of Self test Registers */
+#define SMI130_GYRO_SELF_TEST_ADDR_BISTRDY__POS 1
+#define SMI130_GYRO_SELF_TEST_ADDR_BISTRDY__LEN 1
+#define SMI130_GYRO_SELF_TEST_ADDR_BISTRDY__MSK 0x02
+#define SMI130_GYRO_SELF_TEST_ADDR_BISTRDY__REG \
+SMI130_GYRO_SELF_TEST_ADDR
+
+/**< 0th bit of Self test Registers */
+#define SMI130_GYRO_SELF_TEST_ADDR_TRIGBIST__POS 0
+#define SMI130_GYRO_SELF_TEST_ADDR_TRIGBIST__LEN 1
+#define SMI130_GYRO_SELF_TEST_ADDR_TRIGBIST__MSK 0x01
+#define SMI130_GYRO_SELF_TEST_ADDR_TRIGBIST__REG \
+SMI130_GYRO_SELF_TEST_ADDR
+
+/**< 7th bit of FIFO CGF1 Registers */
+#define SMI130_GYRO_FIFO_CGF1_ADDR_TAG__POS 7
+#define SMI130_GYRO_FIFO_CGF1_ADDR_TAG__LEN 1
+#define SMI130_GYRO_FIFO_CGF1_ADDR_TAG__MSK 0x80
+#define SMI130_GYRO_FIFO_CGF1_ADDR_TAG__REG SMI130_GYRO_FIFO_CGF1_ADDR
+
+/**< First 7 bits of FIFO CGF1 Registers */
+#define SMI130_GYRO_FIFO_CGF1_ADDR_WML__POS 0
+#define SMI130_GYRO_FIFO_CGF1_ADDR_WML__LEN 7
+#define SMI130_GYRO_FIFO_CGF1_ADDR_WML__MSK 0x7F
+#define SMI130_GYRO_FIFO_CGF1_ADDR_WML__REG SMI130_GYRO_FIFO_CGF1_ADDR
+
+/**< Last 2 bits of FIFO CGF0 Addr Registers */
+#define SMI130_GYRO_FIFO_CGF0_ADDR_MODE__POS 6
+#define SMI130_GYRO_FIFO_CGF0_ADDR_MODE__LEN 2
+#define SMI130_GYRO_FIFO_CGF0_ADDR_MODE__MSK 0xC0
+#define SMI130_GYRO_FIFO_CGF0_ADDR_MODE__REG SMI130_GYRO_FIFO_CGF0_ADDR
+
+/**< First 2 bits of FIFO CGF0 Addr Registers */
+#define SMI130_GYRO_FIFO_CGF0_ADDR_DATA_SEL__POS 0
+#define SMI130_GYRO_FIFO_CGF0_ADDR_DATA_SEL__LEN 2
+#define SMI130_GYRO_FIFO_CGF0_ADDR_DATA_SEL__MSK 0x03
+#define SMI130_GYRO_FIFO_CGF0_ADDR_DATA_SEL__REG SMI130_GYRO_FIFO_CGF0_ADDR
+
+ /**< Last 2 bits of INL Offset MSB Registers */
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_X__POS 6
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_X__LEN 2
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_X__MSK 0xC0
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_X__REG SMI130_GYRO_OFC1_ADDR
+
+/**< 3 bits of INL Offset MSB Registers */
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_Y__POS 3
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_Y__LEN 3
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_Y__MSK 0x38
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_Y__REG SMI130_GYRO_OFC1_ADDR
+
+/**< First 3 bits of INL Offset MSB Registers */
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_Z__POS 0
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_Z__LEN 3
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_Z__MSK 0x07
+#define SMI130_GYRO_OFC1_ADDR_OFFSET_Z__REG SMI130_GYRO_OFC1_ADDR
+
+/**< 4 bits of Trim GP0 Registers */
+#define SMI130_GYRO_TRIM_GP0_ADDR_GP0__POS 4
+#define SMI130_GYRO_TRIM_GP0_ADDR_GP0__LEN 4
+#define SMI130_GYRO_TRIM_GP0_ADDR_GP0__MSK 0xF0
+#define SMI130_GYRO_TRIM_GP0_ADDR_GP0__REG SMI130_GYRO_TRIM_GP0_ADDR
+
+/**< 2 bits of Trim GP0 Registers */
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_X__POS 2
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_X__LEN 2
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_X__MSK 0x0C
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_X__REG SMI130_GYRO_TRIM_GP0_ADDR
+
+/**< 1st bit of Trim GP0 Registers */
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Y__POS 1
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Y__LEN 1
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Y__MSK 0x02
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Y__REG SMI130_GYRO_TRIM_GP0_ADDR
+
+/**< First bit of Trim GP0 Registers */
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Z__POS 0
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Z__LEN 1
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Z__MSK 0x01
+#define SMI130_GYRO_TRIM_GP0_ADDR_OFFSET_Z__REG SMI130_GYRO_TRIM_GP0_ADDR
+
+/* For Axis Selection */
+/**< It refers SMI130_GYRO X-axis */
+#define SMI130_GYRO_X_AXIS 0
+/**< It refers SMI130_GYRO Y-axis */
+#define SMI130_GYRO_Y_AXIS 1
+/**< It refers SMI130_GYRO Z-axis */
+#define SMI130_GYRO_Z_AXIS 2
+
+/* For Mode Settings */
+#define SMI130_GYRO_MODE_NORMAL 0
+#define SMI130_GYRO_MODE_DEEPSUSPEND 1
+#define SMI130_GYRO_MODE_SUSPEND 2
+#define SMI130_GYRO_MODE_FASTPOWERUP 3
+#define SMI130_GYRO_MODE_ADVANCEDPOWERSAVING 4
+
+/* get bit slice */
+#define SMI130_GYRO_GET_BITSLICE(regvar, bitname)\
+((regvar & bitname##__MSK) >> bitname##__POS)
+
+/* Set bit slice */
+#define SMI130_GYRO_SET_BITSLICE(regvar, bitname, val)\
+((regvar&~bitname##__MSK)|((val<<bitname##__POS)&bitname##__MSK))
+/* Constants */
+
+#define SMI130_GYRO_NULL 0
+/**< constant declaration of NULL */
+#define SMI130_GYRO_DISABLE 0
+/**< It refers SMI130_GYRO disable */
+#define SMI130_GYRO_ENABLE 1
+/**< It refers SMI130_GYRO enable */
+#define SMI130_GYRO_OFF 0
+/**< It refers SMI130_GYRO OFF state */
+#define SMI130_GYRO_ON 1
+/**< It refers SMI130_GYRO ON state */
+
+
+#define SMI130_GYRO_TURN1 0
+/**< It refers SMI130_GYRO TURN1 */
+#define SMI130_GYRO_TURN2 1
+/**< It refers SMI130_GYRO TURN2 */
+
+#define SMI130_GYRO_INT1 0
+/**< It refers SMI130_GYRO INT1 */
+#define SMI130_GYRO_INT2 1
+/**< It refers SMI130_GYRO INT2 */
+
+#define SMI130_GYRO_SLOW_OFFSET 0
+/**< It refers SMI130_GYRO Slow Offset */
+#define SMI130_GYRO_AUTO_OFFSET 1
+/**< It refers SMI130_GYRO Auto Offset */
+#define SMI130_GYRO_FAST_OFFSET 2
+/**< It refers SMI130_GYRO Fast Offset */
+#define SMI130_GYRO_S_TAP 0
+/**< It refers SMI130_GYRO Single Tap */
+#define SMI130_GYRO_D_TAP 1
+/**< It refers SMI130_GYRO Double Tap */
+#define SMI130_GYRO_INT1_DATA 0
+/**< It refers SMI130_GYRO Int1 Data */
+#define SMI130_GYRO_INT2_DATA 1
+/**< It refers SMI130_GYRO Int2 Data */
+#define SMI130_GYRO_TAP_UNFILT_DATA 0
+/**< It refers SMI130_GYRO Tap unfilt data */
+#define SMI130_GYRO_HIGH_UNFILT_DATA 1
+/**< It refers SMI130_GYRO High unfilt data */
+#define SMI130_GYRO_CONST_UNFILT_DATA 2
+/**< It refers SMI130_GYRO Const unfilt data */
+#define SMI130_GYRO_ANY_UNFILT_DATA 3
+/**< It refers SMI130_GYRO Any unfilt data */
+#define SMI130_GYRO_SHAKE_UNFILT_DATA 4
+/**< It refers SMI130_GYRO Shake unfilt data */
+#define SMI130_GYRO_SHAKE_TH 0
+/**< It refers SMI130_GYRO Shake Threshold */
+#define SMI130_GYRO_SHAKE_TH2 1
+/**< It refers SMI130_GYRO Shake Threshold2 */
+#define SMI130_GYRO_AUTO_OFFSET_WL 0
+/**< It refers SMI130_GYRO Auto Offset word length */
+#define SMI130_GYRO_FAST_OFFSET_WL 1
+/**< It refers SMI130_GYRO Fast Offset word length */
+#define SMI130_GYRO_I2C_WDT_EN 0
+/**< It refers SMI130_GYRO I2C WDT En */
+#define SMI130_GYRO_I2C_WDT_SEL 1
+/**< It refers SMI130_GYRO I2C WDT Sel */
+#define SMI130_GYRO_EXT_MODE 0
+/**< It refers SMI130_GYRO Ext Mode */
+#define SMI130_GYRO_EXT_PAGE 1
+/**< It refers SMI130_GYRO Ext page */
+#define SMI130_GYRO_START_ADDR 0
+/**< It refers SMI130_GYRO Start Address */
+#define SMI130_GYRO_STOP_ADDR 1
+/**< It refers SMI130_GYRO Stop Address */
+#define SMI130_GYRO_SLOW_CMD 0
+/**< It refers SMI130_GYRO Slow Command */
+#define SMI130_GYRO_FAST_CMD 1
+/**< It refers SMI130_GYRO Fast Command */
+#define SMI130_GYRO_TRIM_VRA 0
+/**< It refers SMI130_GYRO Trim VRA */
+#define SMI130_GYRO_TRIM_VRD 1
+/**< It refers SMI130_GYRO Trim VRD */
+#define SMI130_GYRO_LOGBIT_EM 0
+/**< It refers SMI130_GYRO LogBit Em */
+#define SMI130_GYRO_LOGBIT_VM 1
+/**< It refers SMI130_GYRO LogBit VM */
+#define SMI130_GYRO_GP0 0
+/**< It refers SMI130_GYRO GP0 */
+#define SMI130_GYRO_GP1 1
+/**< It refers SMI130_GYRO GP1*/
+#define SMI130_GYRO_LOW_SPEED 0
+/**< It refers SMI130_GYRO Low Speed Oscillator */
+#define SMI130_GYRO_HIGH_SPEED 1
+/**< It refers SMI130_GYRO High Speed Oscillator */
+#define SMI130_GYRO_DRIVE_OFFSET_P 0
+/**< It refers SMI130_GYRO Drive Offset P */
+#define SMI130_GYRO_DRIVE_OFFSET_N 1
+/**< It refers SMI130_GYRO Drive Offset N */
+#define SMI130_GYRO_TEST_MODE_EN 0
+/**< It refers SMI130_GYRO Test Mode Enable */
+#define SMI130_GYRO_TEST_MODE_REG 1
+/**< It refers SMI130_GYRO Test Mode reg */
+#define SMI130_GYRO_IBIAS_DRIVE_TRIM 0
+/**< It refers SMI130_GYRO IBIAS Drive Trim */
+#define SMI130_GYRO_IBIAS_RATE_TRIM 1
+/**< It refers SMI130_GYRO IBIAS Rate Trim */
+#define SMI130_GYRO_BAA_MODE 0
+/**< It refers SMI130_GYRO BAA Mode Trim */
+#define SMI130_GYRO_SMI_ACC_MODE 1
+/**< It refers SMI130_GYRO SMI_ACC Mode Trim */
+#define SMI130_GYRO_PI_KP 0
+/**< It refers SMI130_GYRO PI KP */
+#define SMI130_GYRO_PI_KI 1
+/**< It refers SMI130_GYRO PI KI */
+
+
+#define C_SMI130_GYRO_SUCCESS 0
+/**< It refers SMI130_GYRO operation is success */
+#define C_SMI130_GYRO_FAILURE 1
+/**< It refers SMI130_GYRO operation is Failure */
+
+#define SMI130_GYRO_SPI_RD_MASK 0x80
+/**< Read mask **/
+#define SMI130_GYRO_READ_SET 0x01
+/**< Setting for rading data **/
+
+#define SMI130_GYRO_SHIFT_1_POSITION 1
+/**< Shift bit by 1 Position **/
+#define SMI130_GYRO_SHIFT_2_POSITION 2
+/**< Shift bit by 2 Position **/
+#define SMI130_GYRO_SHIFT_3_POSITION 3
+/**< Shift bit by 3 Position **/
+#define SMI130_GYRO_SHIFT_4_POSITION 4
+/**< Shift bit by 4 Position **/
+#define SMI130_GYRO_SHIFT_5_POSITION 5
+/**< Shift bit by 5 Position **/
+#define SMI130_GYRO_SHIFT_6_POSITION 6
+/**< Shift bit by 6 Position **/
+#define SMI130_GYRO_SHIFT_7_POSITION 7
+/**< Shift bit by 7 Position **/
+#define SMI130_GYRO_SHIFT_8_POSITION 8
+/**< Shift bit by 8 Position **/
+#define SMI130_GYRO_SHIFT_12_POSITION 12
+/**< Shift bit by 12 Position **/
+
+#define C_SMI130_GYRO_Null_U8X 0
+#define C_SMI130_GYRO_Zero_U8X 0
+#define C_SMI130_GYRO_One_U8X 1
+#define C_SMI130_GYRO_Two_U8X 2
+#define C_SMI130_GYRO_Three_U8X 3
+#define C_SMI130_GYRO_Four_U8X 4
+#define C_SMI130_GYRO_Five_U8X 5
+#define C_SMI130_GYRO_Six_U8X 6
+#define C_SMI130_GYRO_Seven_U8X 7
+#define C_SMI130_GYRO_Eight_U8X 8
+#define C_SMI130_GYRO_Nine_U8X 9
+#define C_SMI130_GYRO_Ten_U8X 10
+#define C_SMI130_GYRO_Eleven_U8X 11
+#define C_SMI130_GYRO_Twelve_U8X 12
+#define C_SMI130_GYRO_Thirteen_U8X 13
+#define C_SMI130_GYRO_Fifteen_U8X 15
+#define C_SMI130_GYRO_Sixteen_U8X 16
+#define C_SMI130_GYRO_TwentyTwo_U8X 22
+#define C_SMI130_GYRO_TwentyThree_U8X 23
+#define C_SMI130_GYRO_TwentyFour_U8X 24
+#define C_SMI130_GYRO_TwentyFive_U8X 25
+#define C_SMI130_GYRO_ThirtyTwo_U8X 32
+#define C_SMI130_GYRO_Hundred_U8X 100
+#define C_SMI130_GYRO_OneTwentySeven_U8X 127
+#define C_SMI130_GYRO_OneTwentyEight_U8X 128
+#define C_SMI130_GYRO_TwoFiftyFive_U8X 255
+#define C_SMI130_GYRO_TwoFiftySix_U16X 256
+
+#define E_SMI130_GYRO_NULL_PTR (signed char)(-127)
+#define E_SMI130_GYRO_COMM_RES (signed char)(-1)
+#define E_SMI130_GYRO_OUT_OF_RANGE (signed char)(-2)
+
+#define C_SMI130_GYRO_No_Filter_U8X 0
+#define C_SMI130_GYRO_BW_230Hz_U8X 1
+#define C_SMI130_GYRO_BW_116Hz_U8X 2
+#define C_SMI130_GYRO_BW_47Hz_U8X 3
+#define C_SMI130_GYRO_BW_23Hz_U8X 4
+#define C_SMI130_GYRO_BW_12Hz_U8X 5
+#define C_SMI130_GYRO_BW_64Hz_U8X 6
+#define C_SMI130_GYRO_BW_32Hz_U8X 7
+
+#define C_SMI130_GYRO_No_AutoSleepDur_U8X 0
+#define C_SMI130_GYRO_4ms_AutoSleepDur_U8X 1
+#define C_SMI130_GYRO_5ms_AutoSleepDur_U8X 2
+#define C_SMI130_GYRO_8ms_AutoSleepDur_U8X 3
+#define C_SMI130_GYRO_10ms_AutoSleepDur_U8X 4
+#define C_SMI130_GYRO_15ms_AutoSleepDur_U8X 5
+#define C_SMI130_GYRO_20ms_AutoSleepDur_U8X 6
+#define C_SMI130_GYRO_40ms_AutoSleepDur_U8X 7
+
+
+
+
+#define SMI130_GYRO_WR_FUNC_PTR int (*bus_write)\
+(unsigned char, unsigned char, unsigned char *, unsigned char)
+#define SMI130_GYRO_RD_FUNC_PTR int (*bus_read)\
+(unsigned char, unsigned char, unsigned char *, unsigned char)
+#define SMI130_GYRO_BRD_FUNC_PTR int (*burst_read)\
+(unsigned char, unsigned char, unsigned char *, SMI130_GYRO_S32)
+#define SMI130_GYRO_MDELAY_DATA_TYPE SMI130_GYRO_U16
+
+
+
+
+/*user defined Structures*/
+struct smi130_gyro_data_t {
+ SMI130_GYRO_S16 datax;
+ SMI130_GYRO_S16 datay;
+ SMI130_GYRO_S16 dataz;
+ char intstatus[5];
+};
+
+
+struct smi130_gyro_offset_t {
+ SMI130_GYRO_U16 datax;
+ SMI130_GYRO_U16 datay;
+ SMI130_GYRO_U16 dataz;
+};
+
+
+struct smi130_gyro_t {
+ unsigned char chip_id;
+ unsigned char dev_addr;
+ SMI130_GYRO_BRD_FUNC_PTR;
+ SMI130_GYRO_WR_FUNC_PTR;
+ SMI130_GYRO_RD_FUNC_PTR;
+ void(*delay_msec)(SMI130_GYRO_MDELAY_DATA_TYPE);
+};
+
+/***************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ***************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ***************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_init(struct smi130_gyro_t *p_smi130_gyro);
+/***************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ***************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataX(SMI130_GYRO_S16 *data_x);
+/****************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ***************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataY(SMI130_GYRO_S16 *data_y);
+/***************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ***************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataZ(SMI130_GYRO_S16 *data_z);
+/************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ***************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataXYZ(struct smi130_gyro_data_t *data);
+/***************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ********************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_dataXYZI(struct smi130_gyro_data_t *data);
+/********************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ********************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_Temperature(unsigned char *temperature);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_FIFO_data_reg
+(unsigned char *fifo_data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_read_register(unsigned char addr,
+unsigned char *data, unsigned char len);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_burst_read(unsigned char addr,
+unsigned char *data, SMI130_GYRO_S32 len);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_write_register(unsigned char addr,
+unsigned char *data, unsigned char len);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_interrupt_status_reg_0
+(unsigned char *status0_data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_interrupt_status_reg_1
+(unsigned char *status1_data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_interrupt_status_reg_2
+(unsigned char *status2_data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_interrupt_status_reg_3
+(unsigned char *status3_data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifostatus_reg
+(unsigned char *fifo_status);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_range_reg
+(unsigned char *range);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_range_reg
+(unsigned char range);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_res
+(unsigned char *high_res);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_res
+(unsigned char high_res);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_bw(unsigned char *bandwidth);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_bw(unsigned char bandwidth);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_pmu_ext_tri_sel
+(unsigned char *pwu_ext_tri_sel);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_pmu_ext_tri_sel
+(unsigned char pwu_ext_tri_sel);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_bw
+(unsigned char *high_bw);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_bw
+(unsigned char high_bw);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_shadow_dis
+(unsigned char *shadow_dis);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_shadow_dis
+(unsigned char shadow_dis);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_soft_reset(void);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_data_enable(unsigned char *data_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_data_en(unsigned char data_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_enable(unsigned char *fifo_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_enable(unsigned char fifo_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_offset_enable
+(unsigned char mode, unsigned char *offset_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_offset_enable
+(unsigned char mode, unsigned char offset_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int_od
+(unsigned char param, unsigned char *int_od);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int_od
+(unsigned char param, unsigned char int_od);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int_lvl
+(unsigned char param, unsigned char *int_lvl);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int_lvl
+(unsigned char param, unsigned char int_lvl);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int1_high
+(unsigned char *int1_high);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int1_high
+(unsigned char int1_high);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int1_any
+(unsigned char *int1_any);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int1_any
+(unsigned char int1_any);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int_data
+(unsigned char axis, unsigned char *int_data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int_data
+(unsigned char axis, unsigned char int_data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int2_offset
+(unsigned char axis, unsigned char *int2_offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int2_offset
+(unsigned char axis, unsigned char int2_offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int1_offset
+(unsigned char axis, unsigned char *int1_offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int1_offset
+(unsigned char axis, unsigned char int1_offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int_fifo(unsigned char *int_fifo);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int_fifo
+(unsigned char axis, unsigned char int_fifo);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int2_high
+(unsigned char *int2_high);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int2_high
+(unsigned char int2_high);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int2_any
+(unsigned char *int2_any);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int2_any
+(unsigned char int2_any);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_offset_unfilt
+(unsigned char param, unsigned char *offset_unfilt);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_offset_unfilt
+(unsigned char param, unsigned char offset_unfilt);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_unfilt_data
+(unsigned char param, unsigned char *unfilt_data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_unfilt_data
+(unsigned char param, unsigned char unfilt_data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_any_th
+(unsigned char *any_th);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_any_th
+(unsigned char any_th);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_awake_dur
+(unsigned char *awake_dur);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_awake_dur
+(unsigned char awake_dur);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_any_dursample
+(unsigned char *dursample);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_any_dursample
+(unsigned char dursample);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_any_en_ch
+(unsigned char channel, unsigned char *data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_any_en_ch
+(unsigned char channel, unsigned char data);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_watermark_enable
+(unsigned char *fifo_wn_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_watermark_enable
+(unsigned char fifo_wn_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_reset_int
+(unsigned char reset_int);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_offset_reset
+(unsigned char offset_reset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_latch_status
+(unsigned char *latch_status);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_latch_status
+(unsigned char latch_status);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_latch_int
+(unsigned char *latch_int);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_latch_int
+(unsigned char latch_int);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_hy
+(unsigned char channel, unsigned char *high_hy);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_hy
+(unsigned char channel, unsigned char high_hy);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_th
+(unsigned char channel, unsigned char *high_th);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_th
+(unsigned char channel, unsigned char high_th);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_en_ch
+(unsigned char channel, unsigned char *high_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_en_ch
+(unsigned char channel, unsigned char high_en);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_high_dur_ch
+(unsigned char channel, unsigned char *high_dur);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_high_dur_ch
+(unsigned char channel, unsigned char high_dur);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_slow_offset_th
+(unsigned char *offset_th);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_slow_offset_th
+(unsigned char offset_th);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_slow_offset_dur
+(unsigned char *offset_dur);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_slow_offset_dur
+(unsigned char offset_dur);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_slow_offset_en_ch
+(unsigned char channel, unsigned char *slow_offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_slow_offset_en_ch
+(unsigned char channel, unsigned char slow_offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_offset_wl
+(unsigned char channel, unsigned char *offset_wl);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_offset_wl
+(unsigned char channel, unsigned char offset_wl);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fast_offset_en
+(unsigned char fast_offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fast_offset_en_ch
+(unsigned char *fast_offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fast_offset_en_ch
+(unsigned char channel, unsigned char fast_offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_enable_fast_offset(void);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_nvm_remain
+(unsigned char *nvm_remain);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_nvm_load
+(unsigned char nvm_load);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_nvm_rdy
+(unsigned char *nvm_rdy);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_nvm_prog_trig
+(unsigned char prog_trig);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_nvm_prog_mode
+(unsigned char *prog_mode);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_nvm_prog_mode
+(unsigned char prog_mode);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_i2c_wdt
+(unsigned char i2c_wdt, unsigned char *prog_mode);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_i2c_wdt
+(unsigned char i2c_wdt, unsigned char prog_mode);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_spi3(unsigned char *spi3);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_spi3(unsigned char spi3);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_tag(unsigned char *tag);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_tag(unsigned char tag);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_watermarklevel
+(unsigned char *water_mark_level);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_watermarklevel
+(unsigned char water_mark_level);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_mode
+(unsigned char *mode);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_mode(unsigned char mode);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_data_sel
+(unsigned char *data_sel);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_fifo_data_sel
+(unsigned char data_sel);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_offset
+(unsigned char axis, SMI130_GYRO_S16 *offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_offset
+(unsigned char axis, SMI130_GYRO_S16 offset);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_gp
+(unsigned char param, unsigned char *value);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_gp
+(unsigned char param, unsigned char value);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_framecount
+(unsigned char *fifo_framecount);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_fifo_overrun
+(unsigned char *fifo_overrun);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int2_fifo
+(unsigned char *int_fifo);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_int1_fifo
+(unsigned char *int_fifo);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int2_fifo
+(unsigned char fifo_int2);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_int1_fifo
+(unsigned char fifo_int1);
+/****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_mode(unsigned char *mode);
+/*****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_mode(unsigned char mode);
+/*****************************************************************************
+ * Description: *//**\brief
+ *
+ *
+ *
+ *
+ * \param
+ *
+ *
+ * \return
+ *
+ *
+ ****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ ****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_selftest(unsigned char *result);
+/*****************************************************************************
+ * Description: *//**\brief This API is used to get data auto sleep duration
+ *
+ *
+ *
+ *
+ * \param unsigned char *duration : Address of auto sleep duration
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_autosleepdur(unsigned char *duration);
+/*****************************************************************************
+ * Description: *//**\brief This API is used to set duration
+ *
+ *
+ *
+ *
+ * \param unsigned char duration:
+ * Value to be written passed as a parameter
+ * unsigned char bandwidth:
+ * Value to be written passed as a parameter
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_autosleepdur(unsigned char duration,
+unsigned char bandwith);
+/*****************************************************************************
+ * Description: *//**\brief This API is used to get data sleep duration
+ *
+ *
+ *
+ *
+ * \param unsigned char *duration : Address of sleep duration
+ * Pointer to a variable passed as a parameter
+ *
+ *
+ *
+ * \return
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_sleepdur(unsigned char *duration);
+/*****************************************************************************
+ * Description: *//**\brief This API is used to set duration
+ *
+ *
+ *
+ *
+ * \param unsigned char duration:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_sleepdur(unsigned char duration);
+/*****************************************************************************
+ * Description: *//**\brief This API is used to set auto offset
+ *
+ *
+ *
+ *
+ * \param unsigned char duration:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_set_auto_offset_en(unsigned char offset_en);
+/*****************************************************************************
+ * Description: *//**\brief This API is used to get auto offset
+ *
+ *
+ *
+ *
+ * \param unsigned char duration:
+ * Value to be written passed as a parameter
+ *
+ *
+ *
+ * \return communication results
+ *
+ *
+ *****************************************************************************/
+/* Scheduling:
+ *
+ *
+ *
+ * Usage guide:
+ *
+ *
+ * Remarks:
+ *
+ *****************************************************************************/
+SMI130_GYRO_RETURN_FUNCTION_TYPE smi130_gyro_get_auto_offset_en(
+unsigned char *offset_en);
+#endif
diff --git a/drivers/input/sensors/smi130/smi130_gyro_driver.c b/drivers/input/sensors/smi130/smi130_gyro_driver.c
new file mode 100644
index 000000000000..65e303c6d8e6
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130_gyro_driver.c
@@ -0,0 +1,2036 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ * @filename smi130_gyro_driver.c
+ * @date 2015/11/17 13:44
+ * @Modification Date 2018/08/28 18:20
+ * @id "836294d"
+ * @version 1.5.9
+ *
+ * @brief SMI130_GYRO Linux Driver
+ */
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/unistd.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <string.h>
+#endif
+#include <linux/math64.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include "smi130_gyro.h"
+#include "bs_log.h"
+
+/* sensor specific */
+#define SENSOR_NAME "smi130_gyro"
+#define SMI130_GYRO_ENABLE_INT1 1
+#define SENSOR_CHIP_ID_SMI_GYRO (0x0f)
+#define CHECK_CHIP_ID_TIME_MAX 5
+#define DRIVER_VERSION "0.0.53.0"
+#define SMI_GYRO_USE_FIFO 1
+#define SMI_GYRO_USE_BASIC_I2C_FUNC 1
+#define SMI_GYRO_REG_NAME(name) SMI130_GYRO_##name
+#define SMI_GYRO_VAL_NAME(name) SMI130_GYRO_##name
+#define SMI_GYRO_CALL_API(name) smi130_gyro_##name
+#define MSC_TIME 6
+
+#define SMI_GYRO_I2C_WRITE_DELAY_TIME 1
+
+/* generic */
+#define SMI_GYRO_MAX_RETRY_I2C_XFER (100)
+#define SMI_GYRO_MAX_RETRY_WAKEUP (5)
+#define SMI_GYRO_MAX_RETRY_WAIT_DRDY (100)
+
+#define SMI_GYRO_DELAY_MIN (1)
+#define SMI_GYRO_DELAY_DEFAULT (200)
+
+#define SMI_GYRO_VALUE_MAX (32767)
+#define SMI_GYRO_VALUE_MIN (-32768)
+
+#define BYTES_PER_LINE (16)
+
+#define SMI_GYRO_SELF_TEST 0
+
+#define SMI_GYRO_SOFT_RESET_VALUE 0xB6
+
+#ifdef SMI_GYRO_USE_FIFO
+#define MAX_FIFO_F_LEVEL 100
+#define MAX_FIFO_F_BYTES 8
+#define SMI130_GYRO_FIFO_DAT_SEL_X 1
+#define SMI130_GYRO_FIFO_DAT_SEL_Y 2
+#define SMI130_GYRO_FIFO_DAT_SEL_Z 3
+#endif
+
+/*!
+ * @brief:BMI058 feature
+ * macro definition
+*/
+#ifdef CONFIG_SENSORS_BMI058
+/*! BMI058 X AXIS definition*/
+#define BMI058_X_AXIS SMI130_GYRO_Y_AXIS
+/*! BMI058 Y AXIS definition*/
+#define BMI058_Y_AXIS SMI130_GYRO_X_AXIS
+
+#define C_BMI058_One_U8X 1
+#define C_BMI058_Two_U8X 2
+#endif
+
+/*! Bosch sensor unknown place*/
+#define BOSCH_SENSOR_PLACE_UNKNOWN (-1)
+/*! Bosch sensor remapping table size P0~P7*/
+#define MAX_AXIS_REMAP_TAB_SZ 8
+
+
+struct bosch_sensor_specific {
+ char *name;
+ /* 0 to 7 */
+ int place;
+ int irq;
+ int (*irq_gpio_cfg)(void);
+};
+
+
+/*!
+ * we use a typedef to hide the detail,
+ * because this type might be changed
+ */
+struct bosch_sensor_axis_remap {
+ /* src means which source will be mapped to target x, y, z axis */
+ /* if an target OS axis is remapped from (-)x,
+ * src is 0, sign_* is (-)1 */
+ /* if an target OS axis is remapped from (-)y,
+ * src is 1, sign_* is (-)1 */
+ /* if an target OS axis is remapped from (-)z,
+ * src is 2, sign_* is (-)1 */
+ int src_x:3;
+ int src_y:3;
+ int src_z:3;
+
+ int sign_x:2;
+ int sign_y:2;
+ int sign_z:2;
+};
+
+
+struct bosch_sensor_data {
+ union {
+ int16_t v[3];
+ struct {
+ int16_t x;
+ int16_t y;
+ int16_t z;
+ };
+ };
+};
+
+struct smi_gyro_client_data {
+ struct smi130_gyro_t device;
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct delayed_work work;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend_handler;
+#endif
+
+ atomic_t delay;
+ uint8_t debug_level;
+ struct smi130_gyro_data_t value;
+ u8 enable:1;
+ unsigned int fifo_count;
+ unsigned char fifo_datasel;
+ uint64_t timestamp;
+ uint64_t base_time;
+ uint64_t fifo_time;
+ uint64_t gyro_count;
+ uint64_t time_odr;
+ /* controls not only reg, but also workqueue */
+ struct mutex mutex_op_mode;
+ struct mutex mutex_enable;
+ struct bosch_sensor_specific *bosch_pd;
+ struct work_struct report_data_work;
+ int is_timer_running;
+ struct hrtimer timer;
+ ktime_t work_delay_kt;
+ uint8_t gpio_pin;
+ int16_t IRQ;
+ struct work_struct irq_work;
+};
+
+static struct i2c_client *smi_gyro_client;
+/* i2c operation for API */
+static int smi_gyro_i2c_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len);
+static int smi_gyro_i2c_write(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len);
+
+static void smi_gyro_dump_reg(struct i2c_client *client);
+static int smi_gyro_check_chip_id(struct i2c_client *client);
+
+static int smi_gyro_pre_suspend(struct i2c_client *client);
+static int smi_gyro_post_resume(struct i2c_client *client);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void smi_gyro_early_suspend(struct early_suspend *handler);
+static void smi_gyro_late_resume(struct early_suspend *handler);
+#endif
+
+static void smi130_gyro_delay(SMI130_GYRO_U16 msec)
+{
+ if (msec <= 20)
+ usleep_range(msec * 1000, msec * 1000);
+ else
+ msleep(msec);
+}
+
+/*!
+* SMI130_GYRO sensor remapping function
+* need to give some parameter in BSP files first.
+*/
+static const struct bosch_sensor_axis_remap
+ bosch_axis_remap_tab_dft[MAX_AXIS_REMAP_TAB_SZ] = {
+ /* src_x src_y src_z sign_x sign_y sign_z */
+ { 0, 1, 2, 1, 1, 1 }, /* P0 */
+ { 1, 0, 2, 1, -1, 1 }, /* P1 */
+ { 0, 1, 2, -1, -1, 1 }, /* P2 */
+ { 1, 0, 2, -1, 1, 1 }, /* P3 */
+
+ { 0, 1, 2, -1, 1, -1 }, /* P4 */
+ { 1, 0, 2, -1, -1, -1 }, /* P5 */
+ { 0, 1, 2, 1, -1, -1 }, /* P6 */
+ { 1, 0, 2, 1, 1, -1 }, /* P7 */
+};
+
+static void bosch_remap_sensor_data(struct bosch_sensor_data *data,
+ const struct bosch_sensor_axis_remap *remap)
+{
+ struct bosch_sensor_data tmp;
+
+ tmp.x = data->v[remap->src_x] * remap->sign_x;
+ tmp.y = data->v[remap->src_y] * remap->sign_y;
+ tmp.z = data->v[remap->src_z] * remap->sign_z;
+
+ memcpy(data, &tmp, sizeof(*data));
+}
+
+static void bosch_remap_sensor_data_dft_tab(struct bosch_sensor_data *data,
+ int place)
+{
+/* sensor with place 0 needs not to be remapped */
+ if ((place <= 0) || (place >= MAX_AXIS_REMAP_TAB_SZ))
+ return;
+ bosch_remap_sensor_data(data, &bosch_axis_remap_tab_dft[place]);
+}
+
+static void smi130_gyro_remap_sensor_data(struct smi130_gyro_data_t *val,
+ struct smi_gyro_client_data *client_data)
+{
+ struct bosch_sensor_data bsd;
+ int place;
+
+ if ((NULL == client_data->bosch_pd) || (BOSCH_SENSOR_PLACE_UNKNOWN
+ == client_data->bosch_pd->place))
+ place = BOSCH_SENSOR_PLACE_UNKNOWN;
+ else
+ place = client_data->bosch_pd->place;
+
+#ifdef CONFIG_SENSORS_BMI058
+/*x,y need to be invesed becase of HW Register for BMI058*/
+ bsd.y = val->datax;
+ bsd.x = val->datay;
+ bsd.z = val->dataz;
+#else
+ bsd.x = val->datax;
+ bsd.y = val->datay;
+ bsd.z = val->dataz;
+#endif
+
+ bosch_remap_sensor_data_dft_tab(&bsd, place);
+
+ val->datax = bsd.x;
+ val->datay = bsd.y;
+ val->dataz = bsd.z;
+
+}
+
+static int smi_gyro_check_chip_id(struct i2c_client *client)
+{
+ int err = -1;
+ u8 chip_id = 0;
+ u8 read_count = 0;
+
+ while (read_count++ < CHECK_CHIP_ID_TIME_MAX) {
+ smi_gyro_i2c_read(client, SMI_GYRO_REG_NAME(CHIP_ID_ADDR), &chip_id, 1);
+ PINFO("read chip id result: %#x", chip_id);
+
+ if ((chip_id & 0xff) != SENSOR_CHIP_ID_SMI_GYRO) {
+ smi130_gyro_delay(1);
+ } else {
+ err = 0;
+ break;
+ }
+ }
+ return err;
+}
+
+static void smi_gyro_dump_reg(struct i2c_client *client)
+{
+ int i;
+ u8 dbg_buf[64];
+ u8 dbg_buf_str[64 * 3 + 1] = "";
+
+ for (i = 0; i < BYTES_PER_LINE; i++) {
+ dbg_buf[i] = i;
+ snprintf(dbg_buf_str + i * 3, 16, "%02x%c",
+ dbg_buf[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ dev_dbg(&client->dev, "%s\n", dbg_buf_str);
+
+ smi_gyro_i2c_read(client, SMI_GYRO_REG_NAME(CHIP_ID_ADDR), dbg_buf, 64);
+ for (i = 0; i < 64; i++) {
+ snprintf(dbg_buf_str + i * 3, 16, "%02x%c",
+ dbg_buf[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ dev_dbg(&client->dev, "%s\n", dbg_buf_str);
+}
+
+/*i2c read routine for API*/
+static int smi_gyro_i2c_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len)
+{
+#if !defined SMI_GYRO_USE_BASIC_I2C_FUNC
+ s32 dummy;
+ if (NULL == client)
+ return -ENODEV;
+
+ while (0 != len--) {
+#ifdef SMI_GYRO_SMBUS
+ dummy = i2c_smbus_read_byte_data(client, reg_addr);
+ if (dummy < 0) {
+ dev_err(&client->dev, "i2c bus read error");
+ return -EIO;
+ }
+ *data = (u8)(dummy & 0xff);
+#else
+ dummy = i2c_master_send(client, (char *)&reg_addr, 1);
+ if (dummy < 0)
+ return -EIO;
+
+ dummy = i2c_master_recv(client, (char *)data, 1);
+ if (dummy < 0)
+ return -EIO;
+#endif
+ reg_addr++;
+ data++;
+ }
+ return 0;
+#else
+ int retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ for (retry = 0; retry < SMI_GYRO_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ smi130_gyro_delay(SMI_GYRO_I2C_WRITE_DELAY_TIME);
+ }
+
+ if (SMI_GYRO_MAX_RETRY_I2C_XFER <= retry) {
+ dev_err(&client->dev, "I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+#endif
+}
+
+#ifdef SMI_GYRO_USE_FIFO
+static int smi_gyro_i2c_burst_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u16 len)
+{
+ int retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ for (retry = 0; retry < SMI_GYRO_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ smi130_gyro_delay(SMI_GYRO_I2C_WRITE_DELAY_TIME);
+ }
+
+ if (SMI_GYRO_MAX_RETRY_I2C_XFER <= retry) {
+ dev_err(&client->dev, "I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+}
+#endif
+
+/*i2c write routine for */
+static int smi_gyro_i2c_write(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len)
+{
+#if !defined SMI_GYRO_USE_BASIC_I2C_FUNC
+ s32 dummy;
+
+#ifndef SMI_GYRO_SMBUS
+ u8 buffer[2];
+#endif
+
+ if (NULL == client)
+ return -ENODEV;
+
+ while (0 != len--) {
+#ifdef SMI_GYRO_SMBUS
+ dummy = i2c_smbus_write_byte_data(client, reg_addr, *data);
+#else
+ buffer[0] = reg_addr;
+ buffer[1] = *data;
+ dummy = i2c_master_send(client, (char *)buffer, 2);
+#endif
+ reg_addr++;
+ data++;
+ if (dummy < 0) {
+ dev_err(&client->dev, "error writing i2c bus");
+ return -EIO;
+ }
+
+ }
+ return 0;
+#else
+ u8 buffer[2];
+ int retry;
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = buffer,
+ },
+ };
+
+ while (0 != len--) {
+ buffer[0] = reg_addr;
+ buffer[1] = *data;
+ for (retry = 0; retry < SMI_GYRO_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg,
+ ARRAY_SIZE(msg)) > 0) {
+ break;
+ } else {
+ smi130_gyro_delay(SMI_GYRO_I2C_WRITE_DELAY_TIME);
+ }
+ }
+ if (SMI_GYRO_MAX_RETRY_I2C_XFER <= retry) {
+ dev_err(&client->dev, "I2C xfer error");
+ return -EIO;
+ }
+ reg_addr++;
+ data++;
+ }
+
+ return 0;
+#endif
+}
+
+static int smi_gyro_i2c_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ int err;
+ err = smi_gyro_i2c_read(smi_gyro_client, reg_addr, data, len);
+ return err;
+}
+
+static int smi_gyro_i2c_write_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ int err;
+ err = smi_gyro_i2c_write(smi_gyro_client, reg_addr, data, len);
+ return err;
+}
+
+
+static void smi_gyro_work_func(struct work_struct *work)
+{
+ struct smi_gyro_client_data *client_data =
+ container_of((struct delayed_work *)work,
+ struct smi_gyro_client_data, work);
+
+ unsigned long delay =
+ msecs_to_jiffies(atomic_read(&client_data->delay));
+ struct smi130_gyro_data_t gyro_data;
+
+ SMI_GYRO_CALL_API(get_dataXYZ)(&gyro_data);
+ /*remapping for SMI130_GYRO sensor*/
+ smi130_gyro_remap_sensor_data(&gyro_data, client_data);
+
+ input_report_abs(client_data->input, ABS_X, gyro_data.datax);
+ input_report_abs(client_data->input, ABS_Y, gyro_data.datay);
+ input_report_abs(client_data->input, ABS_Z, gyro_data.dataz);
+ input_sync(client_data->input);
+
+ schedule_delayed_work(&client_data->work, delay);
+}
+
+static struct workqueue_struct *reportdata_wq;
+
+uint64_t smi130_gyro_get_alarm_timestamp(void)
+{
+ uint64_t ts_ap;
+ struct timespec tmp_time;
+ get_monotonic_boottime(&tmp_time);
+ ts_ap = (uint64_t)tmp_time.tv_sec * 1000000000 + tmp_time.tv_nsec;
+ return ts_ap;
+}
+#define ABS(x) ((x) > 0 ? (x) : -(x))
+
+static void smi130_gyro_work_func(struct work_struct *work)
+{
+ struct smi_gyro_client_data *smi130_gyro =
+ container_of(work,
+ struct smi_gyro_client_data, report_data_work);
+ int i;
+ struct smi130_gyro_data_t gyro_lsb;
+ unsigned char fifo_framecount;
+ signed char fifo_data_out[MAX_FIFO_F_LEVEL * MAX_FIFO_F_BYTES] = {0};
+ unsigned char f_len = 0;
+ uint64_t del;
+ uint64_t time_internal;
+ struct timespec ts;
+ int64_t drift_time = 0;
+ static uint64_t time_odr;
+ static uint32_t data_cnt;
+ static uint32_t pre_data_cnt;
+ static int64_t sample_drift_offset;
+ if (smi130_gyro->fifo_datasel)
+ /*Select one axis data output for every fifo frame*/
+ f_len = 2;
+ else
+ /*Select X Y Z axis data output for every fifo frame*/
+ f_len = 6;
+ if (SMI_GYRO_CALL_API(get_fifo_framecount)(&fifo_framecount) < 0) {
+ PERR("bm160_get_fifo_framecount err\n");
+ return;
+ }
+ if (fifo_framecount == 0)
+ return;
+ if (fifo_framecount > MAX_FIFO_F_LEVEL)
+ fifo_framecount = MAX_FIFO_F_LEVEL;
+ if (smi_gyro_i2c_burst_read(smi130_gyro->client, SMI130_GYRO_FIFO_DATA_ADDR,
+ fifo_data_out, fifo_framecount * f_len) < 0) {
+ PERR("smi130_gyro read fifo err\n");
+ return;
+ }
+ smi130_gyro->fifo_time = smi130_gyro_get_alarm_timestamp();
+ if (smi130_gyro->gyro_count == 0)
+ smi130_gyro->base_time = smi130_gyro->timestamp =
+ smi130_gyro->fifo_time - (fifo_framecount-1) * smi130_gyro->time_odr;
+
+ smi130_gyro->gyro_count += fifo_framecount;
+ del = smi130_gyro->fifo_time - smi130_gyro->base_time;
+ time_internal = div64_u64(del, smi130_gyro->gyro_count);
+ data_cnt++;
+ if (data_cnt == 1)
+ time_odr = smi130_gyro->time_odr;
+ if (time_internal > time_odr) {
+ if (time_internal - time_odr > div64_u64 (time_odr, 200))
+ time_internal = time_odr + div64_u64(time_odr, 200);
+ } else {
+ if (time_odr - time_internal > div64_u64(time_odr, 200))
+ time_internal = time_odr - div64_u64(time_odr, 200);
+ }
+
+ /* Select X Y Z axis data output for every frame */
+ for (i = 0; i < fifo_framecount; i++) {
+ if (smi130_gyro->debug_level & 0x01)
+ printk(KERN_INFO "smi_gyro time =%llu fifo_time = %llu time_internal = %llu smi_gyro->count= %llu count = %d",
+ smi130_gyro->timestamp, smi130_gyro->fifo_time,
+ time_internal, smi130_gyro->gyro_count, fifo_framecount);
+ ts = ns_to_timespec(smi130_gyro->timestamp);
+ gyro_lsb.datax =
+ ((unsigned char)fifo_data_out[i * f_len + 1] << 8
+ | (unsigned char)fifo_data_out[i * f_len + 0]);
+ gyro_lsb.datay =
+ ((unsigned char)fifo_data_out[i * f_len + 3] << 8
+ | (unsigned char)fifo_data_out[i * f_len + 2]);
+ gyro_lsb.dataz =
+ ((unsigned char)fifo_data_out[i * f_len + 5] << 8
+ | (unsigned char)fifo_data_out[i * f_len + 4]);
+ smi130_gyro_remap_sensor_data(&gyro_lsb, smi130_gyro);
+ input_event(smi130_gyro->input, EV_MSC, MSC_TIME,
+ ts.tv_sec);
+ input_event(smi130_gyro->input, EV_MSC, MSC_TIME,
+ ts.tv_nsec);
+ input_event(smi130_gyro->input, EV_MSC,
+ MSC_GESTURE, gyro_lsb.datax);
+ input_event(smi130_gyro->input, EV_MSC,
+ MSC_RAW, gyro_lsb.datay);
+ input_event(smi130_gyro->input, EV_MSC,
+ MSC_SCAN, gyro_lsb.dataz);
+ input_sync(smi130_gyro->input);
+ smi130_gyro->timestamp += time_internal - sample_drift_offset;
+ }
+ drift_time = smi130_gyro->timestamp - smi130_gyro->fifo_time;
+ if (data_cnt % 20 == 0) {
+ if (ABS(drift_time) > div64_u64(time_odr, 5)) {
+ sample_drift_offset =
+ div64_s64(drift_time, smi130_gyro->gyro_count - pre_data_cnt);
+ pre_data_cnt = smi130_gyro->gyro_count;
+ time_odr = time_internal;
+ }
+ }
+}
+
+
+static enum hrtimer_restart reportdata_timer_fun(
+ struct hrtimer *hrtimer)
+{
+ struct smi_gyro_client_data *client_data =
+ container_of(hrtimer, struct smi_gyro_client_data, timer);
+ int32_t delay = 0;
+ delay = 10;
+ queue_work(reportdata_wq, &(client_data->report_data_work));
+ client_data->work_delay_kt = ns_to_ktime(delay*1000000);
+ hrtimer_forward(hrtimer, ktime_get(), client_data->work_delay_kt);
+
+ return HRTIMER_RESTART;
+}
+
+static ssize_t smi_gyro_show_enable_timer(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "%d\n", client_data->is_timer_running);
+}
+
+static ssize_t smi_gyro_store_enable_timer(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (data) {
+ if (0 == client_data->is_timer_running) {
+ hrtimer_start(&client_data->timer,
+ ns_to_ktime(10000000),
+ HRTIMER_MODE_REL);
+ client_data->is_timer_running = 1;
+ client_data->base_time = 0;
+ client_data->timestamp = 0;
+ client_data->gyro_count = 0;
+ }
+ } else {
+ if (1 == client_data->is_timer_running) {
+ hrtimer_cancel(&client_data->timer);
+ client_data->is_timer_running = 0;
+ client_data->base_time = 0;
+ client_data->timestamp = 0;
+ client_data->gyro_count = 0;
+ }
+ }
+ return count;
+}
+
+static ssize_t smi130_gyro_show_debug_level(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ err = snprintf(buf, 8, "%d\n", client_data->debug_level);
+ return err;
+}
+static ssize_t smi130_gyro_store_debug_level(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int32_t ret = 0;
+ unsigned long data;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ ret = kstrtoul(buf, 16, &data);
+ if (ret)
+ return ret;
+ client_data->debug_level = (uint8_t)data;
+ return count;
+}
+
+static int smi_gyro_set_soft_reset(struct i2c_client *client)
+{
+ int err = 0;
+ unsigned char data = SMI_GYRO_SOFT_RESET_VALUE;
+ err = smi_gyro_i2c_write(client, SMI130_GYRO_BGW_SOFTRESET_ADDR, &data, 1);
+ return err;
+}
+
+static ssize_t smi_gyro_show_chip_id(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, 16, "%d\n", SENSOR_CHIP_ID_SMI_GYRO);
+}
+
+static ssize_t smi_gyro_show_op_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ u8 op_mode = 0xff;
+
+ mutex_lock(&client_data->mutex_op_mode);
+ SMI_GYRO_CALL_API(get_mode)(&op_mode);
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ ret = snprintf(buf, 16, "%d\n", op_mode);
+
+ return ret;
+}
+
+static ssize_t smi_gyro_store_op_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+
+ long op_mode;
+
+ err = kstrtoul(buf, 10, &op_mode);
+ if (err)
+ return err;
+ mutex_lock(&client_data->mutex_op_mode);
+
+ err = SMI_GYRO_CALL_API(set_mode)(op_mode);
+
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ if (err)
+ return err;
+ else
+ return count;
+}
+
+
+
+static ssize_t smi_gyro_show_value(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ int count;
+
+ struct smi130_gyro_data_t value_data;
+ SMI_GYRO_CALL_API(get_dataXYZ)(&value_data);
+ /*SMI130_GYRO sensor raw data remapping*/
+ smi130_gyro_remap_sensor_data(&value_data, client_data);
+
+ count = snprintf(buf, 96, "%hd %hd %hd\n",
+ value_data.datax,
+ value_data.datay,
+ value_data.dataz);
+
+ return count;
+}
+
+static ssize_t smi_gyro_show_range(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char range = 0;
+ SMI_GYRO_CALL_API(get_range_reg)(&range);
+ err = snprintf(buf, 16, "%d\n", range);
+ return err;
+}
+
+static ssize_t smi_gyro_store_range(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long range;
+ err = kstrtoul(buf, 10, &range);
+ if (err)
+ return err;
+ SMI_GYRO_CALL_API(set_range_reg)(range);
+ return count;
+}
+
+/*
+decimation odr filter bandwidth bits
+20 100HZ 32HZ 7
+10 200Hz 64HZ 6
+20 100HZ 12HZ 5
+10 200hz 23HZ 4
+5 400HZ 47HZ 3
+2 1000HZ 116HZ 2
+0 2000HZ 230HZ 1
+0 2000HZ Unfiltered(523HZ) 0
+*/
+
+static const uint64_t odr_map[8] = {
+500000, 500000, 1000000, 2500000, 5000000, 10000000, 5000000, 10000000};
+
+static ssize_t smi_gyro_show_bandwidth(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char bandwidth = 0;
+ SMI_GYRO_CALL_API(get_bw)(&bandwidth);
+ err = snprintf(buf, 16, "%d\n", bandwidth);
+ return err;
+}
+
+static ssize_t smi_gyro_store_bandwidth(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ unsigned long bandwidth;
+ u8 op_mode = 0xff;
+ err = kstrtoul(buf, 10, &bandwidth);
+ if (err)
+ return err;
+ /*
+ set bandwidth only in the op_mode=0
+ */
+ err = SMI_GYRO_CALL_API(get_mode)(&op_mode);
+ if (op_mode == 0) {
+ err += SMI_GYRO_CALL_API(set_bw)(bandwidth);
+ } else {
+ err += SMI_GYRO_CALL_API(set_mode)(0);
+ err += SMI_GYRO_CALL_API(set_bw)(bandwidth);
+ smi130_gyro_delay(1);
+ err += SMI_GYRO_CALL_API(set_mode)(2);
+ smi130_gyro_delay(3);
+ }
+
+ if (err)
+ PERR("set failed");
+ client_data->time_odr = odr_map[bandwidth];
+ client_data->base_time = 0;
+ client_data->gyro_count = 0;
+ return count;
+}
+
+
+static ssize_t smi_gyro_show_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ int err;
+
+ mutex_lock(&client_data->mutex_enable);
+ err = snprintf(buf, 16, "%d\n", client_data->enable);
+ mutex_unlock(&client_data->mutex_enable);
+ return err;
+}
+
+static ssize_t smi_gyro_store_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ data = data ? 1 : 0;
+ mutex_lock(&client_data->mutex_enable);
+ if (data != client_data->enable) {
+ if (data) {
+ schedule_delayed_work(
+ &client_data->work,
+ msecs_to_jiffies(atomic_read(
+ &client_data->delay)));
+ } else {
+ cancel_delayed_work_sync(&client_data->work);
+ }
+
+ client_data->enable = data;
+ }
+ mutex_unlock(&client_data->mutex_enable);
+
+ return count;
+}
+
+static ssize_t smi_gyro_show_delay(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+
+ return snprintf(buf, 16, "%d\n", atomic_read(&client_data->delay));
+
+}
+
+static ssize_t smi_gyro_store_delay(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+
+ err = kstrtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ if (data == 0) {
+ err = -EINVAL;
+ return err;
+ }
+
+ if (data < SMI_GYRO_DELAY_MIN)
+ data = SMI_GYRO_DELAY_MIN;
+
+ atomic_set(&client_data->delay, data);
+
+ return count;
+}
+
+
+static ssize_t smi_gyro_store_fastoffset_en(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long fastoffset_en;
+ err = kstrtoul(buf, 10, &fastoffset_en);
+ if (err)
+ return err;
+ if (fastoffset_en) {
+
+#ifdef CONFIG_SENSORS_BMI058
+ SMI_GYRO_CALL_API(set_fast_offset_en_ch)(BMI058_X_AXIS, 1);
+ SMI_GYRO_CALL_API(set_fast_offset_en_ch)(BMI058_Y_AXIS, 1);
+#else
+ SMI_GYRO_CALL_API(set_fast_offset_en_ch)(SMI130_GYRO_X_AXIS, 1);
+ SMI_GYRO_CALL_API(set_fast_offset_en_ch)(SMI130_GYRO_Y_AXIS, 1);
+#endif
+
+ SMI_GYRO_CALL_API(set_fast_offset_en_ch)(SMI130_GYRO_Z_AXIS, 1);
+ SMI_GYRO_CALL_API(enable_fast_offset)();
+ }
+ return count;
+}
+
+static ssize_t smi_gyro_store_slowoffset_en(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long slowoffset_en;
+ err = kstrtoul(buf, 10, &slowoffset_en);
+ if (err)
+ return err;
+ if (slowoffset_en) {
+ SMI_GYRO_CALL_API(set_slow_offset_th)(3);
+ SMI_GYRO_CALL_API(set_slow_offset_dur)(0);
+#ifdef CONFIG_SENSORS_BMI058
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(BMI058_X_AXIS, 1);
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(BMI058_Y_AXIS, 1);
+#else
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(SMI130_GYRO_X_AXIS, 1);
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(SMI130_GYRO_Y_AXIS, 1);
+#endif
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(SMI130_GYRO_Z_AXIS, 1);
+ } else {
+#ifdef CONFIG_SENSORS_BMI058
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(BMI058_X_AXIS, 0);
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(BMI058_Y_AXIS, 0);
+#else
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(SMI130_GYRO_X_AXIS, 0);
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(SMI130_GYRO_Y_AXIS, 0);
+#endif
+ SMI_GYRO_CALL_API(set_slow_offset_en_ch)(SMI130_GYRO_Z_AXIS, 0);
+ }
+
+ return count;
+}
+
+static ssize_t smi_gyro_show_selftest(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char selftest;
+ SMI_GYRO_CALL_API(selftest)(&selftest);
+ err = snprintf(buf, 16, "%d\n", selftest);
+ return err;
+}
+
+static ssize_t smi_gyro_show_sleepdur(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char sleepdur;
+ SMI_GYRO_CALL_API(get_sleepdur)(&sleepdur);
+ err = snprintf(buf, 16, "%d\n", sleepdur);
+ return err;
+}
+
+static ssize_t smi_gyro_store_sleepdur(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long sleepdur;
+ err = kstrtoul(buf, 10, &sleepdur);
+ if (err)
+ return err;
+ SMI_GYRO_CALL_API(set_sleepdur)(sleepdur);
+ return count;
+}
+
+static ssize_t smi_gyro_show_autosleepdur(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char autosleepdur;
+ SMI_GYRO_CALL_API(get_autosleepdur)(&autosleepdur);
+ err = snprintf(buf, 16, "%d\n", autosleepdur);
+ return err;
+}
+
+static ssize_t smi_gyro_store_autosleepdur(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long autosleepdur;
+ unsigned char bandwidth;
+ err = kstrtoul(buf, 10, &autosleepdur);
+ if (err)
+ return err;
+ SMI_GYRO_CALL_API(get_bw)(&bandwidth);
+ SMI_GYRO_CALL_API(set_autosleepdur)(autosleepdur, bandwidth);
+ return count;
+}
+
+static ssize_t smi_gyro_show_place(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ int place = BOSCH_SENSOR_PLACE_UNKNOWN;
+
+ if (NULL != client_data->bosch_pd)
+ place = client_data->bosch_pd->place;
+
+ return snprintf(buf, 16, "%d\n", place);
+}
+
+
+#ifdef SMI_GYRO_DEBUG
+static ssize_t smi_gyro_store_softreset(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long softreset;
+ err = kstrtoul(buf, 10, &softreset);
+ if (err)
+ return err;
+ SMI_GYRO_CALL_API(set_soft_reset)();
+ return count;
+}
+
+static ssize_t smi_gyro_show_dumpreg(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ size_t count = 0;
+ u8 reg[0x40];
+ int i;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+
+ for (i = 0; i < 0x40; i++) {
+ smi_gyro_i2c_read(client_data->client, i, reg+i, 1);
+
+ count += snprintf(&buf[count], 48, "0x%x: 0x%x\n", i, reg[i]);
+ }
+ return count;
+}
+#endif
+
+#ifdef SMI_GYRO_USE_FIFO
+static ssize_t smi_gyro_show_fifo_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char fifo_mode;
+ SMI_GYRO_CALL_API(get_fifo_mode)(&fifo_mode);
+ err = snprintf(buf, 16, "%d\n", fifo_mode);
+ return err;
+}
+
+static ssize_t smi_gyro_store_fifo_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long fifo_mode;
+ err = kstrtoul(buf, 10, &fifo_mode);
+ if (err)
+ return err;
+ SMI_GYRO_CALL_API(set_fifo_mode)(fifo_mode);
+ return count;
+}
+
+static ssize_t smi_gyro_show_fifo_framecount(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char fifo_framecount;
+ SMI_GYRO_CALL_API(get_fifo_framecount)(&fifo_framecount);
+ err = snprintf(buf, 32, "%d\n", fifo_framecount);
+ return err;
+}
+
+static ssize_t smi_gyro_store_fifo_framecount(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ error = kstrtoul(buf, 10, &data);
+ if (error)
+ return error;
+ client_data->fifo_count = (unsigned int) data;
+
+ return count;
+}
+
+static ssize_t smi_gyro_show_fifo_overrun(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char fifo_overrun;
+ SMI_GYRO_CALL_API(get_fifo_overrun)(&fifo_overrun);
+ err = snprintf(buf, 16, "%d\n", fifo_overrun);
+ return err;
+}
+
+static ssize_t smi_gyro_show_fifo_data_frame(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char f_len = 0;
+ unsigned char fifo_framecount;
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+
+ if (client_data->fifo_datasel)
+ /*Select one axis data output for every fifo frame*/
+ f_len = 2;
+ else
+ /*Select X Y Z axis data output for every fifo frame*/
+ f_len = 6;
+
+ if (SMI_GYRO_CALL_API(get_fifo_framecount)(&fifo_framecount) < 0) {
+ PERR("bm160_get_fifo_framecount err\n");
+ return -EINVAL;
+ }
+ if (fifo_framecount == 0)
+ return 0;
+
+ smi_gyro_i2c_burst_read(client_data->client, SMI130_GYRO_FIFO_DATA_ADDR,
+ buf, fifo_framecount * f_len);
+ return fifo_framecount * f_len;
+}
+
+/*!
+ * @brief show fifo_data_sel axis definition(Android definition, not sensor HW reg).
+ * 0--> x, y, z axis fifo data for every frame
+ * 1--> only x axis fifo data for every frame
+ * 2--> only y axis fifo data for every frame
+ * 3--> only z axis fifo data for every frame
+ */
+static ssize_t smi_gyro_show_fifo_data_sel(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char fifo_data_sel;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smi_gyro_client_data *client_data = i2c_get_clientdata(client);
+ signed char place = BOSCH_SENSOR_PLACE_UNKNOWN;
+
+ SMI_GYRO_CALL_API(get_fifo_data_sel)(&fifo_data_sel);
+
+ /*remapping fifo_dat_sel if define virtual place in BSP files*/
+ if ((NULL != client_data->bosch_pd) &&
+ (BOSCH_SENSOR_PLACE_UNKNOWN != client_data->bosch_pd->place)) {
+ place = client_data->bosch_pd->place;
+ /* sensor with place 0 needs not to be remapped */
+ if ((place > 0) && (place < MAX_AXIS_REMAP_TAB_SZ)) {
+ if (SMI130_GYRO_FIFO_DAT_SEL_X == fifo_data_sel)
+ /* SMI130_GYRO_FIFO_DAT_SEL_X: 1, Y:2, Z:3;
+ *bosch_axis_remap_tab_dft[i].src_x:0, y:1, z:2
+ *so we need to +1*/
+ fifo_data_sel =
+ bosch_axis_remap_tab_dft[place].src_x + 1;
+
+ else if (SMI130_GYRO_FIFO_DAT_SEL_Y == fifo_data_sel)
+ fifo_data_sel =
+ bosch_axis_remap_tab_dft[place].src_y + 1;
+ }
+
+ }
+
+ err = snprintf(buf, 16, "%d\n", fifo_data_sel);
+ return err;
+}
+
+/*!
+ * @brief store fifo_data_sel axis definition(Android definition, not sensor HW reg).
+ * 0--> x, y, z axis fifo data for every frame
+ * 1--> only x axis fifo data for every frame
+ * 2--> only y axis fifo data for every frame
+ * 3--> only z axis fifo data for every frame
+ */
+static ssize_t smi_gyro_store_fifo_data_sel(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+
+{
+ int err;
+ unsigned long fifo_data_sel;
+
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ signed char place;
+
+ err = kstrtoul(buf, 10, &fifo_data_sel);
+ if (err)
+ return err;
+
+ /*save fifo_data_sel(android axis definition)*/
+ client_data->fifo_datasel = (unsigned char) fifo_data_sel;
+
+ /*remaping fifo_dat_sel if define virtual place*/
+ if ((NULL != client_data->bosch_pd) &&
+ (BOSCH_SENSOR_PLACE_UNKNOWN != client_data->bosch_pd->place)) {
+ place = client_data->bosch_pd->place;
+ /* sensor with place 0 needs not to be remapped */
+ if ((place > 0) && (place < MAX_AXIS_REMAP_TAB_SZ)) {
+ /*Need X Y axis revesal sensor place: P1, P3, P5, P7 */
+ /* SMI130_GYRO_FIFO_DAT_SEL_X: 1, Y:2, Z:3;
+ * but bosch_axis_remap_tab_dft[i].src_x:0, y:1, z:2
+ * so we need to +1*/
+ if (SMI130_GYRO_FIFO_DAT_SEL_X == fifo_data_sel)
+ fifo_data_sel =
+ bosch_axis_remap_tab_dft[place].src_x + 1;
+
+ else if (SMI130_GYRO_FIFO_DAT_SEL_Y == fifo_data_sel)
+ fifo_data_sel =
+ bosch_axis_remap_tab_dft[place].src_y + 1;
+ }
+ }
+
+ if (SMI_GYRO_CALL_API(set_fifo_data_sel)(fifo_data_sel) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t smi_gyro_show_fifo_tag(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ unsigned char fifo_tag;
+ SMI_GYRO_CALL_API(get_fifo_tag)(&fifo_tag);
+ err = snprintf(buf, 16, "%d\n", fifo_tag);
+ return err;
+}
+
+static ssize_t smi_gyro_store_fifo_tag(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+
+{
+ int err;
+ unsigned long fifo_tag;
+ err = kstrtoul(buf, 10, &fifo_tag);
+ if (err)
+ return err;
+ SMI_GYRO_CALL_API(set_fifo_tag)(fifo_tag);
+ return count;
+}
+#endif
+
+static ssize_t smi130_gyro_driver_version_show(struct device *dev
+ , struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct smi_gyro_client_data *client_data = input_get_drvdata(input);
+ int ret;
+
+ if (client_data == NULL) {
+ printk(KERN_ERR "Invalid client_data pointer");
+ return -ENODEV;
+ }
+
+ ret = snprintf(buf, 128, "Driver version: %s\n",
+ DRIVER_VERSION);
+ return ret;
+}
+static DEVICE_ATTR(chip_id, S_IRUSR,
+ smi_gyro_show_chip_id, NULL);
+static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR,
+ smi_gyro_show_op_mode, smi_gyro_store_op_mode);
+static DEVICE_ATTR(value, S_IRUSR,
+ smi_gyro_show_value, NULL);
+static DEVICE_ATTR(range, S_IRUGO | S_IWUSR,
+ smi_gyro_show_range, smi_gyro_store_range);
+static DEVICE_ATTR(bandwidth, S_IRUGO | S_IWUSR,
+ smi_gyro_show_bandwidth, smi_gyro_store_bandwidth);
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
+ smi_gyro_show_enable, smi_gyro_store_enable);
+static DEVICE_ATTR(delay, S_IRUGO | S_IWUSR,
+ smi_gyro_show_delay, smi_gyro_store_delay);
+static DEVICE_ATTR(fastoffset_en, S_IWUSR,
+ NULL, smi_gyro_store_fastoffset_en);
+static DEVICE_ATTR(slowoffset_en, S_IWUSR,
+ NULL, smi_gyro_store_slowoffset_en);
+static DEVICE_ATTR(selftest, S_IRUGO,
+ smi_gyro_show_selftest, NULL);
+static DEVICE_ATTR(sleepdur, S_IRUGO | S_IWUSR,
+ smi_gyro_show_sleepdur, smi_gyro_store_sleepdur);
+static DEVICE_ATTR(autosleepdur, S_IRUGO | S_IWUSR,
+ smi_gyro_show_autosleepdur, smi_gyro_store_autosleepdur);
+static DEVICE_ATTR(place, S_IRUSR,
+ smi_gyro_show_place, NULL);
+static DEVICE_ATTR(enable_timer, S_IRUGO | S_IWUSR,
+ smi_gyro_show_enable_timer, smi_gyro_store_enable_timer);
+static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
+ smi130_gyro_show_debug_level, smi130_gyro_store_debug_level);
+static DEVICE_ATTR(driver_version, S_IRUSR,
+ smi130_gyro_driver_version_show, NULL);
+#ifdef SMI_GYRO_DEBUG
+static DEVICE_ATTR(softreset, S_IWUSR,
+ NULL, smi_gyro_store_softreset);
+static DEVICE_ATTR(regdump, S_IRUSR,
+ smi_gyro_show_dumpreg, NULL);
+#endif
+#ifdef SMI_GYRO_USE_FIFO
+static DEVICE_ATTR(fifo_mode, S_IRUGO | S_IWUSR,
+ smi_gyro_show_fifo_mode, smi_gyro_store_fifo_mode);
+static DEVICE_ATTR(fifo_framecount, S_IRUGO | S_IWUSR,
+ smi_gyro_show_fifo_framecount, smi_gyro_store_fifo_framecount);
+static DEVICE_ATTR(fifo_overrun, S_IRUGO,
+ smi_gyro_show_fifo_overrun, NULL);
+static DEVICE_ATTR(fifo_data_frame, S_IRUSR,
+ smi_gyro_show_fifo_data_frame, NULL);
+static DEVICE_ATTR(fifo_data_sel, S_IRUGO | S_IWUSR,
+ smi_gyro_show_fifo_data_sel, smi_gyro_store_fifo_data_sel);
+static DEVICE_ATTR(fifo_tag, S_IRUGO | S_IWUSR,
+ smi_gyro_show_fifo_tag, smi_gyro_store_fifo_tag);
+#endif
+
+static struct attribute *smi_gyro_attributes[] = {
+ &dev_attr_chip_id.attr,
+ &dev_attr_op_mode.attr,
+ &dev_attr_value.attr,
+ &dev_attr_range.attr,
+ &dev_attr_bandwidth.attr,
+ &dev_attr_enable.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_fastoffset_en.attr,
+ &dev_attr_slowoffset_en.attr,
+ &dev_attr_selftest.attr,
+ &dev_attr_sleepdur.attr,
+ &dev_attr_autosleepdur.attr,
+ &dev_attr_place.attr,
+ &dev_attr_enable_timer.attr,
+ &dev_attr_debug_level.attr,
+ &dev_attr_driver_version.attr,
+#ifdef SMI_GYRO_DEBUG
+ &dev_attr_softreset.attr,
+ &dev_attr_regdump.attr,
+#endif
+#ifdef SMI_GYRO_USE_FIFO
+ &dev_attr_fifo_mode.attr,
+ &dev_attr_fifo_framecount.attr,
+ &dev_attr_fifo_overrun.attr,
+ &dev_attr_fifo_data_frame.attr,
+ &dev_attr_fifo_data_sel.attr,
+ &dev_attr_fifo_tag.attr,
+#endif
+ NULL
+};
+
+static struct attribute_group smi_gyro_attribute_group = {
+ .attrs = smi_gyro_attributes
+};
+
+
+static int smi_gyro_input_init(struct smi_gyro_client_data *client_data)
+{
+ struct input_dev *dev;
+ int err = 0;
+
+ dev = input_allocate_device();
+ if (NULL == dev)
+ return -ENOMEM;
+
+ dev->name = SENSOR_NAME;
+ dev->id.bustype = BUS_I2C;
+
+ input_set_capability(dev, EV_ABS, ABS_MISC);
+ input_set_abs_params(dev, ABS_X, SMI_GYRO_VALUE_MIN, SMI_GYRO_VALUE_MAX, 0, 0);
+ input_set_abs_params(dev, ABS_Y, SMI_GYRO_VALUE_MIN, SMI_GYRO_VALUE_MAX, 0, 0);
+ input_set_abs_params(dev, ABS_Z, SMI_GYRO_VALUE_MIN, SMI_GYRO_VALUE_MAX, 0, 0);
+ input_set_capability(dev, EV_MSC, MSC_GESTURE);
+ input_set_capability(dev, EV_MSC, MSC_RAW);
+ input_set_capability(dev, EV_MSC, MSC_SCAN);
+ input_set_capability(dev, EV_MSC, MSC_TIME);
+ input_set_drvdata(dev, client_data);
+
+ err = input_register_device(dev);
+ if (err < 0) {
+ input_free_device(dev);
+ return err;
+ }
+ client_data->input = dev;
+
+ return 0;
+}
+
+static void smi_gyro_input_destroy(struct smi_gyro_client_data *client_data)
+{
+ struct input_dev *dev = client_data->input;
+
+ input_unregister_device(dev);
+ input_free_device(dev);
+}
+
+#if defined(SMI130_GYRO_ENABLE_INT1) || defined(SMI130_GYRO_ENABLE_INT2)
+static void smi130_gyro_irq_work_func(struct work_struct *work)
+{
+ struct smi_gyro_client_data *client_data = container_of(work,
+ struct smi_gyro_client_data, irq_work);
+ struct smi130_gyro_data_t gyro_data;
+ struct timespec ts;
+ ts = ns_to_timespec(client_data->timestamp);
+
+ SMI_GYRO_CALL_API(get_dataXYZ)(&gyro_data);
+ /*remapping for SMI130_GYRO sensor*/
+ smi130_gyro_remap_sensor_data(&gyro_data, client_data);
+ input_event(client_data->input, EV_MSC, MSC_TIME,
+ ts.tv_sec);
+ input_event(client_data->input, EV_MSC, MSC_TIME,
+ ts.tv_nsec);
+ input_event(client_data->input, EV_MSC,
+ MSC_GESTURE, gyro_data.datax);
+ input_event(client_data->input, EV_MSC,
+ MSC_RAW, gyro_data.datay);
+ input_event(client_data->input, EV_MSC,
+ MSC_SCAN, gyro_data.dataz);
+ input_sync(client_data->input);
+
+}
+
+static irqreturn_t smi_gyro_irq_handler(int irq, void *handle)
+{
+ struct smi_gyro_client_data *client_data = handle;
+ client_data->timestamp= smi130_gyro_get_alarm_timestamp();
+ schedule_work(&client_data->irq_work);
+ return IRQ_HANDLED;
+}
+#endif
+static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct smi_gyro_client_data *client_data = NULL;
+ PINFO("function entrance");
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ PERR("i2c_check_functionality error!");
+ err = -EIO;
+ goto exit_err_clean;
+ }
+
+ if (NULL == smi_gyro_client) {
+ smi_gyro_client = client;
+ } else {
+ PERR("this driver does not support multiple clients");
+ err = -EINVAL;
+ goto exit_err_clean;
+ }
+
+ /* check chip id */
+ err = smi_gyro_check_chip_id(client);
+ if (!err) {
+ PINFO("Bosch Sensortec Device %s detected", SENSOR_NAME);
+ } else {
+ PERR("Bosch Sensortec Device not found, chip id mismatch");
+ err = -1;
+ goto exit_err_clean;
+ }
+
+ /* do soft reset */
+ smi130_gyro_delay(5);
+ err = smi_gyro_set_soft_reset(client);
+ if (err < 0) {
+ PERR("erro soft reset!\n");
+ err = -EINVAL;
+ goto exit_err_clean;
+ }
+ smi130_gyro_delay(30);
+
+
+ client_data = kzalloc(sizeof(struct smi_gyro_client_data), GFP_KERNEL);
+ if (NULL == client_data) {
+ PERR("no memory available");
+ err = -ENOMEM;
+ goto exit_err_clean;
+ }
+
+ i2c_set_clientdata(client, client_data);
+ client_data->client = client;
+
+ mutex_init(&client_data->mutex_op_mode);
+ mutex_init(&client_data->mutex_enable);
+
+ /* input device init */
+ err = smi_gyro_input_init(client_data);
+ if (err < 0)
+ goto exit_err_clean;
+
+ /* sysfs node creation */
+ err = sysfs_create_group(&client_data->input->dev.kobj,
+ &smi_gyro_attribute_group);
+
+ if (err < 0)
+ goto exit_err_sysfs;
+
+ if (NULL != client->dev.platform_data) {
+ client_data->bosch_pd = kzalloc(sizeof(*client_data->bosch_pd),
+ GFP_KERNEL);
+
+ if (NULL != client_data->bosch_pd) {
+ memcpy(client_data->bosch_pd, client->dev.platform_data,
+ sizeof(*client_data->bosch_pd));
+ PINFO("%s sensor driver set place: p%d",
+ SENSOR_NAME,
+ client_data->bosch_pd->place);
+ }
+ }
+
+ /* workqueue init */
+ INIT_DELAYED_WORK(&client_data->work, smi_gyro_work_func);
+ atomic_set(&client_data->delay, SMI_GYRO_DELAY_DEFAULT);
+
+ /* h/w init */
+ client_data->device.bus_read = smi_gyro_i2c_read_wrapper;
+ client_data->device.bus_write = smi_gyro_i2c_write_wrapper;
+ client_data->device.delay_msec = smi130_gyro_delay;
+ SMI_GYRO_CALL_API(init)(&client_data->device);
+
+ smi_gyro_dump_reg(client);
+
+ client_data->enable = 0;
+ client_data->fifo_datasel = 0;
+ client_data->fifo_count = 0;
+
+ /*workqueue init*/
+ INIT_WORK(&client_data->report_data_work,
+ smi130_gyro_work_func);
+ reportdata_wq = create_singlethread_workqueue("smi130_gyro_wq");
+ if (NULL == reportdata_wq)
+ PERR("fail to create the reportdta_wq %d", -ENOMEM);
+ hrtimer_init(&client_data->timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ client_data->timer.function = reportdata_timer_fun;
+ client_data->work_delay_kt = ns_to_ktime(10000000);
+ client_data->is_timer_running = 0;
+ client_data->time_odr = 500000;
+#ifdef SMI130_GYRO_ENABLE_INT1
+ err = SMI_GYRO_CALL_API(set_mode)(SMI130_GYRO_MODE_NORMAL);
+ smi130_gyro_delay(5);
+ /*config the interrupt and map the interrupt*/
+ /*high level trigger*/
+ err += smi130_gyro_set_int_lvl(SMI130_GYRO_INT1_DATA, 1);
+ smi130_gyro_delay(5);
+ err += smi130_gyro_set_int_od(SMI130_GYRO_INT1, 0);
+ smi130_gyro_delay(5);
+ err += smi130_gyro_set_int_data(SMI130_GYRO_INT1_DATA, SMI130_GYRO_ENABLE);
+ smi130_gyro_delay(5);
+ err += smi130_gyro_set_data_en(SMI130_GYRO_ENABLE);
+ smi130_gyro_delay(5);
+ /*default odr is 100HZ*/
+ err += SMI_GYRO_CALL_API(set_bw)(7);
+ smi130_gyro_delay(5);
+ if (err)
+ PERR("config sensor data ready interrupt failed");
+#endif
+#ifdef SMI130_GYRO_ENABLE_INT2
+ err = SMI_GYRO_CALL_API(set_mode)(SMI130_GYRO_MODE_NORMAL);
+ /*config the interrupt and map the interrupt*/
+ /*high level trigger*/
+ err += smi130_gyro_set_int_lvl(SMI130_GYRO_INT2_DATA, 1);
+ smi130_gyro_delay(3);
+ err += smi130_gyro_set_int_od(SMI130_GYRO_INT2, 0);
+ smi130_gyro_delay(5);
+ err += smi130_gyro_set_int_data(SMI130_GYRO_INT2_DATA, SMI130_GYRO_ENABLE);
+ smi130_gyro_delay(3);
+ err += smi130_gyro_set_data_en(SMI130_GYRO_ENABLE);
+ /*default odr is 100HZ*/
+ err += SMI_GYRO_CALL_API(set_bw)(7);
+ smi130_gyro_delay(5);
+ if (err)
+ PERR("config sensor data ready interrupt failed");
+#endif
+ err += SMI_GYRO_CALL_API(set_mode)(
+ SMI_GYRO_VAL_NAME(MODE_SUSPEND));
+ if (err < 0)
+ goto exit_err_sysfs;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ client_data->early_suspend_handler.suspend = smi_gyro_early_suspend;
+ client_data->early_suspend_handler.resume = smi_gyro_late_resume;
+ register_early_suspend(&client_data->early_suspend_handler);
+#endif
+#if defined(SMI130_GYRO_ENABLE_INT1) || defined(SMI130_GYRO_ENABLE_INT2)
+ client_data->gpio_pin = of_get_named_gpio_flags(
+ client->dev.of_node,
+ "smi130_gyro,gpio_irq", 0, NULL);
+ PDEBUG("smi130_gyro qpio number:%d\n", client_data->gpio_pin);
+ err = gpio_request_one(client_data->gpio_pin,
+ GPIOF_IN, "bm160_interrupt");
+ if (err < 0) {
+ PDEBUG("requestgpio failed\n");
+ client_data->gpio_pin = 0;
+ }
+ if (client_data->gpio_pin != 0) {
+ err = gpio_direction_input(client_data->gpio_pin);
+ if (err < 0) {
+ PDEBUG("request failed\n");
+ }
+ client_data->IRQ = gpio_to_irq(client_data->gpio_pin);
+ err = request_irq(client_data->IRQ, smi_gyro_irq_handler,
+ IRQF_TRIGGER_RISING,
+ SENSOR_NAME, client_data);
+ if (err < 0)
+ PDEBUG("request handle failed\n");
+ }
+ INIT_WORK(&client_data->irq_work, smi130_gyro_irq_work_func);
+#endif
+ PINFO("sensor %s probed successfully", SENSOR_NAME);
+
+ dev_dbg(&client->dev,
+ "i2c_client: %p client_data: %p i2c_device: %p input: %p",
+ client, client_data, &client->dev, client_data->input);
+
+ return 0;
+
+exit_err_sysfs:
+ if (err)
+ smi_gyro_input_destroy(client_data);
+
+exit_err_clean:
+ if (err) {
+ if (client_data != NULL) {
+ kfree(client_data);
+ client_data = NULL;
+ }
+
+ smi_gyro_client = NULL;
+ }
+
+ return err;
+}
+
+static int smi_gyro_pre_suspend(struct i2c_client *client)
+{
+ int err = 0;
+ struct smi_gyro_client_data *client_data =
+ (struct smi_gyro_client_data *)i2c_get_clientdata(client);
+ PINFO("function entrance");
+
+ mutex_lock(&client_data->mutex_enable);
+ if (client_data->enable) {
+ cancel_delayed_work_sync(&client_data->work);
+ PINFO("cancel work");
+ }
+ mutex_unlock(&client_data->mutex_enable);
+ if (client_data->is_timer_running) {
+ hrtimer_cancel(&client_data->timer);
+ client_data->base_time = 0;
+ client_data->timestamp = 0;
+ client_data->fifo_time = 0;
+ client_data->gyro_count = 0;
+ }
+ return err;
+}
+
+static int smi_gyro_post_resume(struct i2c_client *client)
+{
+ int err = 0;
+ struct smi_gyro_client_data *client_data =
+ (struct smi_gyro_client_data *)i2c_get_clientdata(client);
+
+ PINFO("function entrance");
+ mutex_lock(&client_data->mutex_enable);
+ if (client_data->enable) {
+ schedule_delayed_work(&client_data->work,
+ msecs_to_jiffies(
+ atomic_read(&client_data->delay)));
+ }
+ mutex_unlock(&client_data->mutex_enable);
+ if (client_data->is_timer_running) {
+ hrtimer_start(&client_data->timer,
+ ns_to_ktime(client_data->time_odr),
+ HRTIMER_MODE_REL);
+ client_data->base_time = 0;
+ client_data->timestamp = 0;
+ client_data->is_timer_running = 1;
+ client_data->gyro_count = 0;
+ }
+ return err;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void smi_gyro_early_suspend(struct early_suspend *handler)
+{
+ int err = 0;
+ struct smi_gyro_client_data *client_data =
+ (struct smi_gyro_client_data *)container_of(handler,
+ struct smi_gyro_client_data, early_suspend_handler);
+ struct i2c_client *client = client_data->client;
+
+ PINFO("function entrance");
+
+ mutex_lock(&client_data->mutex_op_mode);
+ if (client_data->enable) {
+ err = smi_gyro_pre_suspend(client);
+ err = SMI_GYRO_CALL_API(set_mode)(
+ SMI_GYRO_VAL_NAME(MODE_SUSPEND));
+ }
+ mutex_unlock(&client_data->mutex_op_mode);
+}
+
+static void smi_gyro_late_resume(struct early_suspend *handler)
+{
+
+ int err = 0;
+ struct smi_gyro_client_data *client_data =
+ (struct smi_gyro_client_data *)container_of(handler,
+ struct smi_gyro_client_data, early_suspend_handler);
+ struct i2c_client *client = client_data->client;
+
+ PINFO("function entrance");
+
+ mutex_lock(&client_data->mutex_op_mode);
+
+ if (client_data->enable)
+ err = SMI_GYRO_CALL_API(set_mode)(SMI_GYRO_VAL_NAME(MODE_NORMAL));
+
+ /* post resume operation */
+ smi_gyro_post_resume(client);
+
+ mutex_unlock(&client_data->mutex_op_mode);
+}
+#else
+static int smi_gyro_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ int err = 0;
+ struct smi_gyro_client_data *client_data =
+ (struct smi_gyro_client_data *)i2c_get_clientdata(client);
+
+ PINFO("function entrance");
+
+ mutex_lock(&client_data->mutex_op_mode);
+ if (client_data->enable) {
+ err = smi_gyro_pre_suspend(client);
+ err = SMI_GYRO_CALL_API(set_mode)(
+ SMI_GYRO_VAL_NAME(MODE_SUSPEND));
+ }
+ mutex_unlock(&client_data->mutex_op_mode);
+ return err;
+}
+
+static int smi_gyro_resume(struct i2c_client *client)
+{
+
+ int err = 0;
+ struct smi_gyro_client_data *client_data =
+ (struct smi_gyro_client_data *)i2c_get_clientdata(client);
+
+ PINFO("function entrance");
+
+ mutex_lock(&client_data->mutex_op_mode);
+
+ if (client_data->enable)
+ err = SMI_GYRO_CALL_API(set_mode)(SMI_GYRO_VAL_NAME(MODE_NORMAL));
+
+ /* post resume operation */
+ smi_gyro_post_resume(client);
+
+ mutex_unlock(&client_data->mutex_op_mode);
+ return err;
+}
+#endif
+
+void smi_gyro_shutdown(struct i2c_client *client)
+{
+ struct smi_gyro_client_data *client_data =
+ (struct smi_gyro_client_data *)i2c_get_clientdata(client);
+
+ mutex_lock(&client_data->mutex_op_mode);
+ SMI_GYRO_CALL_API(set_mode)(
+ SMI_GYRO_VAL_NAME(MODE_DEEPSUSPEND));
+ mutex_unlock(&client_data->mutex_op_mode);
+}
+
+static int smi_gyro_remove(struct i2c_client *client)
+{
+ int err = 0;
+ u8 op_mode;
+
+ struct smi_gyro_client_data *client_data =
+ (struct smi_gyro_client_data *)i2c_get_clientdata(client);
+
+ if (NULL != client_data) {
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&client_data->early_suspend_handler);
+#endif
+ mutex_lock(&client_data->mutex_op_mode);
+ SMI_GYRO_CALL_API(get_mode)(&op_mode);
+ if (SMI_GYRO_VAL_NAME(MODE_NORMAL) == op_mode) {
+ cancel_delayed_work_sync(&client_data->work);
+ PINFO("cancel work");
+ }
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ err = SMI_GYRO_CALL_API(set_mode)(
+ SMI_GYRO_VAL_NAME(MODE_SUSPEND));
+ smi130_gyro_delay(SMI_GYRO_I2C_WRITE_DELAY_TIME);
+
+ sysfs_remove_group(&client_data->input->dev.kobj,
+ &smi_gyro_attribute_group);
+ smi_gyro_input_destroy(client_data);
+ kfree(client_data);
+
+ smi_gyro_client = NULL;
+ }
+
+ return err;
+}
+
+static const struct i2c_device_id smi_gyro_id[] = {
+ { SENSOR_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, smi_gyro_id);
+static const struct of_device_id smi130_gyro_of_match[] = {
+ { .compatible = "smi130_gyro", },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, smi130_gyro_of_match);
+
+static struct i2c_driver smi_gyro_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+ .of_match_table = smi130_gyro_of_match,
+ },
+ .class = I2C_CLASS_HWMON,
+ .id_table = smi_gyro_id,
+ .probe = smi_gyro_probe,
+ .remove = smi_gyro_remove,
+ .shutdown = smi_gyro_shutdown,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ //.suspend = smi_gyro_suspend,
+ //.resume = smi_gyro_resume,
+#endif
+};
+
+static int __init SMI_GYRO_init(void)
+{
+ return i2c_add_driver(&smi_gyro_driver);
+}
+
+static void __exit SMI_GYRO_exit(void)
+{
+ i2c_del_driver(&smi_gyro_driver);
+}
+
+MODULE_AUTHOR("contact@bosch-sensortec.com>");
+MODULE_DESCRIPTION("SMI_GYRO GYROSCOPE SENSOR DRIVER");
+MODULE_LICENSE("GPL v2");
+
+module_init(SMI_GYRO_init);
+module_exit(SMI_GYRO_exit);
diff --git a/drivers/input/sensors/smi130/smi130_i2c.c b/drivers/input/sensors/smi130/smi130_i2c.c
new file mode 100644
index 000000000000..09c4d29e3959
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130_i2c.c
@@ -0,0 +1,472 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename smi130_i2c.c
+ * @date 2014/11/25 14:40
+ * @Modification Date 2018/08/28 18:20
+ * @id "20f77db"
+ * @version 1.3
+ *
+ * @brief
+ * This file implements moudle function, which add
+ * the driver to I2C core.
+*/
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "smi130_driver.h"
+
+/*! @defgroup smi130_i2c_src
+ * @brief smi130 i2c driver module
+ @{*/
+
+static struct i2c_client *smi_client;
+/*!
+ * @brief define i2c wirte function
+ *
+ * @param client the pointer of i2c client
+ * @param reg_addr register address
+ * @param data the pointer of data buffer
+ * @param len block size need to write
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+/* i2c read routine for API*/
+static s8 smi_i2c_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len)
+ {
+#if !defined SMI_USE_BASIC_I2C_FUNC
+ s32 dummy;
+ if (NULL == client)
+ return -EINVAL;
+
+ while (0 != len--) {
+#ifdef SMI_SMBUS
+ dummy = i2c_smbus_read_byte_data(client, reg_addr);
+ if (dummy < 0) {
+ dev_err(&client->dev, "i2c smbus read error");
+ return -EIO;
+ }
+ *data = (u8)(dummy & 0xff);
+#else
+ dummy = i2c_master_send(client, (char *)&reg_addr, 1);
+ if (dummy < 0) {
+ dev_err(&client->dev, "i2c bus master write error");
+ return -EIO;
+ }
+
+ dummy = i2c_master_recv(client, (char *)data, 1);
+ if (dummy < 0) {
+ dev_err(&client->dev, "i2c bus master read error");
+ return -EIO;
+ }
+#endif
+ reg_addr++;
+ data++;
+ }
+ return 0;
+#else
+ int retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ for (retry = 0; retry < SMI_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg,
+ ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ usleep_range(SMI_I2C_WRITE_DELAY_TIME * 1000,
+ SMI_I2C_WRITE_DELAY_TIME * 1000);
+ }
+
+ if (SMI_MAX_RETRY_I2C_XFER <= retry) {
+ dev_err(&client->dev, "I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+#endif
+ }
+
+
+static s8 smi_i2c_burst_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u16 len)
+{
+ int retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ for (retry = 0; retry < SMI_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ usleep_range(SMI_I2C_WRITE_DELAY_TIME * 1000,
+ SMI_I2C_WRITE_DELAY_TIME * 1000);
+ }
+
+ if (SMI_MAX_RETRY_I2C_XFER <= retry) {
+ dev_err(&client->dev, "I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+
+/* i2c write routine for */
+static s8 smi_i2c_write(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len)
+{
+#if !defined SMI_USE_BASIC_I2C_FUNC
+ s32 dummy;
+
+#ifndef SMI_SMBUS
+ u8 buffer[2];
+#endif
+
+ if (NULL == client)
+ return -EPERM;
+
+ while (0 != len--) {
+#ifdef SMI_SMBUS
+ dummy = i2c_smbus_write_byte_data(client, reg_addr, *data);
+#else
+ buffer[0] = reg_addr;
+ buffer[1] = *data;
+ dummy = i2c_master_send(client, (char *)buffer, 2);
+#endif
+ reg_addr++;
+ data++;
+ if (dummy < 0) {
+ dev_err(&client->dev, "error writing i2c bus");
+ return -EPERM;
+ }
+
+ }
+ usleep_range(SMI_I2C_WRITE_DELAY_TIME * 1000,
+ SMI_I2C_WRITE_DELAY_TIME * 1000);
+ return 0;
+#else
+ u8 buffer[2];
+ int retry;
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = buffer,
+ },
+ };
+
+ while (0 != len--) {
+ buffer[0] = reg_addr;
+ buffer[1] = *data;
+ for (retry = 0; retry < SMI_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg,
+ ARRAY_SIZE(msg)) > 0) {
+ break;
+ } else {
+ usleep_range(SMI_I2C_WRITE_DELAY_TIME * 1000,
+ SMI_I2C_WRITE_DELAY_TIME * 1000);
+ }
+ }
+ if (SMI_MAX_RETRY_I2C_XFER <= retry) {
+ dev_err(&client->dev, "I2C xfer error");
+ return -EIO;
+ }
+ reg_addr++;
+ data++;
+ }
+
+ usleep_range(SMI_I2C_WRITE_DELAY_TIME * 1000,
+ SMI_I2C_WRITE_DELAY_TIME * 1000);
+ return 0;
+#endif
+}
+
+
+static s8 smi_i2c_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ int err = 0;
+ err = smi_i2c_read(smi_client, reg_addr, data, len);
+ return err;
+}
+
+static s8 smi_i2c_write_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ int err = 0;
+ err = smi_i2c_write(smi_client, reg_addr, data, len);
+ return err;
+}
+
+s8 smi_burst_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u16 len)
+{
+ int err = 0;
+ err = smi_i2c_burst_read(smi_client, reg_addr, data, len);
+ return err;
+}
+EXPORT_SYMBOL(smi_burst_read_wrapper);
+/*!
+ * @brief SMI probe function via i2c bus
+ *
+ * @param client the pointer of i2c client
+ * @param id the pointer of i2c device id
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static int smi_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct smi_client_data *client_data = NULL;
+
+ dev_info(&client->dev, "SMI130 i2c function probe entrance");
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "i2c_check_functionality error!");
+ err = -EIO;
+ goto exit_err_clean;
+ }
+
+ if (NULL == smi_client) {
+ smi_client = client;
+ } else {
+ dev_err(&client->dev,
+ "this driver does not support multiple clients");
+ err = -EBUSY;
+ goto exit_err_clean;
+ }
+
+ client_data = kzalloc(sizeof(struct smi_client_data),
+ GFP_KERNEL);
+ if (NULL == client_data) {
+ dev_err(&client->dev, "no memory available");
+ err = -ENOMEM;
+ goto exit_err_clean;
+ }
+
+ client_data->device.bus_read = smi_i2c_read_wrapper;
+ client_data->device.bus_write = smi_i2c_write_wrapper;
+
+ return smi_probe(client_data, &client->dev);
+
+exit_err_clean:
+ if (err)
+ smi_client = NULL;
+ return err;
+}
+/*
+static int smi_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ int err = 0;
+ err = smi_suspend(&client->dev);
+ return err;
+}
+
+static int smi_i2c_resume(struct i2c_client *client)
+{
+ int err = 0;
+
+ err = smi_resume(&client->dev);
+
+ return err;
+}
+*/
+
+static int smi_i2c_remove(struct i2c_client *client)
+{
+ int err = 0;
+ err = smi_remove(&client->dev);
+ smi_client = NULL;
+
+ return err;
+}
+
+
+
+static const struct i2c_device_id smi_id[] = {
+ {SENSOR_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, smi_id);
+
+static const struct of_device_id smi130_of_match[] = {
+ { .compatible = "bosch-sensortec,smi130", },
+ { .compatible = "smi130", },
+ { .compatible = "bosch, smi130", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, smi130_of_match);
+
+static struct i2c_driver smi_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+ .of_match_table = smi130_of_match,
+ },
+ .class = I2C_CLASS_HWMON,
+ .id_table = smi_id,
+ .probe = smi_i2c_probe,
+ .remove = smi_i2c_remove,
+ /*.suspend = smi_i2c_suspend,
+ .resume = smi_i2c_resume,*/
+};
+
+static int __init SMI_i2c_init(void)
+{
+ return i2c_add_driver(&smi_i2c_driver);
+}
+
+static void __exit SMI_i2c_exit(void)
+{
+ i2c_del_driver(&smi_i2c_driver);
+}
+
+MODULE_AUTHOR("Contact <contact@bosch-sensortec.com>");
+MODULE_DESCRIPTION("driver for " SENSOR_NAME);
+MODULE_LICENSE("GPL v2");
+
+module_init(SMI_i2c_init);
+module_exit(SMI_i2c_exit);
+
diff --git a/drivers/input/sensors/smi130/smi130_spi.c b/drivers/input/sensors/smi130/smi130_spi.c
new file mode 100644
index 000000000000..b02efbf111b1
--- /dev/null
+++ b/drivers/input/sensors/smi130/smi130_spi.c
@@ -0,0 +1,402 @@
+/*!
+ * @section LICENSE
+ * (C) Copyright 2011~2016 Bosch Sensortec GmbH All Rights Reserved
+ *
+ * (C) Modification Copyright 2018 Robert Bosch Kft All Rights Reserved
+ *
+ * This software program is licensed subject to the GNU General
+ * Public License (GPL).Version 2,June 1991,
+ * available at http://www.fsf.org/copyleft/gpl.html
+ *
+ * Special: Description of the Software:
+ *
+ * This software module (hereinafter called "Software") and any
+ * information on application-sheets (hereinafter called "Information") is
+ * provided free of charge for the sole purpose to support your application
+ * work.
+ *
+ * As such, the Software is merely an experimental software, not tested for
+ * safety in the field and only intended for inspiration for further development
+ * and testing. Any usage in a safety-relevant field of use (like automotive,
+ * seafaring, spacefaring, industrial plants etc.) was not intended, so there are
+ * no precautions for such usage incorporated in the Software.
+ *
+ * The Software is specifically designed for the exclusive use for Bosch
+ * Sensortec products by personnel who have special experience and training. Do
+ * not use this Software if you do not have the proper experience or training.
+ *
+ * This Software package is provided as is and without any expressed or
+ * implied warranties, including without limitation, the implied warranties of
+ * merchantability and fitness for a particular purpose.
+ *
+ * Bosch Sensortec and their representatives and agents deny any liability for
+ * the functional impairment of this Software in terms of fitness, performance
+ * and safety. Bosch Sensortec and their representatives and agents shall not be
+ * liable for any direct or indirect damages or injury, except as otherwise
+ * stipulated in mandatory applicable law.
+ * The Information provided is believed to be accurate and reliable. Bosch
+ * Sensortec assumes no responsibility for the consequences of use of such
+ * Information nor for any infringement of patents or other rights of third
+ * parties which may result from its use.
+ *
+ *------------------------------------------------------------------------------
+ * The following Product Disclaimer does not apply to the BSX4-HAL-4.1NoFusion Software
+ * which is licensed under the Apache License, Version 2.0 as stated above.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Product Disclaimer
+ *
+ * Common:
+ *
+ * Assessment of Products Returned from Field
+ *
+ * Returned products are considered good if they fulfill the specifications /
+ * test data for 0-mileage and field listed in this document.
+ *
+ * Engineering Samples
+ *
+ * Engineering samples are marked with (e) or (E). Samples may vary from the
+ * valid technical specifications of the series product contained in this
+ * data sheet. Therefore, they are not intended or fit for resale to
+ * third parties or for use in end products. Their sole purpose is internal
+ * client testing. The testing of an engineering sample may in no way replace
+ * the testing of a series product. Bosch assumes no liability for the use
+ * of engineering samples. The purchaser shall indemnify Bosch from all claims
+ * arising from the use of engineering samples.
+ *
+ * Intended use
+ *
+ * Provided that SMI130 is used within the conditions (environment, application,
+ * installation, loads) as described in this TCD and the corresponding
+ * agreed upon documents, Bosch ensures that the product complies with
+ * the agreed properties. Agreements beyond this require
+ * the written approval by Bosch. The product is considered fit for the intended
+ * use when the product successfully has passed the tests
+ * in accordance with the TCD and agreed upon documents.
+ *
+ * It is the responsibility of the customer to ensure the proper application
+ * of the product in the overall system/vehicle.
+ *
+ * Bosch does not assume any responsibility for changes to the environment
+ * of the product that deviate from the TCD and the agreed upon documents
+ * as well as all applications not released by Bosch
+ *
+ * The resale and/or use of products are at the purchaser’s own risk and
+ * responsibility. The examination and testing of the SMI130
+ * is the sole responsibility of the purchaser.
+ *
+ * The purchaser shall indemnify Bosch from all third party claims
+ * arising from any product use not covered by the parameters of
+ * this product data sheet or not approved by Bosch and reimburse Bosch
+ * for all costs and damages in connection with such claims.
+ *
+ * The purchaser must monitor the market for the purchased products,
+ * particularly with regard to product safety, and inform Bosch without delay
+ * of all security relevant incidents.
+ *
+ * Application Examples and Hints
+ *
+ * With respect to any application examples, advice, normal values
+ * and/or any information regarding the application of the device,
+ * Bosch hereby disclaims any and all warranties and liabilities of any kind,
+ * including without limitation warranties of
+ * non-infringement of intellectual property rights or copyrights
+ * of any third party.
+ * The information given in this document shall in no event be regarded
+ * as a guarantee of conditions or characteristics. They are provided
+ * for illustrative purposes only and no evaluation regarding infringement
+ * of intellectual property rights or copyrights or regarding functionality,
+ * performance or error has been made.
+ *
+ * @filename smi130_spi.c
+ * @date 2014/11/25 14:40
+ * @Modification Date 2018/08/28 18:20
+ * @id "20f77db"
+ * @version 1.3
+ *
+ * @brief
+ * This file implements moudle function, which add
+ * the driver to SPI core.
+*/
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include "smi130_driver.h"
+
+/*! @defgroup smi130_spi_src
+ * @brief smi130 spi driver module
+ @{*/
+/*! the maximum of transfer buffer size */
+#define SMI_MAX_BUFFER_SIZE 32
+
+static struct spi_device *smi_spi_client;
+
+/*!
+ * @brief define spi wirte function
+ *
+ * @param dev_addr sensor device address
+ * @param reg_addr register address
+ * @param data the pointer of data buffer
+ * @param len block size need to write
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static char smi_spi_write_block(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ struct spi_device *client = smi_spi_client;
+ u8 buffer[SMI_MAX_BUFFER_SIZE + 1];
+ struct spi_transfer xfer = {
+ .tx_buf = buffer,
+ .len = len + 1,
+ };
+ struct spi_message msg;
+
+ if (len > SMI_MAX_BUFFER_SIZE)
+ return -EINVAL;
+
+ buffer[0] = reg_addr&0x7F;/* write: MSB = 0 */
+ memcpy(&buffer[1], data, len);
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+ return spi_sync(client, &msg);
+}
+
+/*!
+ * @brief define spi read function
+ *
+ * @param dev_addr sensor device address
+ * @param reg_addr register address
+ * @param data the pointer of data buffer
+ * @param len block size need to read
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static char smi_spi_read_block(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ struct spi_device *client = smi_spi_client;
+ u8 reg = reg_addr | 0x80;/* read: MSB = 1 */
+ struct spi_transfer xfer[2] = {
+ [0] = {
+ .tx_buf = &reg,
+ .len = 1,
+ },
+ [1] = {
+ .rx_buf = data,
+ .len = len,
+ }
+ };
+ struct spi_message msg;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer[0], &msg);
+ spi_message_add_tail(&xfer[1], &msg);
+ return spi_sync(client, &msg);
+}
+
+s8 smi_burst_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u16 len)
+{
+ struct spi_device *client = smi_spi_client;
+ u8 reg = reg_addr | 0x80;/* read: MSB = 1 */
+ struct spi_transfer xfer[2] = {
+ [0] = {
+ .tx_buf = &reg,
+ .len = 1,
+ },
+ [1] = {
+ .rx_buf = data,
+ .len = len,
+ }
+ };
+ struct spi_message msg;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer[0], &msg);
+ spi_message_add_tail(&xfer[1], &msg);
+ return spi_sync(client, &msg);
+}
+EXPORT_SYMBOL(smi_burst_read_wrapper);
+/*!
+ * @brief SMI probe function via spi bus
+ *
+ * @param client the pointer of spi client
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static int smi_spi_probe(struct spi_device *client)
+{
+ int status;
+ int err = 0;
+ struct smi_client_data *client_data = NULL;
+
+ if (NULL == smi_spi_client)
+ smi_spi_client = client;
+ else{
+ dev_err(&client->dev, "This driver does not support multiple clients!\n");
+ return -EBUSY;
+ }
+
+ client->bits_per_word = 8;
+ status = spi_setup(client);
+ if (status < 0) {
+ dev_err(&client->dev, "spi_setup failed!\n");
+ return status;
+ }
+
+ client_data = kzalloc(sizeof(struct smi_client_data), GFP_KERNEL);
+ if (NULL == client_data) {
+ dev_err(&client->dev, "no memory available");
+ err = -ENOMEM;
+ goto exit_err_clean;
+ }
+
+ client_data->device.bus_read = smi_spi_read_block;
+ client_data->device.bus_write = smi_spi_write_block;
+
+ return smi_probe(client_data, &client->dev);
+
+exit_err_clean:
+ if (err)
+ smi_spi_client = NULL;
+ return err;
+}
+
+/*!
+ * @brief shutdown smi device in spi driver
+ *
+ * @param client the pointer of spi client
+ *
+ * @return no return value
+*/
+static void smi_spi_shutdown(struct spi_device *client)
+{
+#ifdef CONFIG_PM
+ smi_suspend(&client->dev);
+#endif
+}
+
+/*!
+ * @brief remove smi spi client
+ *
+ * @param client the pointer of spi client
+ *
+ * @return zero
+ * @retval zero
+*/
+static int smi_spi_remove(struct spi_device *client)
+{
+ int err = 0;
+ err = smi_remove(&client->dev);
+ smi_spi_client = NULL;
+
+ return err;
+}
+
+#ifdef CONFIG_PM
+/*!
+ * @brief suspend smi device in spi driver
+ *
+ * @param dev the pointer of device
+ *
+ * @return zero
+ * @retval zero
+*/
+static int smi_spi_suspend(struct device *dev)
+{
+ int err = 0;
+ err = smi_suspend(dev);
+ return err;
+}
+
+/*!
+ * @brief resume smi device in spi driver
+ *
+ * @param dev the pointer of device
+ *
+ * @return zero
+ * @retval zero
+*/
+static int smi_spi_resume(struct device *dev)
+{
+ int err = 0;
+ /* post resume operation */
+ err = smi_resume(dev);
+
+ return err;
+}
+
+/*!
+ * @brief register spi device power manager hooks
+*/
+static const struct dev_pm_ops smi_spi_pm_ops = {
+ /**< device suspend */
+ .suspend = smi_spi_suspend,
+ /**< device resume */
+ .resume = smi_spi_resume
+};
+#endif
+
+/*!
+ * @brief register spi device id
+*/
+static const struct spi_device_id smi_id[] = {
+ { SENSOR_NAME, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, smi_id);
+
+/*!
+ * @brief register spi driver hooks
+*/
+static struct spi_driver smi_spi_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+#ifdef CONFIG_PM
+ .pm = &smi_spi_pm_ops,
+#endif
+ },
+ .id_table = smi_id,
+ .probe = smi_spi_probe,
+ .shutdown = smi_spi_shutdown,
+ .remove = smi_spi_remove
+};
+
+/*!
+ * @brief initialize smi spi module
+ *
+ * @return zero success, non-zero failed
+ * @retval zero success
+ * @retval non-zero failed
+*/
+static int __init smi_spi_init(void)
+{
+ return spi_register_driver(&smi_spi_driver);
+}
+
+/*!
+ * @brief remove smi spi module
+ *
+ * @return no return value
+*/
+static void __exit smi_spi_exit(void)
+{
+ spi_unregister_driver(&smi_spi_driver);
+}
+
+
+MODULE_AUTHOR("Contact <contact@bosch-sensortec.com>");
+MODULE_DESCRIPTION("SMI130 SPI DRIVER");
+MODULE_LICENSE("GPL v2");
+
+module_init(smi_spi_init);
+module_exit(smi_spi_exit);
+/*@}*/
+
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index ae33da7ab51f..2d564aabbc74 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -11,7 +11,9 @@ menuconfig INPUT_TOUCHSCREEN
if INPUT_TOUCHSCREEN
-config TOUCHSCREEN_PROPERTIES
+source "drivers/input/touchscreen/synaptics_dsx/Kconfig"
+
+config OF_TOUCHSCREEN
def_tristate INPUT
depends on INPUT
@@ -115,6 +117,18 @@ config TOUCHSCREEN_ATMEL_MXT
To compile this driver as a module, choose M here: the
module will be called atmel_mxt_ts.
+config TOUCHSCREEN_ATMEL_MAXTOUCH_TS
+ tristate "Atmel Maxtouch Touchscreen Family"
+ depends on I2C
+ help
+ Say Y here if you have Atmel MaXTouch Touchscreen
+ using i2c connected to your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called atmel_maxtouch_ts.
+
config TOUCHSCREEN_AUO_PIXCIR
tristate "AUO in-cell touchscreen using Pixcir ICs"
depends on I2C
@@ -1095,6 +1109,34 @@ config TOUCHSCREEN_COLIBRI_VF50
To compile this driver as a module, choose M here: the
module will be called colibri_vf50_ts.
+config TOUCHSCREEN_FT5X06_PSENSOR
+ tristate "FocalTech proximity feature support"
+ depends on TOUCHSCREEN_FT5X06 && SENSORS
+ help
+ Say Y here if you want to support ft5x06's proximity
+ feature.
+
+ If unsure, say N.
+
+config TOUCHSCREEN_FT5X06_GESTURE
+ tristate "FocalTech gesture feature support"
+ depends on TOUCHSCREEN_FT5X06
+ help
+ Say Y here if you want to support ft5x06's gesture
+ feature.
+
+ If unsure, say N.
+
+config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+ bool "Synaptics DSX firmware update extra sysfs attributes"
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE
+ help
+ Say Y here to enable support for extra sysfs attributes
+ supporting firmware update in a development environment.
+ This does not affect the core or other subsystem attributes.
+
+ If unsure, say N.
+
config TOUCHSCREEN_ROHM_BU21023
tristate "ROHM BU21023/24 Dual touch support resistive touchscreens"
depends on I2C
@@ -1106,4 +1148,81 @@ config TOUCHSCREEN_ROHM_BU21023
To compile this driver as a module, choose M here: the
module will be called bu21023_ts.
+config TOUCHSCREEN_MAXIM_STI
+ tristate "Maxim based STI touchscreens"
+ depends on SPI_MASTER
+ help
+ Say Y here if you have a touchscreen interface using the
+ Maxim STI based touch controller.
+
+ If unsure, say N
+
+ To compile this driver as a module, choose M here: the
+ module will be called maxim_sti.
+
+config SECURE_TOUCH
+ bool "Secure Touch"
+ depends on (TOUCHSCREEN_SYNAPTICS_I2C_RMI4 || \
+ TOUCHSCREEN_SYNAPTICS_DSX_I2C_v21)
+ help
+ Say Y here to enable Secure Touch in supported drivers.
+
+ If unsure, say N.
+
+config TOUCHSCREEN_GEN_VKEYS
+ tristate "Touchscreen Virtual Keys Driver"
+ help
+ Say Y here if you want to generate a sysfs entry for virtual
+ keys on Android.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gen_vkeys.
+
+config TOUCHSCREEN_FT5X06
+ tristate "FocalTech touchscreens"
+ depends on I2C
+ help
+ Say Y here if you have a ft5X06 touchscreen.
+ Ft5x06 controllers are multi touch controllers which can
+ report 5 touches at a time.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ft5x06_ts.
+
+config FT_SECURE_TOUCH
+ bool "Secure Touch support for Focaltech Touchscreen"
+ depends on TOUCHSCREEN_FT5X06
+ help
+ Say Y here
+ -Focaltech touch driver is connected
+ -To enable secure touch for Focaltech touch driver
+
+ If unsure, say N.
+
+config TOUCHSCREEN_IT7260_I2C
+ tristate "IT7260 Touchscreen Driver"
+ depends on I2C
+ help
+ Say Y here if you have a IT7260 Touchscreen Driver
+ connected to your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called it7258_ts_i2c.
+
+config TOUCHSCREEN_ST
+ bool "STMicroelectronics Touchscreen Driver"
+ depends on I2C
+ help
+ Say Y here if you have a STMicroelectronics Touchscreen.
+
+ If unsure, say N.
+
+source "drivers/input/touchscreen/st/Kconfig"
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index cbaa6abb08da..f5be6fc19751 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH_TS) += atmel_maxtouch_ts.o
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8318) += chipone_icn8318.o
@@ -36,15 +37,19 @@ obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_FT6236) += ft6236.o
+obj-$(CONFIG_TOUCHSCREEN_FT5X06) += ft5x06_ts.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
+obj-$(CONFIG_TOUCHSCREEN_GEN_VKEYS) += gen_vkeys.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
+obj-$(CONFIG_TOUCHSCREEN_IT7260_I2C) += it7258_ts_i2c.o
obj-$(CONFIG_TOUCHSCREEN_IPROC) += bcm_iproc_tsc.o
obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MAXIM_STI) += maxim_sti.o
obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
@@ -64,6 +69,7 @@ obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v21) += synaptics_dsx/
obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
@@ -91,3 +97,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
+obj-$(CONFIG_TOUCHSCREEN_ST) += st/
diff --git a/drivers/input/touchscreen/atmel_maxtouch_ts.c b/drivers/input/touchscreen/atmel_maxtouch_ts.c
new file mode 100644
index 000000000000..423a055bbec6
--- /dev/null
+++ b/drivers/input/touchscreen/atmel_maxtouch_ts.c
@@ -0,0 +1,4215 @@
+/*
+ * Atmel maXTouch Touchscreen driver
+ *
+ * Copyright (c) 2014-2015, 2018 The Linux Foundation. All rights reserved.
+ *
+ * Linux foundation chooses to take subject only to the GPLv2 license terms,
+ * and distributes only under these terms.
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Copyright (C) 2011-2012 Atmel Corporation
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/input/atmel_maxtouch_ts.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+/* Early-suspend level */
+#define MXT_SUSPEND_LEVEL 1
+#endif
+
+#if defined(CONFIG_SECURE_TOUCH)
+#include <linux/completion.h>
+#include <linux/pm_runtime.h>
+#include <linux/errno.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#endif
+
+/* Configuration file */
+#define MXT_CFG_MAGIC "OBP_RAW V1"
+
+/* Registers */
+#define MXT_OBJECT_START 0x07
+#define MXT_OBJECT_SIZE 6
+#define MXT_INFO_CHECKSUM_SIZE 3
+#define MXT_MAX_BLOCK_WRITE 256
+
+/* Object types */
+#define MXT_DEBUG_DIAGNOSTIC_T37 37
+#define MXT_GEN_MESSAGE_T5 5
+#define MXT_GEN_COMMAND_T6 6
+#define MXT_GEN_POWER_T7 7
+#define MXT_GEN_ACQUIRE_T8 8
+#define MXT_GEN_DATASOURCE_T53 53
+#define MXT_TOUCH_MULTI_T9 9
+#define MXT_TOUCH_KEYARRAY_T15 15
+#define MXT_TOUCH_PROXIMITY_T23 23
+#define MXT_TOUCH_PROXKEY_T52 52
+#define MXT_PROCI_GRIPFACE_T20 20
+#define MXT_PROCG_NOISE_T22 22
+#define MXT_PROCI_ONETOUCH_T24 24
+#define MXT_PROCI_TWOTOUCH_T27 27
+#define MXT_PROCI_GRIP_T40 40
+#define MXT_PROCI_PALM_T41 41
+#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
+#define MXT_PROCI_STYLUS_T47 47
+#define MXT_PROCG_NOISESUPPRESSION_T48 48
+#define MXT_SPT_COMMSCONFIG_T18 18
+#define MXT_SPT_GPIOPWM_T19 19
+#define MXT_SPT_SELFTEST_T25 25
+#define MXT_SPT_CTECONFIG_T28 28
+#define MXT_SPT_USERDATA_T38 38
+#define MXT_SPT_DIGITIZER_T43 43
+#define MXT_SPT_MESSAGECOUNT_T44 44
+#define MXT_SPT_CTECONFIG_T46 46
+#define MXT_PROCI_ACTIVE_STYLUS_T63 63
+#define MXT_TOUCH_MULTITOUCHSCREEN_T100 100
+
+/* MXT_GEN_MESSAGE_T5 object */
+#define MXT_RPTID_NOMSG 0xff
+
+/* MXT_GEN_COMMAND_T6 field */
+#define MXT_COMMAND_RESET 0
+#define MXT_COMMAND_BACKUPNV 1
+#define MXT_COMMAND_CALIBRATE 2
+#define MXT_COMMAND_REPORTALL 3
+#define MXT_COMMAND_DIAGNOSTIC 5
+
+/* Define for T6 status byte */
+#define MXT_T6_STATUS_RESET (1 << 7)
+#define MXT_T6_STATUS_OFL (1 << 6)
+#define MXT_T6_STATUS_SIGERR (1 << 5)
+#define MXT_T6_STATUS_CAL (1 << 4)
+#define MXT_T6_STATUS_CFGERR (1 << 3)
+#define MXT_T6_STATUS_COMSERR (1 << 2)
+
+/* MXT_GEN_POWER_T7 field */
+struct t7_config {
+ u8 idle;
+ u8 active;
+} __packed;
+
+#define MXT_POWER_CFG_RUN 0
+#define MXT_POWER_CFG_DEEPSLEEP 1
+
+/* MXT_TOUCH_MULTI_T9 field */
+#define MXT_T9_ORIENT 9
+#define MXT_T9_RANGE 18
+
+/* MXT_TOUCH_MULTI_T9 status */
+#define MXT_T9_UNGRIP (1 << 0)
+#define MXT_T9_SUPPRESS (1 << 1)
+#define MXT_T9_AMP (1 << 2)
+#define MXT_T9_VECTOR (1 << 3)
+#define MXT_T9_MOVE (1 << 4)
+#define MXT_T9_RELEASE (1 << 5)
+#define MXT_T9_PRESS (1 << 6)
+#define MXT_T9_DETECT (1 << 7)
+
+struct t9_range {
+ u16 x;
+ u16 y;
+} __packed;
+
+/* MXT_TOUCH_MULTI_T9 orient */
+#define MXT_T9_ORIENT_SWITCH (1 << 0)
+
+/* MXT_SPT_COMMSCONFIG_T18 */
+#define MXT_COMMS_CTRL 0
+#define MXT_COMMS_CMD 1
+#define MXT_COMMS_RETRIGEN (1 << 6)
+
+/* Define for MXT_GEN_COMMAND_T6 */
+#define MXT_BOOT_VALUE 0xa5
+#define MXT_RESET_VALUE 0x01
+#define MXT_BACKUP_VALUE 0x55
+
+/* Define for MXT_PROCI_TOUCHSUPPRESSION_T42 */
+#define MXT_T42_MSG_TCHSUP (1 << 0)
+
+/* T47 Stylus */
+#define MXT_TOUCH_MAJOR_T47_STYLUS 1
+
+/* T63 Stylus */
+#define MXT_T63_STYLUS_PRESS (1 << 0)
+#define MXT_T63_STYLUS_RELEASE (1 << 1)
+#define MXT_T63_STYLUS_MOVE (1 << 2)
+#define MXT_T63_STYLUS_SUPPRESS (1 << 3)
+
+#define MXT_T63_STYLUS_DETECT (1 << 4)
+#define MXT_T63_STYLUS_TIP (1 << 5)
+#define MXT_T63_STYLUS_ERASER (1 << 6)
+#define MXT_T63_STYLUS_BARREL (1 << 7)
+
+#define MXT_T63_STYLUS_PRESSURE_MASK 0x3F
+
+/* T100 Multiple Touch Touchscreen */
+#define MXT_T100_CTRL 0
+#define MXT_T100_CFG1 1
+#define MXT_T100_TCHAUX 3
+#define MXT_T100_XRANGE 13
+#define MXT_T100_YRANGE 24
+
+#define MXT_T100_CFG_SWITCHXY (1 << 5)
+
+#define MXT_T100_TCHAUX_VECT (1 << 0)
+#define MXT_T100_TCHAUX_AMPL (1 << 1)
+#define MXT_T100_TCHAUX_AREA (1 << 2)
+
+#define MXT_T100_DETECT (1 << 7)
+#define MXT_T100_TYPE_MASK 0x70
+#define MXT_T100_TYPE_STYLUS 0x20
+
+/* Delay times */
+#define MXT_BACKUP_TIME 50 /* msec */
+#define MXT_RESET_TIME 200 /* msec */
+#define MXT_RESET_TIMEOUT 3000 /* msec */
+#define MXT_CRC_TIMEOUT 1000 /* msec */
+#define MXT_FW_RESET_TIME 3000 /* msec */
+#define MXT_FW_CHG_TIMEOUT 300 /* msec */
+#define MXT_WAKEUP_TIME 25 /* msec */
+#define MXT_REGULATOR_DELAY 150 /* msec */
+#define MXT_POWERON_DELAY 150 /* msec */
+
+/* Command to unlock bootloader */
+#define MXT_UNLOCK_CMD_MSB 0xaa
+#define MXT_UNLOCK_CMD_LSB 0xdc
+
+/* Bootloader mode status */
+#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
+#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
+#define MXT_FRAME_CRC_CHECK 0x02
+#define MXT_FRAME_CRC_FAIL 0x03
+#define MXT_FRAME_CRC_PASS 0x04
+#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
+#define MXT_BOOT_STATUS_MASK 0x3f
+#define MXT_BOOT_EXTENDED_ID (1 << 5)
+#define MXT_BOOT_ID_MASK 0x1f
+
+/* Touchscreen absolute values */
+#define MXT_MAX_AREA 0xff
+
+#define MXT_PIXELS_PER_MM 20
+
+#define DEBUG_MSG_MAX 200
+
+#define MXT_COORDS_ARR_SIZE 4
+
+/* Orient */
+#define MXT_NORMAL 0x0
+#define MXT_DIAGONAL 0x1
+#define MXT_HORIZONTAL_FLIP 0x2
+#define MXT_ROTATED_90_COUNTER 0x3
+#define MXT_VERTICAL_FLIP 0x4
+#define MXT_ROTATED_90 0x5
+#define MXT_ROTATED_180 0x6
+#define MXT_DIAGONAL_COUNTER 0x7
+
+/* MXT_TOUCH_KEYARRAY_T15 */
+#define MXT_KEYARRAY_MAX_KEYS 32
+
+/* Bootoader IDs */
+#define MXT_BOOTLOADER_ID_224 0x0A
+#define MXT_BOOTLOADER_ID_224E 0x06
+#define MXT_BOOTLOADER_ID_336S 0x1A
+#define MXT_BOOTLOADER_ID_1386 0x01
+#define MXT_BOOTLOADER_ID_1386E 0x10
+#define MXT_BOOTLOADER_ID_1664S 0x14
+
+/* recommended voltage specifications */
+#define MXT_VDD_VTG_MIN_UV 1800000
+#define MXT_VDD_VTG_MAX_UV 1800000
+#define MXT_AVDD_VTG_MIN_UV 2700000
+#define MXT_AVDD_VTG_MAX_UV 3300000
+#define MXT_XVDD_VTG_MIN_UV 2700000
+#define MXT_XVDD_VTG_MAX_UV 10000000
+
+#define MXT_GEN_CFG "maxtouch_generic_cfg.raw"
+#define MXT_NAME_MAX_LEN 100
+
+struct mxt_info {
+ u8 family_id;
+ u8 variant_id;
+ u8 version;
+ u8 build;
+ u8 matrix_xsize;
+ u8 matrix_ysize;
+ u8 object_num;
+};
+
+struct mxt_object {
+ u8 type;
+ u16 start_address;
+ u8 size_minus_one;
+ u8 instances_minus_one;
+ u8 num_report_ids;
+} __packed;
+
+/* Each client has this additional data */
+struct mxt_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct pinctrl *ts_pinctrl;
+ struct pinctrl_state *gpio_state_active;
+ struct pinctrl_state *gpio_state_suspend;
+ char phys[64]; /* device physical location */
+ struct mxt_platform_data *pdata;
+ struct mxt_object *object_table;
+ struct mxt_info *info;
+ void *raw_info_block;
+ unsigned int irq;
+ unsigned int max_x;
+ unsigned int max_y;
+ bool in_bootloader;
+ u16 mem_size;
+ u8 t100_aux_ampl;
+ u8 t100_aux_area;
+ u8 t100_aux_vect;
+ struct bin_attribute mem_access_attr;
+ bool debug_enabled;
+ bool debug_v2_enabled;
+ u8 *debug_msg_data;
+ u16 debug_msg_count;
+ struct bin_attribute debug_msg_attr;
+ struct mutex debug_msg_lock;
+ u8 max_reportid;
+ u32 config_crc;
+ u32 info_crc;
+ u8 bootloader_addr;
+ struct t7_config t7_cfg;
+ u8 *msg_buf;
+ u8 t6_status;
+ bool update_input;
+ u8 last_message_count;
+ u8 num_touchids;
+ u8 num_stylusids;
+ unsigned long t15_keystatus;
+ bool use_retrigen_workaround;
+ bool use_regulator;
+ struct regulator *reg_vdd;
+ struct regulator *reg_avdd;
+ struct regulator *reg_xvdd;
+ char fw_name[MXT_NAME_MAX_LEN];
+ char cfg_name[MXT_NAME_MAX_LEN];
+ u8 cfg_version[3];
+ bool fw_w_no_cfg_update;
+
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+ /* Cached parameters from object table */
+ u16 T5_address;
+ u8 T5_msg_size;
+ u8 T6_reportid;
+ u16 T6_address;
+ u16 T7_address;
+ u8 T9_reportid_min;
+ u8 T9_reportid_max;
+ u8 T15_reportid_min;
+ u8 T15_reportid_max;
+ u16 T18_address;
+ u8 T19_reportid;
+ u8 T42_reportid_min;
+ u8 T42_reportid_max;
+ u16 T44_address;
+ u8 T48_reportid;
+ u8 T63_reportid_min;
+ u8 T63_reportid_max;
+ u8 T100_reportid_min;
+ u8 T100_reportid_max;
+
+ /* for fw update in bootloader */
+ struct completion bl_completion;
+
+ /* for reset handling */
+ struct completion reset_completion;
+
+ /* for reset handling */
+ struct completion crc_completion;
+
+ /* Enable reporting of input events */
+ bool enable_reporting;
+
+ /* Indicates whether device is in suspend */
+ bool suspended;
+
+#if defined(CONFIG_SECURE_TOUCH)
+ atomic_t st_enabled;
+ atomic_t st_pending_irqs;
+ bool st_initialized;
+ struct completion st_powerdown;
+ struct clk *core_clk;
+ struct clk *iface_clk;
+#endif
+};
+
+static inline unsigned int mxt_obj_size(const struct mxt_object *obj)
+{
+ return obj->size_minus_one + 1;
+}
+
+static inline unsigned int mxt_obj_instances(const struct mxt_object *obj)
+{
+ return obj->instances_minus_one + 1;
+}
+
+static bool mxt_object_readable(unsigned int type)
+{
+ switch (type) {
+ case MXT_GEN_COMMAND_T6:
+ case MXT_GEN_POWER_T7:
+ case MXT_GEN_ACQUIRE_T8:
+ case MXT_GEN_DATASOURCE_T53:
+ case MXT_TOUCH_MULTI_T9:
+ case MXT_TOUCH_KEYARRAY_T15:
+ case MXT_TOUCH_PROXIMITY_T23:
+ case MXT_TOUCH_PROXKEY_T52:
+ case MXT_PROCI_GRIPFACE_T20:
+ case MXT_PROCG_NOISE_T22:
+ case MXT_PROCI_ONETOUCH_T24:
+ case MXT_PROCI_TWOTOUCH_T27:
+ case MXT_PROCI_GRIP_T40:
+ case MXT_PROCI_PALM_T41:
+ case MXT_PROCI_TOUCHSUPPRESSION_T42:
+ case MXT_PROCI_STYLUS_T47:
+ case MXT_PROCG_NOISESUPPRESSION_T48:
+ case MXT_SPT_COMMSCONFIG_T18:
+ case MXT_SPT_GPIOPWM_T19:
+ case MXT_SPT_SELFTEST_T25:
+ case MXT_SPT_CTECONFIG_T28:
+ case MXT_SPT_USERDATA_T38:
+ case MXT_SPT_DIGITIZER_T43:
+ case MXT_SPT_CTECONFIG_T46:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void mxt_dump_message(struct mxt_data *data, u8 *message)
+{
+ print_hex_dump(KERN_DEBUG, "MXT MSG:", DUMP_PREFIX_NONE, 16, 1,
+ message, data->T5_msg_size, false);
+}
+
+static void mxt_debug_msg_enable(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+
+ if (data->debug_v2_enabled)
+ return;
+
+ mutex_lock(&data->debug_msg_lock);
+
+ data->debug_msg_data = kcalloc(DEBUG_MSG_MAX,
+ data->T5_msg_size, GFP_KERNEL);
+ if (!data->debug_msg_data) {
+ dev_err(&data->client->dev, "Failed to allocate buffer\n");
+ return;
+ }
+
+ data->debug_v2_enabled = true;
+ mutex_unlock(&data->debug_msg_lock);
+
+ dev_info(dev, "Enabled message output\n");
+}
+
+static void mxt_debug_msg_disable(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+
+ if (!data->debug_v2_enabled)
+ return;
+
+ dev_info(dev, "disabling message output\n");
+ data->debug_v2_enabled = false;
+
+ mutex_lock(&data->debug_msg_lock);
+ kfree(data->debug_msg_data);
+ data->debug_msg_data = NULL;
+ data->debug_msg_count = 0;
+ mutex_unlock(&data->debug_msg_lock);
+ dev_info(dev, "Disabled message output\n");
+}
+
+static void mxt_debug_msg_add(struct mxt_data *data, u8 *msg)
+{
+ struct device *dev = &data->client->dev;
+
+ mutex_lock(&data->debug_msg_lock);
+
+ if (!data->debug_msg_data) {
+ dev_err(dev, "No buffer!\n");
+ return;
+ }
+
+ if (data->debug_msg_count < DEBUG_MSG_MAX) {
+ memcpy(data->debug_msg_data + data->debug_msg_count * data->T5_msg_size,
+ msg,
+ data->T5_msg_size);
+ data->debug_msg_count++;
+ } else {
+ dev_dbg(dev, "Discarding %u messages\n", data->debug_msg_count);
+ data->debug_msg_count = 0;
+ }
+
+ mutex_unlock(&data->debug_msg_lock);
+
+ sysfs_notify(&data->client->dev.kobj, NULL, "debug_notify");
+}
+
+static ssize_t mxt_debug_msg_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off,
+ size_t count)
+{
+ return -EIO;
+}
+
+static ssize_t mxt_debug_msg_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t bytes)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int count;
+ size_t bytes_read;
+
+ if (!data->debug_msg_data) {
+ dev_err(dev, "No buffer!\n");
+ return 0;
+ }
+
+ count = bytes / data->T5_msg_size;
+
+ if (count > DEBUG_MSG_MAX)
+ count = DEBUG_MSG_MAX;
+
+ mutex_lock(&data->debug_msg_lock);
+
+ if (count > data->debug_msg_count)
+ count = data->debug_msg_count;
+
+ bytes_read = count * data->T5_msg_size;
+
+ memcpy(buf, data->debug_msg_data, bytes_read);
+ data->debug_msg_count = 0;
+
+ mutex_unlock(&data->debug_msg_lock);
+
+ return bytes_read;
+}
+
+static int mxt_debug_msg_init(struct mxt_data *data)
+{
+ int ret;
+
+ sysfs_bin_attr_init(&data->debug_msg_attr);
+ data->debug_msg_attr.attr.name = "debug_msg";
+ data->debug_msg_attr.attr.mode = 0666;
+ data->debug_msg_attr.read = mxt_debug_msg_read;
+ data->debug_msg_attr.write = mxt_debug_msg_write;
+ data->debug_msg_attr.size = data->T5_msg_size * DEBUG_MSG_MAX;
+
+ ret = sysfs_create_bin_file(&data->client->dev.kobj,
+ &data->debug_msg_attr);
+ if (ret < 0) {
+ if (ret == -EEXIST) {
+ dev_info(&data->client->dev,
+ "Debugfs already exists\n");
+ ret = 0;
+ } else {
+ dev_err(&data->client->dev,
+ "Failed to create 'debug_msg' file\n");
+ }
+ }
+
+ return ret;
+}
+
+static void mxt_debug_msg_remove(struct mxt_data *data)
+{
+ if (data->debug_msg_attr.attr.name)
+ sysfs_remove_bin_file(&data->client->dev.kobj,
+ &data->debug_msg_attr);
+}
+
+static int mxt_wait_for_completion(struct mxt_data *data,
+ struct completion *comp, unsigned int timeout_ms)
+{
+ struct device *dev = &data->client->dev;
+ unsigned long timeout = msecs_to_jiffies(timeout_ms);
+ long ret;
+
+ ret = wait_for_completion_interruptible_timeout(comp, timeout);
+ if (ret < 0) {
+ dev_err(dev, "Wait for completion interrupted.\n");
+ return -EINTR;
+ } else if (ret == 0) {
+ dev_err(dev, "Wait for completion timed out.\n");
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int mxt_bootloader_read(struct mxt_data *data,
+ u8 *val, unsigned int count)
+{
+ int ret;
+ struct i2c_msg msg;
+
+ msg.addr = data->bootloader_addr;
+ msg.flags = data->client->flags & I2C_M_TEN;
+ msg.flags |= I2C_M_RD;
+ msg.len = count;
+ msg.buf = val;
+
+ ret = i2c_transfer(data->client->adapter, &msg, 1);
+
+ if (ret == 1) {
+ ret = 0;
+ } else {
+ ret = (ret < 0) ? ret : -EIO;
+ dev_err(&data->client->dev, "%s: i2c recv failed (%d)\n",
+ __func__, ret);
+ }
+
+ return ret;
+}
+
+static int mxt_bootloader_write(struct mxt_data *data,
+ const u8 * const val, unsigned int count)
+{
+ int ret;
+ struct i2c_msg msg;
+
+ msg.addr = data->bootloader_addr;
+ msg.flags = data->client->flags & I2C_M_TEN;
+ msg.len = count;
+ msg.buf = (u8 *)val;
+
+ ret = i2c_transfer(data->client->adapter, &msg, 1);
+ if (ret == 1) {
+ ret = 0;
+ } else {
+ ret = (ret < 0) ? ret : -EIO;
+ dev_err(&data->client->dev, "%s: i2c send failed (%d)\n",
+ __func__, ret);
+ }
+
+ return ret;
+}
+
+static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
+{
+ u8 appmode = data->client->addr;
+ u8 bootloader;
+ u8 family_id = 0;
+
+ if (data->pdata->bl_addr) {
+ data->bootloader_addr = data->pdata->bl_addr;
+ return 0;
+ }
+
+ if (data->info)
+ family_id = data->info->family_id;
+
+ switch (appmode) {
+ case 0x4a:
+ case 0x4b:
+ /* Chips after 1664S use different scheme */
+ if (retry || family_id >= 0xa2) {
+ bootloader = appmode - 0x24;
+ break;
+ }
+ /* Fall through for normal case */
+ case 0x4c:
+ case 0x4d:
+ case 0x5a:
+ case 0x5b:
+ bootloader = appmode - 0x26;
+ break;
+ default:
+ dev_err(&data->client->dev,
+ "Appmode i2c address 0x%02x not found\n",
+ appmode);
+ return -EINVAL;
+ }
+
+ data->bootloader_addr = bootloader;
+ return 0;
+}
+
+static int mxt_probe_bootloader(struct mxt_data *data, bool retry)
+{
+ struct device *dev = &data->client->dev;
+ int ret;
+ u8 val;
+ bool crc_failure;
+
+ ret = mxt_lookup_bootloader_address(data, retry);
+ if (ret)
+ return ret;
+
+ ret = mxt_bootloader_read(data, &val, 1);
+ if (ret)
+ return ret;
+
+ /* Check app crc fail mode */
+ crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL;
+
+ dev_err(dev, "Detected bootloader, status:%02X%s\n",
+ val, crc_failure ? ", APP_CRC_FAIL" : "");
+
+ return 0;
+}
+
+static u8 mxt_get_bootloader_version(struct mxt_data *data, u8 val)
+{
+ struct device *dev = &data->client->dev;
+ u8 buf[3];
+
+ if (val & MXT_BOOT_EXTENDED_ID) {
+ if (mxt_bootloader_read(data, &buf[0], 3) != 0) {
+ dev_err(dev, "%s: i2c failure\n", __func__);
+ return -EIO;
+ }
+
+ dev_info(dev, "Bootloader ID:%d Version:%d\n", buf[1], buf[2]);
+
+ return buf[0];
+ } else {
+ dev_info(dev, "Bootloader ID:%d\n", val & MXT_BOOT_ID_MASK);
+
+ return val;
+ }
+}
+
+static int mxt_check_bootloader(struct mxt_data *data, unsigned int state,
+ bool wait)
+{
+ struct device *dev = &data->client->dev;
+ u8 val;
+ int ret;
+
+recheck:
+ if (wait) {
+ /*
+ * In application update mode, the interrupt
+ * line signals state transitions. We must wait for the
+ * CHG assertion before reading the status byte.
+ * Once the status byte has been read, the line is deasserted.
+ */
+ ret = mxt_wait_for_completion(data, &data->bl_completion,
+ MXT_FW_CHG_TIMEOUT);
+ if (ret) {
+ /*
+ * TODO: handle -EINTR better by terminating fw update
+ * process before returning to userspace by writing
+ * length 0x000 to device (iff we are in
+ * WAITING_FRAME_DATA state).
+ */
+ dev_err(dev, "Update wait error %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = mxt_bootloader_read(data, &val, 1);
+ if (ret)
+ return ret;
+
+ if (state == MXT_WAITING_BOOTLOAD_CMD)
+ val = mxt_get_bootloader_version(data, val);
+
+ switch (state) {
+ case MXT_WAITING_BOOTLOAD_CMD:
+ case MXT_WAITING_FRAME_DATA:
+ case MXT_APP_CRC_FAIL:
+ val &= ~MXT_BOOT_STATUS_MASK;
+ break;
+ case MXT_FRAME_CRC_PASS:
+ if (val == MXT_FRAME_CRC_CHECK) {
+ goto recheck;
+ } else if (val == MXT_FRAME_CRC_FAIL) {
+ dev_err(dev, "Bootloader CRC fail\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (val != state) {
+ dev_err(dev, "Invalid bootloader state %02X != %02X\n",
+ val, state);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
+{
+ int ret;
+ u8 buf[2];
+
+ if (unlock) {
+ buf[0] = MXT_UNLOCK_CMD_LSB;
+ buf[1] = MXT_UNLOCK_CMD_MSB;
+ } else {
+ buf[0] = 0x01;
+ buf[1] = 0x01;
+ }
+
+ ret = mxt_bootloader_write(data, buf, 2);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int __mxt_read_reg(struct i2c_client *client,
+ u16 reg, u16 len, void *val)
+{
+ struct i2c_msg xfer[2];
+ u8 buf[2];
+ int ret;
+ bool retry = false;
+
+ buf[0] = reg & 0xff;
+ buf[1] = (reg >> 8) & 0xff;
+
+ /* Write register */
+ xfer[0].addr = client->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = 2;
+ xfer[0].buf = buf;
+
+ /* Read data */
+ xfer[1].addr = client->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = len;
+ xfer[1].buf = val;
+
+retry_read:
+ ret = i2c_transfer(client->adapter, xfer, ARRAY_SIZE(xfer));
+ if (ret != ARRAY_SIZE(xfer)) {
+ if (!retry) {
+ dev_dbg(&client->dev, "%s: i2c retry\n", __func__);
+ msleep(MXT_WAKEUP_TIME);
+ retry = true;
+ goto retry_read;
+ } else {
+ dev_err(&client->dev, "%s: i2c transfer failed (%d)\n",
+ __func__, ret);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
+ const void *val)
+{
+ u8 *buf;
+ int count;
+ int ret;
+ bool retry = false;
+
+ count = len + 2;
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf[0] = reg & 0xff;
+ buf[1] = (reg >> 8) & 0xff;
+ memcpy(&buf[2], val, len);
+
+retry_write:
+ ret = i2c_master_send(client, buf, count);
+ if (ret != count) {
+ if (!retry) {
+ dev_dbg(&client->dev, "%s: i2c retry\n", __func__);
+ msleep(MXT_WAKEUP_TIME);
+ retry = true;
+ goto retry_write;
+ } else {
+ dev_err(&client->dev, "%s: i2c send failed (%d)\n",
+ __func__, ret);
+ ret = -EIO;
+ }
+ } else {
+ ret = 0;
+ }
+
+ kfree(buf);
+ return ret;
+}
+
+static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
+{
+ return __mxt_write_reg(client, reg, 1, &val);
+}
+
+static struct mxt_object *
+mxt_get_object(struct mxt_data *data, u8 type)
+{
+ struct mxt_object *object;
+ int i;
+
+ for (i = 0; i < data->info->object_num; i++) {
+ object = data->object_table + i;
+ if (object->type == type)
+ return object;
+ }
+
+ dev_warn(&data->client->dev, "Invalid object type T%u\n", type);
+ return NULL;
+}
+
+static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg)
+{
+ struct device *dev = &data->client->dev;
+ u8 status = msg[1];
+ u32 crc = msg[2] | (msg[3] << 8) | (msg[4] << 16);
+
+ if (crc != data->config_crc) {
+ data->config_crc = crc;
+ dev_dbg(dev, "T6 Config Checksum: 0x%06X\n", crc);
+ complete(&data->crc_completion);
+ }
+
+ /* Detect transition out of reset */
+ if ((data->t6_status & MXT_T6_STATUS_RESET) &&
+ !(status & MXT_T6_STATUS_RESET))
+ complete(&data->reset_completion);
+
+ /* Output debug if status has changed */
+ if (status != data->t6_status)
+ dev_dbg(dev, "T6 Status 0x%02X%s%s%s%s%s%s%s\n",
+ status,
+ (status == 0) ? " OK" : "",
+ (status & MXT_T6_STATUS_RESET) ? " RESET" : "",
+ (status & MXT_T6_STATUS_OFL) ? " OFL" : "",
+ (status & MXT_T6_STATUS_SIGERR) ? " SIGERR" : "",
+ (status & MXT_T6_STATUS_CAL) ? " CAL" : "",
+ (status & MXT_T6_STATUS_CFGERR) ? " CFGERR" : "",
+ (status & MXT_T6_STATUS_COMSERR) ? " COMSERR" : "");
+
+ /* Save current status */
+ data->t6_status = status;
+}
+
+static void mxt_input_button(struct mxt_data *data, u8 *message)
+{
+ struct input_dev *input = data->input_dev;
+ const struct mxt_platform_data *pdata = data->pdata;
+ bool button;
+ int i;
+
+ /* do not report events if input device not yet registered */
+ if (!data->enable_reporting)
+ return;
+
+ /* Active-low switch */
+ for (i = 0; i < pdata->t19_num_keys; i++) {
+ if (pdata->t19_keymap[i] == KEY_RESERVED)
+ continue;
+ button = !(message[1] & (1 << i));
+ input_report_key(input, pdata->t19_keymap[i], button);
+ }
+}
+
+static void mxt_input_sync(struct input_dev *input_dev)
+{
+ input_mt_report_pointer_emulation(input_dev, false);
+ input_sync(input_dev);
+}
+
+static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
+{
+ struct device *dev = &data->client->dev;
+ struct input_dev *input_dev = data->input_dev;
+ int id;
+ u8 status;
+ int x;
+ int y;
+ int area;
+ int amplitude;
+ u8 vector;
+ int tool;
+
+ /* do not report events if input device not yet registered */
+ if (!data->enable_reporting)
+ return;
+
+ id = message[0] - data->T9_reportid_min;
+ status = message[1];
+ x = (message[2] << 4) | ((message[4] >> 4) & 0xf);
+ y = (message[3] << 4) | ((message[4] & 0xf));
+
+ /* Handle 10/12 bit switching */
+ if (data->max_x < 1024)
+ x >>= 2;
+ if (data->max_y < 1024)
+ y >>= 2;
+
+ area = message[5];
+
+ amplitude = message[6];
+ vector = message[7];
+
+ dev_dbg(dev,
+ "[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u vector: %02X\n",
+ id,
+ (status & MXT_T9_DETECT) ? 'D' : '.',
+ (status & MXT_T9_PRESS) ? 'P' : '.',
+ (status & MXT_T9_RELEASE) ? 'R' : '.',
+ (status & MXT_T9_MOVE) ? 'M' : '.',
+ (status & MXT_T9_VECTOR) ? 'V' : '.',
+ (status & MXT_T9_AMP) ? 'A' : '.',
+ (status & MXT_T9_SUPPRESS) ? 'S' : '.',
+ (status & MXT_T9_UNGRIP) ? 'U' : '.',
+ x, y, area, amplitude, vector);
+
+ input_mt_slot(input_dev, id);
+
+ if (status & MXT_T9_DETECT) {
+ /* Multiple bits may be set if the host is slow to read the
+ * status messages, indicating all the events that have
+ * happened */
+ if (status & MXT_T9_RELEASE) {
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, 0);
+ mxt_input_sync(input_dev);
+ }
+
+ /* A reported size of zero indicates that the reported touch
+ * is a stylus from a linked Stylus T47 object. */
+ if (area == 0) {
+ area = MXT_TOUCH_MAJOR_T47_STYLUS;
+ tool = MT_TOOL_PEN;
+ } else {
+ tool = MT_TOOL_FINGER;
+ }
+
+ /* Touch active */
+ input_mt_report_slot_state(input_dev, tool, 1);
+ input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(input_dev, ABS_MT_PRESSURE, amplitude);
+ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area);
+ input_report_abs(input_dev, ABS_MT_ORIENTATION, vector);
+ } else {
+ /* Touch no longer active, close out slot */
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
+ }
+
+ data->update_input = true;
+}
+
+static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)
+{
+ struct device *dev = &data->client->dev;
+ struct input_dev *input_dev = data->input_dev;
+ int id;
+ u8 status;
+ int x;
+ int y;
+ int tool;
+
+ /* do not report events if input device not yet registered */
+ if (!data->enable_reporting)
+ return;
+
+ id = message[0] - data->T100_reportid_min - 2;
+
+ /* ignore SCRSTATUS events */
+ if (id < 0)
+ return;
+
+ status = message[1];
+ x = (message[3] << 8) | message[2];
+ y = (message[5] << 8) | message[4];
+
+ dev_dbg(dev,
+ "[%u] status:%02X x:%u y:%u area:%02X amp:%02X vec:%02X\n",
+ id,
+ status,
+ x, y,
+ (data->t100_aux_area) ? message[data->t100_aux_area] : 0,
+ (data->t100_aux_ampl) ? message[data->t100_aux_ampl] : 0,
+ (data->t100_aux_vect) ? message[data->t100_aux_vect] : 0);
+
+ input_mt_slot(input_dev, id);
+
+ if (status & MXT_T100_DETECT) {
+ /* A reported size of zero indicates that the reported touch
+ * is a stylus from a linked Stylus T47 object. */
+ if ((status & MXT_T100_TYPE_MASK) == MXT_T100_TYPE_STYLUS)
+ tool = MT_TOOL_PEN;
+ else
+ tool = MT_TOOL_FINGER;
+
+ /* Touch active */
+ input_mt_report_slot_state(input_dev, tool, 1);
+ input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+
+ if (data->t100_aux_ampl)
+ input_report_abs(input_dev, ABS_MT_PRESSURE,
+ message[data->t100_aux_ampl]);
+ else
+ input_report_abs(input_dev, ABS_MT_PRESSURE, 255);
+
+ if (data->t100_aux_area) {
+ if (tool == MT_TOOL_PEN)
+ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+ MXT_TOUCH_MAJOR_T47_STYLUS);
+ else
+ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+ message[data->t100_aux_area]);
+ }
+
+ if (data->t100_aux_vect)
+ input_report_abs(input_dev, ABS_MT_ORIENTATION,
+ message[data->t100_aux_vect]);
+ } else {
+ /* Touch no longer active, close out slot */
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
+ }
+
+ data->update_input = true;
+}
+
+
+static void mxt_proc_t15_messages(struct mxt_data *data, u8 *msg)
+{
+ struct input_dev *input_dev = data->input_dev;
+ struct device *dev = &data->client->dev;
+ int key;
+ bool curr_state, new_state;
+ bool sync = false;
+ unsigned long keystates = le32_to_cpu(msg[2]);
+
+ /* do not report events if input device not yet registered */
+ if (!data->enable_reporting)
+ return;
+
+ for (key = 0; key < data->pdata->t15_num_keys; key++) {
+ curr_state = test_bit(key, &data->t15_keystatus);
+ new_state = test_bit(key, &keystates);
+
+ if (!curr_state && new_state) {
+ dev_dbg(dev, "T15 key press: %u\n", key);
+ __set_bit(key, &data->t15_keystatus);
+ input_event(input_dev, EV_KEY,
+ data->pdata->t15_keymap[key], 1);
+ sync = true;
+ } else if (curr_state && !new_state) {
+ dev_dbg(dev, "T15 key release: %u\n", key);
+ __clear_bit(key, &data->t15_keystatus);
+ input_event(input_dev, EV_KEY,
+ data->pdata->t15_keymap[key], 0);
+ sync = true;
+ }
+ }
+
+ if (sync)
+ input_sync(input_dev);
+}
+
+static void mxt_proc_t42_messages(struct mxt_data *data, u8 *msg)
+{
+ struct device *dev = &data->client->dev;
+ u8 status = msg[1];
+
+ if (status & MXT_T42_MSG_TCHSUP)
+ dev_info(dev, "T42 suppress\n");
+ else
+ dev_info(dev, "T42 normal\n");
+}
+
+static int mxt_proc_t48_messages(struct mxt_data *data, u8 *msg)
+{
+ struct device *dev = &data->client->dev;
+ u8 status, state;
+
+ status = msg[1];
+ state = msg[4];
+
+ dev_dbg(dev, "T48 state %d status %02X %s%s%s%s%s\n",
+ state,
+ status,
+ (status & 0x01) ? "FREQCHG " : "",
+ (status & 0x02) ? "APXCHG " : "",
+ (status & 0x04) ? "ALGOERR " : "",
+ (status & 0x10) ? "STATCHG " : "",
+ (status & 0x20) ? "NLVLCHG " : "");
+
+ return 0;
+}
+
+static void mxt_proc_t63_messages(struct mxt_data *data, u8 *msg)
+{
+ struct device *dev = &data->client->dev;
+ struct input_dev *input_dev = data->input_dev;
+ u8 id;
+ u16 x, y;
+ u8 pressure;
+
+ /* do not report events if input device not yet registered */
+ if (!data->enable_reporting)
+ return;
+
+ /* stylus slots come after touch slots */
+ id = data->num_touchids + (msg[0] - data->T63_reportid_min);
+
+ if (id < 0 || id > (data->num_touchids + data->num_stylusids)) {
+ dev_err(dev, "invalid stylus id %d, max slot is %d\n",
+ id, data->num_stylusids);
+ return;
+ }
+
+ x = msg[3] | (msg[4] << 8);
+ y = msg[5] | (msg[6] << 8);
+ pressure = msg[7] & MXT_T63_STYLUS_PRESSURE_MASK;
+
+ dev_dbg(dev,
+ "[%d] %c%c%c%c x: %d y: %d pressure: %d stylus:%c%c%c%c\n",
+ id,
+ (msg[1] & MXT_T63_STYLUS_SUPPRESS) ? 'S' : '.',
+ (msg[1] & MXT_T63_STYLUS_MOVE) ? 'M' : '.',
+ (msg[1] & MXT_T63_STYLUS_RELEASE) ? 'R' : '.',
+ (msg[1] & MXT_T63_STYLUS_PRESS) ? 'P' : '.',
+ x, y, pressure,
+ (msg[2] & MXT_T63_STYLUS_BARREL) ? 'B' : '.',
+ (msg[2] & MXT_T63_STYLUS_ERASER) ? 'E' : '.',
+ (msg[2] & MXT_T63_STYLUS_TIP) ? 'T' : '.',
+ (msg[2] & MXT_T63_STYLUS_DETECT) ? 'D' : '.');
+
+ input_mt_slot(input_dev, id);
+
+ if (msg[2] & MXT_T63_STYLUS_DETECT) {
+ input_mt_report_slot_state(input_dev, MT_TOOL_PEN, 1);
+ input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(input_dev, ABS_MT_PRESSURE, pressure);
+ } else {
+ input_mt_report_slot_state(input_dev, MT_TOOL_PEN, 0);
+ }
+
+ input_report_key(input_dev, BTN_STYLUS,
+ (msg[2] & MXT_T63_STYLUS_ERASER));
+ input_report_key(input_dev, BTN_STYLUS2,
+ (msg[2] & MXT_T63_STYLUS_BARREL));
+
+ mxt_input_sync(input_dev);
+}
+
+static int mxt_proc_message(struct mxt_data *data, u8 *message)
+{
+ u8 report_id = message[0];
+ bool dump = data->debug_enabled;
+
+ if (report_id == MXT_RPTID_NOMSG)
+ return 0;
+
+ if (report_id == data->T6_reportid) {
+ mxt_proc_t6_messages(data, message);
+ } else if (report_id >= data->T9_reportid_min
+ && report_id <= data->T9_reportid_max) {
+ mxt_proc_t9_message(data, message);
+ } else if (report_id >= data->T100_reportid_min
+ && report_id <= data->T100_reportid_max) {
+ mxt_proc_t100_message(data, message);
+ } else if (report_id == data->T19_reportid) {
+ mxt_input_button(data, message);
+ data->update_input = true;
+ } else if (report_id >= data->T63_reportid_min
+ && report_id <= data->T63_reportid_max) {
+ mxt_proc_t63_messages(data, message);
+ } else if (report_id >= data->T42_reportid_min
+ && report_id <= data->T42_reportid_max) {
+ mxt_proc_t42_messages(data, message);
+ } else if (report_id == data->T48_reportid) {
+ mxt_proc_t48_messages(data, message);
+ } else if (report_id >= data->T15_reportid_min
+ && report_id <= data->T15_reportid_max) {
+ mxt_proc_t15_messages(data, message);
+ } else {
+ dump = true;
+ }
+
+ if (dump)
+ mxt_dump_message(data, message);
+
+ if (data->debug_v2_enabled)
+ mxt_debug_msg_add(data, message);
+
+ return 1;
+}
+
+static int mxt_read_and_process_messages(struct mxt_data *data, u8 count)
+{
+ struct device *dev = &data->client->dev;
+ int ret;
+ int i;
+ u8 num_valid = 0;
+
+ /* Safety check for msg_buf */
+ if (count > data->max_reportid)
+ return -EINVAL;
+
+ /* Process remaining messages if necessary */
+ ret = __mxt_read_reg(data->client, data->T5_address,
+ data->T5_msg_size * count, data->msg_buf);
+ if (ret) {
+ dev_err(dev, "Failed to read %u messages (%d)\n", count, ret);
+ return ret;
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = mxt_proc_message(data,
+ data->msg_buf + data->T5_msg_size * i);
+
+ if (ret == 1)
+ num_valid++;
+ }
+
+ /* return number of messages read */
+ return num_valid;
+}
+
+static irqreturn_t mxt_process_messages_t44(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+ int ret;
+ u8 count, num_left;
+
+ /* Read T44 and T5 together */
+ ret = __mxt_read_reg(data->client, data->T44_address,
+ data->T5_msg_size + 1, data->msg_buf);
+ if (ret) {
+ dev_err(dev, "Failed to read T44 and T5 (%d)\n", ret);
+ return IRQ_NONE;
+ }
+
+ count = data->msg_buf[0];
+
+ if (count == 0) {
+ dev_warn(dev, "Interrupt triggered but zero messages\n");
+ return IRQ_NONE;
+ } else if (count > data->max_reportid) {
+ dev_err(dev, "T44 count %d exceeded max report id\n", count);
+ count = data->max_reportid;
+ }
+
+ /* Process first message */
+ ret = mxt_proc_message(data, data->msg_buf + 1);
+ if (ret < 0) {
+ dev_warn(dev, "Unexpected invalid message\n");
+ return IRQ_NONE;
+ }
+
+ num_left = count - 1;
+
+ /* Process remaining messages if necessary */
+ if (num_left) {
+ ret = mxt_read_and_process_messages(data, num_left);
+ if (ret < 0)
+ goto end;
+ else if (ret != num_left)
+ dev_warn(dev, "Unexpected invalid message\n");
+ }
+
+end:
+ if (data->update_input) {
+ mxt_input_sync(data->input_dev);
+ data->update_input = false;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int mxt_process_messages_until_invalid(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+ int count, read;
+ u8 tries = 2;
+
+ count = data->max_reportid;
+
+ /* Read messages until we force an invalid */
+ do {
+ read = mxt_read_and_process_messages(data, count);
+ if (read < count)
+ return 0;
+ } while (--tries);
+
+ if (data->update_input) {
+ mxt_input_sync(data->input_dev);
+ data->update_input = false;
+ }
+
+ dev_err(dev, "CHG pin isn't cleared\n");
+ return -EBUSY;
+}
+
+static irqreturn_t mxt_process_messages(struct mxt_data *data)
+{
+ int total_handled, num_handled;
+ u8 count = data->last_message_count;
+
+ if (count < 1 || count > data->max_reportid)
+ count = 1;
+
+ /* include final invalid message */
+ total_handled = mxt_read_and_process_messages(data, count + 1);
+ if (total_handled < 0)
+ return IRQ_NONE;
+ /* if there were invalid messages, then we are done */
+ else if (total_handled <= count)
+ goto update_count;
+
+ /* read two at a time until an invalid message or else we reach
+ * reportid limit */
+ do {
+ num_handled = mxt_read_and_process_messages(data, 2);
+ if (num_handled < 0)
+ return IRQ_NONE;
+
+ total_handled += num_handled;
+
+ if (num_handled < 2)
+ break;
+ } while (total_handled < data->num_touchids);
+
+update_count:
+ data->last_message_count = total_handled;
+
+ if (data->enable_reporting && data->update_input) {
+ mxt_input_sync(data->input_dev);
+ data->update_input = false;
+ }
+
+ return IRQ_HANDLED;
+}
+
+#if defined(CONFIG_SECURE_TOUCH)
+static void mxt_secure_touch_notify(struct mxt_data *data)
+{
+ sysfs_notify(&data->client->dev.kobj, NULL, "secure_touch");
+}
+
+static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
+{
+ if (atomic_read(&data->st_enabled)) {
+ if (atomic_cmpxchg(&data->st_pending_irqs, 0, 1) == 0)
+ mxt_secure_touch_notify(data);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+#else
+static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
+{
+ return IRQ_NONE;
+}
+#endif
+
+static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+{
+ struct mxt_data *data = dev_id;
+
+ if (data->in_bootloader) {
+ /* bootloader state transition completion */
+ complete(&data->bl_completion);
+ return IRQ_HANDLED;
+ }
+
+ if (IRQ_HANDLED == mxt_filter_interrupt(data))
+ return IRQ_HANDLED;
+
+ if (!data->object_table)
+ return IRQ_NONE;
+
+ if (data->T44_address) {
+ return mxt_process_messages_t44(data);
+ } else {
+ return mxt_process_messages(data);
+ }
+}
+
+static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset,
+ u8 value, bool wait)
+{
+ u16 reg;
+ u8 command_register = 0;
+ int timeout_counter = 0;
+ int ret;
+
+ reg = data->T6_address + cmd_offset;
+
+ ret = mxt_write_reg(data->client, reg, value);
+ if (ret)
+ return ret;
+
+ if (!wait)
+ return 0;
+
+ do {
+ msleep(20);
+ ret = __mxt_read_reg(data->client, reg, 1, &command_register);
+ if (ret)
+ return ret;
+ } while ((command_register != 0) && (timeout_counter++ <= 100));
+
+ if (timeout_counter > 100) {
+ dev_err(&data->client->dev, "Command failed!\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int mxt_soft_reset(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+ int ret = 0;
+
+ dev_info(dev, "Resetting chip\n");
+
+ reinit_completion(&data->reset_completion);
+
+ ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_RESET_VALUE, false);
+ if (ret)
+ return ret;
+
+ ret = mxt_wait_for_completion(data, &data->reset_completion,
+ MXT_RESET_TIMEOUT);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void mxt_update_crc(struct mxt_data *data, u8 cmd, u8 value)
+{
+ /* on failure, CRC is set to 0 and config will always be downloaded */
+ data->config_crc = 0;
+ reinit_completion(&data->crc_completion);
+
+ mxt_t6_command(data, cmd, value, true);
+
+ /* Wait for crc message. On failure, CRC is set to 0 and config will
+ * always be downloaded */
+ mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT);
+}
+
+static void mxt_calc_crc24(u32 *crc, u8 firstbyte, u8 secondbyte)
+{
+ static const unsigned int crcpoly = 0x80001B;
+ u32 result;
+ u32 data_word;
+
+ data_word = (secondbyte << 8) | firstbyte;
+ result = ((*crc << 1) ^ data_word);
+
+ if (result & 0x1000000)
+ result ^= crcpoly;
+
+ *crc = result;
+}
+
+static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off)
+{
+ u32 crc = 0;
+ u8 *ptr = base + start_off;
+ u8 *last_val = base + end_off - 1;
+
+ if (end_off < start_off)
+ return -EINVAL;
+
+ while (ptr < last_val) {
+ mxt_calc_crc24(&crc, *ptr, *(ptr + 1));
+ ptr += 2;
+ }
+
+ /* if len is odd, fill the last byte with 0 */
+ if (ptr == last_val)
+ mxt_calc_crc24(&crc, *ptr, 0);
+
+ /* Mask to 24-bit */
+ crc &= 0x00FFFFFF;
+
+ return crc;
+}
+
+static int mxt_check_retrigen(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ int error;
+ int val = 0;
+
+ if (data->pdata->irqflags & IRQF_TRIGGER_LOW)
+ return 0;
+
+ if (data->T18_address) {
+ error = __mxt_read_reg(client,
+ data->T18_address + MXT_COMMS_CTRL,
+ 1, &val);
+ if (error)
+ return error;
+
+ if (val & MXT_COMMS_RETRIGEN)
+ return 0;
+ }
+
+ dev_warn(&client->dev, "Enabling RETRIGEN workaround\n");
+ data->use_retrigen_workaround = true;
+ return 0;
+}
+
+static int mxt_init_t7_power_cfg(struct mxt_data *data);
+
+static int mxt_update_cfg_version(struct mxt_data *data)
+{
+ struct mxt_object *object;
+ int error;
+
+ object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
+ if (!object)
+ return -EINVAL;
+
+ error = __mxt_read_reg(data->client, object->start_address,
+ sizeof(data->cfg_version), &data->cfg_version);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+static int mxt_update_t100_resolution(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ int error;
+ struct mxt_object *object;
+ u16 range_x = 0;
+ u16 range_y = 0;
+ u16 temp;
+ u8 cfg = 0;
+ u8 tchaux = 0;
+ u8 aux;
+ bool update = false;
+
+ object = mxt_get_object(data, MXT_TOUCH_MULTITOUCHSCREEN_T100);
+ if (!object)
+ return -EINVAL;
+
+ error = __mxt_read_reg(client,
+ object->start_address + MXT_T100_XRANGE,
+ sizeof(range_x), &range_x);
+ if (error)
+ return error;
+
+ le16_to_cpus(range_x);
+
+ error = __mxt_read_reg(client,
+ object->start_address + MXT_T100_YRANGE,
+ sizeof(range_y), &range_y);
+ if (error)
+ return error;
+
+ le16_to_cpus(range_y);
+
+ error = __mxt_read_reg(client,
+ object->start_address + MXT_T100_CFG1,
+ 1, &cfg);
+ if (error)
+ return error;
+
+ error = __mxt_read_reg(client,
+ object->start_address + MXT_T100_TCHAUX,
+ 1, &tchaux);
+ if (error)
+ return error;
+
+ /* Handle default values */
+ if (range_x == 0)
+ range_x = 1023;
+
+ if (range_y == 0)
+ range_y = 1023;
+
+ dev_dbg(&client->dev, "initial x=%d y=%d\n", range_x, range_y);
+
+ if (cfg & MXT_T100_CFG_SWITCHXY) {
+ dev_dbg(&client->dev, "flip x and y\n");
+ temp = range_y;
+ range_y = range_x;
+ range_x = temp;
+ }
+
+ if (data->pdata->panel_maxx != range_x) {
+ if (cfg & MXT_T100_CFG_SWITCHXY)
+ range_x = data->pdata->panel_maxy;
+ else
+ range_x = data->pdata->panel_maxx;
+ cpu_to_le16s(range_x);
+ error = __mxt_write_reg(client,
+ object->start_address + MXT_T100_XRANGE,
+ sizeof(range_x), &range_x);
+ if (error)
+ return error;
+ dev_dbg(&client->dev, "panel maxx mismatch. update\n");
+ update = true;
+ }
+
+ if (data->pdata->panel_maxy != range_y) {
+ if (cfg & MXT_T100_CFG_SWITCHXY)
+ range_y = data->pdata->panel_maxx;
+ else
+ range_y = data->pdata->panel_maxy;
+
+ cpu_to_le16s(range_y);
+ error = __mxt_write_reg(client,
+ object->start_address + MXT_T100_YRANGE,
+ sizeof(range_y), &range_y);
+ if (error)
+ return error;
+ dev_dbg(&client->dev, "panel maxy mismatch. update\n");
+ update = true;
+ }
+
+ if (update) {
+ mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
+
+ mxt_soft_reset(data);
+ }
+
+ /* allocate aux bytes */
+ aux = 6;
+
+ if (tchaux & MXT_T100_TCHAUX_VECT)
+ data->t100_aux_vect = aux++;
+
+ if (tchaux & MXT_T100_TCHAUX_AMPL)
+ data->t100_aux_ampl = aux++;
+
+ if (tchaux & MXT_T100_TCHAUX_AREA)
+ data->t100_aux_area = aux++;
+
+ dev_info(&client->dev,
+ "T100 Touchscreen size X%uY%u\n", range_x, range_y);
+
+ return 0;
+}
+
+static int mxt_update_t9_resolution(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ int error;
+ struct t9_range range = {0};
+ unsigned char orient = 0;
+ struct mxt_object *object;
+ u16 temp;
+ bool update = false;
+
+ object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
+ if (!object)
+ return -EINVAL;
+
+ error = __mxt_read_reg(client,
+ object->start_address + MXT_T9_RANGE,
+ sizeof(range), &range);
+ if (error)
+ return error;
+
+ le16_to_cpus(range.x);
+ le16_to_cpus(range.y);
+
+ error = __mxt_read_reg(client,
+ object->start_address + MXT_T9_ORIENT,
+ 1, &orient);
+ if (error)
+ return error;
+
+ /* Handle default values */
+ if (range.x == 0)
+ range.x = 1023;
+
+ if (range.y == 0)
+ range.y = 1023;
+
+ dev_dbg(&client->dev, "initial x=%d y=%d\n", range.x, range.y);
+
+ if (orient & MXT_T9_ORIENT_SWITCH) {
+ dev_dbg(&client->dev, "flip x and y\n");
+ temp = range.y;
+ range.y = range.x;
+ range.x = temp;
+ }
+
+ if (data->pdata->panel_maxx != range.x) {
+ if (orient & MXT_T9_ORIENT_SWITCH)
+ range.x = data->pdata->panel_maxy;
+ else
+ range.x = data->pdata->panel_maxx;
+ cpu_to_le16s(range.x);
+ error = __mxt_write_reg(client,
+ object->start_address + MXT_T100_XRANGE,
+ sizeof(range.x), &range.x);
+ if (error)
+ return error;
+ dev_dbg(&client->dev, "panel maxx mismatch. update\n");
+ update = true;
+ }
+
+ if (data->pdata->panel_maxy != range.y) {
+ if (orient & MXT_T9_ORIENT_SWITCH)
+ range.y = data->pdata->panel_maxx;
+ else
+ range.y = data->pdata->panel_maxy;
+
+ cpu_to_le16s(range.y);
+ error = __mxt_write_reg(client,
+ object->start_address + MXT_T100_YRANGE,
+ sizeof(range.y), &range.y);
+ if (error)
+ return error;
+ dev_dbg(&client->dev, "panel maxy mismatch. update\n");
+ update = true;
+ }
+
+ if (update) {
+ mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
+
+ mxt_soft_reset(data);
+ }
+
+ dev_info(&client->dev,
+ "Touchscreen size X%uY%u\n", range.x, range.y);
+
+ return 0;
+}
+
+/*
+ * mxt_load_cfg - download configuration to chip
+ *
+ * Atmel Raw Config File Format
+ *
+ * The first four lines of the raw config file contain:
+ * 1) Version
+ * 2) Chip ID Information (first 7 bytes of device memory)
+ * 3) Chip Information Block 24-bit CRC Checksum
+ * 4) Chip Configuration 24-bit CRC Checksum
+ *
+ * The rest of the file consists of one line per object instance:
+ * <TYPE> <INSTANCE> <SIZE> <CONTENTS>
+ *
+ * <TYPE> - 2-byte object type as hex
+ * <INSTANCE> - 2-byte object instance number as hex
+ * <SIZE> - 2-byte object size as hex
+ * <CONTENTS> - array of <SIZE> 1-byte hex values
+ */
+static int mxt_load_cfg(struct mxt_data *data, bool force)
+{
+ struct device *dev = &data->client->dev;
+ struct mxt_info cfg_info;
+ struct mxt_object *object;
+ const struct firmware *cfg = NULL;
+ int ret = 0;
+ int offset;
+ int data_pos;
+ int byte_offset;
+ int i;
+ int cfg_start_ofs;
+ u32 info_crc, config_crc, calculated_crc;
+ u8 *config_mem;
+ unsigned int config_mem_size;
+ unsigned int type, instance, size;
+ u8 val;
+ int ver[3];
+ u16 reg;
+
+ if (!data->cfg_name) {
+ dev_dbg(dev, "Skipping cfg download\n");
+ goto report_enable;
+ }
+
+ ret = request_firmware(&cfg, data->cfg_name, dev);
+ if (ret < 0) {
+ dev_err(dev, "Failure to request config file %s\n",
+ data->cfg_name);
+ goto report_enable;
+ }
+
+ mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
+
+ if (strncmp(cfg->data, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) {
+ dev_err(dev, "Unrecognised config file\n");
+ ret = -EINVAL;
+ goto release;
+ }
+
+ data_pos = strlen(MXT_CFG_MAGIC);
+
+ /* Load information block and check */
+ for (i = 0; i < sizeof(struct mxt_info); i++) {
+ ret = sscanf(cfg->data + data_pos, "%hhx%n",
+ (unsigned char *)&cfg_info + i,
+ &offset);
+ if (ret != 1) {
+ dev_err(dev, "Bad format\n");
+ ret = -EINVAL;
+ goto release;
+ }
+
+ data_pos += offset;
+ }
+
+ if (cfg_info.family_id != data->info->family_id) {
+ dev_err(dev, "Family ID mismatch!\n");
+ ret = -EINVAL;
+ goto release;
+ }
+
+ if (cfg_info.variant_id != data->info->variant_id) {
+ dev_err(dev, "Variant ID mismatch!\n");
+ ret = -EINVAL;
+ goto release;
+ }
+
+ /* Read CRCs */
+ ret = sscanf(cfg->data + data_pos, "%x%n", &info_crc, &offset);
+ if (ret != 1) {
+ dev_err(dev, "Bad format: failed to parse Info CRC\n");
+ ret = -EINVAL;
+ goto release;
+ }
+ data_pos += offset;
+
+ ret = sscanf(cfg->data + data_pos, "%x%n", &config_crc, &offset);
+ if (ret != 1) {
+ dev_err(dev, "Bad format: failed to parse Config CRC\n");
+ ret = -EINVAL;
+ goto release;
+ }
+ data_pos += offset;
+
+ /* Malloc memory to store configuration */
+ cfg_start_ofs = MXT_OBJECT_START
+ + data->info->object_num * sizeof(struct mxt_object)
+ + MXT_INFO_CHECKSUM_SIZE;
+ config_mem_size = data->mem_size - cfg_start_ofs;
+ config_mem = kzalloc(config_mem_size, GFP_KERNEL);
+ if (!config_mem) {
+ dev_err(dev, "Failed to allocate memory\n");
+ ret = -ENOMEM;
+ goto release;
+ }
+
+ while (data_pos < cfg->size) {
+ /* Read type, instance, length */
+ ret = sscanf(cfg->data + data_pos, "%x %x %x%n",
+ &type, &instance, &size, &offset);
+ if (ret == 0) {
+ /* EOF */
+ break;
+ } else if (ret != 3) {
+ dev_err(dev, "Bad format: failed to parse object\n");
+ ret = -EINVAL;
+ goto release_mem;
+ }
+ data_pos += offset;
+
+ if (type == MXT_SPT_USERDATA_T38) {
+ ret = sscanf(cfg->data + data_pos, "%x %x %x",
+ &ver[0], &ver[1], &ver[2]);
+ dev_info(dev, "controller version:%d.%d.%d file version:%d.%d.%d",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2], ver[0], ver[1], ver[2]);
+
+ if (force || data->fw_w_no_cfg_update) {
+ dev_info(dev, "starting force cfg update\n");
+ } else if (data->cfg_version[0] != ver[0]) {
+ dev_info(dev, "cfg major versions do not match\n");
+ ret = -EINVAL;
+ goto release_mem;
+ } else if (data->cfg_version[1] > ver[1]) {
+ dev_info(dev, "configuration is up-to-date\n");
+ ret = -EINVAL;
+ goto release_mem;
+ } else if (data->cfg_version[1] == ver[1]) {
+ if (data->cfg_version[2] >= ver[2]) {
+ dev_info(dev, "configuration is up-to-date\n");
+ ret = -EINVAL;
+ goto release_mem;
+ }
+ } else {
+ dev_info(dev, "starting cfg update\n");
+ }
+ }
+
+ object = mxt_get_object(data, type);
+ if (!object) {
+ /* Skip object */
+ for (i = 0; i < size; i++) {
+ ret = sscanf(cfg->data + data_pos, "%hhx%n",
+ &val,
+ &offset);
+ data_pos += offset;
+ }
+ continue;
+ }
+
+ if (size > mxt_obj_size(object)) {
+ /* Either we are in fallback mode due to wrong
+ * config or config from a later fw version,
+ * or the file is corrupt or hand-edited */
+ dev_warn(dev, "Discarding %u byte(s) in T%u\n",
+ size - mxt_obj_size(object), type);
+ } else if (mxt_obj_size(object) > size) {
+ /* If firmware is upgraded, new bytes may be added to
+ * end of objects. It is generally forward compatible
+ * to zero these bytes - previous behaviour will be
+ * retained. However this does invalidate the CRC and
+ * will force fallback mode until the configuration is
+ * updated. We warn here but do nothing else - the
+ * malloc has zeroed the entire configuration. */
+ dev_warn(dev, "Zeroing %u byte(s) in T%d\n",
+ mxt_obj_size(object) - size, type);
+ }
+
+ if (instance >= mxt_obj_instances(object)) {
+ dev_err(dev, "Object instances exceeded!\n");
+ ret = -EINVAL;
+ goto release_mem;
+ }
+
+ reg = object->start_address + mxt_obj_size(object) * instance;
+
+ for (i = 0; i < size; i++) {
+ ret = sscanf(cfg->data + data_pos, "%hhx%n",
+ &val,
+ &offset);
+ if (ret != 1) {
+ dev_err(dev, "Bad format in T%d\n", type);
+ ret = -EINVAL;
+ goto release_mem;
+ }
+ data_pos += offset;
+
+ if (i > mxt_obj_size(object))
+ continue;
+
+ byte_offset = reg + i - cfg_start_ofs;
+
+ if ((byte_offset >= 0)
+ && (byte_offset <= config_mem_size)) {
+ *(config_mem + byte_offset) = val;
+ } else {
+ dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n",
+ reg, object->type, byte_offset);
+ ret = -EINVAL;
+ goto release_mem;
+ }
+ }
+ }
+
+ /* calculate crc of the received configs (not the raw config file) */
+ if (data->T7_address < cfg_start_ofs) {
+ dev_err(dev, "Bad T7 address, T7addr = %x, config offset %x\n",
+ data->T7_address, cfg_start_ofs);
+ ret = 0;
+ goto release_mem;
+ }
+
+ calculated_crc = mxt_calculate_crc(config_mem,
+ data->T7_address - cfg_start_ofs,
+ config_mem_size);
+
+ if (config_crc > 0 && (config_crc != calculated_crc))
+ dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n",
+ calculated_crc, config_crc);
+
+ /* Write configuration as blocks */
+ byte_offset = 0;
+ while (byte_offset < config_mem_size) {
+ size = config_mem_size - byte_offset;
+
+ if (size > MXT_MAX_BLOCK_WRITE)
+ size = MXT_MAX_BLOCK_WRITE;
+
+ ret = __mxt_write_reg(data->client,
+ cfg_start_ofs + byte_offset,
+ size, config_mem + byte_offset);
+ if (ret != 0) {
+ dev_err(dev, "Config write error, ret=%d\n", ret);
+ goto release_mem;
+ }
+
+ byte_offset += size;
+ }
+
+ mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
+
+ ret = mxt_check_retrigen(data);
+ if (ret)
+ goto release_mem;
+
+ ret = mxt_soft_reset(data);
+ if (ret)
+ goto release_mem;
+
+ dev_info(dev, "Config written\n");
+
+ /* T7 config may have changed */
+ mxt_init_t7_power_cfg(data);
+
+ mxt_update_cfg_version(data);
+
+ /* update resolution if needed */
+ if (data->T9_reportid_min) {
+ ret = mxt_update_t9_resolution(data);
+ if (ret)
+ goto release_mem;
+ } else if (data->T100_reportid_min) {
+ ret = mxt_update_t100_resolution(data);
+ if (ret)
+ goto release_mem;
+ } else {
+ dev_warn(dev, "No touch object detected\n");
+ }
+
+release_mem:
+ kfree(config_mem);
+release:
+ release_firmware(cfg);
+report_enable:
+ data->enable_reporting = true;
+
+ return ret;
+}
+
+static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep)
+{
+ struct device *dev = &data->client->dev;
+ int error;
+ struct t7_config *new_config;
+ struct t7_config deepsleep = { .active = 0, .idle = 0 };
+
+ if (sleep == MXT_POWER_CFG_DEEPSLEEP)
+ new_config = &deepsleep;
+ else
+ new_config = &data->t7_cfg;
+
+ error = __mxt_write_reg(data->client, data->T7_address,
+ sizeof(data->t7_cfg),
+ new_config);
+ if (error)
+ return error;
+
+ dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d\n",
+ new_config->active, new_config->idle);
+
+ return 0;
+}
+
+static int mxt_init_t7_power_cfg(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+ int error;
+ bool retry = false;
+
+recheck:
+ error = __mxt_read_reg(data->client, data->T7_address,
+ sizeof(data->t7_cfg), &data->t7_cfg);
+ if (error)
+ return error;
+
+ if (data->t7_cfg.active == 0 || data->t7_cfg.idle == 0) {
+ if (!retry) {
+ dev_info(dev, "T7 cfg zero, resetting\n");
+ mxt_soft_reset(data);
+ retry = true;
+ goto recheck;
+ } else {
+ dev_dbg(dev, "T7 cfg zero after reset, overriding\n");
+ data->t7_cfg.active = 20;
+ data->t7_cfg.idle = 100;
+ return mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
+ }
+ } else {
+ dev_info(dev, "Initialised power cfg: ACTV %d, IDLE %d\n",
+ data->t7_cfg.active, data->t7_cfg.idle);
+ return 0;
+ }
+}
+
+static int mxt_acquire_irq(struct mxt_data *data)
+{
+ int error;
+
+ enable_irq(data->irq);
+
+ if (data->use_retrigen_workaround) {
+ error = mxt_process_messages_until_invalid(data);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+static void mxt_free_input_device(struct mxt_data *data)
+{
+ if (data->input_dev) {
+ input_unregister_device(data->input_dev);
+ data->input_dev = NULL;
+ }
+}
+
+static void mxt_free_object_table(struct mxt_data *data)
+{
+ mxt_debug_msg_remove(data);
+
+ kfree(data->raw_info_block);
+ data->object_table = NULL;
+ data->info = NULL;
+ data->raw_info_block = NULL;
+ kfree(data->msg_buf);
+ data->msg_buf = NULL;
+
+ mxt_free_input_device(data);
+
+ data->enable_reporting = false;
+ data->T5_address = 0;
+ data->T5_msg_size = 0;
+ data->T6_reportid = 0;
+ data->T7_address = 0;
+ data->T9_reportid_min = 0;
+ data->T9_reportid_max = 0;
+ data->T15_reportid_min = 0;
+ data->T15_reportid_max = 0;
+ data->T18_address = 0;
+ data->T19_reportid = 0;
+ data->T42_reportid_min = 0;
+ data->T42_reportid_max = 0;
+ data->T44_address = 0;
+ data->T48_reportid = 0;
+ data->T63_reportid_min = 0;
+ data->T63_reportid_max = 0;
+ data->T100_reportid_min = 0;
+ data->T100_reportid_max = 0;
+ data->max_reportid = 0;
+}
+
+static int mxt_parse_object_table(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ int i;
+ u8 reportid;
+ u16 end_address;
+
+ /* Valid Report IDs start counting from 1 */
+ reportid = 1;
+ data->mem_size = 0;
+ for (i = 0; i < data->info->object_num; i++) {
+ struct mxt_object *object = data->object_table + i;
+ u8 min_id, max_id;
+
+ le16_to_cpus(&object->start_address);
+
+ if (object->num_report_ids) {
+ min_id = reportid;
+ reportid += object->num_report_ids *
+ mxt_obj_instances(object);
+ max_id = reportid - 1;
+ } else {
+ min_id = 0;
+ max_id = 0;
+ }
+
+ dev_dbg(&data->client->dev,
+ "T%u Start:%u Size:%u Instances:%u Report IDs:%u-%u\n",
+ object->type, object->start_address,
+ mxt_obj_size(object), mxt_obj_instances(object),
+ min_id, max_id);
+
+ switch (object->type) {
+ case MXT_GEN_MESSAGE_T5:
+ if (data->info->family_id == 0x80) {
+ /* On mXT224 read and discard unused CRC byte
+ * otherwise DMA reads are misaligned */
+ data->T5_msg_size = mxt_obj_size(object);
+ } else {
+ /* CRC not enabled, so skip last byte */
+ data->T5_msg_size = mxt_obj_size(object) - 1;
+ }
+ data->T5_address = object->start_address;
+ case MXT_GEN_COMMAND_T6:
+ data->T6_reportid = min_id;
+ data->T6_address = object->start_address;
+ break;
+ case MXT_GEN_POWER_T7:
+ data->T7_address = object->start_address;
+ break;
+ case MXT_TOUCH_MULTI_T9:
+ /* Only handle messages from first T9 instance */
+ data->T9_reportid_min = min_id;
+ data->T9_reportid_max = min_id +
+ object->num_report_ids - 1;
+ data->num_touchids = object->num_report_ids;
+ break;
+ case MXT_TOUCH_KEYARRAY_T15:
+ data->T15_reportid_min = min_id;
+ data->T15_reportid_max = max_id;
+ break;
+ case MXT_SPT_COMMSCONFIG_T18:
+ data->T18_address = object->start_address;
+ break;
+ case MXT_PROCI_TOUCHSUPPRESSION_T42:
+ data->T42_reportid_min = min_id;
+ data->T42_reportid_max = max_id;
+ break;
+ case MXT_SPT_MESSAGECOUNT_T44:
+ data->T44_address = object->start_address;
+ break;
+ case MXT_SPT_GPIOPWM_T19:
+ data->T19_reportid = min_id;
+ break;
+ case MXT_PROCG_NOISESUPPRESSION_T48:
+ data->T48_reportid = min_id;
+ break;
+ case MXT_PROCI_ACTIVE_STYLUS_T63:
+ /* Only handle messages from first T63 instance */
+ data->T63_reportid_min = min_id;
+ data->T63_reportid_max = min_id;
+ data->num_stylusids = 1;
+ break;
+ case MXT_TOUCH_MULTITOUCHSCREEN_T100:
+ data->T100_reportid_min = min_id;
+ data->T100_reportid_max = max_id;
+ /* first two report IDs reserved */
+ data->num_touchids = object->num_report_ids - 2;
+ break;
+ }
+
+ end_address = object->start_address
+ + mxt_obj_size(object) * mxt_obj_instances(object) - 1;
+
+ if (end_address >= data->mem_size)
+ data->mem_size = end_address + 1;
+ }
+
+ /* Store maximum reportid */
+ data->max_reportid = reportid;
+
+ /* If T44 exists, T5 position has to be directly after */
+ if (data->T44_address && (data->T5_address != data->T44_address + 1)) {
+ dev_err(&client->dev, "Invalid T44 position\n");
+ return -EINVAL;
+ }
+
+ data->msg_buf = kcalloc(data->max_reportid,
+ data->T5_msg_size, GFP_KERNEL);
+ if (!data->msg_buf) {
+ dev_err(&client->dev, "Failed to allocate message buffer\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int mxt_read_info_block(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ int error;
+ u16 size;
+ void *buf;
+ uint8_t num_objects;
+ u32 calculated_crc;
+ u8 *crc_ptr;
+
+ /* If info block already allocated, free it */
+ if (data->raw_info_block != NULL)
+ mxt_free_object_table(data);
+
+ /* Read 7-byte ID information block starting at address 0 */
+ size = sizeof(struct mxt_info);
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ error = __mxt_read_reg(client, 0, size, buf);
+ if (error)
+ goto err_free_mem;
+
+ /* Resize buffer to give space for rest of info block */
+ num_objects = ((struct mxt_info *)buf)->object_num;
+ size += (num_objects * sizeof(struct mxt_object))
+ + MXT_INFO_CHECKSUM_SIZE;
+
+ buf = krealloc(buf, size, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ error = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ /* Read rest of info block */
+ error = __mxt_read_reg(client, MXT_OBJECT_START,
+ size - MXT_OBJECT_START,
+ buf + MXT_OBJECT_START);
+ if (error)
+ goto err_free_mem;
+
+ /* Extract & calculate checksum */
+ crc_ptr = buf + size - MXT_INFO_CHECKSUM_SIZE;
+ data->info_crc = crc_ptr[0] | (crc_ptr[1] << 8) | (crc_ptr[2] << 16);
+
+ calculated_crc = mxt_calculate_crc(buf, 0,
+ size - MXT_INFO_CHECKSUM_SIZE);
+
+ /* CRC mismatch can be caused by data corruption due to I2C comms
+ * issue or else device is not using Object Based Protocol */
+ if ((data->info_crc == 0) || (data->info_crc != calculated_crc)) {
+ dev_err(&client->dev,
+ "Info Block CRC error calculated=0x%06X read=0x%06X\n",
+ data->info_crc, calculated_crc);
+ if (!data->pdata->ignore_crc)
+ goto err_free_mem;
+ }
+
+ /* Save pointers in device data structure */
+ data->raw_info_block = buf;
+ data->info = (struct mxt_info *)buf;
+ data->object_table = (struct mxt_object *)(buf + MXT_OBJECT_START);
+
+ /* Parse object table information */
+ error = mxt_parse_object_table(data);
+ if (error) {
+ dev_err(&client->dev, "Error %d reading object table\n", error);
+ goto err_free_obj_table;
+ }
+
+ error = mxt_update_cfg_version(data);
+ if (error)
+ goto err_free_obj_table;
+
+ dev_info(&client->dev,
+ "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u cfg version: %d.%d.%d\n",
+ data->info->family_id, data->info->variant_id,
+ data->info->version >> 4, data->info->version & 0xf,
+ data->info->build, data->info->object_num,
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2]);
+
+
+ return 0;
+
+err_free_obj_table:
+ mxt_free_object_table(data);
+err_free_mem:
+ kfree(buf);
+ return error;
+}
+
+static int mxt_pinctrl_init(struct mxt_data *data)
+{
+ int error;
+
+ /* Get pinctrl if target uses pinctrl */
+ data->ts_pinctrl = devm_pinctrl_get((&data->client->dev));
+ if (IS_ERR_OR_NULL(data->ts_pinctrl)) {
+ dev_dbg(&data->client->dev,
+ "Device does not use pinctrl\n");
+ error = PTR_ERR(data->ts_pinctrl);
+ data->ts_pinctrl = NULL;
+ return error;
+ }
+
+ data->gpio_state_active
+ = pinctrl_lookup_state(data->ts_pinctrl, "pmx_ts_active");
+ if (IS_ERR_OR_NULL(data->gpio_state_active)) {
+ dev_dbg(&data->client->dev,
+ "Can not get ts default pinstate\n");
+ error = PTR_ERR(data->gpio_state_active);
+ data->ts_pinctrl = NULL;
+ return error;
+ }
+
+ data->gpio_state_suspend
+ = pinctrl_lookup_state(data->ts_pinctrl, "pmx_ts_suspend");
+ if (IS_ERR_OR_NULL(data->gpio_state_suspend)) {
+ dev_dbg(&data->client->dev,
+ "Can not get ts sleep pinstate\n");
+ error = PTR_ERR(data->gpio_state_suspend);
+ data->ts_pinctrl = NULL;
+ return error;
+ }
+
+ return 0;
+}
+
+static int mxt_pinctrl_select(struct mxt_data *data, bool on)
+{
+ struct pinctrl_state *pins_state;
+ int error;
+
+ pins_state = on ? data->gpio_state_active
+ : data->gpio_state_suspend;
+ if (!IS_ERR_OR_NULL(pins_state)) {
+ error = pinctrl_select_state(data->ts_pinctrl, pins_state);
+ if (error) {
+ dev_err(&data->client->dev,
+ "can not set %s pins\n",
+ on ? "pmx_ts_active" : "pmx_ts_suspend");
+ return error;
+ }
+ } else {
+ dev_err(&data->client->dev,
+ "not a valid '%s' pinstate\n",
+ on ? "pmx_ts_active" : "pmx_ts_suspend");
+ }
+
+ return 0;
+}
+
+static int mxt_gpio_enable(struct mxt_data *data, bool enable)
+{
+ const struct mxt_platform_data *pdata = data->pdata;
+ int error;
+
+ if (data->ts_pinctrl) {
+ error = mxt_pinctrl_select(data, enable);
+ if (error < 0)
+ return error;
+ }
+
+ if (enable) {
+ if (gpio_is_valid(pdata->gpio_irq)) {
+ error = gpio_request(pdata->gpio_irq,
+ "maxtouch_gpio_irq");
+ if (error) {
+ dev_err(&data->client->dev,
+ "unable to request %d gpio(%d)\n",
+ pdata->gpio_irq, error);
+ return error;
+ }
+ error = gpio_direction_input(pdata->gpio_irq);
+ if (error) {
+ dev_err(&data->client->dev,
+ "unable to set dir for %d gpio(%d)\n",
+ data->pdata->gpio_irq, error);
+ goto err_free_irq;
+ }
+
+ } else {
+ dev_err(&data->client->dev, "irq gpio not provided\n");
+ return -EINVAL;
+ }
+
+ if (gpio_is_valid(pdata->gpio_reset)) {
+ error = gpio_request(pdata->gpio_reset,
+ "maxtouch_gpio_reset");
+ if (error) {
+ dev_err(&data->client->dev,
+ "unable to request %d gpio(%d)\n",
+ pdata->gpio_reset, error);
+ goto err_free_irq;
+ }
+ error = gpio_direction_output(pdata->gpio_reset, 0);
+ if (error) {
+ dev_err(&data->client->dev,
+ "unable to set dir for %d gpio(%d)\n",
+ pdata->gpio_reset, error);
+ goto err_free_reset;
+ }
+ } else {
+ dev_err(&data->client->dev,
+ "reset gpio not provided\n");
+ goto err_free_irq;
+ }
+
+ if (gpio_is_valid(pdata->gpio_i2cmode)) {
+ error = gpio_request(pdata->gpio_i2cmode,
+ "maxtouch_gpio_i2cmode");
+ if (error) {
+ dev_err(&data->client->dev,
+ "unable to request %d gpio (%d)\n",
+ pdata->gpio_i2cmode, error);
+ goto err_free_reset;
+ }
+ error = gpio_direction_output(pdata->gpio_i2cmode, 1);
+ if (error) {
+ dev_err(&data->client->dev,
+ "unable to set dir for %d gpio (%d)\n",
+ pdata->gpio_i2cmode, error);
+ goto err_free_i2cmode;
+ }
+ } else {
+ dev_info(&data->client->dev,
+ "i2cmode gpio is not used\n");
+ }
+ } else {
+ if (gpio_is_valid(pdata->gpio_irq))
+ gpio_free(pdata->gpio_irq);
+
+ if (gpio_is_valid(pdata->gpio_reset)) {
+ gpio_free(pdata->gpio_reset);
+ }
+
+ if (gpio_is_valid(pdata->gpio_i2cmode)) {
+ gpio_set_value(pdata->gpio_i2cmode, 0);
+ gpio_free(pdata->gpio_i2cmode);
+ }
+ }
+
+ return 0;
+
+err_free_i2cmode:
+ if (gpio_is_valid(pdata->gpio_i2cmode)) {
+ gpio_set_value(pdata->gpio_i2cmode, 0);
+ gpio_free(pdata->gpio_i2cmode);
+ }
+err_free_reset:
+ if (gpio_is_valid(pdata->gpio_reset)) {
+ gpio_free(pdata->gpio_reset);
+ }
+err_free_irq:
+ if (gpio_is_valid(pdata->gpio_irq))
+ gpio_free(pdata->gpio_irq);
+ return error;
+}
+
+static int mxt_regulator_enable(struct mxt_data *data)
+{
+ int error;
+
+ if (!data->use_regulator)
+ return 0;
+
+ gpio_set_value(data->pdata->gpio_reset, 0);
+
+ error = regulator_enable(data->reg_vdd);
+ if (error) {
+ dev_err(&data->client->dev,
+ "vdd enable failed, error=%d\n", error);
+ return error;
+ }
+ error = regulator_enable(data->reg_avdd);
+ if (error) {
+ dev_err(&data->client->dev,
+ "avdd enable failed, error=%d\n", error);
+ goto err_dis_vdd;
+ }
+
+ if (!IS_ERR(data->reg_xvdd)) {
+ error = regulator_enable(data->reg_xvdd);
+ if (error) {
+ dev_err(&data->client->dev,
+ "xvdd enable failed, error=%d\n", error);
+ goto err_dis_avdd;
+ }
+ }
+ msleep(MXT_REGULATOR_DELAY);
+
+ reinit_completion(&data->bl_completion);
+ gpio_set_value(data->pdata->gpio_reset, 1);
+ mxt_wait_for_completion(data, &data->bl_completion, MXT_POWERON_DELAY);
+
+ return 0;
+
+err_dis_avdd:
+ regulator_disable(data->reg_avdd);
+err_dis_vdd:
+ regulator_disable(data->reg_vdd);
+ return error;
+}
+
+static void mxt_regulator_disable(struct mxt_data *data)
+{
+ regulator_disable(data->reg_vdd);
+ regulator_disable(data->reg_avdd);
+ if (!IS_ERR(data->reg_xvdd))
+ regulator_disable(data->reg_xvdd);
+}
+
+static int mxt_regulator_configure(struct mxt_data *data, bool state)
+{
+ struct device *dev = &data->client->dev;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ int error = 0;
+
+ /* According to maXTouch power sequencing specification, RESET line
+ * must be kept low until some time after regulators come up to
+ * voltage */
+ if (!data->pdata->gpio_reset) {
+ dev_warn(dev, "Must have reset GPIO to use regulator support\n");
+ return 0;
+ }
+
+ if (!state)
+ goto deconfig;
+
+ data->reg_vdd = regulator_get(dev, "vdd");
+ if (IS_ERR(data->reg_vdd)) {
+ error = PTR_ERR(data->reg_vdd);
+ dev_err(dev, "Error %d getting vdd regulator\n", error);
+ return error;
+ }
+
+ if (regulator_count_voltages(data->reg_vdd) > 0) {
+ error = regulator_set_voltage(data->reg_vdd,
+ MXT_VDD_VTG_MIN_UV, MXT_VDD_VTG_MAX_UV);
+ if (error) {
+ dev_err(&data->client->dev,
+ "vdd set_vtg failed err=%d\n", error);
+ goto fail_put_vdd;
+ }
+ }
+
+ data->reg_avdd = regulator_get(dev, "avdd");
+ if (IS_ERR(data->reg_avdd)) {
+ error = PTR_ERR(data->reg_avdd);
+ dev_err(dev, "Error %d getting avdd regulator\n", error);
+ goto fail_put_vdd;
+ }
+
+ if (regulator_count_voltages(data->reg_avdd) > 0) {
+ error = regulator_set_voltage(data->reg_avdd,
+ MXT_AVDD_VTG_MIN_UV, MXT_AVDD_VTG_MAX_UV);
+ if (error) {
+ dev_err(&data->client->dev,
+ "avdd set_vtg failed err=%d\n", error);
+ goto fail_put_avdd;
+ }
+ }
+
+ data->reg_xvdd = regulator_get(dev, "xvdd");
+ if (IS_ERR(data->reg_xvdd)) {
+ error = PTR_ERR(data->reg_xvdd);
+ prop = of_find_property(np, "xvdd-supply", NULL);
+ if (prop && (error == -EPROBE_DEFER))
+ return -EPROBE_DEFER;
+ dev_info(dev, "xvdd regulator is not used\n");
+ } else {
+ if (regulator_count_voltages(data->reg_xvdd) > 0) {
+ error = regulator_set_voltage(data->reg_xvdd,
+ MXT_XVDD_VTG_MIN_UV, MXT_XVDD_VTG_MAX_UV);
+ if (error)
+ dev_err(&data->client->dev,
+ "xvdd set_vtg failed err=%d\n", error);
+ }
+ }
+
+ data->use_regulator = true;
+
+ dev_dbg(dev, "Initialised regulators\n");
+ return 0;
+
+deconfig:
+ if (!IS_ERR(data->reg_xvdd))
+ regulator_put(data->reg_xvdd);
+fail_put_avdd:
+ regulator_put(data->reg_avdd);
+fail_put_vdd:
+ regulator_put(data->reg_vdd);
+ return error;
+}
+
+
+#if defined(CONFIG_SECURE_TOUCH)
+static void mxt_secure_touch_stop(struct mxt_data *data, int blocking)
+{
+ if (atomic_read(&data->st_enabled)) {
+ atomic_set(&data->st_pending_irqs, -1);
+ mxt_secure_touch_notify(data);
+ if (blocking)
+ wait_for_completion_interruptible(&data->st_powerdown);
+ }
+}
+#else
+static void mxt_secure_touch_stop(struct mxt_data *data, int blocking)
+{
+}
+#endif
+
+static void mxt_start(struct mxt_data *data)
+{
+ if (!data->suspended || data->in_bootloader)
+ return;
+
+ mxt_secure_touch_stop(data, 1);
+
+ /* enable gpios */
+ mxt_gpio_enable(data, true);
+
+ /* enable regulators */
+ mxt_regulator_enable(data);
+
+ /* Discard any messages still in message buffer from before
+ * chip went to sleep */
+ mxt_process_messages_until_invalid(data);
+
+ mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
+
+ /* Recalibrate since chip has been in deep sleep */
+ mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false);
+
+ mxt_acquire_irq(data);
+ data->enable_reporting = true;
+ data->suspended = false;
+}
+
+static void mxt_reset_slots(struct mxt_data *data)
+{
+ struct input_dev *input_dev = data->input_dev;
+ unsigned int num_mt_slots;
+ int id;
+
+ num_mt_slots = data->num_touchids + data->num_stylusids;
+
+ for (id = 0; id < num_mt_slots; id++) {
+ input_mt_slot(input_dev, id);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
+ }
+
+ mxt_input_sync(input_dev);
+}
+
+static void mxt_stop(struct mxt_data *data)
+{
+ if (data->suspended || data->in_bootloader)
+ return;
+
+ mxt_secure_touch_stop(data, 1);
+
+ data->enable_reporting = false;
+ disable_irq(data->irq);
+
+ /* put in deep sleep */
+ mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
+
+ /* disable regulators */
+ mxt_regulator_disable(data);
+
+ /* disable gpios */
+ mxt_gpio_enable(data, false);
+
+ mxt_reset_slots(data);
+ data->suspended = true;
+}
+
+
+static int mxt_input_open(struct input_dev *dev)
+{
+ struct mxt_data *data = input_get_drvdata(dev);
+
+ mxt_start(data);
+
+ return 0;
+}
+
+static void mxt_input_close(struct input_dev *dev)
+{
+ struct mxt_data *data = input_get_drvdata(dev);
+
+ mxt_stop(data);
+}
+
+static int mxt_create_input_dev(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+ struct input_dev *input_dev;
+ int error;
+ unsigned int num_mt_slots;
+ int i;
+
+ if (data->T9_reportid_min) {
+ error = mxt_update_t9_resolution(data);
+ if (error) {
+ dev_err(dev, "update resolution failed\n");
+ return error;
+ }
+ } else if (data->T100_reportid_min) {
+ error = mxt_update_t100_resolution(data);
+ if (error) {
+ dev_err(dev, "update resolution failed\n");
+ return error;
+ }
+ } else {
+ dev_warn(dev, "No touch object detected\n");
+ }
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ dev_err(dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ input_dev->name = "Atmel maXTouch Touchscreen";
+ input_dev->phys = data->phys;
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = dev;
+ input_dev->open = mxt_input_open;
+ input_dev->close = mxt_input_close;
+
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ num_mt_slots = data->num_touchids + data->num_stylusids;
+ error = input_mt_init_slots(input_dev, num_mt_slots, 0);
+ if (error) {
+ dev_err(dev, "Error %d initialising slots\n", error);
+ goto err_free_mem;
+ }
+
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, MXT_MAX_AREA, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ data->pdata->disp_minx, data->pdata->disp_maxx,
+ 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ data->pdata->disp_miny, data->pdata->disp_maxy,
+ 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+ 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
+ 0, 255, 0, 0);
+
+ /* For T63 active stylus */
+ if (data->T63_reportid_min) {
+ input_set_capability(input_dev, EV_KEY, BTN_STYLUS);
+ input_set_capability(input_dev, EV_KEY, BTN_STYLUS2);
+ input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
+ 0, MT_TOOL_MAX, 0, 0);
+ }
+
+ /* For T15 key array */
+ if (data->pdata->key_codes && data->T15_reportid_min) {
+ data->t15_keystatus = 0;
+
+ for (i = 0; i < data->pdata->t15_num_keys; i++)
+ input_set_capability(input_dev, EV_KEY,
+ data->pdata->t15_keymap[i]);
+ }
+
+ input_set_drvdata(input_dev, data);
+
+ error = input_register_device(input_dev);
+ if (error) {
+ dev_err(dev, "Error %d registering input device\n", error);
+ goto err_free_mem;
+ }
+
+ data->input_dev = input_dev;
+
+ return 0;
+
+err_free_mem:
+ input_free_device(input_dev);
+ return error;
+}
+
+static int mxt_configure_objects(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ int error;
+
+ error = mxt_debug_msg_init(data);
+ if (error)
+ return error;
+
+ error = mxt_init_t7_power_cfg(data);
+ if (error)
+ dev_dbg(&client->dev, "Failed to initialize power cfg\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static int mxt_get_dt_coords(struct device *dev, char *name,
+ struct mxt_platform_data *pdata)
+{
+ u32 coords[MXT_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ size_t coords_size;
+ int error;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != MXT_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ error = of_property_read_u32_array(np, name, coords, coords_size);
+ if (error && (error != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return error;
+ }
+
+ if (strcmp(name, "atmel,panel-coords") == 0) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (strcmp(name, "atmel,display-coords") == 0) {
+ pdata->disp_minx = coords[0];
+ pdata->disp_miny = coords[1];
+ pdata->disp_maxx = coords[2];
+ pdata->disp_maxy = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mxt_search_fw_name(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+ struct device_node *np = dev->of_node, *temp;
+ u32 temp_val; size_t len;
+ int rc;
+
+ data->fw_name[0] = '\0';
+
+ if (data->in_bootloader)
+ return 0;
+
+ for_each_child_of_node(np, temp) {
+ rc = of_property_read_u32(temp, "atmel,version", &temp_val);
+ if (rc) {
+ dev_err(dev, "Unable to read controller version\n");
+ return rc;
+ }
+
+ if (temp_val != data->info->version)
+ continue;
+
+ rc = of_property_read_u32(temp, "atmel,build", &temp_val);
+ if (rc) {
+ dev_err(dev, "Unable to read build id\n");
+ return rc;
+ }
+
+ if (temp_val != data->info->build)
+ continue;
+
+ rc = of_property_read_string(temp, "atmel,fw-name",
+ &data->pdata->fw_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw name\n");
+ return rc;
+ }
+
+ dev_dbg(dev, "fw name found(%s)\n", data->pdata->fw_name);
+
+ if (data->pdata->fw_name) {
+ len = strlen(data->pdata->fw_name);
+ if (len > MXT_NAME_MAX_LEN - 1) {
+ dev_err(dev, "Invalid firmware name\n");
+ return -EINVAL;
+ }
+ strlcpy(data->fw_name, data->pdata->fw_name, len + 1);
+ }
+ }
+
+ return 0;
+}
+
+static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
+{
+ int error;
+ u32 temp_val;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+
+ error = mxt_get_dt_coords(dev, "atmel,panel-coords", pdata);
+ if (error)
+ return error;
+
+ error = mxt_get_dt_coords(dev, "atmel,display-coords", pdata);
+ if (error)
+ return error;
+
+ pdata->cfg_name = MXT_GEN_CFG;
+ error = of_property_read_string(np, "atmel,cfg-name", &pdata->cfg_name);
+ if (error && (error != -EINVAL)) {
+ dev_err(dev, "Unable to read cfg name\n");
+ return error;
+ }
+
+ /* reset, irq gpio info */
+ pdata->gpio_reset = of_get_named_gpio_flags(np, "atmel,reset-gpio",
+ 0, &temp_val);
+ pdata->resetflags = temp_val;
+ pdata->gpio_irq = of_get_named_gpio_flags(np, "atmel,irq-gpio",
+ 0, &temp_val);
+ pdata->irqflags = temp_val;
+ pdata->gpio_i2cmode = of_get_named_gpio_flags(np, "atmel,i2cmode-gpio",
+ 0, &temp_val);
+
+ pdata->ignore_crc = of_property_read_bool(np, "atmel,ignore-crc");
+
+ error = of_property_read_u32(np, "atmel,bl-addr", &temp_val);
+ if (error && (error != -EINVAL))
+ dev_err(dev, "Unable to read bootloader address\n");
+ else if (error != -EINVAL)
+ pdata->bl_addr = (u8) temp_val;
+
+ /* keycodes for keyarray object */
+ prop = of_find_property(np, "atmel,key-codes", NULL);
+ if (prop) {
+ pdata->key_codes = devm_kzalloc(dev,
+ sizeof(int) * MXT_KEYARRAY_MAX_KEYS,
+ GFP_KERNEL);
+ if (!pdata->key_codes)
+ return -ENOMEM;
+ if ((prop->length/sizeof(u32)) == MXT_KEYARRAY_MAX_KEYS) {
+ error = of_property_read_u32_array(np,
+ "atmel,key-codes", pdata->key_codes,
+ MXT_KEYARRAY_MAX_KEYS);
+ if (error) {
+ dev_err(dev, "Unable to read key codes\n");
+ return error;
+ }
+ } else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#else
+static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
+{
+ return -ENODEV;
+}
+
+static int mxt_search_fw_name(struct mxt_data *data)
+{
+
+ return -ENODEV;
+}
+#endif
+
+static int mxt_initialize(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ int error;
+ bool alt_bootloader_addr = false;
+ bool retry = false;
+
+retry_info:
+ error = mxt_read_info_block(data);
+ if (error) {
+retry_bootloader:
+ error = mxt_probe_bootloader(data, alt_bootloader_addr);
+ if (error) {
+ if (alt_bootloader_addr) {
+ /* Chip is not in appmode or bootloader mode */
+ return error;
+ }
+
+ dev_info(&client->dev, "Trying alternate bootloader address\n");
+ alt_bootloader_addr = true;
+ goto retry_bootloader;
+ } else {
+ if (retry) {
+ dev_err(&client->dev,
+ "Could not recover device from "
+ "bootloader mode\n");
+ /* this is not an error state, we can reflash
+ * from here */
+ data->in_bootloader = true;
+ goto recover_bootloader;
+ }
+
+ /* Attempt to exit bootloader into app mode */
+ mxt_send_bootloader_cmd(data, false);
+ msleep(MXT_FW_RESET_TIME);
+ retry = true;
+ goto retry_info;
+ }
+ }
+
+ error = mxt_check_retrigen(data);
+ if (error)
+ return error;
+
+ error = mxt_acquire_irq(data);
+ if (error)
+ return error;
+
+ error = mxt_configure_objects(data);
+ if (error)
+ return error;
+
+recover_bootloader:
+ error = mxt_create_input_dev(data);
+ if (error) {
+ dev_err(&client->dev, "Failed to create input dev\n");
+ return error;
+ }
+
+ data->enable_reporting = true;
+
+ error = mxt_search_fw_name(data);
+ if (error)
+ dev_dbg(&client->dev, "firmware name search fail\n");
+
+ return 0;
+}
+
+/* Firmware Version is returned as Major.Minor.Build */
+static ssize_t mxt_fw_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n",
+ data->info->version >> 4, data->info->version & 0xf,
+ data->info->build);
+}
+
+/* Hardware Version is returned as FamilyID.VariantID */
+static ssize_t mxt_hw_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%u.%u\n",
+ data->info->family_id, data->info->variant_id);
+}
+
+/* Hardware Version is returned as FamilyID.VariantID */
+static ssize_t mxt_cfg_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%u.%u.%u\n",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2]);
+}
+
+static ssize_t mxt_show_instance(char *buf, int count,
+ struct mxt_object *object, int instance,
+ const u8 *val)
+{
+ int i;
+
+ if (mxt_obj_instances(object) > 1)
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "Instance %u\n", instance);
+
+ for (i = 0; i < mxt_obj_size(object); i++)
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "\t[%2u]: %02x (%d)\n", i, val[i], val[i]);
+ count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
+
+ return count;
+}
+
+static ssize_t mxt_object_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ struct mxt_object *object;
+ int count = 0;
+ int i, j;
+ int error;
+ u8 *obuf;
+
+ /* Pre-allocate buffer large enough to hold max sized object. */
+ obuf = kmalloc(256, GFP_KERNEL);
+ if (!obuf)
+ return -ENOMEM;
+
+ error = 0;
+ for (i = 0; i < data->info->object_num; i++) {
+ object = data->object_table + i;
+
+ if (!mxt_object_readable(object->type))
+ continue;
+
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "T%u:\n", object->type);
+
+ for (j = 0; j < mxt_obj_instances(object); j++) {
+ u16 size = mxt_obj_size(object);
+ u16 addr = object->start_address + j * size;
+
+ error = __mxt_read_reg(data->client, addr, size, obuf);
+ if (error)
+ goto done;
+
+ count = mxt_show_instance(buf, count, object, j, obuf);
+ }
+ }
+
+done:
+ kfree(obuf);
+ return error ?: count;
+}
+
+static int mxt_check_firmware_format(struct device *dev,
+ const struct firmware *fw)
+{
+ unsigned int pos = 0;
+ char c;
+
+ while (pos < fw->size) {
+ c = *(fw->data + pos);
+
+ if (c < '0' || (c > '9' && c < 'A') || c > 'F')
+ return 0;
+
+ pos++;
+ }
+
+ /* To convert file try
+ * xxd -r -p mXTXXX__APP_VX-X-XX.enc > maxtouch.fw */
+ dev_err(dev, "Aborting: firmware file must be in binary format\n");
+
+ return -1;
+}
+
+static int mxt_load_fw(struct device *dev)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ const struct firmware *fw = NULL;
+ unsigned int frame_size;
+ unsigned int pos = 0;
+ unsigned int retry = 0;
+ unsigned int frame = 0;
+ int ret;
+
+ ret = request_firmware(&fw, data->fw_name, dev);
+ if (ret) {
+ dev_err(dev, "Unable to open firmware %s\n", data->fw_name);
+ return ret;
+ }
+
+ /* Check for incorrect enc file */
+ ret = mxt_check_firmware_format(dev, fw);
+ if (ret)
+ goto release_firmware;
+
+ if (data->suspended) {
+ if (data->use_regulator)
+ mxt_regulator_enable(data);
+
+ enable_irq(data->irq);
+ data->suspended = false;
+ }
+
+ if (!data->in_bootloader) {
+ /* Change to the bootloader mode */
+ data->in_bootloader = true;
+
+ ret = mxt_t6_command(data, MXT_COMMAND_RESET,
+ MXT_BOOT_VALUE, false);
+ if (ret)
+ goto release_firmware;
+
+ msleep(MXT_RESET_TIME);
+
+ /* At this stage, do not need to scan since we know
+ * family ID */
+ ret = mxt_lookup_bootloader_address(data, 0);
+ if (ret)
+ goto release_firmware;
+ } else {
+ enable_irq(data->irq);
+ }
+
+ mxt_free_object_table(data);
+ reinit_completion(&data->bl_completion);
+
+ ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false);
+ if (ret) {
+ /* Bootloader may still be unlocked from previous update
+ * attempt */
+ ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, false);
+ if (ret)
+ goto disable_irq;
+ } else {
+ dev_info(dev, "Unlocking bootloader\n");
+
+ /* Unlock bootloader */
+ ret = mxt_send_bootloader_cmd(data, true);
+ if (ret)
+ goto disable_irq;
+ }
+
+ while (pos < fw->size) {
+ ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, true);
+ if (ret)
+ goto disable_irq;
+
+ frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+
+ /* Take account of CRC bytes */
+ frame_size += 2;
+
+ /* Write one frame to device */
+ ret = mxt_bootloader_write(data, fw->data + pos, frame_size);
+ if (ret)
+ goto disable_irq;
+
+ ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true);
+ if (ret) {
+ retry++;
+
+ /* Back off by 20ms per retry */
+ msleep(retry * 20);
+
+ if (retry > 20) {
+ dev_err(dev, "Retry count exceeded\n");
+ goto disable_irq;
+ }
+ } else {
+ retry = 0;
+ pos += frame_size;
+ frame++;
+ }
+
+ if (frame % 50 == 0)
+ dev_info(dev, "Sent %d frames, %d/%zd bytes\n",
+ frame, pos, fw->size);
+ }
+
+ /* Wait for flash. */
+ ret = mxt_wait_for_completion(data, &data->bl_completion,
+ MXT_FW_RESET_TIME);
+ if (ret)
+ goto disable_irq;
+
+ dev_info(dev, "Sent %d frames, %u bytes\n", frame, pos);
+
+ /* Wait for device to reset. Some bootloader versions do not assert
+ * the CHG line after bootloading has finished, so ignore error */
+ mxt_wait_for_completion(data, &data->bl_completion,
+ MXT_FW_RESET_TIME);
+
+ data->in_bootloader = false;
+
+disable_irq:
+ disable_irq(data->irq);
+release_firmware:
+ release_firmware(fw);
+ return ret;
+}
+
+static ssize_t mxt_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int error;
+
+ if (data->fw_name[0] == '\0') {
+ if (data->in_bootloader)
+ dev_info(dev, "Manual update needed\n");
+ else
+ dev_info(dev, "firmware is up-to-date\n");
+ return count;
+ }
+
+ error = mxt_load_fw(dev);
+ if (error) {
+ dev_err(dev, "The firmware update failed(%d)\n", error);
+ count = error;
+ } else {
+ dev_info(dev, "The firmware update succeeded\n");
+
+ msleep(MXT_FW_RESET_TIME);
+ data->suspended = false;
+
+ error = mxt_initialize(data);
+ if (error)
+ return error;
+
+ data->fw_w_no_cfg_update = true;
+ }
+
+ return count;
+}
+
+static int mxt_update_cfg(struct mxt_data *data, bool force)
+{
+ int ret;
+
+ if (data->in_bootloader) {
+ dev_err(&data->client->dev, "Not in appmode\n");
+ return -EINVAL;
+ }
+
+ data->enable_reporting = false;
+
+ if (data->suspended) {
+ if (data->use_regulator)
+ mxt_regulator_enable(data);
+
+ mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
+
+ mxt_acquire_irq(data);
+
+ data->suspended = false;
+ }
+
+ /* load config */
+ ret = mxt_load_cfg(data, force);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static ssize_t mxt_update_cfg_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ /* update config */
+ ret = mxt_update_cfg(data, false);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t mxt_force_update_cfg_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int ret;
+
+ /* update force config */
+ ret = mxt_update_cfg(data, true);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t mxt_debug_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ char c;
+
+ c = data->debug_enabled ? '1' : '0';
+ return scnprintf(buf, PAGE_SIZE, "%c\n", c);
+}
+
+static ssize_t mxt_debug_notify_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "0\n");
+}
+
+static ssize_t mxt_debug_v2_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int i;
+
+ if (sscanf(buf, "%u", &i) == 1 && i < 2) {
+ if (i == 1)
+ mxt_debug_msg_enable(data);
+ else
+ mxt_debug_msg_disable(data);
+
+ return count;
+ } else {
+ dev_dbg(dev, "debug_enabled write error\n");
+ return -EINVAL;
+ }
+}
+
+static ssize_t mxt_debug_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int i;
+
+ if (sscanf(buf, "%u", &i) == 1 && i < 2) {
+ data->debug_enabled = (i == 1);
+
+ dev_dbg(dev, "%s\n", i ? "debug enabled" : "debug disabled");
+ return count;
+ } else {
+ dev_dbg(dev, "debug_enabled write error\n");
+ return -EINVAL;
+ }
+}
+
+static int mxt_check_mem_access_params(struct mxt_data *data, loff_t off,
+ size_t *count)
+{
+ if (off >= data->mem_size)
+ return -EIO;
+
+ if (off + *count > data->mem_size)
+ *count = data->mem_size - off;
+
+ if (*count > MXT_MAX_BLOCK_WRITE)
+ *count = MXT_MAX_BLOCK_WRITE;
+
+ return 0;
+}
+
+static ssize_t mxt_mem_access_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int ret = 0;
+
+ ret = mxt_check_mem_access_params(data, off, &count);
+ if (ret < 0)
+ return ret;
+
+ if (count > 0)
+ ret = __mxt_read_reg(data->client, off, count, buf);
+
+ return ret == 0 ? count : ret;
+}
+
+static ssize_t mxt_mem_access_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off,
+ size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int ret = 0;
+
+ ret = mxt_check_mem_access_params(data, off, &count);
+ if (ret < 0)
+ return ret;
+
+ if (count > 0)
+ ret = __mxt_write_reg(data->client, off, count, buf);
+
+ return ret == 0 ? count : 0;
+}
+
+#if defined(CONFIG_SECURE_TOUCH)
+
+static int mxt_secure_touch_clk_prepare_enable(
+ struct mxt_data *data)
+{
+ int ret;
+ ret = clk_prepare_enable(data->iface_clk);
+ if (ret) {
+ dev_err(&data->client->dev,
+ "error on clk_prepare_enable(iface_clk):%d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(data->core_clk);
+ if (ret) {
+ clk_disable_unprepare(data->iface_clk);
+ dev_err(&data->client->dev,
+ "error clk_prepare_enable(core_clk):%d\n", ret);
+ }
+ return ret;
+}
+
+static void mxt_secure_touch_clk_disable_unprepare(
+ struct mxt_data *data)
+{
+ clk_disable_unprepare(data->core_clk);
+ clk_disable_unprepare(data->iface_clk);
+}
+
+static ssize_t mxt_secure_touch_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled));
+}
+/*
+ * Accept only "0" and "1" valid values.
+ * "0" will reset the st_enabled flag, then wake up the reading process.
+ * The bus driver is notified via pm_runtime that it is not required to stay
+ * awake anymore.
+ * It will also make sure the queue of events is emptied in the controller,
+ * in case a touch happened in between the secure touch being disabled and
+ * the local ISR being ungated.
+ * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
+ * The bus driver is requested via pm_runtime to stay awake.
+ */
+static ssize_t mxt_secure_touch_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ struct device *adapter = data->client->adapter->dev.parent;
+ unsigned long value;
+ int err = 0;
+
+ if (count > 2)
+ return -EINVAL;
+
+ err = kstrtoul(buf, 10, &value);
+ if (err != 0)
+ return err;
+
+ if (!data->st_initialized)
+ return -EIO;
+
+ err = count;
+
+ switch (value) {
+ case 0:
+ if (atomic_read(&data->st_enabled) == 0)
+ break;
+
+ mxt_secure_touch_clk_disable_unprepare(data);
+ pm_runtime_put_sync(adapter);
+ atomic_set(&data->st_enabled, 0);
+ mxt_secure_touch_notify(data);
+ mxt_interrupt(data->client->irq, data);
+ complete(&data->st_powerdown);
+ break;
+ case 1:
+ if (atomic_read(&data->st_enabled)) {
+ err = -EBUSY;
+ break;
+ }
+
+ if (pm_runtime_get_sync(adapter) < 0) {
+ dev_err(&data->client->dev, "pm_runtime_get failed\n");
+ err = -EIO;
+ break;
+ }
+
+ if (mxt_secure_touch_clk_prepare_enable(data) < 0) {
+ pm_runtime_put_sync(adapter);
+ err = -EIO;
+ break;
+ }
+ reinit_completion(&data->st_powerdown);
+ atomic_set(&data->st_enabled, 1);
+ synchronize_irq(data->client->irq);
+ atomic_set(&data->st_pending_irqs, 0);
+ break;
+ default:
+ dev_err(&data->client->dev, "unsupported value: %lu\n", value);
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static ssize_t mxt_secure_touch_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int val = 0;
+
+ if (atomic_read(&data->st_enabled) == 0)
+ return -EBADF;
+
+ if (atomic_cmpxchg(&data->st_pending_irqs, -1, 0) == -1)
+ return -EINVAL;
+
+ if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) == 1)
+ val = 1;
+
+ return scnprintf(buf, PAGE_SIZE, "%u", val);
+}
+
+static DEVICE_ATTR(secure_touch_enable, S_IRUGO | S_IWUSR | S_IWGRP ,
+ mxt_secure_touch_enable_show,
+ mxt_secure_touch_enable_store);
+static DEVICE_ATTR(secure_touch, S_IRUGO, mxt_secure_touch_show, NULL);
+#endif
+
+static ssize_t mxt_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ return snprintf(buf, MXT_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
+}
+
+static ssize_t mxt_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+
+ if (size > MXT_NAME_MAX_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(data->fw_name, buf, size);
+ if (data->fw_name[size-1] == '\n')
+ data->fw_name[size-1] = 0;
+
+ return size;
+}
+
+static ssize_t mxt_cfg_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ return snprintf(buf, MXT_NAME_MAX_LEN - 1, "%s\n", data->cfg_name);
+}
+
+static ssize_t mxt_cfg_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+
+ if (size > MXT_NAME_MAX_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(data->cfg_name, buf, size);
+ if (data->cfg_name[size-1] == '\n')
+ data->cfg_name[size-1] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(fw_name, S_IWUSR | S_IRUSR,
+ mxt_fw_name_show, mxt_fw_name_store);
+static DEVICE_ATTR(cfg_name, S_IWUSR | S_IRUSR,
+ mxt_cfg_name_show, mxt_cfg_name_store);
+static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
+static DEVICE_ATTR(cfg_version, S_IRUGO, mxt_cfg_version_show, NULL);
+static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
+static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+static DEVICE_ATTR(update_cfg, S_IWUSR, NULL, mxt_update_cfg_store);
+static DEVICE_ATTR(force_update_cfg, S_IWUSR, NULL, mxt_force_update_cfg_store);
+static DEVICE_ATTR(debug_v2_enable, S_IWUSR | S_IRUSR, NULL, mxt_debug_v2_enable_store);
+static DEVICE_ATTR(debug_notify, S_IRUGO, mxt_debug_notify_show, NULL);
+static DEVICE_ATTR(debug_enable, S_IWUSR | S_IRUSR, mxt_debug_enable_show,
+ mxt_debug_enable_store);
+
+static struct attribute *mxt_attrs[] = {
+ &dev_attr_fw_name.attr,
+ &dev_attr_cfg_name.attr,
+ &dev_attr_fw_version.attr,
+ &dev_attr_hw_version.attr,
+ &dev_attr_cfg_version.attr,
+ &dev_attr_object.attr,
+ &dev_attr_update_fw.attr,
+ &dev_attr_update_cfg.attr,
+ &dev_attr_force_update_cfg.attr,
+ &dev_attr_debug_enable.attr,
+ &dev_attr_debug_v2_enable.attr,
+ &dev_attr_debug_notify.attr,
+#if defined(CONFIG_SECURE_TOUCH)
+ &dev_attr_secure_touch_enable.attr,
+ &dev_attr_secure_touch.attr,
+#endif
+ NULL
+};
+
+static const struct attribute_group mxt_attr_group = {
+ .attrs = mxt_attrs,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int mxt_suspend(struct device *dev)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ struct input_dev *input_dev = data->input_dev;
+
+ mutex_lock(&input_dev->mutex);
+
+ if (input_dev->users)
+ mxt_stop(data);
+
+ mutex_unlock(&input_dev->mutex);
+
+ return 0;
+}
+
+static int mxt_resume(struct device *dev)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ struct input_dev *input_dev = data->input_dev;
+
+ mxt_secure_touch_stop(data, 1);
+
+ mutex_lock(&input_dev->mutex);
+
+ if (input_dev->users)
+ mxt_start(data);
+
+ mutex_unlock(&input_dev->mutex);
+
+ return 0;
+}
+
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct mxt_data *mxt_dev_data =
+ container_of(self, struct mxt_data, fb_notif);
+
+ if (evdata && evdata->data && mxt_dev_data && mxt_dev_data->client) {
+ if (event == FB_EARLY_EVENT_BLANK)
+ mxt_secure_touch_stop(mxt_dev_data, 0);
+ else if (event == FB_EVENT_BLANK) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ mxt_resume(&mxt_dev_data->client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ mxt_suspend(&mxt_dev_data->client->dev);
+ }
+ }
+
+ return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void mxt_early_suspend(struct early_suspend *h)
+{
+ struct mxt_data *data = container_of(h, struct mxt_data,
+ early_suspend);
+ mxt_suspend(&data->client->dev);
+}
+
+static void mxt_late_resume(struct early_suspend *h)
+{
+ struct mxt_data *data = container_of(h, struct mxt_data,
+ early_suspend);
+ mxt_resume(&data->client->dev);
+}
+#endif
+
+static const struct dev_pm_ops mxt_pm_ops = {
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
+ .suspend = mxt_suspend,
+ .resume = mxt_resume,
+#endif
+};
+#endif
+
+#if defined(CONFIG_SECURE_TOUCH)
+static void mxt_secure_touch_init(struct mxt_data *data)
+{
+ int ret = 0;
+ data->st_initialized = 0;
+ init_completion(&data->st_powerdown);
+ /* Get clocks */
+ data->core_clk = clk_get(&data->client->dev, "core_clk");
+ if (IS_ERR(data->core_clk)) {
+ ret = PTR_ERR(data->core_clk);
+ dev_err(&data->client->dev,
+ "%s: error on clk_get(core_clk):%d\n", __func__, ret);
+ return;
+ }
+
+ data->iface_clk = clk_get(&data->client->dev, "iface_clk");
+ if (IS_ERR(data->iface_clk)) {
+ ret = PTR_ERR(data->iface_clk);
+ dev_err(&data->client->dev,
+ "%s: error on clk_get(iface_clk):%d\n", __func__, ret);
+ goto err_iface_clk;
+ }
+
+ data->st_initialized = 1;
+ return;
+
+err_iface_clk:
+ clk_put(data->core_clk);
+ data->core_clk = NULL;
+}
+#else
+static void mxt_secure_touch_init(struct mxt_data *data)
+{
+}
+#endif
+
+static int mxt_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct mxt_data *data;
+ struct mxt_platform_data *pdata;
+ int error, len;
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct mxt_platform_data), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ error = mxt_parse_dt(&client->dev, pdata);
+ if (error)
+ return error;
+ } else
+ pdata = client->dev.platform_data;
+
+ if (!pdata)
+ return -EINVAL;
+
+ data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
+ client->adapter->nr, client->addr);
+
+ data->client = client;
+ data->irq = client->irq;
+ data->pdata = pdata;
+ i2c_set_clientdata(client, data);
+
+ init_completion(&data->bl_completion);
+ init_completion(&data->reset_completion);
+ init_completion(&data->crc_completion);
+ mutex_init(&data->debug_msg_lock);
+
+ if (data->pdata->cfg_name) {
+ len = strlen(data->pdata->cfg_name);
+ if (len > MXT_NAME_MAX_LEN - 1) {
+ dev_err(&client->dev, "Invalid config name\n");
+ error = -EINVAL;
+ goto err_destroy_mutex;
+ }
+
+ strlcpy(data->cfg_name, data->pdata->cfg_name, len + 1);
+ }
+
+ error = mxt_pinctrl_init(data);
+ if (error)
+ dev_info(&client->dev, "No pinctrl support\n");
+
+ error = mxt_gpio_enable(data, true);
+ if (error) {
+ dev_err(&client->dev, "Failed to configure gpios\n");
+ goto err_destroy_mutex;
+ }
+ data->irq = data->client->irq =
+ gpio_to_irq(data->pdata->gpio_irq);
+
+ error = mxt_regulator_configure(data, true);
+ if (error) {
+ dev_err(&client->dev, "Failed to probe regulators\n");
+ goto err_free_gpios;
+ }
+
+ error = mxt_regulator_enable(data);
+ if (error) {
+ dev_err(&client->dev, "Error %d enabling regulators\n", error);
+ goto err_put_regs;
+ }
+
+ error = mxt_initialize(data);
+ if (error)
+ goto err_free_regs;
+
+ error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
+ if (error) {
+ dev_err(&client->dev, "Failure %d creating sysfs group\n",
+ error);
+ goto err_free_object;
+ }
+
+ sysfs_bin_attr_init(&data->mem_access_attr);
+ data->mem_access_attr.attr.name = "mem_access";
+ data->mem_access_attr.attr.mode = S_IRUGO | S_IWUSR;
+ data->mem_access_attr.read = mxt_mem_access_read;
+ data->mem_access_attr.write = mxt_mem_access_write;
+ data->mem_access_attr.size = data->mem_size;
+
+ if (sysfs_create_bin_file(&client->dev.kobj,
+ &data->mem_access_attr) < 0) {
+ dev_err(&client->dev, "Failed to create %s\n",
+ data->mem_access_attr.attr.name);
+ goto err_remove_sysfs_group;
+ }
+
+ error = request_threaded_irq(data->irq, NULL, mxt_interrupt,
+ data->pdata->irqflags | IRQF_ONESHOT,
+ client->name, data);
+ if (error) {
+ dev_err(&client->dev, "Failed to register interrupt\n");
+ goto err_remove_sysfs_group;
+ }
+
+#if defined(CONFIG_FB)
+ data->fb_notif.notifier_call = fb_notifier_callback;
+
+ error = fb_register_client(&data->fb_notif);
+
+ if (error) {
+ dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
+ error);
+ goto err_free_irq;
+ }
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ MXT_SUSPEND_LEVEL;
+ data->early_suspend.suspend = mxt_early_suspend;
+ data->early_suspend.resume = mxt_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+
+ mxt_secure_touch_init(data);
+
+ return 0;
+
+err_free_irq:
+ free_irq(data->irq, data);
+err_remove_sysfs_group:
+ sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+err_free_object:
+ mxt_free_object_table(data);
+err_put_regs:
+ mxt_regulator_configure(data, false);
+err_free_regs:
+ mxt_regulator_disable(data);
+err_free_gpios:
+ mxt_gpio_enable(data, false);
+err_destroy_mutex:
+ mutex_destroy(&data->debug_msg_lock);
+ return error;
+}
+
+static int mxt_remove(struct i2c_client *client)
+{
+ struct mxt_data *data = i2c_get_clientdata(client);
+
+ if (data->mem_access_attr.attr.name)
+ sysfs_remove_bin_file(&client->dev.kobj,
+ &data->mem_access_attr);
+
+#if defined(CONFIG_FB)
+ fb_unregister_client(&data->fb_notif);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&data->early_suspend);
+#endif
+ sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+ free_irq(data->irq, data);
+ mxt_regulator_configure(data, false);
+ mxt_regulator_disable(data);
+ if (!IS_ERR(data->reg_xvdd))
+ regulator_put(data->reg_xvdd);
+ regulator_put(data->reg_avdd);
+ regulator_put(data->reg_vdd);
+ mxt_free_object_table(data);
+ if (!dev_get_platdata(&data->client->dev))
+ kfree(data->pdata);
+ kfree(data);
+
+ return 0;
+}
+
+static void mxt_shutdown(struct i2c_client *client)
+{
+ struct mxt_data *data = i2c_get_clientdata(client);
+
+ disable_irq(data->irq);
+}
+
+static const struct i2c_device_id mxt_id[] = {
+ { "qt602240_ts", 0 },
+ { "atmel_mxt_ts", 0 },
+ { "atmel_maxtouch_ts", 0 },
+ { "atmel_mxt_tp", 0 },
+ { "mXT224", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mxt_id);
+#ifdef CONFIG_OF
+static struct of_device_id mxt_match_table[] = {
+ { .compatible = "atmel,maxtouch-ts",},
+ { },
+};
+#else
+#define mxt_match_table NULL
+#endif
+
+static struct i2c_driver mxt_driver = {
+ .driver = {
+ .name = "atmel_maxtouch_ts",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM_SLEEP
+ .pm = &mxt_pm_ops,
+#endif
+ .of_match_table = mxt_match_table,
+ },
+ .probe = mxt_probe,
+ .remove = mxt_remove,
+ .shutdown = mxt_shutdown,
+ .id_table = mxt_id,
+};
+
+static int __init mxt_init(void)
+{
+ return i2c_add_driver(&mxt_driver);
+}
+
+static void __exit mxt_exit(void)
+{
+ i2c_del_driver(&mxt_driver);
+}
+
+late_initcall(mxt_init);
+module_exit(mxt_exit);
+
+/* Module information */
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
new file mode 100644
index 000000000000..fc4bc283ccaf
--- /dev/null
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -0,0 +1,2781 @@
+/*
+ *
+ * FocalTech ft5x06 TouchScreen driver.
+ *
+ * Copyright (c) 2010 Focal tech Ltd.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
+#include <linux/debugfs.h>
+#include <linux/input/ft5x06_ts.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+/* Early-suspend level */
+#define FT_SUSPEND_LEVEL 1
+#endif
+
+#if defined(CONFIG_FT_SECURE_TOUCH)
+#include <linux/completion.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+static irqreturn_t ft5x06_ts_interrupt(int irq, void *data);
+#endif
+
+#define FT_DRIVER_VERSION 0x02
+
+#define FT_META_REGS 3
+#define FT_ONE_TCH_LEN 6
+#define FT_TCH_LEN(x) (FT_META_REGS + FT_ONE_TCH_LEN * x)
+
+#define FT_PRESS 0x7F
+#define FT_MAX_ID 0x0F
+#define FT_TOUCH_X_H_POS 3
+#define FT_TOUCH_X_L_POS 4
+#define FT_TOUCH_Y_H_POS 5
+#define FT_TOUCH_Y_L_POS 6
+#define FT_TD_STATUS 2
+#define FT_TOUCH_EVENT_POS 3
+#define FT_TOUCH_ID_POS 5
+#define FT_TOUCH_DOWN 0
+#define FT_TOUCH_CONTACT 2
+
+/* register address*/
+#define FT_REG_DEV_MODE 0x00
+#define FT_DEV_MODE_REG_CAL 0x02
+#define FT_REG_ID 0xA3
+#define FT_REG_PMODE 0xA5
+#define FT_REG_FW_VER 0xA6
+#define FT_REG_FW_VENDOR_ID 0xA8
+#define FT_REG_POINT_RATE 0x88
+#define FT_REG_THGROUP 0x80
+#define FT_REG_ECC 0xCC
+#define FT_REG_RESET_FW 0x07
+#define FT_REG_FW_MIN_VER 0xB2
+#define FT_REG_FW_SUB_MIN_VER 0xB3
+
+/* gesture register address*/
+#define FT_REG_GESTURE_ENABLE 0xD0
+#define FT_REG_GESTURE_OUTPUT 0xD3
+
+/* gesture register bits*/
+#define FT_GESTURE_DOUBLECLICK_COORD_X 100
+#define FT_GESTURE_DOUBLECLICK_COORD_Y 100
+#define FT_GESTURE_WAKEUP_TIMEOUT 500
+#define FT_GESTURE_DEFAULT_TRACKING_ID 0x0A
+#define FT_GESTURE_DOUBLECLICK_ID 0x24
+#define FT_GESTURE_POINTER_NUM_MAX 128
+#define FT_GESTURE_POINTER_SIZEOF 4
+#define FT_GESTURE_ID_FLAG_SIZE 1
+#define FT_GESTURE_POINTER_NUM_FLAG_SIZE 1
+/* 6 bytes are taken to mark which gesture is supported in firmware */
+#define FT_GESTURE_SET_FLAG_SIZE 6
+#define I2C_TRANSFER_MAX_BYTE 255
+#define FT_GESTURE_DATA_HEADER (FT_GESTURE_ID_FLAG_SIZE + \
+ FT_GESTURE_POINTER_NUM_FLAG_SIZE + \
+ FT_GESTURE_SET_FLAG_SIZE)
+
+/* power register bits*/
+#define FT_PMODE_ACTIVE 0x00
+#define FT_PMODE_MONITOR 0x01
+#define FT_PMODE_STANDBY 0x02
+#define FT_PMODE_HIBERNATE 0x03
+#define FT_FACTORYMODE_VALUE 0x40
+#define FT_WORKMODE_VALUE 0x00
+#define FT_RST_CMD_REG1 0xFC
+#define FT_RST_CMD_REG2 0xBC
+#define FT_READ_ID_REG 0x90
+#define FT_ERASE_APP_REG 0x61
+#define FT_ERASE_PANEL_REG 0x63
+#define FT_FW_START_REG 0xBF
+
+#define FT_STATUS_NUM_TP_MASK 0x0F
+
+#define FT_VTG_MIN_UV 2600000
+#define FT_VTG_MAX_UV 3300000
+#define FT_I2C_VTG_MIN_UV 1800000
+#define FT_I2C_VTG_MAX_UV 1800000
+
+#define FT_COORDS_ARR_SIZE 4
+#define MAX_BUTTONS 4
+
+#define FT_8BIT_SHIFT 8
+#define FT_4BIT_SHIFT 4
+#define FT_FW_NAME_MAX_LEN 50
+
+#define FT5316_ID 0x0A
+#define FT5306I_ID 0x55
+#define FT6X06_ID 0x06
+#define FT6X36_ID 0x36
+
+#define FT_UPGRADE_AA 0xAA
+#define FT_UPGRADE_55 0x55
+
+#define FT_FW_MIN_SIZE 8
+#define FT_FW_MAX_SIZE 32768
+
+/* Firmware file is not supporting minor and sub minor so use 0 */
+#define FT_FW_FILE_MAJ_VER(x) ((x)->data[(x)->size - 2])
+#define FT_FW_FILE_MIN_VER(x) 0
+#define FT_FW_FILE_SUB_MIN_VER(x) 0
+#define FT_FW_FILE_VENDOR_ID(x) ((x)->data[(x)->size - 1])
+
+#define FT_FW_FILE_MAJ_VER_FT6X36(x) ((x)->data[0x10a])
+#define FT_FW_FILE_VENDOR_ID_FT6X36(x) ((x)->data[0x108])
+
+/**
+* Application data verification will be run before upgrade flow.
+* Firmware image stores some flags with negative and positive value
+* in corresponding addresses, we need pick them out do some check to
+* make sure the application data is valid.
+*/
+#define FT_FW_CHECK(x, ts_data) \
+ (ts_data->family_id == FT6X36_ID ? \
+ (((x)->data[0x104] ^ (x)->data[0x105]) == 0xFF \
+ && ((x)->data[0x106] ^ (x)->data[0x107]) == 0xFF) : \
+ (((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \
+ && ((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \
+ && ((x)->data[(x)->size - 3] ^ (x)->data[(x)->size - 4]) == 0xFF))
+
+#define FT_MAX_TRIES 5
+#define FT_RETRY_DLY 20
+
+#define FT_MAX_WR_BUF 10
+#define FT_MAX_RD_BUF 2
+#define FT_FW_PKT_LEN 128
+#define FT_FW_PKT_META_LEN 6
+#define FT_FW_PKT_DLY_MS 20
+#define FT_FW_LAST_PKT 0x6ffa
+#define FT_EARSE_DLY_MS 100
+#define FT_55_AA_DLY_NS 5000
+
+#define FT_UPGRADE_LOOP 30
+#define FT_CAL_START 0x04
+#define FT_CAL_FIN 0x00
+#define FT_CAL_STORE 0x05
+#define FT_CAL_RETRY 100
+#define FT_REG_CAL 0x00
+#define FT_CAL_MASK 0x70
+
+#define FT_INFO_MAX_LEN 512
+
+#define FT_BLOADER_SIZE_OFF 12
+#define FT_BLOADER_NEW_SIZE 30
+#define FT_DATA_LEN_OFF_OLD_FW 8
+#define FT_DATA_LEN_OFF_NEW_FW 14
+#define FT_FINISHING_PKT_LEN_OLD_FW 6
+#define FT_FINISHING_PKT_LEN_NEW_FW 12
+#define FT_MAGIC_BLOADER_Z7 0x7bfa
+#define FT_MAGIC_BLOADER_LZ4 0x6ffa
+#define FT_MAGIC_BLOADER_GZF_30 0x7ff4
+#define FT_MAGIC_BLOADER_GZF 0x7bf4
+
+#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE "pmx_ts_release"
+
+static irqreturn_t ft5x06_ts_interrupt(int irq, void *data);
+
+enum {
+ FT_BLOADER_VERSION_LZ4 = 0,
+ FT_BLOADER_VERSION_Z7 = 1,
+ FT_BLOADER_VERSION_GZF = 2,
+};
+
+enum {
+ FT_FT5336_FAMILY_ID_0x11 = 0x11,
+ FT_FT5336_FAMILY_ID_0x12 = 0x12,
+ FT_FT5336_FAMILY_ID_0x13 = 0x13,
+ FT_FT5336_FAMILY_ID_0x14 = 0x14,
+};
+
+#define FT_STORE_TS_INFO(buf, id, fw_maj, fw_min, fw_sub_min) \
+ snprintf(buf, FT_INFO_MAX_LEN, \
+ "vendor name = Focaltech\n" \
+ "model = 0x%x\n" \
+ "fw_version = %d.%d.%d\n", \
+ id, fw_maj, fw_min, fw_sub_min)
+#define FT_TS_INFO_SYSFS_DIR_NAME "ts_info"
+static char *ts_info_buff;
+
+#define FT_STORE_TS_DBG_INFO(buf, id, name, max_tch, group_id, \
+ fw_vkey_support, fw_name, fw_maj, fw_min, fw_sub_min) \
+ snprintf(buf, FT_INFO_MAX_LEN, \
+ "controller\t= focaltech\n" \
+ "model\t\t= 0x%x\n" \
+ "name\t\t= %s\n" \
+ "max_touches\t= %d\n" \
+ "drv_ver\t\t= 0x%x\n" \
+ "group_id\t= 0x%x\n" \
+ "fw_vkey_support\t= %s\n" \
+ "fw_name\t\t= %s\n" \
+ "fw_ver\t\t= %d.%d.%d\n", id, name, \
+ max_tch, FT_DRIVER_VERSION, group_id, \
+ fw_vkey_support, fw_name, fw_maj, fw_min, \
+ fw_sub_min)
+
+#define FT_DEBUG_DIR_NAME "ts_debug"
+
+struct ft5x06_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ const struct ft5x06_ts_platform_data *pdata;
+ struct ft5x06_gesture_platform_data *gesture_pdata;
+ struct regulator *vdd;
+ struct regulator *vcc_i2c;
+ struct mutex ft_clk_io_ctrl_mutex;
+ char fw_name[FT_FW_NAME_MAX_LEN];
+ bool loading_fw;
+ u8 family_id;
+ struct dentry *dir;
+ u16 addr;
+ bool suspended;
+ char *ts_info;
+ u8 *tch_data;
+ u32 tch_data_len;
+ u8 fw_ver[3];
+ u8 fw_vendor_id;
+ struct kobject *ts_info_kobj;
+#if defined(CONFIG_FB)
+ struct work_struct fb_notify_work;
+ struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+ struct pinctrl *ts_pinctrl;
+ struct pinctrl_state *pinctrl_state_active;
+ struct pinctrl_state *pinctrl_state_suspend;
+ struct pinctrl_state *pinctrl_state_release;
+#if defined(CONFIG_FT_SECURE_TOUCH)
+ atomic_t st_enabled;
+ atomic_t st_pending_irqs;
+ struct completion st_powerdown;
+ struct completion st_irq_processed;
+ bool st_initialized;
+ struct clk *core_clk;
+ struct clk *iface_clk;
+#endif
+};
+
+static int ft5x06_ts_start(struct device *dev);
+static int ft5x06_ts_stop(struct device *dev);
+
+#if defined(CONFIG_FT_SECURE_TOUCH)
+static void ft5x06_secure_touch_init(struct ft5x06_ts_data *data)
+{
+ data->st_initialized = 0;
+
+ init_completion(&data->st_powerdown);
+ init_completion(&data->st_irq_processed);
+
+ /* Get clocks */
+ data->core_clk = devm_clk_get(&data->client->dev, "core_clk");
+ if (IS_ERR(data->core_clk)) {
+ data->core_clk = NULL;
+ dev_warn(&data->client->dev,
+ "%s: core_clk is not defined\n", __func__);
+ }
+
+ data->iface_clk = devm_clk_get(&data->client->dev, "iface_clk");
+ if (IS_ERR(data->iface_clk)) {
+ data->iface_clk = NULL;
+ dev_warn(&data->client->dev,
+ "%s: iface_clk is not defined", __func__);
+ }
+ data->st_initialized = 1;
+}
+
+static void ft5x06_secure_touch_notify(struct ft5x06_ts_data *data)
+{
+ sysfs_notify(&data->input_dev->dev.kobj, NULL, "secure_touch");
+}
+
+static irqreturn_t ft5x06_filter_interrupt(struct ft5x06_ts_data *data)
+{
+ if (atomic_read(&data->st_enabled)) {
+ if (atomic_cmpxchg(&data->st_pending_irqs, 0, 1) == 0) {
+ reinit_completion(&data->st_irq_processed);
+ ft5x06_secure_touch_notify(data);
+ wait_for_completion_interruptible(
+ &data->st_irq_processed);
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+/*
+ * 'blocking' variable will have value 'true' when we want to prevent the driver
+ * from accessing the xPU/SMMU protected HW resources while the session is
+ * active.
+ */
+static void ft5x06_secure_touch_stop(struct ft5x06_ts_data *data, bool blocking)
+{
+ if (atomic_read(&data->st_enabled)) {
+ atomic_set(&data->st_pending_irqs, -1);
+ ft5x06_secure_touch_notify(data);
+ if (blocking)
+ wait_for_completion_interruptible(
+ &data->st_powerdown);
+ }
+}
+
+static int ft5x06_clk_prepare_enable(struct ft5x06_ts_data *data)
+{
+ int ret;
+
+ ret = clk_prepare_enable(data->iface_clk);
+ if (ret) {
+ dev_err(&data->client->dev,
+ "error on clk_prepare_enable(iface_clk):%d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(data->core_clk);
+ if (ret) {
+ clk_disable_unprepare(data->iface_clk);
+ dev_err(&data->client->dev,
+ "error clk_prepare_enable(core_clk):%d\n", ret);
+ }
+ return ret;
+}
+
+static void ft5x06_clk_disable_unprepare(struct ft5x06_ts_data *data)
+{
+ clk_disable_unprepare(data->core_clk);
+ clk_disable_unprepare(data->iface_clk);
+}
+
+static int ft5x06_bus_get(struct ft5x06_ts_data *data)
+{
+ int retval;
+
+ mutex_lock(&data->ft_clk_io_ctrl_mutex);
+ retval = pm_runtime_get_sync(data->client->adapter->dev.parent);
+ if (retval >= 0 && data->core_clk != NULL && data->iface_clk != NULL) {
+ retval = ft5x06_clk_prepare_enable(data);
+ if (retval)
+ pm_runtime_put_sync(data->client->adapter->dev.parent);
+ }
+ mutex_unlock(&data->ft_clk_io_ctrl_mutex);
+ return retval;
+}
+
+static void ft5x06_bus_put(struct ft5x06_ts_data *data)
+{
+ mutex_lock(&data->ft_clk_io_ctrl_mutex);
+ if (data->core_clk != NULL && data->iface_clk != NULL)
+ ft5x06_clk_disable_unprepare(data);
+ pm_runtime_put_sync(data->client->adapter->dev.parent);
+ mutex_unlock(&data->ft_clk_io_ctrl_mutex);
+}
+
+static ssize_t ft5x06_secure_touch_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled));
+}
+
+/*
+ * Accept only "0" and "1" valid values.
+ * "0" will reset the st_enabled flag, then wake up the reading process and
+ * the interrupt handler.
+ * The bus driver is notified via pm_runtime that it is not required to stay
+ * awake anymore.
+ * It will also make sure the queue of events is emptied in the controller,
+ * in case a touch happened in between the secure touch being disabled and
+ * the local ISR being ungated.
+ * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
+ * The bus driver is requested via pm_runtime to stay awake.
+ */
+static ssize_t ft5x06_secure_touch_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long value;
+ int err = 0;
+
+ if (count > 2)
+ return -EINVAL;
+ err = kstrtoul(buf, 10, &value);
+ if (err != 0)
+ return err;
+
+ if (!data->st_initialized)
+ return -EIO;
+
+ err = count;
+ switch (value) {
+ case 0:
+ if (atomic_read(&data->st_enabled) == 0)
+ break;
+ ft5x06_bus_put(data);
+ atomic_set(&data->st_enabled, 0);
+ ft5x06_secure_touch_notify(data);
+ complete(&data->st_irq_processed);
+ ft5x06_ts_interrupt(data->client->irq, data);
+ complete(&data->st_powerdown);
+ break;
+
+ case 1:
+ if (atomic_read(&data->st_enabled)) {
+ err = -EBUSY;
+ break;
+ }
+ synchronize_irq(data->client->irq);
+ if (ft5x06_bus_get(data) < 0) {
+ dev_err(&data->client->dev, "ft5x06_bus_get failed\n");
+ err = -EIO;
+ break;
+ }
+ reinit_completion(&data->st_powerdown);
+ reinit_completion(&data->st_irq_processed);
+ atomic_set(&data->st_enabled, 1);
+ atomic_set(&data->st_pending_irqs, 0);
+ break;
+
+ default:
+ dev_err(&data->client->dev, "unsupported value: %lu\n", value);
+ err = -EINVAL;
+ break;
+ }
+ return err;
+}
+
+/*
+ * This function returns whether there are pending interrupts, or
+ * other error conditions that need to be signaled to the userspace library,
+ * according tot he following logic:
+ * - st_enabled is 0 if secure touch is not enabled, returning -EBADF
+ * - st_pending_irqs is -1 to signal that secure touch is in being stopped,
+ * returning -EINVAL
+ * - st_pending_irqs is 1 to signal that there is a pending irq, returning
+ * the value "1" to the sysfs read operation
+ * - st_pending_irqs is 0 (only remaining case left) if the pending interrupt
+ * has been processed, so the interrupt handler can be allowed to continue.
+ */
+static ssize_t ft5x06_secure_touch_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ int val = 0;
+
+ if (atomic_read(&data->st_enabled) == 0)
+ return -EBADF;
+ if (atomic_cmpxchg(&data->st_pending_irqs, -1, 0) == -1)
+ return -EINVAL;
+ if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) == 1)
+ val = 1;
+ else
+ complete(&data->st_irq_processed);
+ return scnprintf(buf, PAGE_SIZE, "%u", val);
+}
+#else
+static void ft5x06_secure_touch_init(struct ft5x06_ts_data *data)
+{
+}
+static irqreturn_t ft5x06_filter_interrupt(struct ft5x06_ts_data *data)
+{
+ return IRQ_NONE;
+}
+static void ft5x06_secure_touch_stop(struct ft5x06_ts_data *data, bool blocking)
+{
+}
+#endif
+
+static struct device_attribute attrs[] = {
+#if defined(CONFIG_FT_SECURE_TOUCH)
+ __ATTR(secure_touch_enable, (S_IRUGO | S_IWUSR | S_IWGRP),
+ ft5x06_secure_touch_enable_show,
+ ft5x06_secure_touch_enable_store),
+ __ATTR(secure_touch, S_IRUGO,
+ ft5x06_secure_touch_show, NULL),
+#endif
+};
+
+static inline bool ft5x06_gesture_support_enabled(void)
+{
+ return config_enabled(CONFIG_TOUCHSCREEN_FT5X06_GESTURE);
+}
+
+static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
+ int writelen, char *readbuf, int readlen)
+{
+ int ret;
+
+ if (writelen > 0) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: i2c read error.\n",
+ __func__);
+ } else {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0)
+ dev_err(&client->dev, "%s:i2c read error.\n", __func__);
+ }
+ return ret;
+}
+
+static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
+ int writelen)
+{
+ int ret;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: i2c write error.\n", __func__);
+
+ return ret;
+}
+
+static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val)
+{
+ u8 buf[2] = {0};
+
+ buf[0] = addr;
+ buf[1] = val;
+
+ return ft5x06_i2c_write(client, buf, sizeof(buf));
+}
+
+static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val)
+{
+ return ft5x06_i2c_read(client, &addr, 1, val, 1);
+}
+
+#ifdef CONFIG_TOUCHSCREEN_FT5X06_GESTURE
+static ssize_t ft5x06_gesture_enable_to_set_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ data->gesture_pdata->gesture_enable_to_set);
+}
+
+static ssize_t ft5x06_gesture_enable_to_set_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long value = 0;
+ int ret;
+
+ if (data->suspended)
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 16, &value);
+ if (ret < 0) {
+ dev_err(dev, "%s:kstrtoul failed, ret=0x%x\n",
+ __func__, ret);
+ return ret;
+ }
+
+ if (value == 1)
+ data->gesture_pdata->gesture_enable_to_set = 1;
+ else
+ data->gesture_pdata->gesture_enable_to_set = 0;
+ return size;
+}
+
+static DEVICE_ATTR(enable, 0664,
+ ft5x06_gesture_enable_to_set_show,
+ ft5x06_gesture_enable_to_set_store);
+
+static int ft5x06_entry_pocket(struct device *dev)
+{
+ return ft5x06_ts_stop(dev);
+}
+
+static int ft5x06_leave_pocket(struct device *dev)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ int err;
+
+ ft5x06_ts_start(dev);
+ ft5x0x_write_reg(data->client, FT_REG_GESTURE_ENABLE, 1);
+ err = enable_irq_wake(data->client->irq);
+ if (err)
+ dev_err(&data->client->dev,
+ "%s: set_irq_wake failed\n", __func__);
+ data->suspended = true;
+
+ return err;
+}
+
+static ssize_t gesture_in_pocket_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ data->gesture_pdata->in_pocket);
+}
+
+static ssize_t gesture_in_pocket_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long value = 0;
+ int ret;
+
+ ret = kstrtoul(buf, 16, &value);
+ if (ret < 0) {
+ dev_err(dev, "%s:kstrtoul failed, ret=0x%x\n",
+ __func__, ret);
+ return ret;
+ }
+
+ if (value == 1 && data->gesture_pdata->in_pocket == 0) {
+ data->gesture_pdata->in_pocket = 1;
+ ft5x06_entry_pocket(dev);
+ } else if (value == 0 && data->gesture_pdata->in_pocket == 1) {
+ ft5x06_leave_pocket(dev);
+ data->gesture_pdata->in_pocket = 0;
+ }
+ return size;
+}
+
+static DEVICE_ATTR(pocket, 0664,
+ gesture_in_pocket_mode_show,
+ gesture_in_pocket_mode_store);
+
+static int ft5x06_report_gesture_doubleclick(struct input_dev *ip_dev)
+{
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ input_mt_slot(ip_dev, FT_GESTURE_DEFAULT_TRACKING_ID);
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
+ input_report_abs(ip_dev, ABS_MT_POSITION_X,
+ FT_GESTURE_DOUBLECLICK_COORD_X);
+ input_report_abs(ip_dev, ABS_MT_POSITION_Y,
+ FT_GESTURE_DOUBLECLICK_COORD_Y);
+ input_mt_report_pointer_emulation(ip_dev, false);
+ input_sync(ip_dev);
+ input_mt_slot(ip_dev, FT_GESTURE_DEFAULT_TRACKING_ID);
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
+ input_mt_report_pointer_emulation(ip_dev, false);
+ input_sync(ip_dev);
+ }
+ return 0;
+}
+
+static int ft5x06_report_gesture(struct i2c_client *i2c_client,
+ struct input_dev *ip_dev)
+{
+ int i, temp, gesture_data_size;
+ int gesture_coord_x, gesture_coord_y;
+ int ret = -1;
+ short pointnum = 0;
+ unsigned char buf[FT_GESTURE_POINTER_NUM_MAX *
+ FT_GESTURE_POINTER_SIZEOF + FT_GESTURE_DATA_HEADER];
+
+ buf[0] = FT_REG_GESTURE_OUTPUT;
+ ret = ft5x06_i2c_read(i2c_client, buf, 1,
+ buf, FT_GESTURE_DATA_HEADER);
+ if (ret < 0) {
+ dev_err(&i2c_client->dev, "%s read touchdata failed.\n",
+ __func__);
+ return ret;
+ }
+
+ /* FW support doubleclick */
+ if (buf[0] == FT_GESTURE_DOUBLECLICK_ID) {
+ ft5x06_report_gesture_doubleclick(ip_dev);
+ return 0;
+ }
+
+ pointnum = (short)(buf[1]) & 0xff;
+ gesture_data_size = pointnum * FT_GESTURE_POINTER_SIZEOF +
+ FT_GESTURE_DATA_HEADER;
+ buf[0] = FT_REG_GESTURE_OUTPUT;
+ temp = gesture_data_size / I2C_TRANSFER_MAX_BYTE;
+ for (i = 0; i < temp; i++)
+ ret = ft5x06_i2c_read(i2c_client, buf, ((i == 0) ? 1 : 0),
+ buf + I2C_TRANSFER_MAX_BYTE * i, I2C_TRANSFER_MAX_BYTE);
+ ret = ft5x06_i2c_read(i2c_client, buf, ((temp == 0) ? 1 : 0),
+ buf + I2C_TRANSFER_MAX_BYTE * temp,
+ gesture_data_size - I2C_TRANSFER_MAX_BYTE * temp);
+ if (ret < 0) {
+ dev_err(&i2c_client->dev, "%s read touchdata failed.\n",
+ __func__);
+ return ret;
+ }
+
+ for (i = 0; i < pointnum; i++) {
+ gesture_coord_x = (((s16) buf[FT_GESTURE_DATA_HEADER +
+ (FT_GESTURE_POINTER_SIZEOF * i)]) & 0x0F) << 8 |
+ (((s16) buf[FT_GESTURE_DATA_HEADER + 1 +
+ (FT_GESTURE_POINTER_SIZEOF * i)]) & 0xFF);
+ gesture_coord_y = (((s16) buf[FT_GESTURE_DATA_HEADER + 2 +
+ (FT_GESTURE_POINTER_SIZEOF * i)]) & 0x0F) << 8 |
+ (((s16) buf[FT_GESTURE_DATA_HEADER + 3 +
+ (FT_GESTURE_POINTER_SIZEOF * i)]) & 0xFF);
+ input_mt_slot(ip_dev, FT_GESTURE_DEFAULT_TRACKING_ID);
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
+ input_report_abs(ip_dev, ABS_MT_POSITION_X, gesture_coord_x);
+ input_report_abs(ip_dev, ABS_MT_POSITION_Y, gesture_coord_y);
+ input_mt_report_pointer_emulation(ip_dev, false);
+ input_sync(ip_dev);
+ }
+ input_mt_slot(ip_dev, FT_GESTURE_DEFAULT_TRACKING_ID);
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
+ input_mt_report_pointer_emulation(ip_dev, false);
+ input_sync(ip_dev);
+
+ return 0;
+}
+#else
+static DEVICE_ATTR(pocket, 0664, NULL, NULL);
+static DEVICE_ATTR(enable, 0664, NULL, NULL);
+
+static int ft5x06_report_gesture(struct i2c_client *i2c_client,
+ struct input_dev *ip_dev)
+{
+ return 0;
+}
+#endif
+
+static void ft5x06_update_fw_vendor_id(struct ft5x06_ts_data *data)
+{
+ struct i2c_client *client = data->client;
+ u8 reg_addr;
+ int err;
+
+ reg_addr = FT_REG_FW_VENDOR_ID;
+ err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_vendor_id, 1);
+ if (err < 0)
+ dev_err(&client->dev, "fw vendor id read failed");
+}
+
+static void ft5x06_update_fw_ver(struct ft5x06_ts_data *data)
+{
+ struct i2c_client *client = data->client;
+ u8 reg_addr;
+ int err;
+
+ reg_addr = FT_REG_FW_VER;
+ err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[0], 1);
+ if (err < 0)
+ dev_err(&client->dev, "fw major version read failed");
+
+ reg_addr = FT_REG_FW_MIN_VER;
+ err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[1], 1);
+ if (err < 0)
+ dev_err(&client->dev, "fw minor version read failed");
+
+ reg_addr = FT_REG_FW_SUB_MIN_VER;
+ err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[2], 1);
+ if (err < 0)
+ dev_err(&client->dev, "fw sub minor version read failed");
+
+ dev_info(&client->dev, "Firmware version = %d.%d.%d\n",
+ data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]);
+}
+
+static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
+{
+ struct ft5x06_ts_data *data = dev_id;
+ struct input_dev *ip_dev;
+ int rc, i;
+ u32 id, x, y, status, num_touches;
+ u8 reg, *buf, gesture_is_active;
+ bool update_input = false;
+
+ if (!data) {
+ pr_err("%s: Invalid data\n", __func__);
+ return IRQ_HANDLED;
+ }
+
+ if (ft5x06_filter_interrupt(data) == IRQ_HANDLED)
+ return IRQ_HANDLED;
+
+ ip_dev = data->input_dev;
+ buf = data->tch_data;
+
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support) {
+ ft5x0x_read_reg(data->client, FT_REG_GESTURE_ENABLE,
+ &gesture_is_active);
+ if (gesture_is_active) {
+ pm_wakeup_event(&(data->client->dev),
+ FT_GESTURE_WAKEUP_TIMEOUT);
+ ft5x06_report_gesture(data->client, ip_dev);
+ return IRQ_HANDLED;
+ }
+ }
+
+ /*
+ * Read touch data start from register FT_REG_DEV_MODE.
+ * The touch x/y value start from FT_TOUCH_X_H/L_POS and
+ * FT_TOUCH_Y_H/L_POS in buf.
+ */
+ reg = FT_REG_DEV_MODE;
+ rc = ft5x06_i2c_read(data->client, &reg, 1, buf, data->tch_data_len);
+ if (rc < 0) {
+ dev_err(&data->client->dev, "%s: read data fail\n", __func__);
+ return IRQ_HANDLED;
+ }
+
+ for (i = 0; i < data->pdata->num_max_touches; i++) {
+ /*
+ * Getting the finger ID of the touch event incase of
+ * multiple touch events
+ */
+ id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4;
+ if (id >= FT_MAX_ID)
+ break;
+
+ update_input = true;
+
+ x = (buf[FT_TOUCH_X_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
+ (buf[FT_TOUCH_X_L_POS + FT_ONE_TCH_LEN * i]);
+ y = (buf[FT_TOUCH_Y_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
+ (buf[FT_TOUCH_Y_L_POS + FT_ONE_TCH_LEN * i]);
+
+ status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6;
+
+ num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK;
+
+ /* invalid combination */
+ if (!num_touches && !status && !id)
+ break;
+
+ input_mt_slot(ip_dev, id);
+ if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) {
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
+ input_report_abs(ip_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(ip_dev, ABS_MT_POSITION_Y, y);
+ } else {
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
+ }
+ }
+
+ if (update_input) {
+ input_mt_report_pointer_emulation(ip_dev, false);
+ input_sync(ip_dev);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int ft5x06_gpio_configure(struct ft5x06_ts_data *data, bool on)
+{
+ int err = 0;
+
+ if (on) {
+ if (gpio_is_valid(data->pdata->irq_gpio)) {
+ err = gpio_request(data->pdata->irq_gpio,
+ "ft5x06_irq_gpio");
+ if (err) {
+ dev_err(&data->client->dev,
+ "irq gpio request failed");
+ goto err_irq_gpio_req;
+ }
+
+ err = gpio_direction_input(data->pdata->irq_gpio);
+ if (err) {
+ dev_err(&data->client->dev,
+ "set_direction for irq gpio failed\n");
+ goto err_irq_gpio_dir;
+ }
+ }
+
+ if (gpio_is_valid(data->pdata->reset_gpio)) {
+ err = gpio_request(data->pdata->reset_gpio,
+ "ft5x06_reset_gpio");
+ if (err) {
+ dev_err(&data->client->dev,
+ "reset gpio request failed");
+ goto err_irq_gpio_dir;
+ }
+
+ err = gpio_direction_output(data->pdata->reset_gpio, 0);
+ if (err) {
+ dev_err(&data->client->dev,
+ "set_direction for reset gpio failed\n");
+ goto err_reset_gpio_dir;
+ }
+ msleep(data->pdata->hard_rst_dly);
+ gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
+ }
+
+ return 0;
+ }
+ if (gpio_is_valid(data->pdata->irq_gpio))
+ gpio_free(data->pdata->irq_gpio);
+ if (gpio_is_valid(data->pdata->reset_gpio)) {
+ /*
+ * This is intended to save leakage current
+ * only. Even if the call(gpio_direction_input)
+ * fails, only leakage current will be more but
+ * functionality will not be affected.
+ */
+ err = gpio_direction_input(data->pdata->reset_gpio);
+ if (err) {
+ dev_err(&data->client->dev,
+ "unable to set direction for gpio [%d]\n",
+ data->pdata->irq_gpio);
+ }
+ gpio_free(data->pdata->reset_gpio);
+ }
+
+ return 0;
+
+err_reset_gpio_dir:
+ if (gpio_is_valid(data->pdata->reset_gpio))
+ gpio_free(data->pdata->reset_gpio);
+err_irq_gpio_dir:
+ if (gpio_is_valid(data->pdata->irq_gpio))
+ gpio_free(data->pdata->irq_gpio);
+err_irq_gpio_req:
+ return err;
+}
+
+static int ft5x06_power_on(struct ft5x06_ts_data *data, bool on)
+{
+ int rc;
+
+ if (!on)
+ goto power_off;
+
+ rc = regulator_enable(data->vdd);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vdd enable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_enable(data->vcc_i2c);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_i2c enable failed rc=%d\n", rc);
+ regulator_disable(data->vdd);
+ }
+
+ return rc;
+
+power_off:
+ rc = regulator_disable(data->vdd);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vdd disable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_disable(data->vcc_i2c);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_i2c disable failed rc=%d\n", rc);
+ rc = regulator_enable(data->vdd);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vdd enable failed rc=%d\n", rc);
+ }
+ }
+
+ return rc;
+}
+
+static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
+{
+ int rc;
+
+ if (!on)
+ goto pwr_deinit;
+
+ data->vdd = regulator_get(&data->client->dev, "vdd");
+ if (IS_ERR(data->vdd)) {
+ rc = PTR_ERR(data->vdd);
+ dev_err(&data->client->dev,
+ "Regulator get failed vdd rc=%d\n", rc);
+ return rc;
+ }
+
+ if (regulator_count_voltages(data->vdd) > 0) {
+ rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
+ FT_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator set_vtg failed vdd rc=%d\n", rc);
+ goto reg_vdd_put;
+ }
+ }
+
+ data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
+ if (IS_ERR(data->vcc_i2c)) {
+ rc = PTR_ERR(data->vcc_i2c);
+ dev_err(&data->client->dev,
+ "Regulator get failed vcc_i2c rc=%d\n", rc);
+ goto reg_vdd_set_vtg;
+ }
+
+ if (regulator_count_voltages(data->vcc_i2c) > 0) {
+ rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
+ FT_I2C_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
+ goto reg_vcc_i2c_put;
+ }
+ }
+
+ return 0;
+
+reg_vcc_i2c_put:
+ regulator_put(data->vcc_i2c);
+reg_vdd_set_vtg:
+ if (regulator_count_voltages(data->vdd) > 0)
+ regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
+reg_vdd_put:
+ regulator_put(data->vdd);
+ return rc;
+
+pwr_deinit:
+ if (regulator_count_voltages(data->vdd) > 0)
+ regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
+
+ regulator_put(data->vdd);
+
+ if (regulator_count_voltages(data->vcc_i2c) > 0)
+ regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
+
+ regulator_put(data->vcc_i2c);
+ return 0;
+}
+
+static int ft5x06_ts_pinctrl_init(struct ft5x06_ts_data *ft5x06_data)
+{
+ int retval;
+
+ /* Get pinctrl if target uses pinctrl */
+ ft5x06_data->ts_pinctrl = devm_pinctrl_get(&(ft5x06_data->client->dev));
+ if (IS_ERR_OR_NULL(ft5x06_data->ts_pinctrl)) {
+ retval = PTR_ERR(ft5x06_data->ts_pinctrl);
+ dev_dbg(&ft5x06_data->client->dev,
+ "Target does not use pinctrl %d\n", retval);
+ goto err_pinctrl_get;
+ }
+
+ ft5x06_data->pinctrl_state_active
+ = pinctrl_lookup_state(ft5x06_data->ts_pinctrl,
+ PINCTRL_STATE_ACTIVE);
+ if (IS_ERR_OR_NULL(ft5x06_data->pinctrl_state_active)) {
+ retval = PTR_ERR(ft5x06_data->pinctrl_state_active);
+ dev_err(&ft5x06_data->client->dev,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_ACTIVE, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ft5x06_data->pinctrl_state_suspend
+ = pinctrl_lookup_state(ft5x06_data->ts_pinctrl,
+ PINCTRL_STATE_SUSPEND);
+ if (IS_ERR_OR_NULL(ft5x06_data->pinctrl_state_suspend)) {
+ retval = PTR_ERR(ft5x06_data->pinctrl_state_suspend);
+ dev_err(&ft5x06_data->client->dev,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_SUSPEND, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ft5x06_data->pinctrl_state_release
+ = pinctrl_lookup_state(ft5x06_data->ts_pinctrl,
+ PINCTRL_STATE_RELEASE);
+ if (IS_ERR_OR_NULL(ft5x06_data->pinctrl_state_release)) {
+ retval = PTR_ERR(ft5x06_data->pinctrl_state_release);
+ dev_dbg(&ft5x06_data->client->dev,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_RELEASE, retval);
+ }
+
+ return 0;
+
+err_pinctrl_lookup:
+ devm_pinctrl_put(ft5x06_data->ts_pinctrl);
+err_pinctrl_get:
+ ft5x06_data->ts_pinctrl = NULL;
+ return retval;
+}
+
+#ifdef CONFIG_PM
+static int ft5x06_ts_start(struct device *dev)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ int err;
+
+ if (data->pdata->power_on) {
+ err = data->pdata->power_on(true);
+ if (err) {
+ dev_err(dev, "power on failed");
+ return err;
+ }
+ } else {
+ err = ft5x06_power_on(data, true);
+ if (err) {
+ dev_err(dev, "power on failed");
+ return err;
+ }
+ }
+
+ if (data->ts_pinctrl) {
+ err = pinctrl_select_state(data->ts_pinctrl,
+ data->pinctrl_state_active);
+ if (err < 0)
+ dev_err(dev, "Cannot get active pinctrl state\n");
+ }
+
+ err = ft5x06_gpio_configure(data, true);
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "failed to put gpios in resue state\n");
+ goto err_gpio_configuration;
+ }
+
+ if (gpio_is_valid(data->pdata->reset_gpio)) {
+ gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
+ msleep(data->pdata->hard_rst_dly);
+ gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
+ }
+
+ msleep(data->pdata->soft_rst_dly);
+
+ enable_irq(data->client->irq);
+ data->suspended = false;
+
+ return 0;
+
+err_gpio_configuration:
+ if (data->ts_pinctrl) {
+ err = pinctrl_select_state(data->ts_pinctrl,
+ data->pinctrl_state_suspend);
+ if (err < 0)
+ dev_err(dev, "Cannot get suspend pinctrl state\n");
+ }
+ if (data->pdata->power_on) {
+ err = data->pdata->power_on(false);
+ if (err)
+ dev_err(dev, "power off failed");
+ } else {
+ err = ft5x06_power_on(data, false);
+ if (err)
+ dev_err(dev, "power off failed");
+ }
+ return err;
+}
+
+static int ft5x06_ts_stop(struct device *dev)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ char txbuf[2];
+ int i, err;
+
+ disable_irq(data->client->irq);
+
+ /* release all touches */
+ for (i = 0; i < data->pdata->num_max_touches; i++) {
+ input_mt_slot(data->input_dev, i);
+ input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
+ }
+ input_mt_report_pointer_emulation(data->input_dev, false);
+ input_sync(data->input_dev);
+
+ if (gpio_is_valid(data->pdata->reset_gpio)) {
+ txbuf[0] = FT_REG_PMODE;
+ txbuf[1] = FT_PMODE_HIBERNATE;
+ ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
+ }
+
+ if (data->pdata->power_on) {
+ err = data->pdata->power_on(false);
+ if (err) {
+ dev_err(dev, "power off failed");
+ goto pwr_off_fail;
+ }
+ } else {
+ err = ft5x06_power_on(data, false);
+ if (err) {
+ dev_err(dev, "power off failed");
+ goto pwr_off_fail;
+ }
+ }
+
+ if (data->ts_pinctrl) {
+ err = pinctrl_select_state(data->ts_pinctrl,
+ data->pinctrl_state_suspend);
+ if (err < 0)
+ dev_err(dev, "Cannot get suspend pinctrl state\n");
+ }
+
+ err = ft5x06_gpio_configure(data, false);
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "failed to put gpios in suspend state\n");
+ goto gpio_configure_fail;
+ }
+
+ data->suspended = true;
+
+ return 0;
+
+gpio_configure_fail:
+ if (data->ts_pinctrl) {
+ err = pinctrl_select_state(data->ts_pinctrl,
+ data->pinctrl_state_active);
+ if (err < 0)
+ dev_err(dev, "Cannot get active pinctrl state\n");
+ }
+ if (data->pdata->power_on) {
+ err = data->pdata->power_on(true);
+ if (err)
+ dev_err(dev, "power on failed");
+ } else {
+ err = ft5x06_power_on(data, true);
+ if (err)
+ dev_err(dev, "power on failed");
+ }
+pwr_off_fail:
+ if (gpio_is_valid(data->pdata->reset_gpio)) {
+ gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
+ msleep(data->pdata->hard_rst_dly);
+ gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
+ }
+ enable_irq(data->client->irq);
+ return err;
+}
+
+static int ft5x06_ts_suspend(struct device *dev)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ int err;
+
+ if (data->loading_fw) {
+ dev_info(dev, "Firmware loading in process...\n");
+ return 0;
+ }
+
+ if (data->suspended) {
+ dev_info(dev, "Already in suspend state\n");
+ return 0;
+ }
+
+ ft5x06_secure_touch_stop(data, true);
+
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support &&
+ device_may_wakeup(dev) &&
+ data->gesture_pdata->gesture_enable_to_set) {
+
+ ft5x0x_write_reg(data->client, FT_REG_GESTURE_ENABLE, 1);
+ err = enable_irq_wake(data->client->irq);
+ if (err)
+ dev_err(&data->client->dev,
+ "%s: set_irq_wake failed\n", __func__);
+ data->suspended = true;
+ return err;
+ }
+
+ return ft5x06_ts_stop(dev);
+}
+
+static int ft5x06_ts_resume(struct device *dev)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ int err;
+
+ if (!data->suspended) {
+ dev_dbg(dev, "Already in awake state\n");
+ return 0;
+ }
+
+ ft5x06_secure_touch_stop(data, true);
+
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support &&
+ device_may_wakeup(dev) &&
+ !(data->gesture_pdata->in_pocket) &&
+ data->gesture_pdata->gesture_enable_to_set) {
+
+ ft5x0x_write_reg(data->client, FT_REG_GESTURE_ENABLE, 0);
+ err = disable_irq_wake(data->client->irq);
+ if (err)
+ dev_err(dev, "%s: disable_irq_wake failed\n",
+ __func__);
+ data->suspended = false;
+ return err;
+ }
+
+ err = ft5x06_ts_start(dev);
+ if (err < 0)
+ return err;
+
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support &&
+ device_may_wakeup(dev) &&
+ data->gesture_pdata->in_pocket &&
+ data->gesture_pdata->gesture_enable_to_set) {
+
+ ft5x0x_write_reg(data->client, FT_REG_GESTURE_ENABLE, 0);
+ err = disable_irq_wake(data->client->irq);
+ if (err)
+ dev_err(dev, "%s: disable_irq_wake failed\n",
+ __func__);
+ data->suspended = false;
+ data->gesture_pdata->in_pocket = 0;
+ }
+ return 0;
+}
+
+static const struct dev_pm_ops ft5x06_ts_pm_ops = {
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
+ .suspend = ft5x06_ts_suspend,
+ .resume = ft5x06_ts_resume,
+#endif
+};
+
+#else
+static int ft5x06_ts_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int ft5x06_ts_resume(struct device *dev)
+{
+ return 0;
+}
+
+#endif
+
+#if defined(CONFIG_FB)
+static void fb_notify_resume_work(struct work_struct *work)
+{
+ struct ft5x06_ts_data *ft5x06_data =
+ container_of(work, struct ft5x06_ts_data, fb_notify_work);
+ ft5x06_ts_resume(&ft5x06_data->client->dev);
+}
+
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct ft5x06_ts_data *ft5x06_data =
+ container_of(self, struct ft5x06_ts_data, fb_notif);
+
+ if (evdata && evdata->data && ft5x06_data && ft5x06_data->client) {
+ blank = evdata->data;
+ if (ft5x06_data->pdata->resume_in_workqueue) {
+ if (event == FB_EARLY_EVENT_BLANK &&
+ *blank == FB_BLANK_UNBLANK)
+ schedule_work(&ft5x06_data->fb_notify_work);
+ else if (event == FB_EVENT_BLANK &&
+ *blank == FB_BLANK_POWERDOWN) {
+ flush_work(&ft5x06_data->fb_notify_work);
+ ft5x06_ts_suspend(&ft5x06_data->client->dev);
+ }
+ } else {
+ if (event == FB_EVENT_BLANK) {
+ if (*blank == FB_BLANK_UNBLANK)
+ ft5x06_ts_resume(
+ &ft5x06_data->client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ ft5x06_ts_suspend(
+ &ft5x06_data->client->dev);
+ }
+ }
+ }
+
+ return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void ft5x06_ts_early_suspend(struct early_suspend *handler)
+{
+ struct ft5x06_ts_data *data = container_of(handler,
+ struct ft5x06_ts_data,
+ early_suspend);
+
+ /*
+ * During early suspend/late resume, the driver doesn't access xPU/SMMU
+ * protected HW resources. So, there is no compelling need to block,
+ * but notifying the userspace that a power event has occurred is
+ * enough. Hence 'blocking' variable can be set to false.
+ */
+ ft5x06_secure_touch_stop(data, false);
+ ft5x06_ts_suspend(&data->client->dev);
+}
+
+static void ft5x06_ts_late_resume(struct early_suspend *handler)
+{
+ struct ft5x06_ts_data *data = container_of(handler,
+ struct ft5x06_ts_data,
+ early_suspend);
+
+ ft5x06_secure_touch_stop(data, false);
+ ft5x06_ts_resume(&data->client->dev);
+}
+#endif
+
+static int ft5x06_auto_cal(struct i2c_client *client)
+{
+ struct ft5x06_ts_data *data = i2c_get_clientdata(client);
+ u8 temp = 0, i;
+
+ /* set to factory mode */
+ msleep(2 * data->pdata->soft_rst_dly);
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+ msleep(data->pdata->soft_rst_dly);
+
+ /* start calibration */
+ ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
+ msleep(2 * data->pdata->soft_rst_dly);
+ for (i = 0; i < FT_CAL_RETRY; i++) {
+ ft5x0x_read_reg(client, FT_REG_CAL, &temp);
+ /* return to normal mode, calibration finish */
+ if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
+ break;
+ }
+
+ /*calibration OK */
+ msleep(2 * data->pdata->soft_rst_dly);
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+ msleep(data->pdata->soft_rst_dly);
+
+ /* store calibration data */
+ ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
+ msleep(2 * data->pdata->soft_rst_dly);
+
+ /* set to normal mode */
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
+ msleep(2 * data->pdata->soft_rst_dly);
+
+ return 0;
+}
+
+static int ft5x06_fw_upgrade_start(struct i2c_client *client,
+ const u8 *data, u32 data_len)
+{
+ struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
+ struct fw_upgrade_info info = ts_data->pdata->info;
+ u8 reset_reg;
+ u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
+ u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
+ int i, j, temp;
+ u32 pkt_num, pkt_len;
+ u8 is_5336_new_bootloader = false;
+ u8 is_5336_fwsize_30 = false;
+ u8 fw_ecc;
+
+ /* determine firmware size */
+ if (*(data + data_len - FT_BLOADER_SIZE_OFF) == FT_BLOADER_NEW_SIZE)
+ is_5336_fwsize_30 = true;
+ else
+ is_5336_fwsize_30 = false;
+
+ for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
+ msleep(FT_EARSE_DLY_MS);
+ /* reset - write 0xaa and 0x55 to reset register */
+ if (ts_data->family_id == FT6X06_ID
+ || ts_data->family_id == FT6X36_ID)
+ reset_reg = FT_RST_CMD_REG2;
+ else
+ reset_reg = FT_RST_CMD_REG1;
+
+ ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA);
+ msleep(info.delay_aa);
+
+ ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55);
+ if (i <= (FT_UPGRADE_LOOP / 2))
+ msleep(info.delay_55 + i * 3);
+ else
+ msleep(info.delay_55 - (i - (FT_UPGRADE_LOOP / 2)) * 2);
+
+ /* Enter upgrade mode */
+ w_buf[0] = FT_UPGRADE_55;
+ ft5x06_i2c_write(client, w_buf, 1);
+ usleep_range(FT_55_AA_DLY_NS, FT_55_AA_DLY_NS + 1);
+ w_buf[0] = FT_UPGRADE_AA;
+ ft5x06_i2c_write(client, w_buf, 1);
+
+ /* check READ_ID */
+ msleep(info.delay_readid);
+ w_buf[0] = FT_READ_ID_REG;
+ w_buf[1] = 0x00;
+ w_buf[2] = 0x00;
+ w_buf[3] = 0x00;
+
+ ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
+
+ if (r_buf[0] != info.upgrade_id_1
+ || r_buf[1] != info.upgrade_id_2) {
+ dev_err(&client->dev, "Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n",
+ i, r_buf[0], r_buf[1],
+ info.upgrade_id_1, info.upgrade_id_2);
+ } else
+ break;
+ }
+
+ if (i >= FT_UPGRADE_LOOP) {
+ dev_err(&client->dev, "Abort upgrade\n");
+ return -EIO;
+ }
+
+ w_buf[0] = 0xcd;
+ ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
+
+ if (r_buf[0] <= 4)
+ is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
+ else if (r_buf[0] == 7)
+ is_5336_new_bootloader = FT_BLOADER_VERSION_Z7;
+ else if (r_buf[0] >= 0x0f &&
+ ((ts_data->family_id == FT_FT5336_FAMILY_ID_0x11) ||
+ (ts_data->family_id == FT_FT5336_FAMILY_ID_0x12) ||
+ (ts_data->family_id == FT_FT5336_FAMILY_ID_0x13) ||
+ (ts_data->family_id == FT_FT5336_FAMILY_ID_0x14)))
+ is_5336_new_bootloader = FT_BLOADER_VERSION_GZF;
+ else
+ is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
+
+ dev_dbg(&client->dev, "bootloader type=%d, r_buf=0x%x, family_id=0x%x\n",
+ is_5336_new_bootloader, r_buf[0], ts_data->family_id);
+ /* is_5336_new_bootloader = FT_BLOADER_VERSION_GZF; */
+
+ /* erase app and panel paramenter area */
+ w_buf[0] = FT_ERASE_APP_REG;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(info.delay_erase_flash);
+
+ if (is_5336_fwsize_30) {
+ w_buf[0] = FT_ERASE_PANEL_REG;
+ ft5x06_i2c_write(client, w_buf, 1);
+ }
+ msleep(FT_EARSE_DLY_MS);
+
+ /* program firmware */
+ if (is_5336_new_bootloader == FT_BLOADER_VERSION_LZ4
+ || is_5336_new_bootloader == FT_BLOADER_VERSION_Z7)
+ data_len = data_len - FT_DATA_LEN_OFF_OLD_FW;
+ else
+ data_len = data_len - FT_DATA_LEN_OFF_NEW_FW;
+
+ pkt_num = (data_len) / FT_FW_PKT_LEN;
+ pkt_len = FT_FW_PKT_LEN;
+ pkt_buf[0] = FT_FW_START_REG;
+ pkt_buf[1] = 0x00;
+ fw_ecc = 0;
+
+ for (i = 0; i < pkt_num; i++) {
+ temp = i * FT_FW_PKT_LEN;
+ pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[3] = (u8) temp;
+ pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
+ pkt_buf[5] = (u8) pkt_len;
+
+ for (j = 0; j < FT_FW_PKT_LEN; j++) {
+ pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
+ fw_ecc ^= pkt_buf[6 + j];
+ }
+
+ ft5x06_i2c_write(client, pkt_buf,
+ FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* send remaining bytes */
+ if ((data_len) % FT_FW_PKT_LEN > 0) {
+ temp = pkt_num * FT_FW_PKT_LEN;
+ pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[3] = (u8) temp;
+ temp = (data_len) % FT_FW_PKT_LEN;
+ pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[5] = (u8) temp;
+
+ for (i = 0; i < temp; i++) {
+ pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
+ fw_ecc ^= pkt_buf[6 + i];
+ }
+
+ ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* send the finishing packet */
+ if (is_5336_new_bootloader == FT_BLOADER_VERSION_LZ4 ||
+ is_5336_new_bootloader == FT_BLOADER_VERSION_Z7) {
+ for (i = 0; i < FT_FINISHING_PKT_LEN_OLD_FW; i++) {
+ if (is_5336_new_bootloader == FT_BLOADER_VERSION_Z7)
+ temp = FT_MAGIC_BLOADER_Z7 + i;
+ else if (is_5336_new_bootloader ==
+ FT_BLOADER_VERSION_LZ4)
+ temp = FT_MAGIC_BLOADER_LZ4 + i;
+ pkt_buf[2] = (u8)(temp >> 8);
+ pkt_buf[3] = (u8)temp;
+ temp = 1;
+ pkt_buf[4] = (u8)(temp >> 8);
+ pkt_buf[5] = (u8)temp;
+ pkt_buf[6] = data[data_len + i];
+ fw_ecc ^= pkt_buf[6];
+
+ ft5x06_i2c_write(client,
+ pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+ } else if (is_5336_new_bootloader == FT_BLOADER_VERSION_GZF) {
+ for (i = 0; i < FT_FINISHING_PKT_LEN_NEW_FW; i++) {
+ if (is_5336_fwsize_30)
+ temp = FT_MAGIC_BLOADER_GZF_30 + i;
+ else
+ temp = FT_MAGIC_BLOADER_GZF + i;
+ pkt_buf[2] = (u8)(temp >> 8);
+ pkt_buf[3] = (u8)temp;
+ temp = 1;
+ pkt_buf[4] = (u8)(temp >> 8);
+ pkt_buf[5] = (u8)temp;
+ pkt_buf[6] = data[data_len + i];
+ fw_ecc ^= pkt_buf[6];
+
+ ft5x06_i2c_write(client,
+ pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+
+ }
+ }
+
+ /* verify checksum */
+ w_buf[0] = FT_REG_ECC;
+ ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
+ if (r_buf[0] != fw_ecc) {
+ dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
+ r_buf[0], fw_ecc);
+ return -EIO;
+ }
+
+ /* reset */
+ w_buf[0] = FT_REG_RESET_FW;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(ts_data->pdata->soft_rst_dly);
+
+ dev_info(&client->dev, "Firmware upgrade successful\n");
+
+ return 0;
+}
+
+static int ft5x06_fw_upgrade(struct device *dev, bool force)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ const struct firmware *fw = NULL;
+ int rc;
+ u8 fw_file_maj, fw_file_min, fw_file_sub_min, fw_file_vendor_id;
+ bool fw_upgrade = false;
+
+ if (data->suspended) {
+ dev_err(dev, "Device is in suspend state: Exit FW upgrade\n");
+ return -EBUSY;
+ }
+
+ rc = request_firmware(&fw, data->fw_name, dev);
+ if (rc < 0) {
+ dev_err(dev, "Request firmware failed - %s (%d)\n",
+ data->fw_name, rc);
+ return rc;
+ }
+
+ if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
+ dev_err(dev, "Invalid firmware size (%zu)\n", fw->size);
+ rc = -EIO;
+ goto rel_fw;
+ }
+
+ if (data->family_id == FT6X36_ID) {
+ fw_file_maj = FT_FW_FILE_MAJ_VER_FT6X36(fw);
+ fw_file_vendor_id = FT_FW_FILE_VENDOR_ID_FT6X36(fw);
+ } else {
+ fw_file_maj = FT_FW_FILE_MAJ_VER(fw);
+ fw_file_vendor_id = FT_FW_FILE_VENDOR_ID(fw);
+ }
+ fw_file_min = FT_FW_FILE_MIN_VER(fw);
+ fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw);
+ fw_file_vendor_id = FT_FW_FILE_VENDOR_ID(fw);
+
+ dev_info(dev, "Current firmware: %d.%d.%d", data->fw_ver[0],
+ data->fw_ver[1], data->fw_ver[2]);
+ dev_info(dev, "New firmware: %d.%d.%d", fw_file_maj,
+ fw_file_min, fw_file_sub_min);
+
+ if (force)
+ fw_upgrade = true;
+ else if ((data->fw_ver[0] < fw_file_maj) &&
+ data->fw_vendor_id == fw_file_vendor_id)
+ fw_upgrade = true;
+
+ if (!fw_upgrade) {
+ dev_info(dev, "Exiting fw upgrade...\n");
+ rc = -EFAULT;
+ goto rel_fw;
+ }
+
+ /* start firmware upgrade */
+ if (FT_FW_CHECK(fw, data)) {
+ rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
+ if (rc < 0)
+ dev_err(dev, "update failed (%d). try later...\n", rc);
+ else if (data->pdata->info.auto_cal)
+ ft5x06_auto_cal(data->client);
+ } else {
+ dev_err(dev, "FW format error\n");
+ rc = -EIO;
+ }
+
+ ft5x06_update_fw_ver(data);
+
+ FT_STORE_TS_DBG_INFO(data->ts_info, data->family_id, data->pdata->name,
+ data->pdata->num_max_touches, data->pdata->group_id,
+ data->pdata->fw_vkey_support ? "yes" : "no",
+ data->pdata->fw_name, data->fw_ver[0],
+ data->fw_ver[1], data->fw_ver[2]);
+ FT_STORE_TS_INFO(ts_info_buff, data->family_id, data->fw_ver[0],
+ data->fw_ver[1], data->fw_ver[2]);
+rel_fw:
+ release_firmware(fw);
+ return rc;
+}
+
+static ssize_t ft5x06_update_fw_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, 2, "%d\n", data->loading_fw);
+}
+
+static ssize_t ft5x06_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = kstrtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ if (data->suspended) {
+ dev_info(dev, "In suspend state, try again later...\n");
+ return size;
+ }
+
+ mutex_lock(&data->input_dev->mutex);
+ if (!data->loading_fw && val) {
+ data->loading_fw = true;
+ ft5x06_fw_upgrade(dev, false);
+ data->loading_fw = false;
+ }
+ mutex_unlock(&data->input_dev->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
+ ft5x06_update_fw_store);
+
+static ssize_t ft5x06_force_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = kstrtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ mutex_lock(&data->input_dev->mutex);
+ if (!data->loading_fw && val) {
+ data->loading_fw = true;
+ ft5x06_fw_upgrade(dev, true);
+ data->loading_fw = false;
+ }
+ mutex_unlock(&data->input_dev->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
+ ft5x06_force_update_fw_store);
+
+static ssize_t ft5x06_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
+}
+
+static ssize_t ft5x06_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ if (size > FT_FW_NAME_MAX_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(data->fw_name, buf, size);
+ if (data->fw_name[size-1] == '\n')
+ data->fw_name[size-1] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
+
+static ssize_t ts_info_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ strlcpy(buf, ts_info_buff, FT_INFO_MAX_LEN);
+ return strnlen(buf, FT_INFO_MAX_LEN);
+}
+static struct kobj_attribute ts_info_attr = __ATTR_RO(ts_info);
+
+static bool ft5x06_debug_addr_is_valid(int addr)
+{
+ if (addr < 0 || addr > 0xFF) {
+ pr_err("FT reg address is invalid: 0x%x\n", addr);
+ return false;
+ }
+
+ return true;
+}
+
+static int ft5x06_debug_data_set(void *_data, u64 val)
+{
+ struct ft5x06_ts_data *data = _data;
+
+ mutex_lock(&data->input_dev->mutex);
+
+ if (ft5x06_debug_addr_is_valid(data->addr))
+ dev_info(&data->client->dev,
+ "Writing into FT registers not supported\n");
+
+ mutex_unlock(&data->input_dev->mutex);
+
+ return 0;
+}
+
+static int ft5x06_debug_data_get(void *_data, u64 *val)
+{
+ struct ft5x06_ts_data *data = _data;
+ int rc;
+ u8 reg = 0;
+
+ mutex_lock(&data->input_dev->mutex);
+
+ if (ft5x06_debug_addr_is_valid(data->addr)) {
+ rc = ft5x0x_read_reg(data->client, data->addr, &reg);
+ if (rc < 0)
+ dev_err(&data->client->dev,
+ "FT read register 0x%x failed (%d)\n",
+ data->addr, rc);
+ else
+ *val = reg;
+ }
+
+ mutex_unlock(&data->input_dev->mutex);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, ft5x06_debug_data_get,
+ ft5x06_debug_data_set, "0x%02llX\n");
+
+static int ft5x06_debug_addr_set(void *_data, u64 val)
+{
+ struct ft5x06_ts_data *data = _data;
+
+ if (ft5x06_debug_addr_is_valid(val)) {
+ mutex_lock(&data->input_dev->mutex);
+ data->addr = val;
+ mutex_unlock(&data->input_dev->mutex);
+ }
+
+ return 0;
+}
+
+static int ft5x06_debug_addr_get(void *_data, u64 *val)
+{
+ struct ft5x06_ts_data *data = _data;
+
+ mutex_lock(&data->input_dev->mutex);
+
+ if (ft5x06_debug_addr_is_valid(data->addr))
+ *val = data->addr;
+
+ mutex_unlock(&data->input_dev->mutex);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, ft5x06_debug_addr_get,
+ ft5x06_debug_addr_set, "0x%02llX\n");
+
+static int ft5x06_debug_suspend_set(void *_data, u64 val)
+{
+ struct ft5x06_ts_data *data = _data;
+
+ mutex_lock(&data->input_dev->mutex);
+
+ if (val)
+ ft5x06_ts_suspend(&data->client->dev);
+ else
+ ft5x06_ts_resume(&data->client->dev);
+
+ mutex_unlock(&data->input_dev->mutex);
+
+ return 0;
+}
+
+static int ft5x06_debug_suspend_get(void *_data, u64 *val)
+{
+ struct ft5x06_ts_data *data = _data;
+
+ mutex_lock(&data->input_dev->mutex);
+ *val = data->suspended;
+ mutex_unlock(&data->input_dev->mutex);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
+ ft5x06_debug_suspend_set, "%lld\n");
+
+static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
+{
+ struct ft5x06_ts_data *data = m->private;
+
+ seq_printf(m, "%s\n", data->ts_info);
+
+ return 0;
+}
+
+static int debugfs_dump_info_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ft5x06_debug_dump_info, inode->i_private);
+}
+
+static const struct file_operations debug_dump_info_fops = {
+ .owner = THIS_MODULE,
+ .open = debugfs_dump_info_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
+#ifdef CONFIG_OF
+static int ft5x06_get_dt_coords(struct device *dev, char *name,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ u32 coords[FT_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != FT_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (!strcmp(name, "focaltech,panel-coords")) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (!strcmp(name, "focaltech,display-coords")) {
+ pdata->x_min = coords[0];
+ pdata->y_min = coords[1];
+ pdata->x_max = coords[2];
+ pdata->y_max = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ft5x06_parse_dt(struct device *dev,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ u32 temp_val, num_buttons;
+ u32 button_map[MAX_BUTTONS];
+
+ pdata->name = "focaltech";
+ rc = of_property_read_string(np, "focaltech,name", &pdata->name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read name\n");
+ return rc;
+ }
+
+ rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
+ if (rc)
+ return rc;
+
+ pdata->i2c_pull_up = of_property_read_bool(np,
+ "focaltech,i2c-pull-up");
+
+ pdata->no_force_update = of_property_read_bool(np,
+ "focaltech,no-force-update");
+ /* reset, irq gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
+ 0, &pdata->reset_gpio_flags);
+ if (pdata->reset_gpio < 0)
+ return pdata->reset_gpio;
+
+ pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
+ 0, &pdata->irq_gpio_flags);
+ if (pdata->irq_gpio < 0)
+ return pdata->irq_gpio;
+
+ pdata->fw_name = "ft_fw.bin";
+ rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw name\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "focaltech,group-id", &temp_val);
+ if (!rc)
+ pdata->group_id = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms",
+ &temp_val);
+ if (!rc)
+ pdata->hard_rst_dly = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms",
+ &temp_val);
+ if (!rc)
+ pdata->soft_rst_dly = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val);
+ if (!rc)
+ pdata->num_max_touches = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay aa\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_aa = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay 55\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_55 = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw upgrade id1\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.upgrade_id_1 = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw upgrade id2\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.upgrade_id_2 = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms",
+ &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay read id\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_readid = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms",
+ &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay erase flash\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_erase_flash = temp_val;
+
+ pdata->info.auto_cal = of_property_read_bool(np,
+ "focaltech,fw-auto-cal");
+
+ pdata->fw_vkey_support = of_property_read_bool(np,
+ "focaltech,fw-vkey-support");
+
+ pdata->ignore_id_check = of_property_read_bool(np,
+ "focaltech,ignore-id-check");
+
+ pdata->gesture_support = of_property_read_bool(np,
+ "focaltech,gesture-support");
+
+ pdata->resume_in_workqueue = of_property_read_bool(np,
+ "focaltech,resume-in-workqueue");
+
+ rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
+ if (!rc)
+ pdata->family_id = temp_val;
+ else
+ return rc;
+
+ prop = of_find_property(np, "focaltech,button-map", NULL);
+ if (prop) {
+ num_buttons = prop->length / sizeof(temp_val);
+ if (num_buttons > MAX_BUTTONS)
+ return -EINVAL;
+
+ rc = of_property_read_u32_array(np,
+ "focaltech,button-map", button_map,
+ num_buttons);
+ if (rc) {
+ dev_err(dev, "Unable to read key codes\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+#else
+static int ft5x06_parse_dt(struct device *dev,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ return -ENODEV;
+}
+#endif
+
+static int ft5x06_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ft5x06_ts_platform_data *pdata;
+ struct ft5x06_gesture_platform_data *gesture_pdata;
+ struct ft5x06_ts_data *data;
+ struct input_dev *input_dev;
+ struct dentry *temp;
+ u8 reg_value = 0;
+ u8 reg_addr;
+ int err, len, retval, attr_count;
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ err = ft5x06_parse_dt(&client->dev, pdata);
+ if (err) {
+ dev_err(&client->dev, "DT parsing failed\n");
+ return err;
+ }
+ } else
+ pdata = client->dev.platform_data;
+
+ if (!pdata) {
+ dev_err(&client->dev, "Invalid pdata\n");
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "I2C not supported\n");
+ return -ENODEV;
+ }
+
+ data = devm_kzalloc(&client->dev,
+ sizeof(struct ft5x06_ts_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ if (pdata->fw_name) {
+ len = strlen(pdata->fw_name);
+ if (len > FT_FW_NAME_MAX_LEN - 1) {
+ dev_err(&client->dev, "Invalid firmware name\n");
+ return -EINVAL;
+ }
+
+ strlcpy(data->fw_name, pdata->fw_name, len + 1);
+ }
+
+ data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches);
+ data->tch_data = devm_kzalloc(&client->dev,
+ data->tch_data_len, GFP_KERNEL);
+ if (!data->tch_data)
+ return -ENOMEM;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ dev_err(&client->dev, "failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ data->input_dev = input_dev;
+ data->client = client;
+ data->pdata = pdata;
+
+ input_dev->name = "ft5x06_ts";
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = &client->dev;
+
+ input_set_drvdata(input_dev, data);
+ i2c_set_clientdata(client, data);
+
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ input_mt_init_slots(input_dev, pdata->num_max_touches, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
+ pdata->x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
+ pdata->y_max, 0, 0);
+
+ err = input_register_device(input_dev);
+ if (err) {
+ dev_err(&client->dev, "Input device registration failed\n");
+ input_free_device(input_dev);
+ return err;
+ }
+
+ if (pdata->power_init) {
+ err = pdata->power_init(true);
+ if (err) {
+ dev_err(&client->dev, "power init failed");
+ goto unreg_inputdev;
+ }
+ } else {
+ err = ft5x06_power_init(data, true);
+ if (err) {
+ dev_err(&client->dev, "power init failed");
+ goto unreg_inputdev;
+ }
+ }
+
+ if (pdata->power_on) {
+ err = pdata->power_on(true);
+ if (err) {
+ dev_err(&client->dev, "power on failed");
+ goto pwr_deinit;
+ }
+ } else {
+ err = ft5x06_power_on(data, true);
+ if (err) {
+ dev_err(&client->dev, "power on failed");
+ goto pwr_deinit;
+ }
+ }
+
+ err = ft5x06_ts_pinctrl_init(data);
+ if (!err && data->ts_pinctrl) {
+ /*
+ * Pinctrl handle is optional. If pinctrl handle is found
+ * let pins to be configured in active state. If not
+ * found continue further without error.
+ */
+ err = pinctrl_select_state(data->ts_pinctrl,
+ data->pinctrl_state_active);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "failed to select pin to active state");
+ }
+ }
+
+ err = ft5x06_gpio_configure(data, true);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "Failed to configure the gpios\n");
+ goto err_gpio_req;
+ }
+
+ /* make sure CTP already finish startup process */
+ msleep(data->pdata->soft_rst_dly);
+
+ /* check the controller id */
+ reg_addr = FT_REG_ID;
+ err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "version read failed");
+ goto free_gpio;
+ }
+
+ dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
+
+ if ((pdata->family_id != reg_value) && (!pdata->ignore_id_check)) {
+ dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
+ goto free_gpio;
+ }
+
+ data->family_id = pdata->family_id;
+
+ err = request_threaded_irq(client->irq, NULL,
+ ft5x06_ts_interrupt,
+ /*
+ * the interrupt trigger mode will be set in Device Tree with property
+ * "interrupts", so here we just need to set the flag IRQF_ONESHOT
+ */
+ IRQF_ONESHOT,
+ client->dev.driver->name, data);
+ if (err) {
+ dev_err(&client->dev, "request irq failed\n");
+ goto free_gpio;
+ }
+
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support) {
+ device_init_wakeup(&client->dev, 1);
+ gesture_pdata = devm_kzalloc(&client->dev,
+ sizeof(struct ft5x06_gesture_platform_data),
+ GFP_KERNEL);
+ if (!gesture_pdata) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ goto free_gesture_dev;
+ }
+ data->gesture_pdata = gesture_pdata;
+ gesture_pdata->data = data;
+
+ gesture_pdata->gesture_class =
+ class_create(THIS_MODULE, "gesture");
+ if (IS_ERR(gesture_pdata->gesture_class)) {
+ err = PTR_ERR(gesture_pdata->gesture_class);
+ dev_err(&client->dev, "Failed to create class.\n");
+ goto free_gesture_pdata;
+ }
+
+ gesture_pdata->dev = device_create(gesture_pdata->gesture_class,
+ NULL, 0, NULL, "gesture_ft5x06");
+ if (IS_ERR(gesture_pdata->dev)) {
+ err = PTR_ERR(gesture_pdata->dev);
+ dev_err(&client->dev, "Failed to create device.\n");
+ goto free_gesture_class;
+ }
+
+ dev_set_drvdata(gesture_pdata->dev, data);
+ err = device_create_file(gesture_pdata->dev,
+ &dev_attr_enable);
+ if (err) {
+ dev_err(gesture_pdata->dev,
+ "sys file creation failed\n");
+ goto free_gesture_dev;
+ }
+ err = device_create_file(gesture_pdata->dev,
+ &dev_attr_pocket);
+ if (err) {
+ dev_err(gesture_pdata->dev,
+ "sys file creation failed\n");
+ goto free_enable_sys;
+ }
+ }
+
+ err = device_create_file(&client->dev, &dev_attr_fw_name);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto free_pocket_sys;
+ }
+
+ err = device_create_file(&client->dev, &dev_attr_update_fw);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto free_fw_name_sys;
+ }
+
+ err = device_create_file(&client->dev, &dev_attr_force_update_fw);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto free_update_fw_sys;
+ }
+
+ data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
+ if (data->dir == NULL || IS_ERR(data->dir)) {
+ pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
+ err = PTR_ERR(data->dir);
+ goto free_force_update_fw_sys;
+ }
+
+ temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data,
+ &debug_addr_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+ err = PTR_ERR(temp);
+ goto free_debug_dir;
+ }
+
+ temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data,
+ &debug_data_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+ err = PTR_ERR(temp);
+ goto free_debug_dir;
+ }
+
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir,
+ data, &debug_suspend_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+ err = PTR_ERR(temp);
+ goto free_debug_dir;
+ }
+
+ temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir,
+ data, &debug_dump_info_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+ err = PTR_ERR(temp);
+ goto free_debug_dir;
+ }
+
+ data->ts_info = devm_kzalloc(&client->dev,
+ FT_INFO_MAX_LEN, GFP_KERNEL);
+ if (!data->ts_info)
+ goto free_debug_dir;
+
+ /*get some register information */
+ reg_addr = FT_REG_POINT_RATE;
+ ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "report rate read failed");
+
+ dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
+
+ reg_addr = FT_REG_THGROUP;
+ err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "threshold read failed");
+
+ dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
+
+ /*creation touch panel info kobj*/
+ data->ts_info_kobj = kobject_create_and_add(FT_TS_INFO_SYSFS_DIR_NAME,
+ kernel_kobj);
+ if (!data->ts_info_kobj) {
+ dev_err(&client->dev, "kobject creation failed.\n");
+ } else {
+ err = sysfs_create_file(data->ts_info_kobj, &ts_info_attr.attr);
+ if (err) {
+ kobject_put(data->ts_info_kobj);
+ dev_err(&client->dev, "sysfs creation failed.\n");
+ } else {
+ ts_info_buff = devm_kzalloc(&client->dev,
+ FT_INFO_MAX_LEN, GFP_KERNEL);
+ if (!ts_info_buff)
+ goto free_debug_dir;
+ }
+ }
+
+ /*Initialize secure touch */
+ ft5x06_secure_touch_init(data);
+ ft5x06_secure_touch_stop(data, true);
+ mutex_init(&(data->ft_clk_io_ctrl_mutex));
+
+ /* Creation of secure touch sysfs files */
+ for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+ retval = sysfs_create_file(&data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ if (retval < 0) {
+ dev_err(&client->dev,
+ "%s: Failed to create sysfs attributes\n",
+ __func__);
+ goto free_secure_touch_sysfs;
+ }
+ }
+
+ ft5x06_update_fw_ver(data);
+ ft5x06_update_fw_vendor_id(data);
+
+ FT_STORE_TS_DBG_INFO(data->ts_info, data->family_id, data->pdata->name,
+ data->pdata->num_max_touches, data->pdata->group_id,
+ data->pdata->fw_vkey_support ? "yes" : "no",
+ data->pdata->fw_name, data->fw_ver[0],
+ data->fw_ver[1], data->fw_ver[2]);
+ FT_STORE_TS_INFO(ts_info_buff, data->family_id, data->fw_ver[0],
+ data->fw_ver[1], data->fw_ver[2]);
+#if defined(CONFIG_FB)
+ INIT_WORK(&data->fb_notify_work, fb_notify_resume_work);
+ data->fb_notif.notifier_call = fb_notifier_callback;
+
+ err = fb_register_client(&data->fb_notif);
+
+ if (err)
+ dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
+ err);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ FT_SUSPEND_LEVEL;
+ data->early_suspend.suspend = ft5x06_ts_early_suspend;
+ data->early_suspend.resume = ft5x06_ts_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+ return 0;
+
+free_secure_touch_sysfs:
+ for (attr_count--; attr_count >= 0; attr_count--) {
+ sysfs_remove_file(&data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ }
+free_debug_dir:
+ debugfs_remove_recursive(data->dir);
+free_force_update_fw_sys:
+ device_remove_file(&client->dev, &dev_attr_force_update_fw);
+free_update_fw_sys:
+ device_remove_file(&client->dev, &dev_attr_update_fw);
+free_fw_name_sys:
+ device_remove_file(&client->dev, &dev_attr_fw_name);
+free_pocket_sys:
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support)
+ device_remove_file(&client->dev, &dev_attr_pocket);
+free_enable_sys:
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support)
+ device_remove_file(&client->dev, &dev_attr_enable);
+free_gesture_dev:
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support)
+ device_destroy(gesture_pdata->gesture_class, 0);
+free_gesture_class:
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support)
+ class_destroy(gesture_pdata->gesture_class);
+free_gesture_pdata:
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support) {
+ devm_kfree(&client->dev, gesture_pdata);
+ data->gesture_pdata = NULL;
+ }
+
+free_gpio:
+ if (gpio_is_valid(pdata->reset_gpio))
+ gpio_free(pdata->reset_gpio);
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+err_gpio_req:
+ if (data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(data->pinctrl_state_release)) {
+ devm_pinctrl_put(data->ts_pinctrl);
+ data->ts_pinctrl = NULL;
+ } else {
+ err = pinctrl_select_state(data->ts_pinctrl,
+ data->pinctrl_state_release);
+ if (err)
+ pr_err("failed to select relase pinctrl state\n");
+ }
+ }
+ if (pdata->power_on)
+ pdata->power_on(false);
+ else
+ ft5x06_power_on(data, false);
+pwr_deinit:
+ if (pdata->power_init)
+ pdata->power_init(false);
+ else
+ ft5x06_power_init(data, false);
+unreg_inputdev:
+ input_unregister_device(input_dev);
+ return err;
+}
+
+static int ft5x06_ts_remove(struct i2c_client *client)
+{
+ struct ft5x06_ts_data *data = i2c_get_clientdata(client);
+ int retval, attr_count;
+
+ if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support) {
+ device_init_wakeup(&client->dev, 0);
+ device_remove_file(&client->dev, &dev_attr_pocket);
+ device_remove_file(&client->dev, &dev_attr_enable);
+ device_destroy(data->gesture_pdata->gesture_class, 0);
+ class_destroy(data->gesture_pdata->gesture_class);
+ devm_kfree(&client->dev, data->gesture_pdata);
+ data->gesture_pdata = NULL;
+ }
+
+ debugfs_remove_recursive(data->dir);
+ device_remove_file(&client->dev, &dev_attr_force_update_fw);
+ device_remove_file(&client->dev, &dev_attr_update_fw);
+ device_remove_file(&client->dev, &dev_attr_fw_name);
+
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&data->fb_notif))
+ dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&data->early_suspend);
+#endif
+ free_irq(client->irq, data);
+
+ if (gpio_is_valid(data->pdata->reset_gpio))
+ gpio_free(data->pdata->reset_gpio);
+
+ if (gpio_is_valid(data->pdata->irq_gpio))
+ gpio_free(data->pdata->irq_gpio);
+
+ if (data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(data->pinctrl_state_release)) {
+ devm_pinctrl_put(data->ts_pinctrl);
+ data->ts_pinctrl = NULL;
+ } else {
+ retval = pinctrl_select_state(data->ts_pinctrl,
+ data->pinctrl_state_release);
+ if (retval < 0)
+ pr_err("failed to select release pinctrl state\n");
+ }
+ }
+
+ for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+ sysfs_remove_file(&data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ }
+
+ if (data->pdata->power_on)
+ data->pdata->power_on(false);
+ else
+ ft5x06_power_on(data, false);
+
+ if (data->pdata->power_init)
+ data->pdata->power_init(false);
+ else
+ ft5x06_power_init(data, false);
+
+ input_unregister_device(data->input_dev);
+ kobject_put(data->ts_info_kobj);
+ return 0;
+}
+
+static const struct i2c_device_id ft5x06_ts_id[] = {
+ {"ft5x06_ts", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id ft5x06_match_table[] = {
+ { .compatible = "focaltech,5x06",},
+ { },
+};
+#else
+#define ft5x06_match_table NULL
+#endif
+
+static struct i2c_driver ft5x06_ts_driver = {
+ .probe = ft5x06_ts_probe,
+ .remove = ft5x06_ts_remove,
+ .driver = {
+ .name = "ft5x06_ts",
+ .owner = THIS_MODULE,
+ .of_match_table = ft5x06_match_table,
+#ifdef CONFIG_PM
+ .pm = &ft5x06_ts_pm_ops,
+#endif
+ },
+ .id_table = ft5x06_ts_id,
+};
+
+static int __init ft5x06_ts_init(void)
+{
+ return i2c_add_driver(&ft5x06_ts_driver);
+}
+module_init(ft5x06_ts_init);
+
+static void __exit ft5x06_ts_exit(void)
+{
+ i2c_del_driver(&ft5x06_ts_driver);
+}
+module_exit(ft5x06_ts_exit);
+
+MODULE_DESCRIPTION("FocalTech ft5x06 TouchScreen driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/gen_vkeys.c b/drivers/input/touchscreen/gen_vkeys.c
new file mode 100644
index 000000000000..dde582f4f8bf
--- /dev/null
+++ b/drivers/input/touchscreen/gen_vkeys.c
@@ -0,0 +1,230 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/input.h>
+#include <linux/input/gen_vkeys.h>
+
+#define MAX_BUF_SIZE 256
+#define VKEY_VER_CODE "0x01"
+
+#define HEIGHT_SCALE_NUM 8
+#define HEIGHT_SCALE_DENOM 10
+
+#define VKEY_Y_OFFSET_DEFAULT 0
+
+/* numerator and denomenator for border equations */
+#define BORDER_ADJUST_NUM 3
+#define BORDER_ADJUST_DENOM 4
+
+static struct kobject *vkey_obj;
+static char *vkey_buf;
+
+static ssize_t vkey_show(struct kobject *obj,
+ struct kobj_attribute *attr, char *buf)
+{
+ strlcpy(buf, vkey_buf, MAX_BUF_SIZE);
+ return strnlen(buf, MAX_BUF_SIZE);
+}
+
+static struct kobj_attribute vkey_obj_attr = {
+ .attr = {
+ .mode = S_IRUGO,
+ },
+ .show = vkey_show,
+};
+
+static struct attribute *vkey_attr[] = {
+ &vkey_obj_attr.attr,
+ NULL,
+};
+
+static struct attribute_group vkey_grp = {
+ .attrs = vkey_attr,
+};
+
+static int vkey_parse_dt(struct device *dev,
+ struct vkeys_platform_data *pdata)
+{
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ int rc, val;
+
+ rc = of_property_read_string(np, "label", &pdata->name);
+ if (rc) {
+ dev_err(dev, "Failed to read label\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(np, "qcom,disp-maxx", &pdata->disp_maxx);
+ if (rc) {
+ dev_err(dev, "Failed to read display max x\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(np, "qcom,disp-maxy", &pdata->disp_maxy);
+ if (rc) {
+ dev_err(dev, "Failed to read display max y\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(np, "qcom,panel-maxx", &pdata->panel_maxx);
+ if (rc) {
+ dev_err(dev, "Failed to read panel max x\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(np, "qcom,panel-maxy", &pdata->panel_maxy);
+ if (rc) {
+ dev_err(dev, "Failed to read panel max y\n");
+ return -EINVAL;
+ }
+
+ prop = of_find_property(np, "qcom,key-codes", NULL);
+ if (prop) {
+ pdata->num_keys = prop->length / sizeof(u32);
+ pdata->keycodes = devm_kzalloc(dev,
+ sizeof(u32) * pdata->num_keys, GFP_KERNEL);
+ if (!pdata->keycodes)
+ return -ENOMEM;
+ rc = of_property_read_u32_array(np, "qcom,key-codes",
+ pdata->keycodes, pdata->num_keys);
+ if (rc) {
+ dev_err(dev, "Failed to read key codes\n");
+ return -EINVAL;
+ }
+ }
+
+ pdata->y_offset = VKEY_Y_OFFSET_DEFAULT;
+ rc = of_property_read_u32(np, "qcom,y-offset", &val);
+ if (!rc)
+ pdata->y_offset = val;
+ else if (rc != -EINVAL) {
+ dev_err(dev, "Failed to read y position offset\n");
+ return rc;
+ }
+ return 0;
+}
+
+static int vkeys_probe(struct platform_device *pdev)
+{
+ struct vkeys_platform_data *pdata;
+ int width, height, center_x, center_y;
+ int x1 = 0, x2 = 0, i, c = 0, ret, border;
+ char *name;
+
+ vkey_buf = devm_kzalloc(&pdev->dev, MAX_BUF_SIZE, GFP_KERNEL);
+ if (!vkey_buf) {
+ dev_err(&pdev->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ if (pdev->dev.of_node) {
+ pdata = devm_kzalloc(&pdev->dev,
+ sizeof(struct vkeys_platform_data), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&pdev->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ ret = vkey_parse_dt(&pdev->dev, pdata);
+ if (ret) {
+ dev_err(&pdev->dev, "Parsing DT failed(%d)", ret);
+ return ret;
+ }
+ } else
+ pdata = pdev->dev.platform_data;
+
+ if (!pdata || !pdata->name || !pdata->keycodes || !pdata->num_keys ||
+ !pdata->disp_maxx || !pdata->disp_maxy || !pdata->panel_maxy) {
+ dev_err(&pdev->dev, "pdata is invalid\n");
+ return -EINVAL;
+ }
+
+ border = (pdata->panel_maxx - pdata->disp_maxx) * 2;
+ width = ((pdata->disp_maxx - (border * (pdata->num_keys - 1)))
+ / pdata->num_keys);
+ height = (pdata->panel_maxy - pdata->disp_maxy);
+ center_y = pdata->disp_maxy + (height / 2) + pdata->y_offset;
+ height = height * HEIGHT_SCALE_NUM / HEIGHT_SCALE_DENOM;
+
+ x2 -= border * BORDER_ADJUST_NUM / BORDER_ADJUST_DENOM;
+
+ for (i = 0; i < pdata->num_keys; i++) {
+ x1 = x2 + border;
+ x2 = x2 + border + width;
+ center_x = x1 + (x2 - x1) / 2;
+ c += snprintf(vkey_buf + c, MAX_BUF_SIZE - c,
+ "%s:%d:%d:%d:%d:%d\n",
+ VKEY_VER_CODE, pdata->keycodes[i],
+ center_x, center_y, width, height);
+ }
+
+ vkey_buf[c] = '\0';
+
+ name = devm_kzalloc(&pdev->dev, sizeof(*name) * MAX_BUF_SIZE,
+ GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ snprintf(name, MAX_BUF_SIZE,
+ "virtualkeys.%s", pdata->name);
+ vkey_obj_attr.attr.name = name;
+
+ vkey_obj = kobject_create_and_add("board_properties", NULL);
+ if (!vkey_obj) {
+ dev_err(&pdev->dev, "unable to create kobject\n");
+ return -ENOMEM;
+ }
+
+ ret = sysfs_create_group(vkey_obj, &vkey_grp);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to create attributes\n");
+ goto destroy_kobj;
+ }
+ return 0;
+
+destroy_kobj:
+ kobject_put(vkey_obj);
+
+ return ret;
+}
+
+static int vkeys_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(vkey_obj, &vkey_grp);
+ kobject_put(vkey_obj);
+
+ return 0;
+}
+
+static struct of_device_id vkey_match_table[] = {
+ { .compatible = "qcom,gen-vkeys",},
+ { },
+};
+
+static struct platform_driver vkeys_driver = {
+ .probe = vkeys_probe,
+ .remove = vkeys_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "gen_vkeys",
+ .of_match_table = vkey_match_table,
+ },
+};
+
+module_platform_driver(vkeys_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c
new file mode 100644
index 000000000000..1a2afd1c1117
--- /dev/null
+++ b/drivers/input/touchscreen/it7258_ts_i2c.c
@@ -0,0 +1,2248 @@
+/* drivers/input/touchscreen/it7258_ts_i2c.c
+ *
+ * Copyright (C) 2014 ITE Tech. Inc.
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+#include <linux/fb.h>
+#include <linux/debugfs.h>
+#include <linux/input/mt.h>
+#include <linux/string.h>
+
+#define MAX_BUFFER_SIZE 144
+#define DEVICE_NAME "it7260"
+#define SCREEN_X_RESOLUTION 320
+#define SCREEN_Y_RESOLUTION 320
+#define DEBUGFS_DIR_NAME "ts_debug"
+#define FW_NAME "it7260_fw.bin"
+#define CFG_NAME "it7260_cfg.bin"
+#define VER_BUFFER_SIZE 4
+#define IT_FW_CHECK(x, y) \
+ (((x)[0] < (y)->data[8]) || ((x)[1] < (y)->data[9]) || \
+ ((x)[2] < (y)->data[10]) || ((x)[3] < (y)->data[11]))
+#define IT_CFG_CHECK(x, y) \
+ (((x)[0] < (y)->data[(y)->size - 8]) || \
+ ((x)[1] < (y)->data[(y)->size - 7]) || \
+ ((x)[2] < (y)->data[(y)->size - 6]) || \
+ ((x)[3] < (y)->data[(y)->size - 5]))
+#define IT7260_COORDS_ARR_SIZE 4
+
+/* all commands writes go to this idx */
+#define BUF_COMMAND 0x20
+#define BUF_SYS_COMMAND 0x40
+/*
+ * "device ready?" and "wake up please" and "read touch data" reads
+ * go to this idx
+ */
+#define BUF_QUERY 0x80
+/* most command response reads go to this idx */
+#define BUF_RESPONSE 0xA0
+#define BUF_SYS_RESPONSE 0xC0
+/* reads of "point" go through here and produce 14 bytes of data */
+#define BUF_POINT_INFO 0xE0
+
+/*
+ * commands and their subcommands. when no subcommands exist, a zero
+ * is send as the second byte
+ */
+#define CMD_IDENT_CHIP 0x00
+/* VERSION_LENGTH bytes of data in response */
+#define CMD_READ_VERSIONS 0x01
+#define SUB_CMD_READ_FIRMWARE_VERSION 0x00
+#define SUB_CMD_READ_CONFIG_VERSION 0x06
+#define VERSION_LENGTH 10
+/* subcommand is zero, next byte is power mode */
+#define CMD_PWR_CTL 0x04
+/* active mode */
+#define PWR_CTL_ACTIVE_MODE 0x00
+/* idle mode */
+#define PWR_CTL_LOW_POWER_MODE 0x01
+/* sleep mode */
+#define PWR_CTL_SLEEP_MODE 0x02
+#define WAIT_CHANGE_MODE 20
+/* command is not documented in the datasheet v1.0.0.7 */
+#define CMD_UNKNOWN_7 0x07
+#define CMD_FIRMWARE_REINIT_C 0x0C
+/* needs to be followed by 4 bytes of zeroes */
+#define CMD_CALIBRATE 0x13
+#define CMD_FIRMWARE_UPGRADE 0x60
+#define SUB_CMD_ENTER_FW_UPGRADE_MODE 0x00
+#define SUB_CMD_EXIT_FW_UPGRADE_MODE 0x80
+/* address for FW read/write */
+#define CMD_SET_START_OFFSET 0x61
+/* subcommand is number of bytes to write */
+#define CMD_FW_WRITE 0x62
+/* subcommand is number of bytes to read */
+#define CMD_FW_READ 0x63
+#define CMD_FIRMWARE_REINIT_6F 0x6F
+
+#define FW_WRITE_CHUNK_SIZE 128
+#define FW_WRITE_RETRY_COUNT 4
+#define CHIP_FLASH_SIZE 0x8000
+#define DEVICE_READY_COUNT_MAX 500
+#define DEVICE_READY_COUNT_20 20
+#define IT_I2C_WAIT_10MS 10
+#define IT_I2C_READ_RET 2
+#define IT_I2C_WRITE_RET 1
+
+/* result of reading with BUF_QUERY bits */
+#define CMD_STATUS_BITS 0x07
+#define CMD_STATUS_DONE 0x00
+#define CMD_STATUS_BUSY 0x01
+#define CMD_STATUS_ERROR 0x02
+#define CMD_STATUS_NO_CONN 0x07
+#define PT_INFO_BITS 0xF8
+#define PT_INFO_YES 0x80
+
+#define PD_FLAGS_DATA_TYPE_BITS 0xF0
+/* other types (like chip-detected gestures) exist but we do not care */
+#define PD_FLAGS_DATA_TYPE_TOUCH 0x00
+#define PD_FLAGS_IDLE_TO_ACTIVE 0x10
+/* a bit for each finger data that is valid (from lsb to msb) */
+#define PD_FLAGS_HAVE_FINGERS 0x07
+#define PD_PALM_FLAG_BIT 0x01
+#define FD_PRESSURE_BITS 0x0F
+#define FD_PRESSURE_NONE 0x00
+#define FD_PRESSURE_LIGHT 0x02
+
+#define IT_VTG_MIN_UV 1800000
+#define IT_VTG_MAX_UV 1800000
+#define IT_ACTIVE_LOAD_UA 15000
+#define IT_I2C_VTG_MIN_UV 2600000
+#define IT_I2C_VTG_MAX_UV 3300000
+#define IT_I2C_ACTIVE_LOAD_UA 10000
+#define DELAY_VTG_REG_EN 170
+
+#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE "pmx_ts_release"
+
+struct finger_data {
+ u8 xLo;
+ u8 hi;
+ u8 yLo;
+ u8 pressure;
+} __packed;
+
+struct point_data {
+ u8 flags;
+ u8 gesture_id;
+ struct finger_data fd[3];
+} __packed;
+
+struct it7260_ts_platform_data {
+ u32 irq_gpio;
+ u32 irq_gpio_flags;
+ u32 reset_gpio;
+ u32 reset_gpio_flags;
+ bool wakeup;
+ bool palm_detect_en;
+ u16 palm_detect_keycode;
+ const char *fw_name;
+ const char *cfg_name;
+ unsigned int panel_minx;
+ unsigned int panel_miny;
+ unsigned int panel_maxx;
+ unsigned int panel_maxy;
+ unsigned int disp_minx;
+ unsigned int disp_miny;
+ unsigned int disp_maxx;
+ unsigned int disp_maxy;
+ unsigned num_of_fingers;
+ unsigned int reset_delay;
+ unsigned int avdd_lpm_cur;
+ bool low_reset;
+};
+
+struct it7260_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ const struct it7260_ts_platform_data *pdata;
+ struct regulator *vdd;
+ struct regulator *avdd;
+ bool in_low_power_mode;
+ bool suspended;
+ bool fw_upgrade_result;
+ bool cfg_upgrade_result;
+ bool fw_cfg_uploading;
+ struct work_struct work_pm_relax;
+ bool calibration_success;
+ bool had_finger_down;
+ char fw_name[MAX_BUFFER_SIZE];
+ char cfg_name[MAX_BUFFER_SIZE];
+ struct mutex fw_cfg_mutex;
+ u8 fw_ver[VER_BUFFER_SIZE];
+ u8 cfg_ver[VER_BUFFER_SIZE];
+#ifdef CONFIG_FB
+ struct notifier_block fb_notif;
+#endif
+ struct dentry *dir;
+ struct pinctrl *ts_pinctrl;
+ struct pinctrl_state *pinctrl_state_active;
+ struct pinctrl_state *pinctrl_state_suspend;
+ struct pinctrl_state *pinctrl_state_release;
+};
+
+/* Function declarations */
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
+static int it7260_ts_resume(struct device *dev);
+static int it7260_ts_suspend(struct device *dev);
+
+static int it7260_debug_suspend_set(void *_data, u64 val)
+{
+ struct it7260_ts_data *ts_data = _data;
+
+ if (val)
+ it7260_ts_suspend(&ts_data->client->dev);
+ else
+ it7260_ts_resume(&ts_data->client->dev);
+
+ return 0;
+}
+
+static int it7260_debug_suspend_get(void *_data, u64 *val)
+{
+ struct it7260_ts_data *ts_data = _data;
+
+ mutex_lock(&ts_data->input_dev->mutex);
+ *val = ts_data->suspended;
+ mutex_lock(&ts_data->input_dev->mutex);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, it7260_debug_suspend_get,
+ it7260_debug_suspend_set, "%lld\n");
+
+/* internal use func - does not make sure chip is ready before read */
+static int it7260_i2c_read_no_ready_check(struct it7260_ts_data *ts_data,
+ uint8_t buf_index, uint8_t *buffer, uint16_t buf_len)
+{
+ int ret;
+ struct i2c_msg msgs[2] = {
+ {
+ .addr = ts_data->client->addr,
+ .flags = I2C_M_NOSTART,
+ .len = 1,
+ .buf = &buf_index
+ },
+ {
+ .addr = ts_data->client->addr,
+ .flags = I2C_M_RD,
+ .len = buf_len,
+ .buf = buffer
+ }
+ };
+
+ memset(buffer, 0xFF, buf_len);
+
+ ret = i2c_transfer(ts_data->client->adapter, msgs, 2);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev, "i2c read failed %d\n", ret);
+
+ return ret;
+}
+
+static int it7260_i2c_write_no_ready_check(struct it7260_ts_data *ts_data,
+ uint8_t buf_index, const uint8_t *buffer, uint16_t buf_len)
+{
+ uint8_t txbuf[257];
+ int ret;
+ struct i2c_msg msg = {
+ .addr = ts_data->client->addr,
+ .flags = 0,
+ .len = buf_len + 1,
+ .buf = txbuf
+ };
+
+ /* just to be careful */
+ if (buf_len > sizeof(txbuf) - 1) {
+ dev_err(&ts_data->client->dev, "buf length is out of limit\n");
+ return false;
+ }
+
+ txbuf[0] = buf_index;
+ memcpy(txbuf + 1, buffer, buf_len);
+
+ ret = i2c_transfer(ts_data->client->adapter, &msg, 1);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev, "i2c write failed %d\n", ret);
+
+ return ret;
+}
+
+/*
+ * Device is apparently always ready for I2C communication but not for
+ * actual register reads/writes. This function checks if it is ready
+ * for that too. The results of this call often were ignored.
+ * If forever is set to TRUE, then check the device's status until it
+ * becomes ready with 500 retries at max. Otherwise retry 25 times only.
+ * If slowly is set to TRUE, then add sleep of 50 ms in each retry,
+ * otherwise don't sleep.
+ */
+static int it7260_wait_device_ready(struct it7260_ts_data *ts_data,
+ bool forever, bool slowly)
+{
+ uint8_t query;
+ uint32_t count = DEVICE_READY_COUNT_20;
+ int ret;
+
+ if (ts_data->fw_cfg_uploading || forever)
+ count = DEVICE_READY_COUNT_MAX;
+
+ do {
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &query,
+ sizeof(query));
+ if (ret < 0 && ((query & CMD_STATUS_BITS)
+ == CMD_STATUS_NO_CONN))
+ continue;
+
+ if ((query & CMD_STATUS_BITS) == CMD_STATUS_DONE)
+ break;
+
+ query = CMD_STATUS_BUSY;
+ if (slowly)
+ msleep(IT_I2C_WAIT_10MS);
+ } while (--count);
+
+ return ((!(query & CMD_STATUS_BITS)) ? 0 : -ENODEV);
+}
+
+static int it7260_i2c_read(struct it7260_ts_data *ts_data, uint8_t buf_index,
+ uint8_t *buffer, uint16_t buf_len)
+{
+ int ret;
+
+ ret = it7260_wait_device_ready(ts_data, false, false);
+ if (ret < 0)
+ return ret;
+
+ return it7260_i2c_read_no_ready_check(ts_data, buf_index,
+ buffer, buf_len);
+}
+
+static int it7260_i2c_write(struct it7260_ts_data *ts_data, uint8_t buf_index,
+ const uint8_t *buffer, uint16_t buf_len)
+{
+ int ret;
+
+ ret = it7260_wait_device_ready(ts_data, false, false);
+ if (ret < 0)
+ return ret;
+
+ return it7260_i2c_write_no_ready_check(ts_data, buf_index,
+ buffer, buf_len);
+}
+
+static int it7260_firmware_reinitialize(struct it7260_ts_data *ts_data,
+ u8 command)
+{
+ uint8_t cmd[] = {command};
+ uint8_t rsp[2];
+ int ret;
+
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, sizeof(cmd));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write fw reinit command %d\n", ret);
+ return ret;
+ }
+
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, rsp, sizeof(rsp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
+
+ /* a reply of two zero bytes signifies success */
+ if (rsp[0] == 0 && rsp[1] == 0)
+ return 0;
+ else
+ return -EIO;
+}
+
+static int it7260_enter_exit_fw_ugrade_mode(struct it7260_ts_data *ts_data,
+ bool enter)
+{
+ uint8_t cmd[] = {CMD_FIRMWARE_UPGRADE, 0, 'I', 'T', '7', '2',
+ '6', '0', 0x55, 0xAA};
+ uint8_t resp[2];
+ int ret;
+
+ cmd[1] = enter ? SUB_CMD_ENTER_FW_UPGRADE_MODE :
+ SUB_CMD_EXIT_FW_UPGRADE_MODE;
+
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, sizeof(cmd));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_FIRMWARE_UPGRADE %d\n", ret);
+ return ret;
+ }
+
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, resp, sizeof(resp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
+
+ /* a reply of two zero bytes signifies success */
+ if (resp[0] == 0 && resp[1] == 0)
+ return 0;
+ else
+ return -EIO;
+}
+
+static int it7260_set_start_offset(struct it7260_ts_data *ts_data,
+ uint16_t offset)
+{
+ uint8_t cmd[] = {CMD_SET_START_OFFSET, 0, ((uint8_t)(offset)),
+ ((uint8_t)((offset) >> 8))};
+ uint8_t resp[2];
+ int ret;
+
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, 4);
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_SET_START_OFFSET %d\n", ret);
+ return ret;
+ }
+
+
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, resp, sizeof(resp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
+
+ /* a reply of two zero bytes signifies success */
+ if (resp[0] == 0 && resp[1] == 0)
+ return 0;
+ else
+ return -EIO;
+}
+
+
+/* write fw_length bytes from fw_data at chip offset wr_start_offset */
+static int it7260_fw_flash_write_verify(struct it7260_ts_data *ts_data,
+ unsigned int fw_length, const uint8_t *fw_data,
+ uint16_t wr_start_offset)
+{
+ uint32_t cur_data_off;
+
+ for (cur_data_off = 0; cur_data_off < fw_length;
+ cur_data_off += FW_WRITE_CHUNK_SIZE) {
+
+ uint8_t cmd_write[2 + FW_WRITE_CHUNK_SIZE] = {CMD_FW_WRITE};
+ uint8_t buf_read[FW_WRITE_CHUNK_SIZE];
+ uint8_t cmd_read[2] = {CMD_FW_READ};
+ unsigned i, retries;
+ uint32_t cur_wr_size;
+
+ /* figure out how much to write */
+ cur_wr_size = fw_length - cur_data_off;
+ if (cur_wr_size > FW_WRITE_CHUNK_SIZE)
+ cur_wr_size = FW_WRITE_CHUNK_SIZE;
+
+ /* prepare the write command */
+ cmd_write[1] = cur_wr_size;
+ for (i = 0; i < cur_wr_size; i++)
+ cmd_write[i + 2] = fw_data[cur_data_off + i];
+
+ /* prepare the read command */
+ cmd_read[1] = cur_wr_size;
+
+ for (retries = 0; retries < FW_WRITE_RETRY_COUNT;
+ retries++) {
+
+ /* set write offset and write the data */
+ it7260_set_start_offset(ts_data,
+ wr_start_offset + cur_data_off);
+ it7260_i2c_write(ts_data, BUF_COMMAND, cmd_write,
+ cur_wr_size + 2);
+
+ /* set offset and read the data back */
+ it7260_set_start_offset(ts_data,
+ wr_start_offset + cur_data_off);
+ it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read,
+ sizeof(cmd_read));
+ it7260_i2c_read(ts_data, BUF_RESPONSE, buf_read,
+ cur_wr_size);
+
+ /* verify. If success break out of retry loop */
+ i = 0;
+ while (i < cur_wr_size &&
+ buf_read[i] == cmd_write[i + 2])
+ i++;
+ if (i == cur_wr_size)
+ break;
+ }
+ /* if we've failed after all the retries, tell the caller */
+ if (retries == FW_WRITE_RETRY_COUNT) {
+ dev_err(&ts_data->client->dev,
+ "write of data offset %u failed on try %u at byte %u/%u\n",
+ cur_data_off, retries, i, cur_wr_size);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * this code to get versions from the chip via i2c transactions, and save
+ * them in driver data structure.
+ */
+static void it7260_get_chip_versions(struct it7260_ts_data *ts_data)
+{
+ static const u8 cmd_read_fw_ver[] = {CMD_READ_VERSIONS,
+ SUB_CMD_READ_FIRMWARE_VERSION};
+ static const u8 cmd_read_cfg_ver[] = {CMD_READ_VERSIONS,
+ SUB_CMD_READ_CONFIG_VERSION};
+ u8 ver_fw[VERSION_LENGTH], ver_cfg[VERSION_LENGTH];
+ int ret;
+
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read_fw_ver,
+ sizeof(cmd_read_fw_ver));
+ if (ret == IT_I2C_WRITE_RET) {
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE,
+ ver_fw, VERSION_LENGTH);
+ if (ret == IT_I2C_READ_RET)
+ memcpy(ts_data->fw_ver, ver_fw + (5 * sizeof(u8)),
+ VER_BUFFER_SIZE * sizeof(u8));
+ else
+ dev_err(&ts_data->client->dev,
+ "failed to read fw-ver from chip %d\n", ret);
+ } else {
+ dev_err(&ts_data->client->dev,
+ "failed to write fw-read command %d\n", ret);
+ }
+
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read_cfg_ver,
+ sizeof(cmd_read_cfg_ver));
+ if (ret == IT_I2C_WRITE_RET) {
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE,
+ ver_cfg, VERSION_LENGTH);
+ if (ret == IT_I2C_READ_RET)
+ memcpy(ts_data->cfg_ver, ver_cfg + (1 * sizeof(u8)),
+ VER_BUFFER_SIZE * sizeof(u8));
+ else
+ dev_err(&ts_data->client->dev,
+ "failed to read cfg-ver from chip %d\n", ret);
+ } else {
+ dev_err(&ts_data->client->dev,
+ "failed to write cfg-read command %d\n", ret);
+ }
+
+ dev_info(&ts_data->client->dev, "Current fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1], ts_data->fw_ver[2],
+ ts_data->fw_ver[3], ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
+}
+
+static int it7260_cfg_upload(struct it7260_ts_data *ts_data, bool force)
+{
+ const struct firmware *cfg = NULL;
+ int ret;
+ bool cfg_upgrade = false;
+ struct device *dev = &ts_data->client->dev;
+
+ ret = request_firmware(&cfg, ts_data->cfg_name, dev);
+ if (ret) {
+ dev_err(dev, "failed to get config data %s for it7260 %d\n",
+ ts_data->cfg_name, ret);
+ return ret;
+ }
+
+ /*
+ * This compares the cfg version number from chip and the cfg
+ * data file. IT flashes only when version of cfg data file is
+ * greater than that of chip or if it is set for force cfg upgrade.
+ */
+ if (force)
+ cfg_upgrade = true;
+ else if (IT_CFG_CHECK(ts_data->cfg_ver, cfg))
+ cfg_upgrade = true;
+
+ if (!cfg_upgrade) {
+ dev_err(dev, "CFG upgrade not required ...\n");
+ dev_info(dev,
+ "Chip CFG : %X.%X.%X.%X Binary CFG : %X.%X.%X.%X\n",
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3],
+ cfg->data[cfg->size - 8], cfg->data[cfg->size - 7],
+ cfg->data[cfg->size - 6], cfg->data[cfg->size - 5]);
+ ret = -EFAULT;
+ goto out;
+ } else {
+ dev_info(dev, "Config upgrading...\n");
+
+ disable_irq(ts_data->client->irq);
+ /* enter cfg upload mode */
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, true);
+ if (ret < 0) {
+ dev_err(dev, "Can't enter cfg upgrade mode %d\n", ret);
+ enable_irq(ts_data->client->irq);
+ goto out;
+ }
+ /* flash config data if requested */
+ ret = it7260_fw_flash_write_verify(ts_data, cfg->size,
+ cfg->data, CHIP_FLASH_SIZE - cfg->size);
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to upgrade touch cfg data %d\n", ret);
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, false);
+ if (ret < 0)
+ dev_err(dev,
+ "Can't exit cfg upgrade mode%d\n", ret);
+
+ ret = it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F);
+ if (ret < 0)
+ dev_err(dev, "Can't reinit cfg %d\n", ret);
+
+ ret = -EIO;
+ enable_irq(ts_data->client->irq);
+ goto out;
+ } else {
+ memcpy(ts_data->cfg_ver, cfg->data +
+ (cfg->size - 8 * sizeof(u8)),
+ VER_BUFFER_SIZE * sizeof(u8));
+ dev_info(dev, "CFG upgrade is success. New cfg ver: %X.%X.%X.%X\n",
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
+
+ }
+ enable_irq(ts_data->client->irq);
+ }
+
+out:
+ release_firmware(cfg);
+
+ return ret;
+}
+
+static int it7260_fw_upload(struct it7260_ts_data *ts_data, bool force)
+{
+ const struct firmware *fw = NULL;
+ int ret;
+ bool fw_upgrade = false;
+ struct device *dev = &ts_data->client->dev;
+
+ ret = request_firmware(&fw, ts_data->fw_name, dev);
+ if (ret) {
+ dev_err(dev, "failed to get firmware %s for it7260 %d\n",
+ ts_data->fw_name, ret);
+ return ret;
+ }
+
+ /*
+ * This compares the fw version number from chip and the fw data
+ * file. It flashes only when version of fw data file is greater
+ * than that of chip or it it is set for force fw upgrade.
+ */
+ if (force)
+ fw_upgrade = true;
+ else if (IT_FW_CHECK(ts_data->fw_ver, fw))
+ fw_upgrade = true;
+
+ if (!fw_upgrade) {
+ dev_err(dev, "FW upgrade not required ...\n");
+ dev_info(dev, "Chip FW : %X.%X.%X.%X Binary FW : %X.%X.%X.%X\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3],
+ fw->data[8], fw->data[9], fw->data[10], fw->data[11]);
+ ret = -EFAULT;
+ goto out;
+ } else {
+ dev_info(dev, "Firmware upgrading...\n");
+
+ disable_irq(ts_data->client->irq);
+ /* enter fw upload mode */
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, true);
+ if (ret < 0) {
+ dev_err(dev, "Can't enter fw upgrade mode %d\n", ret);
+ enable_irq(ts_data->client->irq);
+ goto out;
+ }
+ /* flash the firmware if requested */
+ ret = it7260_fw_flash_write_verify(ts_data, fw->size,
+ fw->data, 0);
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to upgrade touch firmware %d\n", ret);
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, false);
+ if (ret < 0)
+ dev_err(dev,
+ "Can't exit fw upgrade mode %d\n", ret);
+
+ ret = it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F);
+ if (ret < 0)
+ dev_err(dev, "Can't reinit firmware %d\n", ret);
+
+ ret = -EIO;
+ enable_irq(ts_data->client->irq);
+ goto out;
+ } else {
+ memcpy(ts_data->fw_ver, fw->data + (8 * sizeof(u8)),
+ VER_BUFFER_SIZE * sizeof(u8));
+ dev_info(dev, "FW upgrade is success. New fw ver: %X.%X.%X.%X\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3]);
+ }
+ enable_irq(ts_data->client->irq);
+ }
+
+out:
+ release_firmware(fw);
+
+ return ret;
+}
+
+static int it7260_ts_chip_low_power_mode(struct it7260_ts_data *ts_data,
+ const u8 sleep_type)
+{
+ const u8 cmd_sleep[] = {CMD_PWR_CTL, 0x00, sleep_type};
+ u8 dummy;
+ int ret;
+
+ if (sleep_type) {
+ ret = it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND,
+ cmd_sleep, sizeof(cmd_sleep));
+ if (ret != IT_I2C_WRITE_RET)
+ dev_err(&ts_data->client->dev,
+ "Can't go to sleep or low power mode(%d) %d\n",
+ sleep_type, ret);
+ else
+ ret = 0;
+ } else {
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &dummy,
+ sizeof(dummy));
+ if (ret != IT_I2C_READ_RET)
+ dev_err(&ts_data->client->dev,
+ "Can't go to active mode %d\n", ret);
+ else
+ ret = 0;
+ }
+
+ msleep(WAIT_CHANGE_MODE);
+ return ret;
+}
+
+static ssize_t sysfs_fw_upgrade_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ int mode = 0, ret;
+
+ if (ts_data->suspended) {
+ dev_err(dev, "Device is suspended, can't flash fw!!!\n");
+ return -EBUSY;
+ }
+
+ ret = kstrtoint(buf, 10, &mode);
+ if (ret) {
+ dev_err(dev, "failed to read input for sysfs\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&ts_data->fw_cfg_mutex);
+ if (mode == 1) {
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_fw_upload(ts_data, false);
+ if (ret) {
+ dev_err(dev, "Failed to flash fw: %d", ret);
+ ts_data->fw_upgrade_result = false;
+ } else {
+ ts_data->fw_upgrade_result = true;
+ }
+ ts_data->fw_cfg_uploading = false;
+ }
+ mutex_unlock(&ts_data->fw_cfg_mutex);
+
+ return count;
+}
+
+static ssize_t sysfs_cfg_upgrade_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ int mode = 0, ret;
+
+ if (ts_data->suspended) {
+ dev_err(dev, "Device is suspended, can't flash cfg!!!\n");
+ return -EBUSY;
+ }
+
+ ret = kstrtoint(buf, 10, &mode);
+ if (ret) {
+ dev_err(dev, "failed to read input for sysfs\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&ts_data->fw_cfg_mutex);
+ if (mode == 1) {
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_cfg_upload(ts_data, false);
+ if (ret) {
+ dev_err(dev, "Failed to flash cfg: %d", ret);
+ ts_data->cfg_upgrade_result = false;
+ } else {
+ ts_data->cfg_upgrade_result = true;
+ }
+ ts_data->fw_cfg_uploading = false;
+ }
+ mutex_unlock(&ts_data->fw_cfg_mutex);
+
+ return count;
+}
+
+static ssize_t sysfs_fw_upgrade_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
+ ts_data->fw_upgrade_result);
+}
+
+static ssize_t sysfs_cfg_upgrade_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
+ ts_data->cfg_upgrade_result);
+}
+
+static ssize_t sysfs_force_fw_upgrade_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ int mode = 0, ret;
+
+ if (ts_data->suspended) {
+ dev_err(dev, "Device is suspended, can't flash fw!!!\n");
+ return -EBUSY;
+ }
+
+ ret = kstrtoint(buf, 10, &mode);
+ if (ret) {
+ dev_err(dev, "failed to read input for sysfs\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&ts_data->fw_cfg_mutex);
+ if (mode == 1) {
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_fw_upload(ts_data, true);
+ if (ret) {
+ dev_err(dev, "Failed to force flash fw: %d", ret);
+ ts_data->fw_upgrade_result = false;
+ } else {
+ ts_data->fw_upgrade_result = true;
+ }
+ ts_data->fw_cfg_uploading = false;
+ }
+ mutex_unlock(&ts_data->fw_cfg_mutex);
+
+ return count;
+}
+
+static ssize_t sysfs_force_cfg_upgrade_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ int mode = 0, ret;
+
+ if (ts_data->suspended) {
+ dev_err(dev, "Device is suspended, can't flash cfg!!!\n");
+ return -EBUSY;
+ }
+
+ ret = kstrtoint(buf, 10, &mode);
+ if (ret) {
+ dev_err(dev, "failed to read input for sysfs\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&ts_data->fw_cfg_mutex);
+ if (mode == 1) {
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_cfg_upload(ts_data, true);
+ if (ret) {
+ dev_err(dev, "Failed to force flash cfg: %d", ret);
+ ts_data->cfg_upgrade_result = false;
+ } else {
+ ts_data->cfg_upgrade_result = true;
+ }
+ ts_data->fw_cfg_uploading = false;
+ }
+ mutex_unlock(&ts_data->fw_cfg_mutex);
+
+ return count;
+}
+
+static ssize_t sysfs_force_fw_upgrade_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, MAX_BUFFER_SIZE, "%d", ts_data->fw_upgrade_result);
+}
+
+static ssize_t sysfs_force_cfg_upgrade_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, MAX_BUFFER_SIZE, "%d",
+ ts_data->cfg_upgrade_result);
+}
+
+static ssize_t sysfs_calibration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
+ ts_data->calibration_success);
+}
+
+static int it7260_ts_send_calibration_cmd(struct it7260_ts_data *ts_data,
+ bool auto_tune_on)
+{
+ uint8_t cmd_calibrate[] = {CMD_CALIBRATE, 0,
+ auto_tune_on ? 1 : 0, 0, 0};
+
+ return it7260_i2c_write(ts_data, BUF_COMMAND, cmd_calibrate,
+ sizeof(cmd_calibrate));
+}
+
+static ssize_t sysfs_calibration_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ uint8_t resp;
+ int ret;
+
+ ret = it7260_ts_send_calibration_cmd(ts_data, false);
+ if (ret < 0) {
+ dev_err(dev, "failed to send calibration command\n");
+ } else {
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, &resp,
+ sizeof(resp));
+ if (ret == IT_I2C_READ_RET)
+ ts_data->calibration_success = true;
+
+ /*
+ * previous logic that was here never called
+ * it7260_firmware_reinitialize() due to checking a
+ * guaranteed-not-null value against null. We now
+ * call it. Hopefully this is OK
+ */
+ if (!resp)
+ dev_dbg(dev, "it7260_firmware_reinitialize-> %s\n",
+ it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F) ? "success" : "fail");
+ }
+
+ return count;
+}
+
+static ssize_t sysfs_point_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ uint8_t pt_data[sizeof(struct point_data)];
+ int readSuccess;
+ ssize_t ret;
+
+ readSuccess = it7260_i2c_read_no_ready_check(ts_data, BUF_POINT_INFO,
+ pt_data, sizeof(pt_data));
+
+ if (readSuccess == IT_I2C_READ_RET) {
+ ret = scnprintf(buf, MAX_BUFFER_SIZE,
+ "point_show read ret[%d]--point[%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]\n",
+ readSuccess, pt_data[0], pt_data[1],
+ pt_data[2], pt_data[3], pt_data[4],
+ pt_data[5], pt_data[6], pt_data[7],
+ pt_data[8], pt_data[9], pt_data[10],
+ pt_data[11], pt_data[12], pt_data[13]);
+ } else {
+ ret = scnprintf(buf, MAX_BUFFER_SIZE,
+ "failed to read point data\n");
+ }
+ dev_dbg(dev, "%s", buf);
+
+ return ret;
+}
+
+static ssize_t sysfs_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, MAX_BUFFER_SIZE,
+ "fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3],
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
+}
+
+static ssize_t sysfs_sleep_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ /*
+ * The usefulness of this was questionable at best - we were at least
+ * leaking a byte of kernel data (by claiming to return a byte but not
+ * writing to buf. To fix this now we actually return the sleep status
+ */
+ *buf = ts_data->suspended ? '1' : '0';
+
+ return 1;
+}
+
+static ssize_t sysfs_sleep_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ int go_to_sleep, ret;
+
+ ret = kstrtoint(buf, 10, &go_to_sleep);
+
+ /* (ts_data->suspended == true && goToSleepVal > 0) means
+ * device is already suspended and you want it to be in sleep,
+ * (ts_data->suspended == false && goToSleepVal == 0) means
+ * device is already active and you also want it to be active.
+ */
+ if ((ts_data->suspended && go_to_sleep > 0) ||
+ (!ts_data->suspended && go_to_sleep == 0))
+ dev_err(dev, "duplicate request to %s chip\n",
+ go_to_sleep ? "sleep" : "wake");
+ else if (go_to_sleep) {
+ disable_irq(ts_data->client->irq);
+ it7260_ts_chip_low_power_mode(ts_data, PWR_CTL_SLEEP_MODE);
+ dev_dbg(dev, "touch is going to sleep...\n");
+ } else {
+ it7260_ts_chip_low_power_mode(ts_data, PWR_CTL_ACTIVE_MODE);
+ enable_irq(ts_data->client->irq);
+ dev_dbg(dev, "touch is going to wake!\n");
+ }
+ ts_data->suspended = go_to_sleep;
+
+ return count;
+}
+
+static ssize_t sysfs_cfg_name_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ char *strptr;
+
+ if (count >= MAX_BUFFER_SIZE) {
+ dev_err(dev, "Input over %d chars long\n", MAX_BUFFER_SIZE);
+ return -EINVAL;
+ }
+
+ strptr = strnstr(buf, ".bin", count);
+ if (!strptr) {
+ dev_err(dev, "Input is invalid cfg file\n");
+ return -EINVAL;
+ }
+
+ strlcpy(ts_data->cfg_name, buf, count);
+
+ return count;
+}
+
+static ssize_t sysfs_cfg_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ if (strnlen(ts_data->cfg_name, MAX_BUFFER_SIZE) > 0)
+ return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n",
+ ts_data->cfg_name);
+ else
+ return scnprintf(buf, MAX_BUFFER_SIZE,
+ "No config file name given\n");
+}
+
+static ssize_t sysfs_fw_name_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ char *strptr;
+
+ if (count >= MAX_BUFFER_SIZE) {
+ dev_err(dev, "Input over %d chars long\n", MAX_BUFFER_SIZE);
+ return -EINVAL;
+ }
+
+ strptr = strnstr(buf, ".bin", count);
+ if (!strptr) {
+ dev_err(dev, "Input is invalid fw file\n");
+ return -EINVAL;
+ }
+
+ strlcpy(ts_data->fw_name, buf, count);
+ return count;
+}
+
+static ssize_t sysfs_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ if (strnlen(ts_data->fw_name, MAX_BUFFER_SIZE) > 0)
+ return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n",
+ ts_data->fw_name);
+ else
+ return scnprintf(buf, MAX_BUFFER_SIZE,
+ "No firmware file name given\n");
+}
+
+static DEVICE_ATTR(version, S_IRUGO | S_IWUSR,
+ sysfs_version_show, NULL);
+static DEVICE_ATTR(sleep, S_IRUGO | S_IWUSR,
+ sysfs_sleep_show, sysfs_sleep_store);
+static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR,
+ sysfs_calibration_show, sysfs_calibration_store);
+static DEVICE_ATTR(fw_update, S_IRUGO | S_IWUSR,
+ sysfs_fw_upgrade_show, sysfs_fw_upgrade_store);
+static DEVICE_ATTR(cfg_update, S_IRUGO | S_IWUSR,
+ sysfs_cfg_upgrade_show, sysfs_cfg_upgrade_store);
+static DEVICE_ATTR(point, S_IRUGO | S_IWUSR,
+ sysfs_point_show, NULL);
+static DEVICE_ATTR(fw_name, S_IRUGO | S_IWUSR,
+ sysfs_fw_name_show, sysfs_fw_name_store);
+static DEVICE_ATTR(cfg_name, S_IRUGO | S_IWUSR,
+ sysfs_cfg_name_show, sysfs_cfg_name_store);
+static DEVICE_ATTR(force_fw_update, S_IRUGO | S_IWUSR,
+ sysfs_force_fw_upgrade_show,
+ sysfs_force_fw_upgrade_store);
+static DEVICE_ATTR(force_cfg_update, S_IRUGO | S_IWUSR,
+ sysfs_force_cfg_upgrade_show,
+ sysfs_force_cfg_upgrade_store);
+
+static struct attribute *it7260_attributes[] = {
+ &dev_attr_version.attr,
+ &dev_attr_sleep.attr,
+ &dev_attr_calibration.attr,
+ &dev_attr_fw_update.attr,
+ &dev_attr_cfg_update.attr,
+ &dev_attr_point.attr,
+ &dev_attr_fw_name.attr,
+ &dev_attr_cfg_name.attr,
+ &dev_attr_force_fw_update.attr,
+ &dev_attr_force_cfg_update.attr,
+ NULL
+};
+
+static const struct attribute_group it7260_attr_group = {
+ .attrs = it7260_attributes,
+};
+
+static void it7260_ts_release_all(struct it7260_ts_data *ts_data)
+{
+ int finger;
+
+ for (finger = 0; finger < ts_data->pdata->num_of_fingers; finger++) {
+ input_mt_slot(ts_data->input_dev, finger);
+ input_mt_report_slot_state(ts_data->input_dev,
+ MT_TOOL_FINGER, 0);
+ }
+
+ input_report_key(ts_data->input_dev, BTN_TOUCH, 0);
+ input_sync(ts_data->input_dev);
+}
+
+static irqreturn_t it7260_ts_threaded_handler(int irq, void *devid)
+{
+ struct point_data pt_data;
+ struct it7260_ts_data *ts_data = devid;
+ struct input_dev *input_dev = ts_data->input_dev;
+ u8 dev_status, finger, touch_count = 0, finger_status;
+ u8 pressure = FD_PRESSURE_NONE;
+ u16 x, y;
+ bool palm_detected;
+ int ret;
+
+ /* verify there is point data to read & it is readable and valid */
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &dev_status,
+ sizeof(dev_status));
+ if (ret == IT_I2C_READ_RET)
+ if (!((dev_status & PT_INFO_BITS) & PT_INFO_YES))
+ return IRQ_HANDLED;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_POINT_INFO,
+ (void *)&pt_data, sizeof(pt_data));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read point data buffer\n");
+ return IRQ_HANDLED;
+ }
+
+ /* Check if controller moves from idle to active state */
+ if ((pt_data.flags & PD_FLAGS_DATA_TYPE_BITS) !=
+ PD_FLAGS_DATA_TYPE_TOUCH) {
+ /*
+ * This code adds the touch-to-wake functionality to the ITE
+ * tech driver. When user puts a finger on touch controller in
+ * idle state, the controller moves to active state and driver
+ * sends the KEY_WAKEUP event to wake the device. The
+ * pm_stay_awake() call tells the pm core to stay awake until
+ * the CPU cores are up already. The schedule_work() call
+ * schedule a work that tells the pm core to relax once the CPU
+ * cores are up.
+ */
+ if ((pt_data.flags & PD_FLAGS_DATA_TYPE_BITS) ==
+ PD_FLAGS_IDLE_TO_ACTIVE &&
+ pt_data.gesture_id == 0) {
+ pm_stay_awake(&ts_data->client->dev);
+ input_report_key(input_dev, KEY_WAKEUP, 1);
+ input_sync(input_dev);
+ input_report_key(input_dev, KEY_WAKEUP, 0);
+ input_sync(input_dev);
+ schedule_work(&ts_data->work_pm_relax);
+ } else {
+ dev_dbg(&ts_data->client->dev,
+ "Ignore the touch data\n");
+ }
+ return IRQ_HANDLED;
+ }
+
+ /*
+ * Check if touch data also includes any palm gesture or not.
+ * If palm gesture is detected, then send the keycode parsed
+ * from the DT.
+ */
+ palm_detected = pt_data.gesture_id & PD_PALM_FLAG_BIT;
+ if (palm_detected && ts_data->pdata->palm_detect_en) {
+ input_report_key(input_dev,
+ ts_data->pdata->palm_detect_keycode, 1);
+ input_sync(input_dev);
+ input_report_key(input_dev,
+ ts_data->pdata->palm_detect_keycode, 0);
+ input_sync(input_dev);
+ }
+
+ for (finger = 0; finger < ts_data->pdata->num_of_fingers; finger++) {
+ finger_status = pt_data.flags & (0x01 << finger);
+
+ input_mt_slot(input_dev, finger);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+ finger_status != 0);
+
+ x = pt_data.fd[finger].xLo +
+ (((u16)(pt_data.fd[finger].hi & 0x0F)) << 8);
+ y = pt_data.fd[finger].yLo +
+ (((u16)(pt_data.fd[finger].hi & 0xF0)) << 4);
+
+ pressure = pt_data.fd[finger].pressure & FD_PRESSURE_BITS;
+
+ if (finger_status) {
+ if (pressure >= FD_PRESSURE_LIGHT) {
+ input_report_key(input_dev, BTN_TOUCH, 1);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_X, x);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_Y, y);
+ touch_count++;
+ }
+ }
+ }
+
+ input_report_key(input_dev, BTN_TOUCH, touch_count > 0);
+ input_sync(input_dev);
+
+ return IRQ_HANDLED;
+}
+
+static void it7260_ts_work_func(struct work_struct *work)
+{
+ struct it7260_ts_data *ts_data = container_of(work,
+ struct it7260_ts_data, work_pm_relax);
+
+ pm_relax(&ts_data->client->dev);
+}
+
+static int it7260_ts_chip_identify(struct it7260_ts_data *ts_data)
+{
+ static const uint8_t cmd_ident[] = {CMD_IDENT_CHIP};
+ static const uint8_t expected_id[] = {0x0A, 'I', 'T', 'E', '7',
+ '2', '6', '0'};
+ uint8_t chip_id[10] = {0,};
+ int ret;
+
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ * FALSE means to retry 20 times at max to read the chip status.
+ * TRUE means to add delay in each retry.
+ */
+ ret = it7260_wait_device_ready(ts_data, false, true);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+ return ret;
+ }
+
+ ret = it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_ident,
+ sizeof(cmd_ident));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_IDENT_CHIP %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ * TRUE means to retry 500 times at max to read the chip status.
+ * FALSE means to avoid unnecessary delays in each retry.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+ return ret;
+ }
+
+
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE, chip_id,
+ sizeof(chip_id));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip-id %d\n", ret);
+ return ret;
+ }
+ dev_info(&ts_data->client->dev,
+ "it7260_ts_chip_identify read id: %02X %c%c%c%c%c%c%c %c%c\n",
+ chip_id[0], chip_id[1], chip_id[2], chip_id[3], chip_id[4],
+ chip_id[5], chip_id[6], chip_id[7], chip_id[8], chip_id[9]);
+
+ if (memcmp(chip_id, expected_id, sizeof(expected_id)))
+ return -EINVAL;
+
+ if (chip_id[8] == '5' && chip_id[9] == '6')
+ dev_info(&ts_data->client->dev, "rev BX3 found\n");
+ else if (chip_id[8] == '6' && chip_id[9] == '6')
+ dev_info(&ts_data->client->dev, "rev BX4 found\n");
+ else
+ dev_info(&ts_data->client->dev, "unknown revision (0x%02X 0x%02X) found\n",
+ chip_id[8], chip_id[9]);
+
+ return 0;
+}
+
+static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
+{
+ return (regulator_count_voltages(reg) > 0) ?
+ regulator_set_load(reg, load_uA) : 0;
+}
+
+static int it7260_regulator_configure(struct it7260_ts_data *ts_data, bool on)
+{
+ int retval;
+
+ if (on == false)
+ goto hw_shutdown;
+
+ ts_data->vdd = devm_regulator_get(&ts_data->client->dev, "vdd");
+ if (IS_ERR(ts_data->vdd)) {
+ dev_err(&ts_data->client->dev,
+ "%s: Failed to get vdd regulator\n", __func__);
+ return PTR_ERR(ts_data->vdd);
+ }
+
+ if (regulator_count_voltages(ts_data->vdd) > 0) {
+ retval = regulator_set_voltage(ts_data->vdd,
+ IT_VTG_MIN_UV, IT_VTG_MAX_UV);
+ if (retval) {
+ dev_err(&ts_data->client->dev,
+ "regulator set_vtg failed retval =%d\n",
+ retval);
+ goto err_set_vtg_vdd;
+ }
+ }
+
+ ts_data->avdd = devm_regulator_get(&ts_data->client->dev, "avdd");
+ if (IS_ERR(ts_data->avdd)) {
+ dev_err(&ts_data->client->dev,
+ "%s: Failed to get i2c regulator\n", __func__);
+ retval = PTR_ERR(ts_data->avdd);
+ goto err_get_vtg_i2c;
+ }
+
+ if (regulator_count_voltages(ts_data->avdd) > 0) {
+ retval = regulator_set_voltage(ts_data->avdd,
+ IT_I2C_VTG_MIN_UV, IT_I2C_VTG_MAX_UV);
+ if (retval) {
+ dev_err(&ts_data->client->dev,
+ "reg set i2c vtg failed retval =%d\n",
+ retval);
+ goto err_set_vtg_i2c;
+ }
+ }
+
+ return 0;
+
+err_set_vtg_i2c:
+err_get_vtg_i2c:
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, IT_VTG_MAX_UV);
+err_set_vtg_vdd:
+ return retval;
+
+hw_shutdown:
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, IT_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->avdd) > 0)
+ regulator_set_voltage(ts_data->avdd, 0, IT_I2C_VTG_MAX_UV);
+ return 0;
+};
+
+static int it7260_power_on(struct it7260_ts_data *ts_data, bool on)
+{
+ int retval;
+
+ if (on == false)
+ goto power_off;
+
+ retval = reg_set_optimum_mode_check(ts_data->vdd,
+ IT_ACTIVE_LOAD_UA);
+ if (retval < 0) {
+ dev_err(&ts_data->client->dev,
+ "Regulator vdd set_opt failed rc=%d\n",
+ retval);
+ return retval;
+ }
+
+ retval = regulator_enable(ts_data->vdd);
+ if (retval) {
+ dev_err(&ts_data->client->dev,
+ "Regulator vdd enable failed rc=%d\n",
+ retval);
+ goto error_reg_en_vdd;
+ }
+
+ retval = reg_set_optimum_mode_check(ts_data->avdd,
+ IT_I2C_ACTIVE_LOAD_UA);
+ if (retval < 0) {
+ dev_err(&ts_data->client->dev,
+ "Regulator avdd set_opt failed rc=%d\n",
+ retval);
+ goto error_reg_opt_i2c;
+ }
+
+ retval = regulator_enable(ts_data->avdd);
+ if (retval) {
+ dev_err(&ts_data->client->dev,
+ "Regulator avdd enable failed rc=%d\n",
+ retval);
+ goto error_reg_en_avdd;
+ }
+
+ return 0;
+
+error_reg_en_avdd:
+ reg_set_optimum_mode_check(ts_data->avdd, 0);
+error_reg_opt_i2c:
+ regulator_disable(ts_data->vdd);
+error_reg_en_vdd:
+ reg_set_optimum_mode_check(ts_data->vdd, 0);
+ return retval;
+
+power_off:
+ reg_set_optimum_mode_check(ts_data->vdd, 0);
+ regulator_disable(ts_data->vdd);
+ reg_set_optimum_mode_check(ts_data->avdd, 0);
+ regulator_disable(ts_data->avdd);
+
+ return 0;
+}
+
+static int it7260_gpio_configure(struct it7260_ts_data *ts_data, bool on)
+{
+ int retval = 0;
+
+ if (on) {
+ if (gpio_is_valid(ts_data->pdata->irq_gpio)) {
+ /* configure touchscreen irq gpio */
+ retval = gpio_request(ts_data->pdata->irq_gpio,
+ "ite_irq_gpio");
+ if (retval) {
+ dev_err(&ts_data->client->dev,
+ "unable to request irq gpio [%d]\n",
+ retval);
+ goto err_irq_gpio_req;
+ }
+
+ retval = gpio_direction_input(ts_data->pdata->irq_gpio);
+ if (retval) {
+ dev_err(&ts_data->client->dev,
+ "unable to set direction for irq gpio [%d]\n",
+ retval);
+ goto err_irq_gpio_dir;
+ }
+ } else {
+ dev_err(&ts_data->client->dev,
+ "irq gpio not provided\n");
+ goto err_irq_gpio_req;
+ }
+
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
+ /* configure touchscreen reset out gpio */
+ retval = gpio_request(ts_data->pdata->reset_gpio,
+ "ite_reset_gpio");
+ if (retval) {
+ dev_err(&ts_data->client->dev,
+ "unable to request reset gpio [%d]\n",
+ retval);
+ goto err_reset_gpio_req;
+ }
+
+ retval = gpio_direction_output(
+ ts_data->pdata->reset_gpio, 1);
+ if (retval) {
+ dev_err(&ts_data->client->dev,
+ "unable to set direction for reset gpio [%d]\n",
+ retval);
+ goto err_reset_gpio_dir;
+ }
+
+ if (ts_data->pdata->low_reset)
+ gpio_set_value(ts_data->pdata->reset_gpio, 0);
+ else
+ gpio_set_value(ts_data->pdata->reset_gpio, 1);
+
+ msleep(ts_data->pdata->reset_delay);
+ } else {
+ dev_err(&ts_data->client->dev,
+ "reset gpio not provided\n");
+ goto err_reset_gpio_req;
+ }
+ } else {
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
+ /*
+ * This is intended to save leakage current
+ * only. Even if the call(gpio_direction_input)
+ * fails, only leakage current will be more but
+ * functionality will not be affected.
+ */
+ retval = gpio_direction_input(
+ ts_data->pdata->reset_gpio);
+ if (retval) {
+ dev_err(&ts_data->client->dev,
+ "unable to set direction for gpio reset [%d]\n",
+ retval);
+ }
+ gpio_free(ts_data->pdata->reset_gpio);
+ }
+ }
+
+ return 0;
+
+err_reset_gpio_dir:
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
+ gpio_free(ts_data->pdata->reset_gpio);
+err_reset_gpio_req:
+err_irq_gpio_dir:
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
+err_irq_gpio_req:
+ return retval;
+}
+
+#if CONFIG_OF
+static int it7260_get_dt_coords(struct device *dev, char *name,
+ struct it7260_ts_platform_data *pdata)
+{
+ u32 coords[IT7260_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != IT7260_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (strcmp(name, "ite,panel-coords") == 0) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+
+ if (pdata->panel_maxx == 0 || pdata->panel_minx > 0)
+ rc = -EINVAL;
+ else if (pdata->panel_maxy == 0 || pdata->panel_miny > 0)
+ rc = -EINVAL;
+
+ if (rc) {
+ dev_err(dev, "Invalid panel resolution %d\n", rc);
+ return rc;
+ }
+ } else if (strcmp(name, "ite,display-coords") == 0) {
+ pdata->disp_minx = coords[0];
+ pdata->disp_miny = coords[1];
+ pdata->disp_maxx = coords[2];
+ pdata->disp_maxy = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int it7260_parse_dt(struct device *dev,
+ struct it7260_ts_platform_data *pdata)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ struct device_node *np = dev->of_node;
+ u32 temp_val;
+ int rc;
+
+ /* reset, irq gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(np,
+ "ite,reset-gpio", 0, &pdata->reset_gpio_flags);
+ pdata->irq_gpio = of_get_named_gpio_flags(np,
+ "ite,irq-gpio", 0, &pdata->irq_gpio_flags);
+
+ rc = of_property_read_u32(np, "ite,num-fingers", &temp_val);
+ if (!rc)
+ pdata->num_of_fingers = temp_val;
+ else if (rc != -EINVAL) {
+ dev_err(dev, "Unable to read reset delay\n");
+ return rc;
+ }
+
+ pdata->wakeup = of_property_read_bool(np, "ite,wakeup");
+ pdata->palm_detect_en = of_property_read_bool(np, "ite,palm-detect-en");
+ if (pdata->palm_detect_en) {
+ rc = of_property_read_u32(np, "ite,palm-detect-keycode",
+ &temp_val);
+ if (!rc) {
+ pdata->palm_detect_keycode = temp_val;
+ } else {
+ dev_err(dev, "Unable to read palm-detect-keycode\n");
+ return rc;
+ }
+ }
+
+ rc = of_property_read_string(np, "ite,fw-name", &pdata->fw_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw image name %d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_string(np, "ite,cfg-name", &pdata->cfg_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read cfg image name %d\n", rc);
+ return rc;
+ }
+
+ snprintf(ts_data->fw_name, MAX_BUFFER_SIZE, "%s",
+ (pdata->fw_name != NULL) ? pdata->fw_name : FW_NAME);
+ snprintf(ts_data->cfg_name, MAX_BUFFER_SIZE, "%s",
+ (pdata->cfg_name != NULL) ? pdata->cfg_name : CFG_NAME);
+
+ rc = of_property_read_u32(np, "ite,reset-delay", &temp_val);
+ if (!rc)
+ pdata->reset_delay = temp_val;
+ else if (rc != -EINVAL) {
+ dev_err(dev, "Unable to read reset delay\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "ite,avdd-lpm-cur", &temp_val);
+ if (!rc) {
+ pdata->avdd_lpm_cur = temp_val;
+ } else if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read avdd lpm current value %d\n", rc);
+ return rc;
+ }
+
+ pdata->low_reset = of_property_read_bool(np, "ite,low-reset");
+
+ rc = it7260_get_dt_coords(dev, "ite,display-coords", pdata);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rc = it7260_get_dt_coords(dev, "ite,panel-coords", pdata);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ return 0;
+}
+#else
+static inline int it7260_ts_parse_dt(struct device *dev,
+ struct it7260_ts_platform_data *pdata)
+{
+ return 0;
+}
+#endif
+
+static int it7260_ts_pinctrl_init(struct it7260_ts_data *ts_data)
+{
+ int retval;
+
+ /* Get pinctrl if target uses pinctrl */
+ ts_data->ts_pinctrl = devm_pinctrl_get(&(ts_data->client->dev));
+ if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) {
+ retval = PTR_ERR(ts_data->ts_pinctrl);
+ dev_dbg(&ts_data->client->dev,
+ "Target does not use pinctrl %d\n", retval);
+ goto err_pinctrl_get;
+ }
+
+ ts_data->pinctrl_state_active
+ = pinctrl_lookup_state(ts_data->ts_pinctrl,
+ PINCTRL_STATE_ACTIVE);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_active)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_active);
+ dev_err(&ts_data->client->dev,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_ACTIVE, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts_data->pinctrl_state_suspend
+ = pinctrl_lookup_state(ts_data->ts_pinctrl,
+ PINCTRL_STATE_SUSPEND);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_suspend)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_suspend);
+ dev_err(&ts_data->client->dev,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_SUSPEND, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts_data->pinctrl_state_release
+ = pinctrl_lookup_state(ts_data->ts_pinctrl,
+ PINCTRL_STATE_RELEASE);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_release);
+ dev_dbg(&ts_data->client->dev,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_RELEASE, retval);
+ }
+
+ return 0;
+
+err_pinctrl_lookup:
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+err_pinctrl_get:
+ ts_data->ts_pinctrl = NULL;
+ return retval;
+}
+
+static int it7260_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ static const uint8_t cmd_start[] = {CMD_UNKNOWN_7};
+ struct it7260_ts_data *ts_data;
+ struct it7260_ts_platform_data *pdata;
+ uint8_t rsp[2];
+ int ret = -1, err;
+ struct dentry *temp;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "need I2C_FUNC_I2C\n");
+ return -ENODEV;
+ }
+
+ ts_data = devm_kzalloc(&client->dev, sizeof(*ts_data), GFP_KERNEL);
+ if (!ts_data)
+ return -ENOMEM;
+
+ ts_data->client = client;
+ i2c_set_clientdata(client, ts_data);
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ ret = it7260_parse_dt(&client->dev, pdata);
+ if (ret)
+ return ret;
+ } else {
+ pdata = client->dev.platform_data;
+ }
+
+ if (!pdata) {
+ dev_err(&client->dev, "No platform data found\n");
+ return -ENOMEM;
+ }
+
+ ts_data->pdata = pdata;
+
+ ret = it7260_regulator_configure(ts_data, true);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to configure regulators\n");
+ goto err_reg_configure;
+ }
+
+ ret = it7260_power_on(ts_data, true);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to power on\n");
+ goto err_power_device;
+ }
+
+ /*
+ * After enabling regulators, controller needs a delay to come to
+ * an active state.
+ */
+ msleep(DELAY_VTG_REG_EN);
+
+ ret = it7260_ts_pinctrl_init(ts_data);
+ if (!ret && ts_data->ts_pinctrl) {
+ /*
+ * Pinctrl handle is optional. If pinctrl handle is found
+ * let pins to be configured in active state. If not
+ * found continue further without error.
+ */
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "failed to select pin to active state %d",
+ ret);
+ }
+ } else {
+ ret = it7260_gpio_configure(ts_data, true);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to configure gpios\n");
+ goto err_gpio_config;
+ }
+ }
+
+ ret = it7260_ts_chip_identify(ts_data);
+ if (ret) {
+ dev_err(&client->dev, "Failed to identify chip %d!!!", ret);
+ goto err_identification_fail;
+ }
+
+ it7260_get_chip_versions(ts_data);
+
+ ts_data->input_dev = input_allocate_device();
+ if (!ts_data->input_dev) {
+ dev_err(&client->dev, "failed to allocate input device\n");
+ ret = -ENOMEM;
+ goto err_input_alloc;
+ }
+
+ /* Initialize mutex for fw and cfg upgrade */
+ mutex_init(&ts_data->fw_cfg_mutex);
+
+ ts_data->input_dev->name = DEVICE_NAME;
+ ts_data->input_dev->phys = "I2C";
+ ts_data->input_dev->id.bustype = BUS_I2C;
+ ts_data->input_dev->id.vendor = 0x0001;
+ ts_data->input_dev->id.product = 0x7260;
+ set_bit(EV_SYN, ts_data->input_dev->evbit);
+ set_bit(EV_KEY, ts_data->input_dev->evbit);
+ set_bit(EV_ABS, ts_data->input_dev->evbit);
+ set_bit(INPUT_PROP_DIRECT, ts_data->input_dev->propbit);
+ set_bit(BTN_TOUCH, ts_data->input_dev->keybit);
+ input_set_abs_params(ts_data->input_dev, ABS_MT_POSITION_X,
+ ts_data->pdata->disp_minx, ts_data->pdata->disp_maxx, 0, 0);
+ input_set_abs_params(ts_data->input_dev, ABS_MT_POSITION_Y,
+ ts_data->pdata->disp_miny, ts_data->pdata->disp_maxy, 0, 0);
+ input_mt_init_slots(ts_data->input_dev,
+ ts_data->pdata->num_of_fingers, 0);
+
+ input_set_drvdata(ts_data->input_dev, ts_data);
+
+ if (pdata->wakeup) {
+ set_bit(KEY_WAKEUP, ts_data->input_dev->keybit);
+ INIT_WORK(&ts_data->work_pm_relax, it7260_ts_work_func);
+ device_init_wakeup(&client->dev, pdata->wakeup);
+ }
+
+ if (pdata->palm_detect_en)
+ set_bit(ts_data->pdata->palm_detect_keycode,
+ ts_data->input_dev->keybit);
+
+ if (input_register_device(ts_data->input_dev)) {
+ dev_err(&client->dev, "failed to register input device\n");
+ goto err_input_register;
+ }
+
+ if (request_threaded_irq(client->irq, NULL, it7260_ts_threaded_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts_data)) {
+ dev_err(&client->dev, "request_irq failed\n");
+ goto err_irq_reg;
+ }
+
+ if (sysfs_create_group(&(client->dev.kobj), &it7260_attr_group)) {
+ dev_err(&client->dev, "failed to register sysfs #2\n");
+ goto err_sysfs_grp_create;
+ }
+
+#if defined(CONFIG_FB)
+ ts_data->fb_notif.notifier_call = fb_notifier_callback;
+
+ ret = fb_register_client(&ts_data->fb_notif);
+ if (ret)
+ dev_err(&client->dev, "Unable to register fb_notifier %d\n",
+ ret);
+#endif
+
+ it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_start,
+ sizeof(cmd_start));
+ msleep(pdata->reset_delay);
+ it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE, rsp, sizeof(rsp));
+ msleep(pdata->reset_delay);
+
+ ts_data->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
+ if (ts_data->dir == NULL || IS_ERR(ts_data->dir)) {
+ dev_err(&client->dev,
+ "%s: Failed to create debugfs directory, ret = %ld\n",
+ __func__, PTR_ERR(ts_data->dir));
+ ret = PTR_ERR(ts_data->dir);
+ goto err_create_debugfs_dir;
+ }
+
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, ts_data->dir,
+ ts_data, &debug_suspend_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ dev_err(&client->dev,
+ "%s: Failed to create suspend debugfs file, ret = %ld\n",
+ __func__, PTR_ERR(temp));
+ ret = PTR_ERR(temp);
+ goto err_create_debugfs_file;
+ }
+
+ return 0;
+
+err_create_debugfs_file:
+ debugfs_remove_recursive(ts_data->dir);
+err_create_debugfs_dir:
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&ts_data->fb_notif))
+ dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#endif
+ sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
+
+err_sysfs_grp_create:
+ free_irq(client->irq, ts_data);
+
+err_irq_reg:
+ input_unregister_device(ts_data->input_dev);
+
+err_input_register:
+ if (pdata->wakeup) {
+ cancel_work_sync(&ts_data->work_pm_relax);
+ device_init_wakeup(&client->dev, false);
+ }
+ if (ts_data->input_dev)
+ input_free_device(ts_data->input_dev);
+ ts_data->input_dev = NULL;
+
+err_input_alloc:
+err_identification_fail:
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
+ } else {
+ err = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
+ if (err)
+ dev_err(&ts_data->client->dev,
+ "failed to select relase pinctrl state %d\n",
+ err);
+ }
+ } else {
+ if (gpio_is_valid(pdata->reset_gpio))
+ gpio_free(pdata->reset_gpio);
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+ }
+
+err_gpio_config:
+ it7260_power_on(ts_data, false);
+
+err_power_device:
+ it7260_regulator_configure(ts_data, false);
+
+err_reg_configure:
+ return ret;
+}
+
+static int it7260_ts_remove(struct i2c_client *client)
+{
+ struct it7260_ts_data *ts_data = i2c_get_clientdata(client);
+ int ret;
+
+ debugfs_remove_recursive(ts_data->dir);
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&ts_data->fb_notif))
+ dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#endif
+ sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
+ free_irq(client->irq, ts_data);
+ input_unregister_device(ts_data->input_dev);
+ if (ts_data->input_dev)
+ input_free_device(ts_data->input_dev);
+ ts_data->input_dev = NULL;
+ if (ts_data->pdata->wakeup) {
+ cancel_work_sync(&ts_data->work_pm_relax);
+ device_init_wakeup(&client->dev, false);
+ }
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
+ } else {
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
+ if (ret)
+ dev_err(&ts_data->client->dev,
+ "failed to select relase pinctrl state %d\n",
+ ret);
+ }
+ } else {
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
+ gpio_free(ts_data->pdata->reset_gpio);
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
+ }
+ it7260_power_on(ts_data, false);
+ it7260_regulator_configure(ts_data, false);
+
+ return 0;
+}
+
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct it7260_ts_data *ts_data = container_of(self,
+ struct it7260_ts_data, fb_notif);
+ struct fb_event *evdata = data;
+ int *blank;
+
+ if (evdata && evdata->data && ts_data && ts_data->client) {
+ if (event == FB_EVENT_BLANK) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ it7260_ts_resume(&(ts_data->client->dev));
+ else if (*blank == FB_BLANK_POWERDOWN ||
+ *blank == FB_BLANK_VSYNC_SUSPEND)
+ it7260_ts_suspend(&(ts_data->client->dev));
+ }
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+static int it7260_ts_resume(struct device *dev)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ int retval;
+
+ if (device_may_wakeup(dev)) {
+ if (ts_data->in_low_power_mode) {
+ /* Set active current for the avdd regulator */
+ if (ts_data->pdata->avdd_lpm_cur) {
+ retval = reg_set_optimum_mode_check(
+ ts_data->avdd,
+ IT_I2C_ACTIVE_LOAD_UA);
+ if (retval < 0)
+ dev_err(dev, "Regulator avdd set_opt failed at resume rc=%d\n",
+ retval);
+ }
+
+ ts_data->in_low_power_mode = false;
+ disable_irq_wake(ts_data->client->irq);
+ }
+ return 0;
+ }
+
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
+ if (retval < 0) {
+ dev_err(dev, "Cannot get default pinctrl state %d\n",
+ retval);
+ goto err_pinctrl_select_suspend;
+ }
+ }
+
+ enable_irq(ts_data->client->irq);
+ ts_data->suspended = false;
+ return 0;
+
+err_pinctrl_select_suspend:
+ return retval;
+}
+
+static int it7260_ts_suspend(struct device *dev)
+{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ int retval;
+
+ if (ts_data->fw_cfg_uploading) {
+ dev_dbg(dev, "Fw/cfg uploading. Can't go to suspend.\n");
+ return -EBUSY;
+ }
+
+ if (device_may_wakeup(dev)) {
+ if (!ts_data->in_low_power_mode) {
+ /* put the device in low power idle mode */
+ retval = it7260_ts_chip_low_power_mode(ts_data,
+ PWR_CTL_LOW_POWER_MODE);
+ if (retval)
+ dev_err(dev, "Can't go to low power mode %d\n",
+ retval);
+
+ /* Set lpm current for avdd regulator */
+ if (ts_data->pdata->avdd_lpm_cur) {
+ retval = reg_set_optimum_mode_check(
+ ts_data->avdd,
+ ts_data->pdata->avdd_lpm_cur);
+ if (retval < 0)
+ dev_err(dev, "Regulator avdd set_opt failed at suspend rc=%d\n",
+ retval);
+ }
+
+ ts_data->in_low_power_mode = true;
+ enable_irq_wake(ts_data->client->irq);
+ }
+ return 0;
+ }
+
+ disable_irq(ts_data->client->irq);
+
+ it7260_ts_release_all(ts_data);
+
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_suspend);
+ if (retval < 0) {
+ dev_err(dev, "Cannot get idle pinctrl state %d\n",
+ retval);
+ goto err_pinctrl_select_suspend;
+ }
+ }
+
+ ts_data->suspended = true;
+
+ return 0;
+
+err_pinctrl_select_suspend:
+ return retval;
+}
+
+static const struct dev_pm_ops it7260_ts_dev_pm_ops = {
+ .suspend = it7260_ts_suspend,
+ .resume = it7260_ts_resume,
+};
+#else
+static int it7260_ts_resume(struct device *dev)
+{
+ return 0;
+}
+
+static int it7260_ts_suspend(struct device *dev)
+{
+ return 0;
+}
+#endif
+
+static const struct i2c_device_id it7260_ts_id[] = {
+ { DEVICE_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, it7260_ts_id);
+
+static const struct of_device_id it7260_match_table[] = {
+ { .compatible = "ite,it7260_ts",},
+ {},
+};
+
+static struct i2c_driver it7260_ts_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DEVICE_NAME,
+ .of_match_table = it7260_match_table,
+#ifdef CONFIG_PM
+ .pm = &it7260_ts_dev_pm_ops,
+#endif
+ },
+ .probe = it7260_ts_probe,
+ .remove = it7260_ts_remove,
+ .id_table = it7260_ts_id,
+};
+
+module_i2c_driver(it7260_ts_driver);
+
+MODULE_DESCRIPTION("it7260 Touchscreen Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/maxim_sti.c b/drivers/input/touchscreen/maxim_sti.c
new file mode 100644
index 000000000000..d10f26357611
--- /dev/null
+++ b/drivers/input/touchscreen/maxim_sti.c
@@ -0,0 +1,2842 @@
+/* drivers/input/touchscreen/maxim_sti.c
+ *
+ * Maxim SmartTouch Imager Touchscreen Driver
+ *
+ * Copyright (c)2013 Maxim Integrated Products, Inc.
+ * Copyright (C) 2013, NVIDIA Corporation. All Rights Reserved.
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kthread.h>
+#include <linux/spi/spi.h>
+#include <linux/firmware.h>
+#include <linux/crc16.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/regulator/consumer.h>
+#include <net/genetlink.h>
+#include <net/sock.h>
+#include <uapi/linux/maxim_sti.h>
+#include <linux/input/mt.h>
+#include <asm/byteorder.h> /* MUST include this header to get byte order */
+#ifdef CONFIG_OF
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#endif
+
+/****************************************************************************\
+* Custom features *
+\****************************************************************************/
+
+#define VTG_DVDD_MIN_UV 1800000
+#define VTG_DVDD_MAX_UV 1800000
+#define VTG_AVDD_MIN_UV 2850000
+#define VTG_AVDD_MAX_UV 2850000
+#define INPUT_DEVICES 1
+#define CFG_FILE_NAME_MAX 64
+
+#define BUF_SIZE 4100
+#define DEF_NL_MC_GROUPS 5
+#define DEF_CHIP_ACC_METHOD 1
+#define TOUCH_FUSION "touch_fusion"
+
+#if defined(CONFIG_FB)
+#include <linux/fb.h>
+#endif
+
+/****************************************************************************\
+* Device context structure, globals, and macros *
+\****************************************************************************/
+#define MAXIM_STI_NAME "maxim_sti"
+
+struct maxim_sti_pdata {
+ char *touch_fusion;
+ char *config_file;
+ char *nl_family;
+ char *fw_name;
+ u32 nl_mc_groups;
+ u32 chip_access_method;
+ u32 default_reset_state;
+ u32 tx_buf_size;
+ u32 rx_buf_size;
+ int gpio_reset;
+ int gpio_irq;
+ int (*init)(struct maxim_sti_pdata *pdata, bool init);
+ void (*reset)(struct maxim_sti_pdata *pdata, int value);
+ int (*irq)(struct maxim_sti_pdata *pdata);
+ bool mt_type_b_enabled;
+};
+
+struct dev_data;
+
+struct chip_access_method {
+ int (*read)(struct dev_data *dd, u16 address, u8 *buf, u16 len);
+ int (*write)(struct dev_data *dd, u16 address, u8 *buf, u16 len);
+};
+
+struct dev_data {
+ u8 *tx_buf;
+ u8 *rx_buf;
+ u8 send_fail_count;
+ u32 nl_seq;
+ u8 nl_mc_group_count;
+ bool nl_enabled;
+ bool start_fusion;
+ bool suspended;
+ bool suspend_in_progress;
+ bool resume_in_progress;
+ bool expect_resume_ack;
+ bool eraser_active;
+ bool legacy_acceleration;
+ bool input_no_deconfig;
+ bool irq_registered;
+ u16 irq_param[MAX_IRQ_PARAMS];
+ pid_t fusion_process;
+ char input_phys[128];
+ struct input_dev *input_dev[INPUT_DEVICES];
+ struct completion suspend_resume;
+ struct chip_access_method chip;
+ struct spi_device *spi;
+ struct genl_family nl_family;
+ struct genl_ops *nl_ops;
+ struct genl_multicast_group *nl_mc_groups;
+ struct sk_buff *outgoing_skb;
+ struct sk_buff_head incoming_skb_queue;
+ struct task_struct *thread;
+ struct sched_param thread_sched;
+ struct list_head dev_list;
+ struct regulator *reg_avdd;
+ struct regulator *reg_dvdd;
+ bool supply;
+ void (*service_irq)(struct dev_data *dd);
+ struct notifier_block fb_notifier;
+ struct kobject *parent;
+ char config_file[CFG_FILE_NAME_MAX];
+ u8 sysfs_created;
+ u16 chip_id;
+ u16 glove_enabled;
+ u16 charger_mode_en;
+ u16 lcd_fps;
+ u16 tf_ver;
+ u16 drv_ver;
+ u16 fw_ver;
+ u16 fw_protocol;
+ u32 tf_status;
+ bool idle;
+ bool gesture_reset;
+ bool touch_status[INPUT_DEVICES]
+ [MAX_INPUT_EVENTS];
+ u16 gesture_en;
+ unsigned long int sysfs_update_type;
+ struct completion sysfs_ack_glove;
+ struct completion sysfs_ack_charger;
+ struct completion sysfs_ack_lcd_fps;
+ struct mutex sysfs_update_mutex;
+ struct pinctrl_state *pinctrl_state_active;
+ struct pinctrl_state *pinctrl_state_suspended;
+ struct pinctrl *ts_pinctrl;
+};
+
+static unsigned short panel_id;
+static struct list_head dev_list;
+static spinlock_t dev_lock;
+
+static irqreturn_t irq_handler(int irq, void *context);
+static void service_irq(struct dev_data *dd);
+static void service_irq_legacy_acceleration(struct dev_data *dd);
+static int send_sysfs_info(struct dev_data *dd);
+
+#define ERROR(a, b...) dev_err(&dd->spi->dev, "maxim: %s (ERROR:%s:%d): " \
+ a "\n", dd->nl_family.name, __func__, \
+ __LINE__, ##b)
+#define INFO(a, b...) dev_info(&dd->spi->dev, "maxim: %s: " a "\n", \
+ dd->nl_family.name, ##b)
+#define DBG(a, b...) dev_dbg(&dd->spi->dev, "maxim: %s: " a "\n", \
+ dd->nl_family.name, ##b)
+
+#define DRV_MSG_DBG(...)
+#define DRV_PT_DBG(...)
+
+/****************************************************************************\
+* Chip access methods *
+\****************************************************************************/
+
+static int
+spi_read_123(struct dev_data *dd, u16 address, u8 *buf, u16 len, bool add_len)
+{
+ struct spi_message message;
+ struct spi_transfer transfer;
+ u16 *tx_buf = (u16 *)dd->tx_buf;
+ u16 *rx_buf = (u16 *)dd->rx_buf;
+ u16 words = len / sizeof(u16), header_len = 1;
+ u16 *ptr2 = rx_buf + 1;
+ int ret;
+
+ if (tx_buf == NULL || rx_buf == NULL)
+ return -ENOMEM;
+
+ tx_buf[0] = (address << 1) | 0x0001;
+
+ if (add_len) {
+ tx_buf[1] = words;
+ ptr2++;
+ header_len++;
+ }
+
+ spi_message_init(&message);
+ memset(&transfer, 0, sizeof(transfer));
+
+ transfer.len = len + header_len * sizeof(u16);
+ transfer.tx_buf = tx_buf;
+ transfer.rx_buf = rx_buf;
+ spi_message_add_tail(&transfer, &message);
+
+ do {
+ ret = spi_sync(dd->spi, &message);
+ } while (ret == -EAGAIN);
+
+ memcpy(buf, ptr2, len);
+
+ return ret;
+}
+
+static int
+spi_write_123(struct dev_data *dd, u16 address, u8 *buf, u16 len,
+ bool add_len)
+{
+ struct maxim_sti_pdata *pdata = dd->spi->dev.platform_data;
+ u16 *tx_buf = (u16 *)dd->tx_buf;
+ u16 words = len / sizeof(u16), header_len = 1;
+ int ret;
+
+ if (tx_buf == NULL)
+ return -ENOMEM;
+
+ tx_buf[0] = address << 1;
+ if (add_len) {
+ tx_buf[1] = words;
+ header_len++;
+ }
+ memcpy(tx_buf + header_len, buf, len);
+
+ do {
+ ret = spi_write(dd->spi, tx_buf,
+ len + header_len * sizeof(u16));
+ } while (ret == -EAGAIN);
+
+ memset(dd->tx_buf, 0xFF, pdata->tx_buf_size);
+ return ret;
+}
+
+/* ======================================================================== */
+
+static int
+spi_read_1(struct dev_data *dd, u16 address, u8 *buf, u16 len)
+{
+ return spi_read_123(dd, address, buf, len, true);
+}
+
+static int
+spi_write_1(struct dev_data *dd, u16 address, u8 *buf, u16 len)
+{
+ return spi_write_123(dd, address, buf, len, true);
+}
+
+/* ======================================================================== */
+
+static inline int
+stop_legacy_acceleration(struct dev_data *dd)
+{
+ u16 value = 0xDEAD, status, i;
+ int ret;
+
+ ret = spi_write_123(dd, 0x0003, (u8 *)&value,
+ sizeof(value), false);
+ if (ret < 0)
+ return -1;
+ usleep_range(100, 120);
+
+ for (i = 0; i < 200; i++) {
+ ret = spi_read_123(dd, 0x0003, (u8 *)&status, sizeof(status),
+ false);
+ if (ret < 0)
+ return -1;
+ if (status == 0xABCD)
+ return 0;
+ }
+
+ return -2;
+}
+
+static inline int
+start_legacy_acceleration(struct dev_data *dd)
+{
+ u16 value = 0xBEEF;
+ int ret;
+
+ ret = spi_write_123(dd, 0x0003, (u8 *)&value, sizeof(value), false);
+ usleep_range(100, 120);
+
+ return ret;
+}
+
+static inline int
+spi_rw_2_poll_status(struct dev_data *dd)
+{
+ u16 status, i;
+ int ret;
+
+ for (i = 0; i < 200; i++) {
+ ret = spi_read_123(dd, 0x0000, (u8 *)&status, sizeof(status),
+ false);
+ if (ret < 0)
+ return -1;
+ if (status == 0xABCD)
+ return 0;
+ }
+
+ return -2;
+}
+
+static inline int
+spi_read_2_page(struct dev_data *dd, u16 address, u8 *buf, u16 len)
+{
+ u16 request[] = {0xFEDC, (address << 1) | 0x0001, len / sizeof(u16)};
+ int ret;
+
+ /* write read request header */
+ ret = spi_write_123(dd, 0x0000, (u8 *)request, sizeof(request),
+ false);
+ if (ret < 0)
+ return -1;
+
+ /* poll status */
+ ret = spi_rw_2_poll_status(dd);
+ if (ret < 0)
+ return ret;
+
+ /* read data */
+ ret = spi_read_123(dd, 0x0004, (u8 *)buf, len, false);
+ return ret;
+}
+
+static inline int
+spi_write_2_page(struct dev_data *dd, u16 address, u8 *buf, u16 len)
+{
+ u16 page[254];
+ int ret;
+
+ page[0] = 0xFEDC;
+ page[1] = address << 1;
+ page[2] = len / sizeof(u16);
+ page[3] = 0x0000;
+ memcpy(page + 4, buf, len);
+
+ /* write data with write request header */
+ ret = spi_write_123(dd, 0x0000, (u8 *)page, len + 4 * sizeof(u16),
+ false);
+ if (ret < 0)
+ return -1;
+
+ /* poll status */
+ return spi_rw_2_poll_status(dd);
+}
+
+static inline int
+spi_rw_2(struct dev_data *dd, u16 address, u8 *buf, u16 len,
+ int (*func)(struct dev_data *dd, u16 address, u8 *buf, u16 len))
+{
+ u16 rx_len, rx_limit = 250 * sizeof(u16), offset = 0;
+ int ret;
+
+ while (len > 0) {
+ rx_len = (len > rx_limit) ? rx_limit : len;
+ if (dd->legacy_acceleration)
+ stop_legacy_acceleration(dd);
+ ret = func(dd, address + (offset / sizeof(u16)), buf + offset,
+ rx_len);
+ if (dd->legacy_acceleration)
+ start_legacy_acceleration(dd);
+ if (ret < 0)
+ return ret;
+ offset += rx_len;
+ len -= rx_len;
+ }
+
+ return 0;
+}
+
+static int
+spi_read_2(struct dev_data *dd, u16 address, u8 *buf, u16 len)
+{
+ return spi_rw_2(dd, address, buf, len, spi_read_2_page);
+}
+
+static int
+spi_write_2(struct dev_data *dd, u16 address, u8 *buf, u16 len)
+{
+ return spi_rw_2(dd, address, buf, len, spi_write_2_page);
+}
+
+/* ======================================================================== */
+
+static int
+spi_read_3(struct dev_data *dd, u16 address, u8 *buf, u16 len)
+{
+ return spi_read_123(dd, address, buf, len, false);
+}
+
+static int
+spi_write_3(struct dev_data *dd, u16 address, u8 *buf, u16 len)
+{
+ return spi_write_123(dd, address, buf, len, false);
+}
+
+/* ======================================================================== */
+
+static struct chip_access_method chip_access_methods[] = {
+ {
+ .read = spi_read_1,
+ .write = spi_write_1,
+ },
+ {
+ .read = spi_read_2,
+ .write = spi_write_2,
+ },
+ {
+ .read = spi_read_3,
+ .write = spi_write_3,
+ },
+};
+
+static int
+set_chip_access_method(struct dev_data *dd, u8 method)
+{
+ if (method == 0 || method > ARRAY_SIZE(chip_access_methods))
+ return -1;
+
+ memcpy(&dd->chip, &chip_access_methods[method - 1], sizeof(dd->chip));
+ return 0;
+}
+
+/* ======================================================================== */
+
+static inline int
+stop_legacy_acceleration_canned(struct dev_data *dd)
+{
+ u16 value = dd->irq_param[18];
+
+ return dd->chip.write(dd, dd->irq_param[16], (u8 *)&value,
+ sizeof(value));
+}
+
+static inline int
+start_legacy_acceleration_canned(struct dev_data *dd)
+{
+ u16 value = dd->irq_param[17];
+
+ return dd->chip.write(dd, dd->irq_param[16], (u8 *)&value,
+ sizeof(value));
+}
+
+/* ======================================================================== */
+
+#define FLASH_BLOCK_SIZE 64 /* flash write buffer in words */
+#define FIRMWARE_SIZE 0xC000 /* fixed 48Kbytes */
+
+static int bootloader_wait_ready(struct dev_data *dd)
+{
+ u16 status, i;
+
+ for (i = 0; i < 15; i++) {
+ if (spi_read_3(dd, 0x00FF, (u8 *)&status,
+ sizeof(status)) != 0)
+ return -1;
+ if (status == 0xABCC)
+ return 0;
+ if (i >= 3)
+ usleep_range(500, 700);
+ }
+ ERROR("unexpected status %04X", status);
+ return -1;
+}
+
+static int bootloader_complete(struct dev_data *dd)
+{
+ u16 value = 0x5432;
+
+ return spi_write_3(dd, 0x00FF, (u8 *)&value, sizeof(value));
+}
+
+static int bootloader_read_data(struct dev_data *dd, u16 *value)
+{
+ u16 buffer[2];
+
+ if (spi_read_3(dd, 0x00FE, (u8 *)buffer, sizeof(buffer)) != 0)
+ return -1;
+ if (buffer[1] != 0xABCC)
+ return -1;
+
+ *value = buffer[0];
+ return bootloader_complete(dd);
+}
+
+static int bootloader_write_data(struct dev_data *dd, u16 value)
+{
+ u16 buffer[2] = {value, 0x5432};
+
+ if (bootloader_wait_ready(dd) != 0)
+ return -1;
+ return spi_write_3(dd, 0x00FE, (u8 *)buffer, sizeof(buffer));
+}
+
+static int bootloader_wait_command(struct dev_data *dd)
+{
+ u16 value, i;
+
+ for (i = 0; i < 15; i++) {
+ if (bootloader_read_data(dd, &value) == 0 && value == 0x003E)
+ return 0;
+ if (i >= 3)
+ usleep_range(500, 700);
+ }
+ return -1;
+}
+
+static int bootloader_enter(struct dev_data *dd)
+{
+ int i;
+ u16 enter[3] = {0x0047, 0x00C7, 0x0007};
+
+ for (i = 0; i < 3; i++) {
+ if (spi_write_3(dd, 0x7F00, (u8 *)&enter[i],
+ sizeof(enter[i])) != 0)
+ return -1;
+ }
+
+ if (bootloader_wait_command(dd) != 0)
+ return -1;
+ return 0;
+}
+
+static int bootloader_exit(struct dev_data *dd)
+{
+ u16 value = 0x0000;
+
+ if (bootloader_write_data(dd, 0x0001) != 0)
+ return -1;
+ return spi_write_3(dd, 0x7F00, (u8 *)&value, sizeof(value));
+}
+
+static int bootloader_get_crc(struct dev_data *dd, u16 *crc16, u16 len)
+{
+ u16 command[] = {0x0030, 0x0002, 0x0000, 0x0000, len & 0xFF,
+ len >> 8}, value[2], i;
+
+ for (i = 0; i < ARRAY_SIZE(command); i++)
+ if (bootloader_write_data(dd, command[i]) != 0)
+ return -1;
+ msleep(200); /* wait 200ms for it to get done */
+
+ for (i = 0; i < 2; i++)
+ if (bootloader_read_data(dd, &value[i]) != 0)
+ return -1;
+
+ if (bootloader_wait_command(dd) != 0)
+ return -1;
+ *crc16 = (value[1] << 8) | value[0];
+ return 0;
+}
+
+static int bootloader_set_byte_mode(struct dev_data *dd)
+{
+ u16 command[2] = {0x000A, 0x0000}, i;
+
+ for (i = 0; i < ARRAY_SIZE(command); i++)
+ if (bootloader_write_data(dd, command[i]) != 0)
+ return -1;
+ if (bootloader_wait_command(dd) != 0)
+ return -1;
+ return 0;
+}
+
+static int bootloader_erase_flash(struct dev_data *dd)
+{
+ if (bootloader_write_data(dd, 0x0002) != 0)
+ return -1;
+ msleep(60); /* wait 60ms */
+ if (bootloader_wait_command(dd) != 0)
+ return -1;
+ return 0;
+}
+
+static int bootloader_write_flash(struct dev_data *dd, u16 *image, u16 len)
+{
+ u16 command[] = {0x00F0, 0x0000, len >> 8, 0x0000, 0x0000};
+ u16 i, buffer[FLASH_BLOCK_SIZE];
+
+ for (i = 0; i < ARRAY_SIZE(command); i++)
+ if (bootloader_write_data(dd, command[i]) != 0)
+ return -1;
+
+ for (i = 0; i < ((len / sizeof(u16)) / FLASH_BLOCK_SIZE); i++) {
+ if (bootloader_wait_ready(dd) != 0)
+ return -1;
+ memcpy(buffer, (void *)(image + i * FLASH_BLOCK_SIZE),
+ sizeof(buffer));
+ if (spi_write_3(dd, ((i % 2) == 0) ? 0x0000 : 0x0040,
+ (u8 *)buffer, sizeof(buffer)) != 0)
+ return -1;
+ if (bootloader_complete(dd) != 0)
+ return -1;
+ }
+
+ usleep_range(10000, 11000);
+ if (bootloader_wait_command(dd) != 0)
+ return -1;
+ return 0;
+}
+
+static int device_fw_load(struct dev_data *dd, const struct firmware *fw)
+{
+ u16 fw_crc16, chip_crc16;
+
+ fw_crc16 = crc16(0, fw->data, fw->size);
+ INFO("firmware size (%d) CRC16(0x%04X)", (int)fw->size, fw_crc16);
+ if (bootloader_enter(dd) != 0) {
+ ERROR("failed to enter bootloader");
+ return -1;
+ }
+ if (bootloader_get_crc(dd, &chip_crc16, fw->size) != 0) {
+ ERROR("failed to get CRC16 from the chip");
+ return -1;
+ }
+ INFO("chip CRC16(0x%04X)", chip_crc16);
+ if (fw_crc16 != chip_crc16) {
+ INFO("will reprogram chip");
+ if (bootloader_erase_flash(dd) != 0) {
+ ERROR("failed to erase chip flash");
+ return -1;
+ }
+ INFO("flash erase OK");
+ if (bootloader_set_byte_mode(dd) != 0) {
+ ERROR("failed to set byte mode");
+ return -1;
+ }
+ INFO("byte mode OK");
+ if (bootloader_write_flash(dd, (u16 *)fw->data,
+ fw->size) != 0) {
+ ERROR("failed to write flash");
+ return -1;
+ }
+ INFO("flash write OK");
+ if (bootloader_get_crc(dd, &chip_crc16, fw->size) != 0) {
+ ERROR("failed to get CRC16 from the chip");
+ return -1;
+ }
+ if (fw_crc16 != chip_crc16) {
+ ERROR("failed to verify programming! (0x%04X)",
+ chip_crc16);
+ return -1;
+ }
+ INFO("chip programmed successfully, new chip CRC16(0x%04X)",
+ chip_crc16);
+ }
+ if (bootloader_exit(dd) != 0) {
+ ERROR("failed to exit bootloader");
+ return -1;
+ }
+ return 0;
+}
+
+static int fw_request_load(struct dev_data *dd)
+{
+ const struct firmware *fw;
+ int ret;
+
+ ret = request_firmware(&fw, "maxim_fp35.bin", &dd->spi->dev);
+ if (ret || fw == NULL) {
+ ERROR("firmware request failed (%d,%p)", ret, fw);
+ return -1;
+ }
+ if (fw->size != FIRMWARE_SIZE) {
+ release_firmware(fw);
+ ERROR("incoming firmware is of wrong size (%04X)",
+ (unsigned int)fw->size);
+ return -1;
+ }
+ ret = device_fw_load(dd, fw);
+ if (ret != 0 && bootloader_exit(dd) != 0)
+ ERROR("failed to exit bootloader");
+ release_firmware(fw);
+ return ret;
+}
+
+/* ======================================================================== */
+
+static void stop_idle_scan(struct dev_data *dd)
+{
+ u16 value;
+
+ value = dd->irq_param[13];
+ (void)dd->chip.write(dd, dd->irq_param[19],
+ (u8 *)&value, sizeof(value));
+}
+
+static void stop_scan_canned(struct dev_data *dd)
+{
+ u16 value;
+ u16 i, clear[2] = { 0 };
+
+ if (dd->legacy_acceleration)
+ (void)stop_legacy_acceleration_canned(dd);
+ value = dd->irq_param[13];
+ (void)dd->chip.write(dd, dd->irq_param[12], (u8 *)&value,
+ sizeof(value));
+ usleep_range(dd->irq_param[15], dd->irq_param[15] + 1000);
+ (void)dd->chip.read(dd, dd->irq_param[0], (u8 *)&clear[0],
+ sizeof(clear[0]));
+ (void)dd->chip.write(dd, dd->irq_param[0], (u8 *)&clear,
+ sizeof(clear));
+
+ for (i = 28; i < 32; i++) {
+ value = dd->irq_param[i];
+ (void)dd->chip.write(dd, dd->irq_param[27],
+ (u8 *)&value, sizeof(value));
+ }
+ value = dd->irq_param[33];
+ (void)dd->chip.write(dd, dd->irq_param[32],
+ (u8 *)&value, sizeof(value));
+ usleep_range(500, 1000);
+ for (i = 28; i < 32; i++) {
+ value = dd->irq_param[i];
+ (void)dd->chip.write(dd, dd->irq_param[27],
+ (u8 *)&value, sizeof(value));
+ }
+ value = dd->irq_param[13];
+ (void)dd->chip.write(dd, dd->irq_param[32],
+ (u8 *)&value, sizeof(value));
+}
+
+static void start_scan_canned(struct dev_data *dd)
+{
+ u16 value;
+
+ if (dd->legacy_acceleration) {
+ (void)start_legacy_acceleration_canned(dd);
+ } else {
+ value = dd->irq_param[14];
+ (void)dd->chip.write(dd, dd->irq_param[12], (u8 *)&value,
+ sizeof(value));
+ }
+}
+
+static void enable_gesture(struct dev_data *dd)
+{
+ u16 value;
+
+ if (!dd->idle)
+ stop_scan_canned(dd);
+
+ value = dd->irq_param[13];
+ (void)dd->chip.write(dd, dd->irq_param[34],
+ (u8 *)&value, sizeof(value));
+ value = dd->irq_param[36];
+ (void)dd->chip.write(dd, dd->irq_param[35],
+ (u8 *)&value, sizeof(value));
+
+ value = dd->irq_param[18];
+ (void)dd->chip.write(dd, dd->irq_param[16], (u8 *)&value,
+ sizeof(value));
+
+ value = dd->irq_param[20];
+ (void)dd->chip.write(dd, dd->irq_param[19], (u8 *)&value,
+ sizeof(value));
+ if (!dd->idle) {
+ value = dd->irq_param[26];
+ (void)dd->chip.write(dd, dd->irq_param[25], (u8 *)&value,
+ sizeof(value));
+ }
+}
+
+static void gesture_wake_detect(struct dev_data *dd)
+{
+ u16 status, value;
+ int ret = 0;
+
+ ret = dd->chip.read(dd, dd->irq_param[0],
+ (u8 *)&status, sizeof(status));
+ INFO("%s: %d = %04X", __func__, dd->irq_param[0], status);
+ if (status & dd->irq_param[10])
+ dd->gesture_reset = true;
+ if (status & dd->irq_param[18] && dd->input_dev[INPUT_DEVICES - 1]) {
+ ret = dd->chip.read(dd, dd->irq_param[22],
+ (u8 *)&value, sizeof(value));
+ INFO("gesture code = 0x%04X", value);
+ if (value == dd->irq_param[24]) {
+ INFO("gesture detected");
+ input_report_key(dd->input_dev[INPUT_DEVICES - 1], KEY_POWER, 1);
+ input_sync(dd->input_dev[INPUT_DEVICES - 1]);
+ input_report_key(dd->input_dev[INPUT_DEVICES - 1], KEY_POWER, 0);
+ input_sync(dd->input_dev[INPUT_DEVICES - 1]);
+ }
+ value = dd->irq_param[18];
+ ret = dd->chip.write(dd, dd->irq_param[0],
+ (u8 *)&value, sizeof(value));
+ } else {
+ ret = dd->chip.write(dd, dd->irq_param[0],
+ (u8 *)&status, sizeof(status));
+ }
+}
+
+static void finish_gesture(struct dev_data *dd)
+{
+ struct maxim_sti_pdata *pdata = dd->spi->dev.platform_data;
+ u16 value;
+ u8 fail_count = 0;
+ int ret;
+
+ value = dd->irq_param[21];
+ (void)dd->chip.write(dd, dd->irq_param[19], (u8 *)&value,
+ sizeof(value));
+ do {
+ msleep(20);
+ ret = dd->chip.read(dd, dd->irq_param[25], (u8 *)&value,
+ sizeof(value));
+ if (ret < 0 || fail_count >= 20) {
+ ERROR("failed to read control register (%d)", ret);
+ pdata->reset(pdata, 0);
+ msleep(20);
+ pdata->reset(pdata, 1);
+ return;
+ }
+ INFO("ctrl = 0x%04X", value);
+ fail_count++;
+ } while (value);
+}
+
+static int regulator_init(struct dev_data *dd)
+{
+ int ret;
+
+ dd->reg_avdd = devm_regulator_get(&dd->spi->dev, "avdd");
+ if (IS_ERR(dd->reg_avdd)) {
+ ret = PTR_ERR(dd->reg_avdd);
+ dd->reg_avdd = NULL;
+ dev_err(&dd->spi->dev, "can't find avdd regulator: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regulator_set_voltage(dd->reg_avdd,
+ VTG_AVDD_MIN_UV, VTG_AVDD_MAX_UV);
+ if (ret) {
+ dev_err(&dd->spi->dev,
+ "can't set avdd regulator voltage: %d\n", ret);
+ goto err_free_avdd;
+ }
+
+ dd->reg_dvdd = devm_regulator_get(&dd->spi->dev, "dvdd");
+ if (IS_ERR(dd->reg_dvdd)) {
+ ret = PTR_ERR(dd->reg_avdd);
+ dd->reg_dvdd = NULL;
+ dev_err(&dd->spi->dev, "can't find avdd regulator: %d\n",
+ ret);
+ goto err_free_avdd;
+ }
+
+ ret = regulator_set_voltage(dd->reg_dvdd,
+ VTG_DVDD_MIN_UV, VTG_DVDD_MAX_UV);
+ if (ret) {
+ dev_err(&dd->spi->dev,
+ "can't set dvdd regulator voltage: %d\n", ret);
+ goto err_free_dvdd;
+ }
+ return 0;
+
+err_free_dvdd:
+ devm_regulator_put(dd->reg_dvdd);
+ dd->reg_dvdd = NULL;
+err_free_avdd:
+ devm_regulator_put(dd->reg_avdd);
+ dd->reg_avdd = NULL;
+ return ret;
+}
+
+static void regulator_uninit(struct dev_data *dd)
+{
+ if (dd->reg_dvdd)
+ devm_regulator_put(dd->reg_dvdd);
+ if (dd->reg_avdd)
+ devm_regulator_put(dd->reg_avdd);
+}
+
+static int regulator_control(struct dev_data *dd, bool on)
+{
+ int ret;
+
+ if (!dd->reg_avdd || !dd->reg_dvdd)
+ return 0;
+
+ if (on && !dd->supply) {
+ DBG("regulator ON.");
+ ret = regulator_enable(dd->reg_dvdd);
+ if (ret < 0) {
+ ERROR("failed to enable dvdd regulator: %d", ret);
+ return ret;
+ }
+ usleep_range(1000, 1020);
+
+ ret = regulator_enable(dd->reg_avdd);
+ if (ret < 0) {
+ ERROR("failed to enable avdd regulator: %d", ret);
+ regulator_disable(dd->reg_dvdd);
+ return ret;
+ }
+
+ dd->supply = true;
+ } else if (!on && dd->supply) {
+ DBG("regulator OFF.");
+
+ ret = regulator_disable(dd->reg_avdd);
+ if (ret < 0)
+ ERROR("Failed to disable regulator avdd: %d", ret);
+
+ ret = regulator_disable(dd->reg_dvdd);
+ if (ret < 0)
+ ERROR("Failed to disable regulator dvdd: %d", ret);
+
+ dd->supply = false;
+ }
+
+ return 0;
+}
+
+#define MAXIM_STI_GPIO_ERROR(ret, gpio, op) \
+ if (ret < 0) { \
+ pr_err("%s: GPIO %d %s failed (%d)\n", __func__, gpio, op, \
+ ret); \
+ return ret; \
+ }
+
+
+int maxim_sti_gpio_init(struct maxim_sti_pdata *pdata, bool init)
+{
+ int ret;
+
+ if (init) {
+ ret = gpio_request(pdata->gpio_irq, "maxim_sti_irq");
+ MAXIM_STI_GPIO_ERROR(ret, pdata->gpio_irq, "request");
+ ret = gpio_direction_input(pdata->gpio_irq);
+ MAXIM_STI_GPIO_ERROR(ret, pdata->gpio_irq, "direction");
+ ret = gpio_request(pdata->gpio_reset, "maxim_sti_reset");
+ MAXIM_STI_GPIO_ERROR(ret, pdata->gpio_reset, "request");
+ ret = gpio_direction_output(pdata->gpio_reset,
+ pdata->default_reset_state);
+ MAXIM_STI_GPIO_ERROR(ret, pdata->gpio_reset, "direction");
+ } else {
+ gpio_free(pdata->gpio_irq);
+ gpio_free(pdata->gpio_reset);
+ }
+
+ return 0;
+}
+
+void maxim_sti_gpio_reset(struct maxim_sti_pdata *pdata, int value)
+{
+ gpio_set_value(pdata->gpio_reset, !!value);
+}
+
+int maxim_sti_gpio_irq(struct maxim_sti_pdata *pdata)
+{
+ return gpio_get_value(pdata->gpio_irq);
+}
+
+/****************************************************************************\
+* Device Tree Support
+\****************************************************************************/
+
+#ifdef CONFIG_OF
+static int maxim_parse_dt(struct device *dev, struct maxim_sti_pdata *pdata)
+{
+ struct device_node *np = dev->of_node;
+ u32 flags;
+ const char *str;
+ int ret;
+
+ pdata->gpio_reset = of_get_named_gpio_flags(np,
+ "maxim_sti,reset-gpio", 0, &flags);
+ pdata->default_reset_state = (u8)flags;
+
+ pdata->gpio_irq = of_get_named_gpio_flags(np,
+ "maxim_sti,irq-gpio", 0, &flags);
+
+ pdata->mt_type_b_enabled =
+ of_property_read_bool(np, "maxim_sti,mt_type_b_enabled");
+
+ ret = of_property_read_string(np, "maxim_sti,touch_fusion", &str);
+ if (ret) {
+ dev_err(dev, "%s: unable to read touch_fusion location (%d)\n",
+ __func__, ret);
+ goto fail;
+ }
+ pdata->touch_fusion = (char *)str;
+
+ ret = of_property_read_string(np, "maxim_sti,config_file", &str);
+ if (ret) {
+ dev_err(dev, "%s: unable to read config_file location (%d)\n",
+ __func__, ret);
+ goto fail;
+ }
+ pdata->config_file = (char *)str;
+
+ ret = of_property_read_string(np, "maxim_sti,fw_name", &str);
+ if (ret) {
+ dev_err(dev, "%s: unable to read fw_name (%d)\n",
+ __func__, ret);
+ }
+ pdata->fw_name = (char *)str;
+
+ return 0;
+
+fail:
+ return ret;
+}
+#endif
+
+/****************************************************************************\
+* Suspend/resume processing *
+\****************************************************************************/
+
+#ifdef CONFIG_PM_SLEEP
+static int suspend(struct device *dev)
+{
+ struct dev_data *dd = spi_get_drvdata(to_spi_device(dev));
+
+ DBG("%s: suspending", __func__);
+
+ if (dd->suspended) {
+ DBG("%s: already suspended", __func__);
+ return 0;
+ }
+
+ if (dd->suspend_in_progress) {
+ dev_err(dev, "suspend already in progress!");
+ return -EINVAL;
+ }
+
+ dd->suspend_in_progress = true;
+ wake_up_process(dd->thread);
+ wait_for_completion(&dd->suspend_resume);
+
+ DBG("%s: suspended", __func__);
+
+ return 0;
+}
+
+static int resume(struct device *dev)
+{
+ struct dev_data *dd = spi_get_drvdata(to_spi_device(dev));
+
+ DBG("%s: resuming", __func__);
+
+ if (!dd->suspended && !dd->suspend_in_progress) {
+ DBG("%s: not suspended", __func__);
+ return 0;
+ }
+
+ dd->resume_in_progress = true;
+ wake_up_process(dd->thread);
+ wait_for_completion(&dd->suspend_resume);
+ DBG("%s: resumed", __func__);
+ return 0;
+}
+
+static const struct dev_pm_ops pm_ops = {
+ .suspend = suspend,
+ .resume = resume,
+};
+
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct dev_data *dd = container_of(self,
+ struct dev_data, fb_notifier);
+
+ DBG("%s: event = %lu", __func__, event);
+ if (evdata && evdata->data && event == FB_EVENT_BLANK) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ resume(&dd->spi->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ suspend(&dd->spi->dev);
+ }
+ return 0;
+}
+#endif
+#endif
+
+/****************************************************************************\
+* Netlink processing *
+\****************************************************************************/
+
+static inline int
+nl_msg_new(struct dev_data *dd, u8 dst)
+{
+ dd->outgoing_skb = alloc_skb(NL_BUF_SIZE, GFP_KERNEL);
+ if (dd->outgoing_skb == NULL)
+ return -ENOMEM;
+ nl_msg_init(dd->outgoing_skb->data, dd->nl_family.id, dd->nl_seq++,
+ dst);
+ if (dd->nl_seq == 0)
+ dd->nl_seq++;
+ return 0;
+}
+
+static int
+nl_callback_noop(struct sk_buff *skb, struct genl_info *info)
+{
+ return 0;
+}
+
+static void
+release_slot_events(struct dev_data *dd, bool *active_touch, int inp)
+{
+ int i;
+
+ for (i = 0; i < MAX_INPUT_EVENTS; i++) {
+ if (dd->touch_status[inp][i] == true &&
+ active_touch[i] == false) {
+ input_mt_slot(dd->input_dev[inp], i);
+ input_mt_report_slot_state(dd->input_dev[inp],
+ MT_TOOL_FINGER, 0);
+ }
+ dd->touch_status[inp][i] = active_touch[i];
+ }
+}
+
+static inline bool
+nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
+{
+ struct maxim_sti_pdata *pdata = dd->spi->dev.platform_data;
+ struct dr_echo_request *echo_msg;
+ struct fu_echo_response *echo_response;
+ struct dr_chip_read *read_msg;
+ struct fu_chip_read_result *read_result;
+ struct dr_chip_write *write_msg;
+ struct dr_chip_access_method *chip_access_method_msg;
+ struct dr_delay *delay_msg;
+ struct fu_irqline_status *irqline_status;
+ struct dr_config_irq *config_irq_msg;
+ struct dr_config_input *config_input_msg;
+ struct dr_config_watchdog *config_watchdog_msg;
+ struct dr_input *input_msg;
+ struct dr_legacy_acceleration *legacy_acceleration_msg;
+ struct dr_handshake *handshake_msg;
+ struct fu_handshake_response *handshake_response;
+ struct dr_config_fw *config_fw_msg;
+ struct dr_sysfs_ack *sysfs_ack_msg;
+ struct dr_idle *idle_msg;
+ struct dr_tf_status *tf_status_msg;
+ u8 i, inp;
+ int ret, id;
+ u16 read_value[2] = { 0 };
+ bool active_touch[INPUT_DEVICES][MAX_INPUT_EVENTS] = { {false} };
+
+ if (dd->expect_resume_ack && msg_id != DR_DECONFIG &&
+ msg_id != DR_RESUME_ACK)
+ return false;
+
+ switch (msg_id) {
+ case DR_ADD_MC_GROUP:
+ INFO("warning: deprecated dynamic mc group add request!");
+ return false;
+ case DR_ECHO_REQUEST:
+ DRV_MSG_DBG("msg: %s", "DR_ECHO_REQUEST");
+ echo_msg = msg;
+ echo_response = nl_alloc_attr(dd->outgoing_skb->data,
+ FU_ECHO_RESPONSE,
+ sizeof(*echo_response));
+ if (echo_response == NULL)
+ goto alloc_attr_failure;
+ echo_response->cookie = echo_msg->cookie;
+ return true;
+ case DR_CHIP_READ:
+ DRV_MSG_DBG("msg: %s", "DR_CHIP_READ");
+ read_msg = msg;
+ read_result = nl_alloc_attr(dd->outgoing_skb->data,
+ FU_CHIP_READ_RESULT,
+ sizeof(*read_result) + read_msg->length);
+ if (read_result == NULL)
+ goto alloc_attr_failure;
+ read_result->address = read_msg->address;
+ read_result->length = read_msg->length;
+ ret = dd->chip.read(dd, read_msg->address, read_result->data,
+ read_msg->length);
+ if (ret < 0)
+ ERROR("failed to read from chip (%d, %d, %d)",
+ read_msg->address, read_msg->length, ret);
+ return true;
+ case DR_CHIP_WRITE:
+ DRV_MSG_DBG("msg: %s", "DR_CHIP_WRITE");
+ write_msg = msg;
+ if (write_msg->address == dd->irq_param[12] &&
+ write_msg->data[0] == dd->irq_param[13]) {
+ ret = dd->chip.write(dd, write_msg->address,
+ write_msg->data,
+ write_msg->length);
+ if (ret < 0)
+ ERROR("failed to write chip (%d)", ret);
+ msleep(15);
+ ret = dd->chip.read(dd, dd->irq_param[0],
+ (u8 *)read_value,
+ sizeof(read_value));
+ if (ret < 0)
+ ERROR("failed to read from chip (%d)", ret);
+ ret = dd->chip.write(dd, dd->irq_param[0],
+ (u8 *)read_value,
+ sizeof(read_value));
+ return false;
+ }
+ if (write_msg->address == dd->irq_param[0]) {
+ if (((u16 *)write_msg->data)[0] == dd->irq_param[11]) {
+ ret = dd->chip.read(dd, dd->irq_param[0],
+ (u8 *)read_value,
+ sizeof(read_value));
+ if (ret < 0)
+ ERROR("failed to read from chip (%d)", ret);
+ ret = dd->chip.write(dd, dd->irq_param[0],
+ (u8 *)read_value,
+ sizeof(read_value));
+ return false;
+ }
+ read_value[0] = ((u16 *)write_msg->data)[0];
+ ret = dd->chip.write(dd, write_msg->address,
+ (u8 *)read_value,
+ sizeof(read_value));
+ return false;
+ }
+ ret = dd->chip.write(dd, write_msg->address, write_msg->data,
+ write_msg->length);
+ if (ret < 0)
+ ERROR("failed to write chip (%d, %d, %d)",
+ write_msg->address, write_msg->length, ret);
+ return false;
+ case DR_CHIP_RESET:
+ DRV_MSG_DBG("msg: %s", "DR_CHIP_RESET");
+ pdata->reset(pdata, ((struct dr_chip_reset *)msg)->state);
+ return false;
+ case DR_GET_IRQLINE:
+ DRV_MSG_DBG("msg: %s", "DR_GET_IRQLINE");
+ irqline_status = nl_alloc_attr(dd->outgoing_skb->data,
+ FU_IRQLINE_STATUS,
+ sizeof(*irqline_status));
+ if (irqline_status == NULL)
+ goto alloc_attr_failure;
+ irqline_status->status = pdata->irq(pdata);
+ return true;
+ case DR_DELAY:
+ DRV_MSG_DBG("msg: %s", "DR_DELAY");
+ delay_msg = msg;
+ if (delay_msg->period > 1000)
+ msleep(delay_msg->period / 1000);
+ usleep_range(delay_msg->period % 1000,
+ (delay_msg->period % 1000) + 10);
+ return false;
+ case DR_CHIP_ACCESS_METHOD:
+ DRV_MSG_DBG("msg: %s", "DR_CHIP_ACCESS_METHOD");
+ chip_access_method_msg = msg;
+ ret = set_chip_access_method(dd,
+ chip_access_method_msg->method);
+ if (ret < 0)
+ ERROR("failed to set chip access method (%d) (%d)",
+ ret, chip_access_method_msg->method);
+ return false;
+ case DR_CONFIG_IRQ:
+ DRV_MSG_DBG("msg: %s", "DR_CONFIG_IRQ");
+ config_irq_msg = msg;
+ if (config_irq_msg->irq_params > MAX_IRQ_PARAMS) {
+ ERROR("too many IRQ parameters");
+ return false;
+ }
+ memcpy(dd->irq_param, config_irq_msg->irq_param,
+ config_irq_msg->irq_params * sizeof(dd->irq_param[0]));
+ if (dd->irq_registered)
+ return false;
+ dd->service_irq = service_irq;
+ ret = request_irq(dd->spi->irq, irq_handler,
+ (config_irq_msg->irq_edge == DR_IRQ_RISING_EDGE) ?
+ IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING,
+ pdata->nl_family, dd);
+ if (ret < 0) {
+ ERROR("failed to request IRQ (%d)", ret);
+ } else {
+ dd->irq_registered = true;
+ wake_up_process(dd->thread);
+ }
+ return false;
+ case DR_CONFIG_INPUT:
+ DRV_MSG_DBG("msg: %s", "DR_CONFIG_INPUT");
+ config_input_msg = msg;
+ for (i = 0; i < INPUT_DEVICES; i++)
+ if (dd->input_dev[i] != NULL)
+ return false;
+ for (i = 0; i < INPUT_DEVICES; i++) {
+ dd->input_dev[i] = input_allocate_device();
+ if (dd->input_dev[i] == NULL) {
+ ERROR("failed to allocate input device");
+ continue;
+ }
+ snprintf(dd->input_phys, sizeof(dd->input_phys),
+ "%s/input%d", dev_name(&dd->spi->dev), i);
+ dd->input_dev[i]->name = pdata->nl_family;
+ dd->input_dev[i]->phys = dd->input_phys;
+ dd->input_dev[i]->id.bustype = BUS_SPI;
+ __set_bit(EV_SYN, dd->input_dev[i]->evbit);
+ __set_bit(EV_ABS, dd->input_dev[i]->evbit);
+ __set_bit(INPUT_PROP_DIRECT, dd->input_dev[i]->propbit);
+ if (i == (INPUT_DEVICES - 1)) {
+ __set_bit(EV_KEY, dd->input_dev[i]->evbit);
+ __set_bit(BTN_TOOL_RUBBER,
+ dd->input_dev[i]->keybit);
+ __set_bit(KEY_POWER,
+ dd->input_dev[i]->keybit);
+ }
+ if (pdata->mt_type_b_enabled &&
+ input_mt_init_slots(dd->input_dev[i],
+ MAX_INPUT_EVENTS, 0)) {
+ ERROR("Error in initialising slots\n");
+ input_free_device(dd->input_dev[i]);
+ dd->input_dev[i] = NULL;
+ continue;
+ } else {
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_TRACKING_ID, 0,
+ MAX_INPUT_EVENTS, 0, 0);
+ }
+
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_POSITION_X, 0,
+ config_input_msg->x_range, 0, 0);
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_POSITION_Y, 0,
+ config_input_msg->y_range, 0, 0);
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
+
+ if (i == (INPUT_DEVICES - 1))
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_TOOL_TYPE, 0,
+ MT_TOOL_MAX, 0, 0);
+ else
+ input_set_abs_params(dd->input_dev[i],
+ ABS_MT_TOOL_TYPE, 0,
+ MT_TOOL_FINGER, 0, 0);
+
+ ret = input_register_device(dd->input_dev[i]);
+ if (ret < 0) {
+ input_free_device(dd->input_dev[i]);
+ dd->input_dev[i] = NULL;
+ ERROR("failed to register input device");
+ }
+ }
+#if defined(CONFIG_FB)
+ dd->fb_notifier.notifier_call = fb_notifier_callback;
+ fb_register_client(&dd->fb_notifier);
+#endif
+ /* create symlink */
+ if (dd->parent == NULL && dd->input_dev[0] != NULL) {
+ dd->parent = dd->input_dev[0]->dev.kobj.parent;
+ ret = sysfs_create_link(dd->parent, &dd->spi->dev.kobj,
+ MAXIM_STI_NAME);
+ if (ret) {
+ ERROR("sysfs_create_link error\n");
+ dd->parent = NULL;
+ }
+ }
+ return false;
+ case DR_CONFIG_WATCHDOG:
+ DRV_MSG_DBG("msg: %s", "DR_CONFIG_WATCHDOG");
+ config_watchdog_msg = msg;
+ dd->fusion_process = (pid_t)config_watchdog_msg->pid;
+ return false;
+ case DR_DECONFIG:
+ DRV_MSG_DBG("msg: %s", "DR_DECONFIG");
+ if (dd->irq_registered) {
+ free_irq(dd->spi->irq, dd);
+ dd->irq_registered = false;
+ }
+ stop_scan_canned(dd);
+
+ if (!dd->input_no_deconfig) {
+ if (dd->parent != NULL) {
+ sysfs_remove_link(
+ dd->input_dev[0]->dev.kobj.parent,
+ MAXIM_STI_NAME);
+ dd->parent = NULL;
+ }
+ }
+
+ if (!dd->input_no_deconfig) {
+ for (i = 0; i < INPUT_DEVICES; i++) {
+ if (dd->input_dev[i] == NULL)
+ continue;
+ input_unregister_device(dd->input_dev[i]);
+ dd->input_dev[i] = NULL;
+ }
+#if defined(CONFIG_FB)
+ fb_unregister_client(&dd->fb_notifier);
+#endif
+ }
+ dd->expect_resume_ack = false;
+ dd->eraser_active = false;
+ dd->legacy_acceleration = false;
+ dd->service_irq = service_irq;
+ dd->fusion_process = (pid_t)0;
+ dd->sysfs_update_type = DR_SYSFS_UPDATE_NONE;
+ return false;
+ case DR_INPUT:
+ DRV_MSG_DBG("msg: %s", "DR_INPUT");
+ input_msg = msg;
+ if (input_msg->events == 0) {
+ if (dd->eraser_active) {
+ input_report_key(
+ dd->input_dev[INPUT_DEVICES - 1],
+ BTN_TOOL_RUBBER, 0);
+ dd->eraser_active = false;
+ }
+ for (i = 0; i < INPUT_DEVICES; i++) {
+ if (pdata->mt_type_b_enabled)
+ release_slot_events(dd,
+ active_touch[i], i);
+ else
+ input_mt_sync(dd->input_dev[i]);
+
+ input_sync(dd->input_dev[i]);
+ }
+ } else {
+ for (i = 0; i < input_msg->events; i++) {
+ switch (input_msg->event[i].tool_type) {
+ case DR_INPUT_FINGER:
+ inp = 0;
+ id = input_msg->event[i].id;
+ if (pdata->mt_type_b_enabled) {
+ input_mt_slot(
+ dd->input_dev[inp], id);
+ input_mt_report_slot_state(
+ dd->input_dev[inp],
+ MT_TOOL_FINGER, 1);
+ active_touch[inp][id] = true;
+ } else {
+ input_report_abs(
+ dd->input_dev[inp],
+ ABS_MT_TOOL_TYPE,
+ MT_TOOL_FINGER);
+ }
+ break;
+ case DR_INPUT_STYLUS:
+ inp = INPUT_DEVICES - 1;
+ if (pdata->mt_type_b_enabled) {
+ input_mt_slot(
+ dd->input_dev[inp], id);
+ input_mt_report_slot_state(
+ dd->input_dev[inp],
+ MT_TOOL_PEN, 1);
+ active_touch[inp][id] = true;
+ } else {
+ input_report_abs(
+ dd->input_dev[inp],
+ ABS_MT_TOOL_TYPE,
+ MT_TOOL_PEN);
+ }
+ break;
+ case DR_INPUT_ERASER:
+ inp = INPUT_DEVICES - 1;
+ input_report_key(dd->input_dev[inp],
+ BTN_TOOL_RUBBER, 1);
+ dd->eraser_active = true;
+ break;
+ default:
+ inp = 0;
+ ERROR("invalid input tool type (%d)",
+ input_msg->event[i].tool_type);
+ break;
+ }
+ if (!pdata->mt_type_b_enabled)
+ input_report_abs(dd->input_dev[inp],
+ ABS_MT_TRACKING_ID, id);
+ input_report_abs(dd->input_dev[inp],
+ ABS_MT_POSITION_X,
+ input_msg->event[i].x);
+ input_report_abs(dd->input_dev[inp],
+ ABS_MT_POSITION_Y,
+ input_msg->event[i].y);
+ input_report_abs(dd->input_dev[inp],
+ ABS_MT_PRESSURE,
+ input_msg->event[i].z);
+ if (!pdata->mt_type_b_enabled)
+ input_mt_sync(dd->input_dev[inp]);
+ }
+
+ if (pdata->mt_type_b_enabled) {
+ for (i = 0; i < INPUT_DEVICES; i++)
+ release_slot_events(dd,
+ active_touch[i], i);
+ }
+
+ for (i = 0; i < INPUT_DEVICES; i++)
+ input_sync(dd->input_dev[i]);
+ }
+ return false;
+ case DR_RESUME_ACK:
+ DRV_MSG_DBG("msg: %s", "DR_RESUME_ACK");
+ dd->expect_resume_ack = false;
+ if (dd->irq_registered
+ && !dd->gesture_en
+ )
+ enable_irq(dd->spi->irq);
+ return false;
+ case DR_LEGACY_FWDL:
+ DRV_MSG_DBG("msg: %s", "DR_LEGACY_FWDL");
+ ret = fw_request_load(dd);
+ if (ret < 0)
+ ERROR("firmware download failed (%d)", ret);
+ else
+ INFO("firmware download OK");
+ return false;
+ case DR_LEGACY_ACCELERATION:
+ DRV_MSG_DBG("msg: %s", "DR_LEGACY_ACCELERATION");
+ legacy_acceleration_msg = msg;
+ if (legacy_acceleration_msg->enable) {
+ dd->service_irq = service_irq_legacy_acceleration;
+ start_legacy_acceleration(dd);
+ dd->legacy_acceleration = true;
+ } else {
+ stop_legacy_acceleration(dd);
+ dd->legacy_acceleration = false;
+ dd->service_irq = service_irq;
+ }
+ return false;
+ case DR_HANDSHAKE:
+ DRV_MSG_DBG("msg: %s", "DR_HANDSHAKE");
+ handshake_msg = msg;
+ dd->tf_ver = handshake_msg->tf_ver;
+ dd->chip_id = handshake_msg->chip_id;
+ dd->drv_ver = DRIVER_VERSION_NUM;
+ handshake_response = nl_alloc_attr(dd->outgoing_skb->data,
+ FU_HANDSHAKE_RESPONSE,
+ sizeof(*handshake_response));
+ if (handshake_response == NULL)
+ goto alloc_attr_failure;
+ handshake_response->driver_ver = dd->drv_ver;
+ handshake_response->panel_id = panel_id;
+ handshake_response->driver_protocol = DRIVER_PROTOCOL;
+ return true;
+ case DR_CONFIG_FW:
+ DRV_MSG_DBG("msg: %s", "DR_CONFIG_FW");
+ config_fw_msg = msg;
+ dd->fw_ver = config_fw_msg->fw_ver;
+ dd->fw_protocol = config_fw_msg->fw_protocol;
+ return false;
+ case DR_SYSFS_ACK:
+ sysfs_ack_msg = msg;
+ if (sysfs_ack_msg->type == DR_SYSFS_ACK_GLOVE)
+ complete(&dd->sysfs_ack_glove);
+ if (sysfs_ack_msg->type == DR_SYSFS_ACK_CHARGER)
+ complete(&dd->sysfs_ack_charger);
+ if (sysfs_ack_msg->type == DR_SYSFS_ACK_LCD_FPS)
+ complete(&dd->sysfs_ack_lcd_fps);
+ return false;
+ case DR_IDLE:
+ DRV_MSG_DBG("msg: %s", "DR_IDLE");
+ idle_msg = msg;
+ dd->idle = !!(idle_msg->idle);
+ return false;
+ case DR_TF_STATUS:
+ tf_status_msg = msg;
+ dd->tf_status = tf_status_msg->tf_status;
+ return false;
+ default:
+ ERROR("unexpected message %d", msg_id);
+ return false;
+ }
+
+alloc_attr_failure:
+ ERROR("failed to allocate response for msg_id %d", msg_id);
+ return false;
+}
+
+static int nl_process_msg(struct dev_data *dd, struct sk_buff *skb)
+{
+ struct nlattr *attr;
+ bool send_reply = false;
+ int ret = 0, ret2;
+
+ /* process incoming message */
+ attr = NL_ATTR_FIRST(skb->data);
+ for (; attr < NL_ATTR_LAST(skb->data); attr = NL_ATTR_NEXT(attr)) {
+ if (nl_process_driver_msg(dd, attr->nla_type,
+ NL_ATTR_VAL(attr, void)))
+ send_reply = true;
+ }
+
+ /* send back reply if requested */
+ if (send_reply) {
+ (void)skb_put(dd->outgoing_skb,
+ NL_SIZE(dd->outgoing_skb->data));
+ if (NL_SEQ(skb->data) == 0)
+ ret = genlmsg_unicast(&init_net,
+ dd->outgoing_skb,
+ NETLINK_CB(skb).portid);
+ else
+ ret = genlmsg_multicast(&dd->nl_family,
+ dd->outgoing_skb, 0,
+ MC_FUSION, GFP_KERNEL);
+ if (ret < 0)
+ ERROR("could not reply to fusion (%d)", ret);
+
+ /* allocate new outgoing skb */
+ ret2 = nl_msg_new(dd, MC_FUSION);
+ if (ret2 < 0)
+ ERROR("could not allocate outgoing skb (%d)", ret2);
+ }
+
+ /* free incoming message */
+ kfree_skb(skb);
+ return ret;
+}
+
+static int
+nl_callback_driver(struct sk_buff *skb, struct genl_info *info)
+{
+ struct dev_data *dd;
+ struct sk_buff *skb2;
+ unsigned long flags;
+
+ /* locate device structure */
+ spin_lock_irqsave(&dev_lock, flags);
+ list_for_each_entry(dd, &dev_list, dev_list)
+ if (dd->nl_family.id == NL_TYPE(skb->data))
+ break;
+ spin_unlock_irqrestore(&dev_lock, flags);
+ if (&dd->dev_list == &dev_list)
+ return -ENODEV;
+ if (!dd->nl_enabled)
+ return -EAGAIN;
+
+ /* queue incoming skb and wake up processing thread */
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2 == NULL) {
+ ERROR("failed to clone incoming skb");
+ return -ENOMEM;
+ } else {
+ skb_queue_tail(&dd->incoming_skb_queue, skb2);
+ wake_up_process(dd->thread);
+ return 0;
+ }
+}
+
+static int
+nl_callback_fusion(struct sk_buff *skb, struct genl_info *info)
+{
+ struct dev_data *dd;
+ unsigned long flags;
+
+ /* locate device structure */
+ spin_lock_irqsave(&dev_lock, flags);
+ list_for_each_entry(dd, &dev_list, dev_list)
+ if (dd->nl_family.id == NL_TYPE(skb->data))
+ break;
+ spin_unlock_irqrestore(&dev_lock, flags);
+ if (&dd->dev_list == &dev_list)
+ return -ENODEV;
+ if (!dd->nl_enabled)
+ return -EAGAIN;
+
+ (void)genlmsg_multicast(&dd->nl_family,
+ skb_clone(skb, GFP_ATOMIC), 0,
+ MC_FUSION, GFP_ATOMIC);
+ return 0;
+}
+
+/****************************************************************************\
+* Interrupt processing *
+\****************************************************************************/
+
+static unsigned long interrupt_count;
+static irqreturn_t irq_handler(int irq, void *context)
+{
+ struct dev_data *dd = context;
+
+ DBG("%s: interrupt #%lu", __func__, interrupt_count++);
+
+ wake_up_process(dd->thread);
+ return IRQ_HANDLED;
+}
+
+static void service_irq_legacy_acceleration(struct dev_data *dd)
+{
+ struct fu_async_data *async_data;
+ u16 len, rx_len = 0, offset = 0;
+ u16 buf[255], rx_limit = 250 * sizeof(u16);
+ int ret = 0, counter = 0;
+
+ async_data = nl_alloc_attr(dd->outgoing_skb->data, FU_ASYNC_DATA,
+ sizeof(*async_data) + dd->irq_param[4] +
+ 2 * sizeof(u16));
+ if (async_data == NULL) {
+ ERROR("can't add data to async IRQ buffer");
+ return;
+ }
+ async_data->length = dd->irq_param[4] + 2 * sizeof(u16);
+ len = async_data->length;
+ async_data->address = 0;
+
+ while (len > 0) {
+ rx_len = (len > rx_limit) ? rx_limit : len;
+ ret = spi_read_123(dd, 0x0000, (u8 *)&buf,
+ rx_len + 4 * sizeof(u16), false);
+ if (ret < 0)
+ break;
+
+ if (buf[3] == 0xBABE) {
+ dd->legacy_acceleration = false;
+ dd->service_irq = service_irq;
+ nl_msg_init(dd->outgoing_skb->data, dd->nl_family.id,
+ dd->nl_seq - 1, MC_FUSION);
+ return;
+ }
+
+ if (rx_limit == rx_len)
+ usleep_range(200, 300);
+
+ if (buf[0] == 0x6060) {
+ ERROR("data not ready");
+ start_legacy_acceleration_canned(dd);
+ ret = -EBUSY;
+ break;
+ } else if (buf[0] == 0x8070) {
+ if (buf[1] == dd->irq_param[1] ||
+ buf[1] == dd->irq_param[2])
+ async_data->address = buf[1];
+
+ if (async_data->address +
+ offset / sizeof(u16) != buf[1]) {
+ ERROR("sequence number incorrect %04X", buf[1]);
+ start_legacy_acceleration_canned(dd);
+ ret = -EBUSY;
+ break;
+ }
+ }
+ counter++;
+ memcpy(async_data->data + offset, buf + 4, rx_len);
+ offset += rx_len;
+ len -= rx_len;
+ }
+ async_data->status = *(buf + rx_len / sizeof(u16) + 2);
+
+ if (ret < 0) {
+ ERROR("can't read IRQ buffer (%d)", ret);
+ nl_msg_init(dd->outgoing_skb->data, dd->nl_family.id,
+ dd->nl_seq - 1, MC_FUSION);
+ } else {
+ (void)skb_put(dd->outgoing_skb,
+ NL_SIZE(dd->outgoing_skb->data));
+ ret = genlmsg_multicast(&dd->nl_family, dd->outgoing_skb, 0,
+ MC_FUSION, GFP_KERNEL);
+ if (ret < 0) {
+ ERROR("can't send IRQ buffer %d", ret);
+ msleep(300);
+ if (++dd->send_fail_count >= 10 &&
+ dd->fusion_process != (pid_t)0) {
+ (void)kill_pid(
+ find_get_pid(dd->fusion_process),
+ SIGKILL, 1);
+ wake_up_process(dd->thread);
+ }
+ } else {
+ dd->send_fail_count = 0;
+ }
+ ret = nl_msg_new(dd, MC_FUSION);
+ if (ret < 0)
+ ERROR("could not allocate outgoing skb (%d)", ret);
+ }
+}
+
+static void service_irq(struct dev_data *dd)
+{
+ struct fu_async_data *async_data;
+ u16 status, test, xbuf, value;
+ u16 address[2] = { 0 };
+ u16 clear[2] = { 0 };
+ bool read_buf[2] = {true, false};
+ int ret, ret2;
+
+ DBG("%s", __func__);
+ ret = dd->chip.read(dd, dd->irq_param[0], (u8 *)&status,
+ sizeof(status));
+ if (ret < 0) {
+ ERROR("can't read IRQ status (%d)", ret);
+ return;
+ }
+ DBG("%s: status = 0x%04X", __func__, status);
+
+ if (dd->gesture_reset) {
+ read_buf[0] = false;
+ clear[0] = dd->irq_param[10];
+ status = dd->irq_param[10];
+ dd->gesture_reset = false;
+ } else
+ if (status & dd->irq_param[10]) {
+ read_buf[0] = false;
+ clear[0] = dd->irq_param[10];
+ } else if (status & dd->irq_param[18]) {
+ (void)dd->chip.read(dd, dd->irq_param[22], (u8 *)&value,
+ sizeof(value));
+ if (value != dd->irq_param[23]) {
+ ERROR("unrecognized value [%#x] => %#x",
+ dd->irq_param[22], value);
+ clear[0] = dd->irq_param[18];
+ ret2 = dd->chip.write(dd, dd->irq_param[0],
+ (u8 *)clear, sizeof(clear));
+ return;
+ }
+
+ test = status & (dd->irq_param[6] | dd->irq_param[7]);
+
+ if (test == 0)
+ return;
+ else if (test == (dd->irq_param[6] | dd->irq_param[7]))
+ xbuf = ((status & dd->irq_param[5]) == 0) ? 0 : 1;
+ else if (test == dd->irq_param[6])
+ xbuf = 0;
+ else if (test == dd->irq_param[7])
+ xbuf = 1;
+ else {
+ ERROR("unexpected IRQ handler case 0x%04X ", status);
+ return;
+ }
+
+ read_buf[1] = true;
+ address[1] = xbuf ? dd->irq_param[2] : dd->irq_param[1];
+ address[0] = dd->irq_param[3];
+ clear[0] = xbuf ? dd->irq_param[7] : dd->irq_param[6];
+ clear[0] |= dd->irq_param[8];
+ clear[0] |= dd->irq_param[18];
+
+ value = dd->irq_param[17];
+ (void)dd->chip.write(dd, dd->irq_param[16], (u8 *)&value,
+ sizeof(value));
+ } else if (status & dd->irq_param[9]) {
+ test = status & (dd->irq_param[6] | dd->irq_param[7]);
+
+ if (test == (dd->irq_param[6] | dd->irq_param[7]))
+ xbuf = ((status & dd->irq_param[5]) != 0) ? 0 : 1;
+ else if (test == dd->irq_param[6])
+ xbuf = 0;
+ else if (test == dd->irq_param[7])
+ xbuf = 1;
+ else {
+ ERROR("unexpected IRQ handler case");
+ return;
+ }
+ read_buf[1] = true;
+ address[1] = xbuf ? dd->irq_param[2] : dd->irq_param[1];
+
+ address[0] = dd->irq_param[3];
+ clear[0] = dd->irq_param[6] | dd->irq_param[7] |
+ dd->irq_param[8] | dd->irq_param[9];
+ value = dd->irq_param[13];
+ (void)dd->chip.write(dd, dd->irq_param[12], (u8 *)&value,
+ sizeof(value));
+ } else {
+ test = status & (dd->irq_param[6] | dd->irq_param[7]);
+
+ if (test == 0)
+ return;
+ else if (test == (dd->irq_param[6] | dd->irq_param[7]))
+ xbuf = ((status & dd->irq_param[5]) == 0) ? 0 : 1;
+ else if (test == dd->irq_param[6])
+ xbuf = 0;
+ else if (test == dd->irq_param[7])
+ xbuf = 1;
+ else {
+ ERROR("unexpected IRQ handler case 0x%04X ",status);
+ return;
+ }
+
+ address[0] = xbuf ? dd->irq_param[2] : dd->irq_param[1];
+ clear[0] = xbuf ? dd->irq_param[7] : dd->irq_param[6];
+ clear[0] |= dd->irq_param[8];
+ }
+
+ async_data = nl_alloc_attr(dd->outgoing_skb->data, FU_ASYNC_DATA,
+ sizeof(*async_data) + dd->irq_param[4]);
+ if (async_data == NULL) {
+ ERROR("can't add data to async IRQ buffer 1");
+ return;
+ }
+
+ async_data->status = status;
+ if (read_buf[0]) {
+ async_data->address = address[0];
+ async_data->length = dd->irq_param[4];
+ ret = dd->chip.read(dd, address[0], async_data->data,
+ dd->irq_param[4]);
+ }
+
+ if (read_buf[1] && ret == 0) {
+ async_data = nl_alloc_attr(dd->outgoing_skb->data,
+ FU_ASYNC_DATA,
+ sizeof(*async_data) +
+ dd->irq_param[4]);
+ if (async_data == NULL) {
+ ERROR("can't add data to async IRQ buffer 2");
+ nl_msg_init(dd->outgoing_skb->data, dd->nl_family.id,
+ dd->nl_seq - 1, MC_FUSION);
+ return;
+ }
+ async_data->address = address[1];
+ async_data->length = dd->irq_param[4];
+ async_data->status = status;
+ ret = dd->chip.read(dd, address[1], async_data->data,
+ dd->irq_param[4]);
+ }
+
+ ret2 = dd->chip.write(dd, dd->irq_param[0], (u8 *)clear,
+ sizeof(clear));
+ if (ret2 < 0)
+ ERROR("can't clear IRQ status (%d)", ret2);
+
+ if (ret < 0) {
+ ERROR("can't read IRQ buffer (%d)", ret);
+ nl_msg_init(dd->outgoing_skb->data, dd->nl_family.id,
+ dd->nl_seq - 1, MC_FUSION);
+ } else {
+ DBG("%s: sending buffer", __func__);
+ (void)skb_put(dd->outgoing_skb,
+ NL_SIZE(dd->outgoing_skb->data));
+ ret = genlmsg_multicast(&dd->nl_family, dd->outgoing_skb, 0,
+ MC_FUSION, GFP_KERNEL);
+ if (ret < 0) {
+ ERROR("can't send IRQ buffer %d", ret);
+ msleep(300);
+ if (read_buf[0] == false ||
+ (++dd->send_fail_count >= 10 &&
+ dd->fusion_process != (pid_t)0)) {
+ (void)kill_pid(
+ find_get_pid(dd->fusion_process),
+ SIGKILL, 1);
+ wake_up_process(dd->thread);
+ }
+ } else {
+ dd->send_fail_count = 0;
+ }
+ ret = nl_msg_new(dd, MC_FUSION);
+ if (ret < 0)
+ ERROR("could not allocate outgoing skb (%d)", ret);
+ }
+}
+
+/****************************************************************************\
+* Processing thread *
+\****************************************************************************/
+
+static int processing_thread(void *arg)
+{
+ struct dev_data *dd = arg;
+ struct maxim_sti_pdata *pdata = dd->spi->dev.platform_data;
+ struct sk_buff *skb;
+ char *argv[] = { pdata->touch_fusion, "daemon",
+ pdata->nl_family,
+ dd->config_file, NULL };
+ int ret = 0, ret2 = 0;
+ bool fusion_dead;
+
+ DRV_PT_DBG("%s started", __FUNCTION__);
+ sched_setscheduler(current, SCHED_FIFO, &dd->thread_sched);
+
+ while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ DRV_PT_DBG("Begin");
+
+ /* ensure that we have outgoing skb */
+ if (dd->outgoing_skb == NULL)
+ if (nl_msg_new(dd, MC_FUSION) < 0) {
+ schedule();
+ continue;
+ }
+
+ /* priority 1: start up fusion process */
+ if (dd->fusion_process != (pid_t)0 && get_pid_task(
+ find_get_pid(dd->fusion_process),
+ PIDTYPE_PID) == NULL) {
+ DRV_PT_DBG("Re-Starting TF");
+ stop_scan_canned(dd);
+ dd->start_fusion = true;
+ dd->fusion_process = (pid_t)0;
+ dd->input_no_deconfig = true;
+ }
+ if (dd->start_fusion) {
+ DRV_PT_DBG("Spawning TF");
+ do {
+ ret = call_usermodehelper(argv[0], argv, NULL,
+ UMH_WAIT_EXEC);
+ if (ret != 0)
+ msleep(100);
+ } while (ret != 0 && !kthread_should_stop());
+
+ if (ret == 0) {
+ /* power-up and reset-high */
+ ret = regulator_control(dd, true);
+ if (ret < 0)
+ ERROR("failed to enable regulators");
+
+ usleep_range(300, 400);
+ pdata->reset(pdata, 1);
+
+ dd->start_fusion = false;
+ dd->tf_status |= TF_STATUS_BUSY;
+ }
+ }
+ if (kthread_should_stop())
+ break;
+
+ /* priority 2: process pending Netlink messages */
+ while ((skb = skb_dequeue(&dd->incoming_skb_queue)) != NULL) {
+ if (kthread_should_stop())
+ break;
+ if (nl_process_msg(dd, skb) < 0)
+ skb_queue_purge(&dd->incoming_skb_queue);
+ }
+ if (kthread_should_stop())
+ break;
+
+ /* priority 3: suspend/resume */
+ if (dd->suspend_in_progress && !(dd->tf_status & TF_STATUS_BUSY)) {
+ if (dd->irq_registered) {
+ disable_irq(dd->spi->irq);
+ if (dd->gesture_en) {
+ enable_gesture(dd);
+ enable_irq(dd->spi->irq);
+ } else
+ if (!dd->idle)
+ stop_scan_canned(dd);
+ else
+ stop_idle_scan(dd);
+ }
+
+ dd->suspended = true;
+ complete(&dd->suspend_resume);
+ dd->expect_resume_ack = true;
+ dd->gesture_reset = false;
+ while (!dd->resume_in_progress) {
+ /* the line below is a MUST */
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (kthread_should_stop())
+ break;
+ if (dd->gesture_en && dd->irq_registered &&
+ pdata->irq(pdata) == 0)
+ gesture_wake_detect(dd);
+ schedule();
+ }
+ if (dd->irq_registered) {
+ if (dd->gesture_en)
+ finish_gesture(dd);
+ else
+ if (!dd->idle)
+ start_scan_canned(dd);
+ }
+ dd->suspended = false;
+ dd->resume_in_progress = false;
+ dd->suspend_in_progress = false;
+ complete(&dd->suspend_resume);
+
+ fusion_dead = false;
+ dd->send_fail_count = 0;
+ do {
+ if (dd->fusion_process != (pid_t)0 &&
+ get_pid_task(find_get_pid(
+ dd->fusion_process),
+ PIDTYPE_PID) == NULL) {
+ fusion_dead = true;
+ break;
+ }
+ ret = nl_add_attr(dd->outgoing_skb->data,
+ FU_RESUME, NULL, 0);
+ if (ret < 0) {
+ ERROR("can't add data to resume " \
+ "buffer");
+ nl_msg_init(dd->outgoing_skb->data,
+ dd->nl_family.id,
+ dd->nl_seq - 1, MC_FUSION);
+ msleep(100);
+ continue;
+ }
+ (void)skb_put(dd->outgoing_skb,
+ NL_SIZE(dd->outgoing_skb->data));
+ ret = genlmsg_multicast(&dd->nl_family,
+ dd->outgoing_skb, 0, MC_FUSION,
+ GFP_KERNEL);
+ if (ret < 0) {
+ ERROR("can't send resume message %d",
+ ret);
+ msleep(100);
+ if (++dd->send_fail_count >= 10) {
+ fusion_dead = true;
+ ret = 0;
+ }
+ }
+ ret2 = nl_msg_new(dd, MC_FUSION);
+ if (ret2 < 0)
+ ERROR("could not allocate outgoing " \
+ "skb (%d)", ret2);
+ } while (ret != 0 && !kthread_should_stop());
+
+ if (!ret && dd->send_fail_count>= 10 &&
+ dd->fusion_process != (pid_t)0)
+ (void)kill_pid(find_get_pid(dd->fusion_process),
+ SIGKILL, 1);
+
+ dd->send_fail_count = 0;
+ if (fusion_dead)
+ continue;
+ }
+ if (kthread_should_stop())
+ break;
+
+ /* priority 4: update /sys/device information */
+ if (dd->sysfs_update_type != DR_SYSFS_UPDATE_NONE)
+ if (!dd->expect_resume_ack) {
+ if (send_sysfs_info(dd) < 0)
+ ERROR(
+ "Can not send sysfs update to touch fusion"
+ );
+ dd->sysfs_update_type = DR_SYSFS_UPDATE_NONE;
+ }
+
+ /* priority 5: service interrupt */
+ if (dd->irq_registered && !dd->expect_resume_ack &&
+ ((pdata->irq(pdata) == 0)
+ || dd->gesture_reset
+ ))
+ dd->service_irq(dd);
+ if (dd->irq_registered && !dd->expect_resume_ack &&
+ pdata->irq(pdata) == 0)
+ continue;
+
+ DRV_PT_DBG("End");
+ /* nothing more to do; sleep */
+ schedule();
+ }
+
+ return 0;
+}
+
+/****************************************************************************\
+* SYSFS interface *
+\****************************************************************************/
+
+static ssize_t chip_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", dd->chip_id);
+}
+
+static ssize_t fw_ver_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", dd->fw_ver);
+}
+
+static ssize_t driver_ver_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", dd->drv_ver);
+}
+
+static ssize_t tf_ver_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", dd->tf_ver);
+}
+
+static ssize_t panel_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "0x%04X\n", panel_id);
+}
+
+static ssize_t glove_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "%u\n", dd->glove_enabled);
+}
+
+static ssize_t glove_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ u32 temp;
+ unsigned long time_left;
+
+ mutex_lock(&dd->sysfs_update_mutex);
+
+ if (sscanf(buf, "%u", &temp) != 1) {
+ ERROR("Invalid (%s)", buf);
+ return -EINVAL;
+ }
+ dd->glove_enabled = !!temp;
+ set_bit(DR_SYSFS_UPDATE_BIT_GLOVE, &(dd->sysfs_update_type));
+ wake_up_process(dd->thread);
+ time_left = wait_for_completion_timeout(&dd->sysfs_ack_glove, 3*HZ);
+
+ mutex_unlock(&dd->sysfs_update_mutex);
+
+ if (time_left > 0)
+ return strnlen(buf, PAGE_SIZE);
+ else
+ return -EAGAIN;
+}
+
+static ssize_t gesture_wakeup_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "%u\n", dd->gesture_en);
+}
+
+static ssize_t gesture_wakeup_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ u32 temp;
+
+ if (sscanf(buf, "%u", &temp) != 1) {
+ ERROR("Invalid (%s)", buf);
+ return -EINVAL;
+ }
+ dd->gesture_en = temp;
+
+ return strnlen(buf, PAGE_SIZE);
+}
+
+static ssize_t charger_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "%u\n", dd->charger_mode_en);
+}
+
+static ssize_t charger_mode_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ u32 temp;
+ unsigned long time_left;
+
+ mutex_lock(&dd->sysfs_update_mutex);
+
+ if (sscanf(buf, "%u", &temp) != 1) {
+ ERROR("Invalid (%s)", buf);
+ return -EINVAL;
+ }
+ if (temp > DR_WIRELESS_CHARGER) {
+ ERROR("Charger Mode Value Out of Range");
+ return -EINVAL;
+ }
+ dd->charger_mode_en = temp;
+ set_bit(DR_SYSFS_UPDATE_BIT_CHARGER, &(dd->sysfs_update_type));
+ wake_up_process(dd->thread);
+ time_left = wait_for_completion_timeout(&dd->sysfs_ack_charger, 3*HZ);
+
+ mutex_unlock(&dd->sysfs_update_mutex);
+
+ if (time_left > 0)
+ return strnlen(buf, PAGE_SIZE);
+ else
+ return -EAGAIN;
+}
+
+static ssize_t info_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "chip id: 0x%04X driver ver: 0x%04X "
+ "fw ver: 0x%04X panel id: 0x%04X "
+ "tf ver: 0x%04X\n",
+ dd->chip_id, dd->drv_ver, dd->fw_ver,
+ panel_id, dd->tf_ver);
+}
+
+static ssize_t screen_status_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ u32 temp;
+
+ if (sscanf(buf, "%u", &temp) != 1) {
+ ERROR("Invalid (%s)", buf);
+ return -EINVAL;
+ }
+ if (temp)
+ resume(dev);
+ else
+ suspend(dev);
+
+ return strnlen(buf, PAGE_SIZE);
+}
+
+static ssize_t tf_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "0x%08X", dd->tf_status);
+}
+
+static ssize_t default_loaded_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "%d",
+ (dd->tf_status & TF_STATUS_DEFAULT_LOADED));
+}
+
+static ssize_t lcd_fps_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ return snprintf(buf, PAGE_SIZE, "%u\n", dd->lcd_fps);
+}
+
+static ssize_t lcd_fps_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct dev_data *dd = spi_get_drvdata(spi);
+ u32 temp;
+ unsigned long time_left;
+
+ mutex_lock(&dd->sysfs_update_mutex);
+
+ if (sscanf(buf, "%u", &temp) != 1) {
+ ERROR("Invalid (%s)", buf);
+ return -EINVAL;
+ }
+
+ dd->lcd_fps = temp;
+ set_bit(DR_SYSFS_UPDATE_BIT_LCD_FPS, &(dd->sysfs_update_type));
+ wake_up_process(dd->thread);
+ time_left = wait_for_completion_timeout(&dd->sysfs_ack_lcd_fps, 3*HZ);
+
+ mutex_unlock(&dd->sysfs_update_mutex);
+
+ if (time_left > 0)
+ return strnlen(buf, PAGE_SIZE);
+ else
+ return -EAGAIN;
+}
+
+static struct device_attribute dev_attrs[] = {
+ __ATTR(fw_ver, S_IRUGO, fw_ver_show, NULL),
+ __ATTR(chip_id, S_IRUGO, chip_id_show, NULL),
+ __ATTR(tf_ver, S_IRUGO, tf_ver_show, NULL),
+ __ATTR(driver_ver, S_IRUGO, driver_ver_show, NULL),
+ __ATTR(panel_id, S_IRUGO, panel_id_show, NULL),
+ __ATTR(glove_en, S_IRUGO | S_IWUSR, glove_show, glove_store),
+ __ATTR(gesture_wakeup, S_IRUGO | S_IWUSR, gesture_wakeup_show, gesture_wakeup_store),
+ __ATTR(charger_mode, S_IRUGO | S_IWUSR, charger_mode_show, charger_mode_store),
+ __ATTR(info, S_IRUGO, info_show, NULL),
+ __ATTR(screen_status, S_IWUSR, NULL, screen_status_store),
+ __ATTR(tf_status, S_IRUGO, tf_status_show, NULL),
+ __ATTR(default_loaded, S_IRUGO, default_loaded_show, NULL),
+ __ATTR(lcd_fps, S_IRUGO | S_IWUSR, lcd_fps_show, lcd_fps_store),
+};
+
+static int create_sysfs_entries(struct dev_data *dd)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < ARRAY_SIZE(dev_attrs); i++) {
+ ret = device_create_file(&dd->spi->dev, &dev_attrs[i]);
+ if (ret) {
+ for (; i >= 0; --i) {
+ device_remove_file(&dd->spi->dev,
+ &dev_attrs[i]);
+ dd->sysfs_created--;
+ }
+ break;
+ }
+ dd->sysfs_created++;
+ }
+ return ret;
+}
+
+static void remove_sysfs_entries(struct dev_data *dd)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dev_attrs); i++)
+ if (dd->sysfs_created && dd->sysfs_created--)
+ device_remove_file(&dd->spi->dev, &dev_attrs[i]);
+}
+
+static int send_sysfs_info(struct dev_data *dd)
+{
+ struct fu_sysfs_info *sysfs_info;
+ int ret, ret2;
+
+ sysfs_info = nl_alloc_attr(dd->outgoing_skb->data,
+ FU_SYSFS_INFO,
+ sizeof(*sysfs_info));
+ if (sysfs_info == NULL) {
+ ERROR("Can't allocate sysfs_info");
+ return -EAGAIN;
+ }
+ sysfs_info->type = dd->sysfs_update_type;
+
+ sysfs_info->glove_value = dd->glove_enabled;
+ sysfs_info->charger_value = dd->charger_mode_en;
+ sysfs_info->lcd_fps_value = dd->lcd_fps;
+
+ (void)skb_put(dd->outgoing_skb,
+ NL_SIZE(dd->outgoing_skb->data));
+ ret = genlmsg_multicast(&dd->nl_family,
+ dd->outgoing_skb, 0,
+ MC_FUSION, GFP_KERNEL);
+ if (ret < 0)
+ ERROR("could not reply to fusion (%d)", ret);
+
+ /* allocate new outgoing skb */
+ ret2 = nl_msg_new(dd, MC_FUSION);
+ if (ret2 < 0)
+ ERROR("could not allocate outgoing skb (%d)", ret2);
+
+ return 0;
+}
+
+/****************************************************************************\
+* Driver initialization *
+\****************************************************************************/
+
+static int probe(struct spi_device *spi)
+{
+ struct maxim_sti_pdata *pdata = spi->dev.platform_data;
+ struct dev_data *dd;
+ unsigned long flags;
+ int ret, i;
+ void *ptr;
+
+#ifdef CONFIG_OF
+ if (pdata == NULL && spi->dev.of_node) {
+ pdata = devm_kzalloc(&spi->dev,
+ sizeof(struct maxim_sti_pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&spi->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ ret = maxim_parse_dt(&spi->dev, pdata);
+ if (ret)
+ goto of_parse_failure;
+ spi->dev.platform_data = pdata;
+ }
+#endif
+
+ pdata->init = maxim_sti_gpio_init;
+ pdata->reset = maxim_sti_gpio_reset;
+ pdata->irq = maxim_sti_gpio_irq;
+
+ pdata->nl_mc_groups = DEF_NL_MC_GROUPS;
+ pdata->chip_access_method = DEF_CHIP_ACC_METHOD;
+ pdata->tx_buf_size = BUF_SIZE;
+ pdata->rx_buf_size = BUF_SIZE;
+ pdata->nl_family = TOUCH_FUSION;
+
+ dev_dbg(&spi->dev, "maxim_sti,reset-gpio: %d", pdata->gpio_reset);
+ dev_dbg(&spi->dev, "maxim_sti,irq-gpio: %d", pdata->gpio_irq);
+ dev_dbg(&spi->dev, "maxim_sti,nl_mc_groups: %d", pdata->nl_mc_groups);
+ dev_dbg(&spi->dev, "maxim_sti,chip_access_method: %d", pdata->chip_access_method);
+ dev_dbg(&spi->dev, "maxim_sti,default_reset_state: %d", pdata->default_reset_state);
+ dev_dbg(&spi->dev, "maxim_sti,tx_buf_size: %d", pdata->tx_buf_size);
+ dev_dbg(&spi->dev, "maxim_sti,rx_buf_size: %d", pdata->rx_buf_size);
+ dev_dbg(&spi->dev, "maxim_sti,touch_fusion: %s", pdata->touch_fusion);
+ dev_dbg(&spi->dev, "maxim_sti,config_file: %s", pdata->config_file);
+ dev_dbg(&spi->dev, "maxim_sti,nl_family: %s", pdata->nl_family);
+ dev_dbg(&spi->dev, "maxim_sti,fw_name: %s", pdata->fw_name);
+
+ /* validate platform data */
+ if (pdata == NULL || pdata->init == NULL || pdata->reset == NULL ||
+ pdata->irq == NULL || pdata->touch_fusion == NULL ||
+ pdata->config_file == NULL || pdata->nl_family == NULL ||
+ GENL_CHK(pdata->nl_family) ||
+ pdata->nl_mc_groups < MC_GROUPS ||
+ pdata->chip_access_method == 0 ||
+ pdata->chip_access_method > ARRAY_SIZE(chip_access_methods) ||
+ pdata->default_reset_state > 1 ||
+ pdata->tx_buf_size == 0 ||
+ pdata->rx_buf_size == 0) {
+ dev_err(&spi->dev, "invalid platform data!");
+ ret = -EINVAL;
+ goto of_parse_failure;
+ }
+
+ /* device context: allocate structure */
+ dd = kzalloc(sizeof(*dd) +
+ sizeof(*dd->nl_ops) * pdata->nl_mc_groups +
+ sizeof(*dd->nl_mc_groups) * pdata->nl_mc_groups,
+ GFP_KERNEL);
+ if (dd == NULL) {
+ dev_err(&spi->dev, "cannot allocate memory!");
+ ret = -ENOMEM;
+ goto of_parse_failure;
+ }
+
+ /* device context: set up dynamic allocation pointers */
+ ptr = (void *)dd + sizeof(*dd);
+ dd->nl_ops = ptr;
+ ptr += sizeof(*dd->nl_ops) * pdata->nl_mc_groups;
+ dd->nl_mc_groups = ptr;
+
+ /* device context: initialize structure members */
+ spi_set_drvdata(spi, dd);
+ spi->bits_per_word = 16;
+ spi_setup(spi);
+ dd->spi = spi;
+ dd->nl_seq = 1;
+ init_completion(&dd->suspend_resume);
+
+ /* allocate DMA memory */
+ dd->tx_buf = kzalloc(pdata->tx_buf_size + pdata->rx_buf_size,
+ GFP_KERNEL | GFP_DMA);
+ if (dd->tx_buf == NULL) {
+ dev_err(&spi->dev, "cannot allocate DMA accesible memory");
+ ret = -ENOMEM;
+ goto buf_alloc_failure;
+ }
+ dd->rx_buf = dd->tx_buf + pdata->tx_buf_size;
+ memset(dd->tx_buf, 0xFF, pdata->tx_buf_size);
+ (void)set_chip_access_method(dd, pdata->chip_access_method);
+
+ /* initialize regulators */
+ regulator_init(dd);
+
+ /* initialize platform */
+
+ /* Get pinctrl if target uses pinctrl */
+ dd->ts_pinctrl = devm_pinctrl_get(&(spi->dev));
+ if (IS_ERR_OR_NULL(dd->ts_pinctrl)) {
+ ret = PTR_ERR(dd->ts_pinctrl);
+ pr_debug("Target does not use pinctrl %d\n", ret);
+ }
+
+ dd->pinctrl_state_active
+ = pinctrl_lookup_state(dd->ts_pinctrl, "pmx_ts_active");
+ if (IS_ERR_OR_NULL(dd->pinctrl_state_active)) {
+ ret = PTR_ERR(dd->pinctrl_state_active);
+ pr_debug("Can not lookup active pinstate %d\n", ret);
+ }
+
+ dd->pinctrl_state_suspended
+ = pinctrl_lookup_state(dd->ts_pinctrl, "pmx_ts_suspend");
+ if (IS_ERR_OR_NULL(dd->pinctrl_state_suspended)) {
+ ret = PTR_ERR(dd->pinctrl_state_suspended);
+ pr_debug("Can not lookup active pinstate %d\n", ret);
+ }
+ ret = pinctrl_select_state(dd->ts_pinctrl,
+ dd->pinctrl_state_active);
+ if (ret < 0)
+ pr_debug("pinctrl set active fail\n");
+
+
+ ret = pdata->init(pdata, true);
+ if (ret < 0)
+ goto pinit_failure;
+
+ /* Netlink: initialize incoming skb queue */
+ skb_queue_head_init(&dd->incoming_skb_queue);
+
+ /* Netlink: register GENL family */
+ dd->nl_family.id = GENL_ID_GENERATE;
+ dd->nl_family.version = NL_FAMILY_VERSION;
+ GENL_COPY(dd->nl_family.name, pdata->nl_family);
+
+ /* Netlink: register family ops */
+ for (i = 0; i < MC_GROUPS; i++) {
+ dd->nl_ops[i].cmd = i;
+ dd->nl_ops[i].doit = nl_callback_noop;
+ }
+ dd->nl_ops[MC_DRIVER].doit = nl_callback_driver;
+ dd->nl_ops[MC_FUSION].doit = nl_callback_fusion;
+ dd->nl_ops[MC_EVENT_BROADCAST].doit = nl_callback_noop;
+
+ /* Netlink: register family multicast groups */
+ GENL_COPY(dd->nl_mc_groups[MC_DRIVER].name, MC_DRIVER_NAME);
+ GENL_COPY(dd->nl_mc_groups[MC_FUSION].name, MC_FUSION_NAME);
+ GENL_COPY(dd->nl_mc_groups[MC_EVENT_BROADCAST].name,
+ MC_EVENT_BROADCAST_NAME);
+ ret = _genl_register_family_with_ops_grps(&dd->nl_family,
+ dd->nl_ops,
+ MC_GROUPS,
+ dd->nl_mc_groups,
+ MC_GROUPS);
+ if (ret < 0) {
+ dev_err(&spi->dev, "error registering nl_mc_group");
+ goto nl_family_failure;
+ }
+ dd->nl_mc_group_count = MC_GROUPS;
+
+ /* Netlink: pre-allocate outgoing skb */
+ ret = nl_msg_new(dd, MC_FUSION);
+ if (ret < 0) {
+ dev_err(&spi->dev, "error alloc msg");
+ goto nl_failure;
+ }
+
+ /* start processing thread */
+ dd->thread_sched.sched_priority = MAX_USER_RT_PRIO / 2;
+ dd->thread = kthread_run(processing_thread, dd, pdata->nl_family);
+ if (IS_ERR(dd->thread)) {
+ dev_err(&spi->dev, "error creating kthread!");
+ ret = PTR_ERR(dd->thread);
+ goto kthread_failure;
+ }
+
+ /* Netlink: ready to start processing incoming messages */
+ dd->nl_enabled = true;
+
+ /* No sysfs update initially */
+ dd->sysfs_update_type = DR_SYSFS_UPDATE_NONE;
+ init_completion(&dd->sysfs_ack_glove);
+ init_completion(&dd->sysfs_ack_charger);
+ init_completion(&dd->sysfs_ack_lcd_fps);
+ mutex_init(&dd->sysfs_update_mutex);
+
+ /* add us to the devices list */
+ spin_lock_irqsave(&dev_lock, flags);
+ list_add_tail(&dd->dev_list, &dev_list);
+ spin_unlock_irqrestore(&dev_lock, flags);
+
+ ret = create_sysfs_entries(dd);
+ if (ret) {
+ dev_err(&spi->dev, "failed to create sysfs file");
+ goto sysfs_failure;
+ }
+ snprintf(dd->config_file, CFG_FILE_NAME_MAX, pdata->config_file, panel_id);
+ dev_dbg(&spi->dev, "configuration file: %s", dd->config_file);
+
+ /* start up Touch Fusion */
+ dd->start_fusion = true;
+ wake_up_process(dd->thread);
+ dev_info(&spi->dev, "%s: driver loaded; version %s; release date %s",
+ dd->nl_family.name, DRIVER_VERSION, DRIVER_RELEASE);
+
+ return 0;
+
+sysfs_failure:
+ dd->nl_enabled = false;
+ spin_lock_irqsave(&dev_lock, flags);
+ list_del(&dd->dev_list);
+ spin_unlock_irqrestore(&dev_lock, flags);
+ (void)kthread_stop(dd->thread);
+kthread_failure:
+ if (dd->outgoing_skb)
+ kfree_skb(dd->outgoing_skb);
+nl_failure:
+ genl_unregister_family(&dd->nl_family);
+nl_family_failure:
+ pdata->init(pdata, false);
+pinit_failure:
+ regulator_uninit(dd);
+ kfree(dd->tx_buf);
+buf_alloc_failure:
+ spi_set_drvdata(spi, NULL);
+ kfree(dd);
+of_parse_failure:
+ spi->dev.platform_data = NULL;
+ devm_kfree(&spi->dev, pdata);
+ return ret;
+}
+
+static int remove(struct spi_device *spi)
+{
+ struct maxim_sti_pdata *pdata = spi->dev.platform_data;
+ struct dev_data *dd = spi_get_drvdata(spi);
+ unsigned long flags;
+ u8 i;
+
+ dev_dbg(&spi->dev, "remove");
+
+ /* BEWARE: tear-down sequence below is carefully staged: */
+ /* 1) first the feeder of Netlink messages to the processing thread */
+ /* is turned off */
+ /* 2) then the thread itself is shut down */
+ /* 3) then Netlink family is torn down since no one would be using */
+ /* it at this point */
+ /* 4) above step (3) insures that all Netlink senders are */
+ /* definitely gone and it is safe to free up outgoing skb buffer */
+ /* and incoming skb queue */
+ dev_dbg(&spi->dev, "stopping thread..");
+ dd->nl_enabled = false;
+ (void)kthread_stop(dd->thread);
+ dev_dbg(&spi->dev, "kthread stopped.");
+ genl_unregister_family(&dd->nl_family);
+ if (dd->outgoing_skb)
+ kfree_skb(dd->outgoing_skb);
+ skb_queue_purge(&dd->incoming_skb_queue);
+
+ if (dd->fusion_process != (pid_t)0)
+ (void)kill_pid(find_get_pid(dd->fusion_process), SIGKILL, 1);
+
+ dev_dbg(&spi->dev, "removing sysfs entries..");
+ if (dd->parent != NULL)
+ sysfs_remove_link(dd->input_dev[0]->dev.kobj.parent,
+ MAXIM_STI_NAME);
+ remove_sysfs_entries(dd);
+
+ dev_dbg(&spi->dev, "unregister input devices..");
+ for (i = 0; i < INPUT_DEVICES; i++)
+ if (dd->input_dev[i])
+ input_unregister_device(dd->input_dev[i]);
+#if defined(CONFIG_FB)
+ fb_unregister_client(&dd->fb_notifier);
+#endif
+
+ if (dd->irq_registered) {
+ dev_dbg(&spi->dev, "disabling interrupt");
+ disable_irq(dd->spi->irq);
+ dev_dbg(&spi->dev, "stopping scan");
+ stop_scan_canned(dd);
+ free_irq(dd->spi->irq, dd);
+ }
+
+ spin_lock_irqsave(&dev_lock, flags);
+ list_del(&dd->dev_list);
+ spin_unlock_irqrestore(&dev_lock, flags);
+
+ pdata->reset(pdata, 0);
+ usleep_range(100, 120);
+ regulator_control(dd, false);
+ pdata->init(pdata, false);
+ regulator_uninit(dd);
+
+ dev_dbg(&spi->dev, "detaching from spi..");
+ spi_set_drvdata(spi, NULL);
+ kzfree(dd);
+ spi->dev.platform_data = NULL;
+ devm_kfree(&spi->dev, pdata);
+
+ dev_info(&spi->dev, "driver unloaded");
+ return 0;
+}
+
+static void shutdown(struct spi_device *spi)
+{
+ struct maxim_sti_pdata *pdata = spi->dev.platform_data;
+ struct dev_data *dd = spi_get_drvdata(spi);
+
+ if (dd->parent != NULL)
+ sysfs_remove_link(dd->input_dev[0]->dev.kobj.parent,
+ MAXIM_STI_NAME);
+ remove_sysfs_entries(dd);
+
+ pdata->reset(pdata, 0);
+ usleep_range(100, 120);
+ regulator_control(dd, false);
+}
+
+/****************************************************************************\
+* Module initialization *
+\****************************************************************************/
+
+static const struct spi_device_id id[] = {
+ { MAXIM_STI_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(spi, id);
+
+#ifdef CONFIG_OF
+static struct of_device_id maxim_match_table[] = {
+ { .compatible = "maxim,maxim_sti",},
+ { },
+};
+#endif
+
+static struct spi_driver driver = {
+ .probe = probe,
+ .remove = remove,
+ .shutdown = shutdown,
+ .id_table = id,
+ .driver = {
+ .name = MAXIM_STI_NAME,
+#ifdef CONFIG_OF
+ .of_match_table = maxim_match_table,
+#endif
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM_SLEEP
+ .pm = &pm_ops,
+#endif
+ },
+};
+
+static int maxim_sti_init(void)
+{
+ INIT_LIST_HEAD(&dev_list);
+ spin_lock_init(&dev_lock);
+ return spi_register_driver(&driver);
+}
+
+static void maxim_sti_exit(void)
+{
+ spi_unregister_driver(&driver);
+}
+
+module_param(panel_id, ushort, S_IRUGO);
+MODULE_PARM_DESC(panel_id, "Touch Panel ID Configuration");
+
+module_init(maxim_sti_init);
+module_exit(maxim_sti_exit);
+
+MODULE_AUTHOR("Maxim Integrated Products, Inc.");
+MODULE_DESCRIPTION("Maxim SmartTouch Imager Touchscreen Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/st/Kconfig b/drivers/input/touchscreen/st/Kconfig
new file mode 100644
index 000000000000..817faea01742
--- /dev/null
+++ b/drivers/input/touchscreen/st/Kconfig
@@ -0,0 +1,9 @@
+#
+# STMicroelectronics touchscreen driver configuration
+#
+
+config TOUCHSCREEN_ST_I2C
+ tristate "STMicroelectronics i2c touchscreen"
+ depends on TOUCHSCREEN_ST
+ help
+ This enables support for ST touch panel over I2C based touchscreens.
diff --git a/drivers/input/touchscreen/st/Makefile b/drivers/input/touchscreen/st/Makefile
new file mode 100644
index 000000000000..0aa7b4a364da
--- /dev/null
+++ b/drivers/input/touchscreen/st/Makefile
@@ -0,0 +1,5 @@
+#
+## Makefile for the STMicroelectronics touchscreen driver.
+#
+
+obj-$(CONFIG_TOUCHSCREEN_ST_I2C) += fts.o fts_gui.o fts_driver_test.o fts_lib/
diff --git a/drivers/input/touchscreen/st/fts.c b/drivers/input/touchscreen/st/fts.c
new file mode 100644
index 000000000000..06f7f569f417
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts.c
@@ -0,0 +1,2385 @@
+/*
+ * fts.c
+ *
+ * FTS Capacitive touch screen controller (FingerTipS)
+ *
+ * Copyright (C) 2016, STMicroelectronics Limited.
+ * Authors: AMG(Analog Mems Group)
+ *
+ * marco.cali@st.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/completion.h>
+
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/notifier.h>
+#include <linux/fb.h>
+
+#ifdef KERNEL_ABOVE_2_6_38
+#include <linux/input/mt.h>
+#endif
+
+#include "fts.h"
+#include "fts_lib/ftsCompensation.h"
+#include "fts_lib/ftsIO.h"
+#include "fts_lib/ftsError.h"
+#include "fts_lib/ftsFlash.h"
+#include "fts_lib/ftsFrame.h"
+#include "fts_lib/ftsGesture.h"
+#include "fts_lib/ftsTest.h"
+#include "fts_lib/ftsTime.h"
+#include "fts_lib/ftsTool.h"
+
+#define LINK_KOBJ_NAME "tp"
+
+/*
+ * Uncomment to use polling mode instead of interrupt mode.
+ *
+ */
+/* #define FTS_USE_POLLING_MODE */
+
+/*
+ * Event installer helpers
+ */
+#define event_id(_e) EVENTID_##_e
+#define handler_name(_h) fts_##_h##_event_handler
+
+#define install_handler(_i, _evt, _hnd) \
+do { \
+ _i->event_dispatch_table[event_id(_evt)] = handler_name(_hnd); \
+} while (0)
+
+/*
+ * Asyncronouns command helper
+ */
+#define WAIT_WITH_TIMEOUT(_info, _timeout, _command) \
+do { \
+ if (wait_for_completion_timeout(&_info->cmd_done, _timeout) == 0) { \
+ dev_warn(_info->dev, "Waiting for %s command: timeout\n", \
+ #_command); \
+ } \
+} while (0)
+
+#ifdef KERNEL_ABOVE_2_6_38
+#define TYPE_B_PROTOCOL
+#endif
+
+#if defined(SCRIPTLESS) || defined(DRIVER_TEST)
+static struct class *fts_cmd_class;
+#endif
+
+extern chipInfo ftsInfo;
+
+unsigned char tune_version_same;
+
+char tag[8] = "[ FTS ]\0";
+
+static u32 *typeOfComand;
+static int numberParameters;
+static int feature_feasibility = ERROR_OP_NOT_ALLOW;
+#ifdef PHONE_GESTURE
+static u8 mask[GESTURE_MASK_SIZE+2];
+#endif
+static void fts_interrupt_enable(struct fts_ts_info *info);
+static int fts_init_hw(struct fts_ts_info *info);
+static int fts_mode_handler(struct fts_ts_info *info, int force);
+static int fts_command(struct fts_ts_info *info, unsigned char cmd);
+static void fts_unblank(struct fts_ts_info *info);
+static int fts_chip_initialization(struct fts_ts_info *info);
+
+void touch_callback(unsigned int status)
+{
+ /* Empty */
+}
+
+unsigned int le_to_uint(const unsigned char *ptr)
+{
+ return (unsigned int) ptr[0] + (unsigned int) ptr[1] * 0x100;
+}
+
+unsigned int be_to_uint(const unsigned char *ptr)
+{
+ return (unsigned int) ptr[1] + (unsigned int) ptr[0] * 0x100;
+}
+
+/* force update firmware*/
+static ssize_t fts_fw_control_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count){
+ int ret, mode;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+ /* reading out firmware upgrade mode */
+ sscanf(buf, "%d", &mode);
+#ifdef FTM3_CHIP
+ ret = flashProcedure(PATH_FILE_FW, mode, !mode);
+#else
+ ret = flashProcedure(PATH_FILE_FW, mode, 1);
+#endif
+ info->fwupdate_stat = ret;
+
+ if (ret < OK)
+ logError(1, "%s %s :Unable to upgrade firmware\n", tag, __func__);
+ return count;
+}
+
+static ssize_t fts_sysfs_config_id_show(struct device *dev, struct device_attribute *attr,
+ char *buf) {
+ int error;
+
+ error = snprintf(buf, TSP_BUF_SIZE, "%x.%x\n", ftsInfo.u16_fwVer, ftsInfo.u16_cfgId);
+ return error;
+}
+
+static ssize_t fts_sysfs_fwupdate_show(struct device *dev, struct device_attribute *attr,
+ char *buf) {
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+ /* fwupdate_stat: ERROR code Returned by flashProcedure. */
+ return snprintf(buf, TSP_BUF_SIZE, "%08X\n", info->fwupdate_stat);
+}
+
+static ssize_t fts_fw_test_show(struct device *dev, struct device_attribute *attr,
+ char *buf) {
+
+ Firmware fw;
+ int ret;
+
+ fw.data = NULL;
+ ret = readFwFile(PATH_FILE_FW, &fw, 0);
+
+ if (ret < OK) {
+ logError(1, "%s: Error during reading FW file! ERROR %08X\n", tag, ret);
+ } else
+ logError(1, "%s: fw_version = %04X, config_version = %04X, size = %d bytes\n",
+ tag, fw.fw_ver, fw.config_id, fw.data_size);
+
+ kfree(fw.data);
+ return 0;
+}
+
+/* TODO: edit this function according to the features policy to allow during the screen on/off */
+int check_feature_feasibility(struct fts_ts_info *info, unsigned int feature)
+{
+ int res = ERROR_OP_NOT_ALLOW;
+
+ if (info->resume_bit == 0) {
+ switch (feature) {
+#ifdef PHONE_GESTURE
+ case FEAT_GESTURE:
+ res = OK;
+ break;
+#endif
+ default:
+ logError(1, "%s %s: Feature not allowed in this operating mode! ERROR %08X\n", tag, __func__, res);
+ break;
+
+ }
+ } else{
+ switch (feature) {
+#ifdef PHONE_GESTURE
+ case FEAT_GESTURE:
+#endif
+ case FEAT_GLOVE:
+ /* glove mode can only activate during sense on */
+ res = OK;
+ break;
+
+ default:
+ logError(1, "%s %s: Feature not allowed in this operating mode! ERROR %08X\n", tag, __func__, res);
+ break;
+
+ }
+ }
+
+ return res;
+
+}
+
+static ssize_t fts_feature_enable_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count) {
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+ char *p = (char *)buf;
+ unsigned int temp;
+ int res = OK;
+
+ if ((count + 1) / 3 != 2) {
+ logError(1, "%s fts_feature_enable: Number of parameter wrong! %d > %d\n",
+ tag, (count + 1) / 3, 2);
+ } else{
+ sscanf(p, "%02X ", &temp);
+ p += 3;
+ res = check_feature_feasibility(info, temp);
+ if (res >= OK) {
+ switch (temp) {
+#ifdef PHONE_GESTURE
+ case FEAT_GESTURE:
+ sscanf(p, "%02X ", &info->gesture_enabled);
+ logError(1, "%s fts_feature_enable: Gesture Enabled = %d\n", tag,
+ info->gesture_enabled);
+ break;
+#endif
+ case FEAT_GLOVE:
+ sscanf(p, "%02X ", &info->glove_enabled);
+ logError(1, "%s fts_feature_enable: Glove Enabled = %d\n",
+ tag, info->glove_enabled);
+
+ break;
+
+ default:
+ logError(1, "%s fts_feature_enable: Feature %02X not valid! ERROR %08X\n", tag, temp, ERROR_OP_NOT_ALLOW);
+
+ }
+ feature_feasibility = res;
+ }
+
+ }
+ return count;
+}
+
+static ssize_t fts_feature_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ char buff[CMD_STR_LEN] = {0};
+ int size = 6 * 2;
+ u8 *all_strbuff = NULL;
+ int count = 0, res;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+ if (feature_feasibility >= OK)
+ res = fts_mode_handler(info, 1);
+ else{
+ res = feature_feasibility;
+ logError(1, "%s %s: Call before echo xx xx > feature_enable with a correct feature! ERROR %08X\n", tag, __func__, res);
+ }
+
+ all_strbuff = (u8 *) kmalloc(size, GFP_KERNEL);
+ if (all_strbuff != NULL) {
+ memset(all_strbuff, 0, size);
+
+ snprintf(buff, sizeof(buff), "%02X", 0xAA);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%08X", res);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", 0xBB);
+ strlcat(all_strbuff, buff, size);
+
+ count = snprintf(buf, TSP_BUF_SIZE, "%s\n", all_strbuff);
+ kfree(all_strbuff);
+ } else{
+ logError(1, "%s fts_feature_enable_show: Unable to allocate all_strbuff! ERROR %08X\n", tag, ERROR_ALLOC);
+ }
+
+ feature_feasibility = ERROR_OP_NOT_ALLOW;
+ return count;
+}
+
+#ifdef PHONE_GESTURE
+static ssize_t fts_gesture_mask_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char buff[CMD_STR_LEN] = {0};
+ int size = 6 * 2;
+ u8 *all_strbuff = NULL;
+ int count = 0, res;
+
+ if (mask[0] == 0) {
+ res = ERROR_OP_NOT_ALLOW;
+ logError(1, "%s %s: Call before echo enable/disable xx xx .... > gesture_mask with a correct number of parameters! ERROR %08X\n", tag, __func__, res);
+
+ } else{
+ res = fts_disableInterrupt();
+ if (res >= OK) {
+ if (mask[1] == FEAT_ENABLE)
+ res = enableGesture(&mask[2], mask[0]);
+ else{
+ if (mask[1] == FEAT_DISABLE)
+ res = disableGesture(&mask[2], mask[0]);
+ else
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ if (res < OK) {
+ logError(1, "%s fts_gesture_mask_store: ERROR %08X\n", tag, res);
+ }
+ }
+ res |= fts_enableInterrupt();
+ }
+
+ all_strbuff = (u8 *) kmalloc(size, GFP_KERNEL);
+ if (all_strbuff != NULL) {
+ memset(all_strbuff, 0, size);
+
+ snprintf(buff, sizeof(buff), "%02X", 0xAA);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%08X", res);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", 0xBB);
+ strlcat(all_strbuff, buff, size);
+
+ count = snprintf(buf, TSP_BUF_SIZE, "%s\n", all_strbuff);
+ kfree(all_strbuff);
+ } else{
+ logError(1, "%s fts_gesture_mask_show: Unable to allocate all_strbuff! ERROR %08X\n", tag, ERROR_ALLOC);
+ }
+
+ mask[0] = 0;
+ return count;
+}
+
+static ssize_t fts_gesture_mask_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ char *p = (char *)buf;
+ int n;
+ unsigned int temp;
+
+ if ((count + 1) / 3 > GESTURE_MASK_SIZE+1) {
+ logError(1, "%s fts_gesture_mask_store: Number of bytes of parameter wrong! %d > (enable/disable + %d )\n", tag, (count + 1) / 3, GESTURE_MASK_SIZE);
+ mask[0] = 0;
+ } else {
+ mask[0] = ((count + 1) / 3) - 1;
+ for (n = 1; n <= (count + 1) / 3; n++) {
+ sscanf(p, "%02X ", &temp);
+ p += 3;
+ mask[n] = (u8)temp;
+ logError(1, "%s mask[%d] = %02X\n", tag, n, mask[n]);
+
+ }
+
+ }
+
+ return count;
+}
+#endif
+
+/************************ PRODUCTION TEST **********************************/
+static ssize_t stm_fts_cmd_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count) {
+ int n;
+ char *p = (char *) buf;
+
+ typeOfComand = (u32 *) kmalloc(8 * sizeof (u32), GFP_KERNEL);
+ if (typeOfComand == NULL) {
+ logError(1, "%s impossible to allocate typeOfComand!\n", tag);
+ return count;
+ }
+ memset(typeOfComand, 0, 8 * sizeof (u32));
+
+ logError(1, "%s\n", tag);
+ for (n = 0; n < (count + 1) / 3; n++) {
+ sscanf(p, "%02X ", &typeOfComand[n]);
+ p += 3;
+ logError(1, "%s typeOfComand[%d] = %02X\n", tag, n, typeOfComand[n]);
+
+ }
+
+ numberParameters = n;
+ logError(1, "%s Number of Parameters = %d\n", tag, numberParameters);
+ return count;
+}
+
+static ssize_t stm_fts_cmd_show(struct device *dev, struct device_attribute *attr,
+ char *buf) {
+ char buff[CMD_STR_LEN] = {0};
+ int res, j, doClean = 0, count;
+
+ int size = 6 * 2;
+ u8 *all_strbuff = NULL;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+ MutualSenseData compData;
+ SelfSenseData comData;
+ MutualSenseFrame frameMS;
+ SelfSenseFrame frameSS;
+
+ /* struct used for defining which test
+ *perform during the production test
+ */
+ TestToDo todoDefault;
+
+ todoDefault.MutualRaw = 1;
+ todoDefault.MutualRawGap = 1;
+ todoDefault.MutualCx1 = 0;
+ todoDefault.MutualCx2 = 1;
+ todoDefault.MutualCx2Adj = 1;
+ todoDefault.MutualCxTotal = 0;
+ todoDefault.MutualCxTotalAdj = 0;
+
+ todoDefault.MutualKeyRaw = 0;
+ todoDefault.MutualKeyCx1 = 0;
+ todoDefault.MutualKeyCx2 = 0;
+ todoDefault.MutualKeyCxTotal = 0;
+
+ todoDefault.SelfForceRaw = 1;
+ todoDefault.SelfForceRawGap = 0;
+ todoDefault.SelfForceIx1 = 0;
+ todoDefault.SelfForceIx2 = 0;
+ todoDefault.SelfForceIx2Adj = 0;
+ todoDefault.SelfForceIxTotal = 1;
+ todoDefault.SelfForceIxTotalAdj = 0;
+ todoDefault.SelfForceCx1 = 0;
+ todoDefault.SelfForceCx2 = 0;
+ todoDefault.SelfForceCx2Adj = 0;
+ todoDefault.SelfForceCxTotal = 0;
+ todoDefault.SelfForceCxTotalAdj = 0;
+
+ todoDefault.SelfSenseRaw = 1;
+ todoDefault.SelfSenseRawGap = 0;
+ todoDefault.SelfSenseIx1 = 0;
+ todoDefault.SelfSenseIx2 = 0;
+ todoDefault.SelfSenseIx2Adj = 0;
+ todoDefault.SelfSenseIxTotal = 1;
+ todoDefault.SelfSenseIxTotalAdj = 0;
+ todoDefault.SelfSenseCx1 = 0;
+ todoDefault.SelfSenseCx2 = 0;
+ todoDefault.SelfSenseCx2Adj = 0;
+ todoDefault.SelfSenseCxTotal = 0;
+ todoDefault.SelfSenseCxTotalAdj = 0;
+
+ if (numberParameters >= 1 && typeOfComand != NULL) {
+ res = fts_disableInterrupt();
+ if (res < 0) {
+ logError(0, "%s fts_disableInterrupt: ERROR %08X\n", tag, res);
+ res = (res | ERROR_DISABLE_INTER);
+ goto END;
+ }
+
+ res = fb_unregister_client(&info->notifier);
+ if (res < 0) {
+ logError(1, "%s ERROR: unregister notifier failed!\n", tag);
+ goto END;
+ }
+
+ switch (typeOfComand[0]) {
+ /*ITO TEST*/
+ case 0x01:
+ res = production_test_ito();
+ break;
+ /*PRODUCTION TEST*/
+ case 0x00:
+ if (ftsInfo.u32_mpPassFlag != INIT_MP) {
+ logError(0, "%s MP Flag not set!\n", tag, res);
+ res = production_test_main(LIMITS_FILE, 1, 1, &todoDefault, INIT_MP);
+ } else{
+ logError(0, "%s MP Flag set!\n", tag, res);
+ res = production_test_main(LIMITS_FILE, 1, 0, &todoDefault, INIT_MP);
+ }
+ break;
+ /*read mutual raw*/
+ case 0x13:
+ logError(0, "%s Get 1 MS Frame\n", tag);
+ /* res = getMSFrame(ADDR_RAW_TOUCH, &frame, 0); */
+ res = getMSFrame2(MS_TOUCH_ACTIVE, &frameMS);
+ if (res < 0) {
+ logError(0, "%s Error while taking the MS frame... ERROR %02X\n", tag, res);
+
+ } else {
+ logError(0, "%s The frame size is %d words\n", tag, res);
+ size = (res * sizeof (short) + 8)*2;
+ /* set res to OK because if getMSFrame is
+ * successful res = number of words read
+ */
+ res = OK;
+ }
+ break;
+ /*read self raw*/
+ case 0x15:
+ logError(0, "%s Get 1 SS Frame\n", tag);
+ res = getSSFrame2(SS_TOUCH, &frameSS);
+
+ if (res < OK) {
+ logError(0, "%s Error while taking the SS frame... ERROR %02X\n", tag, res);
+
+ } else {
+ logError(0, "%s The frame size is %d words\n", tag, res);
+ size = (res * sizeof (short) + 8)*2+1;
+ /* set res to OK because if getMSFrame is
+ * successful res = number of words read
+ */
+ res = OK;
+ }
+
+ break;
+
+ case 0x14: /*read mutual comp data */
+ logError(0, "%s Get MS Compensation Data\n", tag);
+ res = readMutualSenseCompensationData(MS_TOUCH_ACTIVE, &compData);
+
+ if (res < 0) {
+ logError(0, "%s Error reading MS compensation data ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s MS Compensation Data Reading Finished!\n", tag);
+ size = ((compData.node_data_size + 9) * sizeof (u8))*2;
+ }
+ break;
+
+ case 0x16: /* read self comp data */
+ logError(0, "%s Get SS Compensation Data...\n", tag);
+ res = readSelfSenseCompensationData(SS_TOUCH, &comData);
+ if (res < 0) {
+ logError(0, "%s Error reading SS compensation data ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s SS Compensation Data Reading Finished!\n", tag);
+ size = ((comData.header.force_node + comData.header.sense_node)*2 + 12) * sizeof (u8)*2;
+ }
+ break;
+
+ case 0x03: /* MS Raw DATA TEST */
+ res = fts_system_reset();
+ if (res >= OK)
+ res = production_test_ms_raw(LIMITS_FILE, 1, &todoDefault);
+ break;
+
+ case 0x04: /* MS CX DATA TEST */
+ res = fts_system_reset();
+ if (res >= OK)
+ res = production_test_ms_cx(LIMITS_FILE, 1, &todoDefault);
+ break;
+
+ case 0x05: /* SS RAW DATA TEST */
+ res = fts_system_reset();
+ if (res >= OK)
+ res = production_test_ss_raw(LIMITS_FILE, 1, &todoDefault);
+ break;
+
+ case 0x06: /* SS IX CX DATA TEST */
+ res = fts_system_reset();
+ if (res >= OK)
+ res = production_test_ss_ix_cx(LIMITS_FILE, 1, &todoDefault);
+ break;
+
+ case 0xF0:
+ case 0xF1: /* TOUCH ENABLE/DISABLE */
+ doClean = (int) (typeOfComand[0]&0x01);
+ res = cleanUp(doClean);
+
+ break;
+
+ default:
+ logError(1, "%s COMMAND NOT VALID!! Insert a proper value ...\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ break;
+ }
+
+ doClean = fts_enableInterrupt();
+ if (doClean < 0) {
+ logError(0, "%s fts_enableInterrupt: ERROR %08X\n", tag, (doClean|ERROR_ENABLE_INTER));
+ }
+ } else {
+ logError(1, "%s NO COMMAND SPECIFIED!!! do: 'echo [cmd_code] [args] > stm_fts_cmd' before looking for result!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ typeOfComand = NULL;
+
+ }
+
+ if (fb_register_client(&info->notifier) < 0) {
+ logError(1, "%s ERROR: register notifier failed!\n", tag);
+ }
+
+END: /* here start the reporting phase, assembling the data to send in the file node */
+ all_strbuff = (u8 *) kmalloc(size, GFP_KERNEL);
+ memset(all_strbuff, 0, size);
+
+ snprintf(buff, sizeof(buff), "%02X", 0xAA);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%08X", res);
+ strlcat(all_strbuff, buff, size);
+
+ if (res >= OK) {
+ /*all the other cases are already fine printing only the res.*/
+ switch (typeOfComand[0]) {
+ case 0x13:
+ snprintf(buff, sizeof (buff), "%02X", (u8) frameMS.header.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", (u8) frameMS.header.sense_node);
+ strlcat(all_strbuff, buff, size);
+
+ for (j = 0; j < frameMS.node_data_size; j++) {
+ snprintf(buff, sizeof(buff), "%04X", frameMS.node_data[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ kfree(frameMS.node_data);
+ break;
+
+ case 0x15:
+ snprintf(buff, sizeof(buff), "%02X", (u8) frameSS.header.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", (u8) frameSS.header.sense_node);
+ strlcat(all_strbuff, buff, size);
+
+ /* Copying self raw data Force */
+ for (j = 0; j < frameSS.header.force_node; j++) {
+ snprintf(buff, sizeof(buff), "%04X", frameSS.force_data[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ /* Copying self raw data Sense */
+ for (j = 0; j < frameSS.header.sense_node; j++) {
+ snprintf(buff, sizeof(buff), "%04X", frameSS.sense_data[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ kfree(frameSS.force_data);
+ kfree(frameSS.sense_data);
+ break;
+
+ case 0x14:
+ snprintf(buff, sizeof(buff), "%02X", (u8) compData.header.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", (u8) compData.header.sense_node);
+ strlcat(all_strbuff, buff, size);
+
+ /* Cpying CX1 value */
+ snprintf(buff, sizeof(buff), "%02X", compData.cx1);
+ strlcat(all_strbuff, buff, size);
+
+ /* Copying CX2 values */
+ for (j = 0; j < compData.node_data_size; j++) {
+ snprintf(buff, sizeof(buff), "%02X", *(compData.node_data + j));
+ strlcat(all_strbuff, buff, size);
+ }
+
+ kfree(compData.node_data);
+ break;
+
+ case 0x16:
+ snprintf(buff, sizeof(buff), "%02X", comData.header.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", comData.header.sense_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", comData.f_ix1);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", comData.s_ix1);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", comData.f_cx1);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof(buff), "%02X", comData.s_cx1);
+ strlcat(all_strbuff, buff, size);
+
+ /* Copying IX2 Force */
+ for (j = 0; j < comData.header.force_node; j++) {
+ snprintf(buff, sizeof(buff), "%02X", comData.ix2_fm[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ /* Copying IX2 Sense */
+ for (j = 0; j < comData.header.sense_node; j++) {
+ snprintf(buff, sizeof(buff), "%02X", comData.ix2_sn[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ /* Copying CX2 Force */
+ for (j = 0; j < comData.header.force_node; j++) {
+ snprintf(buff, sizeof(buff), "%02X", comData.cx2_fm[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ /* Copying CX2 Sense */
+ for (j = 0; j < comData.header.sense_node; j++) {
+ snprintf(buff, sizeof(buff), "%02X", comData.cx2_sn[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ kfree(comData.ix2_fm);
+ kfree(comData.ix2_sn);
+ kfree(comData.cx2_fm);
+ kfree(comData.cx2_sn);
+ break;
+
+ default:
+ break;
+
+ }
+ }
+
+ snprintf(buff, sizeof(buff), "%02X", 0xBB);
+ strlcat(all_strbuff, buff, size);
+
+ count = snprintf(buf, TSP_BUF_SIZE, "%s\n", all_strbuff);
+ numberParameters = 0; /* need to reset the number of parameters
+ * in order to wait the next command, comment
+ *if you want to repeat the last command sent
+ *just doing a cat
+ */
+ /* logError(0,"%s numberParameters = %d\n", tag, numberParameters); */
+ kfree(all_strbuff);
+
+ kfree(typeOfComand);
+ return count;
+
+}
+
+static DEVICE_ATTR(fwupdate, (S_IRUGO | S_IWUSR | S_IWGRP), fts_sysfs_fwupdate_show, fts_fw_control_store);
+static DEVICE_ATTR(appid, (S_IRUGO), fts_sysfs_config_id_show, NULL);
+static DEVICE_ATTR(fw_file_test, (S_IRUGO), fts_fw_test_show, NULL);
+static DEVICE_ATTR(stm_fts_cmd, (S_IRUGO | S_IWUSR | S_IWGRP), stm_fts_cmd_show, stm_fts_cmd_store);
+static DEVICE_ATTR(feature_enable, (S_IRUGO | S_IWUSR | S_IWGRP), fts_feature_enable_show, fts_feature_enable_store);
+#ifdef PHONE_GESTURE
+static DEVICE_ATTR(gesture_mask, (S_IRUGO | S_IWUSR | S_IWGRP), fts_gesture_mask_show, fts_gesture_mask_store);
+#endif
+/* /sys/devices/soc.0/f9928000.i2c/i2c-6/6-0049 */
+static struct attribute *fts_attr_group[] = {
+ &dev_attr_fwupdate.attr,
+ &dev_attr_appid.attr,
+ &dev_attr_fw_file_test.attr,
+ /* &dev_attr_touch_debug.attr, */
+ &dev_attr_stm_fts_cmd.attr,
+ &dev_attr_feature_enable.attr,
+#ifdef PHONE_GESTURE
+ &dev_attr_gesture_mask.attr,
+#endif
+ NULL,
+};
+
+static int fts_command(struct fts_ts_info *info, unsigned char cmd)
+{
+ unsigned char regAdd;
+ int ret;
+
+ regAdd = cmd;
+
+ ret = fts_writeCmd(&regAdd, sizeof (regAdd)); /* 0 = ok */
+
+ logError(0, "%s Issued command 0x%02x, return value %08X\n", cmd, ret);
+
+ return ret;
+}
+
+void fts_input_report_key(struct fts_ts_info *info, int key_code)
+{
+ mutex_lock(&info->input_report_mutex);
+ input_report_key(info->input_dev, key_code, 1);
+ input_sync(info->input_dev);
+ input_report_key(info->input_dev, key_code, 0);
+ input_sync(info->input_dev);
+ mutex_unlock(&info->input_report_mutex);
+}
+
+/*
+ * New Interrupt handle implementation
+ */
+
+static inline unsigned char *fts_next_event(unsigned char *evt)
+{
+ /* Nothing to do with this event, moving to the next one */
+ evt += FIFO_EVENT_SIZE;
+
+ /* the previous one was the last event ? */
+ return (evt[-1] & 0x1F) ? evt : NULL;
+}
+
+/* EventId : 0x00 */
+static unsigned char *fts_nop_event_handler(struct fts_ts_info *info,
+ unsigned char *event) {
+ /* logError(1, "%s %s Doing nothing for event = %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ * tag, __func__, event[0], event[1], event[2], event[3], event[4], event[5], event[6], event[7]);
+ */
+ return fts_next_event(event);
+}
+
+/* EventId : 0x03 */
+static unsigned char *fts_enter_pointer_event_handler(struct fts_ts_info *info,
+ unsigned char *event) {
+ unsigned char touchId, touchcount;
+ int x, y, z;
+
+ if (!info->resume_bit)
+ goto no_report;
+
+ touchId = event[1] & 0x0F;
+ touchcount = (event[1] & 0xF0) >> 4;
+
+ __set_bit(touchId, &info->touch_id);
+
+ x = (event[2] << 4) | (event[4] & 0xF0) >> 4;
+ y = (event[3] << 4) | (event[4] & 0x0F);
+ z = (event[5] & 0x3F);
+
+ if (x == X_AXIS_MAX)
+ x--;
+
+ if (y == Y_AXIS_MAX)
+ y--;
+
+ input_mt_slot(info->input_dev, touchId);
+ input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 1);
+ logError(0, "%s %s : TouchID = %d,Touchcount = %d\n", tag, __func__, touchId, touchcount);
+ if (touchcount == 1) {
+ input_report_key(info->input_dev, BTN_TOUCH, 1);
+ input_report_key(info->input_dev, BTN_TOOL_FINGER, 1);
+ }
+ /* input_report_abs(info->input_dev, ABS_MT_TRACKING_ID, touchId); */
+ input_report_abs(info->input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(info->input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(info->input_dev, ABS_MT_TOUCH_MAJOR, z);
+ input_report_abs(info->input_dev, ABS_MT_TOUCH_MINOR, z);
+ input_report_abs(info->input_dev, ABS_MT_PRESSURE, z);
+ logError(0, "%s %s : Event 0x%02x - ID[%d], (x, y, z) = (%3d, %3d, %3d)\n", tag, __func__, *event, touchId, x, y, z);
+
+no_report:
+ return fts_next_event(event);
+}
+
+/* EventId : 0x04 */
+static unsigned char *fts_leave_pointer_event_handler(struct fts_ts_info *info,
+ unsigned char *event) {
+ unsigned char touchId, touchcount;
+
+ touchId = event[1] & 0x0F;
+ touchcount = (event[1] & 0xF0) >> 4;
+
+ __clear_bit(touchId, &info->touch_id);
+
+ input_mt_slot(info->input_dev, touchId);
+ input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 0);
+ logError(0, "%s %s : TouchID = %d, Touchcount = %d\n", tag, __func__, touchId, touchcount);
+ if (touchcount == 0) {
+ input_report_key(info->input_dev, BTN_TOUCH, 0);
+ input_report_key(info->input_dev, BTN_TOOL_FINGER, 0);
+ }
+
+ input_report_abs(info->input_dev, ABS_MT_TRACKING_ID, -1);
+ logError(0, "%s %s : Event 0x%02x - release ID[%d]\n", tag, __func__, event[0], touchId);
+
+ return fts_next_event(event);
+}
+
+/* EventId : 0x05 */
+#define fts_motion_pointer_event_handler fts_enter_pointer_event_handler
+
+#ifdef PHONE_KEY
+/* EventId : 0x0E */
+static unsigned char *fts_key_status_event_handler(struct fts_ts_info *info, unsigned char *event)
+{
+ int value;
+ logError(0, "%s %s Received event %02X %02X %02X %02X %02X %02X %02X %02X\n", tag, __func__, event[0], event[1], event[2], event[3], event[4], event[5], event[6], event[7]);
+ /* TODO: the customer should handle the events coming from the keys according his needs (this is an example that report only the single pressure of one key at time) */
+ if (event[2] != 0) { /* event[2] contain the bitmask of the keys that are actually pressed */
+ switch (event[2]) {
+ case KEY1:
+ value = KEY_HOMEPAGE;
+ logError(0, "%s %s: Button HOME !\n", tag, __func__);
+ break;
+
+ case KEY2:
+ value = KEY_BACK;
+ logError(0, "%s %s: Button Back !\n", tag, __func__);
+ break;
+
+ case KEY3:
+ value = KEY_MENU;
+ logError(0, "%s %s: Button Menu !\n", tag, __func__);
+ break;
+
+ default:
+ logError(0, "%s %s: No valid Button ID or more than one key pressed!\n", tag, __func__);
+ goto done;
+ }
+
+ fts_input_report_key(info, value);
+ } else{
+ logError(0, "%s %s: All buttons released!\n", tag, __func__);
+ }
+done:
+ return fts_next_event(event);
+}
+#endif
+
+/* EventId : 0x0F */
+static unsigned char *fts_error_event_handler(struct fts_ts_info *info,
+ unsigned char *event) {
+ int error = 0, i = 0;
+ logError(0, "%s %s Received event 0x%02x 0x%02x\n", tag, __func__, event[0], event[1]);
+
+ switch (event[1]) {
+ case EVENT_TYPE_ESD_ERROR:
+ {
+ for (i = 0; i < TOUCH_ID_MAX; i++) {
+ input_mt_slot(info->input_dev, i);
+ input_mt_report_slot_state(info->input_dev, (i < FINGER_MAX) ? MT_TOOL_FINGER : MT_TOOL_PEN, 0);
+ }
+ input_sync(info->input_dev);
+
+ fts_chip_powercycle(info);
+
+ error = fts_system_reset();
+ error |= fts_mode_handler(info, 0);
+ error |= fts_enableInterrupt();
+ if (error < OK) {
+ logError(1, "%s %s Cannot restore the device ERROR %08X\n", tag, __func__, error);
+ }
+ }
+ break;
+ case EVENT_TYPE_WATCHDOG_ERROR: /* watch dog timer */
+ {
+ if (event[2] == 0) {
+ /* before reset clear all slot */
+ for (i = 0; i < TOUCH_ID_MAX; i++) {
+ input_mt_slot(info->input_dev, i);
+ input_mt_report_slot_state(info->input_dev,
+ (i < FINGER_MAX) ? MT_TOOL_FINGER : MT_TOOL_PEN, 0);
+ }
+ input_sync(info->input_dev);
+ error = fts_system_reset();
+ error |= fts_mode_handler(info, 0);
+ error |= fts_enableInterrupt();
+ if (error < OK) {
+ logError(1, "%s %s Cannot reset the device ERROR %08X\n", tag, __func__, error);
+ }
+ }
+ }
+ break;
+
+ }
+ return fts_next_event(event);
+}
+
+/* EventId : 0x10 */
+static unsigned char *fts_controller_ready_event_handler(
+ struct fts_ts_info *info, unsigned char *event) {
+ int error;
+ logError(0, "%s %s Received event 0x%02x\n", tag, __func__, event[0]);
+ info->touch_id = 0;
+ input_sync(info->input_dev);
+ setSystemResettedUp(1);
+ setSystemResettedDown(1);
+ error = fts_mode_handler(info, 0);
+ if (error < OK) {
+ logError(1, "%s %s Cannot restore the device status ERROR %08X\n", tag, __func__, error);
+ }
+ return fts_next_event(event);
+}
+
+/* EventId : 0x16 */
+static unsigned char *fts_status_event_handler(
+ struct fts_ts_info *info, unsigned char *event) {
+ /* logError(1, "%s Received event 0x%02x\n", tag, event[0]); */
+
+ switch (event[1]) {
+ case EVENT_TYPE_MS_TUNING_CMPL:
+ case EVENT_TYPE_SS_TUNING_CMPL:
+ case FTS_FORCE_CAL_SELF_MUTUAL:
+ case FTS_FLASH_WRITE_CONFIG:
+ case FTS_FLASH_WRITE_COMP_MEMORY:
+ case FTS_FORCE_CAL_SELF:
+ case FTS_WATER_MODE_ON:
+ case FTS_WATER_MODE_OFF:
+ default:
+ logError(0,
+ "%s %s Received unhandled status event = %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ tag, __func__, event[0], event[1], event[2],
+ event[3], event[4], event[5], event[6], event[7]);
+ break;
+ }
+
+ return fts_next_event(event);
+}
+
+#ifdef PHONE_GESTURE
+static unsigned char *fts_gesture_event_handler(struct fts_ts_info *info, unsigned char *event)
+{
+ unsigned char touchId;
+ int value;
+
+ logError(0, "%s gesture event data: %02X %02X %02X %02X %02X %02X %02X %02X\n", tag, event[0], event[1], event[2], event[3], event[4], event[5], event[6], event[7]);
+
+ if (event[1] == 0x03) {
+
+ logError(1, "%s %s: Gesture ID %02X enable_status = %02X\n", tag, __func__, event[2], event[3]);
+
+ }
+ if (event[1] == EVENT_TYPE_ENB && event[2] == 0x00) {
+ switch (event[3]) {
+ case GESTURE_ENABLE:
+ logError(1, "%s %s: Gesture Enabled! res = %02X\n", tag, __func__, event[4]);
+ break;
+
+ case GESTURE_DISABLE:
+ logError(1, "%s %s: Gesture Disabled! res = %02X\n", tag, __func__, event[4]);
+ break;
+
+ default:
+ logError(1, "%s %s: Event not Valid!\n", tag, __func__);
+
+ }
+
+ }
+
+ /* always use touchId zero */
+ touchId = 0;
+ __set_bit(touchId, &info->touch_id);
+
+ if (event[0] == EVENTID_GESTURE && (event[1] == EVENT_TYPE_GESTURE_DTC1 || event[1] == EVENT_TYPE_GESTURE_DTC2)) {
+
+ switch (event[2]) {
+ case GES_ID_DBLTAP:
+ value = KEY_WAKEUP;
+ logError(0, "%s %s: double tap !\n", tag, __func__);
+ break;
+
+ case GES_ID_AT:
+ value = KEY_WWW;
+ logError(0, "%s %s: @ !\n", tag, __func__);
+ break;
+
+ case GES_ID_C:
+ value = KEY_C;
+ logError(0, "%s %s: C !\n", tag, __func__);
+ break;
+
+ case GES_ID_E:
+ value = KEY_E;
+ logError(0, "%s %s: e !\n", tag, __func__);
+ break;
+
+ case GES_ID_F:
+ value = KEY_F;
+ logError(0, "%s %s: F !\n", tag, __func__);
+ break;
+
+ case GES_ID_L:
+ value = KEY_L;
+ logError(0, "%s %s: L !\n", tag, __func__);
+ break;
+
+ case GES_ID_M:
+ value = KEY_M;
+ logError(0, "%s %s: M !\n", tag, __func__);
+ break;
+
+ case GES_ID_O:
+ value = KEY_O;
+ logError(0, "%s %s: O !\n", tag, __func__);
+ break;
+
+ case GES_ID_S:
+ value = KEY_S;
+ logError(0, "%s %s: S !\n", tag, __func__);
+ break;
+
+ case GES_ID_V:
+ value = KEY_V;
+ logError(0, "%s %s: V !\n", tag, __func__);
+ break;
+
+ case GES_ID_W:
+ value = KEY_W;
+ logError(0, "%s %s: W !\n", tag, __func__);
+ break;
+
+ case GES_ID_Z:
+ value = KEY_Z;
+ logError(0, "%s %s: Z !\n", tag, __func__);
+ break;
+
+ case GES_ID_HFLIP_L2R:
+ value = KEY_RIGHT;
+ logError(0, "%s %s: -> !\n", tag, __func__);
+ break;
+
+ case GES_ID_HFLIP_R2L:
+ value = KEY_LEFT;
+ logError(0, "%s %s: <- !\n", tag, __func__);
+ break;
+
+ case GES_ID_VFLIP_D2T:
+ value = KEY_UP;
+ logError(0, "%s %s: UP !\n", tag, __func__);
+ break;
+
+ case GES_ID_VFLIP_T2D:
+ value = KEY_DOWN;
+ logError(0, "%s %s: DOWN !\n", tag, __func__);
+ break;
+
+ case GES_ID_CUST1:
+ value = KEY_F1;
+ logError(0, "%s %s: F1 !\n", tag, __func__);
+ break;
+
+ case GES_ID_CUST2:
+ value = KEY_F1;
+ logError(0, "%s %s: F2 !\n", tag, __func__);
+ break;
+
+ case GES_ID_CUST3:
+ value = KEY_F3;
+ logError(0, "%s %s: F3 !\n", tag, __func__);
+ break;
+
+ case GES_ID_CUST4:
+ value = KEY_F1;
+ logError(0, "%s %s: F4 !\n", tag, __func__);
+ break;
+
+ case GES_ID_CUST5:
+ value = KEY_F1;
+ logError(0, "%s %s: F5 !\n", tag, __func__);
+ break;
+
+ case GES_ID_LEFTBRACE:
+ value = KEY_LEFTBRACE;
+ logError(0, "%s %s: < !\n", tag, __func__);
+ break;
+
+ case GES_ID_RIGHTBRACE:
+ value = KEY_RIGHTBRACE;
+ logError(0, "%s %s: > !\n", tag, __func__);
+ break;
+ default:
+ logError(0, "%s %s: No valid GestureID!\n", tag, __func__);
+ goto gesture_done;
+
+ }
+
+ fts_input_report_key(info, value);
+
+ gesture_done:
+ /* Done with gesture event, clear bit. */
+ __clear_bit(touchId, &info->touch_id);
+ }
+
+ return fts_next_event(event);
+}
+#endif
+
+/* EventId : 0x05 */
+#define fts_motion_pointer_event_handler fts_enter_pointer_event_handler
+
+/*
+ * This handler is called each time there is at least
+ * one new event in the FIFO
+ */
+static void fts_event_handler(struct work_struct *work)
+{
+ struct fts_ts_info *info;
+ int error, error1;
+ int left_events;
+ unsigned char regAdd;
+ unsigned char data[FIFO_EVENT_SIZE * (FIFO_DEPTH)] = {0};
+ unsigned char *event = NULL;
+ unsigned char eventId;
+ event_dispatch_handler_t event_handler;
+
+ info = container_of(work, struct fts_ts_info, work);
+ /*
+ * to avoid reading all FIFO, we read the first event and
+ * then check how many events left in the FIFO
+ */
+
+
+ regAdd = FIFO_CMD_READONE;
+ error = fts_readCmd(&regAdd,
+ sizeof (regAdd), data, FIFO_EVENT_SIZE);
+
+ if (!error) {
+
+ left_events = data[7] & 0x1F;
+ if ((left_events > 0) && (left_events < FIFO_DEPTH)) {
+ /*
+ * Read remaining events.
+ */
+ regAdd = FIFO_CMD_READALL;
+
+ error1 = fts_readCmd(&regAdd, sizeof (regAdd),
+ &data[FIFO_EVENT_SIZE],
+ left_events * FIFO_EVENT_SIZE);
+ /*
+ * Got an error reading remaining events,
+ * process at least * the first one that was
+ * reading fine.
+ */
+ if (error1)
+ data[7] &= 0xE0;
+ }
+
+ /* At least one event is available */
+ event = data;
+ do {
+ eventId = *event;
+ event_handler = info->event_dispatch_table[eventId];
+
+ if (eventId < EVENTID_LAST) {
+ event = event_handler(info, (event));
+ } else {
+ event = fts_next_event(event);
+ }
+ input_sync(info->input_dev);
+ } while (event);
+ }
+
+ /*
+ * re-enable interrupts
+ */
+ fts_interrupt_enable(info);
+}
+
+static int cx_crc_check(void)
+{
+ unsigned char regAdd1[3] = {FTS_CMD_HW_REG_R, ADDR_CRC_BYTE0, ADDR_CRC_BYTE1};
+ unsigned char val = 0;
+ unsigned char crc_status;
+ unsigned int error;
+
+ error = fts_readCmd(regAdd1, sizeof (regAdd1), &val, 1);
+ if (error < OK) {
+ logError(1, "%s %s Cannot read crc status ERROR %08X\n", tag, __func__, error);
+ return error;
+ }
+
+ crc_status = val & CRC_MASK;
+ if (crc_status != OK) { /* CRC error if crc_status!= 0 */
+ logError(1, "%s %s CRC ERROR = %X\n", tag, __func__, crc_status);
+ }
+
+ return crc_status; /* return OK if no CRC error, or a number >OK if crc error */
+}
+
+static void fts_fw_update_auto(struct work_struct *work)
+{
+ int retval = 0;
+ int retval1 = 0;
+ int ret;
+ struct fts_ts_info *info;
+ struct delayed_work *fwu_work = container_of(work, struct delayed_work, work);
+ int crc_status = 0;
+ int error = 0;
+ info = container_of(fwu_work, struct fts_ts_info, fwu_work);
+
+ logError(1, "%s Fw Auto Update is starting...\n", tag);
+
+ /* check CRC status */
+ ret = cx_crc_check();
+ if (ret > OK && ftsInfo.u16_fwVer == 0x0000) {
+ logError(1, "%s %s: CRC Error or NO FW!\n", tag, __func__);
+ crc_status = 1;
+ } else {
+ crc_status = 0;
+ logError(1, "%s %s: NO CRC Error or Impossible to read CRC register!\n", tag, __func__);
+ }
+#ifdef FTM3_CHIP
+ retval = flashProcedure(PATH_FILE_FW, crc_status, !crc_status);
+#else
+ retval = flashProcedure(PATH_FILE_FW, crc_status, 1);
+#endif
+ if ((retval & 0xFF000000) == ERROR_FLASH_PROCEDURE) {
+ logError(1, "%s %s: firmware update failed and retry! ERROR %08X\n", tag, __func__, retval);
+ fts_chip_powercycle(info); /* power reset */
+#ifdef FTM3_CHIP
+ retval1 = flashProcedure(PATH_FILE_FW, crc_status, !crc_status);
+#else
+ retval1 = flashProcedure(PATH_FILE_FW, crc_status, 1);
+#endif
+ if ((retval1 & 0xFF000000) == ERROR_FLASH_PROCEDURE) {
+ logError(1, "%s %s: firmware update failed again! ERROR %08X\n", tag, __func__, retval1);
+ logError(1, "%s Fw Auto Update Failed!\n", tag);
+ /* return; */
+ }
+ }
+
+ if ((ftsInfo.u32_mpPassFlag != INIT_MP) && (ftsInfo.u32_mpPassFlag != INIT_FIELD))
+ ret = ERROR_GET_INIT_STATUS;
+ else
+ ret = OK;
+
+ if (ret == ERROR_GET_INIT_STATUS) { /* initialization status not correct or after FW complete update, do initialization. */
+ error = fts_chip_initialization(info);
+ if (error < OK) {
+ logError(1, "%s %s Cannot initialize the chip ERROR %08X\n", tag, __func__, error);
+ }
+ }
+ error = fts_init_hw(info);
+ if (error < OK) {
+ logError(1, "%s Cannot initialize the hardware device ERROR %08X\n", tag, error);
+ }
+
+ logError(1, "%s Fw Auto Update Finished!\n", tag);
+}
+
+static int fts_chip_initialization(struct fts_ts_info *info)
+{
+ int ret2 = 0;
+ int retry;
+ int initretrycnt = 0;
+
+ /* initialization error, retry initialization */
+ for (retry = 0; retry <= INIT_FLAG_CNT; retry++) {
+ ret2 = production_test_initialization();
+ if (ret2 == OK) {
+ ret2 = save_mp_flag(INIT_FIELD);
+ if (ret2 == OK)
+ break;
+ }
+ initretrycnt++;
+ logError(1, "%s initialization cycle count = %04d - ERROR %08X\n", tag, initretrycnt, ret2);
+ fts_chip_powercycle(info);
+ }
+ if (ret2 < OK) { /* initialization error */
+ logError(1, "%s fts initialization failed 3 times\n", tag);
+ }
+
+ return ret2;
+}
+
+#ifdef FTS_USE_POLLING_MODE
+
+static enum hrtimer_restart fts_timer_func(struct hrtimer *timer)
+{
+ struct fts_ts_info *info =
+ container_of(timer, struct fts_ts_info, timer);
+
+ queue_work(info->event_wq, &info->work);
+ return HRTIMER_NORESTART;
+}
+#else
+
+static irqreturn_t fts_interrupt_handler(int irq, void *handle)
+{
+ struct fts_ts_info *info = handle;
+ disable_irq_nosync(info->client->irq);
+ queue_work(info->event_wq, &info->work);
+ return IRQ_HANDLED;
+}
+#endif
+
+static int fts_interrupt_install(struct fts_ts_info *info)
+{
+ int i, error = 0;
+
+ info->event_dispatch_table = kzalloc(
+ sizeof (event_dispatch_handler_t) * EVENTID_LAST, GFP_KERNEL);
+
+ if (!info->event_dispatch_table) {
+ logError(1, "%s OOM allocating event dispatch table\n", tag);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < EVENTID_LAST; i++)
+ info->event_dispatch_table[i] = fts_nop_event_handler;
+
+ install_handler(info, ENTER_POINTER, enter_pointer);
+ install_handler(info, LEAVE_POINTER, leave_pointer);
+ install_handler(info, MOTION_POINTER, motion_pointer);
+ install_handler(info, ERROR_EVENT, error);
+ install_handler(info, CONTROL_READY, controller_ready);
+ install_handler(info, STATUS_UPDATE, status);
+#ifdef PHONE_GESTURE
+ install_handler(info, GESTURE, gesture);
+#endif
+#ifdef PHONE_KEY
+ install_handler(info, KEY_STATUS, key_status);
+#endif
+
+ /* disable interrupts in any case */
+ error = fts_disableInterrupt();
+
+#ifdef FTS_USE_POLLING_MODE
+ logError(1, "%s Polling Mode\n");
+ hrtimer_init(&info->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ info->timer.function = fts_timer_func;
+ hrtimer_start(&info->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+#else
+ logError(1, "%s Interrupt Mode\n", tag);
+ if (request_irq(info->client->irq, fts_interrupt_handler,
+ IRQF_TRIGGER_LOW, info->client->name,
+ info)) {
+ logError(1, "%s Request irq failed\n", tag);
+ kfree(info->event_dispatch_table);
+ error = -EBUSY;
+ } /*else {
+ error = fts_enableInterrupt();
+ }*/
+#endif
+
+ return error;
+}
+
+static void fts_interrupt_uninstall(struct fts_ts_info *info)
+{
+
+ fts_disableInterrupt();
+
+ kfree(info->event_dispatch_table);
+#ifdef FTS_USE_POLLING_MODE
+ hrtimer_cancel(&info->timer);
+#else
+ free_irq(info->client->irq, info);
+#endif
+}
+
+static void fts_interrupt_enable(struct fts_ts_info *info)
+{
+#ifdef FTS_USE_POLLING_MODE
+ hrtimer_start(&info->timer,
+ ktime_set(0, 10000000), HRTIMER_MODE_REL);
+#else
+ enable_irq(info->client->irq);
+#endif
+}
+
+/*
+static void fts_interrupt_disable(struct fts_ts_info *info)
+{
+#ifdef FTS_USE_POLLING_MODE
+ hrtimer_cancel(&info->timer);
+#else
+ disable_irq(info->client->irq);
+#endif
+}
+*/
+
+static int fts_init(struct fts_ts_info *info)
+{
+ int error;
+
+ error = fts_system_reset();
+ if (error < OK && error != (ERROR_TIMEOUT | ERROR_SYSTEM_RESET_FAIL)) {
+ logError(1, "%s Cannot reset the device! ERROR %08X\n", tag, error);
+ return error;
+ }
+ if (error == (ERROR_TIMEOUT | ERROR_SYSTEM_RESET_FAIL)) {
+ logError(1, "%s Setting default Chip INFO!\n", tag);
+ defaultChipInfo(0);
+ } else {
+ error = readChipInfo(0); /* system reset OK */
+ if (error < OK) {
+ logError(1, "%s Cannot read Chip Info! ERROR %08X\n", tag, error);
+ }
+ }
+
+ error = fts_interrupt_install(info);
+
+ if (error != OK) {
+ logError(1, "%s Init (1) error (ERROR = %08X)\n", error);
+ return error;
+ }
+
+ fts_unblank(info);
+
+ return error;
+}
+
+int fts_chip_powercycle(struct fts_ts_info *info)
+{
+ int error, i;
+
+ logError(1, "%s %s: Power Cycle Starting...\n", tag, __func__);
+ if (info->pwr_reg) {
+ error = regulator_disable(info->pwr_reg);
+ if (error < 0) {
+ logError(1, "%s %s: Failed to disable DVDD regulator\n", tag, __func__);
+ }
+ }
+
+ if (info->bus_reg) {
+ error = regulator_disable(info->bus_reg);
+ if (error < 0) {
+ logError(1, "%s %s: Failed to disable AVDD regulator\n", tag, __func__);
+ }
+ }
+
+ if (info->bdata->reset_gpio != GPIO_NOT_DEFINED)
+ gpio_set_value(info->bdata->reset_gpio, 0);
+
+ msleep(300);
+ if (info->pwr_reg) {
+ error = regulator_enable(info->bus_reg);
+ if (error < 0) {
+ logError(1, "%s %s: Failed to enable AVDD regulator\n", tag, __func__);
+ }
+ }
+
+ if (info->bus_reg) {
+ error = regulator_enable(info->pwr_reg);
+ if (error < 0) {
+ logError(1, "%s %s: Failed to enable DVDD regulator\n", tag, __func__);
+ }
+ }
+ msleep(300); /* time needed by the regulators for reaching the regime values */
+
+ if (info->bdata->reset_gpio != GPIO_NOT_DEFINED) {
+ msleep(10); /* time to wait before bring up the reset gpio after the power up of the regulators */
+ gpio_set_value(info->bdata->reset_gpio, 1);
+ /* msleep(300); */
+ }
+
+ /* before reset clear all slot */
+ for (i = 0; i < TOUCH_ID_MAX; i++) {
+ input_mt_slot(info->input_dev, i);
+ input_mt_report_slot_state(info->input_dev,
+ (i < FINGER_MAX) ? MT_TOOL_FINGER : MT_TOOL_PEN, 0);
+ }
+ input_sync(info->input_dev);
+
+ logError(1, "%s %s: Power Cycle Finished! ERROR CODE = %08x\n", tag, __func__, error);
+ setSystemResettedUp(1);
+ setSystemResettedDown(1);
+ return error;
+}
+
+int fts_chip_powercycle2(struct fts_ts_info *info, unsigned long sleep)
+{
+ int error, i;
+
+ logError(1, "%s %s: Power Cycle Starting...\n", tag, __func__);
+ if (info->pwr_reg) {
+ error = regulator_disable(info->pwr_reg);
+ if (error < 0) {
+ logError(1, "%s %s: Failed to disable DVDD regulator\n", tag, __func__);
+ }
+ }
+
+ if (info->bus_reg) {
+ error = regulator_disable(info->bus_reg);
+ if (error < 0) {
+ logError(1, "%s %s: Failed to disable AVDD regulator\n", tag, __func__);
+ }
+ }
+
+ if (info->bdata->reset_gpio != GPIO_NOT_DEFINED)
+ gpio_set_value(info->bdata->reset_gpio, 0);
+
+ msleep(sleep);
+ if (info->pwr_reg) {
+ error = regulator_enable(info->bus_reg);
+ if (error < 0) {
+ logError(1, "%s %s: Failed to enable AVDD regulator\n", tag, __func__);
+ }
+ }
+
+ if (info->bus_reg) {
+ error = regulator_enable(info->pwr_reg);
+ if (error < 0) {
+ logError(1, "%s %s: Failed to enable DVDD regulator\n", tag, __func__);
+ }
+ }
+ msleep(500); /*time needed by the regulators for reaching the regime values */
+
+ if (info->bdata->reset_gpio != GPIO_NOT_DEFINED) {
+ msleep(10); /*time to wait before bring up the reset gpio after the power up of the regulators */
+ gpio_set_value(info->bdata->reset_gpio, 1);
+ /* msleep(300); */
+ }
+
+ /* before reset clear all slot */
+ for (i = 0; i < TOUCH_ID_MAX; i++) {
+ input_mt_slot(info->input_dev, i);
+ input_mt_report_slot_state(info->input_dev,
+ (i < FINGER_MAX) ? MT_TOOL_FINGER : MT_TOOL_PEN, 0);
+ }
+ input_sync(info->input_dev);
+
+ logError(1, "%s %s: Power Cycle Finished! ERROR CODE = %08x\n", tag, __func__, error);
+ setSystemResettedUp(1);
+ setSystemResettedDown(1);
+ return error;
+}
+
+static int fts_init_hw(struct fts_ts_info *info)
+{
+ int error = 0;
+
+ error = cleanUp(1);
+ if (error < OK)
+ logError(1, "%s Init (2) error (ERROR = %08X)\n", tag, error);
+
+ info->mode = MODE_NORMAL;
+
+ return error;
+}
+
+ /*
+ * TODO: change this function according with the needs of
+ *customer in temrs of feature to enable/disable
+ */
+static int fts_mode_handler(struct fts_ts_info *info, int force)
+{
+ int res = OK;
+ int ret = OK;
+
+ logError(0, "%s %s: Mode Handler starting...\n", tag, __func__);
+ switch (info->resume_bit) {
+ case 0:/* screen down */
+ logError(0, "%s %s: Screen OFF...\n", tag, __func__);
+#ifdef PHONE_GESTURE
+ if (info->gesture_enabled == 1) {
+ logError(0, "%s %s: enter in gesture mode !\n", tag, __func__);
+ res = enterGestureMode(isSystemResettedDown());
+ if (res >= OK) {
+
+ info->mode = MODE_GESTURE;
+ /* return OK; */
+ } else {
+ logError(1, "%s %s: enterGestureMode failed! ERROR %08X recovery in senseOff...\n", tag, __func__, res);
+ }
+ }
+#endif
+ if (info->mode != MODE_GESTURE || info->gesture_enabled == 0) {
+ logError(0, "%s %s: Sense OFF!\n", tag, __func__);
+ res |= fts_command(info, FTS_CMD_MS_MT_SENSE_OFF); /* we need to use fts_command for speed reason (no need to check echo in this case and interrupt can be enabled) */
+#ifdef PHONE_KEY
+ logError(0, "%s %s: Key OFF!\n", tag, __func__);
+ res |= fts_command(info, FTS_CMD_MS_KEY_OFF);
+#endif
+
+ info->mode = MODE_SENSEOFF;
+
+ }
+ setSystemResettedDown(0);
+ break;
+
+ case 1: /* screen up */
+ logError(0, "%s %s: Screen ON...\n", tag, __func__);
+ logError(0, "%s %s: Sense ON!\n", tag, __func__);
+ res |= fts_command(info, FTS_CMD_MS_MT_SENSE_ON);
+#ifdef PHONE_KEY
+ logError(0, "%s %s: Key ON!\n", tag, __func__);
+ res |= fts_command(info, FTS_CMD_MS_KEY_ON);
+#endif
+ info->mode = MODE_NORMAL;
+
+ if (info->glove_enabled == FEAT_ENABLE || force == 1) {
+ if (isSystemResettedUp() || force == 1) {
+ logError(0, "%s %s: Glove Mode setting...\n", tag, __func__);
+ ret = featureEnableDisable(info->glove_enabled, FEAT_GLOVE);
+ if (ret < OK) {
+ logError(1, "%s %s: error during setting GLOVE_MODE! ERROR %08X\n", tag, __func__, ret);
+ }
+ res |= ret;
+ }
+ if (ret >= OK && info->glove_enabled == FEAT_ENABLE) {
+ info->mode = MODE_GLOVE;
+ logError(1, "%s %s: GLOVE_MODE Enabled!\n", tag, __func__);
+ } else{
+ logError(1, "%s %s: GLOVE_MODE Disabled!\n", tag, __func__);
+ }
+ }
+
+ setSystemResettedUp(0);
+ break;
+
+ default:
+ logError(1, "%s %s: invalid resume_bit value = %d! ERROR %08X\n", tag, __func__, info->resume_bit, ERROR_OP_NOT_ALLOW);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ logError(0, "%s %s: Mode Handler finished! res = %08X\n", tag, __func__, res);
+ return res;
+
+}
+
+static int fts_fb_state_chg_callback(struct notifier_block *nb, unsigned long val, void *data)
+{
+ struct fts_ts_info *info = container_of(nb, struct fts_ts_info, notifier);
+ struct fb_event *evdata = data;
+ int i;
+ unsigned int blank;
+
+ if (val != FB_EVENT_BLANK)
+ return 0;
+
+ logError(0, "%s %s: fts notifier begin!\n", tag, __func__);
+
+ if (evdata && evdata->data && val == FB_EVENT_BLANK && info) {
+
+ blank = *(int *) (evdata->data);
+
+ switch (blank) {
+ case FB_BLANK_POWERDOWN:
+ if (info->sensor_sleep)
+ break;
+
+ logError(0, "%s %s: FB_BLANK_POWERDOWN\n", tag, __func__);
+
+ /* Release all slots */
+ for (i = 0; i < TOUCH_ID_MAX; i++) {
+ input_mt_slot(info->input_dev, i);
+ input_mt_report_slot_state(info->input_dev,
+ (i < FINGER_MAX) ? MT_TOOL_FINGER : MT_TOOL_PEN, 0);
+ }
+ input_sync(info->input_dev);
+
+ info->resume_bit = 0;
+
+ fts_mode_handler(info, 0);
+
+ info->sensor_sleep = true;
+
+ fts_disableInterrupt();
+
+ break;
+
+ case FB_BLANK_UNBLANK:
+ if (!info->sensor_sleep)
+ break;
+
+ logError(0, "%s %s: FB_BLANK_UNBLANK\n", tag, __func__);
+
+ for (i = 0; i < TOUCH_ID_MAX; i++) {
+ input_mt_slot(info->input_dev, i);
+ input_mt_report_slot_state(info->input_dev,
+ (i < FINGER_MAX) ? MT_TOOL_FINGER : MT_TOOL_PEN, 0);
+ }
+ input_sync(info->input_dev);
+
+ info->resume_bit = 1;
+
+ fts_mode_handler(info, 0);
+
+ info->sensor_sleep = false;
+
+ fts_enableInterrupt();
+ break;
+ default:
+ break;
+
+ }
+ }
+ return NOTIFY_OK;
+
+}
+
+static void fts_unblank(struct fts_ts_info *info)
+{
+ int i;
+
+ for (i = 0; i < TOUCH_ID_MAX; i++) {
+ input_mt_slot(info->input_dev, i);
+ input_mt_report_slot_state(info->input_dev,
+ (i < FINGER_MAX) ? MT_TOOL_FINGER : MT_TOOL_PEN, 0);
+ }
+ input_sync(info->input_dev);
+
+ info->resume_bit = 1;
+
+ fts_mode_handler(info, 0);
+
+ info->sensor_sleep = false;
+
+ fts_enableInterrupt();
+}
+
+static struct notifier_block fts_noti_block = {
+ .notifier_call = fts_fb_state_chg_callback,
+};
+
+static int fts_get_reg(struct fts_ts_info *rmi4_data,
+ bool get) {
+ int retval;
+ const struct fts_i2c_platform_data *bdata =
+ rmi4_data->bdata;
+
+ if (!get) {
+ retval = 0;
+ goto regulator_put;
+ }
+
+ if ((bdata->pwr_reg_name != NULL) && (*bdata->pwr_reg_name != 0)) {
+ rmi4_data->pwr_reg = regulator_get(rmi4_data->dev,
+ bdata->pwr_reg_name);
+ if (IS_ERR(rmi4_data->pwr_reg)) {
+ logError(1, "%s %s: Failed to get power regulator\n", tag,
+ __func__);
+ retval = PTR_ERR(rmi4_data->pwr_reg);
+ goto regulator_put;
+ }
+ }
+
+ if ((bdata->bus_reg_name != NULL) && (*bdata->bus_reg_name != 0)) {
+ rmi4_data->bus_reg = regulator_get(rmi4_data->dev,
+ bdata->bus_reg_name);
+ if (IS_ERR(rmi4_data->bus_reg)) {
+ logError(1, "%s %s: Failed to get bus pullup regulator\n", tag,
+ __func__);
+ retval = PTR_ERR(rmi4_data->bus_reg);
+ goto regulator_put;
+ }
+ }
+
+ return 0;
+
+regulator_put:
+ if (rmi4_data->pwr_reg) {
+ regulator_put(rmi4_data->pwr_reg);
+ rmi4_data->pwr_reg = NULL;
+ }
+
+ if (rmi4_data->bus_reg) {
+ regulator_put(rmi4_data->bus_reg);
+ rmi4_data->bus_reg = NULL;
+ }
+
+ return retval;
+}
+
+static int fts_enable_reg(struct fts_ts_info *rmi4_data,
+ bool enable) {
+ int retval;
+
+ if (!enable) {
+ retval = 0;
+ goto disable_pwr_reg;
+ }
+
+ if (rmi4_data->bus_reg) {
+ retval = regulator_enable(rmi4_data->bus_reg);
+ if (retval < 0) {
+ logError(1, "%s %s: Failed to enable bus regulator\n", tag,
+ __func__);
+ goto exit;
+ }
+ }
+
+ if (rmi4_data->pwr_reg) {
+ retval = regulator_enable(rmi4_data->pwr_reg);
+ if (retval < 0) {
+ logError(1, "%s %s: Failed to enable power regulator\n", tag,
+ __func__);
+ goto disable_bus_reg;
+ }
+ }
+
+ return OK;
+
+disable_pwr_reg:
+ if (rmi4_data->pwr_reg)
+ regulator_disable(rmi4_data->pwr_reg);
+
+disable_bus_reg:
+ if (rmi4_data->bus_reg)
+ regulator_disable(rmi4_data->bus_reg);
+
+exit:
+ return retval;
+}
+
+static int fts_gpio_setup(int gpio, bool config, int dir, int state)
+{
+ int retval = 0;
+ unsigned char buf[16];
+
+ if (config) {
+ snprintf(buf, 16, "fts_gpio_%u\n", gpio);
+
+ retval = gpio_request(gpio, buf);
+ if (retval) {
+ logError(1, "%s %s: Failed to get gpio %d (code: %d)", tag,
+ __func__, gpio, retval);
+ return retval;
+ }
+
+ if (dir == 0)
+ retval = gpio_direction_input(gpio);
+ else
+ retval = gpio_direction_output(gpio, state);
+ if (retval) {
+ logError(1, "%s %s: Failed to set gpio %d direction", tag,
+ __func__, gpio);
+ return retval;
+ }
+ } else {
+ gpio_free(gpio);
+ }
+
+ return retval;
+}
+
+static int fts_set_gpio(struct fts_ts_info *rmi4_data)
+{
+ int retval;
+ const struct fts_i2c_platform_data *bdata =
+ rmi4_data->bdata;
+
+ retval = fts_gpio_setup(bdata->irq_gpio, true, 0, 0);
+ if (retval < 0) {
+ logError(1, "%s %s: Failed to configure irq GPIO\n", tag, __func__);
+ goto err_gpio_irq;
+ }
+
+ if (bdata->reset_gpio >= 0) {
+ retval = fts_gpio_setup(bdata->reset_gpio, true, 1, 0);
+ if (retval < 0) {
+ logError(1, "%s %s: Failed to configure reset GPIO\n", tag, __func__);
+ goto err_gpio_reset;
+ }
+ }
+ if (bdata->reset_gpio >= 0) {
+ gpio_set_value(bdata->reset_gpio, 0);
+ msleep(10);
+ gpio_set_value(bdata->reset_gpio, 1);
+ }
+
+ setResetGpio(bdata->reset_gpio);
+ return OK;
+
+err_gpio_reset:
+ fts_gpio_setup(bdata->irq_gpio, false, 0, 0);
+ setResetGpio(GPIO_NOT_DEFINED);
+err_gpio_irq:
+ return retval;
+}
+
+static int parse_dt(struct device *dev, struct fts_i2c_platform_data *bdata)
+{
+ int retval;
+ const char *name;
+ struct device_node *np = dev->of_node;
+
+ bdata->irq_gpio = of_get_named_gpio_flags(np,
+ "st,irq-gpio", 0, NULL);
+
+ logError(0, "%s irq_gpio = %d\n", tag, bdata->irq_gpio);
+
+ retval = of_property_read_string(np, "st,regulator_dvdd", &name);
+ if (retval == -EINVAL)
+ bdata->pwr_reg_name = NULL;
+ else if (retval < 0)
+ return retval;
+ bdata->pwr_reg_name = name;
+ logError(0, "%s pwr_reg_name = %s\n", tag, name);
+
+ retval = of_property_read_string(np, "st,regulator_avdd", &name);
+ if (retval == -EINVAL)
+ bdata->bus_reg_name = NULL;
+ else if (retval < 0)
+ return retval;
+ bdata->bus_reg_name = name;
+ logError(0, "%s bus_reg_name = %s\n", tag, name);
+
+ if (of_property_read_bool(np, "st,reset-gpio")) {
+ bdata->reset_gpio = of_get_named_gpio_flags(np,
+ "st,reset-gpio", 0, NULL);
+ logError(0, "%s reset_gpio =%d\n", tag, bdata->reset_gpio);
+ } else {
+ bdata->reset_gpio = GPIO_NOT_DEFINED;
+ }
+
+ return OK;
+}
+
+static int fts_probe(struct i2c_client *client,
+ const struct i2c_device_id *idp) {
+ struct fts_ts_info *info = NULL;
+ char fts_ts_phys[64];
+ int error = 0;
+ struct device_node *dp = client->dev.of_node;
+ int retval;
+
+ logError(1, "%s %s: driver probe begin!\n", tag, __func__);
+
+ logError(1, "%s SET I2C Functionality and Dev INFO:\n", tag);
+ openChannel(client);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ logError(1, "%s Unsupported I2C functionality\n", tag);
+ error = -EIO;
+ goto ProbeErrorExit_0;
+ }
+
+ info = kzalloc(sizeof (struct fts_ts_info), GFP_KERNEL);
+ if (!info) {
+ logError(1, "%s Out of memory... Impossible to allocate struct info!\n", tag);
+ error = -ENOMEM;
+ goto ProbeErrorExit_0;
+ }
+
+ info->client = client;
+
+ i2c_set_clientdata(client, info);
+ logError(1, "%s i2c address: %x\n", tag, client->addr);
+ info->dev = &info->client->dev;
+ if (dp) {
+ info->bdata = devm_kzalloc(&client->dev, sizeof (struct fts_i2c_platform_data), GFP_KERNEL);
+ if (!info->bdata) {
+ logError(1, "%s ERROR:info.bdata kzalloc failed\n", tag);
+ goto ProbeErrorExit_1;
+ }
+ parse_dt(&client->dev, info->bdata);
+ }
+
+ logError(1, "%s SET Regulators:\n", tag);
+ retval = fts_get_reg(info, true);
+ if (retval < 0) {
+ logError(1, "%s ERROR: %s: Failed to get regulators\n", tag, __func__);
+ goto ProbeErrorExit_1;
+ }
+
+ retval = fts_enable_reg(info, true);
+ if (retval < 0) {
+ logError(1, "%s %s: ERROR Failed to enable regulators\n", tag, __func__);
+ goto ProbeErrorExit_2;
+ }
+
+ logError(1, "%s SET GPIOS:\n", tag);
+ retval = fts_set_gpio(info);
+ if (retval < 0) {
+ logError(1, "%s %s: ERROR Failed to set up GPIO's\n", tag, __func__);
+ goto ProbeErrorExit_2;
+ }
+ info->client->irq = gpio_to_irq(info->bdata->irq_gpio);
+
+ logError(1, "%s SET Auto Fw Update:\n", tag);
+ info->fwu_workqueue = create_singlethread_workqueue("fts-fwu-queue");
+ if (!info->fwu_workqueue) {
+ logError(1, "%s ERROR: Cannot create fwu work thread\n", tag);
+ goto ProbeErrorExit_3;
+ }
+ INIT_DELAYED_WORK(&info->fwu_work, fts_fw_update_auto);
+
+ logError(1, "%s SET Event Handler:\n", tag);
+ info->event_wq = create_singlethread_workqueue("fts-event-queue");
+ if (!info->event_wq) {
+ logError(1, "%s ERROR: Cannot create work thread\n", tag);
+ error = -ENOMEM;
+ goto ProbeErrorExit_4;
+ }
+
+ INIT_WORK(&info->work, fts_event_handler);
+
+ logError(1, "%s SET Input Device Property:\n", tag);
+ info->dev = &info->client->dev;
+ info->input_dev = input_allocate_device();
+ if (!info->input_dev) {
+ logError(1, "%s ERROR: No such input device defined!\n", tag);
+ error = -ENODEV;
+ goto ProbeErrorExit_5;
+ }
+ info->input_dev->dev.parent = &client->dev;
+ info->input_dev->name = FTS_TS_DRV_NAME;
+ snprintf(fts_ts_phys, sizeof (fts_ts_phys), "%s/input0",
+ info->input_dev->name);
+ info->input_dev->phys = fts_ts_phys;
+ info->input_dev->id.bustype = BUS_I2C;
+ info->input_dev->id.vendor = 0x0001;
+ info->input_dev->id.product = 0x0002;
+ info->input_dev->id.version = 0x0100;
+
+ __set_bit(EV_SYN, info->input_dev->evbit);
+ __set_bit(EV_KEY, info->input_dev->evbit);
+ __set_bit(EV_ABS, info->input_dev->evbit);
+ __set_bit(BTN_TOUCH, info->input_dev->keybit);
+ __set_bit(BTN_TOOL_FINGER, info->input_dev->keybit);
+
+ input_mt_init_slots(info->input_dev, TOUCH_ID_MAX, INPUT_MT_DIRECT);
+
+ /* input_mt_init_slots(info->input_dev, TOUCH_ID_MAX); */
+
+ /* input_set_abs_params(info->input_dev, ABS_MT_TRACKING_ID, 0, FINGER_MAX, 0, 0); */
+ input_set_abs_params(info->input_dev, ABS_MT_POSITION_X,
+ X_AXIS_MIN, X_AXIS_MAX, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_POSITION_Y,
+ Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MAJOR,
+ AREA_MIN, AREA_MAX, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MINOR,
+ AREA_MIN, AREA_MAX, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_PRESSURE,
+ PRESSURE_MIN, PRESSURE_MAX, 0, 0);
+
+#ifdef PHONE_GESTURE
+ input_set_capability(info->input_dev, EV_KEY, KEY_WAKEUP);
+
+ input_set_capability(info->input_dev, EV_KEY, KEY_M);
+ input_set_capability(info->input_dev, EV_KEY, KEY_O);
+ input_set_capability(info->input_dev, EV_KEY, KEY_E);
+ input_set_capability(info->input_dev, EV_KEY, KEY_W);
+ input_set_capability(info->input_dev, EV_KEY, KEY_C);
+ input_set_capability(info->input_dev, EV_KEY, KEY_L);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F);
+ input_set_capability(info->input_dev, EV_KEY, KEY_V);
+ input_set_capability(info->input_dev, EV_KEY, KEY_S);
+ input_set_capability(info->input_dev, EV_KEY, KEY_Z);
+ input_set_capability(info->input_dev, EV_KEY, KEY_WWW);
+
+ input_set_capability(info->input_dev, EV_KEY, KEY_LEFT);
+ input_set_capability(info->input_dev, EV_KEY, KEY_RIGHT);
+ input_set_capability(info->input_dev, EV_KEY, KEY_UP);
+ input_set_capability(info->input_dev, EV_KEY, KEY_DOWN);
+
+ input_set_capability(info->input_dev, EV_KEY, KEY_F1);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F2);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F3);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F4);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F5);
+
+ input_set_capability(info->input_dev, EV_KEY, KEY_LEFTBRACE);
+ input_set_capability(info->input_dev, EV_KEY, KEY_RIGHTBRACE);
+#endif
+
+#ifdef PHONE_KEY
+ /* KEY associated to the touch screen buttons */
+ input_set_capability(info->input_dev, EV_KEY, KEY_HOMEPAGE);
+ input_set_capability(info->input_dev, EV_KEY, KEY_BACK);
+ input_set_capability(info->input_dev, EV_KEY, KEY_MENU);
+#endif
+
+ mutex_init(&(info->input_report_mutex));
+
+ /* register the multi-touch input device */
+ error = input_register_device(info->input_dev);
+ if (error) {
+ logError(1, "%s ERROR: No such input device\n", tag);
+ error = -ENODEV;
+ goto ProbeErrorExit_5_1;
+ }
+
+ /* track slots */
+ info->touch_id = 0;
+
+ /* init hardware device */
+ logError(1, "%s Device Initialization:\n", tag);
+ error = fts_init(info);
+ if (error < OK) {
+ logError(1, "%s Cannot initialize the device ERROR %08X\n", tag, error);
+ error = -ENODEV;
+ goto ProbeErrorExit_6;
+ }
+
+ info->gesture_enabled = 0;
+ info->glove_enabled = 0;
+ info->resume_bit = 1;
+ info->notifier = fts_noti_block;
+ error = fb_register_client(&info->notifier);
+ if (error) {
+ logError(1, "%s ERROR: register notifier failed!\n", tag);
+ goto ProbeErrorExit_6;
+ }
+
+ logError(1, "%s SET Device File Nodes:\n", tag);
+ /* sysfs stuff */
+ info->attrs.attrs = fts_attr_group;
+ error = sysfs_create_group(&client->dev.kobj, &info->attrs);
+ if (error) {
+ logError(1, "%s ERROR: Cannot create sysfs structure!\n", tag);
+ error = -ENODEV;
+ goto ProbeErrorExit_7;
+ }
+
+#ifdef SCRIPTLESS
+ /*I2C cmd*/
+ if (fts_cmd_class == NULL)
+ fts_cmd_class = class_create(THIS_MODULE, FTS_TS_DRV_NAME);
+ info->i2c_cmd_dev = device_create(fts_cmd_class,
+ NULL, DCHIP_ID_0, info, "fts_i2c");
+ if (IS_ERR(info->i2c_cmd_dev)) {
+ logError(1, "%s ERROR: Failed to create device for the sysfs!\n", tag);
+ goto ProbeErrorExit_8;
+ }
+
+ dev_set_drvdata(info->i2c_cmd_dev, info);
+
+ error = sysfs_create_group(&info->i2c_cmd_dev->kobj,
+ &i2c_cmd_attr_group);
+ if (error) {
+ logError(1, "%s ERROR: Failed to create sysfs group!\n", tag);
+ goto ProbeErrorExit_9;
+ }
+
+#endif
+
+#ifdef DRIVER_TEST
+ if (fts_cmd_class == NULL)
+ fts_cmd_class = class_create(THIS_MODULE, FTS_TS_DRV_NAME);
+ info->test_cmd_dev = device_create(fts_cmd_class,
+ NULL, DCHIP_ID_0, info, "fts_driver_test");
+ if (IS_ERR(info->test_cmd_dev)) {
+ logError(1, "%s ERROR: Failed to create device for the sysfs!\n", tag);
+ goto ProbeErrorExit_10;
+ }
+
+ dev_set_drvdata(info->test_cmd_dev, info);
+
+ error = sysfs_create_group(&info->test_cmd_dev->kobj,
+ &test_cmd_attr_group);
+ if (error) {
+ logError(1, "%s ERROR: Failed to create sysfs group!\n", tag);
+ goto ProbeErrorExit_11;
+ }
+
+#endif
+ /*if wanna auto-update FW when probe,
+ * please don't comment the following code
+ */
+
+ /* queue_delayed_work(info->fwu_workqueue, &info->fwu_work,
+ * msecs_to_jiffies(EXP_FN_WORK_DELAY_MS));
+ */
+ logError(1, "%s Probe Finished!\n", tag);
+ return OK;
+
+ /* error exit path */
+#ifdef DRIVER_TEST
+ProbeErrorExit_11:
+#ifndef SCRIPTLESS
+ device_destroy(fts_cmd_class, DCHIP_ID_0);
+#endif
+
+ProbeErrorExit_10:
+#ifndef SCRIPTLESS
+ sysfs_remove_group(&client->dev.kobj, &info->attrs);
+#endif
+#endif
+
+#ifdef SCRIPTLESS
+ProbeErrorExit_9:
+ device_destroy(fts_cmd_class, DCHIP_ID_0);
+
+ProbeErrorExit_8:
+ sysfs_remove_group(&client->dev.kobj, &info->attrs);
+#endif
+
+ProbeErrorExit_7:
+ fb_unregister_client(&info->notifier);
+
+ProbeErrorExit_6:
+ input_unregister_device(info->input_dev);
+
+ProbeErrorExit_5_1:
+ /* intput_free_device(info->input_dev ); */
+
+ ProbeErrorExit_5:
+ destroy_workqueue(info->event_wq);
+
+ProbeErrorExit_4:
+ destroy_workqueue(info->fwu_workqueue);
+
+ProbeErrorExit_3:
+ fts_enable_reg(info, false);
+
+ProbeErrorExit_2:
+ fts_get_reg(info, false);
+
+ProbeErrorExit_1:
+ kfree(info);
+
+ProbeErrorExit_0:
+ logError(1, "%s Probe Failed!\n", tag);
+
+ return error;
+}
+
+static int fts_remove(struct i2c_client *client)
+{
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+#ifdef DRIVER_TEST
+ sysfs_remove_group(&info->test_cmd_dev->kobj,
+ &test_cmd_attr_group);
+#endif
+
+#ifdef SCRIPTLESS
+ /*I2C cmd*/
+ sysfs_remove_group(&info->i2c_cmd_dev->kobj,
+ &i2c_cmd_attr_group);
+
+#endif
+
+#if defined(SCRIPTLESS) || defined(DRIVER_TEST)
+ device_destroy(fts_cmd_class, DCHIP_ID_0);
+#endif
+
+ /* sysfs stuff */
+ sysfs_remove_group(&client->dev.kobj, &info->attrs);
+
+ /* remove interrupt and event handlers */
+ fts_interrupt_uninstall(info);
+
+ fb_unregister_client(&info->notifier);
+
+ /* unregister the device */
+ input_unregister_device(info->input_dev);
+
+ /* intput_free_device(info->input_dev ); */
+
+ /* Empty the FIFO buffer */
+ fts_command(info, FIFO_CMD_FLUSH);
+ /* flushFIFO(); */
+
+ /* Remove the work thread */
+ destroy_workqueue(info->event_wq);
+ destroy_workqueue(info->fwu_workqueue);
+
+ fts_enable_reg(info, false);
+ fts_get_reg(info, false);
+
+ /* free all */
+ kfree(info);
+
+ return OK;
+}
+
+static struct of_device_id fts_of_match_table[] = {
+ {
+ .compatible = "st,fts",
+ },
+ {},
+};
+static const struct i2c_device_id fts_device_id[] = {
+ {FTS_TS_DRV_NAME, 0},
+ {}
+};
+
+static struct i2c_driver fts_i2c_driver = {
+ .driver = {
+ .name = FTS_TS_DRV_NAME,
+ .of_match_table = fts_of_match_table,
+ },
+ .probe = fts_probe,
+ .remove = fts_remove,
+ .id_table = fts_device_id,
+};
+
+static int __init fts_driver_init(void)
+{
+ return i2c_add_driver(&fts_i2c_driver);
+}
+
+static void __exit fts_driver_exit(void)
+{
+ i2c_del_driver(&fts_i2c_driver);
+}
+
+MODULE_DESCRIPTION("STMicroelectronics MultiTouch IC Driver");
+MODULE_AUTHOR("STMicroelectronics, Inc.");
+MODULE_LICENSE("GPL");
+
+late_initcall(fts_driver_init);
+module_exit(fts_driver_exit);
diff --git a/drivers/input/touchscreen/st/fts.h b/drivers/input/touchscreen/st/fts.h
new file mode 100644
index 000000000000..7d72d226349f
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts.h
@@ -0,0 +1,249 @@
+/*
+ * fts.c
+ *
+ * FTS Capacitive touch screen controller (FingerTipS)
+ *
+ * Copyright (C) 2016, STMicroelectronics Limited.
+ * Authors: AMG(Analog Mems Group)
+ *
+ * marco.cali@st.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _LINUX_FTS_I2C_H_
+#define _LINUX_FTS_I2C_H_
+
+#include "fts_lib/ftsSoftware.h"
+#include "fts_lib/ftsHardware.h"
+
+#define FTS_POWER_ON 1
+#define FTS_POWER_OFF 0
+
+/****************** CONFIGURATION SECTION ******************/
+/* #define PHONE_KEY */
+
+/* #define PHONE_GESTURE */
+
+#define SCRIPTLESS
+#ifdef SCRIPTLESS
+#define SCRIPTLESS_DEBUG
+/* uncomment this macro definition to print debug
+* message for script less support
+*/
+#endif
+
+#define DRIVER_TEST
+
+#define FW_H_FILE
+#ifdef FW_H_FILE
+#define FW_SIZE_NAME myArray_size
+#define FW_ARRAY_NAME myArray
+#endif
+
+#define LIMITS_H_FILE
+#ifdef LIMITS_H_FILE
+#define LIMITS_SIZE_NAME myArray2_size
+#define LIMITS_ARRAY_NAME myArray2
+#endif
+
+#define FTS_TS_DRV_NAME "fts"
+#define FTS_TS_DRV_VERSION "4.1.0"
+
+#define X_AXIS_MAX 1440
+#define X_AXIS_MIN 0
+#define Y_AXIS_MAX 2560
+#define Y_AXIS_MIN 0
+
+#define PRESSURE_MIN 0
+#define PRESSURE_MAX 127
+
+#define FINGER_MAX 10
+#define STYLUS_MAX 1
+#define TOUCH_ID_MAX (FINGER_MAX + STYLUS_MAX)
+
+#define AREA_MIN PRESSURE_MIN
+#define AREA_MAX PRESSURE_MAX
+
+/*********************************************************/
+
+/* Flash programming */
+
+#define INIT_FLAG_CNT 3
+
+/* KEYS */
+#define KEY1 0x02
+#define KEY2 0x01
+#define KEY3 0x04
+
+/*
+ * Configuration mode
+ */
+#define MODE_NORMAL 0
+#define MODE_GESTURE 1
+#define MODE_GLOVE 2
+#define MODE_SENSEOFF 3
+
+/*
+ * Status Event Field:
+ * id of command that triggered the event
+ */
+
+#define FTS_FLASH_WRITE_CONFIG 0x03
+#define FTS_FLASH_WRITE_COMP_MEMORY 0x04
+#define FTS_FORCE_CAL_SELF_MUTUAL 0x05
+#define FTS_FORCE_CAL_SELF 0x06
+#define FTS_WATER_MODE_ON 0x07
+#define FTS_WATER_MODE_OFF 0x08
+
+#define EXP_FN_WORK_DELAY_MS 1000
+
+#define CMD_STR_LEN 32
+
+#ifdef SCRIPTLESS
+/*
+ * I2C Command Read/Write Function
+ */
+
+#define CMD_RESULT_STR_LEN 2048
+#endif
+
+#define TSP_BUF_SIZE 4096
+
+struct fts_i2c_platform_data {
+ int (*power)(bool on);
+ int irq_gpio;
+ int reset_gpio;
+ const char *pwr_reg_name;
+ const char *bus_reg_name;
+
+};
+
+/*
+ * Forward declaration
+ */
+struct fts_ts_info;
+extern char tag[8];
+
+/*
+ * Dispatch event handler
+ */
+typedef unsigned char * (*event_dispatch_handler_t)
+(struct fts_ts_info *info, unsigned char *data);
+
+/*
+ * struct fts_ts_info - FTS capacitive touch screen device information
+ * @dev: Pointer to the structure device
+ * @client: I2C client structure
+ * @input_dev Input device structure
+ * @work Work thread
+ * @event_wq Event queue for work thread
+ * @cmd_done Asyncronous command notification
+ * @event_dispatch_table Event dispatch table handlers
+ * @fw_version Firmware version
+ * @attrs SysFS attributes
+ * @mode Device operating mode
+ * @touch_id Bitmask for touch id (mapped to input slots)
+ * @buttons Bitmask for buttons status
+ * @timer Timer when operating in polling mode
+ * @early_suspend Structure for early suspend functions
+ * @power Power on/off routine
+ */
+
+struct fts_ts_info {
+ struct device *dev;
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+
+ struct work_struct work;
+ struct workqueue_struct *event_wq;
+
+ struct delayed_work fwu_work;
+ struct workqueue_struct *fwu_workqueue;
+ struct completion cmd_done;
+
+ event_dispatch_handler_t *event_dispatch_table;
+
+ unsigned int fw_version;
+ unsigned int config_id;
+
+ struct attribute_group attrs;
+
+ unsigned int mode;
+ unsigned long touch_id;
+ unsigned int buttons;
+
+#ifdef FTS_USE_POLLING_MODE
+ struct hrtimer timer;
+#endif
+
+#ifdef SCRIPTLESS
+ /*I2C cmd*/
+ struct device *i2c_cmd_dev;
+ char cmd_read_result[CMD_RESULT_STR_LEN];
+ char cmd_wr_result[CMD_RESULT_STR_LEN];
+ char cmd_write_result[20];
+#endif
+
+#ifdef DRIVER_TEST
+ struct device *test_cmd_dev;
+#endif
+
+ int (*power)(bool on);
+
+ struct fts_i2c_platform_data *bdata;
+ struct regulator *pwr_reg;
+ struct regulator *bus_reg;
+
+ bool fw_force;
+ int debug_enable;
+
+ int resume_bit;
+ int fwupdate_stat;
+ int touch_debug;
+
+ struct notifier_block notifier;
+ bool sensor_sleep;
+ bool stay_awake;
+
+ /* input lock */
+ struct mutex input_report_mutex;
+
+ /* switches */
+ int gesture_enabled;
+ int glove_enabled;
+
+};
+
+typedef enum {
+ ERR_ITO_NO_ERR, /* < 0 No ITO Error */
+ ERR_ITO_PANEL_OPEN_FORCE, /* < 1 Panel Open Force */
+ ERR_ITO_PANEL_OPEN_SENSE, /* < 2 Panel Open Sense */
+ ERR_ITO_F2G, /* < 3 Force short to ground */
+ ERR_ITO_S2G, /* < 4 Sense short to ground */
+ ERR_ITO_F2VDD, /* < 5 Force short to VDD */
+ ERR_ITO_S2VDD, /* < 6 Sense short to VDD */
+ ERR_ITO_P2P_FORCE, /* < 7 Pin to Pin short (Force) */
+ ERR_ITO_P2P_SENSE, /* < 8 Pin to Pin short (Sense) */
+} errItoSubTypes_t;
+
+int fts_chip_powercycle(struct fts_ts_info *info);
+int fts_chip_powercycle2(struct fts_ts_info *info, unsigned long sleep);
+int fts_get_fw_version(struct fts_ts_info *info);
+extern unsigned int le_to_uint(const unsigned char *ptr);
+extern unsigned int be_to_uint(const unsigned char *ptr);
+extern int input_register_notifier_client(struct notifier_block *nb);
+extern int input_unregister_notifier_client(struct notifier_block *nb);
+
+#ifdef SCRIPTLESS
+extern struct attribute_group i2c_cmd_attr_group;
+#endif
+
+#ifdef DRIVER_TEST
+extern struct attribute_group test_cmd_attr_group;
+#endif
+
+#endif
diff --git a/drivers/input/touchscreen/st/fts_driver_test.c b/drivers/input/touchscreen/st/fts_driver_test.c
new file mode 100644
index 000000000000..5c55d8e4ac88
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_driver_test.c
@@ -0,0 +1,871 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* API used by Driver Test Apk *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/completion.h>
+
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include "fts.h"
+#include "fts_lib/ftsCompensation.h"
+#include "fts_lib/ftsIO.h"
+#include "fts_lib/ftsError.h"
+#include "fts_lib/ftsFrame.h"
+#include "fts_lib/ftsFlash.h"
+#include "fts_lib/ftsTest.h"
+#include "fts_lib/ftsTime.h"
+#include "fts_lib/ftsTool.h"
+
+#ifdef DRIVER_TEST
+
+#define MAX_PARAMS 10
+
+/* DEFINE COMMANDS TO TEST */
+#define CMD_READ 0x00
+#define CMD_WRITE 0x01
+#define CMD_READU16 0x02
+#define CMD_READB2 0x03
+#define CMD_READB2U16 0x04
+#define CMD_POLLFOREVENT 0x05
+#define CMD_SYSTEMRESET 0x06
+#define CMD_CLEANUP 0x07
+#define CMD_GETFORCELEN 0x08
+#define CMD_GETSENSELEN 0x09
+#define CMD_GETMSFRAME 0x0A
+/* #define CMD_GETMSKEYFRAME 0x0B */
+#define CMD_GETSSFRAME 0x0C
+#define CMD_REQCOMPDATA 0x0D
+#define CMD_READCOMPDATAHEAD 0x0E
+#define CMD_READMSCOMPDATA 0x0F
+#define CMD_READSSCOMPDATA 0x10
+#define CMD_READGNCOMPDATA 0x11
+#define CMD_GETFWVER 0x12
+#define CMD_FLASHSTATUS 0x13
+#define CMD_FLASHUNLOCK 0x14
+#define CMD_READFWFILE 0x15
+#define CMD_FLASHPROCEDURE 0x16
+#define CMD_ITOTEST 0x17
+#define CMD_INITTEST 0x18
+#define CMD_MSRAWTEST 0x19
+#define CMD_MSINITDATATEST 0x1A
+#define CMD_SSRAWTEST 0x1B
+#define CMD_SSINITDATATEST 0x1C
+#define CMD_MAINTEST 0x1D
+#define CMD_POWERCYCLE 0x1E
+#define CMD_FWWRITE 0x1F
+#define CMD_READCHIPINFO 0x20
+#define CMD_REQFRAME 0x21
+
+u32 *functionToTest;
+int numberParam;
+
+static ssize_t stm_driver_test_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count) {
+ int n;
+ char *p = (char *) buf;
+
+ functionToTest = (u32 *) kmalloc(MAX_PARAMS * sizeof (u32), GFP_KERNEL);
+ if (functionToTest == NULL) {
+ logError(1, "%s impossible to allocate functionToTest!\n", tag);
+ return count;
+ }
+ memset(functionToTest, 0, MAX_PARAMS * sizeof (u32));
+
+ for (n = 0; n < (count + 1) / 3 && n < MAX_PARAMS; n++) {
+ sscanf(p, "%02X ", &functionToTest[n]);
+ p += 3;
+ logError(1, "%s functionToTest[%d] = %02X\n", tag, n, functionToTest[n]);
+
+ }
+
+ numberParam = n;
+ logError(1, "%s Number of Parameters = %d\n", tag, numberParam);
+ return count;
+}
+
+static ssize_t stm_driver_test_show(struct device *dev, struct device_attribute *attr,
+ char *buf) {
+ char buff[CMD_STR_LEN] = {0};
+ int res = -1, j, count;
+ /* int res2; */
+ int size = 6 * 2;
+ int temp, i, byteToRead;
+ u8 *readData = NULL;
+ u8 *all_strbuff = NULL;
+ u8 *cmd;
+
+ MutualSenseFrame frameMS;
+ SelfSenseFrame frameSS;
+
+ DataHeader dataHead;
+ MutualSenseData compData;
+ SelfSenseData comData;
+ GeneralData gnData;
+
+ u16 address;
+ u16 fw_version;
+ u16 config_id;
+
+ Firmware fw;
+
+ /* struct used for defining which test perform during the MP test */
+
+ TestToDo todoDefault;
+
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+ fw.data = NULL;
+
+ todoDefault.MutualRaw = 1;
+ todoDefault.MutualRawGap = 1;
+ todoDefault.MutualCx1 = 0;
+ todoDefault.MutualCx2 = 1;
+ todoDefault.MutualCx2Adj = 1;
+ todoDefault.MutualCxTotal = 0;
+ todoDefault.MutualCxTotalAdj = 0;
+
+ todoDefault.MutualKeyRaw = 0;
+ todoDefault.MutualKeyCx1 = 0;
+ todoDefault.MutualKeyCx2 = 0;
+ todoDefault.MutualKeyCxTotal = 0;
+
+ todoDefault.SelfForceRaw = 1;
+ todoDefault.SelfForceRawGap = 0;
+ todoDefault.SelfForceIx1 = 0;
+ todoDefault.SelfForceIx2 = 0;
+ todoDefault.SelfForceIx2Adj = 0;
+ todoDefault.SelfForceIxTotal = 1;
+ todoDefault.SelfForceIxTotalAdj = 0;
+ todoDefault.SelfForceCx1 = 0;
+ todoDefault.SelfForceCx2 = 0;
+ todoDefault.SelfForceCx2Adj = 0;
+ todoDefault.SelfForceCxTotal = 0;
+ todoDefault.SelfForceCxTotalAdj = 0;
+
+ todoDefault.SelfSenseRaw = 1;
+ todoDefault.SelfSenseRawGap = 0;
+ todoDefault.SelfSenseIx1 = 0;
+ todoDefault.SelfSenseIx2 = 0;
+ todoDefault.SelfSenseIx2Adj = 0;
+ todoDefault.SelfSenseIxTotal = 1;
+ todoDefault.SelfSenseIxTotalAdj = 0;
+ todoDefault.SelfSenseCx1 = 0;
+ todoDefault.SelfSenseCx2 = 0;
+ todoDefault.SelfSenseCx2Adj = 0;
+ todoDefault.SelfSenseCxTotal = 0;
+ todoDefault.SelfSenseCxTotalAdj = 0;
+
+ if (numberParam >= 1 && functionToTest != NULL) {
+ res = fts_disableInterrupt();
+ if (res < 0) {
+ logError(0, "%s stm_driver_test_show: ERROR %08X\n", tag, res);
+ res = (res | ERROR_DISABLE_INTER);
+ goto END;
+ }
+ switch (functionToTest[0]) {
+ case CMD_READ:
+ if (numberParam >= 4) {
+ temp = (int) functionToTest[1];
+ if (numberParam == 4 + (temp - 1) && temp != 0) {
+ cmd = (u8 *) kmalloc(temp * sizeof (u8), GFP_KERNEL);
+ for (i = 0; i < temp; i++) {
+ cmd[i] = functionToTest[i + 2];
+ }
+ byteToRead = functionToTest[i + 2];
+ readData = (u8 *) kmalloc(byteToRead * sizeof (u8), GFP_KERNEL);
+ res = fts_readCmd(cmd, temp, readData, byteToRead);
+ size += (byteToRead * sizeof (u8))*2;
+ } else {
+ logError(1, "%s Wrong parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_WRITE:
+ if (numberParam >= 3) { /* need to pass: cmdLength cmd[0] cmd[1] … cmd[cmdLength-1] */
+ temp = (int) functionToTest[1];
+ if (numberParam == 3 + (temp - 1) && temp != 0) {
+ cmd = (u8 *) kmalloc(temp * sizeof (u8), GFP_KERNEL);
+ for (i = 0; i < temp; i++) {
+ cmd[i] = functionToTest[i + 2];
+ }
+ res = fts_writeCmd(cmd, temp);
+ } else {
+ logError(1, "%s Wrong parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_FWWRITE:
+ if (numberParam >= 3) { /* need to pass: cmdLength cmd[0] cmd[1] … cmd[cmdLength-1] */
+ temp = (int) functionToTest[1];
+ if (numberParam == 3 + (temp - 1) && temp != 0) {
+ cmd = (u8 *) kmalloc(temp * sizeof (u8), GFP_KERNEL);
+ for (i = 0; i < temp; i++) {
+ cmd[i] = functionToTest[i + 2];
+ }
+ res = fts_writeFwCmd(cmd, temp);
+ } else {
+ logError(1, "%s Wrong parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READU16:
+ if (numberParam == 6) { /* need to pass: cmd addr[0] addr[1] byteToRead hasDummyByte */
+ byteToRead = functionToTest[4];
+ readData = (u8 *) kmalloc(byteToRead * sizeof (u8), GFP_KERNEL);
+ res = readCmdU16((u8) functionToTest[1], (u16) ((((u8) functionToTest[2] & 0x00FF) << 8) + ((u8) functionToTest[3] & 0x00FF)), readData, byteToRead, functionToTest[5]);
+ size += (byteToRead * sizeof (u8))*2;
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READB2:
+ if (numberParam == 4) { /* need to pass: addr[0] addr[1] byteToRead */
+ byteToRead = functionToTest[3];
+ readData = (u8 *) kmalloc(byteToRead * sizeof (u8), GFP_KERNEL);
+ res = readB2((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), readData, byteToRead);
+ size += (byteToRead * sizeof (u8))*2;
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READB2U16:
+ if (numberParam == 4) { /* need to pass: addr[0] addr[1] byteToRead */
+ byteToRead = functionToTest[3];
+ readData = (u8 *) kmalloc(byteToRead * sizeof (u8), GFP_KERNEL);
+ res = readB2U16((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), readData, byteToRead);
+ size += (byteToRead * sizeof (u8))*2;
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_POLLFOREVENT:
+ if (numberParam >= 5) { /* need to pass: eventLength event[0] event[1] event[eventLength-1] timeTowait */
+ temp = (int) functionToTest[1];
+ if (numberParam == 5 + (temp - 1) && temp != 0) {
+ readData = (u8 *) kmalloc(FIFO_EVENT_SIZE * sizeof (u8), GFP_KERNEL);
+ res = pollForEvent((int *) &functionToTest[2], temp, readData, ((functionToTest[temp + 2] & 0x00FF) << 8)+(functionToTest[temp + 3] & 0x00FF));
+ if (res >= OK)
+ res = OK; /* pollForEvent return the number of error found */
+ size += (FIFO_EVENT_SIZE * sizeof (u8))*2;
+ byteToRead = FIFO_EVENT_SIZE;
+ } else {
+ logError(1, "%s Wrong parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_SYSTEMRESET:
+ res = fts_system_reset();
+
+ break;
+
+ case CMD_READCHIPINFO:
+ if (numberParam == 2) { /* need to pass: doRequest */
+ res = readChipInfo(functionToTest[1]);
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ break;
+
+ case CMD_CLEANUP: /* TOUCH ENABLE/DISABLE */
+ if (numberParam == 2) { /* need to pass: enableTouch */
+ res = cleanUp(functionToTest[1]);
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ break;
+
+ case CMD_GETFORCELEN: /* read number Tx channels */
+ temp = getForceLen();
+ if (temp < OK)
+ res = temp;
+ else {
+ size += (1 * sizeof (u8))*2;
+ res = OK;
+ }
+ break;
+
+ case CMD_GETSENSELEN: /* read number Rx channels */
+ temp = getSenseLen();
+ if (temp < OK)
+ res = temp;
+ else {
+ size += (1 * sizeof (u8))*2;
+ res = OK;
+ }
+ break;
+
+ case CMD_REQFRAME: /* request a frame */
+ if (numberParam == 3) {
+ logError(0, "%s Requesting Frame\n", tag);
+ res = requestFrame((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)));
+
+ if (res < OK) {
+ logError(0, "%s Error requesting frame ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s Requesting Frame Finished!\n", tag);
+ }
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_GETMSFRAME:
+ if (numberParam == 3) {
+ logError(0, "%s Get 1 MS Frame\n", tag);
+ flushFIFO(); /* delete the events related to some touch (allow to call this function while touching the sreen without having a flooding of the FIFO) */
+ res = getMSFrame2((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &frameMS);
+ if (res < 0) {
+ logError(0, "%s Error while taking the MS frame... ERROR %02X\n", tag, res);
+
+ } else {
+ logError(0, "%s The frame size is %d words\n", tag, res);
+ size = (res * sizeof (short) + 8)*2;
+ /* set res to OK because if getMSFrame is
+ successful res = number of words read
+ */
+ res = OK;
+ print_frame_short("MS frame =", array1dTo2d_short(frameMS.node_data, frameMS.node_data_size, frameMS.header.sense_node), frameMS.header.force_node, frameMS.header.sense_node);
+ }
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ /*read self raw*/
+ case CMD_GETSSFRAME:
+ if (numberParam == 3) {
+ logError(0, "%s Get 1 SS Frame\n", tag);
+ flushFIFO(); /* delete the events related to some touch (allow to call this function while touching the sreen without having a flooding of the FIFO) */
+ res = getSSFrame2((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &frameSS);
+
+ if (res < OK) {
+ logError(0, "%s Error while taking the SS frame... ERROR %02X\n", tag, res);
+
+ } else {
+ logError(0, "%s The frame size is %d words\n", tag, res);
+ size = (res * sizeof (short) + 8)*2+1;
+ /* set res to OK because if getMSFrame is
+ successful res = number of words read
+ */
+ res = OK;
+ print_frame_short("SS force frame =", array1dTo2d_short(frameSS.force_data, frameSS.header.force_node, 1), frameSS.header.force_node, 1);
+ print_frame_short("SS sense frame =", array1dTo2d_short(frameSS.sense_data, frameSS.header.sense_node, frameSS.header.sense_node), 1, frameSS.header.sense_node);
+ }
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_REQCOMPDATA: /* request comp data */
+ if (numberParam == 3) {
+ logError(0, "%s Requesting Compensation Data\n", tag);
+ res = requestCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)));
+
+ if (res < OK) {
+ logError(0, "%s Error requesting compensation data ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s Requesting Compensation Data Finished!\n", tag);
+ }
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READCOMPDATAHEAD: /* read comp data header */
+ if (numberParam == 3) {
+ logError(0, "%s Requesting Compensation Data\n", tag);
+ res = requestCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)));
+ if (res < OK) {
+ logError(0, "%s Error requesting compensation data ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s Requesting Compensation Data Finished!\n", tag);
+ res = readCompensationDataHeader((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &dataHead, &address);
+ if (res < OK) {
+ logError(0, "%s Read Compensation Data Header ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s Read Compensation Data Header OK!\n", tag);
+ size += (2 * sizeof (u8))*2;
+ }
+ }
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READMSCOMPDATA: /* read mutual comp data */
+ if (numberParam == 3) {
+ logError(0, "%s Get MS Compensation Data\n", tag);
+ res = readMutualSenseCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &compData);
+
+ if (res < OK) {
+ logError(0, "%s Error reading MS compensation data ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s MS Compensation Data Reading Finished!\n", tag);
+ size = ((compData.node_data_size + 9) * sizeof (u8))*2;
+ print_frame_u8("MS Data (Cx2) =", array1dTo2d_u8(compData.node_data, compData.node_data_size, compData.header.sense_node), compData.header.force_node, compData.header.sense_node);
+ }
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READSSCOMPDATA:
+ if (numberParam == 3) { /* read self comp data */
+ logError(0, "%s Get SS Compensation Data...\n", tag);
+ res = readSelfSenseCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &comData);
+ if (res < OK) {
+ logError(0, "%s Error reading SS compensation data ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s SS Compensation Data Reading Finished!\n", tag);
+ size = ((comData.header.force_node + comData.header.sense_node)*2 + 12) * sizeof (u8)*2;
+ print_frame_u8("SS Data Ix2_fm = ", array1dTo2d_u8(comData.ix2_fm, comData.header.force_node, comData.header.force_node), 1, comData.header.force_node);
+ print_frame_u8("SS Data Cx2_fm = ", array1dTo2d_u8(comData.cx2_fm, comData.header.force_node, comData.header.force_node), 1, comData.header.force_node);
+ print_frame_u8("SS Data Ix2_sn = ", array1dTo2d_u8(comData.ix2_sn, comData.header.sense_node, comData.header.sense_node), 1, comData.header.sense_node);
+ print_frame_u8("SS Data Cx2_sn = ", array1dTo2d_u8(comData.cx2_sn, comData.header.sense_node, comData.header.sense_node), 1, comData.header.sense_node);
+ }
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READGNCOMPDATA:
+ if (numberParam == 3) { /* read self comp data */
+ logError(0, "%s Get General Compensation Data...\n", tag);
+ res = readGeneralCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &gnData);
+ if (res < OK) {
+ logError(0, "%s Error reading General compensation data ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s General Compensation Data Reading Finished!\n", tag);
+ size = (14) * sizeof (u8)*2;
+ }
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_GETFWVER:
+ res = getFirmwareVersion(&fw_version, &config_id);
+ if (res < OK) {
+ logError(1, "%s Error reading firmware version and config id ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s getFirmwareVersion Finished!\n", tag);
+ size += (4) * sizeof (u8)*2;
+ }
+ break;
+#ifdef FTM3_CHIP
+ case CMD_FLASHSTATUS:
+ res = flash_status(); /* return 0 = flash ready, 1 = flash busy, <0 error */
+ if (res < OK) {
+ logError(1, "%s Error reading flash status ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s Flash Status: %d\n", tag, res);
+ size += (1 * sizeof (u8))*2;
+ temp = res; /* need to store the value for further display */
+ res = OK; /* set res =ok for returning code */
+ }
+ break;
+#endif
+
+ case CMD_FLASHUNLOCK:
+ res = flash_unlock();
+ if (res < OK) {
+ logError(1, "%s Impossible Unlock Flash ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s Flash Unlock OK!\n", tag);
+ }
+ break;
+
+ case CMD_READFWFILE:
+ if (numberParam == 2) { /* read fw file */
+ logError(0, "%s Reading FW File...\n", tag);
+ res = readFwFile(PATH_FILE_FW, &fw, functionToTest[1]);
+ if (res < OK) {
+ logError(0, "%s Error reading FW File ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s Read FW File Finished!\n", tag);
+ }
+ kfree(fw.data);
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_FLASHPROCEDURE:
+ if (numberParam == 3) { /* flashing procedure */
+ logError(0, "%s Starting Flashing Procedure...\n", tag);
+ res = flashProcedure(PATH_FILE_FW, functionToTest[1], functionToTest[2]);
+ if (res < OK) {
+ logError(0, "%s Error during flash procedure ERROR %02X\n", tag, res);
+ } else {
+ logError(0, "%s Flash Procedure Finished!\n", tag);
+ }
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ /*ITO TEST*/
+ case CMD_ITOTEST:
+ res = production_test_ito();
+ break;
+
+ /*Initialization*/
+ case CMD_INITTEST:
+ if (numberParam == 2) { /* need to specify if if save value on Flash */
+ if (functionToTest[1] == 0x01)
+ res = production_test_initialization();
+ else
+ res = production_test_splited_initialization(false);
+ } else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_MSRAWTEST: /* MS Raw DATA TEST */
+ if (numberParam == 2) /* need to specify if stopOnFail */
+ res = production_test_ms_raw(LIMITS_FILE, functionToTest[1], &todoDefault);
+ else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_MSINITDATATEST: /* MS CX DATA TEST */
+ if (numberParam == 2) /* need to specify if stopOnFail */
+ res = production_test_ms_cx(LIMITS_FILE, functionToTest[1], &todoDefault);
+ else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_SSRAWTEST: /* SS RAW DATA TEST */
+ if (numberParam == 2) /* need to specify if stopOnFail */
+ res = production_test_ss_raw(LIMITS_FILE, functionToTest[1], &todoDefault);
+ else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_SSINITDATATEST: /* SS IX CX DATA TEST */
+ if (numberParam == 2) /* need to specify if stopOnFail */
+ res = production_test_ss_ix_cx(LIMITS_FILE, functionToTest[1], &todoDefault);
+ else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ /*PRODUCTION TEST*/
+ case CMD_MAINTEST:
+ if (numberParam == 3) /* need to specify if stopOnFail and saveInit */
+ res = production_test_main(LIMITS_FILE, functionToTest[1], functionToTest[2], &todoDefault, INIT_FIELD);
+ else {
+ logError(1, "%s Wrong number of parameters!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_POWERCYCLE:
+ res = fts_chip_powercycle(info);
+ break;
+
+ default:
+ logError(1, "%s COMMAND ID NOT VALID!! Inset a value between 00 and 1E..\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ break;
+ }
+
+ /*res2 = fts_enableInterrupt(); enabling the interrupt was disabled on purpose in this node because it can be used for testing procedure and between one step and another the interrupt wan to be kept disabled
+ if (res2 < 0) {
+ logError(0, "%s stm_driver_test_show: ERROR %08X\n", tag, (res2 | ERROR_ENABLE_INTER));
+ }*/
+ } else {
+ logError(1, "%s NO COMMAND SPECIFIED!!! do: 'echo [cmd_code] [args] > stm_fts_cmd' before looking for result!\n", tag);
+ res = ERROR_OP_NOT_ALLOW;
+ functionToTest = NULL;
+ }
+
+END: /* here start the reporting phase, assembling the data to send in the file node */
+ all_strbuff = (u8 *) kmalloc(size, GFP_KERNEL);
+ memset(all_strbuff, 0, size);
+
+ snprintf(buff, sizeof (buff), "%02X", 0xAA);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%08X", res);
+ strlcat(all_strbuff, buff, size);
+
+ if (res >= OK) {
+ /*all the other cases are already fine printing only the res.*/
+ switch (functionToTest[0]) {
+ case CMD_READ:
+ case CMD_READU16:
+ case CMD_READB2:
+ case CMD_READB2U16:
+ case CMD_POLLFOREVENT:
+ for (j = 0; j < byteToRead; j++) {
+ snprintf(buff, sizeof (buff), "%02X", readData[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+ break;
+
+ case CMD_GETFORCELEN:
+ case CMD_GETSENSELEN:
+ case CMD_FLASHSTATUS:
+ snprintf(buff, sizeof (buff), "%02X", (u8) temp);
+ strlcat(all_strbuff, buff, size);
+ break;
+
+ case CMD_GETMSFRAME:
+ snprintf(buff, sizeof (buff), "%02X", (u8) frameMS.header.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", (u8) frameMS.header.sense_node);
+ strlcat(all_strbuff, buff, size);
+
+ for (j = 0; j < frameMS.node_data_size; j++) {
+ snprintf(buff, sizeof (buff), "%04X", frameMS.node_data[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ kfree(frameMS.node_data);
+ break;
+
+ case CMD_GETSSFRAME:
+ snprintf(buff, sizeof (buff), "%02X", (u8) frameSS.header.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", (u8) frameSS.header.sense_node);
+ strlcat(all_strbuff, buff, size);
+
+ /* Copying self raw data Force */
+ for (j = 0; j < frameSS.header.force_node; j++) {
+ snprintf(buff, sizeof (buff), "%04X", frameSS.force_data[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ /* Copying self raw data Sense */
+ for (j = 0; j < frameSS.header.sense_node; j++) {
+ snprintf(buff, sizeof (buff), "%04X", frameSS.sense_data[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ kfree(frameSS.force_data);
+ kfree(frameSS.sense_data);
+ break;
+
+ case CMD_READMSCOMPDATA:
+ snprintf(buff, sizeof (buff), "%02X", (u8) compData.header.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", (u8) compData.header.sense_node);
+ strlcat(all_strbuff, buff, size);
+
+ /* Cpying CX1 value */
+ snprintf(buff, sizeof (buff), "%02X", compData.cx1);
+ strlcat(all_strbuff, buff, size);
+
+ /* Copying CX2 values */
+ for (j = 0; j < compData.node_data_size; j++) {
+ snprintf(buff, sizeof (buff), "%02X", *(compData.node_data + j));
+ strlcat(all_strbuff, buff, size);
+ }
+
+ kfree(compData.node_data);
+ break;
+
+ case CMD_READSSCOMPDATA:
+ snprintf(buff, sizeof (buff), "%02X", comData.header.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", comData.header.sense_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", comData.f_ix1);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", comData.s_ix1);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", comData.f_cx1);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", comData.s_cx1);
+ strlcat(all_strbuff, buff, size);
+
+ /* Copying IX2 Force */
+ for (j = 0; j < comData.header.force_node; j++) {
+ snprintf(buff, sizeof (buff), "%02X", comData.ix2_fm[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ /* Copying IX2 Sense */
+ for (j = 0; j < comData.header.sense_node; j++) {
+ snprintf(buff, sizeof (buff), "%02X", comData.ix2_sn[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ /* Copying CX2 Force */
+ for (j = 0; j < comData.header.force_node; j++) {
+ snprintf(buff, sizeof (buff), "%02X", comData.cx2_fm[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ /* Copying CX2 Sense */
+ for (j = 0; j < comData.header.sense_node; j++) {
+ snprintf(buff, sizeof (buff), "%02X", comData.cx2_sn[j]);
+ strlcat(all_strbuff, buff, size);
+ }
+
+ kfree(comData.ix2_fm);
+ kfree(comData.ix2_sn);
+ kfree(comData.cx2_fm);
+ kfree(comData.cx2_sn);
+ break;
+
+ case CMD_READGNCOMPDATA:
+ snprintf(buff, sizeof (buff), "%02X", gnData.header.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", gnData.header.sense_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", gnData.ftsd_lp_timer_cal0);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", gnData.ftsd_lp_timer_cal1);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", gnData.ftsd_lp_timer_cal2);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", gnData.ftsd_lp_timer_cal3);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", gnData.ftsa_lp_timer_cal0);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", gnData.ftsa_lp_timer_cal1);
+ strlcat(all_strbuff, buff, size);
+ break;
+
+ case CMD_GETFWVER:
+ snprintf(buff, sizeof (buff), "%04X", fw_version);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%04X", config_id);
+ strlcat(all_strbuff, buff, size);
+ break;
+
+ case CMD_READCOMPDATAHEAD:
+ snprintf(buff, sizeof (buff), "%02X", dataHead.force_node);
+ strlcat(all_strbuff, buff, size);
+
+ snprintf(buff, sizeof (buff), "%02X", dataHead.sense_node);
+ strlcat(all_strbuff, buff, size);
+ break;
+
+ default:
+ break;
+
+ }
+ }
+
+ snprintf(buff, sizeof (buff), "%02X", 0xBB);
+ strlcat(all_strbuff, buff, size);
+
+ count = snprintf(buf, TSP_BUF_SIZE, "%s\n", all_strbuff);
+ numberParam = 0; /* need to reset the number of parameters in order to wait the next comand, comment if you want to repeat the last comand sent just doing a cat */
+ /* logError(0,"%s numberParameters = %d\n",tag, numberParam); */
+ kfree(all_strbuff);
+ kfree(functionToTest);
+ return count;
+
+}
+
+/*static DEVICE_ATTR(stm_driver_test, (S_IRWXU|S_IRWXG), stm_driver_test_show, stm_driver_test_store);*/
+static DEVICE_ATTR(stm_driver_test, (S_IRUGO | S_IWUSR | S_IWGRP), stm_driver_test_show, stm_driver_test_store);
+
+static struct attribute *test_cmd_attributes[] = {
+ &dev_attr_stm_driver_test.attr,
+ NULL,
+};
+
+struct attribute_group test_cmd_attr_group = {
+ .attrs = test_cmd_attributes,
+};
+
+#endif
diff --git a/drivers/input/touchscreen/st/fts_fw.h b/drivers/input/touchscreen/st/fts_fw.h
new file mode 100644
index 000000000000..d928a06951ea
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_fw.h
@@ -0,0 +1,10 @@
+#ifndef FTS_FW_H
+#define FTS_FW_H
+/* This is an auto generated header file
+* --->Remember to change the name of the two variables!<--- */
+const uint32_t myArray_size;
+
+const uint8_t myArray[] = {
+};
+
+#endif
diff --git a/drivers/input/touchscreen/st/fts_gui.c b/drivers/input/touchscreen/st/fts_gui.c
new file mode 100644
index 000000000000..f695137ada09
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_gui.c
@@ -0,0 +1,359 @@
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/completion.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include "fts.h"
+#include "fts_lib/ftsCompensation.h"
+#include "fts_lib/ftsIO.h"
+#include "fts_lib/ftsError.h"
+#include "fts_lib/ftsFrame.h"
+#include "fts_lib/ftsTest.h"
+#include "fts_lib/ftsTime.h"
+#include "fts_lib/ftsTool.h"
+
+#ifdef SCRIPTLESS
+
+unsigned int data[CMD_RESULT_STR_LEN] = {0};
+unsigned char pAddress_i2c[CMD_RESULT_STR_LEN] = {0};
+int byte_count_read;
+char Out_buff[TSP_BUF_SIZE];
+
+/*I2C CMd functions: functions to interface with GUI without script */
+
+ssize_t fts_i2c_wr_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+ int i;
+ char buff[16];
+ memset(Out_buff, 0x00, ARRAY_SIZE(Out_buff));
+ if (byte_count_read == 0) {
+ snprintf(Out_buff, sizeof(Out_buff), "{FAILED}");
+ return snprintf(buf, TSP_BUF_SIZE, "{%s}\n", Out_buff);
+ }
+#ifdef SCRIPTLESS_DEBUG
+ printk("%s:DATA READ {", __func__);
+ for (i = 0; i < byte_count_read; i++) {
+ printk(" %02X", (unsigned int)info->cmd_wr_result[i]);
+ if (i < (byte_count_read-1)) {
+ printk(" ");
+ }
+ }
+ printk("}\n");
+#endif
+ snprintf(buff, sizeof(buff), "{");
+ strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
+ for (i = 0; i < (byte_count_read+2); i++) {
+ if ((i == 0)) {
+ char temp_byte_count_read = (byte_count_read >> 8) & 0xFF;
+ snprintf(buff, sizeof(buff), "%02X", temp_byte_count_read);
+ } else if (i == 1) {
+ char temp_byte_count_read = (byte_count_read) & 0xFF;
+ snprintf(buff, sizeof(buff), "%02X", temp_byte_count_read);
+
+ } else {
+ snprintf(buff, sizeof(buff), "%02X", info->cmd_wr_result[i-2]);
+ }
+ /* snprintf(buff, sizeof(buff), "%02X", info->cmd_wr_result[i]); */
+ strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
+ if (i < (byte_count_read+1)) {
+ snprintf(buff, sizeof(buff), " ");
+ strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
+ }
+ }
+ snprintf(buff, sizeof(buff), "}");
+ strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
+ return snprintf(buf, TSP_BUF_SIZE, "%s\n", Out_buff);
+}
+
+ssize_t fts_i2c_wr_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+ unsigned char pAddress[8] = {0};
+ unsigned int byte_count = 0 ;
+ int i ;
+
+ unsigned int data[8] = {0};
+ memset(data, 0x00, ARRAY_SIZE(data));
+ memset(info->cmd_wr_result, 0x00, ARRAY_SIZE(info->cmd_wr_result));
+ sscanf(buf, "%x %x %x %x %x %x %x %x ", (data+7), (data), (data+1),
+ (data+2), (data+3), (data+4), (data+5), (data+6));
+
+ byte_count = data[7];
+
+ /*if (sizeof(buf) != byte_count )
+ {
+ printk("%s : Byte count is wrong\n",__func__);
+ return count;
+ }*/
+#ifdef SCRIPTLESS_DEBUG
+ printk("\n");
+ printk("%s: Input Data 1:", __func__);
+
+ for (i = 0 ; i < 7; i++) {
+ printk(" %02X", data[i]);
+ pAddress[i] = (unsigned char)data[i];
+ }
+ printk("\n");
+#else
+ for (i = 0 ; i < 7; i++) {
+ pAddress[i] = (unsigned char)data[i];
+ }
+#endif
+ byte_count_read = data[byte_count-1];
+ ret = fts_writeCmd(pAddress, 3);
+ msleep(20);
+ ret = fts_readCmd(&pAddress[3], (byte_count-4), info->cmd_wr_result,
+ byte_count_read);
+#ifdef SCRIPTLESS_DEBUG
+ printk("%s:DATA READ\n{", __func__);
+ for (i = 0; i < (2+byte_count_read); i++) {
+ if ((i == 0)) {
+ char temp_byte_count_read = (byte_count_read >> 8) & 0xFF;
+ printk("%02X", (unsigned int)temp_byte_count_read);
+ } else if (i == 1) {
+ char temp_byte_count_read = (byte_count_read) & 0xFF;
+ printk("%02X", (unsigned int)temp_byte_count_read);
+
+ } else {
+ printk("%02X", (unsigned int)info->cmd_read_result[i-2]);
+ }
+ if (i < (byte_count_read+1)) {
+ printk(" ");
+ }
+
+ }
+ printk("}\n");
+#endif
+ if (ret)
+ dev_err(dev, "Unable to read register\n");
+ return count;
+}
+
+ssize_t fts_i2c_read_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+ int i ;
+ char buff[16];
+
+ memset(Out_buff, 0x00, ARRAY_SIZE(Out_buff));
+ if (byte_count_read == 0) {
+ snprintf(Out_buff, sizeof(Out_buff), "{FAILED}");
+ return snprintf(buf, TSP_BUF_SIZE, "{%s}\n", Out_buff);
+ }
+#ifdef SCRIPTLESS_DEBUG
+ printk("%s:DATA READ {", __func__);
+ for (i = 0; i < byte_count_read; i++) {
+ printk("%02X", (unsigned int)info->cmd_read_result[i]);
+ if (i < (byte_count_read-1)) {
+ printk(" ");
+ }
+ }
+ printk("}\n");
+#endif
+ snprintf(buff, sizeof(buff), "{");
+ strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
+ for (i = 0; i < (byte_count_read+2); i++) {
+ if ((i == 0)) {
+ char temp_byte_count_read = (byte_count_read >> 8) & 0xFF;
+ snprintf(buff, sizeof(buff), "%02X", temp_byte_count_read);
+ } else if (i == 1) {
+ char temp_byte_count_read = (byte_count_read) & 0xFF;
+ snprintf(buff, sizeof(buff), "%02X", temp_byte_count_read);
+
+ } else {
+ snprintf(buff, sizeof(buff), "%02X", info->cmd_read_result[i-2]);
+ }
+ strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
+ if (i < (byte_count_read+1)) {
+ snprintf(buff, sizeof(buff), " ");
+ strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
+ }
+ }
+ snprintf(buff, sizeof(buff), "}");
+ strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
+
+ return snprintf(buf, TSP_BUF_SIZE, "%s\n", Out_buff);
+}
+
+ssize_t fts_i2c_read_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+ unsigned char pAddress[8] = {0};
+ unsigned int byte_count = 0;
+ int i ;
+ unsigned int data[8] = {0};
+
+ byte_count_read = 0;
+ memset(data, 0x00, ARRAY_SIZE(data));
+ memset(info->cmd_read_result, 0x00, ARRAY_SIZE(info->cmd_read_result));
+ sscanf(buf, "%x %x %x %x %x %x %x %x ", (data+7), (data), (data+1), (data+2), (data+3), (data+4), (data+5), (data+6));
+ byte_count = data[7];
+
+ if (byte_count > 7) {
+#ifdef SCRIPTLESS_DEBUG
+ printk("%s : Byte count is more than 7\n", __func__);
+#endif
+ return count;
+ }
+ /*if (sizeof(buf) != byte_count )
+ {
+ printk("%s : Byte count is wrong\n",__func__);
+ return count;
+ }*/
+#ifdef SCRIPTLESS_DEBUG
+ printk("\n");
+ printk("%s: Input Data 1:", __func__);
+ for (i = 0 ; i < byte_count; i++) {
+ printk(" %02X", data[i]);
+ pAddress[i] = (unsigned char)data[i];
+ }
+ printk("\n");
+#else
+ for (i = 0 ; i < byte_count; i++) {
+ pAddress[i] = (unsigned char)data[i];
+ }
+#endif
+ byte_count_read = data[byte_count-1];
+ ret = fts_readCmd(pAddress, (byte_count-1), info->cmd_read_result, byte_count_read);
+#ifdef SCRIPTLESS_DEBUG
+ printk("%s:DATA READ\n{", __func__);
+ for (i = 0; i < (byte_count_read+2); i++) {
+ if ((i == 0)) {
+ char temp_byte_count_read = (byte_count_read >> 8) & 0xFF;
+ printk("%02X", (unsigned int)temp_byte_count_read);
+ } else if (i == 1) {
+ char temp_byte_count_read = (byte_count_read) & 0xFF;
+ printk("%02X", (unsigned int)temp_byte_count_read);
+
+ } else {
+ printk("%02X", (unsigned int)info->cmd_read_result[i-2]);
+ }
+ if (i < (byte_count_read+1)) {
+ printk(" ");
+ }
+ }
+ printk("}\n");
+#endif
+ if (ret)
+ dev_err(dev, "Unable to read register\n");
+ return count;
+}
+
+ssize_t fts_i2c_write_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+ return snprintf(buf, TSP_BUF_SIZE, "%s", info->cmd_write_result);
+
+}
+
+ssize_t fts_i2c_write_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+ unsigned int byte_count = 0;
+ int i ;
+ memset(data, 0x00, ARRAY_SIZE(data));
+ memset(pAddress_i2c, 0x00, ARRAY_SIZE(pAddress_i2c));
+ memset(info->cmd_write_result, 0x00, ARRAY_SIZE(info->cmd_write_result));
+ sscanf(buf, "%x %x", data, (data + 1));
+ byte_count = data[0] << 8 | data[1];
+
+ if (byte_count <= ARRAY_SIZE(pAddress_i2c)) {
+ for (i = 0; i < (byte_count); i++) {
+ sscanf(&buf[3*(i+2)], "%x ", (data+i));
+ } } else {
+#ifdef SCRIPTLESS_DEBUG
+ printk("%s : message size is more than allowed limit of 512 bytes\n", __func__);
+#endif
+ snprintf(info->cmd_write_result, sizeof(info->cmd_write_result), "{Write NOT OK}\n");
+ }
+#ifdef SCRIPTLESS_DEBUG
+ printk("\n");
+ printk("%s: Byte_count= %02d | Count = %02d | size of buf:%02d\n", __func__, byte_count, (int)count, (int)sizeof(buf));
+ printk("%s: Input Data 1:", __func__);
+ for (i = 0 ; i < byte_count; i++) {
+ printk("%02X", data[i]);
+ pAddress_i2c[i] = (unsigned char)data[i];
+ }
+ printk("\n");
+#else
+ for (i = 0; i < byte_count; i++) {
+ pAddress_i2c[i] = (unsigned char)data[i];
+ }
+#endif
+ if ((pAddress_i2c[0] == 0xb3) && (pAddress_i2c[3] == 0xb1)) {
+ ret = fts_writeCmd(pAddress_i2c, 3);
+ msleep(20);
+ ret = fts_writeCmd(&pAddress_i2c[3], byte_count-3);
+ } else {
+ ret = fts_writeCmd(pAddress_i2c, byte_count);
+ }
+
+#ifdef SCRIPTLESS_DEBUG
+ printk("%s:DATA :", __func__);
+ for (i = 0; i < byte_count; i++) {
+ printk(" %02X", (unsigned int)pAddress_i2c[i]);
+ }
+ printk(" byte_count: %02X\n", byte_count);
+#endif
+ if (ret < 0) {
+ dev_err(dev, "{Write NOT OK}\n");
+ snprintf(info->cmd_write_result, sizeof(info->cmd_write_result), "{Write NOT OK}\n");
+ } else {
+ snprintf(info->cmd_write_result, sizeof(info->cmd_write_result), "{Write OK}\n");
+#ifdef SCRIPTLESS_DEBUG
+ printk("%s : {Write OK}\n", __func__);
+#endif
+ }
+ return count;
+}
+
+static DEVICE_ATTR(iread, (S_IWUSR|S_IWGRP), NULL, fts_i2c_read_store);
+static DEVICE_ATTR(iread_result, (S_IRUSR|S_IRGRP), fts_i2c_read_show, NULL);
+static DEVICE_ATTR(iwr, (S_IWUSR|S_IWGRP), NULL, fts_i2c_wr_store);
+static DEVICE_ATTR(iwr_result, (S_IRUSR|S_IRGRP), fts_i2c_wr_show, NULL);
+static DEVICE_ATTR(iwrite, (S_IWUSR|S_IWGRP), NULL, fts_i2c_write_store);
+static DEVICE_ATTR(iwrite_result, (S_IRUSR|S_IRGRP), fts_i2c_write_show, NULL);
+
+static struct attribute *i2c_cmd_attributes[] = {
+ &dev_attr_iread.attr,
+ &dev_attr_iread_result.attr,
+ &dev_attr_iwr.attr,
+ &dev_attr_iwr_result.attr,
+ &dev_attr_iwrite.attr,
+ &dev_attr_iwrite_result.attr,
+ NULL,
+};
+
+struct attribute_group i2c_cmd_attr_group = {
+ .attrs = i2c_cmd_attributes,
+};
+
+#endif
diff --git a/drivers/input/touchscreen/st/fts_lib/Makefile b/drivers/input/touchscreen/st/fts_lib/Makefile
new file mode 100644
index 000000000000..24eca48fc3cd
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the FTS touchscreen driver.
+#
+
+obj-$(CONFIG_TOUCHSCREEN_ST_I2C) += ftsCompensation.o \
+ ftsCrossCompile.o ftsError.o ftsFrame.o ftsIO.o ftsTest.o \
+ ftsTime.o ftsTool.o ftsFlash.o ftsGesture.o
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsCompensation.c b/drivers/input/touchscreen/st/fts_lib/ftsCompensation.c
new file mode 100644
index 000000000000..2ca0067f34b0
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsCompensation.c
@@ -0,0 +1,591 @@
+/*
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS functions for getting Initialization Data *
+* *
+**************************************************************************
+**************************************************************************
+*/
+
+#include "ftsCrossCompile.h"
+#include "ftsCompensation.h"
+#include "ftsError.h"
+#include "ftsFrame.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTool.h"
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/time.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+/* #include <linux/sec_sysfs.h> */
+
+static char tag[8] = "[ FTS ]\0";
+
+chipInfo ftsInfo;
+
+int requestCompensationData(u16 type)
+{
+ int retry = 0;
+ int ret;
+ u16 answer;
+
+ int event_to_search[3];
+ u8 readEvent[FIFO_EVENT_SIZE];
+
+ u8 cmd[3] = { FTS_CMD_REQU_COMP_DATA, 0x00, 0x00 };
+ /* B8 is the command for asking compensation data */
+ u16ToU8(type, &cmd[1]);
+
+ event_to_search[0] = (int)EVENTID_COMP_DATA_READ;
+ event_to_search[1] = cmd[1];
+ event_to_search[2] = cmd[2];
+
+ while (retry < COMP_DATA_READ_RETRY) {
+ logError(0, "%s %s", tag, printHex("Command = ", cmd, 3));
+ ret = fts_writeFwCmd(cmd, 3);
+ /* send the request to the chip to load in memory the Compensation Data */
+ if (ret < OK) {
+ logError(1, "%s requestCompensationData: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+ ret = pollForEvent(event_to_search, 3, readEvent, TIMEOUT_REQU_COMP_DATA);
+ if (ret < OK) {
+ logError(0, "%s Event did not Found at %d attemp! \n", tag, retry+1);
+ retry += 1;
+ } else {
+ retry = 0;
+ break;
+ }
+ }
+
+ if (retry == COMP_DATA_READ_RETRY) {
+ logError(1, "%s requestCompensationData: ERROR %02X\n", tag, ERROR_TIMEOUT);
+ return ERROR_TIMEOUT;
+ }
+
+ u8ToU16_le(&readEvent[1], &answer);
+
+ if (answer == type)
+ return OK;
+ logError(1, "%s The event found has a different type of Compensation data ERROR %02X \n", tag, ERROR_DIFF_COMP_TYPE);
+ return ERROR_DIFF_COMP_TYPE;
+
+}
+
+int readCompensationDataHeader(u16 type, DataHeader *header, u16 *address)
+{
+
+ u16 offset = ADDR_FRAMEBUFFER_DATA;
+ u16 answer;
+ u8 data[COMP_DATA_HEADER];
+
+ if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, offset, data, COMP_DATA_HEADER, DUMMY_FRAMEBUFFER) < 0) {
+ logError(1, "%s readCompensationDataHeader: ERROR %02X \n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+ logError(0, "%s Read Data Header done! \n", tag);
+
+ if (data[0] != HEADER_SIGNATURE) {
+ logError(1, "%s readCompensationDataHeader: ERROR %02X The Header Signature was wrong! %02X != %02X \n", tag, ERROR_WRONG_COMP_SIGN, data[0], HEADER_SIGNATURE);
+ return ERROR_WRONG_COMP_SIGN;
+ }
+
+ u8ToU16_le(&data[1], &answer);
+
+ if (answer != type) {
+ logError(1, "%s readCompensationDataHeader: ERROR %02X\n", tag, ERROR_DIFF_COMP_TYPE);
+ return ERROR_DIFF_COMP_TYPE;
+ }
+
+ logError(0, "%s Type of Compensation data OK! \n", tag);
+
+ header->type = type;
+ header->force_node = (int)data[4];
+ header->sense_node = (int)data[5];
+
+ *address = offset + COMP_DATA_HEADER;
+
+ return OK;
+
+}
+
+int readMutualSenseGlobalData(u16 *address, MutualSenseData *global)
+{
+
+ u8 data[COMP_DATA_GLOBAL];
+
+ logError(0, "%s Address for Global data= %02X \n", tag, *address);
+
+ if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, *address, data, COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER) < 0) {
+ logError(1, "%s readMutualSenseGlobalData: ERROR %02X\n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+ logError(0, "%s Global data Read !\n", tag);
+
+ global->tuning_ver = data[0];
+ global->cx1 = data[1];
+
+ logError(0, "%s tuning_ver = %d CX1 = %d \n", tag, global->tuning_ver, global->cx1);
+
+ *address += COMP_DATA_GLOBAL;
+ return OK;
+
+}
+
+int readMutualSenseNodeData(u16 address, MutualSenseData *node)
+{
+
+ int size = node->header.force_node*node->header.sense_node;
+
+ logError(0, "%s Address for Node data = %02X \n", tag, address);
+
+ node->node_data = (u8 *)kmalloc(size*(sizeof(u8)), GFP_KERNEL);
+
+ if (node->node_data == NULL) {
+ logError(1, "%s readMutualSenseNodeData: ERROR %02X", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ logError(0, "%s Node Data to read %d bytes \n", tag, size);
+
+ if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, node->node_data, size, DUMMY_FRAMEBUFFER) < 0) {
+ logError(1, "%s readMutualSenseNodeData: ERROR %02X \n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+ node->node_data_size = size;
+
+ logError(0, "%s Read node data ok! \n", tag);
+
+ return size;
+
+}
+
+int readMutualSenseCompensationData(u16 type, MutualSenseData *data)
+{
+
+ int ret;
+ u16 address;
+
+ if (!(type == MS_TOUCH_ACTIVE || type == MS_TOUCH_LOW_POWER ||
+ type == MS_TOUCH_ULTRA_LOW_POWER || type == MS_KEY)) {
+ logError(1, "%s readMutualSenseCompensationData: Choose a MS type of compensation data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = requestCompensationData(type);
+ if (ret < 0) {
+ logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
+ return (ret|ERROR_REQU_COMP_DATA);
+ }
+
+ ret = readCompensationDataHeader(type, &(data->header), &address);
+ if (ret < 0) {
+ logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
+ return (ret|ERROR_COMP_DATA_HEADER);
+ }
+
+ ret = readMutualSenseGlobalData(&address, data);
+ if (ret < 0) {
+ logError(1, "%s readMutualSenseCompensationData: ERROR %02X \n", tag, ERROR_COMP_DATA_GLOBAL);
+ return (ret|ERROR_COMP_DATA_GLOBAL);
+ }
+
+ ret = readMutualSenseNodeData(address, data);
+ if (ret < 0) {
+ logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_NODE);
+ return (ret|ERROR_COMP_DATA_NODE);
+ }
+
+ return OK;
+
+}
+
+int readSelfSenseGlobalData(u16 *address, SelfSenseData *global)
+{
+
+ u8 data[COMP_DATA_GLOBAL];
+
+ logError(0, "%s Address for Global data= %02X \n", tag, *address);
+
+ if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, *address, data, COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER) < 0) {
+ logError(1, "%s readSelfSenseGlobalData: ERROR %02X \n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+
+ logError(0, "%s Global data Read !\n", tag);
+
+ global->tuning_ver = data[0];
+ global->f_ix1 = data[1];
+ global->s_ix1 = data[2];
+ global->f_cx1 = data[3];
+ global->s_cx1 = data[4];
+ global->f_max_n = data[5];
+ global->s_max_n = data[6];
+
+ logError(0, "%s tuning_ver = %d f_ix1 = %d s_ix1 = %d f_cx1 = %d s_cx1 = %d \n", tag, global->tuning_ver, global->f_ix1, global->s_ix1, global->f_cx1, global->s_cx1);
+ logError(0, "%s max_n = %d s_max_n = %d \n", tag, global->f_max_n, global->s_max_n);
+
+ *address += COMP_DATA_GLOBAL;
+
+ return OK;
+
+}
+
+int readSelfSenseNodeData(u16 address, SelfSenseData *node)
+{
+
+ int size = node->header.force_node*2+node->header.sense_node*2;
+ u8 data[size];
+
+ node->ix2_fm = (u8 *)kmalloc(node->header.force_node*(sizeof(u8)), GFP_KERNEL);
+ node->cx2_fm = (u8 *)kmalloc(node->header.force_node*(sizeof(u8)), GFP_KERNEL);
+ node->ix2_sn = (u8 *)kmalloc(node->header.sense_node*(sizeof(u8)), GFP_KERNEL);
+ node->cx2_sn = (u8 *)kmalloc(node->header.sense_node*(sizeof(u8)), GFP_KERNEL);
+
+ if (node->ix2_fm == NULL || node->cx2_fm == NULL || node->ix2_sn == NULL
+ || node->cx2_sn == NULL) {
+ logError(1, "%s readSelfSenseNodeData: ERROR %02X", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ logError(0, "%s Address for Node data = %02X \n", tag, address);
+
+ logError(0, "%s Node Data to read %d bytes \n", tag, size);
+
+ if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, data, size, DUMMY_FRAMEBUFFER) < 0) {
+ logError(1, "%s readSelfSenseNodeData: ERROR %02X\n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+
+ logError(0, "%s Read node data ok! \n", tag);
+
+ memcpy(node->ix2_fm, data, node->header.force_node);
+ memcpy(node->ix2_sn, &data[node->header.force_node], node->header.sense_node);
+ memcpy(node->cx2_fm, &data[node->header.force_node + node->header.sense_node], node->header.force_node);
+ memcpy(node->cx2_sn, &data[node->header.force_node*2 + node->header.sense_node], node->header.sense_node);
+
+ return OK;
+
+}
+
+int readSelfSenseCompensationData(u16 type, SelfSenseData *data)
+{
+
+ int ret;
+ u16 address;
+
+ if (!(type == SS_TOUCH || type == SS_KEY || type == SS_HOVER || type == SS_PROXIMITY)) {
+ logError(1, "%s readSelfSenseCompensationData: Choose a SS type of compensation data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = requestCompensationData(type);
+ if (ret < 0) {
+ logError(1, "%s readSelfSenseCompensationData: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
+ return (ret|ERROR_REQU_COMP_DATA);
+ }
+
+ ret = readCompensationDataHeader(type, &(data->header), &address);
+ if (ret < 0) {
+ logError(1, "%s readSelfSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
+ return (ret|ERROR_COMP_DATA_HEADER);
+ }
+
+ ret = readSelfSenseGlobalData(&address, data);
+ if (ret < 0) {
+ logError(1, "%s readSelfSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_GLOBAL);
+ return (ret|ERROR_COMP_DATA_GLOBAL);
+ }
+
+ ret = readSelfSenseNodeData(address, data);
+ if (ret < 0) {
+ logError(1, "%s readSelfSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_NODE);
+ return (ret|ERROR_COMP_DATA_NODE);
+ }
+
+ return OK;
+
+}
+
+int readGeneralGlobalData(u16 address, GeneralData *global)
+{
+ u8 data[COMP_DATA_GLOBAL];
+
+ if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, data, COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER) < 0) {
+ logError(1, "%s readGeneralGlobalData: ERROR %02X \n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+
+ global->ftsd_lp_timer_cal0 = data[0];
+ global->ftsd_lp_timer_cal1 = data[1];
+ global->ftsd_lp_timer_cal2 = data[2];
+ global->ftsd_lp_timer_cal3 = data[3];
+ global->ftsa_lp_timer_cal0 = data[4];
+ global->ftsa_lp_timer_cal1 = data[5];
+
+ return OK;
+
+}
+
+int readGeneralCompensationData(u16 type, GeneralData *data)
+{
+
+ int ret;
+ u16 address;
+
+ if (!(type == GENERAL_TUNING)) {
+ logError(1, "%s readGeneralCompensationData: Choose a GENERAL type of compensation data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = requestCompensationData(type);
+ if (ret < 0) {
+ logError(1, "%s readGeneralCompensationData: ERROR %02X \n", tag, ERROR_REQU_COMP_DATA);
+ return ERROR_REQU_COMP_DATA;
+ }
+
+ ret = readCompensationDataHeader(type, &(data->header), &address);
+ if (ret < 0) {
+ logError(1, "%s readGeneralCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
+ return ERROR_COMP_DATA_HEADER;
+ }
+
+ ret = readGeneralGlobalData(address, data);
+ if (ret < 0) {
+ logError(1, "%s readGeneralCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_GLOBAL);
+ return ERROR_COMP_DATA_GLOBAL;
+ }
+
+ return OK;
+
+}
+
+int defaultChipInfo(int i2cError)
+{
+ int i;
+ logError(0, "%s Setting default Chip Info... \n", tag);
+ ftsInfo.u32_echoEn = 0x00000000;
+ ftsInfo.u8_msScrConfigTuneVer = 0;
+ ftsInfo.u8_ssTchConfigTuneVer = 0;
+ ftsInfo.u8_msScrCxmemTuneVer = 0;
+ ftsInfo.u8_ssTchCxmemTuneVer = 0;
+ if (i2cError == 1) {
+ ftsInfo.u16_fwVer = 0xFFFF;
+ ftsInfo.u16_cfgId = 0xFFFF;
+ for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
+ ftsInfo.u8_extReleaseInfo[i] = 0xFF;
+ }
+ } else {
+ ftsInfo.u16_fwVer = 0x0000;
+ ftsInfo.u16_cfgId = 0x0000;
+ for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
+ ftsInfo.u8_extReleaseInfo[i] = 0x00;
+ }
+ }
+ ftsInfo.u32_mpPassFlag = INIT_FIELD;
+ logError(0, "%s default Chip Info DONE! \n", tag);
+ return OK;
+
+}
+
+int readChipInfo(int doRequest)
+{
+ int ret, i;
+ u16 answer;
+ u8 data[CHIP_INFO_SIZE+3];
+ /* +3 because need to read all the field of the struct plus the signature and 2 address bytes */
+ int index = 0;
+
+ logError(0, "%s Starting Read Chip Info... \n", tag);
+ if (doRequest == 1) {
+ ret = requestCompensationData(CHIP_INFO);
+ if (ret < 0) {
+ logError(1, "%s readChipInfo: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
+ ret = (ret | ERROR_REQU_COMP_DATA);
+ goto FAIL;
+ }
+ }
+
+ logError(0, "%s Byte to read = %d bytes \n", tag, CHIP_INFO_SIZE+3);
+
+ if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, ADDR_FRAMEBUFFER_DATA, data, CHIP_INFO_SIZE+3, DUMMY_FRAMEBUFFER) < 0) {
+ logError(1, "%s readChipInfo: ERROR %02X\n", tag, ERROR_I2C_R);
+ ret = ERROR_I2C_R;
+ goto FAIL;
+ }
+
+ logError(0, "%s Read data ok! \n", tag);
+
+ logError(0, "%s Starting parsing of data... \n", tag);
+
+ if (data[0] != HEADER_SIGNATURE) {
+ logError(1, "%s readChipInfo: ERROR %02X The Header Signature was wrong! %02X != %02X \n", tag, ERROR_WRONG_COMP_SIGN, data[0], HEADER_SIGNATURE);
+ ret = ERROR_WRONG_COMP_SIGN;
+ goto FAIL;
+ }
+
+ u8ToU16_le(&data[1], &answer);
+
+ if (answer != CHIP_INFO) {
+ logError(1, "%s readChipInfo: ERROR %02X\n", tag, ERROR_DIFF_COMP_TYPE);
+ ret = ERROR_DIFF_COMP_TYPE;
+ goto FAIL;
+ }
+
+ index += 3;
+ ftsInfo.u8_loadCnt = data[index++];
+ ftsInfo.u8_infoVer = data[index++];
+ u8ToU16(&data[index], &ftsInfo.u16_ftsdId);
+ index += 2;
+ ftsInfo.u8_ftsdVer = data[index++];
+ ftsInfo.u8_ftsaId = data[index++];
+ ftsInfo.u8_ftsaVer = data[index++];
+ ftsInfo.u8_tchRptVer = data[index++];
+
+ logError(1, "%s External Release = ", tag);
+ for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
+ ftsInfo.u8_extReleaseInfo[i] = data[index++];
+ logError(1, "%02X ", ftsInfo.u8_extReleaseInfo[i]);
+ }
+ logError(1, "\n");
+
+ for (i = 0; i < sizeof(ftsInfo.u8_custInfo); i++) {
+ ftsInfo.u8_custInfo[i] = data[index++];
+ }
+
+ u8ToU16(&data[index], &ftsInfo.u16_fwVer);
+ index += 2;
+ logError(1, "%s FW VERSION = %04X \n", tag, ftsInfo.u16_fwVer);
+
+ u8ToU16(&data[index], &ftsInfo.u16_cfgId);
+ index += 2;
+ logError(1, "%s CONFIG ID = %04X \n", tag, ftsInfo.u16_cfgId);
+
+ ftsInfo.u32_projId = ((data[index + 3] & 0x000000FF) << 24) + ((data[index + 2] & 0x000000FF) << 16) + ((data[index + 1] & 0x000000FF) << 8) + (data[index] & 0x000000FF);
+ index += 4;
+
+ u8ToU16(&data[index], &ftsInfo.u16_scrXRes);
+ index += 2;
+
+ u8ToU16(&data[index], &ftsInfo.u16_scrYRes);
+ index += 2;
+
+ ftsInfo.u8_scrForceLen = data[index++];
+ logError(1, "%s Force Len = %d \n", tag, ftsInfo.u8_scrForceLen);
+
+ ftsInfo.u8_scrSenseLen = data[index++];
+ logError(1, "%s Sense Len = %d \n", tag, ftsInfo.u8_scrSenseLen);
+
+ for (i = 0; i < 8; i++) {
+ ftsInfo.u64_scrForceEn[i] = data[index++];
+ }
+
+ for (i = 0; i < 8; i++) {
+ ftsInfo.u64_scrSenseEn[i] = data[index++];
+ }
+
+ ftsInfo.u8_msKeyLen = data[index++];
+ logError(1, "%s MS Key Len = %d \n", tag, ftsInfo.u8_msKeyLen);
+
+ for (i = 0; i < 8; i++) {
+ ftsInfo.u64_msKeyForceEn[i] = data[index++];
+ }
+
+ for (i = 0; i < 8; i++) {
+ ftsInfo.u64_msKeySenseEn[i] = data[index++];
+ }
+
+ ftsInfo.u8_ssKeyLen = data[index++];
+ logError(1, "%s SS Key Len = %d \n", tag, ftsInfo.u8_ssKeyLen);
+
+ for (i = 0; i < 8; i++) {
+ ftsInfo.u64_ssKeyForceEn[i] = data[index++];
+ }
+
+ for (i = 0; i < 8; i++) {
+ ftsInfo.u64_ssKeySenseEn[i] = data[index++];
+ }
+
+ ftsInfo.u8_frcTchXLen = data[index++];
+
+ ftsInfo.u8_frcTchYLen = data[index++];
+
+ for (i = 0; i < 8; i++) {
+ ftsInfo.u64_frcTchForceEn[i] = data[index++];
+ }
+
+ for (i = 0; i < 8; i++) {
+ ftsInfo.u64_frcTchSenseEn[i] = data[index++];
+ }
+
+ ftsInfo.u8_msScrConfigTuneVer = data[index++];
+ logError(1, "%s CFG MS TUNING VERSION = %02X \n", tag, ftsInfo.u8_msScrConfigTuneVer);
+ ftsInfo.u8_msScrLpConfigTuneVer = data[index++];
+ ftsInfo.u8_msScrHwulpConfigTuneVer = data[index++];
+ ftsInfo.u8_msKeyConfigTuneVer = data[index++];
+ ftsInfo.u8_ssTchConfigTuneVer = data[index++];
+ logError(1, "%s CFG SS TUNING VERSION = %02X \n", tag, ftsInfo.u8_ssTchConfigTuneVer);
+ ftsInfo.u8_ssKeyConfigTuneVer = data[index++];
+ ftsInfo.u8_ssHvrConfigTuneVer = data[index++];
+ ftsInfo.u8_frcTchConfigTuneVer = data[index++];
+ ftsInfo.u8_msScrCxmemTuneVer = data[index++];
+ logError(1, "%s CX MS TUNING VERSION = %02X \n", tag, ftsInfo.u8_msScrCxmemTuneVer);
+ ftsInfo.u8_msScrLpCxmemTuneVer = data[index++];
+ ftsInfo.u8_msScrHwulpCxmemTuneVer = data[index++];
+ ftsInfo.u8_msKeyCxmemTuneVer = data[index++];
+ ftsInfo.u8_ssTchCxmemTuneVer = data[index++];
+ logError(1, "%s CX SS TUNING VERSION = %02X \n", tag, ftsInfo.u8_ssTchCxmemTuneVer);
+ ftsInfo.u8_ssKeyCxmemTuneVer = data[index++];
+ ftsInfo.u8_ssHvrCxmemTuneVer = data[index++];
+ ftsInfo.u8_frcTchCxmemTuneVer = data[index++];
+ ftsInfo.u32_mpPassFlag = ((data[index + 3] & 0x000000FF) << 24) + ((data[index + 2] & 0x000000FF) << 16) + ((data[index + 1] & 0x000000FF) << 8) + (data[index] & 0x000000FF);
+ index += 4;
+ logError(1, "%s MP SIGNATURE = %08X \n", tag, ftsInfo.u32_mpPassFlag);
+ ftsInfo.u32_featEn = ((data[index + 3] & 0x000000FF) << 24) + ((data[index + 2] & 0x000000FF) << 16) + ((data[index + 1] & 0x000000FF) << 8) + (data[index] & 0x000000FF);
+ index += 4;
+ ftsInfo.u32_echoEn = ((data[index + 3] & 0x000000FF) << 24) + ((data[index + 2] & 0x000000FF) << 16) + ((data[index + 1] & 0x000000FF) << 8) + (data[index] & 0x000000FF);
+ index += 4;
+ logError(1, "%s FEATURES = %08X \n", tag, ftsInfo.u32_echoEn);
+
+ logError(1, "%s Parsed %d bytes! \n", tag, index);
+
+ if (index != CHIP_INFO_SIZE + 3) {
+ logError(1, "%s readChipInfo: index = %d different from %d ERROR %02X\n", tag, index, CHIP_INFO_SIZE+3, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ logError(1, "%s Chip Info Read DONE!\n", tag);
+ return OK;
+
+FAIL:
+ defaultChipInfo(isI2cError(ret));
+ return ret;
+
+}
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsCompensation.h b/drivers/input/touchscreen/st/fts_lib/ftsCompensation.h
new file mode 100644
index 000000000000..c4cc5913fc18
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsCompensation.h
@@ -0,0 +1,146 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS functions for getting Initialization Data *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsCrossCompile.h"
+#include "ftsSoftware.h"
+
+#define COMP_DATA_READ_RETRY 2
+
+/* Bytes dimension of Compensation Data Format */
+
+#define COMP_DATA_HEADER 8
+#define COMP_DATA_GLOBAL 8
+
+#define HEADER_SIGNATURE 0xA5
+
+/* Possible Compensation/Frame Data Type */
+#define GENERAL_TUNING 0x0100
+#define MS_TOUCH_ACTIVE 0x0200
+#define MS_TOUCH_LOW_POWER 0x0400
+#define MS_TOUCH_ULTRA_LOW_POWER 0x0800
+#define MS_KEY 0x1000
+#define SS_TOUCH 0x2000
+#define SS_KEY 0x4000
+#define SS_HOVER 0x8000
+#define SS_PROXIMITY 0x0001
+#define CHIP_INFO 0xFFFF
+
+#define TIMEOUT_REQU_COMP_DATA 1000 /* ms */
+
+/* CHIP INFO */
+#define CHIP_INFO_SIZE 138/* bytes to read from framebuffer (exclude the signature and the type because already checked during the reading) */
+#define EXTERNAL_RELEASE_INFO_SIZE 8/* bytes */
+
+typedef struct {
+ int force_node, sense_node;
+ u16 type;
+} DataHeader;
+
+typedef struct {
+ DataHeader header;
+ u8 tuning_ver;
+ u8 cx1;
+ u8 *node_data;
+ int node_data_size;
+} MutualSenseData;
+
+typedef struct {
+ DataHeader header;
+ u8 tuning_ver;
+ u8 f_ix1, s_ix1;
+ u8 f_cx1, s_cx1;
+ u8 f_max_n, s_max_n;
+
+ u8 *ix2_fm;
+ u8 *ix2_sn;
+ u8 *cx2_fm;
+ u8 *cx2_sn;
+
+} SelfSenseData;
+
+typedef struct {
+ DataHeader header;
+ u8 ftsd_lp_timer_cal0;
+ u8 ftsd_lp_timer_cal1;
+ u8 ftsd_lp_timer_cal2;
+
+ u8 ftsd_lp_timer_cal3;
+ u8 ftsa_lp_timer_cal0;
+ u8 ftsa_lp_timer_cal1;
+
+} GeneralData;
+
+typedef struct {
+ u8 u8_loadCnt; /* 03 - Load Counter */
+ u8 u8_infoVer; /* 04 - New chip info version */
+ u16 u16_ftsdId; /* 05 - FTSD ID */
+ u8 u8_ftsdVer; /* 07 - FTSD version */
+ u8 u8_ftsaId; /* 08 - FTSA ID */
+ u8 u8_ftsaVer; /* 09 - FTSA version */
+ u8 u8_tchRptVer; /* 0A - Touch report version (e.g. ST, Samsung etc) */
+ u8 u8_extReleaseInfo[EXTERNAL_RELEASE_INFO_SIZE]; /* 0B - External release information */
+ u8 u8_custInfo[12]; /* 13 - Customer information */
+ u16 u16_fwVer; /* 1F - Firmware version */
+ u16 u16_cfgId; /* 21 - Configuration ID */
+ u32 u32_projId; /* 23 - Project ID */
+ u16 u16_scrXRes; /* 27 - X resolution on main screen */
+ u16 u16_scrYRes; /* 29 - Y resolution on main screen */
+ u8 u8_scrForceLen; /* 2B - Number of force channel on main screen */
+ u8 u8_scrSenseLen; /* 2C - Number of sense channel on main screen */
+ u8 u64_scrForceEn[8]; /* 2D - Force channel enabled on main screen */
+ u8 u64_scrSenseEn[8]; /* 35 - Sense channel enabled on main screen */
+ u8 u8_msKeyLen; /* 3D - Number of MS Key channel */
+ u8 u64_msKeyForceEn[8]; /* 3E - MS Key force channel enable */
+ u8 u64_msKeySenseEn[8]; /* 46 - MS Key sense channel enable */
+ u8 u8_ssKeyLen; /* 4E - Number of SS Key channel */
+ u8 u64_ssKeyForceEn[8]; /* 4F - SS Key force channel enable */
+ u8 u64_ssKeySenseEn[8]; /* 57 - SS Key sense channel enable */
+ u8 u8_frcTchXLen; /* 5F - Number of force touch force channel */
+ u8 u8_frcTchYLen; /* 60 - Number of force touch sense channel */
+ u8 u64_frcTchForceEn[8]; /* 61 - Force touch force channel enable */
+ u8 u64_frcTchSenseEn[8]; /* 69 - Force touch sense channel enable */
+ u8 u8_msScrConfigTuneVer; /* 71 - MS screen tuning version in config */
+ u8 u8_msScrLpConfigTuneVer; /* 72 - MS screen LP mode tuning version in config */
+ u8 u8_msScrHwulpConfigTuneVer; /* 73 - MS screen ultra low power mode tuning version in config */
+ u8 u8_msKeyConfigTuneVer; /* 74 - MS Key tuning version in config */
+ u8 u8_ssTchConfigTuneVer; /* 75 - SS touch tuning version in config */
+ u8 u8_ssKeyConfigTuneVer; /* 76 - SS Key tuning version in config */
+ u8 u8_ssHvrConfigTuneVer; /* 77 - SS hover tuning version in config */
+ u8 u8_frcTchConfigTuneVer; /* 78 - Force touch tuning version in config */
+ u8 u8_msScrCxmemTuneVer; /* 79 - MS screen tuning version in cxmem */
+ u8 u8_msScrLpCxmemTuneVer; /* 7A - MS screen LP mode tuning version in cxmem */
+ u8 u8_msScrHwulpCxmemTuneVer; /* 7B - MS screen ultra low power mode tuning version in cxmem */
+ u8 u8_msKeyCxmemTuneVer; /* 7C - MS Key tuning version in cxmem */
+ u8 u8_ssTchCxmemTuneVer; /* 7D - SS touch tuning version in cxmem */
+ u8 u8_ssKeyCxmemTuneVer; /* 7E - SS Key tuning version in cxmem */
+ u8 u8_ssHvrCxmemTuneVer; /* 7F - SS hover tuning version in cxmem */
+ u8 u8_frcTchCxmemTuneVer; /* 80 - Force touch tuning version in cxmem */
+ u32 u32_mpPassFlag; /* 81 - Mass production pass flag */
+ u32 u32_featEn; /* 85 - Supported features */
+ u32 u32_echoEn; /* 89 - enable of particular features: first bit is Echo Enables */
+} chipInfo;
+
+int requestCompensationData(u16 type);
+int readCompensationDataHeader(u16 type, DataHeader *header, u16 *address);
+int readMutualSenseGlobalData(u16 *address, MutualSenseData *global);
+int readMutualSenseNodeData(u16 address, MutualSenseData *node);
+int readMutualSenseCompensationData(u16 type, MutualSenseData *data);
+int readSelfSenseGlobalData(u16 *address, SelfSenseData *global);
+int readSelfSenseNodeData(u16 address, SelfSenseData *node);
+int readSelfSenseCompensationData(u16 type, SelfSenseData *data);
+int readGeneralGlobalData(u16 address, GeneralData *global);
+int readGeneralCompensationData(u16 type, GeneralData *data);
+int defaultChipInfo(int i2cError);
+int readChipInfo(int doRequest);
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsCrossCompile.c b/drivers/input/touchscreen/st/fts_lib/ftsCrossCompile.c
new file mode 100644
index 000000000000..502dace75e4f
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsCrossCompile.c
@@ -0,0 +1,43 @@
+#include "ftsCrossCompile.h"
+#include "ftsError.h"
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+/* #include <linux/sec_sysfs.h> */
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/spi/spidev.h>
+#include <linux/fcntl.h>
+#include <linux/syscalls.h>
+
+/* static char tag[8]="[ FTS ]\0"; */
+void *stmalloc(size_t size)
+{
+ return kmalloc(size, GFP_KERNEL);
+
+}
+
+void stfree(void *ptr)
+{
+ kfree(ptr);
+}
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsCrossCompile.h b/drivers/input/touchscreen/st/fts_lib/ftsCrossCompile.h
new file mode 100644
index 000000000000..8b287dd342f8
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsCrossCompile.h
@@ -0,0 +1,34 @@
+/* #define NDK */
+/* #define DEBUG */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+/* #include <linux/sec_sysfs.h> */
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/spi/spidev.h>
+#include <linux/fcntl.h>
+#include <linux/syscalls.h>
+
+void *stmalloc(size_t size);
+void stfree(void *ptr);
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsError.c b/drivers/input/touchscreen/st/fts_lib/ftsError.c
new file mode 100644
index 000000000000..844e5019fec6
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsError.c
@@ -0,0 +1,105 @@
+/*
+***************************************************************************
+* STMicroelectronics
+**************************************************************************
+* marco.cali@st.com
+**************************************************************************
+*
+* FTS error/info kernel log reporting
+*
+**************************************************************************
+**************************************************************************
+*/
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/completion.h>
+
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+
+#include "../fts.h"
+#include "ftsCrossCompile.h"
+#include "ftsError.h"
+#include "ftsIO.h"
+#include "ftsTool.h"
+
+void logError(int force, const char *msg, ...)
+{
+ if (force == 1
+#ifdef DEBUG
+ || 1
+#endif
+ ) {
+ va_list args;
+ va_start(args, msg);
+ vprintk(msg, args);
+ va_end(args);
+ }
+}
+
+int isI2cError(int error)
+{
+ if (((error & 0x000000FF) >= (ERROR_I2C_R & 0x000000FF)) && ((error & 0x000000FF) <= (ERROR_I2C_O & 0x000000FF)))
+ return 1;
+ else
+ return 0;
+}
+
+int errorHandler(u8 *event, int size)
+{
+ int res = OK;
+ struct fts_ts_info *info = NULL;
+
+ if (getClient() != NULL)
+ info = i2c_get_clientdata(getClient());
+
+ if (info != NULL && event != NULL && size > 1 && event[0] == EVENTID_ERROR_EVENT) {
+ logError(1, "%s errorHandler: Starting handling...\n", tag);
+ switch (event[1])
+ /* TODO: write an error log for undefinied command subtype 0xBA*/
+ {
+ case EVENT_TYPE_ESD_ERROR: /* esd */
+ res = fts_chip_powercycle(info);
+ if (res < OK) {
+ logError(1, "%s errorHandler: Error performing powercycle ERROR %08X\n", tag, res);
+ }
+
+ res = fts_system_reset();
+ if (res < OK) {
+ logError(1, "%s errorHandler: Cannot reset the device ERROR %08X\n", tag, res);
+ }
+ res = (ERROR_HANDLER_STOP_PROC|res);
+ break;
+
+ case EVENT_TYPE_WATCHDOG_ERROR: /* watchdog */
+ res = fts_system_reset();
+ if (res < OK) {
+ logError(1, "%s errorHandler: Cannot reset the device ERROR %08X\n", tag, res);
+ }
+ res = (ERROR_HANDLER_STOP_PROC|res);
+ break;
+
+ default:
+ logError(1, "%s errorHandler: No Action taken! \n", tag);
+ break;
+
+ }
+ logError(1, "%s errorHandler: handling Finished! res = %08X\n", tag, res);
+ return res;
+ }
+ logError(1, "%s errorHandler: event Null or not correct size! ERROR %08X \n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+}
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsError.h b/drivers/input/touchscreen/st/fts_lib/ftsError.h
new file mode 100644
index 000000000000..fc8fa5003158
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsError.h
@@ -0,0 +1,75 @@
+/*
+**************************************************************************
+** STMicroelectronics
+**************************************************************************
+** marco.cali@st.com
+**************************************************************************
+*
+* FTS error/info kernel log reporting
+*
+**************************************************************************
+**************************************************************************
+*/
+
+
+/*FIRST LEVEL ERROR CODE*/
+#define OK ((int)0x00000000) /*No ERROR*/
+#define ERROR_ALLOC ((int)0x80000001) /*allocation of memory failed*/
+#define ERROR_I2C_R ((int)0x80000002) /*i2c read failed*/
+#define ERROR_I2C_W ((int)0x80000003) /*i2c write failed*/
+#define ERROR_I2C_WR ((int)0x80000004) /*i2c write/read failed*/
+#define ERROR_I2C_O ((int)0x80000005) /*error during opening a i2c device*/
+#define ERROR_OP_NOT_ALLOW ((int)0x80000006) /*operation not allowed*/
+#define ERROR_TIMEOUT ((int)0x80000007) /*timeout expired! exceed the max number of retries or the max waiting time*/
+#define ERROR_FILE_NOT_FOUND ((int)0x80000008) /*the file that i want to open is not found*/
+#define ERROR_FILE_PARSE ((int)0x80000009) /*error during parsing the file*/
+#define ERROR_FILE_READ ((int)0x8000000A) /*error during reading the file*/
+#define ERROR_LABEL_NOT_FOUND ((int)0x8000000B) /*label not found*/
+#define ERROR_FW_NO_UPDATE ((int)0x8000000C) /*fw in the chip newer than the one in the memmh*/
+#define ERROR_FLASH_UNKNOWN ((int)0x8000000D) /*flash status busy or unknown*/
+
+/*SECOND LEVEL ERROR CODE*/
+#define ERROR_DISABLE_INTER ((int)0x80000200) /*unable to disable the interrupt*/
+#define ERROR_ENABLE_INTER ((int)0x80000300) /*unable to activate the interrup*/
+#define ERROR_READ_B2 ((int)0x80000400) /*B2 command failed*/
+#define ERROR_GET_OFFSET ((int)0x80000500) /*unable to read an offset from memory*/
+#define ERROR_GET_FRAME_DATA ((int)0x80000600) /*unable to retrieve the data of a required frame*/
+#define ERROR_DIFF_COMP_TYPE ((int)0x80000700) /*FW answers with an event that has a different address respect the request done*/
+#define ERROR_WRONG_COMP_SIGN ((int)0x80000800) /*the signature of the compensation data is not A5*/
+#define ERROR_SENSE_ON_FAIL ((int)0x80000900) /*the command Sense On failed*/
+#define ERROR_SENSE_OFF_FAIL ((int)0x80000A00) /*the command Sense Off failed*/
+#define ERROR_SYSTEM_RESET_FAIL ((int)0x80000B00) /*the command SYSTEM RESET failed*/
+#define ERROR_FLASH_NOT_READY ((int)0x80000C00) /*flash status not ready within a timeout*/
+#define ERROR_FW_VER_READ ((int)0x80000D00) /*unable to retrieve fw_vers or the config_id*/
+#define ERROR_GESTURE_ENABLE_FAIL ((int)0x80000E00) /*unable to enable/disable the gesture*/
+#define ERROR_GESTURE_START_ADD ((int)0x80000F00) /*unable to start to add custom gesture*/
+#define ERROR_GESTURE_FINISH_ADD ((int)0x80001000) /*unable to finish to add custom gesture*/
+#define ERROR_GESTURE_DATA_ADD ((int)0x80001100) /*unable to add custom gesture data*/
+#define ERROR_GESTURE_REMOVE ((int)0x80001200) /*unable to remove custom gesture data*/
+#define ERROR_FEATURE_ENABLE_DISABLE ((int)0x80001300) /*unable to enable/disable a feature mode in the IC*/
+/*THIRD LEVEL ERROR CODE*/
+#define ERROR_CH_LEN ((int)0x80010000) /*unable to retrieve the force and/or sense length*/
+#define ERROR_REQU_COMP_DATA ((int)0x80020000) /*compensation data request failed*/
+#define ERROR_COMP_DATA_HEADER ((int)0x80030000) /*unable to retrieve the compensation data header*/
+#define ERROR_COMP_DATA_GLOBAL ((int)0x80040000) /*unable to retrieve the global compensation data*/
+#define ERROR_COMP_DATA_NODE ((int)0x80050000) /*unable to retrieve the compensation data for each node*/
+#define ERROR_TEST_CHECK_FAIL ((int)0x80060000) /*check of production limits or of fw answers failed*/
+#define ERROR_MEMH_READ ((int)0x80070000) /*memh reading failed*/
+#define ERROR_FLASH_BURN_FAILED ((int)0x80080000) /*flash burn failed*/
+#define ERROR_MS_TUNING ((int)0x80090000) /*ms tuning failed*/
+#define ERROR_SS_TUNING ((int)0x800A0000) /*ss tuning failed*/
+#define ERROR_LP_TIMER_TUNING ((int)0x800B0000) /*lp timer calibration failed*/
+#define ERROR_SAVE_CX_TUNING ((int)0x800C0000) /*save cx data to flash failed*/
+#define ERROR_HANDLER_STOP_PROC ((int)0x800D0000) /*stop the poll of the FIFO if particular errors are found*/
+#define ERROR_CHECK_ECHO_FAIL ((int)0x800E0000) /*unable to retrieve echo event*/
+
+/*FOURTH LEVEL ERROR CODE*/
+#define ERROR_PROD_TEST_DATA ((int)0x81000000) /*production data test failed*/
+#define ERROR_FLASH_PROCEDURE ((int)0x82000000) /*complete flash procedure failed*/
+#define ERROR_PROD_TEST_ITO ((int)0x83000000) /*production ito test failed*/
+#define ERROR_PROD_TEST_INITIALIZATION ((int)0x84000000) /*production initialization test failed*/
+#define ERROR_GET_INIT_STATUS ((int)0x85000000) /*mismatch of the MS or SS tuning_version*/
+
+void logError(int force, const char *msg, ...);
+int isI2cError(int error);
+int errorHandler(u8 *event, int size);
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsFlash.c b/drivers/input/touchscreen/st/fts_lib/ftsFlash.c
new file mode 100644
index 000000000000..f3becac79102
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsFlash.c
@@ -0,0 +1,1071 @@
+/*
+
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS API for Flashing the IC *
+ * *
+ **************************************************************************
+ **************************************************************************
+
+ */
+
+#include "ftsCrossCompile.h"
+#include "ftsCompensation.h"
+#include "ftsError.h"
+#include "ftsFlash.h"
+#include "ftsFrame.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTest.h"
+#include "ftsTime.h"
+#include "ftsTool.h"
+#include "../fts.h" /* needed for the FW_H_FILE define */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/time.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+/* #include <linux/sec_sysfs.h> */
+
+#ifdef FW_H_FILE
+#include <../fts_fw.h>
+#endif
+
+/* static char tag[8] = "[ FTS ]\0"; */
+extern chipInfo ftsInfo;
+
+int getFirmwareVersion(u16 *fw_vers, u16 *config_id)
+{
+ u8 fwvers[DCHIP_FW_VER_BYTE];
+ u8 confid[CONFIG_ID_BYTE];
+ int res;
+
+ res = readCmdU16(FTS_CMD_HW_REG_R, DCHIP_FW_VER_ADDR, fwvers, DCHIP_FW_VER_BYTE, DUMMY_HW_REG);
+ if (res < OK) {
+ logError(1, "%s getFirmwareVersion: unable to read fw_version ERROR %02X\n", tag, ERROR_FW_VER_READ);
+ return (res | ERROR_FW_VER_READ);
+ }
+
+ u8ToU16(fwvers, fw_vers); /* fw version use big endian */
+ if (*fw_vers != 0) { /* if fw_version is 00 00 means that there is no firmware running in the chip therefore will be impossible find the config_id */
+ res = readB2(CONFIG_ID_ADDR, confid, CONFIG_ID_BYTE);
+ if (res < OK) {
+ logError(1, "%s getFirmwareVersion: unable to read config_id ERROR %02X\n", tag, ERROR_FW_VER_READ);
+ return (res | ERROR_FW_VER_READ);
+ }
+ u8ToU16(confid, config_id); /* config id use little endian */
+ } else {
+ *config_id = 0x0000;
+ }
+
+ logError(0, "%s FW VERS = %04X\n", tag, *fw_vers);
+ logError(0, "%s CONFIG ID = %04X\n", tag, *config_id);
+ return OK;
+
+}
+
+#ifdef FTM3_CHIP
+
+int flash_status(void)
+{
+ u8 cmd[2] = {FLASH_CMD_READSTATUS, 0x00};
+ u8 readData = 0;
+
+ logError(0, "%s Reading flash_status...\n", tag);
+ if (fts_readCmd(cmd, 2, &readData, FLASH_STATUS_BYTES) < 0) {
+ logError(1, "%s flash_status: ERROR % 02X\n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+
+ readData &= 0x01;
+ /* logError(0, "%s flash_status = %d\n", tag,readData); */
+ return (int) readData;
+
+}
+
+int flash_status_ready(void)
+{
+
+ int status = flash_status();
+
+ if (status == ERROR_I2C_R) {
+ logError(1, "%s flash_status_ready: ERROR % 02X\n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+
+ if (status != FLASH_READY) {
+ logError(1, "%s flash_status_ready: flash busy or unknown STATUS = % 02X\n", tag, status);
+ return ERROR_FLASH_UNKNOWN;
+ }
+
+ return FLASH_READY;
+
+}
+
+int wait_for_flash_ready(void)
+{
+ int status;
+ int(*code)(void);
+
+ code = flash_status_ready;
+
+ logError(0, "%s Waiting for flash ready...\n", tag);
+ status = attempt_function(code, FLASH_WAIT_BEFORE_RETRY, FLASH_RETRY_COUNT);
+
+ if (status != FLASH_READY) {
+ logError(1, "%s wait_for_flash_ready: ERROR % 02X\n", tag, ERROR_FLASH_NOT_READY);
+ return (status | ERROR_FLASH_NOT_READY);
+ }
+
+ logError(0, "%s Flash ready!\n", tag);
+ return OK;
+}
+
+int flash_unlock(void)
+{
+
+ int status;
+ u8 cmd[3] = {FLASH_CMD_UNLOCK, FLASH_UNLOCK_CODE0, FLASH_UNLOCK_CODE1}; /* write the comand to perform the unlock */
+
+ logError(0, "%s Try to unlock flash...\n", tag);
+ status = wait_for_flash_ready();
+
+ if (status != OK) {
+ logError(1, "%s flash_unlock: ERROR % 02X\n", tag, ERROR_FLASH_NOT_READY);
+ return (status | ERROR_FLASH_NOT_READY); /* Flash not ready within the choosen time, better exit! */
+ }
+
+ logError(0, "%s Command unlock ...\n", tag);
+ if (fts_writeCmd(cmd, sizeof (cmd)) < 0) {
+ logError(1, "%s flash_unlock: ERROR % 02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ status = wait_for_flash_ready();
+
+ if (status != OK) {
+ logError(1, "%s flash_unlock: ERROR % 02X\n", tag, ERROR_FLASH_NOT_READY);
+ return (status | ERROR_FLASH_NOT_READY); /* Flash not ready within the choosen time, better exit! */
+ }
+
+ logError(0, "%s Unlock flash DONE!\n", tag);
+
+ return OK;
+
+}
+
+/*int parseMemhFile(const char *pathToFile, u8** data, int* length, int dimension)
+{
+
+ int i = 0;
+ unsigned long ul;
+ u8* buff = NULL;
+ int fd = -1;
+ int n, size, pointer = 0;
+ char *data_file, *line;
+ const struct firmware *fw = NULL;
+ struct device *dev = NULL;
+
+ line = (char *) kmalloc(11 * sizeof (char), GFP_KERNEL);
+ if (line == NULL) {
+ logError(1, "%s parseMemhFile: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ logError(0, "%s parseMemhFile: allocating %d bytes\n", tag, dimension);
+ buff = (u8*) kmalloc(dimension * sizeof (u8), GFP_KERNEL);
+ if (buff == NULL) {
+ logError(1, "%s parseMemhFile: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ dev = getDev();
+ if (dev != NULL)
+ fd = request_firmware(&fw, pathToFile, dev);
+
+ if (fd == 0) {
+ size = fw->size;
+ logError(0, "%s The size of the firmware file is %d bytes...\n", tag, size);
+ data_file = (char *) fw->data;
+ logError(0, "%s Start to reading %s...\n", tag, pathToFile);
+
+ while (size - pointer > 0 && (i * 4 + 4) <= dimension) {
+ if (readLine(&data_file[pointer], &line, size - pointer, &n) < 0) {
+ break;
+ }
+ pointer += n;
+ logError(0, "%s Pointer= %d riga = %s\n", tag, pointer, line);
+ ul = simple_strtoul(line, NULL, 16);
+
+ buff[i * 4] = (u8) ((ul & 0x000000FF) >> 0);
+ buff[i * 4 + 1] = (u8) ((ul & 0x0000FF00) >> 8);
+ buff[i * 4 + 2] = (u8) ((ul & 0x00FF0000) >> 16);
+ buff[i * 4 + 3] = (u8) ((ul & 0xFF000000) >> 24);
+ i++;
+ }
+
+ kfree(line);
+
+ *length = i * 4;
+ if (*length < dimension) {
+ logError(1, "%s parseMemhFile: Read only %d instead of %d... ERROR %02X\n", tag, *length, dimension, ERROR_FILE_PARSE);
+ release_firmware(fw);
+ return ERROR_FILE_PARSE;
+ }
+ *data = buff;
+
+ logError(0, "%s READ DONE %d bytes!\n", tag, *length);
+ release_firmware(fw);
+ return OK;
+ } else {
+ logError(1, "%s parseProductionTestLimits: ERROR %02X\n", tag, ERROR_FILE_NOT_FOUND);
+ return ERROR_FILE_NOT_FOUND;
+ }
+
+}*/
+
+int parseBinFile(const char *pathToFile, u8 **data, int *length, int dimension)
+{
+
+ int fd = -1;
+ int fw_size = 0;
+ u8 *fw_data = NULL;
+
+#ifndef FW_H_FILE
+ const struct firmware *fw = NULL;
+ struct device *dev = NULL;
+ dev = getDev();
+
+ if (dev != NULL)
+ fd = request_firmware(&fw, pathToFile, dev);
+ else {
+ logError(1, "%s parseBinFile: No device found! ERROR %02X\n", ERROR_FILE_PARSE);
+ return ERROR_FILE_PARSE;
+ }
+#else
+ fd = 0;
+#endif
+
+ if (fd == 0) {
+#ifndef FW_H_FILE
+ fw_size = fw->size;
+ fw_data = (u8 *) (fw->data);
+#else
+ fw_size = FW_SIZE_NAME;
+ fw_data = (u8 *) FW_ARRAY_NAME;
+#endif
+ if (fw_size - FW_HEADER_SIZE != FW_SIZE) {
+ logError(1, "%s parseBinFile: Read only %d instead of %d... ERROR %02X\n", tag, fw_size, FW_SIZE, ERROR_FILE_PARSE);
+#ifndef FW_H_FILE
+ release_firmware(fw);
+#endif
+ return ERROR_FILE_PARSE;
+ }
+ *data = (u8 *) kmalloc(dimension * sizeof (u8), GFP_KERNEL);
+ if (*data == NULL) {
+ logError(1, "%s parseBinFile: ERROR %02X\n", tag, ERROR_ALLOC);
+#ifndef FW_H_FILE
+ release_firmware(fw);
+#endif
+ return ERROR_ALLOC;
+ }
+
+ memcpy(*data, ((u8 *) (fw_data) + FW_HEADER_SIZE), dimension);
+ *length = dimension;
+
+ logError(0, "%s READ FW DONE %d bytes!\n", tag, *length);
+#ifndef FW_H_FILE
+ release_firmware(fw);
+#endif
+ return OK;
+ }
+ logError(1, "%s parseBinFile: File Not Found! ERROR %02X\n", tag, ERROR_FILE_NOT_FOUND);
+ return ERROR_FILE_NOT_FOUND;
+}
+
+int readFwFile(const char *path, Firmware *fw, int keep_cx)
+{
+ int res;
+ int size;
+
+ if (keep_cx) {
+ size = FW_SIZE - FW_CX_SIZE;
+ logError(1, "%s readFwFile: Selected 124k Configuration!\n", tag);
+ } else {
+ size = FW_SIZE;
+ logError(1, "%s readFwFile: Selected 128k Configuration!\n", tag);
+ }
+
+ /* res = parseMemhFile(path, &(fw->data), &(fw->data_size), size); */
+ res = parseBinFile(path, &(fw->data), &(fw->data_size), size);
+ if (res < OK) {
+ logError(1, "%s readFwFile: ERROR %02X\n", tag, ERROR_MEMH_READ);
+ return (res | ERROR_MEMH_READ);
+ }
+
+ fw->fw_ver = (u16) (((fw->data[FW_VER_MEMH_BYTE1] & 0x00FF) << 8) + (fw->data[FW_VER_MEMH_BYTE0] & 0x00FF));
+ fw->config_id = (u16) (((fw->data[(FW_CODE_SIZE) + FW_OFF_CONFID_MEMH_BYTE1] & 0x00FF) << 8) + (fw->data[(FW_CODE_SIZE) + FW_OFF_CONFID_MEMH_BYTE0] & 0x00FF));
+
+ logError(0, "%s FW VERS File = %04X\n", tag, fw->fw_ver);
+ logError(0, "%s CONFIG ID File = %04X\n", tag, fw->config_id);
+ return OK;
+
+}
+
+int fillMemory(u32 address, u8 *data, int size)
+{
+
+ int remaining = size;
+ int toWrite = 0;
+
+ u8 *buff = (u8 *) kmalloc((MEMORY_CHUNK + 3) * sizeof (u8), GFP_KERNEL);
+ if (buff == NULL) {
+ logError(1, "%s fillMemory: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ while (remaining > 0) {
+ if (remaining >= MEMORY_CHUNK) {
+ if ((address + MEMORY_CHUNK) < FLASH_ADDR_SWITCH_CMD) {
+ buff[0] = FLASH_CMD_WRITE_LOWER_64;
+ toWrite = MEMORY_CHUNK;
+ remaining -= MEMORY_CHUNK;
+ } else {
+ if (address < FLASH_ADDR_SWITCH_CMD) {
+ int delta = FLASH_ADDR_SWITCH_CMD - address;
+ buff[0] = FLASH_CMD_WRITE_LOWER_64;
+ toWrite = delta;
+ remaining -= delta;
+ } else {
+ buff[0] = FLASH_CMD_WRITE_UPPER_64;
+ toWrite = MEMORY_CHUNK;
+ remaining -= MEMORY_CHUNK;
+ }
+ }
+ } else {
+ if ((address + remaining) < FLASH_ADDR_SWITCH_CMD) {
+ buff[0] = FLASH_CMD_WRITE_LOWER_64;
+ toWrite = remaining;
+ remaining = 0;
+ } else {
+ if (address < FLASH_ADDR_SWITCH_CMD) {
+ int delta = FLASH_ADDR_SWITCH_CMD - address;
+ buff[0] = FLASH_CMD_WRITE_LOWER_64;
+ toWrite = delta;
+ remaining -= delta;
+ } else {
+ buff[0] = FLASH_CMD_WRITE_UPPER_64;
+ toWrite = remaining;
+ remaining = 0;
+ }
+ }
+ }
+
+ buff[1] = (u8) ((address & 0x0000FF00) >> 8);
+ buff[2] = (u8) (address & 0x000000FF);
+ memcpy(buff + 3, data, toWrite);
+ logError(0, "%s Command = %02X , address = %02X %02X, bytes = %d\n", tag, buff[0], buff[1], buff[2], toWrite);
+ if (fts_writeCmd(buff, 3 + toWrite) < 0) {
+ logError(1, "%s fillMemory: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ address += toWrite;
+ data += toWrite;
+
+ }
+ return OK;
+}
+
+int flash_burn(Firmware fw, int force_burn)
+{
+ u8 cmd;
+ int res;
+
+ if (!force_burn && (ftsInfo.u16_fwVer >= fw.fw_ver) && (ftsInfo.u16_cfgId >= fw.config_id)) {
+ logError(1, "%s flash_burn: Firmware in the chip newer or equal to the one to burn! NO UPDATE ERROR %02X\n", tag, ERROR_FW_NO_UPDATE);
+ return (ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED);
+ }
+
+ /* programming procedure start */
+
+ logError(0, "%s Programming Procedure for flashing started:\n\n", tag);
+
+ logError(0, "%s 1) SYSTEM RESET:\n", tag);
+ res = fts_system_reset();
+ if (res < 0) {
+ logError(1, "%s system reset FAILED!\n", tag);
+ if (res != (ERROR_SYSTEM_RESET_FAIL | ERROR_TIMEOUT)) /* if there is no firmware i will not get the controller ready event and there will be a timeout but i can keep going, but if there is an I2C error i have to exit */
+ return (res | ERROR_FLASH_BURN_FAILED);
+ } else
+ logError(0, "%s system reset COMPLETED!\n\n", tag);
+
+ logError(0, "%s 2) FLASH UNLOCK:\n", tag);
+ res = flash_unlock();
+ if (res < 0) {
+ logError(1, "%s flash unlock FAILED! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+ logError(0, "%s flash unlock COMPLETED!\n\n", tag);
+
+ /* Write the lower part of the Program RAM */
+ logError(0, "%s 3) PREPARING DATA FOR FLASH BURN:\n", tag);
+
+ res = fillMemory(FLASH_ADDR_CODE, fw.data, fw.data_size);
+ if (res < 0) {
+ logError(1, "%s Error During filling the memory! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+ logError(0, "%s Data copy COMPLETED!\n\n", tag);
+
+ logError(0, "%s 4) ERASE FLASH:\n", tag);
+ res = wait_for_flash_ready();
+ if (res < 0) {
+ logError(1, "%s Flash not ready! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+
+ logError(0, "%s Command erase ...\n", tag);
+ cmd = FLASH_CMD_ERASE;
+ if (fts_writeCmd(&cmd, 1) < 0) {
+ logError(1, "%s Error during erasing flash! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (ERROR_I2C_W | ERROR_FLASH_BURN_FAILED);
+ }
+
+ res = wait_for_flash_ready();
+ if (res < 0) {
+ logError(1, "%s Flash not ready 2! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+
+ logError(0, "%s Flash erase COMPLETED!\n\n", tag);
+
+ logError(0, "%s 5) BURN FLASH:\n", tag);
+ logError(0, "%s Command burn ...\n", tag);
+ cmd = FLASH_CMD_BURN;
+ if (fts_writeCmd(&cmd, 1) < 0) {
+ logError(1, "%s Error during burning data! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (ERROR_I2C_W | ERROR_FLASH_BURN_FAILED);
+ }
+
+ res = wait_for_flash_ready();
+ if (res < 0) {
+ logError(1, "%s Flash not ready! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+
+ logError(0, "%s Flash burn COMPLETED!\n\n", tag);
+
+ logError(0, "%s 6) SYSTEM RESET:\n", tag);
+ res = fts_system_reset();
+ if (res < 0) {
+ logError(1, "%s system reset FAILED! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+ logError(0, "%s system reset COMPLETED!\n\n", tag);
+
+ logError(0, "%s 7) FINAL CHECK:\n", tag);
+ res = readChipInfo(0);
+ if (res < 0) {
+ logError(1, "%s flash_burn: Unable to retrieve Chip INFO! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+
+ if ((ftsInfo.u16_fwVer != fw.fw_ver) && (ftsInfo.u16_cfgId != fw.config_id)) {
+ logError(1, "%s Firmware in the chip different from the one that was burn! fw: %x != %x , conf: %x != %x\n", tag, ftsInfo.u16_fwVer, fw.fw_ver, ftsInfo.u16_cfgId, fw.config_id);
+ return ERROR_FLASH_BURN_FAILED;
+ }
+
+ logError(0, "%s Final check OK! fw: %02X , conf: %02X\n", tag, ftsInfo.u16_fwVer, ftsInfo.u16_cfgId);
+
+ return OK;
+}
+
+int flashProcedure(const char *path, int force, int keep_cx)
+{
+ Firmware fw;
+ int res;
+
+ fw.data = NULL;
+ logError(0, "%s Reading Fw file...\n", tag);
+ res = readFwFile(path, &fw, keep_cx);
+ if (res < OK) {
+ logError(1, "%s flashProcedure: ERROR %02X\n", tag, (res | ERROR_FLASH_PROCEDURE));
+ kfree(fw.data);
+ return (res | ERROR_FLASH_PROCEDURE);
+ }
+ logError(0, "%s Fw file read COMPLETED!\n", tag);
+
+ logError(0, "%s Starting flashing procedure...\n", tag);
+ res = flash_burn(fw, force);
+ if (res < OK && res != (ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED)) {
+ logError(1, "%s flashProcedure: ERROR %02X\n", tag, ERROR_FLASH_PROCEDURE);
+ kfree(fw.data);
+ return (res | ERROR_FLASH_PROCEDURE);
+ }
+ logError(0, "%s flashing procedure Finished!\n", tag);
+ kfree(fw.data);
+
+ /* cleanUp(0); //after talking with Kusuma, the SenseOn should be issued only at the very end of the initialization process, if senso on here it can trigger autotune protection */
+ return res;
+}
+
+#else
+
+int wait_for_flash_ready(u8 type)
+{
+ u8 cmd[2] = {FLASH_CMD_READ_REGISTER, type};
+ u8 readData;
+ int i, res = -1;
+
+ logError(0, "%s Waiting for flash ready ...\n", tag);
+ for (i = 0; i < FLASH_RETRY_COUNT && res != 0; i++) {
+ if (fts_readCmd(cmd, sizeof (cmd), &readData, 1) < 0) {
+ logError(1, "%s wait_for_flash_ready: ERROR % 02X\n", tag, ERROR_I2C_W);
+ } else{
+ res = readData & 0x80;
+ /* logError(0, "%s flash status = %d \n", tag, res); */
+ }
+ msleep(FLASH_WAIT_BEFORE_RETRY);
+ }
+
+ if (i == FLASH_RETRY_COUNT && res != 0) {
+ logError(1, "%s Wait for flash TIMEOUT! ERROR %02X\n", tag, ERROR_TIMEOUT);
+ return ERROR_TIMEOUT;
+ }
+
+ logError(0, "%s Flash READY!\n", tag);
+ return OK;
+}
+
+int fts_warm_boot(void)
+{
+
+ u8 cmd[4] = {FTS_CMD_HW_REG_W, 0x00, 0x00, WARM_BOOT_VALUE}; /* write the command to perform the warm boot */
+ u16ToU8_be(ADDR_WARM_BOOT, &cmd[1]);
+
+ logError(0, "%s Command warm boot ...\n", tag);
+ if (fts_writeCmd(cmd, sizeof (cmd)) < 0) {
+ logError(1, "%s flash_unlock: ERROR % 02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ logError(0, "%s Warm boot DONE!\n", tag);
+
+ return OK;
+}
+
+int parseBinFile(const char *pathToFile, Firmware *fwData, int keep_cx)
+{
+
+ int fd = -1;
+ int dimension, index = 0;
+ u32 temp;
+ u8 *data;
+ int res, i, fw_size;
+
+#ifndef FW_H_FILE
+ const struct firmware *fw = NULL;
+ struct device *dev = NULL;
+ dev = getDev();
+
+ if (dev != NULL)
+ fd = request_firmware(&fw, pathToFile, dev);
+ else {
+ logError(1, "%s parseBinFile: No device found! ERROR %02X\n", ERROR_FILE_PARSE);
+ return ERROR_FILE_PARSE;
+ }
+
+ fw_size = fw->size;
+#else
+fd = 0;
+fw_size = SIZE_NAME;
+#endif
+
+ if (fd == 0 && fw_size > 0) { /* the file should contain at least the header plus the content_crc */
+ if (fw_size < FW_HEADER_SIZE+FW_BYTES_ALIGN) {
+ logError(1, "%s parseBinFile: Read only %d instead of %d... ERROR %02X\n", tag, fw_size, FW_HEADER_SIZE+FW_BYTES_ALIGN, ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ } else {
+ /* start parsing of bytes */
+#ifndef FW_H_FILE
+ data = (u8 *) (fw->data);
+#else
+ data = (u8 *) (ARRAY_NAME);
+#endif
+ u8ToU32(&data[index], &temp);
+ if (temp != FW_HEADER_SIGNATURE) {
+ logError(1, "%s parseBinFile: Wrong Signature %08X ... ERROR %02X\n", tag, temp, ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ }
+ logError(0, "%s parseBinFile: Fw Signature OK!\n", tag);
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&data[index], &temp);
+ if (temp != FW_FTB_VER) {
+ logError(1, "%s parseBinFile: Wrong ftb_version %08X ... ERROR %02X\n", tag, temp, ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ }
+ logError(0, "%s parseBinFile: ftb_version OK!\n", tag);
+ index += FW_BYTES_ALIGN;
+ if (data[index] != DCHIP_ID_0 || data[index+1] != DCHIP_ID_1) {
+ logError(1, "%s parseBinFile: Wrong target %02X != %02X %02X != %02X ... ERROR %08X\n", tag, data[index], DCHIP_ID_0, data[index+1], DCHIP_ID_1, ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ }
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&data[index], &temp);
+ logError(1, "%s parseBinFile: Fw ID = %08X\n", tag, temp);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&data[index], &temp);
+ fwData->fw_ver = temp;
+ logError(1, "%s parseBinFile: FILE Fw Version = %04X\n", tag, fwData->fw_ver);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&data[index], &temp);
+ fwData->config_id = temp;
+ logError(1, "%s parseBinFile: FILE Config ID = %08X\n", tag, temp);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&data[index], &temp);
+ logError(1, "%s parseBinFile: Config Version = %08X\n", tag, temp);
+
+ index += FW_BYTES_ALIGN*2; /* skip reserved data */
+
+ index += FW_BYTES_ALIGN;
+ logError(1, "%s parseBinFile: File External Release = ", tag);
+ for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
+ fwData->externalRelease[i] = data[index++];
+ logError(1, "%02X ", fwData->externalRelease[i]);
+ }
+ logError(1, "\n");
+
+ /* index += FW_BYTES_ALIGN; */
+ u8ToU32(&data[index], &temp);
+ fwData->sec0_size = temp;
+ logError(1, "%s parseBinFile: sec0_size = %08X (%d bytes)\n", tag, fwData->sec0_size, fwData->sec0_size);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&data[index], &temp);
+ fwData->sec1_size = temp;
+ logError(1, "%s parseBinFile: sec1_size = %08X (%d bytes)\n", tag, fwData->sec1_size, fwData->sec1_size);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&data[index], &temp);
+ fwData->sec2_size = temp;
+ logError(1, "%s parseBinFile: sec2_size = %08X (%d bytes)\n", tag, fwData->sec2_size, fwData->sec2_size);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&data[index], &temp);
+ fwData->sec3_size = temp;
+ logError(1, "%s parseBinFile: sec3_size = %08X (%d bytes)\n", tag, fwData->sec3_size, fwData->sec3_size);
+
+ index += FW_BYTES_ALIGN; /* skip header crc */
+
+ if (!keep_cx) {
+ dimension = fwData->sec0_size + fwData->sec1_size + fwData->sec2_size + fwData->sec3_size;
+ temp = fw_size;
+ } else {
+ dimension = fwData->sec0_size + fwData->sec1_size; /* sec2 may contain cx data (future implementation) sec3 atm not used */
+ temp = fw_size - fwData->sec2_size - fwData->sec3_size;
+ }
+
+ if (dimension+FW_HEADER_SIZE+FW_BYTES_ALIGN != temp) {
+ logError(1, "%s parseBinFile: Read only %d instead of %d... ERROR %02X\n", tag, fw_size, dimension+FW_HEADER_SIZE+FW_BYTES_ALIGN, ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ }
+
+ fwData->data = (u8 *) kmalloc(dimension * sizeof (u8), GFP_KERNEL);
+ if (fwData->data == NULL) {
+ logError(1, "%s parseBinFile: ERROR %02X\n", tag, ERROR_ALLOC);
+ res = ERROR_ALLOC;
+ goto END;
+ }
+
+ index += FW_BYTES_ALIGN;
+ memcpy(fwData->data, &data[index], dimension);
+ fwData->data_size = dimension;
+
+ logError(0, "%s READ FW DONE %d bytes!\n", tag, fwData->data_size);
+ res = OK;
+ goto END;
+ }
+ } else {
+ logError(1, "%s parseBinFile: File Not Found! ERROR %02X\n", tag, ERROR_FILE_NOT_FOUND);
+ return ERROR_FILE_NOT_FOUND;
+ }
+
+END:
+#ifndef FW_H_FILE
+ release_firmware(fw);
+#endif
+ return res;
+}
+
+int readFwFile(const char *path, Firmware *fw, int keep_cx)
+{
+ int res;
+
+ res = parseBinFile(path, fw, keep_cx);
+ if (res < OK) {
+ logError(1, "%s readFwFile: ERROR %02X\n", tag, ERROR_MEMH_READ);
+ return (res | ERROR_MEMH_READ);
+ }
+
+ return OK;
+
+}
+
+int flash_unlock(void)
+{
+ u8 cmd[3] = {FLASH_CMD_UNLOCK, FLASH_UNLOCK_CODE0, FLASH_UNLOCK_CODE1}; /* write the command to perform the unlock */
+
+ logError(0, "%s Command unlock ...\n", tag);
+ if (fts_writeCmd(cmd, sizeof (cmd)) < 0) {
+ logError(1, "%s flash_unlock: ERROR % 02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ /* msleep(FLASH_WAIT_TIME); */
+ logError(0, "%s Unlock flash DONE!\n", tag);
+
+ return OK;
+
+}
+
+int flash_erase_unlock(void)
+{
+ u8 cmd[3] = {FLASH_CMD_WRITE_REGISTER, FLASH_ERASE_UNLOCK_CODE0, FLASH_ERASE_UNLOCK_CODE1}; /* write the command to perform the unlock for erasing the flash */
+
+ logError(0, "%s Try to erase unlock flash...\n", tag);
+
+ logError(0, "%s Command erase unlock ...\n", tag);
+ if (fts_writeCmd(cmd, sizeof (cmd)) < 0) {
+ logError(1, "%s flash_erase_unlock: ERROR % 02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ logError(0, "%s Erase Unlock flash DONE!\n", tag);
+
+ return OK;
+
+}
+
+int flash_full_erase(void)
+{
+
+ int status;
+ u8 cmd[3] = {FLASH_CMD_WRITE_REGISTER, FLASH_ERASE_CODE0, FLASH_ERASE_CODE1};
+ /* write the command to erase the flash */
+
+ logError(0, "%s Command full erase sent ...\n", tag);
+ if (fts_writeCmd(cmd, sizeof (cmd)) < 0) {
+ logError(1, "%s flash_full_erase: ERROR % 02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ status = wait_for_flash_ready(FLASH_ERASE_CODE0);
+
+ if (status != OK) {
+ logError(1, "%s flash_full_erase: ERROR % 02X\n", tag, ERROR_FLASH_NOT_READY);
+ return (status | ERROR_FLASH_NOT_READY);
+ /* Flash not ready within the chosen time, better exit! */
+ }
+
+ logError(0, "%s Full Erase flash DONE!\n", tag);
+
+ return OK;
+
+}
+
+int start_flash_dma(void)
+{
+ int status;
+ u8 cmd[3] = {FLASH_CMD_WRITE_REGISTER, FLASH_DMA_CODE0, FLASH_DMA_CODE1};
+ /* write the command to erase the flash */
+
+ logError(0, "%s Command flash DMA ...\n", tag);
+ if (fts_writeCmd(cmd, sizeof (cmd)) < 0) {
+ logError(1, "%s start_flash_dma: ERROR % 02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ status = wait_for_flash_ready(FLASH_DMA_CODE0);
+
+ if (status != OK) {
+ logError(1, "%s start_flash_dma: ERROR % 02X\n", tag, ERROR_FLASH_NOT_READY);
+ return (status | ERROR_FLASH_NOT_READY);
+ /* Flash not ready within the chosen time, better exit! */
+ }
+
+ logError(0, "%s flash DMA DONE!\n", tag);
+
+ return OK;
+}
+
+int fillFlash(u32 address, u8 *data, int size)
+{
+
+ int remaining = size;
+ int toWrite = 0;
+ int byteBlock = 0;
+ int wheel = 0;
+ u32 addr = 0;
+ int res;
+ int delta;
+
+ u8 *buff = (u8 *) kmalloc((DMA_CHUNK + 3) * sizeof (u8), GFP_KERNEL);
+ if (buff == NULL) {
+ logError(1, "%s fillFlash: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ while (remaining > 0) {
+ byteBlock = 0;
+ addr = 0;
+ while (byteBlock < FLASH_CHUNK && remaining > 0) {
+ buff[0] = FLASH_CMD_WRITE_64K;
+ if (remaining >= DMA_CHUNK) {
+ if ((byteBlock + DMA_CHUNK) <= FLASH_CHUNK) {
+ /* logError(1, "%s fillFlash: 1\n", tag); */
+ toWrite = DMA_CHUNK;
+ remaining -= DMA_CHUNK;
+ byteBlock += DMA_CHUNK;
+ } else {
+ /* logError(1, "%s fillFlash: 2\n", tag); */
+ delta = FLASH_CHUNK - byteBlock;
+ toWrite = delta;
+ remaining -= delta;
+ byteBlock += delta;
+ }
+ } else {
+ if ((byteBlock + remaining) <= FLASH_CHUNK) {
+ /* logError(1, "%s fillFlash: 3\n", tag); */
+ toWrite = remaining;
+ byteBlock += remaining;
+ remaining = 0;
+
+ } else {
+ /* logError(1, "%s fillFlash: 4\n", tag); */
+ delta = FLASH_CHUNK - byteBlock;
+ toWrite = delta;
+ remaining -= delta;
+ byteBlock += delta;
+ }
+ }
+
+ buff[1] = (u8) ((addr & 0x0000FF00) >> 8);
+ buff[2] = (u8) (addr & 0x000000FF);
+ memcpy(&buff[3], data, toWrite);
+ if (fts_writeCmd(buff, 3 + toWrite) < 0) {
+ logError(1, "%s fillFlash: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ addr += toWrite;
+ data += toWrite;
+ }
+
+ kfree(buff);
+
+ /* configuring the DMA */
+ byteBlock = byteBlock / 4 - 1;
+
+ buff = (u8 *) kmalloc((9) * sizeof (u8), GFP_KERNEL);
+ buff[0] = FLASH_CMD_WRITE_REGISTER;
+ buff[1] = FLASH_DMA_CONFIG;
+ buff[2] = 0x00;
+ buff[3] = 0x00;
+
+ addr = address + ((wheel * FLASH_CHUNK)/4);
+ buff[4] = (u8) ((addr & 0x000000FF));
+ buff[5] = (u8) ((addr & 0x0000FF00) >> 8);
+ buff[6] = (u8) (byteBlock & 0x000000FF);
+ buff[7] = (u8) ((byteBlock & 0x0000FF00) >> 8);
+ buff[8] = 0x00;
+
+ logError(0, "%s Command = %02X , address = %02X %02X, words = %02X %02X\n", tag, buff[0], buff[5], buff[4], buff[7], buff[6]);
+ if (fts_writeCmd(buff, 9) < OK) {
+ logError(1, "%s Error during filling Flash! ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ /* msleep(FLASH_WAIT_TIME); */
+ res = start_flash_dma();
+ if (res < OK) {
+ logError(1, "%s Error during flashing DMA! ERROR %02X\n", tag, res);
+ return res;
+ }
+ wheel++;
+ }
+ return OK;
+}
+
+int flash_burn(Firmware fw, int force_burn)
+{
+ int res;
+
+ if (!force_burn) {
+ for (res = EXTERNAL_RELEASE_INFO_SIZE-1; res >= 0; res--) {
+ if (fw.externalRelease[res] > ftsInfo.u8_extReleaseInfo[res])
+ goto start;
+ }
+ logError(1, "%s flash_burn: Firmware in the chip newer or equal to the one to burn! NO UPDATE ERROR %02X\n", tag, ERROR_FW_NO_UPDATE);
+ return (ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED);
+ }
+
+ /* programming procedure start */
+start:
+ logError(0, "%s Programming Procedure for flashing started:\n\n", tag);
+
+ logError(0, "%s 1) SYSTEM RESET:\n", tag);
+ res = fts_system_reset();
+ if (res < 0) {
+ logError(1, "%s system reset FAILED!\n", tag);
+ if (res != (ERROR_SYSTEM_RESET_FAIL | ERROR_TIMEOUT))
+ /* if there is no firmware i will not get the controller
+ *ready event and there will be a timeout but i can keep going,
+ *but if there is an I2C error i have to exit
+ */
+ return (res | ERROR_FLASH_BURN_FAILED);
+ } else
+ logError(0, "%s system reset COMPLETED!\n\n", tag);
+
+ logError(0, "%s 2) WARM BOOT:\n", tag);
+ res = fts_warm_boot();
+ if (res < OK) {
+ logError(1, "%s warm boot FAILED!\n", tag);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ } else
+ logError(0, "%s warm boot COMPLETED!\n\n", tag);
+
+ /* msleep(FLASH_WAIT_TIME); */
+ logError(0, "%s 3) FLASH UNLOCK:\n", tag);
+ res = flash_unlock();
+ if (res < OK) {
+ logError(1, "%s flash unlock FAILED! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+ logError(0, "%s flash unlock COMPLETED!\n\n", tag);
+
+ /* msleep(200); */
+ logError(0, "%s 4) FLASH ERASE UNLOCK:\n", tag);
+ res = flash_erase_unlock();
+ if (res < 0) {
+ logError(1, "%s flash unlock FAILED! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+ logError(0, "%s flash unlock COMPLETED!\n\n", tag);
+
+ /* msleep(FLASH_WAIT_TIME); */
+ logError(0, "%s 5) FLASH ERASE:\n", tag);
+ res = flash_full_erase();
+ if (res < 0) {
+ logError(1, "%s flash erase FAILED! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+ logError(0, "%s flash erase COMPLETED!\n\n", tag);
+
+ /* msleep(FLASH_WAIT_TIME); */
+ logError(0, "%s 6) LOAD PROGRAM:\n", tag);
+ res = fillFlash(FLASH_ADDR_CODE, &fw.data[0], fw.sec0_size);
+ if (res < OK) {
+ logError(1, "%s load program ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+ logError(1, "%s load program DONE!\n", tag);
+
+ logError(0, "%s 7) LOAD CONFIG:\n", tag);
+ res = fillFlash(FLASH_ADDR_CONFIG, &(fw.data[fw.sec0_size]), fw.sec1_size);
+ if (res < OK) {
+ logError(1, "%s load config ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+ logError(1, "%s load config DONE!\n", tag);
+
+ logError(0, "%s Flash burn COMPLETED!\n\n", tag);
+
+ logError(0, "%s 8) SYSTEM RESET:\n", tag);
+ res = fts_system_reset();
+ if (res < 0) {
+ logError(1, "%s system reset FAILED! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+ logError(0, "%s system reset COMPLETED!\n\n", tag);
+
+ logError(0, "%s 9) FINAL CHECK:\n", tag);
+ res = readChipInfo(0);
+ if (res < 0) {
+ logError(1, "%s flash_burn: Unable to retrieve Chip INFO! ERROR %02X\n", tag, ERROR_FLASH_BURN_FAILED);
+ return (res | ERROR_FLASH_BURN_FAILED);
+ }
+
+ for (res = 0; res < EXTERNAL_RELEASE_INFO_SIZE; res++) {
+ if (fw.externalRelease[res] != ftsInfo.u8_extReleaseInfo[res]) {
+ /* external release is prined during readChipInfo */
+ logError(1, "%s Firmware in the chip different from the one that was burn! fw: %x != %x , conf: %x != %x\n", tag, ftsInfo.u16_fwVer, fw.fw_ver, ftsInfo.u16_cfgId, fw.config_id);
+ return ERROR_FLASH_BURN_FAILED;
+ }
+ }
+
+ logError(0, "%s Final check OK! fw: %02X, conf: %02X\n", tag, ftsInfo.u16_fwVer, ftsInfo.u16_cfgId);
+
+ return OK;
+}
+
+int flashProcedure(const char *path, int force, int keep_cx)
+{
+ Firmware fw;
+ int res;
+
+ fw.data = NULL;
+ logError(0, "%s Reading Fw file...\n", tag);
+ res = readFwFile(path, &fw, keep_cx);
+ if (res < OK) {
+ logError(1, "%s flashProcedure: ERROR %02X\n", tag, (res | ERROR_FLASH_PROCEDURE));
+ kfree(fw.data);
+ return (res | ERROR_FLASH_PROCEDURE);
+ }
+ logError(0, "%s Fw file read COMPLETED!\n", tag);
+
+ logError(0, "%s Starting flashing procedure...\n", tag);
+ res = flash_burn(fw, force);
+ if (res < OK && res != (ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED)) {
+ logError(1, "%s flashProcedure: ERROR %02X\n", tag, ERROR_FLASH_PROCEDURE);
+ kfree(fw.data);
+ return (res | ERROR_FLASH_PROCEDURE);
+ }
+ logError(0, "%s flashing procedure Finished!\n", tag);
+ kfree(fw.data);
+ return res;
+}
+
+#endif
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsFlash.h b/drivers/input/touchscreen/st/fts_lib/ftsFlash.h
new file mode 100644
index 000000000000..69635e07a9f4
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsFlash.h
@@ -0,0 +1,79 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS API for Flashing the IC *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsSoftware.h"
+
+/* Flash possible status */
+#define FLASH_READY 0
+#define FLASH_BUSY 1
+#define FLASH_UNKNOWN -1
+
+#define FLASH_STATUS_BYTES 1
+
+/* Flash timing parameters */
+#define FLASH_RETRY_COUNT 1000
+#define FLASH_WAIT_BEFORE_RETRY 50 /* ms */
+
+#define FLASH_WAIT_TIME 200 /* ms */
+
+/* PATHS FW FILES */
+/* #define PATH_FILE_FW "fw.memh" */
+#ifdef FTM3_CHIP
+#define PATH_FILE_FW "st_fts.bin"
+#else
+#define PATH_FILE_FW "st_fts.ftb" /* new bin file structure */
+#endif
+
+#ifndef FTM3_CHIP
+#define FLASH_CHUNK (64*1024)
+#define DMA_CHUNK 32
+#endif
+
+typedef struct {
+ u8 *data;
+ u16 fw_ver;
+ u16 config_id;
+ u8 externalRelease[EXTERNAL_RELEASE_INFO_SIZE];
+ int data_size;
+#ifndef FTM3_CHIP
+ u32 sec0_size;
+ u32 sec1_size;
+ u32 sec2_size;
+ u32 sec3_size;
+#endif
+} Firmware;
+
+#ifdef FTM3_CHIP
+int flash_status(void);
+int flash_status_ready(void);
+int wait_for_flash_ready(void);
+int parseBinFile(const char *pathToFile, u8 **data, int *length, int dimension);
+/* int parseMemhFile(const char* pathToFile, u8** data, int* length, int dimension); */
+#else
+int wait_for_flash_ready(u8 type);
+int fts_warm_boot(void);
+int parseBinFile(const char *pathToFile, Firmware *fw, int keep_cx);
+int flash_erase_unlock(void);
+int flash_full_erase(void);
+int start_flash_dma(void);
+int fillFlash(u32 address, u8 *data, int size);
+#endif
+
+int flash_unlock(void);
+int fillMemory(u32 address, u8 *data, int size);
+int getFirmwareVersion(u16 *fw_vers, u16 *config_id);
+int readFwFile(const char *path, Firmware *fw, int keep_cx);
+int flash_burn(Firmware fw, int force_burn);
+int flashProcedure(const char *path, int force, int keep_cx);
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsFrame.c b/drivers/input/touchscreen/st/fts_lib/ftsFrame.c
new file mode 100644
index 000000000000..c502559319a0
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsFrame.c
@@ -0,0 +1,569 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS functions for getting frames *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsCrossCompile.h"
+#include "ftsCompensation.h"
+#include "ftsError.h"
+#include "ftsFrame.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTool.h"
+#include "ftsTime.h"
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/time.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+/* #include <linux/sec_sysfs.h> */
+
+static char tag[8] = "[ FTS ]\0";
+static int sense_len, force_len;
+
+/*int getOffsetFrame(u16 address, u16 *offset)
+{
+
+ u8 data[2];
+ u8 cmd = { FTS_CMD_FRAMEBUFFER_R };
+
+ if (readCmdU16(cmd, address, data, OFFSET_LENGTH, DUMMY_FRAMEBUFFER) < 0) {
+ logError(1, "%s getOffsetFrame: ERROR %02X\n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+ else {
+ u8ToU16(data, offset);
+ logError(0, "%s %s", tag, printHex("Offest = ", data, OFFSET_LENGTH));
+ return OK;
+ }
+
+}*/
+
+int getChannelsLength(void)
+{
+
+ int ret;
+ u8 *data = (u8 *)kmalloc(2*sizeof(u8), GFP_KERNEL);
+
+ if (data == NULL) {
+ logError(1, "%s getChannelsLength: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ ret = readB2(ADDR_SENSE_LEN, data, 2);
+ if (ret < OK) {
+ logError(1, "%s getChannelsLength: ERROR %02X\n", tag, ERROR_READ_B2);
+ return (ret|ERROR_READ_B2);
+ }
+
+ sense_len = (int)data[0];
+ force_len = (int)data[1];
+
+ logError(0, "%s Force_len = %d Sense_Len = %d\n", tag, force_len, sense_len);
+
+ kfree(data);
+
+ return OK;
+}
+
+int getFrameData(u16 address, int size, short **frame)
+{
+ int i, j, ret;
+ u8 *data = (u8 *)kmalloc(size*sizeof(u8), GFP_KERNEL);
+ if (data == NULL) {
+ logError(1, "%s getFrameData: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ ret = readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, data, size, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ logError(1, "%s getFrameData: ERROR %02X\n", tag, ERROR_I2C_R);
+ kfree(data);
+ return ERROR_I2C_R;
+ }
+ j = 0;
+ for (i = 0; i < size; i += 2) {
+ (*frame)[j] = (short)((data[i + 1] << 8) + data[i]);
+ j++;
+ }
+ kfree(data);
+ return OK;
+}
+
+/*int getMSFrame(u16 type, short **frame, int keep_first_row)
+{
+ u16 offset;
+ int size, ret;
+
+ if (getSenseLen() == 0 || getForceLen() == 0) {
+ ret=getChannelsLength();
+ if (ret<OK) {
+ logError(1, "%s getMSFrame: ERROR %02X\n", tag,ERROR_CH_LEN);
+ return (ret|ERROR_CH_LEN);
+ }
+ }
+
+ ret = getOffsetFrame(type, &offset);
+ if (ret<OK) {
+ logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_GET_OFFSET);
+ return (ret | ERROR_GET_OFFSET);
+ }
+
+ switch (type) {
+ case ADDR_RAW_TOUCH:
+ case ADDR_FILTER_TOUCH:
+ case ADDR_NORM_TOUCH:
+ case ADDR_CALIB_TOUCH:
+ if (keep_first_row ==1)
+ size = ((force_len+1)*sense_len);
+ else {
+ size = ((force_len)*sense_len);
+ offset+= (sense_len * BYTES_PER_NODE);
+ }
+ break;
+
+ default:
+ logError(1, "%s getMSFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *frame = (short*)kmalloc(size*sizeof(short), GFP_KERNEL);
+ if (*frame==NULL) {
+ logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ ret=getFrameData(offset, size*BYTES_PER_NODE, frame);
+ if (ret<OK) {
+ logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
+ return (ret|ERROR_GET_FRAME_DATA);
+ }
+
+ logError(0, "%s Frame acquired!\n", tag);
+ return size;
+
+}
+
+int getMSKeyFrame(u16 type, short **frame) {
+ u16 offset;
+ int size, ret;
+ u16 address;
+ MutualSenseData data;
+
+ if (type != ADDR_RAW_MS_KEY) {
+ logError(1, "%s getMSKeyFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = getOffsetFrame(type, &offset);
+ if (ret<OK) {
+ logError(1, "%s getMSKeyFrame: ERROR %02X\n", tag, ERROR_GET_OFFSET);
+ return (ret | ERROR_GET_OFFSET);
+ }
+
+ ret = requestCompensationData(MS_KEY);
+ if (ret < OK) {
+ logError(1, "%s getMSKeyFrame: readMutualSenseCompensationData ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
+ return (ret | ERROR_REQU_COMP_DATA);
+ }
+
+ ret = readCompensationDataHeader(MS_KEY, &(data.header), &address);
+ if (ret < OK) {
+ logError(1, "%s getMSKeyFrame: readMutualSenseCompensationData ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
+ return (ret | ERROR_COMP_DATA_HEADER);
+ }
+
+ if (data.header.force_node>data.header.sense_node)
+ size = data.header.force_node;
+ else
+ size = data.header.sense_node;
+
+ *frame = (short*)kmalloc(size*sizeof(short), GFP_KERNEL);
+ if (frame == NULL) {
+ logError(1, "%s getMSKeyFrame: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ ret = getFrameData(offset, size*BYTES_PER_NODE, frame);
+ if (ret<OK) {
+ logError(1, "%s getMSKeyFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
+ return (ret | ERROR_GET_FRAME_DATA);
+ }
+
+ logError(0, "%s Frame acquired!\n", tag);
+}
+
+int getSSFrame(u16 type, short **frame) {
+ u16 offset;
+ int size, ret;
+
+ if (getSenseLen() == 0 || getForceLen() == 0) {
+ ret = getChannelsLength();
+ if (ret<0) {
+ logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_CH_LEN);
+ return (ret | ERROR_CH_LEN);
+ }
+ }
+
+ switch (type) {
+ case ADDR_RAW_HOVER_FORCE:
+ case ADDR_FILTER_HOVER_FORCE:
+ case ADDR_NORM_HOVER_FORCE:
+ case ADDR_CALIB_HOVER_FORCE:
+ case ADDR_RAW_PRX_FORCE:
+ case ADDR_FILTER_PRX_FORCE:
+ case ADDR_NORM_PRX_FORCE:
+ case ADDR_CALIB_PRX_FORCE:
+ size = ((force_len)* 1);
+ break;
+
+ case ADDR_RAW_HOVER_SENSE:
+ case ADDR_FILTER_HOVER_SENSE:
+ case ADDR_NORM_HOVER_SENSE:
+ case ADDR_CALIB_HOVER_SENSE:
+ case ADDR_RAW_PRX_SENSE:
+ case ADDR_FILTER_PRX_SENSE:
+ case ADDR_NORM_PRX_SENSE:
+ case ADDR_CALIB_PRX_SENSE:
+ size = ((1)*sense_len);
+ break;
+
+ default:
+ logError(1, "%s getSSFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+
+ }
+
+ ret = getOffsetFrame(type, &offset);
+ if (ret<OK) {
+ logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_GET_OFFSET);
+ return (ret | ERROR_GET_OFFSET);
+ }
+
+ *frame = (short*)kmalloc(size*sizeof(short), GFP_KERNEL);
+ if (*frame == NULL) {
+ logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ ret = getFrameData(offset, size*BYTES_PER_NODE, frame);
+ if (ret<OK) {
+ logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
+ return (ret | ERROR_GET_FRAME_DATA);
+ }
+
+ logError(0, "%s Frame acquired!\n", tag);
+ return size;
+
+}
+
+int getNmsFrame(u16 type, short ***frames, int *size, int keep_first_row, int fs, int n) {
+ int i;
+ StopWatch global, local;
+ int temp;
+
+ *frames = (short **)kmalloc(n*sizeof(short *), GFP_KERNEL);
+
+ if (*frames == NULL) {
+ logError(1, "%s getNmsFrame: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ fs = (1*1000 / fs) ;
+
+ startStopWatch(&global);
+ for (i = 0; i < n; i++) {
+
+ startStopWatch(&local);
+
+ *size = getMSFrame(type, ((*frames)+i), keep_first_row);
+ if (*size < OK) {
+ logError(1, "%s getNFrame: getFrame failed\n",tag);
+ return *size;
+ }
+
+ stopStopWatch(&local);
+ temp = elapsedMillisecond(&local);
+ logError(0, "%s Iteration %d performed in %d ms... the process wait for %ld ms\n\n", tag, i, temp, (unsigned long)(fs - temp));
+
+ if (temp < fs)
+ msleep((unsigned long)(fs - temp));
+
+ }
+
+ stopStopWatch(&global);
+ temp = elapsedMillisecond(&global);
+ logError(0, "%s Global Iteration performed in %d ms\n", tag, temp);
+ temp /= n;
+ logError(0, "%s Mean Iteration performed in %d ms\n", tag, temp);
+ return (1000 / (temp));
+
+}*/
+
+int getSenseLen(void)
+{
+ int ret;
+ if (sense_len != 0)
+ return sense_len;
+ ret = getChannelsLength();
+ if (ret < OK)
+ return ret;
+ else
+ return sense_len;
+}
+
+int getForceLen(void)
+{
+ int ret;
+ if (force_len != 0)
+ return force_len;
+ ret = getChannelsLength();
+ if (ret < OK)
+ return ret;
+ else
+ return force_len;
+}
+
+int requestFrame(u16 type)
+{
+ int retry = 0;
+ int ret;
+ u16 answer;
+
+ int event_to_search[1];
+ u8 readEvent[FIFO_EVENT_SIZE];
+
+ u8 cmd[3] = { FTS_CMD_REQU_FRAME_DATA, 0x00, 0x00 };
+ /* B7 is the command for asking frame data */
+ event_to_search[0] = (int)EVENTID_FRAME_DATA_READ;
+
+ u16ToU8(type, &cmd[1]);
+
+ while (retry < FRAME_DATA_READ_RETRY) {
+ logError(0, "%s %s", tag, printHex("Command = ", cmd, 3));
+ ret = fts_writeFwCmd(cmd, 3);
+ /* send the request to the chip to load in memory the Frame Data */
+ if (ret < OK) {
+ logError(1, "%s requestFrame: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+ ret = pollForEvent(event_to_search, 1, readEvent, TIMEOUT_REQU_COMP_DATA);
+ if (ret < OK) {
+ logError(0, "%s Event did not Found at %d attemp!\n", tag, retry + 1);
+ retry += 1;
+ } else {
+ retry = 0;
+ break;
+ }
+ }
+
+ if (retry == FRAME_DATA_READ_RETRY) {
+ logError(1, "%s requestFrame: ERROR %02X\n", tag, ERROR_TIMEOUT);
+ return ERROR_TIMEOUT;
+ }
+
+ u8ToU16_le(&readEvent[1], &answer);
+
+ if (answer == type)
+ return OK;
+ logError(1, "%s The event found has a different type of Frame data ERROR %02X\n", tag, ERROR_DIFF_COMP_TYPE);
+ return ERROR_DIFF_COMP_TYPE;
+
+}
+
+int readFrameDataHeader(u16 type, DataHeader *header)
+{
+
+ u16 offset = ADDR_FRAMEBUFFER_DATA;
+ u16 answer;
+ u8 data[FRAME_DATA_HEADER];
+
+ if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, offset, data, FRAME_DATA_HEADER, DUMMY_FRAMEBUFFER) < 0) {
+ logError(1, "%s readFrameDataHeader: ERROR %02X\n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+ logError(0, "%s Read Data Header done!\n", tag);
+
+ if (data[0] != FRAME_HEADER_SIGNATURE) {
+ logError(1, "%s readFrameDataHeader: ERROR %02X The Header Signature was wrong! %02X != %02X\n", tag, ERROR_WRONG_COMP_SIGN, data[0], HEADER_SIGNATURE);
+ return ERROR_WRONG_COMP_SIGN;
+ }
+
+ u8ToU16_le(&data[1], &answer);
+
+ if (answer != type) {
+ logError(1, "%s readFrameDataHeader: ERROR %02X\n", tag, ERROR_DIFF_COMP_TYPE);
+ return ERROR_DIFF_COMP_TYPE;
+ }
+
+ logError(0, "%s Type of Frame data OK!\n", tag);
+
+ header->type = type;
+ header->force_node = (int)data[4];
+ header->sense_node = (int)data[5];
+
+ return OK;
+
+}
+
+int getMSFrame2(u16 type, MutualSenseFrame *frame)
+{
+ u16 offset = ADDR_FRAMEBUFFER_DATA+FRAME_DATA_HEADER;
+ int size, ret;
+
+ if (!(type == MS_TOUCH_ACTIVE || type == MS_TOUCH_LOW_POWER || type == MS_TOUCH_ULTRA_LOW_POWER || type == MS_KEY)) {
+ logError(1, "%s getMSFrame: Choose a MS type of frame data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = requestFrame(type);
+ if (ret < 0) {
+ logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
+ return (ret | ERROR_REQU_COMP_DATA);
+ }
+
+ ret = readFrameDataHeader(type, &(frame->header));
+ if (ret < 0) {
+ logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
+ return (ret | ERROR_COMP_DATA_HEADER);
+ }
+
+ switch (type) {
+ case MS_TOUCH_ACTIVE:
+ case MS_TOUCH_LOW_POWER:
+ case MS_TOUCH_ULTRA_LOW_POWER:
+ size = frame->header.force_node*frame->header.sense_node;
+ break;
+ case MS_KEY:
+ if (frame->header.force_node > frame->header.sense_node)
+ /* or use directly the number in the ftsChip */
+ size = frame->header.force_node;
+ else
+ size = frame->header.sense_node;
+ frame->header.force_node = 1;
+ frame->header.sense_node = size;
+ break;
+
+ default:
+ logError(1, "%s getMSFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ frame->node_data = (short *)kmalloc(size*sizeof(short), GFP_KERNEL);
+ if (frame->node_data == NULL) {
+ logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ ret = getFrameData(offset, size*BYTES_PER_NODE, &(frame->node_data));
+ if (ret < OK) {
+ logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
+ return (ret | ERROR_GET_FRAME_DATA);
+ }
+ /* if you want to access one node i,j, you should compute the offset like: offset = i*columns + j = > frame[i, j] */
+
+ logError(0, "%s Frame acquired!\n", tag);
+ frame->node_data_size = size;
+ return size; /* return the number of data put inside frame */
+
+}
+
+int getSSFrame2(u16 type, SelfSenseFrame *frame)
+{
+ u16 offset = ADDR_FRAMEBUFFER_DATA + FRAME_DATA_HEADER;
+ int size, ret;
+ short *temp = NULL;
+
+ if (!(type == SS_TOUCH || type == SS_KEY || type == SS_HOVER || type == SS_PROXIMITY)) {
+ logError(1, "%s getSSFrame: Choose a SS type of frame data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = requestFrame(type);
+ if (ret < 0) {
+ logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
+ return (ret | ERROR_REQU_COMP_DATA);
+ }
+
+ ret = readFrameDataHeader(type, &(frame->header));
+ if (ret < 0) {
+ logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
+ return (ret | ERROR_COMP_DATA_HEADER);
+ }
+
+ switch (type) {
+ case SS_TOUCH:
+ case SS_HOVER:
+ case SS_PROXIMITY:
+ size = frame->header.force_node+frame->header.sense_node;
+ break;
+
+ default:
+ logError(1, "%s getSSFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ temp = (short *)kmalloc(size*sizeof(short), GFP_KERNEL);
+ if (temp == NULL) {
+ logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ ret = getFrameData(offset, size*BYTES_PER_NODE, &temp);
+ if (ret < OK) {
+ logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
+ return (ret | ERROR_GET_FRAME_DATA);
+ }
+
+ frame->force_data = (short *)kmalloc(frame->header.force_node*sizeof(short), GFP_KERNEL);
+ if (frame->force_data == NULL) {
+ logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ memcpy(frame->force_data, temp, frame->header.force_node*sizeof(short));
+
+ frame->sense_data = (short *)kmalloc(frame->header.sense_node*sizeof(short), GFP_KERNEL);
+ if (frame->sense_data == NULL) {
+ logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ memcpy(frame->sense_data, &temp[frame->header.force_node], frame->header.sense_node*sizeof(short));
+
+ logError(0, "%s Frame acquired!\n", tag);
+ kfree(temp);
+ return size; /* return the number of data put inside frame */
+
+}
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsFrame.h b/drivers/input/touchscreen/st/fts_lib/ftsFrame.h
new file mode 100644
index 000000000000..89f4e5080a53
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsFrame.h
@@ -0,0 +1,49 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS functions for getting frames *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsSoftware.h"
+
+/* Number of data bytes for each node */
+#define BYTES_PER_NODE 2
+#define OFFSET_LENGTH 2
+#define FRAME_DATA_HEADER 8
+#define FRAME_HEADER_SIGNATURE 0xB5
+#define FRAME_DATA_READ_RETRY 2
+
+typedef struct {
+ DataHeader header;
+ short *node_data;
+ int node_data_size;
+} MutualSenseFrame;
+
+typedef struct {
+ DataHeader header;
+ short *force_data;
+ short *sense_data;
+} SelfSenseFrame;
+
+/* int getOffsetFrame(u16 address, u16 *offset); */
+int getChannelsLength(void);
+int getFrameData(u16 address, int size, short **frame);
+/* int getMSFrame(u16 type, short **frame, int keep_first_row); */
+/* int getMSKeyFrame(u16 type, short **frame); */
+/* int getSSFrame(u16 type, short **frame); */
+/* int getNmsFrame(u16 type, short ***frames, int * sizes, int keep_first_row, int fs, int n); */
+int getSenseLen(void);
+int getForceLen(void);
+int requestFrame(u16 type);
+int readFrameDataHeader(u16 type, DataHeader *header);
+int getMSFrame2(u16 type, MutualSenseFrame *frame);
+int getSSFrame2(u16 type, SelfSenseFrame *frame);
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsGesture.c b/drivers/input/touchscreen/st/fts_lib/ftsGesture.c
new file mode 100644
index 000000000000..ee97a417d4cb
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsGesture.c
@@ -0,0 +1,393 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS Gesture Utilities *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsSoftware.h"
+#include "ftsError.h"
+#include "ftsGesture.h"
+#include "ftsIO.h"
+#include "ftsTool.h"
+
+static char tag[8] = "[ FTS ]\0";
+
+static u8 gesture_mask[GESTURE_MASK_SIZE] = { 0 };
+static u8 custom_gestures[GESTURE_CUSTOM_NUMBER][GESTURE_CUSTOM_POINTS];
+static u8 custom_gesture_index[GESTURE_CUSTOM_NUMBER] = { 0 };
+
+int enableGesture(u8 *mask, int size)
+{
+ u8 cmd[size+2];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ int i, res;
+ int event_to_search[4] = {EVENTID_GESTURE, EVENT_TYPE_ENB, 0x00, GESTURE_ENABLE};
+
+ logError(0, "%s Trying to enable gesture...\n", tag);
+ cmd[0] = FTS_CMD_GESTURE_CMD;
+ cmd[1] = GESTURE_ENABLE;
+
+ if (size <= GESTURE_MASK_SIZE) {
+ if (mask != NULL) {
+ for (i = 0; i < size; i++) {
+ cmd[i + 2] = mask[i];
+ gesture_mask[i] = gesture_mask[i]|mask[i];
+ /* back up of the gesture enabled */
+ }
+ while (i < GESTURE_MASK_SIZE) {
+ cmd[i + 2] = gesture_mask[i];
+ i++;
+ }
+ } else {
+ for (i = 0; i < GESTURE_MASK_SIZE; i++) {
+ cmd[i + 2] = gesture_mask[i];
+ }
+ }
+
+ res = fts_writeFwCmd(cmd, GESTURE_MASK_SIZE + 2);
+ if (res < OK) {
+ logError(1, "%s enableGesture: ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
+ if (res < OK) {
+ logError(1, "%s enableGesture: pollForEvent ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ if (readData[4] != 0x00) {
+ logError(1, "%s enableGesture: ERROR %08X\n", tag, ERROR_GESTURE_ENABLE_FAIL);
+ return ERROR_GESTURE_ENABLE_FAIL;
+ }
+
+ logError(0, "%s enableGesture DONE!\n", tag);
+ return OK;
+ } else {
+ logError(1, "%s enableGesture: Size not valid! %d > %d ERROR %08X\n", tag, size, GESTURE_MASK_SIZE);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+}
+
+int disableGesture(u8 *mask, int size)
+{
+ u8 cmd[2+GESTURE_MASK_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ u8 temp;
+ int i, res;
+ int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, 0x00, GESTURE_DISABLE };
+
+ logError(0, "%s Trying to disable gesture...\n", tag);
+ cmd[0] = FTS_CMD_GESTURE_CMD;
+ cmd[1] = GESTURE_DISABLE;
+
+ if (size <= GESTURE_MASK_SIZE) {
+ if (mask != NULL) {
+ for (i = 0; i < size; i++) {
+ cmd[i + 2] = mask[i];
+ temp = gesture_mask[i] ^ mask[i];
+ /* enabled XOR disabled */
+ gesture_mask[i] = temp & gesture_mask[i];
+ /* disable the gestures that were enabled */
+ }
+ while (i < GESTURE_MASK_SIZE) {
+ cmd[i + 2] = gesture_mask[i];
+ /* disable all the other gesture not specified */
+ gesture_mask[i] = 0x00;
+ i++;
+ }
+ } else {
+ for (i = 0; i < GESTURE_MASK_SIZE; i++) {
+ cmd[i + 2] = gesture_mask[i];
+ }
+ }
+
+ res = fts_writeFwCmd(cmd, 2 + GESTURE_MASK_SIZE);
+ if (res < OK) {
+ logError(1, "%s disableGesture: ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
+ if (res < OK) {
+ logError(1, "%s disableGesture: pollForEvent ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ if (readData[4] != 0x00) {
+ logError(1, "%s disableGesture: ERROR %08X\n", tag, ERROR_GESTURE_ENABLE_FAIL);
+ return ERROR_GESTURE_ENABLE_FAIL;
+ }
+
+ logError(0, "%s disableGesture DONE!\n", tag);
+ return OK;
+ } else {
+ logError(1, "%s disableGesture: Size not valid! %d > %d ERROR %08X\n", tag, size, GESTURE_MASK_SIZE);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+int startAddCustomGesture(u8 gestureID)
+{
+ u8 cmd[3] = { FTS_CMD_GESTURE_CMD, GESTURE_START_ADD, gestureID };
+ int res;
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GESTURE_START_ADD };
+
+ res = fts_writeFwCmd(cmd, 3);
+ if (res < OK) {
+ logError(1, "%s startAddCustomGesture: Impossible to start adding custom gesture ID = %02X! ERROR %08X\n", tag, gestureID, res);
+ return res;
+ }
+
+ res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
+ if (res < OK) {
+ logError(1, "%s startAddCustomGesture: start add event not found! ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ if (readData[2] != gestureID || readData[4] != 0x00) { /* check of gestureID is redundant */
+ logError(1, "%s startAddCustomGesture: start add event status not OK! ERROR %08X\n", tag, readData[4]);
+ return ERROR_GESTURE_START_ADD;
+ }
+
+ return OK;
+}
+
+int finishAddCustomGesture(u8 gestureID)
+{
+ u8 cmd[3] = { FTS_CMD_GESTURE_CMD, GESTURE_FINISH_ADD, gestureID };
+ int res;
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GESTURE_FINISH_ADD };
+
+ res = fts_writeFwCmd(cmd, 3);
+ if (res < OK) {
+ logError(1, "%s finishAddCustomGesture: Impossible to finish adding custom gesture ID = %02X! ERROR %08X\n", tag, gestureID, res);
+ return res;
+ }
+
+ res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
+ if (res < OK) {
+ logError(1, "%s finishAddCustomGesture: finish add event not found! ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ if (readData[2] != gestureID || readData[4] != 0x00) { /* check of gestureID is redundant */
+ logError(1, "%s finishAddCustomGesture: finish add event status not OK! ERROR %08X\n", tag, readData[4]);
+ return ERROR_GESTURE_FINISH_ADD;
+ }
+
+ return OK;
+
+}
+
+int loadCustomGesture(u8 *template, u8 gestureID)
+{
+ int res, i;
+ int remaining = GESTURE_CUSTOM_POINTS;
+ int toWrite, offset = 0;
+ u8 cmd[TEMPLATE_CHUNK + 5];
+ int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GESTURE_DATA_ADD };
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+
+ logError(0, "%s Starting adding custom gesture procedure...\n", tag);
+
+ res = startAddCustomGesture(gestureID);
+ if (res < OK) {
+ logError(1, "%s loadCustomGesture: unable to start adding procedure! ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ cmd[0] = FTS_CMD_GESTURE_CMD;
+ cmd[1] = GESTURE_DATA_ADD;
+ cmd[2] = gestureID;
+ while (remaining > 0) {
+ if (remaining > TEMPLATE_CHUNK) {
+ toWrite = TEMPLATE_CHUNK;
+ } else {
+ toWrite = remaining;
+ }
+
+ cmd[3] = toWrite;
+ cmd[4] = offset;
+ for (i = 0; i < toWrite; i++) {
+ cmd[i + 5] = template[i];
+ }
+
+ res = fts_writeFwCmd(cmd, toWrite + 5);
+ if (res < OK) {
+ logError(1, "%s loadCustomGesture: unable to start adding procedure! ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
+ if (res < OK) {
+ logError(1, "%s loadCustomGesture: add event not found! ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ if (readData[2] != gestureID || readData[4] != 0x00) { /* check of gestureID is redundant */
+ logError(1, "%s loadCustomGesture: add event status not OK! ERROR %08X\n", tag, readData[4]);
+ return ERROR_GESTURE_DATA_ADD;
+ }
+
+ remaining -= toWrite;
+ offset += toWrite / 2;
+ }
+
+ res = finishAddCustomGesture(gestureID);
+ if (res < OK) {
+ logError(1, "%s loadCustomGesture: unable to finish adding procedure! ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ logError(0, "%s Adding custom gesture procedure DONE!\n", tag);
+ return OK;
+
+}
+
+int reloadCustomGesture(void)
+{
+ int res, i;
+
+ logError(0, "%s Starting reload Gesture Template...\n", tag);
+
+ for (i = 0; i < GESTURE_CUSTOM_NUMBER; i++) {
+ if (custom_gesture_index[i] == 1) {
+ res = loadCustomGesture(custom_gestures[i], GESTURE_CUSTOM_OFFSET+i);
+ if (res < OK) {
+ logError(1, "%s reloadCustomGesture: Impossible to load custom gesture ID = %02X! ERROR %08X\n", tag, GESTURE_CUSTOM_OFFSET + i, res);
+ return res;
+ }
+ }
+ }
+
+ logError(0, "%s Reload Gesture Template DONE!\n", tag);
+ return OK;
+
+}
+
+int enterGestureMode(int reload)
+{
+ u8 cmd = FTS_CMD_GESTURE_MODE;
+ int res, ret;
+
+ res = fts_disableInterrupt();
+ if (res < OK) {
+ logError(1, "%s enterGestureMode: ERROR %08X\n", tag, res|ERROR_DISABLE_INTER);
+ return res | ERROR_DISABLE_INTER;
+ }
+
+ if (reload == 1) {
+
+ res = reloadCustomGesture();
+ if (res < OK) {
+ logError(1, "%s enterGestureMode: impossible reload custom gesture! ERROR %08X\n", tag, res);
+ goto END;
+ }
+
+ res = disableGesture(NULL, 0);
+ if (res < OK) {
+ logError(1, "%s enterGestureMode: disableGesture ERROR %08X\n", tag, res);
+ goto END;
+ }
+
+ res = enableGesture(NULL, 0);
+ if (res < OK) {
+ logError(1, "%s enterGestureMode: enableGesture ERROR %08X\n", tag, res);
+ goto END;
+ }
+ }
+
+ res = fts_writeFwCmd(&cmd, 1);
+ if (res < OK) {
+ logError(1, "%s enterGestureMode: enter gesture mode ERROR %08X\n", tag, res);
+ goto END;
+ }
+
+ res = OK;
+END:
+ ret = fts_enableInterrupt();
+ if (ret < OK) {
+ logError(1, "%s enterGestureMode: fts_enableInterrupt ERROR %08X\n", tag, res | ERROR_ENABLE_INTER);
+ res |= ret | ERROR_ENABLE_INTER;
+ }
+
+ return res;
+}
+
+int addCustomGesture(u8 *data, int size, u8 gestureID)
+{
+ int index, res, i;
+
+ index = gestureID - GESTURE_CUSTOM_OFFSET;
+
+ logError(0, "%s Starting Custom Gesture Adding procedure...\n", tag);
+ if (size != GESTURE_CUSTOM_POINTS && gestureID != GES_ID_CUST1 && gestureID != GES_ID_CUST2 && gestureID != GES_ID_CUST3 && gestureID != GES_ID_CUST4 && gestureID && GES_ID_CUST5) {
+ logError(1, "%s addCustomGesture: Invalid size (%d) or Custom GestureID (%02X)! ERROR %08X\n", tag, size, gestureID, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ for (i = 0; i < GESTURE_CUSTOM_POINTS; i++) {
+ custom_gestures[index][i] = data[i];
+ }
+
+ res = loadCustomGesture(custom_gestures[index], gestureID);
+ if (res < OK) {
+ logError(1, "%s addCustomGesture: impossible to load the custom gesture! ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ custom_gesture_index[index] = 1;
+ logError(0, "%s Custom Gesture Adding procedure DONE!\n", tag);
+ return OK;
+}
+
+int removeCustomGesture(u8 gestureID)
+{
+ int res, index;
+ u8 cmd[3] = { FTS_CMD_GESTURE_CMD, GETURE_REMOVE_CUSTOM, gestureID };
+ int event_to_search[4] = {EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GETURE_REMOVE_CUSTOM };
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+
+ index = gestureID - GESTURE_CUSTOM_OFFSET;
+
+ logError(0, "%s Starting Custom Gesture Removing procedure...\n", tag);
+ if (gestureID != GES_ID_CUST1 && gestureID != GES_ID_CUST2 && gestureID != GES_ID_CUST3 && gestureID != GES_ID_CUST4 && gestureID && GES_ID_CUST5) {
+ logError(1, "%s removeCustomGesture: Invalid size (%d) or Custom GestureID (%02X)! ERROR %08X\n", tag, gestureID, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ res = fts_writeFwCmd(cmd, 3);/* when a gesture is removed, it is also disabled automatically */
+ if (res < OK) {
+ logError(1, "%s removeCustomGesture: Impossible to remove custom gesture ID = %02X! ERROR %08X\n", tag, gestureID, res);
+ return res;
+ }
+
+ res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
+ if (res < OK) {
+ logError(1, "%s removeCustomGesture: remove event not found! ERROR %08X\n", tag, res);
+ return res;
+ }
+
+ if (readData[2] != gestureID || readData[4] != 0x00) { /* check of gestureID is redundant */
+ logError(1, "%s removeCustomGesture: remove event status not OK! ERROR %08X\n", tag, readData[4]);
+ return ERROR_GESTURE_REMOVE;
+ }
+
+ custom_gesture_index[index] = 0;
+ logError(0, "%s Custom Gesture Remove procedure DONE!\n", tag);
+ return OK;
+
+}
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsGesture.h b/drivers/input/touchscreen/st/fts_lib/ftsGesture.h
new file mode 100644
index 000000000000..a9c3e3c05573
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsGesture.h
@@ -0,0 +1,74 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS Gesture Utilities *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#define GESTURE_MASK_SIZE 8
+
+#define GESTURE_CUSTOM_POINTS (30*2)
+/* for each custom gesture should be provided 30 points (each point is a couple of x,y) */
+#define GESTURE_CUSTOM_NUMBER 5 /* fw support up to 5 custom gestures */
+
+#define TEMPLATE_CHUNK (10*2)
+/* number of points to transfer with each I2C transaction */
+
+/* Gesture IDs */
+#define GES_ID_DBLTAP 0x01 /* Double Tap */
+#define GES_ID_O 0x02 /* 'O' */
+#define GES_ID_C 0x03 /* 'C' */
+#define GES_ID_M 0x04 /* 'M' */
+#define GES_ID_W 0x05 /* 'W' */
+#define GES_ID_E 0x06 /* 'e' */
+#define GES_ID_HFLIP_L2R 0x07 /* Left to right line */
+#define GES_ID_HFLIP_R2L 0x08 /* Right to left line */
+#define GES_ID_VFLIP_T2D 0x09 /* Top to bottom line */
+#define GES_ID_VFLIP_D2T 0x0A /* Bottom to Top line */
+#define GES_ID_L 0x0B /* 'L' */
+#define GES_ID_F 0x0C /* 'F' */
+#define GES_ID_V 0x0D /* 'V' */
+#define GES_ID_AT 0x0E /* '@' */
+#define GES_ID_S 0x0F /* 'S' */
+#define GES_ID_Z 0x10 /* 'Z' */
+#define GES_ID_CUST1 0x11 /* Custom gesture 1 */
+#define GES_ID_CUST2 0x12 /* Custom gesture 2 */
+#define GES_ID_CUST3 0x13 /* Custom gesture 3 */
+#define GES_ID_CUST4 0x14 /* Custom gesture 4 */
+#define GES_ID_CUST5 0x15 /* Custom gesture 5 */
+#define GES_ID_LEFTBRACE 0x20 /* '<' */
+#define GES_ID_RIGHTBRACE 0x21 /* '>' */
+
+#define GESTURE_CUSTOM_OFFSET GES_ID_CUST1
+
+/* Command sub-type */
+#define GESTURE_ENABLE 0x01
+#define GESTURE_DISABLE 0x02
+#define GESTURE_ENB_CHECK 0x03
+#define GESTURE_START_ADD 0x10
+#define GESTURE_DATA_ADD 0x11
+#define GESTURE_FINISH_ADD 0x12
+#define GETURE_REMOVE_CUSTOM 0x13
+#define GESTURE_CHECK_CUSTOM 0x14
+
+/* Event sub-type */
+#define EVENT_TYPE_ENB 0x04
+#define EVENT_TYPE_CHECK_ENB 0x03
+#define EVENT_TYPE_GESTURE_DTC1 0x01
+#define EVENT_TYPE_GESTURE_DTC2 0x02
+
+int disableGesture(u8 *mask, int size);
+int enableGesture(u8 *mask, int size);
+int startAddCustomGesture(u8 gestureID);
+int finishAddCustomGesture(u8 gestureID);
+int loadCustomGesture(u8 *template, u8 gestureID);
+int reloadCustomGesture(void);
+int enterGestureMode(int reload);
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsHardware.h b/drivers/input/touchscreen/st/fts_lib/ftsHardware.h
new file mode 100644
index 000000000000..933059e671b4
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsHardware.h
@@ -0,0 +1,177 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* HW related data *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#define FTM3_CHIP
+
+/* DUMMY BYTES DATA */
+#define DUMMY_HW_REG 1
+#define DUMMY_FRAMEBUFFER 1
+#define DUMMY_MEMORY 1
+
+/* DIGITAL CHIP INFO */
+#ifdef FTM3_CHIP
+#define DCHIP_ID_0 0x39
+#define DCHIP_ID_1 0x6C
+#else
+#define DCHIP_ID_0 0x36
+#define DCHIP_ID_1 0x70
+#endif
+
+#ifdef FTM3_CHIP
+#define DCHIP_ID_ADDR 0x0007
+#define DCHIP_FW_VER_ADDR 0x000A
+#else
+#define DCHIP_ID_ADDR 0x0004
+#define DCHIP_FW_VER_ADDR 0x000B
+#endif
+
+#define DCHIP_FW_VER_BYTE 2
+
+/* CHUNKS */
+#define READ_CHUNK (2*1024)
+#define WRITE_CHUNK (2*1024)
+#define MEMORY_CHUNK (2*1024)
+
+/* PROTOCOL INFO */
+#ifdef FTM3_CHIP
+#define I2C_SAD 0x49
+#else
+#define I2C_SAD 0x48
+#endif
+
+#define I2C_INTERFACE /* comment if the chip use SPI */
+#define ICR_ADDR 0x0024
+#define ICR_SPI_VALUE 0x02
+
+/* SYSTEM RESET INFO */
+#ifdef FTM3_CHIP
+#define SYSTEM_RESET_ADDRESS 0x0023
+#define SYSTEM_RESET_VALUE 0x01
+#else
+#define SYSTEM_RESET_ADDRESS 0x0028
+#define SYSTEM_RESET_VALUE 0x80
+#endif
+
+/* INTERRUPT INFO */
+#ifdef FTM3_CHIP
+#define IER_ADDR 0x001C
+#else
+#define IER_ADDR 0x002C
+#endif
+
+#define IER_ENABLE 0x41
+#define IER_DISABLE 0x00
+
+/* FLASH COMMAND */
+
+#define FLASH_CMD_UNLOCK 0xF7
+
+#ifdef FTM3_CHIP
+#define FLASH_CMD_WRITE_LOWER_64 0xF0
+#define FLASH_CMD_WRITE_UPPER_64 0xF1
+#define FLASH_CMD_BURN 0xF2
+#define FLASH_CMD_ERASE 0xF3
+#define FLASH_CMD_READSTATUS 0xF4
+#else
+#define FLASH_CMD_WRITE_64K 0xF8
+#define FLASH_CMD_READ_REGISTER 0xF9
+#define FLASH_CMD_WRITE_REGISTER 0xFA
+#endif
+
+/* FLASH UNLOCK PARAMETER */
+#define FLASH_UNLOCK_CODE0 0x74
+#define FLASH_UNLOCK_CODE1 0x45
+
+#ifndef FTM3_CHIP
+/* FLASH ERASE and DMA PARAMETER */
+#define FLASH_ERASE_UNLOCK_CODE0 0x72
+#define FLASH_ERASE_UNLOCK_CODE1 0x03
+#define FLASH_ERASE_UNLOCK_CODE2 0x02
+#define FLASH_ERASE_CODE0 0x02
+#define FLASH_ERASE_CODE1 0xC0
+#define FLASH_DMA_CODE0 0x05
+#define FLASH_DMA_CODE1 0xC0
+#define FLASH_DMA_CONFIG 0x06
+#endif
+
+/* FLASH ADDRESS */
+#ifdef FTM3_CHIP
+#define FLASH_ADDR_SWITCH_CMD 0x00010000
+#define FLASH_ADDR_CODE 0x00000000
+#define FLASH_ADDR_CONFIG 0x0001E800
+#define FLASH_ADDR_CX 0x0001F000
+#else
+#define ADDR_WARM_BOOT 0x001E
+#define WARM_BOOT_VALUE 0x38
+#define FLASH_ADDR_CODE 0x00000000
+#define FLASH_ADDR_CONFIG 0x0000FC00
+#endif
+
+/* CRC ADDR */
+#ifdef FTM3_CHIP
+#define ADDR_CRC_BYTE0 0x00
+#define ADDR_CRC_BYTE1 0x86
+#define CRC_MASK 0x02
+#else
+#define ADDR_CRC_BYTE0 0x00
+#define ADDR_CRC_BYTE1 0x74
+#define CRC_MASK 0x03
+#endif
+
+/* SIZES FW, CODE, CONFIG, MEMH */
+#ifdef FTM3_CHIP
+#define FW_HEADER_SIZE 32
+#define FW_SIZE (int)(128*1024)
+#define FW_CODE_SIZE (int)(122*1024)
+#define FW_CONFIG_SIZE (int)(2*1024)
+#define FW_CX_SIZE (int)(FW_SIZE-FW_CODE_SIZE-FW_CONFIG_SIZE)
+#define FW_VER_MEMH_BYTE1 193
+#define FW_VER_MEMH_BYTE0 192
+#define FW_OFF_CONFID_MEMH_BYTE1 2
+#define FW_OFF_CONFID_MEMH_BYTE0 1
+#define FW_BIN_VER_OFFSET 4
+#define FW_BIN_CONFIG_VER_OFFSET (FW_HEADER_SIZE+FW_CODE_SIZE+1)
+#else
+#define FW_HEADER_SIZE 64
+#define FW_HEADER_SIGNATURE 0xAA55AA55
+#define FW_FTB_VER 0x00000001
+#define FW_BYTES_ALIGN 4
+#define FW_BIN_VER_OFFSET 16
+#define FW_BIN_CONFIG_VER_OFFSET 20
+#endif
+
+/* FIFO */
+#define FIFO_EVENT_SIZE 8
+#ifdef FTM3_CHIP
+#define FIFO_DEPTH 32
+#else
+#define FIFO_DEPTH 64
+#endif
+
+#define FIFO_CMD_READONE 0x85
+#define FIFO_CMD_READALL 0x86
+#define FIFO_CMD_LAST 0x87
+#define FIFO_CMD_FLUSH 0xA1
+
+/* CONSTANT TOTAL CX */
+#define CX1_WEIGHT 4
+#define CX2_WEIGHT 1
+
+/* OP CODES FOR MEMORY (based on protocol) */
+
+#define FTS_CMD_HW_REG_R 0xB6
+#define FTS_CMD_HW_REG_W 0xB6
+#define FTS_CMD_FRAMEBUFFER_R 0xD0
+#define FTS_CMD_FRAMEBUFFER_W 0xD0
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsIO.c b/drivers/input/touchscreen/st/fts_lib/ftsIO.c
new file mode 100644
index 000000000000..96ca8cfecd8a
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsIO.c
@@ -0,0 +1,403 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* I2C/SPI Communication *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsSoftware.h"
+#include "ftsCrossCompile.h"
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+/* #include <linux/sec_sysfs.h> */
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/spi/spidev.h>
+static struct i2c_client *client;
+static u16 I2CSAD;
+
+#include "ftsError.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+#include "ftsTool.h"
+
+static char tag[8] = "[ FTS ]\0";
+
+int openChannel(struct i2c_client *clt)
+{
+ client = clt;
+ I2CSAD = clt->addr;
+ logError(1, "%s openChannel: SAD: %02X\n", tag, I2CSAD);
+ return OK;
+}
+
+struct device *getDev(void)
+{
+ if (client != NULL)
+ return &(client->dev);
+ else
+ return NULL;
+}
+
+struct i2c_client *getClient(void)
+{
+ if (client != NULL)
+ return client;
+ else
+ return NULL;
+}
+
+int fts_readCmd(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead)
+{
+ int ret = -1;
+ int retry = 0;
+ struct i2c_msg I2CMsg[2];
+
+ /* write msg */
+ I2CMsg[0].addr = (__u16)I2CSAD;
+ I2CMsg[0].flags = (__u16)0;
+ I2CMsg[0].len = (__u16)cmdLength;
+ I2CMsg[0].buf = (__u8 *)cmd;
+
+ /* read msg */
+ I2CMsg[1].addr = (__u16)I2CSAD;
+ I2CMsg[1].flags = I2C_M_RD;
+ I2CMsg[1].len = byteToRead;
+ I2CMsg[1].buf = (__u8 *)outBuf;
+
+ if (client == NULL)
+ return ERROR_I2C_O;
+ while (retry < I2C_RETRY && ret < OK) {
+ ret = i2c_transfer(client->adapter, I2CMsg, 2);
+ if (ret >= OK)
+ break;
+ retry++;
+ msleep(I2C_WAIT_BEFORE_RETRY);
+ }
+ if (ret < 0) {
+ logError(1, "%s fts_readCmd: ERROR %02X\n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+ return OK;
+}
+
+int fts_writeCmd(u8 *cmd, int cmdLength)
+{
+ int ret = -1;
+ int retry = 0;
+ struct i2c_msg I2CMsg[2];
+
+ I2CMsg[0].addr = (__u16)I2CSAD;
+ I2CMsg[0].flags = (__u16)0;
+ I2CMsg[0].len = (__u16)cmdLength;
+ I2CMsg[0].buf = (__u8 *)cmd;
+
+ if (client == NULL)
+return ERROR_I2C_O;
+ while (retry < I2C_RETRY && ret < OK) {
+ ret = i2c_transfer(client->adapter, I2CMsg, 1);
+ if (ret >= OK)
+ break;
+ retry++;
+ msleep(I2C_WAIT_BEFORE_RETRY);
+ /* logError(1, "%s fts_writeCmd: attempt %d\n", tag, retry); */
+ }
+ if (ret < 0) {
+ logError(1, "%s fts_writeCmd: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+ return OK;
+}
+
+int fts_writeFwCmd(u8 *cmd, int cmdLength)
+{
+ int ret = -1;
+ int ret2 = -1;
+ int retry = 0;
+ struct i2c_msg I2CMsg[2];
+
+ I2CMsg[0].addr = (__u16)I2CSAD;
+ I2CMsg[0].flags = (__u16)0;
+ I2CMsg[0].len = (__u16)cmdLength;
+ I2CMsg[0].buf = (__u8 *)cmd;
+
+ if (client == NULL)
+return ERROR_I2C_O;
+ while (retry < I2C_RETRY && (ret < OK || ret2 < OK)) {
+ ret = i2c_transfer(client->adapter, I2CMsg, 1);
+ retry++;
+ if (ret >= 0) {
+ ret2 = checkEcho(cmd, cmdLength);
+ break;
+ }
+ msleep(I2C_WAIT_BEFORE_RETRY);
+ /* logError(1, "%s fts_writeCmd: attempt %d\n", tag, retry); */
+ }
+ if (ret < 0) {
+ logError(1, "%s fts_writeFwCmd: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+ if (ret2 < OK) {
+ logError(1, "%s fts_writeFwCmd: check echo ERROR %02X\n", tag, ret2);
+ return (ret|ERROR_I2C_W);
+ }
+ return OK;
+}
+
+int writeReadCmd(u8 *writeCmd1, int writeCmdLength, u8 *readCmd1,
+ int readCmdLength, u8 *outBuf, int byteToRead)
+{
+ int ret = -1;
+ int retry = 0;
+ struct i2c_msg I2CMsg[3];
+
+ /* write msg */
+ I2CMsg[0].addr = (__u16)I2CSAD;
+ I2CMsg[0].flags = (__u16)0;
+ I2CMsg[0].len = (__u16)writeCmdLength;
+ I2CMsg[0].buf = (__u8 *)writeCmd1;
+
+ /* write msg */
+ I2CMsg[1].addr = (__u16)I2CSAD;
+ I2CMsg[1].flags = (__u16)0;
+ I2CMsg[1].len = (__u16)readCmdLength;
+ I2CMsg[1].buf = (__u8 *)readCmd1;
+
+ /* read msg */
+ I2CMsg[2].addr = (__u16)I2CSAD;
+ I2CMsg[2].flags = I2C_M_RD;
+ I2CMsg[2].len = byteToRead;
+ I2CMsg[2].buf = (__u8 *)outBuf;
+
+ if (client == NULL)
+ return ERROR_I2C_O;
+ while (retry < I2C_RETRY && ret < OK) {
+ ret = i2c_transfer(client->adapter, I2CMsg, 3);
+ if (ret >= OK)
+ break;
+ retry++;
+ msleep(I2C_WAIT_BEFORE_RETRY);
+ }
+
+ if (ret < 0) {
+ logError(1, "%s writeReadCmd: ERROR %02X\n", tag, ERROR_I2C_WR);
+ return ERROR_I2C_WR;
+ }
+ return OK;
+
+}
+
+int readCmdU16(u8 cmd, u16 address, u8 *outBuf, int byteToRead, int hasDummyByte)
+{
+
+ int remaining = byteToRead;
+ int toRead = 0;
+ u8 rCmd[3] = { cmd, 0x00, 0x00 };
+
+ u8 *buff = (u8 *)kmalloc((READ_CHUNK + 1)*sizeof(u8), GFP_KERNEL);
+ if (buff == NULL) {
+ logError(1, "%s readCmdU16: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ while (remaining > 0) {
+ if (remaining >= READ_CHUNK) {
+ toRead = READ_CHUNK;
+ remaining -= READ_CHUNK;
+ } else {
+ toRead = remaining;
+ remaining = 0;
+ }
+
+ rCmd[1] = (u8)((address & 0xFF00) >> 8);
+ rCmd[2] = (u8)(address & 0xFF);
+
+ if (hasDummyByte) {
+ if (fts_readCmd(rCmd, 3, buff, toRead + 1) < 0) {
+ logError(1, "%s readCmdU16: ERROR %02X\n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+ }
+ memcpy(outBuf, buff + 1, toRead);
+ } else {
+ if (fts_readCmd(rCmd, 3, buff, toRead) < 0)
+ return ERROR_I2C_R;
+ memcpy(outBuf, buff, toRead);
+ }
+
+ address += toRead;
+
+ outBuf += toRead;
+
+ }
+ kfree(buff);
+
+ return OK;
+}
+
+int writeCmdU16(u8 WriteCmd, u16 address, u8 *dataToWrite, int byteToWrite)
+{
+
+ int remaining = byteToWrite;
+ int toWrite = 0;
+
+ u8 *buff = (u8 *)kmalloc((WRITE_CHUNK + 3)*sizeof(u8), GFP_KERNEL);
+ if (buff == NULL) {
+ logError(1, "%s writeCmdU16: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ buff[0] = WriteCmd;
+
+ while (remaining > 0) {
+ if (remaining >= WRITE_CHUNK) {
+ toWrite = WRITE_CHUNK;
+ remaining -= WRITE_CHUNK;
+ } else {
+ toWrite = remaining;
+ remaining = 0;
+ }
+
+ buff[1] = (u8)((address & 0xFF00) >> 8);
+ buff[2] = (u8)(address & 0xFF);
+ memcpy(buff + 3, dataToWrite, toWrite);
+ if (fts_writeCmd(buff, 3 + toWrite) < 0) {
+ logError(1, "%s writeCmdU16: ERROR %02\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+ address += toWrite;
+ dataToWrite += toWrite;
+
+ }
+
+ return OK;
+}
+
+int writeCmdU32(u8 writeCmd1, u8 writeCmd2, u32 address, u8 *dataToWrite, int byteToWrite)
+{
+
+ int remaining = byteToWrite;
+ int toWrite = 0;
+
+ u8 buff1[3] = { writeCmd1, 0x00, 0x00 };
+ u8 *buff2 = (u8 *)kmalloc((WRITE_CHUNK + 3)*sizeof(u8), GFP_KERNEL);
+ if (buff2 == NULL) {
+ logError(1, "%s writeCmdU32: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+ buff2[0] = writeCmd2;
+
+ while (remaining > 0) {
+ if (remaining >= WRITE_CHUNK) {
+ toWrite = WRITE_CHUNK;
+ remaining -= WRITE_CHUNK;
+ } else {
+ toWrite = remaining;
+ remaining = 0;
+ }
+
+ buff1[1] = (u8)((address & 0xFF000000) >> 24);
+ buff1[2] = (u8)((address & 0x00FF0000) >> 16);
+ buff2[1] = (u8)((address & 0x0000FF00) >> 8);
+ buff2[2] = (u8)(address & 0xFF);
+ memcpy(buff2 + 3, dataToWrite, toWrite);
+
+ if (fts_writeCmd(buff1, 3) < 0) {
+ logError(1, "%s writeCmdU32: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+ if (fts_writeCmd(buff2, 3 + toWrite) < 0) {
+ logError(1, "%s writeCmdU32: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ address += toWrite;
+ dataToWrite += toWrite;
+
+ }
+
+ return OK;
+}
+
+int writeReadCmdU32(u8 wCmd, u8 rCmd, u32 address, u8 *outBuf, int byteToRead, int hasDummyByte)
+{
+
+ int remaining = byteToRead;
+ int toRead = 0;
+ u8 reaCmd[3];
+ u8 wriCmd[3];
+
+ u8 *buff = (u8 *)kmalloc((READ_CHUNK + 1)*sizeof(u8), GFP_KERNEL);
+ if (buff == NULL) {
+ logError(1, "%s writereadCmd32: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ reaCmd[0] = rCmd;
+ wriCmd[0] = wCmd;
+
+ while (remaining > 0) {
+ if (remaining >= READ_CHUNK) {
+ toRead = READ_CHUNK;
+ remaining -= READ_CHUNK;
+ } else {
+ toRead = remaining;
+ remaining = 0;
+ }
+
+ wriCmd[1] = (u8)((address & 0xFF000000) >> 24);
+ wriCmd[2] = (u8)((address & 0x00FF0000) >> 16);
+
+ reaCmd[1] = (u8)((address & 0x0000FF00) >> 8);
+ reaCmd[2] = (u8)(address & 0x000000FF);
+
+ if (hasDummyByte) {
+ if (writeReadCmd(wriCmd, 3, reaCmd, 3, buff, toRead + 1) < 0) {
+ logError(1, "%s writeCmdU32: ERROR %02X\n", tag, ERROR_I2C_WR);
+ return ERROR_I2C_WR;
+ }
+ memcpy(outBuf, buff + 1, toRead);
+ } else {
+ if (writeReadCmd(wriCmd, 3, reaCmd, 3, buff, toRead) < 0)
+ return ERROR_I2C_WR;
+ memcpy(outBuf, buff, toRead);
+ }
+
+ address += toRead;
+
+ outBuf += toRead;
+
+ }
+
+ return OK;
+}
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsIO.h b/drivers/input/touchscreen/st/fts_lib/ftsIO.h
new file mode 100644
index 000000000000..7bdeda2f9a2d
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsIO.h
@@ -0,0 +1,35 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* I2C/SPI Communication *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsSoftware.h"
+#include "ftsCrossCompile.h"
+
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#define I2C_RETRY 3 /* number */
+#define I2C_WAIT_BEFORE_RETRY 10 /* ms */
+
+int openChannel(struct i2c_client *clt);
+struct device *getDev(void);
+struct i2c_client *getClient(void);
+int fts_readCmd(u8 *cmd, int cmdLenght, u8 *outBuf, int byteToRead);
+int fts_writeCmd(u8 *cmd, int cmdLenght);
+int fts_writeFwCmd(u8 *cmd, int cmdLenght);
+int writeReadCmd(u8 *writeCmd, int writeCmdLenght, u8 *readCmd, int readCmdLenght, u8 *outBuf, int byteToRead);
+int readCmdU16(u8 cmd, u16 address, u8 *outBuf, int byteToRead, int hasDummyByte);
+int writeCmdU16(u8 WriteCmd, u16 address, u8 *dataToWrite, int byteToWrite);
+int writeCmdU32(u8 writeCmd1, u8 writeCmd2, u32 address, u8 *dataToWrite, int byteToWrite);
+int writeReadCmdU32(u8 wCmd, u8 rCmd, u32 address, u8 *outBuf, int byteToRead, int hasDummyByte);
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsSoftware.h b/drivers/input/touchscreen/st/fts_lib/ftsSoftware.h
new file mode 100644
index 000000000000..c8bbc8e18d28
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsSoftware.h
@@ -0,0 +1,131 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FW related data *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsHardware.h"
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+#define ECHO_ENABLED 0x00000001
+
+/* chipInfo ftsInfo; */
+
+/* FTS FW COMAND */
+#define FTS_CMD_MS_MT_SENSE_OFF 0x92
+#define FTS_CMD_MS_MT_SENSE_ON 0x93
+#define FTS_CMD_SS_HOVER_OFF 0x94
+#define FTS_CMD_SS_HOVER_ON 0x95
+#define FTS_CMD_LP_TIMER_CALIB 0x97
+#define FTS_CMD_MS_KEY_OFF 0x9A
+#define FTS_CMD_MS_KEY_ON 0x9B
+#define FTS_CMD_MS_COMP_TUNING 0xA3
+#define FTS_CMD_SS_COMP_TUNING 0xA4
+#define FTS_CMD_FULL_INITIALIZATION 0xA5
+#define FTS_CMD_ITO_CHECK 0xA7
+#define FTS_CMD_RELEASE_INFO 0xAA
+#define FTS_CMD_GESTURE_MODE 0xAD
+#define FTS_CMD_REQU_FW_CONF 0xB2
+#define FTS_CMD_REQU_FRAME_DATA 0xB7
+#define FTS_CMD_REQU_COMP_DATA 0xB8
+#define FTS_CMD_WRITE_MP_FLAG 0xC0
+#define FTS_CMD_FEATURE_ENABLE 0xC1
+#define FTS_CMD_FEATURE_DISABLE 0xC2
+#define FTS_CMD_GESTURE_CMD 0xC3
+#define FTS_CMD_SAVE_CX_TUNING 0xFC
+
+/* Event ID */
+#define EVENTID_NO_EVENT 0x00
+#define EVENTID_ERROR_EVENT 0x0F
+#define EVENTID_CONTROL_READY 0x10
+#define EVENTID_FW_CONFIGURATION 0x12
+#define EVENTID_COMP_DATA_READ 0x13
+#define EVENTID_STATUS_UPDATE 0x16
+#define EVENTID_RELEASE_INFO 0x1C
+#define EVENTID_ENTER_POINTER 0x03
+#define EVENTID_LEAVE_POINTER 0x04
+#define EVENTID_MOTION_POINTER 0x05
+#define EVENTID_HOVER_ENTER_POINTER 0x07
+#define EVENTID_HOVER_LEAVE_POINTER 0x08
+#define EVENTID_HOVER_MOTION_POINTER 0x09
+#define EVENTID_PROXIMITY_ENTER 0x0B
+#define EVENTID_PROXIMITY_LEAVE 0x0C
+#define EVENTID_KEY_STATUS 0x0E
+#define EVENTID_GESTURE 0x22
+#define EVENTID_FRAME_DATA_READ 0x25
+#define EVENTID_ECHO 0xEC
+#define EVENTID_LAST (EVENTID_FRAME_DATA_READ+1)
+
+/* EVENT TYPE */
+#define EVENT_TYPE_MS_TUNING_CMPL 0x01
+#define EVENT_TYPE_SS_TUNING_CMPL 0x02
+#define EVENT_TYPE_COMP_DATA_SAVED 0x04
+#define EVENT_TYPE_ITO 0x05
+#define EVENT_TYPE_FULL_INITIALIZATION 0x07
+#define EVENT_TYPE_LPTIMER_TUNING_CMPL 0x20
+#define EVENT_TYPE_ESD_ERROR 0x0A
+#define EVENT_TYPE_WATCHDOG_ERROR 0x01
+
+/* CONFIG ID INFO */
+#define CONFIG_ID_ADDR 0x0001
+#define CONFIG_ID_BYTE 2
+
+/* ADDRESS OFFSET IN SYSINFO */
+#define ADDR_RAW_TOUCH 0x0000
+#define ADDR_FILTER_TOUCH 0x0002
+#define ADDR_NORM_TOUCH 0x0004
+#define ADDR_CALIB_TOUCH 0x0006
+#define ADDR_RAW_HOVER_FORCE 0x000A
+#define ADDR_RAW_HOVER_SENSE 0x000C
+#define ADDR_FILTER_HOVER_FORCE 0x000E
+#define ADDR_FILTER_HOVER_SENSE 0x0010
+#define ADDR_NORM_HOVER_FORCE 0x0012
+#define ADDR_NORM_HOVER_SENSE 0x0014
+#define ADDR_CALIB_HOVER_FORCE 0x0016
+#define ADDR_CALIB_HOVER_SENSE 0x0018
+#define ADDR_RAW_PRX_FORCE 0x001A
+#define ADDR_RAW_PRX_SENSE 0x001C
+#define ADDR_FILTER_PRX_FORCE 0x001E
+#define ADDR_FILTER_PRX_SENSE 0x0020
+#define ADDR_NORM_PRX_FORCE 0x0022
+#define ADDR_NORM_PRX_SENSE 0x0024
+#define ADDR_CALIB_PRX_FORCE 0x0026
+#define ADDR_CALIB_PRX_SENSE 0x0028
+#define ADDR_RAW_MS_KEY 0x0032
+#define ADDR_COMP_DATA 0x0050
+#define ADDR_FRAMEBUFFER_DATA 0x8000
+
+/* ADDRESS FW REGISTER */
+#define ADDR_SENSE_LEN 0x0014
+#define ADDR_FORCE_LEN 0x0015
+#define ADDR_MS_TUNING_VER 0x0729
+#define ADDR_SS_TUNING_VER 0x074E
+
+/* B2 INFO */
+#define B2_DATA_BYTES 4
+#define B2_CHUNK ((FIFO_DEPTH/2)*B2_DATA_BYTES) /* number of bytes */
+
+/* FEATURES */
+#define FEAT_GESTURE 0x00
+#define FEAT_GLOVE 0x01
+#define FEAT_STYLUS 0x02
+#define FEAT_COVER 0x04
+#define FEAT_CHARGER 0x08
+#define FEAT_VR 0x10
+#define FEAT_EDGE_REJECTION 0x20
+
+/* MP_FLAG_VALUE */
+#define INIT_MP 0xA5A5A501
+#define INIT_FIELD 0xA5A5A502
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsTest.c b/drivers/input/touchscreen/st/fts_lib/ftsTest.c
new file mode 100644
index 000000000000..3810fd02001a
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsTest.c
@@ -0,0 +1,2324 @@
+/*
+
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS API for MP test *
+ * *
+ **************************************************************************
+ **************************************************************************
+
+ */
+
+#include "ftsCrossCompile.h"
+#include "ftsCompensation.h"
+#include "ftsError.h"
+#include "ftsFrame.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTest.h"
+#include "ftsTime.h"
+#include "ftsTool.h"
+#include "../fts.h"
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/time.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+/* #include <linux/sec_sysfs.h> */
+
+#ifdef LIMITS_H_FILE
+#include <../fts_limits.h>
+#endif
+
+/* static char tag[8] = "[ FTS ]\0"; */
+
+int computeAdjHoriz(u8 *data, int row, int column, u8 **result)
+{
+ int i, j;
+ int size = row * (column - 1);
+
+ if (column < 2) {
+ logError(1, "%s computeAdjHoriz: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u8 *) kmalloc(size * sizeof (u8), GFP_KERNEL);
+ if (*result == NULL) {
+ logError(1, "%s computeAdjHoriz: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 0; i < row; i++) {
+ for (j = 1; j < column; j++) {
+ *(*result + (i * (column - 1) + (j - 1))) = abs(data[i * column + j] - data[i * column + (j - 1)]);
+ }
+ }
+
+ return OK;
+
+}
+
+int computeAdjHorizTotal(u16 *data, int row, int column, u16 **result)
+{
+ int i, j;
+ int size = row * (column - 1);
+
+ if (column < 2) {
+ logError(1, "%s computeAdjHorizTotal: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u16 *) kmalloc(size * sizeof (u16), GFP_KERNEL);
+ if (*result == NULL) {
+ logError(1, "%s computeAdjHorizTotal: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 0; i < row; i++) {
+ for (j = 1; j < column; j++) {
+ *(*result + (i * (column - 1) + (j - 1))) = abs(data[i * column + j] - data[i * column + (j - 1)]);
+ }
+ }
+
+ return OK;
+
+}
+
+int computeAdjVert(u8 *data, int row, int column, u8 **result)
+{
+ int i, j;
+ int size = (row - 1)*(column);
+
+ if (row < 2) {
+ logError(1, "%s computeAdjVert: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u8 *) kmalloc(size * sizeof (u8), GFP_KERNEL);
+ if (*result == NULL) {
+ logError(1, "%s computeAdjVert: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 1; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ *(*result + ((i - 1) * column + j)) = abs(data[i * column + j] - data[(i - 1) * column + j]);
+ }
+ }
+
+ return OK;
+}
+
+int computeAdjVertTotal(u16 *data, int row, int column, u16 **result)
+{
+ int i, j;
+ int size = (row - 1)*(column);
+
+ if (row < 2) {
+ logError(1, "%s computeAdjVertTotal: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u16 *) kmalloc(size * sizeof (u16), GFP_KERNEL);
+ if (*result == NULL) {
+ logError(1, "%s computeAdjVertTotal: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 1; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ *(*result + ((i - 1) * column + j)) = abs(data[i * column + j] - data[(i - 1) * column + j]);
+ }
+ }
+
+ return OK;
+}
+
+int computeTotal(u8 *data, u8 main, int row, int column, int m, int n, u16 **result)
+{
+ int i, j;
+ int size = (row)*(column);
+
+ *result = (u16 *) kmalloc(size * sizeof (u16), GFP_KERNEL);
+ if (*result == NULL) {
+ logError(1, "%s computeTotal : ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ *(*result + (i * column + j)) = m * main + n * data[i * column + j];
+ }
+ }
+
+ return OK;
+}
+
+int checkLimitsMinMax(short *data, int row, int column, int min, int max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min || data[i * column + j] > max) {
+ logError(1, "%s checkLimitsMinMax: Node[%d,%d] = %d exceed limit [%d, %d]\n", tag, i, j, data[i * column + j], min, max);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+int checkLimitsGap(short *data, int row, int column, int threshold)
+{
+ int i, j;
+ int min_node;
+ int max_node;
+
+ if (row == 0 || column == 0) {
+ logError(1, "%s checkLimitsGap: invalid number of rows = %d or columns = %d ERROR %02\n", tag, row, column, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ min_node = data[0];
+ max_node = data[0];
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min_node) {
+ min_node = data[i * column + j];
+ } else {
+ if (data[i * column + j] > max_node)
+ max_node = data[i * column + j];
+ }
+ }
+ }
+
+ if (max_node - min_node > threshold) {
+ logError(1, "%s checkLimitsGap: GAP = %d exceed limit %d\n", tag, max_node - min_node, threshold);
+ return ERROR_TEST_CHECK_FAIL;
+ } else
+ return OK;
+
+}
+
+int checkLimitsMap(u8 *data, int row, int column, int *min, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min[i * column + j] || data[i * column + j] > max[i * column + j]) {
+ logError(1, "%s checkLimitsMap: Node[%d,%d] = %d exceed limit [%d, %d]\n", tag, i, j, data[i * column + j], min[i * column + j], max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+int checkLimitsMapTotal(u16 *data, int row, int column, int *min, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min[i * column + j] || data[i * column + j] > max[i * column + j]) {
+ logError(1, "%s checkLimitsMapTotal: Node[%d,%d] = %d exceed limit [%d, %d]\n", tag, i, j, data[i * column + j], min[i * column + j], max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+int checkLimitsMapAdj(u8 *data, int row, int column, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] > max[i * column + j]) {
+ logError(1, "%s checkLimitsMapAdj: Node[%d,%d] = %d exceed limit > %d\n", tag, i, j, data[i * column + j], max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+int checkLimitsMapAdjTotal(u16 *data, int row, int column, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] > max[i * column + j]) {
+ logError(1, "%s checkLimitsMapAdjTotal: Node[%d,%d] = %d exceed limit > %d\n", tag, i, j, data[i * column + j], max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+int production_test_ito(void)
+{
+ int res = OK;
+ u8 cmd;
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ int eventToSearch[2] = {EVENTID_ERROR_EVENT, EVENT_TYPE_ITO}; /* look for ito event */
+
+ logError(0, "%s ITO Production test is starting...\n", tag);
+
+ res = fts_system_reset();
+ if (res < 0) {
+ logError(1, "%s production_test_ito: ERROR %02X\n", tag, ERROR_PROD_TEST_ITO);
+ return (res | ERROR_PROD_TEST_ITO);
+ }
+
+ cmd = FTS_CMD_ITO_CHECK;
+
+ logError(0, "%s ITO Check command sent...\n", tag);
+ if (fts_writeFwCmd(&cmd, 1) < 0) {
+ logError(1, "%s production_test_ito: ERROR %02X\n", tag, (ERROR_I2C_W | ERROR_PROD_TEST_ITO));
+ return (ERROR_I2C_W | ERROR_PROD_TEST_ITO);
+ }
+
+ logError(0, "%s Looking for ITO Event...\n", tag);
+ res = pollForEvent(eventToSearch, 2, readData, TIMEOUT_ITO_TEST_RESULT);
+ if (res < 0) {
+ logError(1, "%s production_test_ito: ITO Production test failed... ERROR %02X\n", tag, ERROR_PROD_TEST_ITO);
+ return (res | ERROR_PROD_TEST_ITO);
+ }
+
+ if (readData[2] != 0x00 || readData[3] != 0x00) {
+ logError(0, "%s ITO Production testes finished!.................FAILED ERROR %02X\n", tag, (ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_ITO));
+ res = (ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_ITO);
+ } else {
+ logError(0, "%s ITO Production test finished!.................OK\n", tag);
+ res = OK;
+ }
+
+ res |= fts_system_reset();
+ if (res < 0) {
+ logError(1, "%s production_test_ito: ERROR %02X\n", tag, ERROR_PROD_TEST_ITO);
+ res = (res | ERROR_PROD_TEST_ITO);
+ }
+ return res;
+}
+
+int production_test_initialization(void)
+{
+ int res;
+ u8 cmd;
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_FULL_INITIALIZATION};
+
+ logError(0, "%s INITIALIZATION Production test is starting...\n", tag);
+
+ res = fts_system_reset();
+ if (res < 0) {
+ logError(1, "%s production_test_initialization: ERROR %02X\n", tag, ERROR_PROD_TEST_INITIALIZATION);
+ return (res | ERROR_PROD_TEST_INITIALIZATION);
+ }
+
+ logError(0, "%s INITIALIZATION command sent...\n", tag);
+ cmd = FTS_CMD_FULL_INITIALIZATION;
+ if (fts_writeFwCmd(&cmd, 1) < 0) {
+ logError(1, "%s production_test_initialization: ERROR %02X\n", tag, (ERROR_I2C_W | ERROR_PROD_TEST_INITIALIZATION));
+ return (ERROR_I2C_W | ERROR_PROD_TEST_INITIALIZATION);
+ }
+
+ logError(0, "%s Looking for INITIALIZATION Event...\n", tag);
+ res = pollForEvent(eventToSearch, 2, readData, TIMEOUT_INITIALIZATION_TEST_RESULT);
+ if (res < 0) {
+ logError(1, "%s production_test_initialization: INITIALIZATION Production test failed... ERROR %02X\n", tag, ERROR_PROD_TEST_INITIALIZATION);
+ return (res | ERROR_PROD_TEST_INITIALIZATION);
+ }
+
+ if (readData[2] != 0x00) {
+ logError(0, "%s INITIALIZATION Production testes finished!.................FAILED ERROR %02X\n", tag, (ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_INITIALIZATION));
+ res = (ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_INITIALIZATION);
+ } else {
+ logError(0, "%s INITIALIZATION Production test.................OK\n", tag);
+ res = OK;
+ }
+
+ logError(0, "%s Refresh Chip Info...\n", tag);
+ res |= readChipInfo(1);
+ /* need to update the chipInfo in order to refresh the tuning_versione */
+
+ if (res < 0) {
+ logError(1, "%s production_test_initialization: read chip info ERROR %02X\n", tag, ERROR_PROD_TEST_INITIALIZATION);
+ res = (res | ERROR_PROD_TEST_INITIALIZATION);
+ }
+
+ return res;
+
+}
+
+int ms_compensation_tuning(void)
+{
+ int res;
+ u8 cmd;
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_MS_TUNING_CMPL};
+
+ logError(0, "%s MS INITIALIZATION command sent...\n", tag);
+ cmd = FTS_CMD_MS_COMP_TUNING;
+ if (fts_writeFwCmd(&cmd, 1) < 0) {
+ logError(1, "%s ms_compensation_tuning 2: ERROR %02X\n", tag, (ERROR_I2C_W | ERROR_MS_TUNING));
+ return (ERROR_I2C_W | ERROR_MS_TUNING);
+ }
+
+ logError(0, "%s Looking for MS INITIALIZATION Event...\n", tag);
+ res = pollForEvent(eventToSearch, 2, readData, TIMEOUT_INITIALIZATION_TEST_RESULT);
+ if (res < 0) {
+ logError(1, "%s ms_compensation_tuning: MS INITIALIZATION Production test failed... ERROR %02X\n", tag, ERROR_MS_TUNING);
+ return (res | ERROR_MS_TUNING);
+ }
+
+ if (readData[2] != 0x00 || readData[3] != 0x00) {
+ logError(0, "%s MS INITIALIZATION Production test finished!.................FAILED ERROR %02X\n", tag, ERROR_MS_TUNING);
+ res = ERROR_MS_TUNING;
+ } else {
+ logError(0, "%s MS INITIALIZATION Production test finished!.................OK\n", tag);
+ res = OK;
+ }
+
+ return res;
+}
+
+int ss_compensation_tuning(void)
+{
+ int res;
+ u8 cmd;
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_SS_TUNING_CMPL};
+
+ logError(0, "%s SS INITIALIZATION command sent...\n", tag);
+ cmd = FTS_CMD_SS_COMP_TUNING;
+ if (fts_writeFwCmd(&cmd, 1) < 0) {
+ logError(1, "%s ss_compensation_tuning 2: ERROR %02X\n", tag, (ERROR_I2C_W | ERROR_SS_TUNING));
+ return (ERROR_I2C_W | ERROR_SS_TUNING);
+ }
+
+ logError(0, "%s Looking for SS INITIALIZATION Event...\n", tag);
+ res = pollForEvent(eventToSearch, 2, readData, TIMEOUT_INITIALIZATION_TEST_RESULT);
+ if (res < 0) {
+ logError(1, "%s ms_compensation_tuning: SS INITIALIZATION Production test failed... ERROR %02X\n", tag, ERROR_SS_TUNING);
+ return (res | ERROR_SS_TUNING);
+ }
+
+ if (readData[2] != 0x00 || readData[3] != 0x00) {
+ logError(0, "%s SS INITIALIZATION Production test finished!.................FAILED ERROR %02X\n", tag, ERROR_SS_TUNING);
+ res = ERROR_SS_TUNING;
+ } else {
+ logError(0, "%s SS INITIALIZATION Production test finished!.................OK\n", tag);
+ res = OK;
+ }
+
+ return res;
+}
+
+int lp_timer_calibration(void)
+{
+ int res;
+ u8 cmd;
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_LPTIMER_TUNING_CMPL};
+
+ logError(0, "%s LP TIMER CALIBRATION command sent...\n", tag);
+ cmd = FTS_CMD_LP_TIMER_CALIB;
+ if (fts_writeFwCmd(&cmd, 1) < 0) {
+ logError(1, "%s lp_timer_calibration 2: ERROR %02X\n", tag, (ERROR_I2C_W | ERROR_LP_TIMER_TUNING));
+ return (ERROR_I2C_W | ERROR_LP_TIMER_TUNING);
+ }
+
+ logError(0, "%s Looking for LP TIMER CALIBRATION Event...\n", tag);
+ res = pollForEvent(eventToSearch, 2, readData, TIMEOUT_INITIALIZATION_TEST_RESULT);
+ if (res < 0) {
+ logError(1, "%s lp_timer_calibration: LP TIMER CALIBRATION Production test failed... ERROR %02X\n", tag, ERROR_LP_TIMER_TUNING);
+ return (res | ERROR_LP_TIMER_TUNING);
+ }
+
+ if (readData[2] != 0x00 || readData[3] != 0x01) {
+ logError(0, "%s LP TIMER CALIBRATION Production test finished!.................FAILED ERROR %02X\n", tag, ERROR_LP_TIMER_TUNING);
+ res = ERROR_LP_TIMER_TUNING;
+ } else {
+ logError(0, "%s LP TIMER CALIBRATION Production test finished!.................OK\n", tag);
+ res = OK;
+ }
+
+ return res;
+}
+
+int save_cx_tuning(void)
+{
+ int res;
+ u8 cmd;
+ u8 readData[FIFO_EVENT_SIZE] = {0};
+ int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_COMP_DATA_SAVED};
+
+ logError(0, "%s SAVE CX command sent...\n", tag);
+ cmd = FTS_CMD_SAVE_CX_TUNING;
+ if (fts_writeCmd(&cmd, 1) < 0) {
+ logError(1, "%s save_cx_tuning 2: ERROR %02X\n", tag, (ERROR_I2C_W | ERROR_SAVE_CX_TUNING));
+ return (ERROR_I2C_W | ERROR_SAVE_CX_TUNING);
+ }
+
+ logError(0, "%s Looking for SAVE CX Event...\n", tag);
+ res = pollForEvent(eventToSearch, 2, readData, TIMEOUT_INITIALIZATION_TEST_RESULT);
+ if (res < 0) {
+ logError(1, "%s save_cx_tuning: SAVE CX failed... ERROR %02X\n", tag, ERROR_SAVE_CX_TUNING);
+ return (res | ERROR_SAVE_CX_TUNING);
+ }
+
+ if (readData[2] != 0x00 || readData[3] != 0x00) {
+ logError(0, "%s SAVE CX finished!.................FAILED ERROR %02X\n", tag, ERROR_SAVE_CX_TUNING);
+ res = ERROR_SAVE_CX_TUNING;
+ } else {
+ logError(0, "%s SAVE CX finished!.................OK\n", tag);
+ res = OK;
+ }
+
+ return res;
+}
+
+int production_test_splited_initialization(int saveToFlash)
+{
+ int res;
+
+ logError(0, "%s Splitted Initialization test is starting...\n", tag);
+ res = fts_system_reset();
+ if (res < 0) {
+ logError(1, "%s production_test_initialization: ERROR %02X\n", tag, ERROR_PROD_TEST_INITIALIZATION);
+ logError(0, "%s LP INITIALIZATION TEST:\n", tag);
+ return (res | ERROR_PROD_TEST_INITIALIZATION);
+ }
+
+ logError(0, "%s MS INITIALIZATION TEST:\n", tag);
+ res = ms_compensation_tuning();
+ if (res < 0) {
+ logError(0, "%s production_test_splited_initialization: MS INITIALIZATION TEST FAILED! ERROR %02X\n", tag, ERROR_PROD_TEST_INITIALIZATION);
+ return (res | ERROR_PROD_TEST_INITIALIZATION);
+ }
+ logError(0, "%s MS INITIALIZATION TEST OK!\n", tag);
+
+ logError(0, "%s\n", tag);
+
+ logError(0, "%s SS INITIALIZATION TEST:\n", tag);
+ res = ss_compensation_tuning();
+ if (res < 0) {
+ logError(0, "%s production_test_splited_initialization: SS INITIALIZATION TEST FAILED! ERROR %02X\n", tag, ERROR_PROD_TEST_INITIALIZATION);
+ return (res | ERROR_PROD_TEST_INITIALIZATION);
+ }
+ logError(0, "%s SS INITIALIZATION TEST OK!\n", tag);
+
+ logError(0, "%s\n", tag);
+
+ logError(0, "%s LP INITIALIZATION TEST:\n", tag);
+ res = lp_timer_calibration();
+ if (res < 0) {
+ logError(0, "%s production_test_splited_initialization: LP INITIALIZATION TEST FAILED! ERROR %02X\n", tag, ERROR_PROD_TEST_INITIALIZATION);
+ return (res | ERROR_PROD_TEST_INITIALIZATION);
+ }
+ logError(0, "%s LP INITIALIZATION TEST OK!\n", tag);
+ if (saveToFlash) {
+ logError(0, "%s\n", tag);
+ logError(0, "%s SAVE CX TEST:\n", tag);
+ res = save_cx_tuning();
+ if (res < 0) {
+ logError(0, "%s production_test_splited_initialization: SAVE CX TEST FAILED! ERROR %02X\n", tag, res);
+ return (res | ERROR_PROD_TEST_INITIALIZATION);
+ }
+ logError(0, "%s SAVE CX TEST OK!\n", tag);
+ }
+ logError(0, "%s Refresh Chip Info...\n", tag);
+ res |= readChipInfo(1);
+ if (res < 0) {
+ logError(1, "%s production_test_initialization: read chip info ERROR %02X\n", tag, ERROR_PROD_TEST_INITIALIZATION);
+ res = (res | ERROR_PROD_TEST_INITIALIZATION);
+ } else
+ logError(0, "%s Splited Initialization test finished!.................OK\n", tag);
+ return res;
+}
+
+int production_test_main(char *pathThresholds, int stop_on_fail,
+ int saveInit, TestToDo *todo, u32 signature)
+{
+ int res, ret;
+
+ logError(0, "%s MAIN Production test is starting...\n", tag);
+
+ logError(0, "%s\n", tag);
+
+ logError(0, "%s ITO TEST:\n", tag);
+ res = production_test_ito();
+ if (res < 0) {
+ logError(0, "%s Error during ITO TEST! ERROR %02X\n", tag, (u8) res);
+ goto END; /* in case of ITO TEST failure is no sense keep going */
+ } else {
+ logError(0, "%s ITO TEST OK!\n", tag);
+ }
+
+ logError(0, "%s\n", tag);
+
+ logError(0, "%s INITIALIZATION TEST :\n", tag);
+ if (saveInit == 1) {
+ res = production_test_initialization();
+ if (res < 0) {
+ logError(0, "%s Error during INITIALIZATION TEST! ERROR %02X\n", tag, (u8) res);
+ if (stop_on_fail)
+ goto END;
+ } else {
+ logError(0, "%s INITIALIZATION TEST OK!\n", tag);
+ }
+ } else
+ logError(0, "%s INITIALIZATION TEST :................. SKIPPED\n", tag);
+
+ logError(0, "%s\n", tag);
+
+ if (saveInit == 1) {
+ logError(0, "%s Cleaning up...\n", tag);
+ ret = cleanUp(0);
+ if (ret < 0) {
+ logError(1, "%s production_test_main: clean up ERROR %02X\n", tag, ret);
+ res |= ret;
+ if (stop_on_fail)
+ goto END;
+ }
+ logError(0, "%s\n", tag);
+ }
+
+ logError(0, "%s PRODUCTION DATA TEST:\n", tag);
+ ret = production_test_data(pathThresholds, stop_on_fail, todo);
+ if (ret < 0) {
+ logError(0, "%s Error during PRODUCTION DATA TEST! ERROR %02X\n", tag, ret);
+ } else {
+ logError(0, "%s PRODUCTION DATA TEST OK!\n", tag);
+ }
+
+ res |= ret;
+ /* the OR is important because if the data test is OK but the inizialization test fail,
+ * the main production test result should = FAIL
+ */
+
+ if (ret == OK && saveInit == 1) {
+ logError(0, "%s SAVE FLAG:\n", tag);
+ ret = save_mp_flag(signature);
+ if (ret < OK)
+ logError(0, "%s SAVE FLAG:................. FAIL! ERROR %08X\n", tag, ret);
+ else
+ logError(0, "%s SAVE FLAG:................. OK!\n", tag);
+ res |= ret;
+ }
+
+ logError(0, "%s\n", tag);
+END:
+ if (res < 0) {
+ logError(0, "%s MAIN Production test finished.................FAILED\n", tag);
+ return res;
+ }
+ logError(0, "%s MAIN Production test finished.................OK\n", tag);
+ return OK;
+}
+
+int production_test_ms_raw(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+
+ int ret, count_fail = 0;
+ MutualSenseFrame msRawFrame;
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+
+ /*********************** Mutual Sense Test **********************/
+ logError(0, "%s\n", tag);
+ logError(0, "%s MS RAW DATA TEST is starting...\n", tag);
+ if (todo->MutualRaw == 1 || todo->MutualRawGap == 1) {
+
+ ret = getMSFrame2(MS_TOUCH_ACTIVE, &msRawFrame);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: getMSFrame failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ logError(0, "%s MS RAW MIN MAX TEST:\n", tag);
+ if (todo->MutualRaw == 1) {
+ ret = parseProductionTestLimits(path_limits, MS_RAW_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_RAW_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMinMax(msRawFrame.node_data, msRawFrame.header.force_node, msRawFrame.header.sense_node, thresholds[0], thresholds[1]);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax MS RAW failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS RAW MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+ }
+ kfree(thresholds);
+ logError(0, "%s MS RAW MIN MAX TEST:.................OK\n", tag);
+ } else
+ logError(0, "%s MS RAW MIN MAX TEST:.................SKIPPED\n", tag);
+
+ logError(0, "%s\n", tag);
+ logError(0, "%s MS RAW GAP TEST:\n", tag);
+ if (todo->MutualRawGap == 1) {
+ ret = parseProductionTestLimits(path_limits, MS_RAW_GAP, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_RAW_GAP failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsGap(msRawFrame.node_data, msRawFrame.header.force_node, msRawFrame.header.sense_node, thresholds[0]);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsGap MS RAW failed... ERROR = %02X\n", tag, ret);
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+
+ } else
+ logError(0, "%s MS RAW GAP TEST:.................OK\n\n", tag);
+ kfree(thresholds);
+ } else
+ logError(0, "%s MS RAW GAP TEST:.................SKIPPED\n", tag);
+
+ kfree(msRawFrame.node_data);
+ } else
+ logError(0, "%s MS RAW FRAME TEST:.................SKIPPED\n", tag);
+
+ logError(0, "%s\n", tag);
+ logError(0, "%s MS KEY RAW TEST:\n", tag);
+ if (todo->MutualKeyRaw == 1) {
+ ret = production_test_ms_key_raw(path_limits);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: production_test_ms_key_raw failed... ERROR = %02X\n", tag, ret);
+ count_fail += 1;
+ }
+ } else
+ logError(0, "%s MS KEY RAW TEST:.................SKIPPED\n", tag);
+
+ERROR:
+ logError(0, "%s\n", tag);
+ if (count_fail == 0) {
+ logError(0, "%s MS RAW DATA TEST finished!.................OK\n", tag);
+ return OK;
+ }
+ print_frame_short("MS Raw frame =", array1dTo2d_short(msRawFrame.node_data, msRawFrame.node_data_size, msRawFrame.header.sense_node), msRawFrame.header.force_node, msRawFrame.header.sense_node);
+ logError(0, "%s MS RAW DATA TEST:.................FAIL fails_count = %d\n\n", tag, count_fail);
+ return (ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL);
+}
+
+int production_test_ms_key_raw(char *path_limits)
+{
+
+ int ret;
+ MutualSenseFrame msRawFrame;
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+
+ /******************************* Mutual Sense Test *******************************/
+ logError(0, "%s MS KEY RAW DATA TEST is starting...\n", tag);
+
+ ret = getMSFrame2(MS_KEY, &msRawFrame);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: getMSKeyFrame failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, MS_KEY_RAW_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_KEY_RAW_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMinMax(msRawFrame.node_data, msRawFrame.header.force_node, msRawFrame.header.sense_node, thresholds[0], thresholds[1]);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax MS KEY RAW failed... ERROR COUNT = %d\n", tag, ret);
+ goto ERROR;
+ } else
+ logError(0, "%s MS KEY RAW TEST:.................OK\n\n", tag);
+
+ kfree(thresholds);
+
+ kfree(msRawFrame.node_data);
+
+ return OK;
+
+ERROR:
+ print_frame_short("MS Key Raw frame =", array1dTo2d_short(msRawFrame.node_data, msRawFrame.node_data_size, msRawFrame.header.sense_node), msRawFrame.header.force_node, msRawFrame.header.sense_node);
+ logError(0, "%s MS KEY RAW TEST:.................FAIL\n\n", tag);
+ return (ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL);
+
+}
+
+int production_test_ms_cx(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+
+ int ret;
+ int count_fail = 0;
+
+ int *thresholds = NULL;
+ int *thresholds_min = NULL;
+ int *thresholds_max = NULL;
+ int trows, tcolumns;
+
+ MutualSenseData msCompData;
+
+ u8 *adjhor = NULL;
+
+ u8 *adjvert = NULL;
+
+ u16 container;
+ u16 *total_cx = NULL;
+ u16 *total_adjhor = NULL;
+ u16 *total_adjvert = NULL;
+
+ /* MS CX TEST */
+ logError(0, "%s\n", tag);
+ logError(0, "%s MS CX Testes are starting...\n", tag);
+
+ ret = readMutualSenseCompensationData(MS_TOUCH_ACTIVE, &msCompData); /* read MS compensation data */
+ if (ret < 0) {
+ logError(1, "%s production_test_data: readMutualSenseCompensationData failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ logError(0, "%s MS CX1 TEST:\n", tag);
+ if (todo->MutualCx1 == 1) {
+
+ ret = parseProductionTestLimits(path_limits, MS_CX1_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_CX1_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ container = (u16) msCompData.cx1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], thresholds[1]); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax MS CX1 failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS CX1 TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS CX1 TEST:.................OK\n\n", tag);
+ } else
+ logError(0, "%s MS CX1 TEST:.................SKIPPED\n\n", tag);
+
+ kfree(thresholds);
+
+ logError(0, "%s MS CX2 MIN MAX TEST:\n", tag);
+ if (todo->MutualCx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, MS_CX2_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load min thresholds */
+ if (ret < 0 || (trows != msCompData.header.force_node || tcolumns != msCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_CX2_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, MS_CX2_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load max thresholds */
+ if (ret < 0 || (trows != msCompData.header.force_node || tcolumns != msCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_CX2_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMap(msCompData.node_data, msCompData.header.force_node, msCompData.header.sense_node, thresholds_min, thresholds_max); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap MS CX2 MIN MAX failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS CX2 MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS CX2 MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s MS CX2 MIN MAX TEST:.................SKIPPED\n\n", tag);
+
+ logError(0, "%s MS CX2 ADJ TEST:\n", tag);
+ if (todo->MutualCx2Adj == 1) {
+ /* MS CX2 ADJ HORIZ */
+ logError(0, "%s MS CX2 ADJ HORIZ TEST:\n", tag);
+
+ ret = computeAdjHoriz(msCompData.node_data, msCompData.header.force_node, msCompData.header.sense_node, &adjhor);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjHoriz failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s MS CX2 ADJ HORIZ computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, MS_CX2_ADJH_MAP_MAX, &thresholds_max, &trows, &tcolumns);
+ if (ret < 0 || (trows != msCompData.header.force_node || tcolumns != msCompData.header.sense_node - 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_CX2_ADJH_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdj(adjhor, msCompData.header.force_node, msCompData.header.sense_node - 1, thresholds_max);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMapAdj CX2 ADJH failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS CX2 ADJ HORIZ TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS CX2 ADJ HORIZ TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(adjhor);
+
+ /* MS CX2 ADJ VERT */
+ logError(0, "%s MS CX2 ADJ VERT TEST:\n", tag);
+
+ ret = computeAdjVert(msCompData.node_data, msCompData.header.force_node, msCompData.header.sense_node, &adjvert);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjVert failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s MS CX2 ADJ VERT computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, MS_CX2_ADJV_MAP_MAX, &thresholds_max, &trows, &tcolumns);
+ if (ret < 0 || (trows != msCompData.header.force_node - 1 || tcolumns != msCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_CX2_ADJV_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdj(adjvert, msCompData.header.force_node - 1, msCompData.header.sense_node - 1, thresholds_max);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMapAdj CX2 ADJV failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS CX2 ADJ HORIZ TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS CX2 ADJ VERT TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(adjvert);
+ } else
+ logError(0, "%s MS CX2 ADJ TEST:.................SKIPPED\n\n", tag);
+
+ /* START OF TOTAL CHECK */
+ logError(0, "%s MS TOTAL CX TEST:\n", tag);
+
+ if (todo->MutualCxTotal == 1 || todo->MutualCxTotalAdj == 1) {
+ ret = computeTotal(msCompData.node_data, msCompData.cx1, msCompData.header.force_node, msCompData.header.sense_node, CX1_WEIGHT, CX2_WEIGHT, &total_cx);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeTotalCx failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s MS TOTAL CX MIN MAX TEST:\n", tag);
+ if (todo->MutualCxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits, MS_TOTAL_CX_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load min thresholds */
+ if (ret < 0 || (trows != msCompData.header.force_node || tcolumns != msCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_TOTAL_CX_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, MS_TOTAL_CX_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load max thresholds */
+ if (ret < 0 || (trows != msCompData.header.force_node || tcolumns != msCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_TOTAL_CX_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapTotal(total_cx, msCompData.header.force_node, msCompData.header.sense_node, thresholds_min, thresholds_max); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap MS TOTAL CX TEST failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS TOTAL CX MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS TOTAL CX MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s MS TOTAL CX MIN MAX TEST:.................SKIPPED\n\n", tag);
+
+ logError(0, "%s MS TOTAL CX ADJ TEST:\n", tag);
+ if (todo->MutualCxTotalAdj == 1) {
+ /* MS TOTAL CX ADJ HORIZ */
+ logError(0, "%s MS TOTAL CX ADJ HORIZ TEST:\n", tag);
+
+ /* thresholds_max = NULL; */
+ ret = computeAdjHorizTotal(total_cx, msCompData.header.force_node, msCompData.header.sense_node, &total_adjhor);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjHoriz failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s MS TOTAL CX ADJ HORIZ computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, MS_TOTAL_CX_ADJH_MAP_MAX, &thresholds_max, &trows, &tcolumns);
+ if (ret < 0 || (trows != msCompData.header.force_node || tcolumns != msCompData.header.sense_node - 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_TOTAL_CX_ADJH_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjhor, msCompData.header.force_node, msCompData.header.sense_node - 1, thresholds_max);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMapAdj MS TOTAL CX ADJH failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS TOTAL CX ADJ HORIZ TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS TOTAL CX ADJ HORIZ TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(total_adjhor);
+
+ /* MS TOTAL CX ADJ VERT */
+ logError(0, "%s MS TOTAL CX ADJ VERT TEST:\n", tag);
+
+ ret = computeAdjVertTotal(total_cx, msCompData.header.force_node, msCompData.header.sense_node, &total_adjvert);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjVert failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s MS TOTAL CX ADJ VERT computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, MS_TOTAL_CX_ADJV_MAP_MAX, &thresholds_max, &trows, &tcolumns);
+ if (ret < 0 || (trows != msCompData.header.force_node - 1 || tcolumns != msCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_TOTAL_CX_ADJV_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjvert, msCompData.header.force_node - 1, msCompData.header.sense_node - 1, thresholds_max);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMapAdj MS TOTAL CX ADJV failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS TOTAL CX ADJ HORIZ TEST:.................FAIL\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS TOTAL CX ADJ VERT TEST:.................OK\n", tag);
+
+ kfree(thresholds_max);
+ kfree(total_adjvert);
+ } else
+ logError(0, "%s MS TOTAL CX ADJ TEST:.................SKIPPED\n", tag);
+
+ kfree(total_cx);
+ } else
+ logError(0, "%s MS TOTAL CX TEST:.................SKIPPED\n", tag);
+
+ kfree(msCompData.node_data);
+
+ if ((todo->MutualKeyCx1 | todo->MutualKeyCx2 | todo->MutualKeyCxTotal) == 1) {
+ ret = production_test_ms_key_cx(path_limits, stop_on_fail, todo);
+ if (ret < 0) {
+ count_fail += 1;
+ logError(1, "%s production_test_data: production_test_ms_key_cx failed... ERROR = %02X\n", tag, ret);
+ logError(0, "%s MS CX testes finished!.................FAILED fails_count = %d\n\n", tag, count_fail);
+ return ret;
+ }
+ } else
+ logError(0, "%s MS KEY CX TEST:.................SKIPPED\n", tag);
+
+ERROR:
+ logError(0, "%s\n", tag);
+ if (count_fail == 0) {
+ logError(0, "%s MS CX testes finished!.................OK\n", tag);
+ return OK;
+ }
+ print_frame_u8("MS Init Data (Cx2) =", array1dTo2d_u8(msCompData.node_data, msCompData.node_data_size, msCompData.header.sense_node), msCompData.header.force_node, msCompData.header.sense_node);
+ logError(0, "%s MS CX testes finished!.................FAILED fails_count = %d\n\n", tag, count_fail);
+ return (ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA);
+
+}
+
+int production_test_ms_key_cx(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+
+ int ret;
+ int count_fail = 0;
+ int num_keys = 0;
+
+ int *thresholds = NULL;
+ int *thresholds_min = NULL;
+ int *thresholds_max = NULL;
+ int trows, tcolumns;
+
+ MutualSenseData msCompData;
+
+ u16 container;
+ u16 *total_cx = NULL;
+
+ /* MS CX TEST */
+ logError(0, "%s MS KEY CX Testes are starting...\n", tag);
+
+ ret = readMutualSenseCompensationData(MS_KEY, &msCompData); /* read MS compensation data */
+ if (ret < 0) {
+ logError(1, "%s production_test_data: readMutualSenseCompensationData failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ if (msCompData.header.force_node > msCompData.header.sense_node)
+/* the meaningful data are only in the first row, the other rows are only a copy of the first one */
+ num_keys = msCompData.header.force_node;
+ else
+ num_keys = msCompData.header.sense_node;
+
+ logError(0, "%s MS KEY CX1 TEST:\n", tag);
+ if (todo->MutualKeyCx1 == 1) {
+
+ ret = parseProductionTestLimits(path_limits, MS_KEY_CX1_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_KEY_CX1_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ container = (u16) msCompData.cx1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], thresholds[1]); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax MS CX1 failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS KEY CX1 TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS KEY CX1 TEST:.................OK\n\n", tag);
+ } else
+ logError(0, "%s MS KEY CX1 TEST:.................SKIPPED\n\n", tag);
+
+ kfree(thresholds);
+
+ logError(0, "%s MS KEY CX2 TEST:\n", tag);
+ if (todo->MutualKeyCx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, MS_KEY_CX2_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != num_keys)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_KEY_CX2_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, MS_KEY_CX2_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != num_keys)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_KEY_CX2_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMap(msCompData.node_data, 1, num_keys, thresholds_min, thresholds_max); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap MS KEY CX2 failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS KEY CX2 TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS KEY CX2 TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s MS CX2 TEST:.................SKIPPED\n\n", tag);
+
+ /* START OF TOTAL CHECK */
+ logError(0, "%s MS KEY TOTAL CX TEST:\n", tag);
+
+ if (todo->MutualKeyCxTotal == 1) {
+ ret = computeTotal(msCompData.node_data, msCompData.cx1, 1, num_keys, CX1_WEIGHT, CX2_WEIGHT, &total_cx);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeTotalCx failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, MS_KEY_TOTAL_CX_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != num_keys)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_KEY_TOTAL_CX_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, MS_KEY_TOTAL_CX_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != num_keys)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits MS_KEY_TOTAL_CX_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapTotal(total_cx, 1, num_keys, thresholds_min, thresholds_max); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap MS TOTAL KEY CX TEST failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s MS KEY TOTAL CX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s MS KEY TOTAL CX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+
+ kfree(total_cx);
+ } else
+ logError(0, "%s MS KEY TOTAL CX TEST:.................SKIPPED\n", tag);
+
+ kfree(msCompData.node_data);
+ERROR:
+ logError(0, "%s\n", tag);
+ if (count_fail == 0) {
+ logError(0, "%s MS KEY CX testes finished!.................OK\n", tag);
+ return OK;
+ }
+ print_frame_u8("MS Key Init Data (Cx2) =", array1dTo2d_u8(msCompData.node_data, msCompData.node_data_size, msCompData.header.sense_node), 1, msCompData.header.sense_node);
+ logError(0, "%s MS Key CX testes finished!.................FAILED fails_count = %d\n\n", tag, count_fail);
+ return (ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA);
+}
+
+int production_test_ss_raw(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+ int ret;
+ int count_fail = 0;
+ int rows, columns;
+
+ /* short *ssRawFrame = NULL; */
+ SelfSenseFrame ssRawFrame;
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+
+ /* MS SS TEST */
+ logError(0, "%s\n", tag);
+ logError(0, "%s SS RAW Testes are starting...\n", tag);
+
+ /******************************* Self Sense Test *******************************/
+
+ logError(0, "%s Getting SS Frame...\n", tag);
+ ret = getSSFrame2(SS_TOUCH, &ssRawFrame);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: getSSFrame failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ /* SS RAW (PROXIMITY) FORCE TEST */
+ logError(0, "%s SS RAW (PROXIMITY) FORCE TEST:\n", tag);
+
+ if (todo->SelfForceRaw == 1 || todo->SelfForceRawGap == 1) {
+
+ columns = 1;
+ /* there are no data for the sense channels due to the fact that the force frame is analized */
+ rows = ssRawFrame.header.force_node;
+
+ logError(0, "%s SS RAW (PROXIMITY) FORCE MIN MAX TEST:\n", tag);
+ if (todo->SelfForceRaw == 1) {
+
+ ret = parseProductionTestLimits(path_limits, SS_RAW_FORCE_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_RAW_FORCE_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMinMax(ssRawFrame.force_data, rows, columns, thresholds[0], thresholds[1]);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax SS RAW (PROXIMITY) FORCE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS RAW (PROXIMITY) FORCE MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ print_frame_short("SS Raw force frame =", array1dTo2d_short(ssRawFrame.force_data, rows*columns, columns), rows, columns);
+ if (stop_on_fail)
+ return (ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL);
+ } else
+ logError(0, "%s SS RAW (PROXIMITY) FORCE MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds);
+ } else
+ logError(0, "%s SS RAW (PROXIMITY) FORCE MIN MAX TEST:.................SKIPPED\n\n", tag);
+
+ logError(0, "%s\n", tag);
+ logError(0, "%s SS RAW (PROXIMITY) FORCE GAP TEST:\n", tag);
+ if (todo->SelfForceRawGap == 1) {
+
+ ret = parseProductionTestLimits(path_limits, SS_RAW_FORCE_GAP, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_RAW_FORCE_GAP failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsGap(ssRawFrame.force_data, rows, columns, thresholds[0]);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsGap SS RAW (PROXIMITY) FORCE GAP failed... ERROR = %02X\n", tag, ret);
+ logError(0, "%s SS RAW (PROXIMITY) FORCE GAP TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ print_frame_short("SS Raw force frame =", array1dTo2d_short(ssRawFrame.force_data, rows*columns, columns), rows, columns);
+ if (stop_on_fail)
+ return (ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL);
+ } else
+ logError(0, "%s SS RAW (PROXIMITY) FORCE GAP TEST:.................OK\n\n", tag);
+
+ kfree(thresholds);
+ } else
+ logError(0, "%s SS RAW (PROXIMITY) FORCE GAP TEST:.................SKIPPED\n\n", tag);
+
+ kfree(ssRawFrame.force_data);
+ } else
+ logError(0, "%s SS RAW (PROXIMITY) FORCE TEST:.................SKIPPED\n\n", tag);
+
+ logError(0, "%s\n", tag);
+ /* SS RAW (PROXIMITY) SENSE TEST */
+ logError(0, "%s SS RAW (PROXIMITY) SENSE TEST:\n", tag);
+
+ if (todo->SelfSenseRaw == 1 || todo->SelfSenseRawGap == 1) {
+ columns = ssRawFrame.header.sense_node;
+ rows = 1; /* there are no data for the force channels due to the fact that the sense frame is analized */
+
+ logError(0, "%s SS RAW (PROXIMITY) SENSE MIN MAX TEST:\n", tag);
+ if (todo->SelfSenseRaw == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_RAW_SENSE_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_RAW_SENSE_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMinMax(ssRawFrame.sense_data, rows, columns, thresholds[0], thresholds[1]);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax SS RAW (PROXIMITY) SENSE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS RAW (PROXIMITY) SENSE MIN MAX TEST:.................FAIL\n", tag);
+ count_fail += 1;
+ print_frame_short("SS Raw sense frame =", array1dTo2d_short(ssRawFrame.sense_data, rows*columns, columns), rows, columns);
+ if (stop_on_fail)
+ return (ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL);
+ } else
+ logError(0, "%s SS RAW (PROXIMITY) SENSE MIN MAX TEST:.................OK\n", tag);
+
+ kfree(thresholds);
+ } else
+ logError(0, "%s SS RAW (PROXIMITY) SENSE MIN MAX TEST:.................SKIPPED\n", tag);
+
+ logError(0, "%s\n", tag);
+ logError(0, "%s SS RAW (PROXIMITY) SENSE GAP TEST:\n", tag);
+ if (todo->SelfSenseRawGap == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_RAW_SENSE_GAP, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_RAW_SENSE_GAP failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsGap(ssRawFrame.sense_data, rows, columns, thresholds[0]);
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsGap SS RAW (PROXIMITY) SENSE GAP failed... ERROR = %02X\n", tag, ret);
+ logError(0, "%s SS RAW (PROXIMITY) SENSE GAP TEST:.................FAIL\n", tag);
+ count_fail += 1;
+ print_frame_short("SS Raw sense frame =", array1dTo2d_short(ssRawFrame.sense_data, rows*columns, columns), rows, columns);
+ if (stop_on_fail)
+ return (ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL);
+ } else
+ logError(0, "%s SS RAW (PROXIMITY) SENSE GAP TEST:.................OK\n", tag);
+
+ kfree(thresholds);
+ } else
+ logError(0, "%s SS RAW (PROXIMITY) SENSE GAP TEST:.................SKIPPED\n", tag);
+
+ kfree(ssRawFrame.sense_data);
+ }
+
+ logError(0, "%s\n", tag);
+ if (count_fail == 0) {
+ logError(0, "%s SS RAW testes finished!.................OK\n\n", tag);
+ return OK;
+ }
+ logError(0, "%s SS RAW testes finished!.................FAILED fails_count = %d\n\n", tag, count_fail);
+ return (ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA);
+}
+
+int production_test_ss_ix_cx(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+
+ int ret;
+ int count_fail = 0;
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+ int *thresholds_min = NULL;
+ int *thresholds_max = NULL;
+
+ SelfSenseData ssCompData;
+
+ u8 *adjhor = NULL;
+ u8 *adjvert = NULL;
+
+ u16 container;
+ int *ix1_w, *ix2_w;
+ u16 *total_ix = NULL;
+ u16 *total_cx = NULL;
+
+ u16 *total_adjhor = NULL;
+ u16 *total_adjvert = NULL;
+
+ logError(0, "%s\n", tag);
+ logError(0, "%s SS IX CX testes are starting...\n", tag);
+ ret = readSelfSenseCompensationData(SS_TOUCH, &ssCompData); /* read the SS compensation data */
+ if (ret < 0) {
+ logError(1, "%s production_test_data: readSelfSenseCompensationData failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ /*************************** SS FORCE IX *************************************/
+ /* SS IX1 FORCE TEST */
+ logError(0, "%s SS IX1 FORCE TEST:\n", tag);
+ if (todo->SelfForceIx1 == 1) {
+
+ ret = parseProductionTestLimits(path_limits, SS_IX1_FORCE_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX1_FORCE_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ container = (u16) ssCompData.f_ix1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], thresholds[1]); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax SS IX1 FORCE TEST failed... ERROR COUNT = %d\n", tag, ret);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS IX1 FORCE TEST:.................OK\n\n", tag);
+ } else
+ logError(0, "%s SS IX1 FORCE TEST:.................SKIPPED\n\n", tag);
+
+ kfree(thresholds);
+ /* SS IX2 FORCE TEST */
+ logError(0, "%s SS IX2 FORCE MIN MAX TEST:\n", tag);
+ if (todo->SelfForceIx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_IX2_FORCE_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load the min thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX2_FORCE_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_IX2_FORCE_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX2_FORCE_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMap(ssCompData.ix2_fm, ssCompData.header.force_node, 1, thresholds_min, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS IX2 FORCE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS IX2 FORCE MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS IX2 FORCE MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s SS IX2 FORCE MIN MAX TEST:.................SKIPPED\n\n", tag);
+
+ logError(0, "%s SS IX2 FORCE ADJ TEST:\n", tag);
+ if (todo->SelfForceIx2Adj == 1) {
+ /* SS IX2 FORCE ADJV TEST */
+ logError(0, "%s SS IX2 FORCE ADJVERT TEST:\n", tag);
+ ret = computeAdjVert(ssCompData.ix2_fm, ssCompData.header.force_node, 1, &adjvert);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjVert SS IX2 FORCE ADJV failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s SS IX2 FORCE ADJV computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, SS_IX2_FORCE_ADJV_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node - 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX2_FORCE_ADJV_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdj(adjvert, ssCompData.header.force_node - 1, 1, thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS IX2 FORCE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS IX2 FORCE ADJV TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS IX2 FORCE ADJV TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(adjvert);
+
+ } else
+ logError(0, "%s SS IX2 FORCE ADJ TEST:.................SKIPPED\n\n", tag);
+
+ /* SS TOTAL FORCE IX */
+ logError(0, "%s SS TOTAL IX FORCE TEST:\n", tag);
+ if (todo->SelfForceIxTotal == 1 || todo->SelfForceIxTotalAdj == 1) {
+ logError(0, "%s Reading TOTAL IX FORCE Weights...\n", tag);
+ ret = parseProductionTestLimits(path_limits, SS_IX1_FORCE_W, &ix1_w, &trows, &tcolumns); /* load the IX1 weight */
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX1_FORCE_W failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_IX2_FORCE_W, &ix2_w, &trows, &tcolumns); /* load the IX2 weight */
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX1_FORCE_W failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ logError(0, "%s Weights: IX1_W = %d IX2_W = %d\n", tag, *ix1_w, *ix2_w);
+
+ ret = computeTotal(ssCompData.ix2_fm, ssCompData.f_ix1, ssCompData.header.force_node, 1, *ix1_w, *ix2_w, &total_ix);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeTotal Ix Force failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ logError(0, "%s SS TOTAL IX FORCE MIN MAX TEST:\n", tag);
+ if (todo->SelfForceIxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_IX_FORCE_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load the min thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_IX_FORCE_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_IX_FORCE_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_IX_FORCE_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapTotal(total_ix, ssCompData.header.force_node, 1, thresholds_min, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS TOTAL IX FORCE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS TOTAL IX FORCE MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS TOTAL IX FORCE MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s SS TOTAL IX FORCE MIN MAX TEST:.................SKIPPED\n", tag);
+
+ logError(0, "%s SS TOTAL IX FORCE ADJ TEST:\n", tag);
+ if (todo->SelfForceIxTotalAdj == 1) {
+ /* SS TOTAL IX FORCE ADJV TEST */
+ logError(0, "%s SS TOTAL IX FORCE ADJVERT TEST:\n", tag);
+ ret = computeAdjVertTotal(total_ix, ssCompData.header.force_node, 1, &total_adjvert);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjVert SS TOTAL IX FORCE ADJV failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s SS TOTAL IX FORCE ADJV computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_IX_FORCE_ADJV_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node - 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_IX_FORCE_ADJV_MAP_MAX... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjvert, ssCompData.header.force_node - 1, 1, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS TOTAL IX FORCE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS TOTAL IX FORCE ADJV TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS TOTAL IX FORCE ADJV TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(total_adjvert);
+ } else
+ logError(0, "%s SS TOTAL IX FORCE ADJ TEST:.................SKIPPED\n", tag);
+
+ kfree(total_ix);
+ } else
+ logError(0, "%s SS TOTAL IX FORCE TEST:.................SKIPPED\n\n", tag);
+
+ /******************* SS SENSE IX **************************/
+ /* SS IX1 SENSE TEST */
+ logError(0, "%s SS IX1 SENSE TEST:\n", tag);
+ if (todo->SelfSenseIx1 == 1) {
+
+ ret = parseProductionTestLimits(path_limits, SS_IX1_SENSE_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX1_SENSE_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ container = (u16) ssCompData.s_ix1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], thresholds[1]); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax SS IX1 SENSE TEST failed... ERROR COUNT = %d\n", tag, ret);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS IX1 SENSE TEST:.................OK\n\n", tag);
+ } else
+ logError(0, "%s SS IX1 SENSE TEST:.................SKIPPED\n\n", tag);
+
+ kfree(thresholds);
+ /* SS IX2 SENSE TEST */
+ logError(0, "%s SS IX2 SENSE MIN MAX TEST:\n", tag);
+ if (todo->SelfSenseIx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_IX2_SENSE_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load the min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX2_SENSE_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_IX2_SENSE_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX2_SENSE_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMap(ssCompData.ix2_sn, 1, ssCompData.header.sense_node, thresholds_min, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS IX2 SENSE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS IX2 SENSE MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS IX2 SENSE MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s SS IX2 SENSE MIN MAX TEST:.................SKIPPED\n\n", tag);
+
+ logError(0, "%s SS IX2 SENSE ADJ TEST:\n", tag);
+ if (todo->SelfSenseIx2Adj == 1) {
+ /* SS IX2 SENSE ADJH TEST */
+ logError(0, "%s SS IX2 SENSE ADJHORIZ TEST:\n", tag);
+ ret = computeAdjHoriz(ssCompData.ix2_sn, 1, ssCompData.header.sense_node, &adjhor);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjHoriz SS IX2 SENSE ADJH failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s SS IX2 SENSE ADJ HORIZ computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, SS_IX2_SENSE_ADJH_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node - 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX2_SENSE_ADJH_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdj(adjhor, 1, ssCompData.header.sense_node - 1, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMapAdj SS IX2 SENSE ADJH failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS IX2 SENSE ADJH TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS IX2 SENSE ADJH TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(adjhor);
+ } else
+ logError(0, "%s SS IX2 SENSE ADJ TEST:.................SKIPPED\n", tag);
+
+ /* SS TOTAL IX SENSE */
+ logError(0, "%s SS TOTAL IX SENSE TEST:\n", tag);
+ if (todo->SelfSenseIxTotal == 1 || todo->SelfSenseIxTotalAdj == 1) {
+ logError(0, "%s Reading TOTAL IX SENSE Weights...\n", tag);
+ ret = parseProductionTestLimits(path_limits, SS_IX1_SENSE_W, &ix1_w, &trows, &tcolumns); /* load the IX1 weight */
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX1_SENSE_W failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_IX2_SENSE_W, &ix2_w, &trows, &tcolumns); /* load the IX2 weight */
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX1_SENSE_W failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ logError(0, "%s Weights: IX1_W = %d IX2_W = %d\n", tag, *ix1_w, *ix2_w);
+
+ ret = computeTotal(ssCompData.ix2_sn, ssCompData.s_ix1, 1, ssCompData.header.sense_node, *ix1_w, *ix2_w, &total_ix);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeTotal Ix Sense failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ logError(0, "%s SS TOTAL IX SENSE MIN MAX TEST:\n", tag);
+ if (todo->SelfSenseIxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_IX_SENSE_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load the min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_IX_SENSE_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_IX_SENSE_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_IX_SENSE_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapTotal(total_ix, 1, ssCompData.header.sense_node, thresholds_min, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS TOTAL IX SENSE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS TOTAL IX SENSE MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS TOTAL IX SENSE MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s SS TOTAL IX SENSE MIN MAX TEST:.................SKIPPED\n", tag);
+
+ logError(0, "%s SS TOTAL IX SENSE ADJ TEST:\n", tag);
+ if (todo->SelfSenseIxTotalAdj == 1) {
+ /* SS TOTAL IX SENSE ADJH TEST */
+ logError(0, "%s SS TOTAL IX SENSE ADJHORIZ TEST:\n", tag);
+ ret = computeAdjHorizTotal(total_ix, 1, ssCompData.header.sense_node, &total_adjhor);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjHoriz SS TOTAL IX SENSE ADJH failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s SS TOTAL IX SENSE ADJ HORIZ computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_IX_SENSE_ADJH_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node - 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_IX_SENSE_ADJH_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjhor, 1, ssCompData.header.sense_node - 1, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMapAdj SS TOTAL IX SENSE ADJH failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS TOTAL IX SENSE ADJH TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS TOTAL IX SENSE ADJH TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(total_adjhor);
+ } else
+ logError(0, "%s SS TOTAL IX SENSE ADJ TEST:.................SKIPPED\n", tag);
+ kfree(total_ix);
+ } else
+ logError(0, "%s SS TOTAL IX SENSE TEST:.................SKIPPED\n", tag);
+
+ /*********************** SS SENSE CX ******************************/
+ /* SS CX1 FORCE TEST */
+ logError(0, "%s SS CX1 FORCE TEST:\n", tag);
+ if (todo->SelfForceCx1 == 1) {
+
+ ret = parseProductionTestLimits(path_limits, SS_CX1_FORCE_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_CX1_FORCE_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ container = (u16) ssCompData.f_cx1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], thresholds[1]); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax SS CX1 FORCE TEST failed... ERROR COUNT = %d\n", tag, ret);
+ count_fail += 1;
+ /* if (stop_on_fail) return (ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL); */
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS CX1 FORCE TEST:.................OK\n\n", tag);
+ kfree(thresholds);
+ } else
+ logError(0, "%s SS CX1 FORCE TEST:.................SKIPPED\n\n", tag);
+
+ /* SS CX2 FORCE TEST */
+ logError(0, "%s SS CX2 FORCE MIN MAX TEST:\n", tag);
+ if (todo->SelfForceCx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_CX2_FORCE_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load the min thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_CX2_FORCE_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_CX2_FORCE_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_CX2_FORCE_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMap(ssCompData.cx2_fm, ssCompData.header.force_node, 1, thresholds_min, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS CX2 FORCE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS CX2 FORCE MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS CX2 FORCE MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s SS CX2 FORCE MIN MAX TEST:.................SKIPPED\n", tag);
+
+ logError(0, "%s SS CX2 FORCE ADJ TEST:\n", tag);
+ if (todo->SelfForceCx2Adj == 1) {
+ /* SS CX2 FORCE ADJV TEST */
+ logError(0, "%s SS CX2 FORCE ADJVERT TEST:\n", tag);
+ ret = computeAdjVert(ssCompData.cx2_fm, ssCompData.header.force_node,
+ 1, &adjvert); /* comepute the ADJV for CX2 FORCE */
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjVert SS CX2 FORCE ADJV failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s SS CX2 FORCE ADJV computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, SS_CX2_FORCE_ADJV_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node - 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_CX2_FORCE_ADJV_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdj(adjvert, ssCompData.header.force_node - 1, 1, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS IX2 FORCE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS CX2 FORCE ADJV TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS CX2 FORCE ADJV TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(adjvert);
+ } else
+ logError(0, "%s SS CX2 FORCE ADJ TEST:.................SKIPPED\n\n", tag);
+
+ /* SS TOTAL CX FORCE */
+ logError(0, "%s SS TOTAL CX FORCE TEST:\n", tag);
+ if (todo->SelfForceCxTotal == 1 || todo->SelfForceCxTotalAdj == 1) {
+ ret = computeTotal(ssCompData.cx2_fm, ssCompData.f_cx1, ssCompData.header.force_node, 1, CX1_WEIGHT, CX2_WEIGHT, &total_cx);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeTotal Cx Force failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ logError(0, "%s SS TOTAL CX FORCE MIN MAX TEST:\n", tag);
+ if (todo->SelfForceCxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_CX_FORCE_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load the min thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_CX_FORCE_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_CX_FORCE_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_CX_FORCE_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapTotal(total_cx, ssCompData.header.force_node, 1, thresholds_min, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS TOTAL FORCE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS TOTAL FORCE MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS TOTAL FORCE MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s SS TOTAL CX FORCE MIN MAX TEST:.................SKIPPED\n", tag);
+
+ /* SS TOTAL CX FORCE ADJV TEST */
+ logError(0, "%s SS TOTAL CX FORCE ADJ TEST:\n", tag);
+ if (todo->SelfForceCxTotalAdj == 1) {
+ logError(0, "%s SS TOTAL CX FORCE ADJVERT TEST:\n", tag);
+ ret = computeAdjVertTotal(total_cx, ssCompData.header.force_node, 1, &total_adjvert); /* comepute the ADJV for CX2 FORCE */
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjVert SS TOTAL CX FORCE ADJV failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s SS TOTAL CX FORCE ADJV computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_CX_FORCE_ADJV_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node - 1 || tcolumns != 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_CX_FORCE_ADJV_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjvert, ssCompData.header.force_node - 1, 1, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS TOTAL CX FORCE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS TOTAL CX FORCE ADJV TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS TOTAL CX FORCE ADJV TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(total_adjvert);
+
+ } else
+ logError(0, "%s SS TOTAL CX FORCE ADJ TEST:.................SKIPPED\n", tag);
+ kfree(total_cx);
+ } else
+ logError(0, "%s SS TOTAL CX FORCE TEST:.................SKIPPED\n\n", tag);
+
+ /* ********************** SS SENSE CX ************************************/
+ /* SS CX1 SENSE TEST */
+ logError(0, "%s SS CX1 SENSE TEST:\n", tag);
+ if (todo->SelfSenseCx1 == 1) {
+
+ ret = parseProductionTestLimits(path_limits, SS_CX1_SENSE_MIN_MAX, &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_CX1_SENSE_MIN_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ container = (u16) ssCompData.s_cx1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0], thresholds[1]); /* check the limits */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMinMax SS CX1 SENSE TEST failed... ERROR COUNT = %d\n", tag, ret);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS CX1 SENSE TEST:.................OK\n\n", tag);
+ kfree(thresholds);
+ } else
+ logError(0, "%s SS CX1 SENSE TEST:.................SKIPPED\n\n", tag);
+
+ /* SS CX2 SENSE TEST */
+ logError(0, "%s SS CX2 SENSE MIN MAX TEST:\n", tag);
+ if (todo->SelfSenseCx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_CX2_SENSE_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load the min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_CX2_SENSE_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_CX2_SENSE_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_CX2_SENSE_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMap(ssCompData.cx2_sn, 1, ssCompData.header.sense_node, thresholds_min, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS CX2 SENSE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS CX2 SENSE MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS CX2 SENSE MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s SS CX2 SENSE MIN MAX TEST:.................SKIPPED\n", tag);
+
+ logError(0, "%s SS CX2 SENSE ADJ TEST:\n", tag);
+ if (todo->SelfSenseCx2Adj == 1) {
+ /* SS CX2 SENSE ADJH TEST */
+ logError(0, "%s SS CX2 SENSE ADJHORIZ TEST:\n", tag);
+ ret = computeAdjHoriz(ssCompData.ix2_sn, 1, ssCompData.header.sense_node, &adjhor);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjHoriz SS CX2 SENSE ADJH failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s SS CX2 SENSE ADJH computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, SS_CX2_SENSE_ADJH_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node - 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_IX2_SENSE_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdj(adjhor, 1, ssCompData.header.sense_node - 1, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMapAdj SS CX2 SENSE ADJH failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS CX2 SENSE ADJH TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS CX2 SENSE ADJH TEST:.................OK\n", tag);
+
+ kfree(thresholds_max);
+ kfree(adjhor);
+ } else
+ logError(0, "%s SS CX2 SENSE ADJ TEST:.................SKIPPED\n\n", tag);
+
+ /* SS TOTAL CX SENSE */
+ logError(0, "%s SS TOTAL CX SENSE TEST:\n", tag);
+ if (todo->SelfSenseCxTotal == 1 || todo->SelfSenseCxTotalAdj == 1) {
+ ret = computeTotal(ssCompData.cx2_sn, ssCompData.s_cx1, 1, ssCompData.header.sense_node, CX1_WEIGHT, CX2_WEIGHT, &total_cx);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeTotal Cx Sense failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ logError(0, "%s SS TOTAL CX SENSE MIN MAX TEST:\n", tag);
+ if (todo->SelfSenseCxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_CX_SENSE_MAP_MIN, &thresholds_min, &trows, &tcolumns); /* load the min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_CX_SENSE_MAP_MIN failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_CX_SENSE_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_CX_SENSE_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapTotal(total_cx, 1, ssCompData.header.sense_node, thresholds_min, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMap SS TOTAL CX SENSE failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS TOTAL CX SENSE MIN MAX TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS TOTAL CX SENSE MIN MAX TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_min);
+ kfree(thresholds_max);
+ } else
+ logError(0, "%s SS TOTAL CX SENSE MIN MAX TEST:.................SKIPPED\n", tag);
+
+ /* SS TOTAL IX SENSE ADJH TEST */
+ logError(0, "%s SS TOTAL CX SENSE ADJ TEST:\n", tag);
+ if (todo->SelfSenseCxTotalAdj == 1) {
+ logError(0, "%s SS TOTAL CX SENSE ADJHORIZ TEST:\n", tag);
+ ret = computeAdjHorizTotal(total_cx, 1, ssCompData.header.sense_node, &total_adjhor);
+ if (ret < 0) {
+ logError(1, "%s production_test_data: computeAdjHoriz SS TOTAL CX SENSE ADJH failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+ logError(0, "%s SS TOTAL CX SENSE ADJ HORIZ computed!\n", tag);
+
+ ret = parseProductionTestLimits(path_limits, SS_TOTAL_CX_SENSE_ADJH_MAP_MAX, &thresholds_max, &trows, &tcolumns); /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns != ssCompData.header.sense_node - 1)) {
+ logError(1, "%s production_test_data: parseProductionTestLimits SS_TOTAL_CX_SENSE_ADJH_MAP_MAX failed... ERROR %02X\n", tag, ERROR_PROD_TEST_DATA);
+ return (ret | ERROR_PROD_TEST_DATA);
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjhor, 1, ssCompData.header.sense_node - 1, thresholds_max); /* check the values with thresholds */
+ if (ret != OK) {
+ logError(1, "%s production_test_data: checkLimitsMapAdj SS TOTAL CX SENSE ADJH failed... ERROR COUNT = %d\n", tag, ret);
+ logError(0, "%s SS TOTAL CX SENSE ADJH TEST:.................FAIL\n\n", tag);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ logError(0, "%s SS TOTAL CX SENSE ADJH TEST:.................OK\n\n", tag);
+
+ kfree(thresholds_max);
+ kfree(total_adjhor);
+ } else
+ logError(0, "%s SS TOTAL CX SENSE ADJ TEST:.................SKIPPED\n", tag);
+ kfree(total_cx);
+ } else
+ logError(0, "%s SS TOTAL CX SENSE TEST:.................SKIPPED\n", tag);
+
+ /* SS compensation data are no usefull anymore */
+
+ kfree(ssCompData.ix2_fm);
+ kfree(ssCompData.ix2_sn);
+ kfree(ssCompData.cx2_fm);
+ kfree(ssCompData.cx2_sn);
+
+ERROR:
+ logError(0, "%s\n", tag);
+ if (count_fail == 0) {
+ logError(0, "%s SS IX CX testes finished!.................OK\n\n", tag);
+ return OK;
+ }
+ /* print all kind of data in just one row for readability reason */
+ print_frame_u8("SS Init Data Ix2_fm = ", array1dTo2d_u8(ssCompData.ix2_fm, ssCompData.header.force_node, ssCompData.header.force_node), 1, ssCompData.header.force_node);
+ print_frame_u8("SS Init Data Cx2_fm = ", array1dTo2d_u8(ssCompData.cx2_fm, ssCompData.header.force_node, ssCompData.header.force_node), 1, ssCompData.header.force_node);
+ print_frame_u8("SS Init Data Ix2_sn = ", array1dTo2d_u8(ssCompData.ix2_sn, ssCompData.header.sense_node, ssCompData.header.sense_node), 1, ssCompData.header.sense_node);
+ print_frame_u8("SS Init Data Cx2_sn = ", array1dTo2d_u8(ssCompData.cx2_sn, ssCompData.header.sense_node, ssCompData.header.sense_node), 1, ssCompData.header.sense_node);
+ logError(0, "%s SS IX CX testes finished!.................FAILED fails_count = %d\n\n", tag, count_fail);
+ return (ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA);
+}
+
+int production_test_data(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+ int res = OK, ret;
+
+ if (todo == NULL) {
+ logError(1, "%s production_test_data: No TestToDo specified!! ERROR = %02X\n", tag, (ERROR_OP_NOT_ALLOW | ERROR_PROD_TEST_DATA));
+ return (ERROR_OP_NOT_ALLOW | ERROR_PROD_TEST_DATA);
+ }
+
+ logError(0, "%s DATA Production test is starting...\n", tag);
+
+ ret = production_test_ms_raw(path_limits, stop_on_fail, todo);
+ res |= ret;
+ if (ret < 0) {
+ logError(1, "%s production_test_data: production_test_ms_raw failed... ERROR = %02X\n", tag, ret);
+ if (stop_on_fail == 1)
+ goto END;
+ }
+
+ ret = production_test_ms_cx(path_limits, stop_on_fail, todo);
+ res |= ret;
+ if (res < 0) {
+ logError(1, "%s production_test_data: production_test_ms_cx failed... ERROR = %02X\n", tag, ret);
+ if (stop_on_fail == 1)
+ goto END;
+ }
+
+ ret = production_test_ss_raw(path_limits, stop_on_fail, todo);
+ res |= ret;
+ if (ret < 0) {
+ logError(1, "%s production_test_data: production_test_ss_raw failed... ERROR = %02X\n", tag, ret);
+ if (stop_on_fail == 1)
+ goto END;
+ }
+
+ ret = production_test_ss_ix_cx(path_limits, stop_on_fail, todo);
+ res |= ret;
+ if (ret < 0) {
+ logError(1, "%s production_test_data: production_test_ss_ix_cx failed... ERROR = %02X\n", tag, ret);
+ if (stop_on_fail == 1)
+ goto END;
+ }
+
+END:
+ if (res < OK)
+ logError(0, "%s DATA Production test failed!\n", tag);
+ else
+ logError(0, "%s DATA Production test finished!\n", tag);
+ return res;
+}
+
+int save_mp_flag(u32 signature)
+{
+ int res = -1, ret;
+ int i;
+ u8 cmd[6] = {FTS_CMD_WRITE_MP_FLAG, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ u32ToU8(signature, &cmd[2]);
+
+ logError(0, "%s Starting Saving Flag with signature = %08X ...\n", tag, signature);
+
+ for (i = 0; i < SAVE_FLAG_RETRY && res < OK; i++) {
+ logError(0, "%s Attempt number %d to save mp flag !\n", tag, i+1);
+ logError(0, "%s Command write flag sent...\n", tag);
+ res = fts_writeFwCmd(cmd, 6);
+ if (res >= OK)
+ res = save_cx_tuning();
+
+ }
+
+ ret = readChipInfo(1); /* need to update the MP Flag */
+ if (ret < OK) {
+ logError(1, "%s save_mp_flag: read chip info ERROR %08X\n", tag, ret);
+ }
+
+ res |= ret;
+ if (res < OK) {
+ logError(1, "%s save_mp_flag: ERROR %08X ...\n", tag, res);
+ return res;
+ }
+ logError(1, "%s Saving Flag DONE!\n", tag);
+ return OK;
+}
+
+int parseProductionTestLimits(char *path, char *label, int **data, int *row, int *column)
+{
+
+ int find = 0;
+ char *token = NULL;
+ int i = 0;
+ int j = 0;
+ int z = 0;
+
+ char *line = NULL;
+ int fd = -1;
+ char *buf = NULL;
+ int n, size, pointer = 0, ret;
+ char *data_file = NULL;
+#ifndef LIMITS_H_FILE
+ const struct firmware *fw = NULL;
+ struct device *dev = NULL;
+
+ dev = getDev();
+ if (dev != NULL)
+ fd = request_firmware(&fw, path, dev);
+#else
+ fd = 0;
+#endif
+
+ line = (char *)kmalloc(1800*sizeof(char), GFP_KERNEL);
+ buf = line;
+
+ if (fd == 0) {
+#ifndef LIMITS_H_FILE
+ size = fw->size;
+ data_file = (char *)fw->data;
+ logError(0, "%s Start to reading %s...\n", tag, path);
+#else
+ size = LIMITS_SIZE_NAME;
+ data_file = (char *)(LIMITS_ARRAY_NAME);
+#endif
+
+ logError(0, "%s The size of the limits file is %d bytes...\n", tag, size);
+
+ while (find == 0) {
+ /* start to look for the wanted label */
+ if (readLine(&data_file[pointer], &line, size-pointer, &n) < 0) {
+ find = -1;
+ break;
+ }
+ pointer += n;
+ if (line[0] == '*') { /* each header row start with * ex. *label,n_row,n_colum */
+ buf = line;
+ line += 1;
+ token = strsep(&line, ",");
+ if (strcmp(token, label) == 0) {
+ /* if the row is the wanted one i retrieve rows and columns info */
+ find = 1;
+ token = strsep(&line, ",");
+ if (token != NULL) {
+ sscanf(token, "%d", row);
+ logError(0, "%s Row = %d\n", tag, *row);
+ } else {
+ logError(1, "%s parseProductionTestLimits 1: ERROR %02X\n", tag, ERROR_FILE_PARSE);
+ /* release_firmware(fw); */
+ /* return ERROR_FILE_PARSE; */
+ ret = ERROR_FILE_PARSE;
+ goto END;
+ }
+ token = strsep(&line, ",");
+ if (token != NULL) {
+ sscanf(token, "%d", column);
+ logError(0, "%s Column = %d\n", tag, *column);
+ } else {
+ logError(1, "%s parseProductionTestLimits 2: ERROR %02X\n", tag, ERROR_FILE_PARSE);
+ /* release_firmware(fw); */
+ /* return ERROR_FILE_PARSE; */
+ ret = ERROR_FILE_PARSE;
+ goto END;
+ }
+
+ *data = (int *)kmalloc(((*row)*(*column))*sizeof(int), GFP_KERNEL);
+ /* allocate the memory for containing the data */
+ j = 0;
+ if (*data == NULL) {
+ logError(1, "%s parseProductionTestLimits: ERROR %02X\n", tag, ERROR_ALLOC);
+ /* release_firmware(fw); */
+ /* return ERROR_ALLOC; */
+ ret = ERROR_ALLOC;
+ goto END;
+ }
+
+ /* start to read the data */
+ for (i = 0; i < *row; i++) {
+ line = buf;
+ if (readLine(&data_file[pointer], &line, size-pointer, &n) < 0) {
+ logError(1, "%s parseProductionTestLimits : ERROR %02X\n", tag, ERROR_FILE_READ);
+ /* release_firmware(fw); */
+ /* return ERROR_FILE_READ; */
+ ret = ERROR_FILE_READ;
+ goto END;
+ }
+ pointer += n;
+ token = strsep(&line, ",");
+ for (z = 0; (z < *column) && (token != NULL); z++) {
+ sscanf(token, "%d", ((*data) + j));
+ j++;
+ token = strsep(&line, ",");
+ }
+ }
+ if (j == ((*row)*(*column))) { /* check that all the data are read */
+ logError(0, "%s READ DONE!\n", tag);
+ /* release_firmware(fw); */
+ /* return OK; */
+ ret = OK;
+ goto END;
+ }
+ logError(1, "%s parseProductionTestLimits 3: ERROR %02X\n", tag, ERROR_FILE_PARSE);
+ /* release_firmware(fw); */
+ /* return ERROR_FILE_PARSE; */
+ ret = ERROR_FILE_PARSE;
+ goto END;
+ }
+ }
+
+ }
+ logError(1, "%s parseProductionTestLimits: ERROR %02X\n", tag, ERROR_LABEL_NOT_FOUND);
+ ret = ERROR_LABEL_NOT_FOUND;
+END:
+#ifndef LIMITS_H_FILE
+ release_firmware(fw);
+#endif
+ return ret;
+
+ } else {
+ logError(1, "%s parseProductionTestLimits: ERROR %02X\n", tag, ERROR_FILE_NOT_FOUND);
+ return ERROR_FILE_NOT_FOUND;
+ }
+
+}
+
+int readLine(char *data, char **line, int size, int *n)
+{
+ int i = 0;
+ if (size < 1)
+ return 1;
+
+ while (data[i] != '\n' && i < size) {
+ *(*line + i) = data[i];
+ i++;
+ }
+ *n = i+1;
+ *(*line + i) = '\0';
+
+ return OK;
+
+}
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsTest.h b/drivers/input/touchscreen/st/fts_lib/ftsTest.h
new file mode 100644
index 000000000000..93da901c9f42
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsTest.h
@@ -0,0 +1,158 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS API for MP test *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsSoftware.h"
+
+#define LIMITS_FILE "stm_fts_production_limits.csv"
+
+#define WAIT_FOR_FRESH_FRAMES 100 /* ms */
+#define WAIT_AFTER_SENSEOFF 50 /* ms */
+#define TIMEOUT_ITO_TEST_RESULT 200 /* ms */
+#define TIMEOUT_INITIALIZATION_TEST_RESULT 5000 /* ms */
+
+/* LABELS PRODUCTION TEST LIMITS FILE */
+#define MS_RAW_MIN_MAX "MS_RAW_DATA_MIN_MAX"
+#define MS_RAW_GAP "MS_RAW_DATA_GAP"
+#define MS_CX1_MIN_MAX "MS_TOUCH_ACTIVE_CX1_MIN_MAX"
+#define MS_CX2_MAP_MIN "MS_TOUCH_ACTIVE_CX2_MIN"
+#define MS_CX2_MAP_MAX "MS_TOUCH_ACTIVE_CX2_MAX"
+#define MS_CX2_ADJH_MAP_MAX "MS_TOUCH_ACTIVE_CX2_ADJ_HORIZONTAL"
+#define MS_CX2_ADJV_MAP_MAX "MS_TOUCH_ACTIVE_CX2_ADJ_VERTICAL"
+#define MS_TOTAL_CX_MAP_MIN "MS_TOUCH_ACTIVE_TOTAL_CX_MIN"
+#define MS_TOTAL_CX_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_MAX"
+#define MS_TOTAL_CX_ADJH_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_ADJ_HORIZONTAL"
+#define MS_TOTAL_CX_ADJV_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_ADJ_VERTICAL"
+#define SS_RAW_FORCE_MIN_MAX "SS_RAW_DATA_FORCE_MIN_MAX"
+#define SS_RAW_SENSE_MIN_MAX "SS_RAW_DATA_SENSE_MIN_MAX"
+#define SS_RAW_FORCE_GAP "SS_RAW_DATA_FORCE_GAP"
+#define SS_RAW_SENSE_GAP "SS_RAW_DATA_SENSE_GAP"
+#define SS_IX1_FORCE_MIN_MAX "SS_TOUCH_ACTIVE_IX1_FORCE_MIN_MAX"
+#define SS_IX1_SENSE_MIN_MAX "SS_TOUCH_ACTIVE_IX1_SENSE_MIN_MAX"
+#define SS_CX1_FORCE_MIN_MAX "SS_TOUCH_ACTIVE_CX1_FORCE_MIN_MAX"
+#define SS_CX1_SENSE_MIN_MAX "SS_TOUCH_ACTIVE_CX1_SENSE_MIN_MAX"
+#define SS_IX2_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_IX2_FORCE_MIN"
+#define SS_IX2_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_IX2_FORCE_MAX"
+#define SS_IX2_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_IX2_SENSE_MIN"
+#define SS_IX2_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_IX2_SENSE_MAX"
+#define SS_IX2_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_IX2_ADJ_VERTICAL"
+#define SS_IX2_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_IX2_ADJ_HORIZONTAL"
+#define SS_CX2_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_CX2_FORCE_MIN"
+#define SS_CX2_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_CX2_FORCE_MAX"
+#define SS_CX2_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_CX2_SENSE_MIN"
+#define SS_CX2_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_CX2_SENSE_MAX"
+#define SS_CX2_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_CX2_ADJ_VERTICAL"
+#define SS_CX2_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_CX2_ADJ_HORIZONTAL"
+
+/* TOTAL SS */
+#define SS_TOTAL_IX_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_IX_FORCE_MIN"
+#define SS_TOTAL_IX_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_FORCE_MAX"
+#define SS_TOTAL_IX_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_IX_SENSE_MIN"
+#define SS_TOTAL_IX_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_SENSE_MAX"
+#define SS_TOTAL_IX_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_ADJ_VERTICAL"
+#define SS_TOTAL_IX_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_ADJ_HORIZONTAL"
+#define SS_TOTAL_CX_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_CX_FORCE_MIN"
+#define SS_TOTAL_CX_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_FORCE_MAX"
+#define SS_TOTAL_CX_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_CX_SENSE_MIN"
+#define SS_TOTAL_CX_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_SENSE_MAX"
+#define SS_TOTAL_CX_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_ADJ_VERTICAL"
+#define SS_TOTAL_CX_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_ADJ_HORIZONTAL"
+
+/* KEYS */
+#define MS_KEY_RAW_MIN_MAX "MS_KEY_RAW_DATA_MIN_MAX"
+#define MS_KEY_CX1_MIN_MAX "MS_KEY_CX1_MIN_MAX"
+#define MS_KEY_CX2_MAP_MIN "MS_KEY_CX2_MIN"
+#define MS_KEY_CX2_MAP_MAX "MS_KEY_CX2_MAX"
+#define MS_KEY_TOTAL_CX_MAP_MIN "MS_KEY_TOTAL_CX_MIN"
+#define MS_KEY_TOTAL_CX_MAP_MAX "MS_KEY_TOTAL_CX_MAX"
+
+/* CONSTANT TOTAL IX */
+#define SS_IX1_FORCE_W "SS_IX1_FORCE_W"
+#define SS_IX2_FORCE_W "SS_IX2_FORCE_W"
+#define SS_IX1_SENSE_W "SS_IX1_SENSE_W"
+#define SS_IX2_SENSE_W "SS_IX2_SENSE_W"
+
+#define SAVE_FLAG_RETRY 3
+
+typedef struct {
+ int MutualRaw;
+ int MutualRawGap;
+ int MutualCx1;
+ int MutualCx2;
+ int MutualCx2Adj;
+ int MutualCxTotal;
+ int MutualCxTotalAdj;
+
+ int MutualKeyRaw;
+ int MutualKeyCx1;
+ int MutualKeyCx2;
+ int MutualKeyCxTotal;
+
+ int SelfForceRaw;
+ int SelfForceRawGap;
+ int SelfForceIx1;
+ int SelfForceIx2;
+ int SelfForceIx2Adj;
+ int SelfForceIxTotal;
+ int SelfForceIxTotalAdj;
+ int SelfForceCx1;
+ int SelfForceCx2;
+ int SelfForceCx2Adj;
+ int SelfForceCxTotal;
+ int SelfForceCxTotalAdj;
+
+ int SelfSenseRaw;
+ int SelfSenseRawGap;
+ int SelfSenseIx1;
+ int SelfSenseIx2;
+ int SelfSenseIx2Adj;
+ int SelfSenseIxTotal;
+ int SelfSenseIxTotalAdj;
+ int SelfSenseCx1;
+ int SelfSenseCx2;
+ int SelfSenseCx2Adj;
+ int SelfSenseCxTotal;
+ int SelfSenseCxTotalAdj;
+
+} TestToDo;
+
+int computeAdjHoriz(u8 *data, int row, int column, u8 **result);
+int computeAdjHorizTotal(u16 *data, int row, int column, u16 **result);
+int computeAdjVert(u8 *data, int row, int column, u8 **result);
+int computeAdjVertTotal(u16 *data, int row, int column, u16 **result);
+int computeTotal(u8 *data, u8 main, int row, int column, int m, int n, u16 **result);
+int checkLimitsMinMax(short *data, int row, int column, int min, int max);
+int checkLimitsMap(u8 *data, int row, int column, int *min, int *max);
+int checkLimitsMapTotal(u16 *data, int row, int column, int *min, int *max);
+int checkLimitsMapAdj(u8 *data, int row, int column, int *max);
+int checkLimitsMapAdjTotal(u16 *data, int row, int column, int *max);
+int production_test_ito(void);
+int production_test_initialization(void);
+int ms_compensation_tuning(void);
+int ss_compensation_tuning(void);
+int lp_timer_calibration(void);
+int save_cx_tuning(void);
+int production_test_splited_initialization(int saveToFlash);
+int production_test_main(char *pathThresholds, int stop_on_fail,
+ int saveInit, TestToDo *todo, u32 signature);
+int production_test_ms_raw(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_ms_cx(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_ss_raw(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_ss_ix_cx(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_data(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_ms_key_cx(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_ms_key_raw(char *path_limits);
+int save_mp_flag(u32 signature);
+int parseProductionTestLimits(char *path, char *label, int **data, int *row, int *column);
+int readLine(char *data, char **line, int size, int *n);
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsTime.c b/drivers/input/touchscreen/st/fts_lib/ftsTime.c
new file mode 100644
index 000000000000..03a2a39fe10b
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsTime.c
@@ -0,0 +1,84 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS Utility for mesuring/handling the time *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsCrossCompile.h"
+#include "ftsTime.h"
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/time.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+/* #include <linux/sec_sysfs.h> */
+
+void startStopWatch(StopWatch *w)
+{
+ w->start = current_kernel_time();
+}
+
+void stopStopWatch(StopWatch *w)
+{
+ w->end = current_kernel_time();
+}
+
+int elapsedMillisecond(StopWatch *w)
+{
+ int result;
+
+ result = ((w->end.tv_sec - w->start.tv_sec)*1000) + (w->end.tv_nsec - w->start.tv_nsec) / 1000000;
+ return result;
+}
+
+int elapsedNanosecond(StopWatch *w)
+{
+ int result;
+
+ result = ((w->end.tv_sec - w->start.tv_sec)*1000000000) + (w->end.tv_nsec - w->start.tv_nsec);
+ return result;
+}
+
+char *timestamp(void)
+{
+ char *result = NULL;
+ result = (char *)kmalloc((1)*sizeof(char), GFP_KERNEL);
+ if (result == NULL)
+ return NULL;
+ result[0] = ' ';
+ return result;
+}
+
+void stdelay(unsigned long ms)
+{
+ msleep(ms);
+}
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsTime.h b/drivers/input/touchscreen/st/fts_lib/ftsTime.h
new file mode 100644
index 000000000000..5eeca6eace97
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsTime.h
@@ -0,0 +1,29 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS Utility for mesuring/handling the time *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsCrossCompile.h"
+
+#include <linux/time.h>
+
+typedef struct {
+ struct timespec start, end;
+} StopWatch;
+
+void startStopWatch(StopWatch *w);
+void stopStopWatch(StopWatch *w);
+int elapsedMillisecond(StopWatch *w);
+int elapsedNanosecond(StopWatch *w);
+char *timestamp(void);
+void stdelay(unsigned long ms);
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsTool.c b/drivers/input/touchscreen/st/fts_lib/ftsTool.c
new file mode 100644
index 000000000000..4c5d54f17ea7
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsTool.c
@@ -0,0 +1,706 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS Utility Functions *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+
+#include "ftsCompensation.h"
+#include "ftsCrossCompile.h"
+#include "ftsError.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTime.h"
+#include "ftsTool.h"
+#include "../fts.h" /* needed for the PHONE_KEY define */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+
+/* static char tag[8]="[ FTS ]\0"; */
+static int reset_gpio = GPIO_NOT_DEFINED;
+static int system_resetted_up;
+static int system_resetted_down;
+extern chipInfo ftsInfo;
+
+int readB2(u16 address, u8 *outBuf, int len)
+{
+ int remaining = len;
+ int toRead = 0;
+ int retry = 0;
+ int ret;
+ int event_to_search[3];
+ u8 *readEvent = (u8 *)kmalloc(FIFO_EVENT_SIZE*sizeof(u8), GFP_KERNEL);
+ u8 cmd[4] = { FTS_CMD_REQU_FW_CONF, 0x00, 0x00, (u8)len };
+
+ if (readEvent == NULL) {
+ logError(1, "%s readB2: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ u16ToU8_be(address, &cmd[1]);
+
+ logError(0, "%s %s", tag, printHex("Command B2 = ", cmd, 4));
+ do {
+ remaining = len;
+ ret = fts_writeFwCmd(cmd, 4);
+ if (ret < 0) {
+ logError(1, "%s readB2: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ret;
+ } /* ask to the FW the data */
+ logError(0, "%s Command to FW sent!\n", tag);
+ event_to_search[0] = (int)EVENTID_FW_CONFIGURATION;
+
+ while (remaining > OK) {
+ event_to_search[1] = (int)((address & 0xFF00)>>8);
+ event_to_search[2] = (int) (address & 0x00FF);
+ if (remaining > B2_DATA_BYTES) {
+ toRead = B2_DATA_BYTES;
+ remaining -= B2_DATA_BYTES;
+ } else {
+ toRead = remaining;
+ remaining = 0;
+ }
+
+ ret = pollForEvent(event_to_search, 3, readEvent, GENERAL_TIMEOUT);
+ if (ret >= OK) { /* start the polling for reading the reply */
+ memcpy(outBuf, &readEvent[3], toRead);
+ retry = 0;
+ outBuf += toRead;
+
+ } else {
+ retry += 1;
+ break;
+ }
+ address += B2_DATA_BYTES;
+ }
+
+ } while (retry < B2_RETRY && retry != 0);
+
+ kfree(readEvent);
+ if (retry == B2_RETRY) {
+ logError(1, "%s readB2: ERROR %02X\n", tag, ERROR_TIMEOUT);
+ return ERROR_TIMEOUT;
+ }
+ logError(0, "%s B2 read %d bytes\n", tag, len);
+
+ return OK;
+}
+
+int readB2U16(u16 address, u8 *outBuf, int byteToRead)
+{
+
+ int remaining = byteToRead;
+ int toRead = 0;
+ int ret;
+
+ u8 *buff = (u8 *)kmalloc((B2_CHUNK + 1)*sizeof(u8), GFP_KERNEL);
+ if (buff == NULL) {
+ logError(1, "%s readB2U16: ERROR %02X\n", tag, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ while (remaining > 0) {
+ if (remaining >= B2_CHUNK) {
+ toRead = B2_CHUNK;
+ remaining -= B2_CHUNK;
+ } else {
+ toRead = remaining;
+ remaining = 0;
+ }
+
+ ret = readB2(address, buff, toRead);
+ if (ret < 0)
+ return ret;
+ memcpy(outBuf, buff, toRead);
+
+ address += toRead;
+
+ outBuf += toRead;
+
+ }
+
+ kfree(buff);
+ return OK;
+}
+
+int releaseInformation(void)
+{
+ int ret;
+ u8 cmd[1] = { FTS_CMD_RELEASE_INFO };
+ int event_to_search[1];
+ u8 readEvent[FIFO_EVENT_SIZE];
+
+ event_to_search[0] = (int)EVENTID_RELEASE_INFO;
+
+ logError(0, "%s releaseInformation started... Chip INFO:\n", tag);
+
+ ret = fts_writeFwCmd(cmd, 1);
+ if (ret < OK) {
+ logError(1, "%s releaseInformation: ERROR %02X\n", tag, ret);
+ return ret;
+ }
+
+ ret = pollForEvent(event_to_search, 1, &readEvent[0], RELEASE_INFO_TIMEOUT);
+ /* start the polling for reading the reply */
+ if (ret < OK) {
+ logError(1, "%s releaseInformation: ERROR %02X\n", tag, ret);
+ return ret;
+ }
+
+ logError(0, "%s releaseInformation: Finished!\n", tag, ret);
+ return OK;
+
+}
+
+char *printHex(char *label, u8 *buff, int count)
+{
+ int i, offset;
+ char *result = NULL;
+
+ offset = strlen(label);
+ result = (char *)kmalloc(((offset + 3 * count) + 1)*sizeof(char), GFP_KERNEL);
+ if (result != NULL) {
+ strlcpy(result, label, sizeof(result));
+
+ for (i = 0; i < count; i++) {
+ snprintf(&result[offset + i * 3], 4, "%02X ", buff[i]);
+ }
+ strlcat(result, "\n", sizeof(result));
+ }
+ return result;
+}
+
+int pollForEvent(int *event_to_search, int event_bytes, u8 *readData, int time_to_wait)
+{
+ int i, find, retry, count_err;
+ int time_to_count;
+ int err_handling = OK;
+ StopWatch clock;
+
+ u8 cmd[1] = { FIFO_CMD_READONE };
+ char *temp = NULL;
+
+ find = 0;
+ retry = 0;
+ count_err = 0;
+ time_to_count = time_to_wait / TIMEOUT_RESOLUTION;
+
+ startStopWatch(&clock);
+ while (find != 1 && retry < time_to_count && fts_readCmd(cmd, 1, readData, FIFO_EVENT_SIZE) >= 0) {
+ /* Log of errors */
+ if (readData[0] == EVENTID_ERROR_EVENT) {
+ logError(1, "%s %s", tag, printHex("ERROR EVENT = ", readData, FIFO_EVENT_SIZE));
+ count_err++;
+ err_handling = errorHandler(readData, FIFO_EVENT_SIZE);
+ if ((err_handling&0xF0FF0000) == ERROR_HANDLER_STOP_PROC) {
+ logError(1, "%s pollForEvent: forced to be stopped! ERROR %08X\n", tag, err_handling);
+ return err_handling;
+ }
+ } else {
+ if (readData[0] != EVENTID_NO_EVENT) {
+ logError(1, "%s %s", tag, printHex("READ EVENT = ", readData, FIFO_EVENT_SIZE));
+ }
+ if (readData[0] == EVENTID_CONTROL_READY && event_to_search[0] != EVENTID_CONTROL_READY) {
+ logError(1, "%s pollForEvent: Unmanned Controller Ready Event! Setting reset flags...\n", tag);
+ setSystemResettedUp(1);
+ setSystemResettedDown(1);
+ }
+ }
+
+ find = 1;
+
+ for (i = 0; i < event_bytes; i++) {
+
+ if (event_to_search[i] != -1 && (int)readData[i] != event_to_search[i]) {
+ find = 0;
+ break;
+ }
+ }
+
+ retry++;
+ msleep(TIMEOUT_RESOLUTION);
+ }
+ stopStopWatch(&clock);
+ if ((retry >= time_to_count) && find != 1) {
+ logError(1, "%s pollForEvent: ERROR %02X\n", tag, ERROR_TIMEOUT);
+ return ERROR_TIMEOUT;
+ } else if (find == 1) {
+ temp = printHex("FOUND EVENT = ", readData, FIFO_EVENT_SIZE);
+ if (temp != NULL)
+ logError(0, "%s %s", tag, temp);
+ kfree(temp);
+ logError(0, "%s Event found in %d ms (%d iterations)! Number of errors found = %d\n", tag, elapsedMillisecond(&clock), retry, count_err);
+ return count_err;
+ }
+ logError(1, "%s pollForEvent: ERROR %02X\n", tag, ERROR_I2C_R);
+ return ERROR_I2C_R;
+}
+
+int flushFIFO(void)
+{
+
+ u8 cmd = FIFO_CMD_FLUSH; /* flush the FIFO */
+ if (fts_writeCmd(&cmd, 1) < 0) {
+ logError(1, "%s flushFIFO: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+
+ logError(0, "%s FIFO flushed!\n", tag);
+ return OK;
+
+}
+
+int fts_disableInterrupt(void)
+{
+ u8 cmd[4] = { FTS_CMD_HW_REG_W, 0x00, 0x00, IER_DISABLE }; /* disable interrupt */
+ u16ToU8_be(IER_ADDR, &cmd[1]);
+
+ if (fts_writeCmd(cmd, 4) < OK) {
+ logError(1, "%s fts_disableInterrupt: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+ logError(0, "%s Interrupt Disabled!\n", tag);
+ return OK;
+}
+
+int fts_enableInterrupt(void)
+{
+ u8 cmd[4] = { FTS_CMD_HW_REG_W, 0x00, 0x00, IER_ENABLE }; /* enable interrupt */
+ u16ToU8_be(IER_ADDR, &cmd[1]);
+ if (fts_writeCmd(cmd, 4) < 0) {
+ logError(1, "%s fts_enableInterrupt: ERROR %02X\n", tag, ERROR_I2C_W);
+ return ERROR_I2C_W;
+ }
+ logError(0, "%s Interrupt Enabled!\n", tag);
+ return OK;
+}
+
+int u8ToU16n(u8 *src, int src_length, u16 *dst)
+{
+ int i, j;
+
+ if (src_length % 2 != 0) {
+ return 0;
+ }
+ j = 0;
+ dst = (u16 *)kmalloc((src_length / 2)*sizeof(u16), GFP_KERNEL);
+ for (i = 0; i < src_length; i += 2) {
+ dst[j] = ((src[i+1] & 0x00FF) << 8) + (src[i] & 0x00FF);
+ j++;
+ }
+
+ return (src_length / 2);
+}
+
+int u8ToU16(u8 *src, u16 *dst)
+{
+ *dst = (u16)(((src[1] & 0x00FF) << 8) + (src[0] & 0x00FF));
+ return 0;
+}
+
+int u8ToU16_le(u8 *src, u16 *dst)
+{
+ *dst = (u16)(((src[0] & 0x00FF) << 8) + (src[1] & 0x00FF));
+ return 0;
+}
+
+int u16ToU8n(u16 *src, int src_length, u8 *dst)
+{
+ int i, j;
+ dst = (u8 *)kmalloc((2 * src_length)*sizeof(u8), GFP_KERNEL);
+ j = 0;
+ for (i = 0; i < src_length; i++) {
+ dst[j] = (u8) (src[i] & 0xFF00)>>8;
+ dst[j+1] = (u8) (src[i] & 0x00FF);
+ j += 2;
+ }
+
+ return src_length * 2;
+
+}
+
+int u16ToU8(u16 src, u8 *dst)
+{
+ dst[0] = (u8)((src & 0xFF00) >> 8);
+ dst[1] = (u8)(src & 0x00FF);
+ return 0;
+}
+
+int u16ToU8_be(u16 src, u8 *dst)
+{
+ dst[0] = (u8)((src & 0xFF00) >> 8);
+ dst[1] = (u8)(src & 0x00FF);
+ return 0;
+}
+
+int u16ToU8_le(u16 src, u8 *dst)
+{
+ dst[1] = (u8)((src & 0xFF00) >> 8);
+ dst[0] = (u8)(src & 0x00FF);
+ return 0;
+}
+
+int u8ToU32(u8 *src, u32 *dst)
+{
+ *dst = (u32)(((src[3] & 0x000000FF) << 24) + ((src[2] & 0x000000FF) << 16) + ((src[1] & 0x000000FF) << 8) + (src[0] & 0x000000FF));
+ return 0;
+}
+
+int u32ToU8(u32 src, u8 *dst)
+{
+ dst[3] = (u8)((src & 0xFF000000) >> 24);
+ dst[2] = (u8)((src & 0x00FF0000) >> 16);
+ dst[1] = (u8)((src & 0x0000FF00) >> 8);
+ dst[0] = (u8)(src & 0x000000FF);
+ return 0;
+}
+
+int attempt_function(int(*code)(void), unsigned long wait_before_retry, int retry_count)
+{
+ int result;
+ int count = 0;
+
+ do {
+ result = code();
+ count++;
+ msleep(wait_before_retry);
+ } while (count < retry_count && result < 0);
+
+ if (count == retry_count)
+ return (result | ERROR_TIMEOUT);
+ else
+ return result;
+
+}
+
+void setResetGpio(int gpio)
+{
+ reset_gpio = gpio;
+ logError(1, "%s setResetGpio: reset_gpio = %d\n", tag, reset_gpio);
+}
+
+int fts_system_reset(void)
+{
+ u8 readData[FIFO_EVENT_SIZE];
+ int event_to_search;
+ int res = -1;
+ int i;
+ u8 cmd[4] = { FTS_CMD_HW_REG_W, 0x00, 0x00, SYSTEM_RESET_VALUE };
+ event_to_search = (int)EVENTID_CONTROL_READY;
+
+ u16ToU8_be(SYSTEM_RESET_ADDRESS, &cmd[1]);
+ logError(0, "%s System resetting...\n", tag);
+ for (i = 0; i < SYSTEM_RESET_RETRY && res < 0; i++) {
+
+ if (reset_gpio == GPIO_NOT_DEFINED) {
+ res = fts_writeCmd(cmd, 4);
+ } else {
+ gpio_set_value(reset_gpio, 0);
+ msleep(10);
+ gpio_set_value(reset_gpio, 1);
+ res = OK;
+ }
+ if (res < OK) {
+ logError(1, "%s fts_system_reset: ERROR %02X\n", tag, ERROR_I2C_W);
+ } else {
+ res = pollForEvent(&event_to_search, 1, readData, GENERAL_TIMEOUT);
+ if (res < OK) {
+ logError(1, "%s fts_system_reset: ERROR %02X\n", tag, res);
+ }
+ }
+ }
+ if (res < OK) {
+ logError(1, "%s fts_system_reset...failed after 3 attempts: ERROR %02X\n", tag, (res | ERROR_SYSTEM_RESET_FAIL));
+ return (res | ERROR_SYSTEM_RESET_FAIL);
+ }
+ logError(0, "%s System reset DONE!\n", tag);
+ system_resetted_down = 1;
+ system_resetted_up = 1;
+ return OK;
+
+}
+
+int isSystemResettedDown(void)
+{
+ return system_resetted_down;
+}
+
+int isSystemResettedUp(void)
+{
+ return system_resetted_up;
+}
+
+void setSystemResettedDown(int val)
+{
+ system_resetted_down = val;
+}
+
+void setSystemResettedUp(int val)
+{
+ system_resetted_up = val;
+}
+
+int senseOn(void)
+{
+ int ret;
+ u8 cmd[1] = { FTS_CMD_MS_MT_SENSE_ON };
+
+ ret = fts_writeFwCmd(cmd, 1);
+ if (ret < OK) {
+ logError(1, "%s senseOn: ERROR %02X\n", tag, ERROR_SENSE_ON_FAIL);
+ return (ret|ERROR_SENSE_ON_FAIL);
+ }
+
+ logError(0, "%s senseOn: SENSE ON\n", tag);
+ return OK;
+}
+
+int senseOff(void)
+{
+ int ret;
+ u8 cmd[1] = { FTS_CMD_MS_MT_SENSE_OFF };
+
+ ret = fts_writeFwCmd(cmd, 1);
+ if (ret < OK) {
+ logError(1, "%s senseOff: ERROR %02X\n", tag, ERROR_SENSE_OFF_FAIL);
+ return (ret | ERROR_SENSE_OFF_FAIL);
+ }
+
+ logError(0, "%s senseOff: SENSE OFF\n", tag);
+ return OK;
+
+}
+
+int keyOn(void)
+{
+ int ret;
+ u8 cmd[1] = { FTS_CMD_MS_KEY_ON };
+
+ ret = fts_writeFwCmd(cmd, 1);
+ if (ret < OK) {
+ logError(1, "%s keyOn: ERROR %02X\n", tag, ERROR_SENSE_ON_FAIL);
+ return (ret | ERROR_SENSE_ON_FAIL);
+ }
+
+ logError(0, "%s keyOn: KEY ON\n", tag);
+ return OK;
+
+}
+
+int keyOff(void)
+{
+ int ret;
+ u8 cmd[1] = { FTS_CMD_MS_KEY_OFF };
+
+ ret = fts_writeFwCmd(cmd, 1);
+ if (ret < OK) {
+ logError(1, "%s keyOff: ERROR %02X\n", tag, ERROR_SENSE_OFF_FAIL);
+ return (ret | ERROR_SENSE_OFF_FAIL);
+ }
+
+ logError(0, "%s keyOff: KEY OFF\n", tag);
+ return OK;
+
+}
+
+int cleanUp(int enableTouch)
+{
+ int res;
+
+ logError(0, "%s cleanUp: system reset...\n", tag);
+ res = fts_system_reset();
+ if (res < OK)
+ return res;
+ if (enableTouch) {
+ logError(0, "%s cleanUp: enabling touches...\n", tag);
+ res = senseOn();
+ if (res < OK)
+ return res;
+#ifdef PHONE_KEY
+ res = keyOn();
+ if (res < OK)
+ return res;
+#endif
+ logError(0, "%s cleanUp: enabling interrupts...\n", tag);
+ res = fts_enableInterrupt();
+ if (res < OK)
+ return res;
+ }
+ return OK;
+
+}
+
+int checkEcho(u8 *cmd, int size)
+{
+ int ret, i;
+ int event_to_search[size+1];
+ u8 readData[FIFO_EVENT_SIZE];
+
+ if ((ftsInfo.u32_echoEn & 0x00000001) != ECHO_ENABLED) {
+ logError(1, "%s ECHO Not Enabled!\n", tag);
+ return OK;
+ }
+ if (size < 1) {
+ logError(1, "%s checkEcho: Error Size = %d not valid! or ECHO not Enabled! ERROR %08X\n", tag, size, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+ if ((size+2) > FIFO_EVENT_SIZE)
+ size = FIFO_EVENT_SIZE-2;
+ /* Echo event EC xx xx xx xx xx xx fifo_status therefore for command
+ *with more than 6 bytes will echo only the first 6
+ */
+ event_to_search[0] = EVENTID_ECHO;
+ for (i = 1; i <= size; i++) {
+ event_to_search[i] = cmd[i-1];
+ }
+ ret = pollForEvent(event_to_search, size+1, readData, GENERAL_TIMEOUT);
+ if (ret < OK) {
+ logError(1, "%s checkEcho: Echo Event not found! ERROR %02X\n", tag, ret);
+ return (ret | ERROR_CHECK_ECHO_FAIL);
+ }
+
+ logError(0, "%s ECHO OK!\n", tag);
+ return OK;
+}
+
+int featureEnableDisable(int on_off, u8 feature)
+{
+ int ret;
+ u8 cmd[2] = { 0x00, feature };
+
+ if (on_off == FEAT_ENABLE) {
+ cmd[0] = FTS_CMD_FEATURE_ENABLE;
+ logError(0, "%s featureEnableDisable: Enabling feature %02X ...\n", tag, feature);
+ } else {
+ cmd[0] = FTS_CMD_FEATURE_DISABLE;
+ logError(0, "%s featureEnableDisable: Disabling feature %02X ...\n", tag, feature);
+ }
+
+ ret = fts_writeCmd(cmd, 2); /* not use writeFwCmd because this function can be called also during interrupt enable and should be fast */
+ if (ret < OK) {
+ logError(1, "%s featureEnableDisable: ERROR %02X\n", tag, ret);
+ return (ret | ERROR_FEATURE_ENABLE_DISABLE);
+ }
+
+ logError(0, "%s featureEnableDisable: DONE!\n", tag);
+ return OK;
+
+}
+
+short **array1dTo2d_short(short *data, int size, int columns)
+{
+
+ int i;
+ short **matrix = (short **)kmalloc(((int)(size / columns))*sizeof(short *), GFP_KERNEL);
+ if (matrix != NULL) {
+ for (i = 0; i < (int)(size / columns); i++) {
+ matrix[i] = (short *)kmalloc(columns*sizeof(short), GFP_KERNEL);
+ }
+
+ for (i = 0; i < size; i++)
+ matrix[i / columns][i % columns] = data[i];
+ }
+
+ return matrix;
+}
+
+u8 **array1dTo2d_u8(u8 *data, int size, int columns)
+{
+
+ int i;
+ u8 **matrix = (u8 **)kmalloc(((int)(size / columns))*sizeof(u8 *), GFP_KERNEL);
+ if (matrix != NULL) {
+ for (i = 0; i < (int)(size / columns); i++) {
+ matrix[i] = (u8 *)kmalloc(columns*sizeof(u8), GFP_KERNEL);
+ }
+
+ for (i = 0; i < size; i++)
+ matrix[i / columns][i % columns] = data[i];
+ }
+
+ return matrix;
+}
+
+void print_frame_short(char *label, short **matrix, int row, int column)
+{
+ int i, j;
+ logError(0, "%s %s\n", tag, label);
+ for (i = 0; i < row; i++) {
+ logError(0, "%s ", tag);
+ for (j = 0; j < column; j++) {
+ printk("%d ", matrix[i][j]);
+ }
+ logError(0, "\n");
+ kfree(matrix[i]);
+ }
+}
+
+void print_frame_u8(char *label, u8 **matrix, int row, int column)
+{
+ int i, j;
+ logError(0, "%s %s\n", tag, label);
+ for (i = 0; i < row; i++) {
+ logError(0, "%s ", tag);
+ for (j = 0; j < column; j++) {
+ printk("%d ", matrix[i][j]);
+ }
+ logError(0, "\n");
+ kfree(matrix[i]);
+ }
+}
+
+void print_frame_u32(char *label, u32 **matrix, int row, int column)
+{
+ int i, j;
+ logError(0, "%s %s\n", tag, label);
+ for (i = 0; i < row; i++) {
+ logError(0, "%s ", tag);
+ for (j = 0; j < column; j++) {
+ printk("%d ", matrix[i][j]);
+ }
+ logError(0, "\n");
+ kfree(matrix[i]);
+ }
+}
+
+void print_frame_int(char *label, int **matrix, int row, int column)
+{
+ int i, j;
+ logError(0, "%s %s\n", tag, label);
+ for (i = 0; i < row; i++) {
+ logError(0, "%s ", tag);
+ for (j = 0; j < column; j++) {
+ printk("%d ", matrix[i][j]);
+ }
+ logError(0, "\n");
+ kfree(matrix[i]);
+ }
+}
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsTool.h b/drivers/input/touchscreen/st/fts_lib/ftsTool.h
new file mode 100644
index 000000000000..a90e79fc5607
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_lib/ftsTool.h
@@ -0,0 +1,64 @@
+/*
+
+**************************************************************************
+** STMicroelectronics **
+**************************************************************************
+** marco.cali@st.com **
+**************************************************************************
+* *
+* FTS Utility Functions *
+* *
+**************************************************************************
+**************************************************************************
+
+*/
+#define GPIO_NOT_DEFINED -1
+
+#define TIMEOUT_RESOLUTION 10 /* ms */
+#define GENERAL_TIMEOUT (50*TIMEOUT_RESOLUTION) /* ms */
+#define RELEASE_INFO_TIMEOUT (15*TIMEOUT_RESOLUTION) /* ms */
+
+#define FEAT_ENABLE 1
+#define FEAT_DISABLE 0
+
+#define SYSTEM_RESET_RETRY 3
+
+#define B2_RETRY 2
+
+int readB2(u16 address, u8 *outBuf, int len);
+int readB2U16(u16 address, u8 *outBuf, int byteToRead);
+int releaseInformation(void);
+char *printHex(char *label, u8 *buff, int count);
+int pollForEvent(int *event_to_search, int event_bytes, u8 *readData, int time_to_wait);
+int fts_disableInterrupt(void);
+int fts_enableInterrupt(void);
+int u8ToU16(u8 *src, u16 *dst);
+int u8ToU16_le(u8 *src, u16 *dst);
+int u8ToU16n(u8 *src, int src_length, u16 *dst);
+int u16ToU8(u16 src, u8 *dst);
+int u16ToU8_le(u16 src, u8 *dst);
+int u16ToU8_be(u16 src, u8 *dst);
+int u16ToU8n(u16 *src, int src_length, u8 *dst);
+int u8ToU32(u8 *src, u32 *dst);
+int u32ToU8(u32 src, u8 *dst);
+int attempt_function(int(*code)(void), unsigned long wait_before_retry, int retry_count);
+void setResetGpio(int gpio);
+int fts_system_reset(void);
+int isSystemResettedUp(void);
+int isSystemResettedDown(void);
+void setSystemResettedUp(int val);
+void setSystemResettedDown(int val);
+int senseOn(void);
+int senseOff(void);
+int keyOn(void);
+int keyOff(void);
+int featureEnableDisable(int on_off, u8 feature);
+int checkEcho(u8 *cmd, int size);
+void print_frame_short(char *label, short **matrix, int row, int column);
+short **array1dTo2d_short(short *data, int size, int columns);
+u8 **array1dTo2d_u8(u8 *data, int size, int columns);
+void print_frame_u8(char *label, u8 **matrix, int row, int column);
+void print_frame_u32(char *label, u32 **matrix, int row, int column);
+void print_frame_int(char *label, int **matrix, int row, int column);
+int cleanUp(int enableTouch);
+int flushFIFO(void);
diff --git a/drivers/input/touchscreen/st/fts_limits.h b/drivers/input/touchscreen/st/fts_limits.h
new file mode 100644
index 000000000000..d3be1a2b1e1a
--- /dev/null
+++ b/drivers/input/touchscreen/st/fts_limits.h
@@ -0,0 +1,10 @@
+#ifndef FTS_LIMITS_H
+#define FTS_LIMITS_H
+/* This is an auto generated header file
+* --->Remember to change the name of the two variables!<--- */
+const uint32_t myArray2_size;
+
+const uint8_t myArray2[] = {
+};
+
+#endif
diff --git a/drivers/input/touchscreen/synaptics_dsx/Kconfig b/drivers/input/touchscreen/synaptics_dsx/Kconfig
new file mode 100644
index 000000000000..18d473969261
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics_dsx/Kconfig
@@ -0,0 +1,64 @@
+#
+# Synaptics DSX touchscreen driver configuration
+#
+menuconfig TOUCHSCREEN_SYNAPTICS_DSX_v21
+ bool "Synaptics DSX touchscreen"
+ default y
+ help
+ Say Y here if you have a Synaptics DSX touchscreen connected
+ to your system.
+
+ If unsure, say N.
+
+if TOUCHSCREEN_SYNAPTICS_DSX_v21
+
+choice
+ default TOUCHSCREEN_SYNAPTICS_DSX_I2C_v21
+ prompt "Synaptics DSX touchscreen bus interface"
+
+config TOUCHSCREEN_SYNAPTICS_DSX_I2C_v21
+ bool "I2C"
+ depends on I2C
+ help
+ Say Y here if you have a Synaptics DSX touchscreen interfaced
+ to the host processor over I2C
+
+ If unsure, say N.
+
+ This module uses the services of DSX CORE
+
+config TOUCHSCREEN_SYNAPTICS_DSX_SPI_v21
+ bool "SPI"
+ depends on SPI_MASTER
+ help
+ Say Y here if you have a Synaptics DSX touchscreen interfaced
+ to the host processor over SPI
+
+ If unsure, say N.
+
+ This module uses the services of DSX CORE
+endchoice
+
+config TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21
+ tristate "Synaptics DSX core driver module"
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_I2C_v21 || TOUCHSCREEN_SYNAPTICS_DSX_SPI_v21
+ help
+ Say Y here to enable basic touch reporting functionalities.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called synaptics_dsx_core.
+
+config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21
+ tristate "Synaptics DSX touchscreen firmware update module"
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21
+ help
+ Say Y here to enable support for carrying out firmware update.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called synaptics_dsx_fw_update.
+
+endif
diff --git a/drivers/input/touchscreen/synaptics_dsx/Makefile b/drivers/input/touchscreen/synaptics_dsx/Makefile
new file mode 100644
index 000000000000..0bffb8da94ea
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics_dsx/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Synaptics DSX touchscreen driver.
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C_v21) += synaptics_dsx_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI_v21) += synaptics_dsx_spi.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21) += synaptics_dsx_core.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21) += synaptics_dsx_fw_update.o
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
new file mode 100644
index 000000000000..6f6cb35d90da
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
@@ -0,0 +1,4506 @@
+/*
+ * Synaptics DSX touchscreen driver
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/input/synaptics_dsx_v2.h>
+#include "synaptics_dsx_core.h"
+#ifdef KERNEL_ABOVE_2_6_38
+#include <linux/input/mt.h>
+#endif
+#if defined(CONFIG_SECURE_TOUCH)
+#include <linux/errno.h>
+#include <soc/qcom/scm.h>
+enum subsystem {
+ TZ = 1,
+ APSS = 3
+};
+
+#define TZ_BLSP_MODIFY_OWNERSHIP_ID 3
+#endif
+
+#define INPUT_PHYS_NAME "synaptics_dsx/input0"
+#define DEBUGFS_DIR_NAME "ts_debug"
+
+#ifdef KERNEL_ABOVE_2_6_38
+#define TYPE_B_PROTOCOL
+#endif
+
+#define NO_0D_WHILE_2D
+#define REPORT_2D_Z
+#define REPORT_2D_W
+
+#define F12_DATA_15_WORKAROUND
+
+/*
+#define IGNORE_FN_INIT_FAILURE
+*/
+
+#define RPT_TYPE (1 << 0)
+#define RPT_X_LSB (1 << 1)
+#define RPT_X_MSB (1 << 2)
+#define RPT_Y_LSB (1 << 3)
+#define RPT_Y_MSB (1 << 4)
+#define RPT_Z (1 << 5)
+#define RPT_WX (1 << 6)
+#define RPT_WY (1 << 7)
+#define RPT_DEFAULT (RPT_TYPE | RPT_X_LSB | RPT_X_MSB | RPT_Y_LSB | RPT_Y_MSB)
+
+#define EXP_FN_WORK_DELAY_MS 1000 /* ms */
+#define MAX_F11_TOUCH_WIDTH 15
+
+#define CHECK_STATUS_TIMEOUT_MS 100
+
+#define F01_STD_QUERY_LEN 21
+#define F01_BUID_ID_OFFSET 18
+#define F11_STD_QUERY_LEN 9
+#define F11_STD_CTRL_LEN 10
+#define F11_STD_DATA_LEN 12
+
+#define STATUS_NO_ERROR 0x00
+#define STATUS_RESET_OCCURRED 0x01
+#define STATUS_INVALID_CONFIG 0x02
+#define STATUS_DEVICE_FAILURE 0x03
+#define STATUS_CONFIG_CRC_FAILURE 0x04
+#define STATUS_FIRMWARE_CRC_FAILURE 0x05
+#define STATUS_CRC_IN_PROGRESS 0x06
+
+#define NORMAL_OPERATION (0 << 0)
+#define SENSOR_SLEEP (1 << 0)
+#define NO_SLEEP_OFF (0 << 2)
+#define NO_SLEEP_ON (1 << 2)
+#define CONFIGURED (1 << 7)
+
+#define SYNA_F11_MAX 4096
+#define SYNA_F12_MAX 65536
+
+#define SYNA_S332U_PACKAGE_ID 332
+#define SYNA_S332U_PACKAGE_ID_REV 85
+
+static int synaptics_rmi4_f12_set_enables(struct synaptics_rmi4_data *rmi4_data,
+ unsigned short ctrl28);
+
+static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data);
+static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data);
+static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data);
+
+static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_full_pm_cycle_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+#if defined(CONFIG_FB)
+static void fb_notify_resume_work(struct work_struct *work);
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void synaptics_rmi4_early_suspend(struct early_suspend *h);
+
+static void synaptics_rmi4_late_resume(struct early_suspend *h);
+#endif
+
+static int synaptics_rmi4_suspend(struct device *dev);
+
+static int synaptics_rmi4_resume(struct device *dev);
+
+static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_rmi4_set_abs_x_axis(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_rmi4_set_abs_y_axis(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static irqreturn_t synaptics_rmi4_irq(int irq, void *data);
+
+#if defined(CONFIG_SECURE_TOUCH)
+static ssize_t synaptics_secure_touch_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_secure_touch_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_secure_touch_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+#endif
+
+struct synaptics_rmi4_f01_device_status {
+ union {
+ struct {
+ unsigned char status_code:4;
+ unsigned char reserved:2;
+ unsigned char flash_prog:1;
+ unsigned char unconfigured:1;
+ } __packed;
+ unsigned char data[1];
+ };
+};
+
+struct synaptics_rmi4_f12_query_5 {
+ union {
+ struct {
+ unsigned char size_of_query6;
+ struct {
+ unsigned char ctrl0_is_present:1;
+ unsigned char ctrl1_is_present:1;
+ unsigned char ctrl2_is_present:1;
+ unsigned char ctrl3_is_present:1;
+ unsigned char ctrl4_is_present:1;
+ unsigned char ctrl5_is_present:1;
+ unsigned char ctrl6_is_present:1;
+ unsigned char ctrl7_is_present:1;
+ } __packed;
+ struct {
+ unsigned char ctrl8_is_present:1;
+ unsigned char ctrl9_is_present:1;
+ unsigned char ctrl10_is_present:1;
+ unsigned char ctrl11_is_present:1;
+ unsigned char ctrl12_is_present:1;
+ unsigned char ctrl13_is_present:1;
+ unsigned char ctrl14_is_present:1;
+ unsigned char ctrl15_is_present:1;
+ } __packed;
+ struct {
+ unsigned char ctrl16_is_present:1;
+ unsigned char ctrl17_is_present:1;
+ unsigned char ctrl18_is_present:1;
+ unsigned char ctrl19_is_present:1;
+ unsigned char ctrl20_is_present:1;
+ unsigned char ctrl21_is_present:1;
+ unsigned char ctrl22_is_present:1;
+ unsigned char ctrl23_is_present:1;
+ } __packed;
+ struct {
+ unsigned char ctrl24_is_present:1;
+ unsigned char ctrl25_is_present:1;
+ unsigned char ctrl26_is_present:1;
+ unsigned char ctrl27_is_present:1;
+ unsigned char ctrl28_is_present:1;
+ unsigned char ctrl29_is_present:1;
+ unsigned char ctrl30_is_present:1;
+ unsigned char ctrl31_is_present:1;
+ } __packed;
+ };
+ unsigned char data[5];
+ };
+};
+
+struct synaptics_rmi4_f12_query_8 {
+ union {
+ struct {
+ unsigned char size_of_query9;
+ struct {
+ unsigned char data0_is_present:1;
+ unsigned char data1_is_present:1;
+ unsigned char data2_is_present:1;
+ unsigned char data3_is_present:1;
+ unsigned char data4_is_present:1;
+ unsigned char data5_is_present:1;
+ unsigned char data6_is_present:1;
+ unsigned char data7_is_present:1;
+ } __packed;
+ struct {
+ unsigned char data8_is_present:1;
+ unsigned char data9_is_present:1;
+ unsigned char data10_is_present:1;
+ unsigned char data11_is_present:1;
+ unsigned char data12_is_present:1;
+ unsigned char data13_is_present:1;
+ unsigned char data14_is_present:1;
+ unsigned char data15_is_present:1;
+ } __packed;
+ };
+ unsigned char data[3];
+ };
+};
+
+struct synaptics_rmi4_f12_ctrl_8 {
+ union {
+ struct {
+ unsigned char max_x_coord_lsb;
+ unsigned char max_x_coord_msb;
+ unsigned char max_y_coord_lsb;
+ unsigned char max_y_coord_msb;
+ unsigned char rx_pitch_lsb;
+ unsigned char rx_pitch_msb;
+ unsigned char tx_pitch_lsb;
+ unsigned char tx_pitch_msb;
+ unsigned char low_rx_clip;
+ unsigned char high_rx_clip;
+ unsigned char low_tx_clip;
+ unsigned char high_tx_clip;
+ unsigned char num_of_rx;
+ unsigned char num_of_tx;
+ };
+ unsigned char data[14];
+ };
+};
+
+struct synaptics_rmi4_f12_ctrl_23 {
+ union {
+ struct {
+ unsigned char obj_type_enable;
+ unsigned char max_reported_objects;
+ };
+ unsigned char data[2];
+ };
+};
+
+struct synaptics_rmi4_f12_finger_data {
+ unsigned char object_type_and_status;
+ unsigned char x_lsb;
+ unsigned char x_msb;
+ unsigned char y_lsb;
+ unsigned char y_msb;
+#ifdef REPORT_2D_Z
+ unsigned char z;
+#endif
+#ifdef REPORT_2D_W
+ unsigned char wx;
+ unsigned char wy;
+#endif
+};
+
+struct synaptics_rmi4_f1a_query {
+ union {
+ struct {
+ unsigned char max_button_count:3;
+ unsigned char reserved:5;
+ unsigned char has_general_control:1;
+ unsigned char has_interrupt_enable:1;
+ unsigned char has_multibutton_select:1;
+ unsigned char has_tx_rx_map:1;
+ unsigned char has_perbutton_threshold:1;
+ unsigned char has_release_threshold:1;
+ unsigned char has_strongestbtn_hysteresis:1;
+ unsigned char has_filter_strength:1;
+ } __packed;
+ unsigned char data[2];
+ };
+};
+
+struct synaptics_rmi4_f1a_control_0 {
+ union {
+ struct {
+ unsigned char multibutton_report:2;
+ unsigned char filter_mode:2;
+ unsigned char reserved:4;
+ } __packed;
+ unsigned char data[1];
+ };
+};
+
+struct synaptics_rmi4_f1a_control {
+ struct synaptics_rmi4_f1a_control_0 general_control;
+ unsigned char button_int_enable;
+ unsigned char multi_button;
+ unsigned char *txrx_map;
+ unsigned char *button_threshold;
+ unsigned char button_release_threshold;
+ unsigned char strongest_button_hysteresis;
+ unsigned char filter_strength;
+};
+
+struct synaptics_rmi4_f1a_handle {
+ int button_bitmask_size;
+ unsigned char max_count;
+ unsigned char valid_button_count;
+ unsigned char *button_data_buffer;
+ unsigned char *button_map;
+ struct synaptics_rmi4_f1a_query button_query;
+ struct synaptics_rmi4_f1a_control button_control;
+};
+
+struct synaptics_rmi4_exp_fhandler {
+ struct synaptics_rmi4_exp_fn *exp_fn;
+ bool insert;
+ bool remove;
+ struct list_head link;
+};
+
+struct synaptics_rmi4_exp_fn_data {
+ bool initialized;
+ bool queue_work;
+ struct mutex mutex;
+ struct list_head list;
+ struct delayed_work work;
+ struct workqueue_struct *workqueue;
+ struct synaptics_rmi4_data *rmi4_data;
+};
+
+static struct synaptics_rmi4_exp_fn_data exp_data;
+
+static struct device_attribute attrs[] = {
+ __ATTR(full_pm_cycle, (S_IRUGO | S_IWUSR | S_IWGRP),
+ synaptics_rmi4_full_pm_cycle_show,
+ synaptics_rmi4_full_pm_cycle_store),
+ __ATTR(reset, (S_IWUSR | S_IWGRP),
+ NULL,
+ synaptics_rmi4_f01_reset_store),
+ __ATTR(set_abs_x_axis, (S_IWUSR | S_IWGRP),
+ NULL,
+ synaptics_rmi4_set_abs_x_axis),
+ __ATTR(set_abs_y_axis, (S_IWUSR | S_IWGRP),
+ NULL,
+ synaptics_rmi4_set_abs_y_axis),
+ __ATTR(productinfo, S_IRUGO,
+ synaptics_rmi4_f01_productinfo_show,
+ synaptics_rmi4_store_error),
+ __ATTR(buildid, S_IRUGO,
+ synaptics_rmi4_f01_buildid_show,
+ synaptics_rmi4_store_error),
+ __ATTR(flashprog, S_IRUGO,
+ synaptics_rmi4_f01_flashprog_show,
+ synaptics_rmi4_store_error),
+ __ATTR(0dbutton, (S_IRUGO | S_IWUSR | S_IWGRP),
+ synaptics_rmi4_0dbutton_show,
+ synaptics_rmi4_0dbutton_store),
+#if defined(CONFIG_SECURE_TOUCH)
+ __ATTR(secure_touch_enable, (S_IRUGO | S_IWUSR | S_IWGRP),
+ synaptics_secure_touch_enable_show,
+ synaptics_secure_touch_enable_store),
+ __ATTR(secure_touch, S_IRUGO ,
+ synaptics_secure_touch_show,
+ NULL),
+#endif
+};
+
+#define MAX_BUF_SIZE 256
+#define VKEY_VER_CODE "0x01"
+
+#define HEIGHT_SCALE_NUM 8
+#define HEIGHT_SCALE_DENOM 10
+
+/* numerator and denomenator for border equations */
+#define BORDER_ADJUST_NUM 3
+#define BORDER_ADJUST_DENOM 4
+
+static struct kobject *vkey_kobj;
+static char *vkey_buf;
+
+static ssize_t vkey_show(struct kobject *obj,
+ struct kobj_attribute *attr, char *buf)
+{
+ strlcpy(buf, vkey_buf, MAX_BUF_SIZE);
+ return strnlen(buf, MAX_BUF_SIZE);
+}
+
+static struct kobj_attribute vkey_obj_attr = {
+ .attr = {
+ .mode = S_IRUGO,
+ .name = "virtualkeys."PLATFORM_DRIVER_NAME,
+ },
+ .show = vkey_show,
+};
+
+static struct attribute *vkey_attr[] = {
+ &vkey_obj_attr.attr,
+ NULL,
+};
+
+static struct attribute_group vkey_grp = {
+ .attrs = vkey_attr,
+};
+
+static int synaptics_rmi4_debug_suspend_set(void *_data, u64 val)
+{
+ struct synaptics_rmi4_data *rmi4_data = _data;
+
+ if (val)
+ synaptics_rmi4_suspend(&rmi4_data->input_dev->dev);
+ else
+ synaptics_rmi4_resume(&rmi4_data->input_dev->dev);
+
+ return 0;
+}
+
+static int synaptics_rmi4_debug_suspend_get(void *_data, u64 *val)
+{
+ struct synaptics_rmi4_data *rmi4_data = _data;
+
+ *val = rmi4_data->suspended;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, synaptics_rmi4_debug_suspend_get,
+ synaptics_rmi4_debug_suspend_set, "%lld\n");
+
+#if defined(CONFIG_SECURE_TOUCH)
+static int synaptics_i2c_change_pipe_owner(
+ struct synaptics_rmi4_data *rmi4_data, enum subsystem subsystem)
+{
+ /*scm call descriptor */
+ struct scm_desc desc = {0};
+ struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+ int ret = 0;
+
+ /* number of arguments */
+ desc.arginfo = SCM_ARGS(2);
+ /* BLSPID (1-12) */
+ desc.args[0] = i2c->adapter->nr - 1;
+ /* Owner if TZ or APSS */
+ desc.args[1] = subsystem;
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_TZ, TZ_BLSP_MODIFY_OWNERSHIP_ID),
+ &desc);
+ if (ret)
+ return ret;
+
+ return desc.ret[0];
+}
+
+static void synaptics_secure_touch_init(struct synaptics_rmi4_data *data)
+{
+ data->st_initialized = 0;
+ init_completion(&data->st_powerdown);
+ init_completion(&data->st_irq_processed);
+ /* Get clocks */
+ data->core_clk = clk_get(data->pdev->dev.parent, "core_clk");
+ if (IS_ERR(data->core_clk)) {
+ data->core_clk = NULL;
+ dev_warn(data->pdev->dev.parent,
+ "%s: core_clk is not defined\n", __func__);
+ }
+
+ data->iface_clk = clk_get(data->pdev->dev.parent, "iface_clk");
+ if (IS_ERR(data->iface_clk)) {
+ data->iface_clk = NULL;
+ dev_warn(data->pdev->dev.parent,
+ "%s: iface_clk is not defined\n", __func__);
+ }
+
+ data->st_initialized = 1;
+}
+static void synaptics_secure_touch_notify(struct synaptics_rmi4_data *rmi4_data)
+{
+ sysfs_notify(&rmi4_data->input_dev->dev.kobj, NULL, "secure_touch");
+}
+static irqreturn_t synaptics_filter_interrupt(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ if (atomic_read(&rmi4_data->st_enabled)) {
+ if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, 0, 1) == 0) {
+ reinit_completion(&rmi4_data->st_irq_processed);
+ synaptics_secure_touch_notify(rmi4_data);
+ wait_for_completion_interruptible(
+ &rmi4_data->st_irq_processed);
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+static void synaptics_secure_touch_stop(
+ struct synaptics_rmi4_data *rmi4_data,
+ int blocking)
+{
+ if (atomic_read(&rmi4_data->st_enabled)) {
+ atomic_set(&rmi4_data->st_pending_irqs, -1);
+ synaptics_secure_touch_notify(rmi4_data);
+ if (blocking)
+ wait_for_completion_interruptible(
+ &rmi4_data->st_powerdown);
+ }
+}
+#else
+static void synaptics_secure_touch_init(struct synaptics_rmi4_data *rmi4_data)
+{
+}
+static irqreturn_t synaptics_filter_interrupt(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ return IRQ_NONE;
+}
+static void synaptics_secure_touch_stop(
+ struct synaptics_rmi4_data *rmi4_data,
+ int blocking)
+{
+}
+#endif
+
+#if defined(CONFIG_SECURE_TOUCH)
+static ssize_t synaptics_secure_touch_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+ return scnprintf(
+ buf,
+ PAGE_SIZE,
+ "%d",
+ atomic_read(&rmi4_data->st_enabled));
+}
+/*
+ * Accept only "0" and "1" valid values.
+ * "0" will reset the st_enabled flag, then wake up the reading process and
+ * the interrupt handler.
+ * The bus driver is notified via pm_runtime that it is not required to stay
+ * awake anymore.
+ * It will also make sure the queue of events is emptied in the controller,
+ * in case a touch happened in between the secure touch being disabled and
+ * the local ISR being ungated.
+ * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
+ * The bus driver is requested via pm_runtime to stay awake.
+ */
+static ssize_t synaptics_secure_touch_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+ unsigned long value;
+ int err = 0;
+
+ if (count > 2)
+ return -EINVAL;
+
+ err = kstrtoul(buf, 10, &value);
+ if (err != 0)
+ return err;
+
+ if (!rmi4_data->st_initialized)
+ return -EIO;
+
+ err = count;
+
+ switch (value) {
+ case 0:
+ if (atomic_read(&rmi4_data->st_enabled) == 0)
+ break;
+
+ synaptics_i2c_change_pipe_owner(rmi4_data, APSS);
+ synaptics_rmi4_bus_put(rmi4_data);
+ atomic_set(&rmi4_data->st_enabled, 0);
+ synaptics_secure_touch_notify(rmi4_data);
+ complete(&rmi4_data->st_irq_processed);
+ synaptics_rmi4_irq(rmi4_data->irq, rmi4_data);
+ complete(&rmi4_data->st_powerdown);
+
+ break;
+ case 1:
+ if (atomic_read(&rmi4_data->st_enabled)) {
+ err = -EBUSY;
+ break;
+ }
+
+ synchronize_irq(rmi4_data->irq);
+
+ if (synaptics_rmi4_bus_get(rmi4_data) < 0) {
+ dev_err(
+ rmi4_data->pdev->dev.parent,
+ "synaptics_rmi4_bus_get failed\n");
+ err = -EIO;
+ break;
+ }
+ synaptics_i2c_change_pipe_owner(rmi4_data, TZ);
+ reinit_completion(&rmi4_data->st_powerdown);
+ reinit_completion(&rmi4_data->st_irq_processed);
+ atomic_set(&rmi4_data->st_enabled, 1);
+ atomic_set(&rmi4_data->st_pending_irqs, 0);
+ break;
+ default:
+ dev_err(
+ rmi4_data->pdev->dev.parent,
+ "unsupported value: %lu\n", value);
+ err = -EINVAL;
+ break;
+ }
+ return err;
+}
+
+/*
+ * This function returns whether there are pending interrupts, or
+ * other error conditions that need to be signaled to the userspace library,
+ * according tot he following logic:
+ * - st_enabled is 0 if secure touch is not enabled, returning -EBADF
+ * - st_pending_irqs is -1 to signal that secure touch is in being stopped,
+ * returning -EINVAL
+ * - st_pending_irqs is 1 to signal that there is a pending irq, returning
+ * the value "1" to the sysfs read operation
+ * - st_pending_irqs is 0 (only remaining case left) if the pending interrupt
+ * has been processed, so the interrupt handler can be allowed to continue.
+ */
+static ssize_t synaptics_secure_touch_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+ int val = 0;
+ if (atomic_read(&rmi4_data->st_enabled) == 0)
+ return -EBADF;
+
+ if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, -1, 0) == -1)
+ return -EINVAL;
+
+ if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, 1, 0) == 1)
+ val = 1;
+ else
+ complete(&rmi4_data->st_irq_processed);
+
+ return scnprintf(buf, PAGE_SIZE, "%u", val);
+
+}
+#endif
+
+static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ rmi4_data->full_pm_cycle);
+}
+
+static ssize_t synaptics_rmi4_full_pm_cycle_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+
+ rmi4_data->full_pm_cycle = input > 0 ? 1 : 0;
+
+ return count;
+}
+
+static ssize_t synaptics_rmi4_set_abs_x_axis(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+
+ if (input == 0)
+ return -EINVAL;
+
+ input_set_abs_params(rmi4_data->input_dev, ABS_MT_POSITION_X,
+ 0, input, 0, 0);
+
+ return count;
+}
+
+static ssize_t synaptics_rmi4_set_abs_y_axis(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+
+ if (input == 0)
+ return -EINVAL;
+
+ input_set_abs_params(rmi4_data->input_dev, ABS_MT_POSITION_Y,
+ 0, input, 0, 0);
+
+ return count;
+}
+
+static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned int reset;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ if (sscanf(buf, "%u", &reset) != 1)
+ return -EINVAL;
+
+ if (reset != 1)
+ return -EINVAL;
+
+ retval = synaptics_rmi4_reset_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to issue reset command, error = %d\n",
+ __func__, retval);
+ return retval;
+ }
+
+ return count;
+}
+
+static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n",
+ (rmi4_data->rmi4_mod_info.product_info[0]),
+ (rmi4_data->rmi4_mod_info.product_info[1]));
+}
+
+static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ rmi4_data->firmware_id);
+}
+
+static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int retval;
+ struct synaptics_rmi4_f01_device_status device_status;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_data_base_addr,
+ device_status.data,
+ sizeof(device_status.data));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read device status, error = %d\n",
+ __func__, retval);
+ return retval;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ device_status.flash_prog);
+}
+
+static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ rmi4_data->button_0d_enabled);
+}
+
+static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned int input;
+ unsigned char ii;
+ unsigned char intr_enable;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+ struct synaptics_rmi4_device_info *rmi;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+
+ input = input > 0 ? 1 : 0;
+
+ if (rmi4_data->button_0d_enabled == input)
+ return count;
+
+ if (list_empty(&rmi->support_fn_list))
+ return -ENODEV;
+
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
+ ii = fhandler->intr_reg_num;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr + 1 + ii,
+ &intr_enable,
+ sizeof(intr_enable));
+ if (retval < 0)
+ return retval;
+
+ if (input == 1)
+ intr_enable |= fhandler->intr_mask;
+ else
+ intr_enable &= ~fhandler->intr_mask;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr + 1 + ii,
+ &intr_enable,
+ sizeof(intr_enable));
+ if (retval < 0)
+ return retval;
+ }
+ }
+
+ rmi4_data->button_0d_enabled = input;
+
+ return count;
+}
+
+ /**
+ * synaptics_rmi4_f11_abs_report()
+ *
+ * Called by synaptics_rmi4_report_touch() when valid Function $11
+ * finger data has been detected.
+ *
+ * This function reads the Function $11 data registers, determines the
+ * status of each finger supported by the Function, processes any
+ * necessary coordinate manipulation, reports the finger data to
+ * the input subsystem, and returns the number of fingers detected.
+ */
+static int synaptics_rmi4_f11_abs_report(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+ int retval;
+ unsigned char touch_count = 0; /* number of touch points */
+ unsigned char reg_index;
+ unsigned char finger;
+ unsigned char fingers_supported;
+ unsigned char num_of_finger_status_regs;
+ unsigned char finger_shift;
+ unsigned char finger_status;
+ unsigned char data_reg_blk_size;
+ unsigned char finger_status_reg[3];
+ unsigned char data[F11_STD_DATA_LEN];
+ unsigned short data_addr;
+ unsigned short data_offset;
+ int x;
+ int y;
+ int wx;
+ int wy;
+ int temp;
+
+ /*
+ * The number of finger status registers is determined by the
+ * maximum number of fingers supported - 2 bits per finger. So
+ * the number of finger status registers to read is:
+ * register_count = ceil(max_num_of_fingers / 4)
+ */
+ fingers_supported = fhandler->num_of_data_points;
+ num_of_finger_status_regs = (fingers_supported + 3) / 4;
+ data_addr = fhandler->full_addr.data_base;
+ data_reg_blk_size = fhandler->size_of_data_register_block;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ data_addr,
+ finger_status_reg,
+ num_of_finger_status_regs);
+ if (retval < 0)
+ return 0;
+
+ for (finger = 0; finger < fingers_supported; finger++) {
+ reg_index = finger / 4;
+ finger_shift = (finger % 4) * 2;
+ finger_status = (finger_status_reg[reg_index] >> finger_shift)
+ & MASK_2BIT;
+
+ /*
+ * Each 2-bit finger status field represents the following:
+ * 00 = finger not present
+ * 01 = finger present and data accurate
+ * 10 = finger present but data may be inaccurate
+ * 11 = reserved
+ */
+#ifdef TYPE_B_PROTOCOL
+ input_mt_slot(rmi4_data->input_dev, finger);
+ input_mt_report_slot_state(rmi4_data->input_dev,
+ MT_TOOL_FINGER, finger_status);
+#endif
+
+ if (finger_status) {
+ data_offset = data_addr +
+ num_of_finger_status_regs +
+ (finger * data_reg_blk_size);
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ data_offset,
+ data,
+ data_reg_blk_size);
+ if (retval < 0)
+ return 0;
+
+ x = (data[0] << 4) | (data[2] & MASK_4BIT);
+ y = (data[1] << 4) | ((data[2] >> 4) & MASK_4BIT);
+ wx = (data[3] & MASK_4BIT);
+ wy = (data[3] >> 4) & MASK_4BIT;
+
+ if (rmi4_data->hw_if->board_data->swap_axes) {
+ temp = x;
+ x = y;
+ y = temp;
+ temp = wx;
+ wx = wy;
+ wy = temp;
+ }
+
+ if (rmi4_data->hw_if->board_data->x_flip)
+ x = rmi4_data->sensor_max_x - x;
+ if (rmi4_data->hw_if->board_data->y_flip)
+ y = rmi4_data->sensor_max_y - y;
+
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOUCH, 1);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, 1);
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_POSITION_X, x);
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_POSITION_Y, y);
+#ifdef REPORT_2D_W
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_TOUCH_MAJOR, max(wx, wy));
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_TOUCH_MINOR, min(wx, wy));
+#endif
+#ifndef TYPE_B_PROTOCOL
+ input_mt_sync(rmi4_data->input_dev);
+#endif
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Finger %d:\n"
+ "status = 0x%02x\n"
+ "x = %d\n"
+ "y = %d\n"
+ "wx = %d\n"
+ "wy = %d\n",
+ __func__, finger,
+ finger_status,
+ x, y, wx, wy);
+
+ touch_count++;
+ }
+ }
+
+ if (touch_count == 0) {
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOUCH, 0);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, 0);
+#ifndef TYPE_B_PROTOCOL
+ input_mt_sync(rmi4_data->input_dev);
+#endif
+ }
+
+ input_sync(rmi4_data->input_dev);
+
+ return touch_count;
+}
+
+ /**
+ * synaptics_rmi4_f12_abs_report()
+ *
+ * Called by synaptics_rmi4_report_touch() when valid Function $12
+ * finger data has been detected.
+ *
+ * This function reads the Function $12 data registers, determines the
+ * status of each finger supported by the Function, processes any
+ * necessary coordinate manipulation, reports the finger data to
+ * the input subsystem, and returns the number of fingers detected.
+ */
+static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+ int retval;
+ unsigned char touch_count = 0; /* number of touch points */
+ unsigned char finger;
+ unsigned char fingers_to_process;
+ unsigned char finger_status;
+ unsigned char size_of_2d_data;
+ unsigned short data_addr;
+ int x;
+ int y;
+ int wx;
+ int wy;
+ int temp;
+ struct synaptics_rmi4_f12_extra_data *extra_data;
+ struct synaptics_rmi4_f12_finger_data *data;
+ struct synaptics_rmi4_f12_finger_data *finger_data;
+#ifdef F12_DATA_15_WORKAROUND
+ static unsigned char fingers_already_present;
+#endif
+
+ fingers_to_process = fhandler->num_of_data_points;
+ data_addr = fhandler->full_addr.data_base;
+ extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
+ size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
+
+
+ /* Determine the total number of fingers to process */
+ if (extra_data->data15_size) {
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ data_addr + extra_data->data15_offset,
+ extra_data->data15_data,
+ extra_data->data15_size);
+ if (retval < 0)
+ return 0;
+
+ /* Start checking from the highest bit */
+ temp = extra_data->data15_size - 1; /* Highest byte */
+ if ((temp >= 0) && (fingers_to_process > 0) &&
+ (temp < ((F12_FINGERS_TO_SUPPORT + 7) / 8))) {
+ finger = (fingers_to_process - 1) % 8; /* Highest bit */
+ do {
+ if (extra_data->data15_data[temp]
+ & (1 << finger))
+ break;
+
+ if (finger) {
+ finger--;
+ } else {
+ /* Move to the next lower byte */
+ temp--;
+ finger = 7;
+ }
+
+ fingers_to_process--;
+ } while (fingers_to_process && (temp >= 0));
+ }
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Number of fingers to process = %d\n",
+ __func__, fingers_to_process);
+ }
+
+#ifdef F12_DATA_15_WORKAROUND
+ fingers_to_process = max(fingers_to_process, fingers_already_present);
+#endif
+
+ if (!fingers_to_process) {
+ synaptics_rmi4_free_fingers(rmi4_data);
+ return 0;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ data_addr + extra_data->data1_offset,
+ (unsigned char *)fhandler->data,
+ fingers_to_process * size_of_2d_data);
+ if (retval < 0)
+ return 0;
+
+ data = (struct synaptics_rmi4_f12_finger_data *)fhandler->data;
+
+ for (finger = 0; finger < fingers_to_process; finger++) {
+ finger_data = data + finger;
+ finger_status = finger_data->object_type_and_status;
+
+ if (finger_status == F12_FINGER_STATUS) {
+#ifdef TYPE_B_PROTOCOL
+ input_mt_slot(rmi4_data->input_dev, finger);
+ input_mt_report_slot_state(rmi4_data->input_dev,
+ MT_TOOL_FINGER, 1);
+#endif
+
+#ifdef F12_DATA_15_WORKAROUND
+ fingers_already_present = finger + 1;
+#endif
+
+ x = (finger_data->x_msb << 8) | (finger_data->x_lsb);
+ y = (finger_data->y_msb << 8) | (finger_data->y_lsb);
+#ifdef REPORT_2D_W
+ wx = finger_data->wx;
+ wy = finger_data->wy;
+#endif
+
+ if (rmi4_data->hw_if->board_data->swap_axes) {
+ temp = x;
+ x = y;
+ y = temp;
+ temp = wx;
+ wx = wy;
+ wy = temp;
+ }
+
+ if (rmi4_data->hw_if->board_data->x_flip)
+ x = rmi4_data->sensor_max_x - x;
+ if (rmi4_data->hw_if->board_data->y_flip)
+ y = rmi4_data->sensor_max_y - y;
+
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOUCH, 1);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, 1);
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_POSITION_X, x);
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_POSITION_Y, y);
+#ifdef REPORT_2D_W
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_TOUCH_MAJOR, max(wx, wy));
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_TOUCH_MINOR, min(wx, wy));
+#endif
+#ifndef TYPE_B_PROTOCOL
+ input_mt_sync(rmi4_data->input_dev);
+#endif
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Finger %d:\n"
+ "status = 0x%02x\n"
+ "x = %d\n"
+ "y = %d\n"
+ "wx = %d\n"
+ "wy = %d\n",
+ __func__, finger,
+ finger_status,
+ x, y, wx, wy);
+
+ touch_count++;
+ } else {
+#ifdef TYPE_B_PROTOCOL
+ input_mt_slot(rmi4_data->input_dev, finger);
+ input_mt_report_slot_state(rmi4_data->input_dev,
+ MT_TOOL_FINGER, 0);
+#endif
+ }
+ }
+
+ if (touch_count == 0) {
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOUCH, 0);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, 0);
+#ifndef TYPE_B_PROTOCOL
+ input_mt_sync(rmi4_data->input_dev);
+#endif
+ }
+
+ input_sync(rmi4_data->input_dev);
+
+ return touch_count;
+}
+
+static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+ int retval;
+ unsigned char touch_count = 0;
+ unsigned char button;
+ unsigned char index;
+ unsigned char shift;
+ unsigned char status;
+ unsigned char *data;
+ unsigned short data_addr = fhandler->full_addr.data_base;
+ struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
+ static unsigned char do_once = 1;
+ static bool current_status[MAX_NUMBER_OF_BUTTONS];
+#ifdef NO_0D_WHILE_2D
+ static bool before_2d_status[MAX_NUMBER_OF_BUTTONS];
+ static bool while_2d_status[MAX_NUMBER_OF_BUTTONS];
+#endif
+
+ if (do_once) {
+ memset(current_status, 0, sizeof(current_status));
+#ifdef NO_0D_WHILE_2D
+ memset(before_2d_status, 0, sizeof(before_2d_status));
+ memset(while_2d_status, 0, sizeof(while_2d_status));
+#endif
+ do_once = 0;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ data_addr,
+ f1a->button_data_buffer,
+ f1a->button_bitmask_size);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read button data registers\n",
+ __func__);
+ return;
+ }
+
+ data = f1a->button_data_buffer;
+
+ for (button = 0; button < f1a->valid_button_count; button++) {
+ index = button / 8;
+ shift = button % 8;
+ status = ((data[index] >> shift) & MASK_1BIT);
+
+ if (current_status[button] == status)
+ continue;
+ else
+ current_status[button] = status;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Button %d (code %d) ->%d\n",
+ __func__, button,
+ f1a->button_map[button],
+ status);
+#ifdef NO_0D_WHILE_2D
+ if (rmi4_data->fingers_on_2d == false) {
+ if (status == 1) {
+ before_2d_status[button] = 1;
+ } else {
+ if (while_2d_status[button] == 1) {
+ while_2d_status[button] = 0;
+ continue;
+ } else {
+ before_2d_status[button] = 0;
+ }
+ }
+ touch_count++;
+ input_report_key(rmi4_data->input_dev,
+ f1a->button_map[button],
+ status);
+ } else {
+ if (before_2d_status[button] == 1) {
+ before_2d_status[button] = 0;
+ touch_count++;
+ input_report_key(rmi4_data->input_dev,
+ f1a->button_map[button],
+ status);
+ } else {
+ if (status == 1)
+ while_2d_status[button] = 1;
+ else
+ while_2d_status[button] = 0;
+ }
+ }
+#else
+ touch_count++;
+ input_report_key(rmi4_data->input_dev,
+ f1a->button_map[button],
+ status);
+#endif
+ }
+
+ if (touch_count)
+ input_sync(rmi4_data->input_dev);
+
+ return;
+}
+
+ /**
+ * synaptics_rmi4_report_touch()
+ *
+ * Called by synaptics_rmi4_sensor_report().
+ *
+ * This function calls the appropriate finger data reporting function
+ * based on the function handler it receives and returns the number of
+ * fingers detected.
+ */
+static void synaptics_rmi4_report_touch(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+ unsigned char touch_count_2d;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Function %02x reporting\n",
+ __func__, fhandler->fn_number);
+
+ switch (fhandler->fn_number) {
+ case SYNAPTICS_RMI4_F11:
+ touch_count_2d = synaptics_rmi4_f11_abs_report(rmi4_data,
+ fhandler);
+
+ if (touch_count_2d)
+ rmi4_data->fingers_on_2d = true;
+ else
+ rmi4_data->fingers_on_2d = false;
+ break;
+ case SYNAPTICS_RMI4_F12:
+ touch_count_2d = synaptics_rmi4_f12_abs_report(rmi4_data,
+ fhandler);
+
+ if (touch_count_2d)
+ rmi4_data->fingers_on_2d = true;
+ else
+ rmi4_data->fingers_on_2d = false;
+ break;
+ case SYNAPTICS_RMI4_F1A:
+ synaptics_rmi4_f1a_report(rmi4_data, fhandler);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+ /**
+ * synaptics_rmi4_sensor_report()
+ *
+ * Called by synaptics_rmi4_irq().
+ *
+ * This function determines the interrupt source(s) from the sensor
+ * and calls synaptics_rmi4_report_touch() with the appropriate
+ * function handler for each function with valid data inputs.
+ */
+static void synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ unsigned char data[MAX_INTR_REGISTERS + 1];
+ unsigned char *intr = &data[1];
+ struct synaptics_rmi4_f01_device_status status;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+ struct synaptics_rmi4_device_info *rmi;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ /*
+ * Get interrupt status information from F01 Data1 register to
+ * determine the source(s) that are flagging the interrupt.
+ */
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_data_base_addr,
+ data,
+ rmi4_data->num_of_intr_regs + 1);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read interrupt status\n",
+ __func__);
+ return;
+ }
+
+ status.data[0] = data[0];
+ if (status.unconfigured && !status.flash_prog) {
+ pr_notice("%s: spontaneous reset detected\n", __func__);
+ retval = synaptics_rmi4_reinit_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to reinit device\n",
+ __func__);
+ }
+ return;
+ }
+
+ /*
+ * Traverse the function handler list and service the source(s)
+ * of the interrupt accordingly.
+ */
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->num_of_data_sources) {
+ if (fhandler->intr_mask &
+ intr[fhandler->intr_reg_num]) {
+ synaptics_rmi4_report_touch(rmi4_data,
+ fhandler);
+ }
+ }
+ }
+ }
+
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link) {
+ if (!exp_fhandler->insert &&
+ !exp_fhandler->remove &&
+ (exp_fhandler->exp_fn->attn != NULL))
+ exp_fhandler->exp_fn->attn(rmi4_data, intr[0]);
+ }
+ }
+ mutex_unlock(&exp_data.mutex);
+
+ return;
+}
+
+ /**
+ * synaptics_rmi4_irq()
+ *
+ * Called by the kernel when an interrupt occurs (when the sensor
+ * asserts the attention irq).
+ *
+ * This function is the ISR thread and handles the acquisition
+ * and the reporting of finger data when the presence of fingers
+ * is detected.
+ */
+static irqreturn_t synaptics_rmi4_irq(int irq, void *data)
+{
+ struct synaptics_rmi4_data *rmi4_data = data;
+
+ if (IRQ_HANDLED == synaptics_filter_interrupt(data))
+ return IRQ_HANDLED;
+
+ synaptics_rmi4_sensor_report(rmi4_data);
+
+ return IRQ_HANDLED;
+}
+
+ /**
+ * synaptics_rmi4_irq_enable()
+ *
+ * Called by synaptics_rmi4_probe() and the power management functions
+ * in this driver and also exported to other expansion Function modules
+ * such as rmi_dev.
+ *
+ * This function handles the enabling and disabling of the attention
+ * irq including the setting up of the ISR thread.
+ */
+static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
+ bool enable)
+{
+ int retval = 0;
+ unsigned char intr_status[MAX_INTR_REGISTERS];
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ if (enable) {
+ if (rmi4_data->irq_enabled)
+ return retval;
+
+ /* Clear interrupts first */
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_data_base_addr + 1,
+ intr_status,
+ rmi4_data->num_of_intr_regs);
+ if (retval < 0)
+ return retval;
+
+ retval = request_threaded_irq(rmi4_data->irq, NULL,
+ synaptics_rmi4_irq, bdata->irq_flags,
+ PLATFORM_DRIVER_NAME, rmi4_data);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to create irq thread\n",
+ __func__);
+ return retval;
+ }
+
+ rmi4_data->irq_enabled = true;
+ } else {
+ if (rmi4_data->irq_enabled) {
+ disable_irq(rmi4_data->irq);
+ free_irq(rmi4_data->irq, rmi4_data);
+ rmi4_data->irq_enabled = false;
+ }
+ }
+
+ return retval;
+}
+
+static int synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
+ struct synaptics_rmi4_fn_desc *fd,
+ unsigned int intr_count)
+{
+ unsigned char ii;
+ unsigned char intr_offset;
+
+ fhandler->intr_reg_num = (intr_count + 7) / 8;
+ if (fhandler->intr_reg_num >= MAX_INTR_REGISTERS) {
+ fhandler->intr_reg_num = 0;
+ fhandler->num_of_data_sources = 0;
+ fhandler->intr_mask = 0;
+ return -EINVAL;
+ }
+ if (fhandler->intr_reg_num != 0)
+ fhandler->intr_reg_num -= 1;
+
+ /* Set an enable bit for each data source */
+ intr_offset = intr_count % 8;
+ fhandler->intr_mask = 0;
+ for (ii = intr_offset;
+ ii < ((fd->intr_src_count & MASK_3BIT) +
+ intr_offset);
+ ii++)
+ fhandler->intr_mask |= 1 << ii;
+
+ return 0;
+}
+
+static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler,
+ struct synaptics_rmi4_fn_desc *fd,
+ unsigned int intr_count)
+{
+ int retval;
+
+ fhandler->fn_number = fd->fn_number;
+ fhandler->num_of_data_sources = fd->intr_src_count;
+ fhandler->data = NULL;
+ fhandler->extra = NULL;
+
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
+
+
+ rmi4_data->f01_query_base_addr = fd->query_base_addr;
+ rmi4_data->f01_ctrl_base_addr = fd->ctrl_base_addr;
+ rmi4_data->f01_data_base_addr = fd->data_base_addr;
+ rmi4_data->f01_cmd_base_addr = fd->cmd_base_addr;
+
+ return 0;
+}
+
+ /**
+ * synaptics_rmi4_f11_set_coords()
+ *
+ * Set panel resolution for f11 to match display resolution.
+ *
+ */
+static int synaptics_rmi4_f11_set_coords(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+ int retval;
+ unsigned char control[F11_STD_CTRL_LEN];
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ if (!rmi4_data->update_coords) {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: No need to update panel resolution\n", __func__);
+ return 0;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.ctrl_base,
+ control,
+ sizeof(control));
+ if (retval < 0)
+ return retval;
+
+ /* Maximum x and y */
+ rmi4_data->sensor_max_x = ((control[6] & MASK_8BIT) << 0) |
+ ((control[7] & MASK_4BIT) << 8);
+ rmi4_data->sensor_max_y = ((control[8] & MASK_8BIT) << 0) |
+ ((control[9] & MASK_4BIT) << 8);
+
+ if (bdata->panel_maxx && bdata->panel_maxy &&
+ (rmi4_data->sensor_max_x != bdata->panel_maxx ||
+ rmi4_data->sensor_max_y != bdata->panel_maxy)) {
+ if (bdata->panel_maxx > SYNA_F11_MAX ||
+ bdata->panel_maxy > SYNA_F11_MAX) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Invalid panel resolution\n", __func__);
+ return -EINVAL;
+ }
+
+ rmi4_data->sensor_max_x = bdata->panel_maxx;
+ rmi4_data->sensor_max_y = bdata->panel_maxy;
+ control[6] = rmi4_data->sensor_max_x & MASK_8BIT;
+ control[7] = (rmi4_data->sensor_max_x >> 8) & MASK_4BIT;
+ control[8] = rmi4_data->sensor_max_y & MASK_8BIT;
+ control[9] = (rmi4_data->sensor_max_y >> 8) & MASK_4BIT;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fhandler->full_addr.ctrl_base,
+ control,
+ sizeof(control));
+ if (retval < 0)
+ return retval;
+ rmi4_data->update_coords = true;
+ } else {
+ rmi4_data->update_coords = false;
+ }
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Function %02x max x = %d max y = %d\n",
+ __func__, fhandler->fn_number,
+ rmi4_data->sensor_max_x,
+ rmi4_data->sensor_max_y);
+
+ rmi4_data->max_touch_width = MAX_F11_TOUCH_WIDTH;
+
+ return 0;
+}
+
+ /**
+ * synaptics_rmi4_f11_init()
+ *
+ * Called by synaptics_rmi4_query_device().
+ *
+ * This funtion parses information from the Function 11 registers
+ * and determines the number of fingers supported, x and y data ranges,
+ * offset to the associated interrupt status register, interrupt bit
+ * mask, and gathers finger data acquisition capabilities from the query
+ * registers.
+ */
+static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler,
+ struct synaptics_rmi4_fn_desc *fd,
+ unsigned int intr_count)
+{
+ int retval;
+ unsigned char abs_data_size;
+ unsigned char abs_data_blk_size;
+ unsigned char query[F11_STD_QUERY_LEN];
+
+ fhandler->fn_number = fd->fn_number;
+ fhandler->num_of_data_sources = fd->intr_src_count;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.query_base,
+ query,
+ sizeof(query));
+ if (retval < 0)
+ return retval;
+
+ /* Maximum number of fingers supported */
+ if ((query[1] & MASK_3BIT) <= 4)
+ fhandler->num_of_data_points = (query[1] & MASK_3BIT) + 1;
+ else if ((query[1] & MASK_3BIT) == 5)
+ fhandler->num_of_data_points = 10;
+
+ rmi4_data->num_of_fingers = fhandler->num_of_data_points;
+
+ retval = synaptics_rmi4_f11_set_coords(rmi4_data, fhandler);
+ if (retval < 0)
+ return retval;
+
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
+
+ abs_data_size = query[5] & MASK_2BIT;
+ abs_data_blk_size = 3 + (2 * (abs_data_size == 0 ? 1 : 0));
+ fhandler->size_of_data_register_block = abs_data_blk_size;
+ fhandler->data = NULL;
+ fhandler->extra = NULL;
+
+ return retval;
+}
+
+static int synaptics_rmi4_f12_set_enables(struct synaptics_rmi4_data *rmi4_data,
+ unsigned short ctrl28)
+{
+ int retval;
+ static unsigned short ctrl_28_address;
+
+ if (ctrl28)
+ ctrl_28_address = ctrl28;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ ctrl_28_address,
+ &rmi4_data->report_enable,
+ sizeof(rmi4_data->report_enable));
+ if (retval < 0)
+ return retval;
+
+ return retval;
+}
+
+ /**
+ * synaptics_rmi4_f12_set_coords()
+ *
+ * Set panel resolution for f12 to match display resolution.
+ *
+ */
+static int synaptics_rmi4_f12_set_coords(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+ struct synaptics_rmi4_f12_query_5 query_5;
+ struct synaptics_rmi4_f12_ctrl_8 ctrl_8;
+ unsigned char ctrl_8_offset;
+ int retval;
+
+ if (!rmi4_data->update_coords) {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: No need to update panel resolution\n", __func__);
+ return 0;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.query_base + 5,
+ query_5.data,
+ sizeof(query_5.data));
+ if (retval < 0)
+ return retval;
+
+ ctrl_8_offset = query_5.ctrl0_is_present +
+ query_5.ctrl1_is_present +
+ query_5.ctrl2_is_present +
+ query_5.ctrl3_is_present +
+ query_5.ctrl4_is_present +
+ query_5.ctrl5_is_present +
+ query_5.ctrl6_is_present +
+ query_5.ctrl7_is_present;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.ctrl_base + ctrl_8_offset,
+ ctrl_8.data,
+ sizeof(ctrl_8.data));
+ if (retval < 0)
+ return retval;
+
+ /* Maximum x and y */
+ rmi4_data->sensor_max_x =
+ ((unsigned short)ctrl_8.max_x_coord_lsb << 0) |
+ ((unsigned short)ctrl_8.max_x_coord_msb << 8);
+ rmi4_data->sensor_max_y =
+ ((unsigned short)ctrl_8.max_y_coord_lsb << 0) |
+ ((unsigned short)ctrl_8.max_y_coord_msb << 8);
+
+ if (bdata->panel_maxx && bdata->panel_maxy &&
+ (rmi4_data->sensor_max_x != bdata->panel_maxx ||
+ rmi4_data->sensor_max_y != bdata->panel_maxy)) {
+
+ if (bdata->panel_maxx > SYNA_F12_MAX ||
+ bdata->panel_maxy > SYNA_F12_MAX) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Invalid panel resolution\n", __func__);
+ retval = -EINVAL;
+ return retval;
+ }
+
+ rmi4_data->sensor_max_x = bdata->panel_maxx;
+ rmi4_data->sensor_max_y = bdata->panel_maxy;
+ ctrl_8.max_x_coord_lsb = rmi4_data->sensor_max_x & MASK_8BIT;
+ ctrl_8.max_x_coord_msb = (rmi4_data->sensor_max_x >> 8) &
+ MASK_4BIT;
+ ctrl_8.max_y_coord_lsb = rmi4_data->sensor_max_y & MASK_8BIT;
+ ctrl_8.max_y_coord_msb = (rmi4_data->sensor_max_y >> 8) &
+ MASK_4BIT;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fhandler->full_addr.ctrl_base + ctrl_8_offset,
+ ctrl_8.data,
+ sizeof(ctrl_8.data));
+ if (retval < 0)
+ return retval;
+ rmi4_data->update_coords = true;
+ } else {
+ rmi4_data->update_coords = false;
+ }
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Function %02x max x = %d max y = %d\n",
+ __func__, fhandler->fn_number,
+ rmi4_data->sensor_max_x,
+ rmi4_data->sensor_max_y);
+
+ rmi4_data->num_of_rx = ctrl_8.num_of_rx;
+ rmi4_data->num_of_tx = ctrl_8.num_of_tx;
+ rmi4_data->max_touch_width = max(rmi4_data->num_of_rx,
+ rmi4_data->num_of_tx);
+
+ return 0;
+}
+
+ /**
+ * synaptics_rmi4_f12_init()
+ *
+ * Called by synaptics_rmi4_query_device().
+ *
+ * This funtion parses information from the Function 12 registers and
+ * determines the number of fingers supported, offset to the data1
+ * register, x and y data ranges, offset to the associated interrupt
+ * status register, interrupt bit mask, and allocates memory resources
+ * for finger data acquisition.
+ */
+static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler,
+ struct synaptics_rmi4_fn_desc *fd,
+ unsigned int intr_count)
+{
+ int retval;
+ unsigned char size_of_2d_data;
+ unsigned char size_of_query8;
+ unsigned char ctrl_8_offset;
+ unsigned char ctrl_23_offset;
+ unsigned char ctrl_28_offset;
+ unsigned char num_of_fingers;
+ struct synaptics_rmi4_f12_extra_data *extra_data;
+ struct synaptics_rmi4_f12_query_5 query_5;
+ struct synaptics_rmi4_f12_query_8 query_8;
+ struct synaptics_rmi4_f12_ctrl_23 ctrl_23;
+
+ fhandler->fn_number = fd->fn_number;
+ fhandler->num_of_data_sources = fd->intr_src_count;
+ size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
+
+ fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL);
+ if (!fhandler->extra) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for function handler\n",
+ __func__);
+ return -ENOMEM;
+ }
+ extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.query_base + 5,
+ query_5.data,
+ sizeof(query_5.data));
+ if (retval < 0)
+ goto free_function_handler_mem;
+
+ ctrl_8_offset = query_5.ctrl0_is_present +
+ query_5.ctrl1_is_present +
+ query_5.ctrl2_is_present +
+ query_5.ctrl3_is_present +
+ query_5.ctrl4_is_present +
+ query_5.ctrl5_is_present +
+ query_5.ctrl6_is_present +
+ query_5.ctrl7_is_present;
+
+ ctrl_23_offset = ctrl_8_offset +
+ query_5.ctrl8_is_present +
+ query_5.ctrl9_is_present +
+ query_5.ctrl10_is_present +
+ query_5.ctrl11_is_present +
+ query_5.ctrl12_is_present +
+ query_5.ctrl13_is_present +
+ query_5.ctrl14_is_present +
+ query_5.ctrl15_is_present +
+ query_5.ctrl16_is_present +
+ query_5.ctrl17_is_present +
+ query_5.ctrl18_is_present +
+ query_5.ctrl19_is_present +
+ query_5.ctrl20_is_present +
+ query_5.ctrl21_is_present +
+ query_5.ctrl22_is_present;
+
+ ctrl_28_offset = ctrl_23_offset +
+ query_5.ctrl23_is_present +
+ query_5.ctrl24_is_present +
+ query_5.ctrl25_is_present +
+ query_5.ctrl26_is_present +
+ query_5.ctrl27_is_present;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.ctrl_base + ctrl_23_offset,
+ ctrl_23.data,
+ sizeof(ctrl_23.data));
+ if (retval < 0)
+ goto free_function_handler_mem;
+
+ /* Maximum number of fingers supported */
+ fhandler->num_of_data_points = min(ctrl_23.max_reported_objects,
+ (unsigned char)F12_FINGERS_TO_SUPPORT);
+
+ num_of_fingers = fhandler->num_of_data_points;
+ rmi4_data->num_of_fingers = num_of_fingers;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.query_base + 7,
+ &size_of_query8,
+ sizeof(size_of_query8));
+ if (retval < 0)
+ goto free_function_handler_mem;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.query_base + 8,
+ query_8.data,
+ size_of_query8);
+ if (retval < 0)
+ goto free_function_handler_mem;
+
+ /* Determine the presence of the Data0 register */
+ extra_data->data1_offset = query_8.data0_is_present;
+
+ if ((size_of_query8 >= 3) && (query_8.data15_is_present)) {
+ extra_data->data15_offset = query_8.data0_is_present +
+ query_8.data1_is_present +
+ query_8.data2_is_present +
+ query_8.data3_is_present +
+ query_8.data4_is_present +
+ query_8.data5_is_present +
+ query_8.data6_is_present +
+ query_8.data7_is_present +
+ query_8.data8_is_present +
+ query_8.data9_is_present +
+ query_8.data10_is_present +
+ query_8.data11_is_present +
+ query_8.data12_is_present +
+ query_8.data13_is_present +
+ query_8.data14_is_present;
+ extra_data->data15_size = (num_of_fingers + 7) / 8;
+ } else {
+ extra_data->data15_size = 0;
+ }
+
+ rmi4_data->report_enable = RPT_DEFAULT;
+#ifdef REPORT_2D_Z
+ rmi4_data->report_enable |= RPT_Z;
+#endif
+#ifdef REPORT_2D_W
+ rmi4_data->report_enable |= (RPT_WX | RPT_WY);
+#endif
+
+ retval = synaptics_rmi4_f12_set_enables(rmi4_data,
+ fhandler->full_addr.ctrl_base + ctrl_28_offset);
+ if (retval < 0)
+ goto free_function_handler_mem;
+
+
+ retval = synaptics_rmi4_f12_set_coords(rmi4_data, fhandler);
+ if (retval < 0)
+ goto free_function_handler_mem;
+
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
+
+ /* Allocate memory for finger data storage space */
+ fhandler->data_size = num_of_fingers * size_of_2d_data;
+ fhandler->data = kmalloc(fhandler->data_size, GFP_KERNEL);
+ if (!fhandler->data) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for function handler data\n",
+ __func__);
+ retval = -ENOMEM;
+ goto free_function_handler_mem;
+ }
+
+ return retval;
+
+free_function_handler_mem:
+ kfree(fhandler->extra);
+ return retval;
+}
+
+static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+ int retval;
+ struct synaptics_rmi4_f1a_handle *f1a;
+
+ f1a = kzalloc(sizeof(*f1a), GFP_KERNEL);
+ if (!f1a) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for function handle\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ fhandler->data = (void *)f1a;
+ fhandler->extra = NULL;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.query_base,
+ f1a->button_query.data,
+ sizeof(f1a->button_query.data));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read query registers\n",
+ __func__);
+ return retval;
+ }
+
+ f1a->max_count = f1a->button_query.max_button_count + 1;
+
+ f1a->button_control.txrx_map = kzalloc(f1a->max_count * 2, GFP_KERNEL);
+ if (!f1a->button_control.txrx_map) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for tx rx mapping\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ f1a->button_bitmask_size = (f1a->max_count + 7) / 8;
+
+ f1a->button_data_buffer = kcalloc(f1a->button_bitmask_size,
+ sizeof(*(f1a->button_data_buffer)), GFP_KERNEL);
+ if (!f1a->button_data_buffer) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for data buffer\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ f1a->button_map = kcalloc(f1a->max_count,
+ sizeof(*(f1a->button_map)), GFP_KERNEL);
+ if (!f1a->button_map) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for button map\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int synaptics_rmi4_f1a_button_map(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+ int retval;
+ unsigned char ii;
+ unsigned char mapping_offset = 0;
+ struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ mapping_offset = f1a->button_query.has_general_control +
+ f1a->button_query.has_interrupt_enable +
+ f1a->button_query.has_multibutton_select;
+
+ if (f1a->button_query.has_tx_rx_map) {
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fhandler->full_addr.ctrl_base + mapping_offset,
+ f1a->button_control.txrx_map,
+ sizeof(f1a->button_control.txrx_map));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read tx rx mapping\n",
+ __func__);
+ return retval;
+ }
+
+ rmi4_data->button_txrx_mapping = f1a->button_control.txrx_map;
+ }
+
+ if (!bdata->cap_button_map) {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: cap_button_map is NULL in board file\n",
+ __func__);
+ } else if (!bdata->cap_button_map->map) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Button map is missing in board file\n",
+ __func__);
+ } else {
+ if (bdata->cap_button_map->nbuttons != f1a->max_count) {
+ f1a->valid_button_count = min(f1a->max_count,
+ bdata->cap_button_map->nbuttons);
+ } else {
+ f1a->valid_button_count = f1a->max_count;
+ }
+
+ for (ii = 0; ii < f1a->valid_button_count; ii++)
+ f1a->button_map[ii] = bdata->cap_button_map->map[ii];
+ }
+
+ return 0;
+}
+
+static void synaptics_rmi4_f1a_kfree(struct synaptics_rmi4_fn *fhandler)
+{
+ struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
+
+ if (f1a) {
+ kfree(f1a->button_control.txrx_map);
+ kfree(f1a->button_data_buffer);
+ kfree(f1a->button_map);
+ kfree(f1a);
+ fhandler->data = NULL;
+ }
+
+ return;
+}
+
+static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler,
+ struct synaptics_rmi4_fn_desc *fd,
+ unsigned int intr_count)
+{
+ int retval;
+
+ fhandler->fn_number = fd->fn_number;
+ fhandler->num_of_data_sources = fd->intr_src_count;
+
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
+
+ retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler);
+ if (retval < 0)
+ goto error_exit;
+
+ retval = synaptics_rmi4_f1a_button_map(rmi4_data, fhandler);
+ if (retval < 0)
+ goto error_exit;
+
+ rmi4_data->button_0d_enabled = 1;
+
+ return 0;
+
+error_exit:
+ synaptics_rmi4_f1a_kfree(fhandler);
+
+ return retval;
+}
+
+static void synaptics_rmi4_empty_fn_list(struct synaptics_rmi4_data *rmi4_data)
+{
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_fn *fhandler_temp;
+ struct synaptics_rmi4_device_info *rmi;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry_safe(fhandler,
+ fhandler_temp,
+ &rmi->support_fn_list,
+ link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
+ synaptics_rmi4_f1a_kfree(fhandler);
+ } else {
+ kfree(fhandler->extra);
+ kfree(fhandler->data);
+ }
+ list_del(&fhandler->link);
+ kfree(fhandler);
+ }
+ }
+ INIT_LIST_HEAD(&rmi->support_fn_list);
+
+ return;
+}
+
+static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
+ bool *was_in_bl_mode)
+{
+ int retval;
+ int timeout = CHECK_STATUS_TIMEOUT_MS;
+ unsigned char command = 0x01;
+ unsigned char intr_status;
+ struct synaptics_rmi4_f01_device_status status;
+
+ /* Do a device reset first */
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ rmi4_data->f01_cmd_base_addr,
+ &command,
+ sizeof(command));
+ if (retval < 0)
+ return retval;
+
+ msleep(rmi4_data->hw_if->board_data->reset_delay_ms);
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_data_base_addr,
+ status.data,
+ sizeof(status.data));
+ if (retval < 0)
+ return retval;
+
+ while (status.status_code == STATUS_CRC_IN_PROGRESS) {
+ if (timeout > 0)
+ msleep(20);
+ else
+ return -1;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_data_base_addr,
+ status.data,
+ sizeof(status.data));
+ if (retval < 0)
+ return retval;
+
+ timeout -= 20;
+ }
+
+ if (timeout != CHECK_STATUS_TIMEOUT_MS)
+ *was_in_bl_mode = true;
+
+ if (status.flash_prog == 1) {
+ rmi4_data->flash_prog_mode = true;
+ pr_notice("%s: In flash prog mode, status = 0x%02x\n",
+ __func__,
+ status.status_code);
+ } else {
+ rmi4_data->flash_prog_mode = false;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_data_base_addr + 1,
+ &intr_status,
+ sizeof(intr_status));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read interrupt status\n",
+ __func__);
+ return retval;
+ }
+
+ return 0;
+}
+
+static void synaptics_rmi4_set_configured(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ unsigned char device_ctrl;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to set configured\n",
+ __func__);
+ return;
+ }
+
+ rmi4_data->no_sleep_setting = device_ctrl & NO_SLEEP_ON;
+ device_ctrl |= CONFIGURED;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to set configured\n",
+ __func__);
+ }
+
+ return;
+}
+
+static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler,
+ struct synaptics_rmi4_fn_desc *rmi_fd, int page_number)
+{
+ *fhandler = kmalloc(sizeof(**fhandler), GFP_KERNEL);
+ if (!(*fhandler))
+ return -ENOMEM;
+
+ (*fhandler)->full_addr.data_base =
+ (rmi_fd->data_base_addr |
+ (page_number << 8));
+ (*fhandler)->full_addr.ctrl_base =
+ (rmi_fd->ctrl_base_addr |
+ (page_number << 8));
+ (*fhandler)->full_addr.cmd_base =
+ (rmi_fd->cmd_base_addr |
+ (page_number << 8));
+ (*fhandler)->full_addr.query_base =
+ (rmi_fd->query_base_addr |
+ (page_number << 8));
+
+ return 0;
+}
+
+static int synaptics_rmi4_read_configid(struct synaptics_rmi4_data *rmi4_data,
+ unsigned char ctrl_base_addr)
+{
+ unsigned int device_config_id;
+
+ /*
+ * We may get an error while trying to read config id if it is
+ * not provisioned by vendor
+ */
+ if (synaptics_rmi4_reg_read(rmi4_data, ctrl_base_addr,
+ (unsigned char *)(&device_config_id),
+ sizeof(device_config_id)) < 0)
+ dev_err(rmi4_data->pdev->dev.parent, "Failed to read device config ID from CTP\n");
+
+ if (rmi4_data->hw_if->board_data->config_id)
+ dev_info(rmi4_data->pdev->dev.parent,
+ "CTP Config ID=%pI4\tDT Config ID=%pI4\n",
+ &device_config_id,
+ &rmi4_data->hw_if->board_data->config_id);
+ else
+ dev_info(rmi4_data->pdev->dev.parent,
+ "CTP Config ID=%pI4\n", &device_config_id);
+
+ return 0;
+}
+
+ /**
+ * synaptics_rmi4_query_device()
+ *
+ * Called by synaptics_rmi4_probe().
+ *
+ * This funtion scans the page description table, records the offsets
+ * to the register types of Function $01, sets up the function handlers
+ * for Function $11 and Function $12, determines the number of interrupt
+ * sources from the sensor, adds valid Functions with data inputs to the
+ * Function linked list, parses information from the query registers of
+ * Function $01, and enables the interrupt sources from the valid Functions
+ * with data inputs.
+ */
+static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ unsigned char ii;
+ unsigned char page_number;
+ unsigned char intr_count;
+ unsigned char f01_query[F01_STD_QUERY_LEN];
+ unsigned short pdt_entry_addr;
+ unsigned short intr_addr;
+ bool f01found;
+ bool was_in_bl_mode;
+ struct synaptics_rmi4_fn_desc rmi_fd;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_device_info *rmi;
+ unsigned char pkg_id[PACKAGE_ID_SIZE];
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+rescan_pdt:
+ f01found = false;
+ was_in_bl_mode = false;
+ intr_count = 0;
+ INIT_LIST_HEAD(&rmi->support_fn_list);
+
+ /* Scan the page description tables of the pages to service */
+ for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) {
+ for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END;
+ pdt_entry_addr -= PDT_ENTRY_SIZE) {
+ pdt_entry_addr |= (page_number << 8);
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ pdt_entry_addr,
+ (unsigned char *)&rmi_fd,
+ sizeof(rmi_fd));
+ if (retval < 0)
+ return retval;
+
+ pdt_entry_addr &= ~(MASK_8BIT << 8);
+
+ fhandler = NULL;
+
+ if (rmi_fd.fn_number == 0) {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Reached end of PDT\n",
+ __func__);
+ break;
+ }
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: F%02x found (page %d)\n",
+ __func__, rmi_fd.fn_number,
+ page_number);
+
+ switch (rmi_fd.fn_number) {
+ case SYNAPTICS_RMI4_F34:
+ /*
+ * Though function F34 is an interrupt source,
+ * but it is not a data source, hence do not
+ * add its handler to support_fn_list
+ */
+ synaptics_rmi4_read_configid(rmi4_data,
+ rmi_fd.ctrl_base_addr);
+ break;
+ case SYNAPTICS_RMI4_F01:
+ if (rmi_fd.intr_src_count == 0)
+ break;
+
+ f01found = true;
+
+ retval = synaptics_rmi4_alloc_fh(&fhandler,
+ &rmi_fd, page_number);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi_fd.fn_number);
+ return retval;
+ }
+
+ retval = synaptics_rmi4_f01_init(rmi4_data,
+ fhandler, &rmi_fd, intr_count);
+ if (retval < 0)
+ return retval;
+
+ retval = synaptics_rmi4_check_status(rmi4_data,
+ &was_in_bl_mode);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to check status\n",
+ __func__);
+ return retval;
+ }
+
+ if (was_in_bl_mode) {
+ kfree(fhandler);
+ fhandler = NULL;
+ goto rescan_pdt;
+ }
+
+ if (rmi4_data->flash_prog_mode)
+ goto flash_prog_mode;
+
+ break;
+ case SYNAPTICS_RMI4_F11:
+ if (rmi_fd.intr_src_count == 0)
+ break;
+
+ retval = synaptics_rmi4_alloc_fh(&fhandler,
+ &rmi_fd, page_number);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi_fd.fn_number);
+ return retval;
+ }
+
+ retval = synaptics_rmi4_f11_init(rmi4_data,
+ fhandler, &rmi_fd, intr_count);
+ if (retval < 0)
+ return retval;
+ break;
+ case SYNAPTICS_RMI4_F12:
+ if (rmi_fd.intr_src_count == 0)
+ break;
+
+ retval = synaptics_rmi4_alloc_fh(&fhandler,
+ &rmi_fd, page_number);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi_fd.fn_number);
+ return retval;
+ }
+
+ retval = synaptics_rmi4_f12_init(rmi4_data,
+ fhandler, &rmi_fd, intr_count);
+ if (retval < 0)
+ return retval;
+ break;
+ case SYNAPTICS_RMI4_F1A:
+ if (rmi_fd.intr_src_count == 0)
+ break;
+
+ retval = synaptics_rmi4_alloc_fh(&fhandler,
+ &rmi_fd, page_number);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi_fd.fn_number);
+ return retval;
+ }
+
+ retval = synaptics_rmi4_f1a_init(rmi4_data,
+ fhandler, &rmi_fd, intr_count);
+ if (retval < 0) {
+#ifdef IGNORE_FN_INIT_FAILURE
+ kfree(fhandler);
+ fhandler = NULL;
+#else
+ return retval;
+#endif
+ }
+ break;
+ }
+
+ /* Accumulate the interrupt count */
+ intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
+
+ if (fhandler && rmi_fd.intr_src_count) {
+ list_add_tail(&fhandler->link,
+ &rmi->support_fn_list);
+ }
+ }
+ }
+
+ if (!f01found) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to find F01\n",
+ __func__);
+ return -EINVAL;
+ }
+
+flash_prog_mode:
+ rmi4_data->num_of_intr_regs = (intr_count + 7) / 8;
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Number of interrupt registers = %d\n",
+ __func__, rmi4_data->num_of_intr_regs);
+ if (rmi4_data->num_of_intr_regs >= MAX_INTR_REGISTERS)
+ return -EINVAL;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_query_base_addr,
+ f01_query,
+ sizeof(f01_query));
+ if (retval < 0)
+ return retval;
+
+ /* RMI Version 4.0 currently supported */
+ rmi->version_major = 4;
+ rmi->version_minor = 0;
+
+ rmi->manufacturer_id = f01_query[0];
+ rmi->product_props = f01_query[1];
+ rmi->product_info[0] = f01_query[2] & MASK_7BIT;
+ rmi->product_info[1] = f01_query[3] & MASK_7BIT;
+ rmi->date_code[0] = f01_query[4] & MASK_5BIT;
+ rmi->date_code[1] = f01_query[5] & MASK_4BIT;
+ rmi->date_code[2] = f01_query[6] & MASK_5BIT;
+ rmi->tester_id = ((f01_query[7] & MASK_7BIT) << 8) |
+ (f01_query[8] & MASK_7BIT);
+ rmi->serial_number = ((f01_query[9] & MASK_7BIT) << 8) |
+ (f01_query[10] & MASK_7BIT);
+ memcpy(rmi->product_id_string, &f01_query[11], 10);
+
+ if (rmi->manufacturer_id != 1) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Non-Synaptics device found, manufacturer ID = %d\n",
+ __func__, rmi->manufacturer_id);
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_query_base_addr + F01_PACKAGE_ID_OFFSET,
+ pkg_id, sizeof(pkg_id));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read device package id (code %d)\n",
+ __func__, retval);
+ return retval;
+ }
+
+ rmi->package_id = (pkg_id[1] << 8) | pkg_id[0];
+ rmi->package_id_rev = (pkg_id[3] << 8) | pkg_id[2];
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET,
+ rmi->build_id,
+ sizeof(rmi->build_id));
+ if (retval < 0)
+ return retval;
+
+ rmi4_data->firmware_id = (unsigned int)rmi->build_id[0] +
+ (unsigned int)rmi->build_id[1] * 0x100 +
+ (unsigned int)rmi->build_id[2] * 0x10000;
+
+ memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask));
+
+ /*
+ * Map out the interrupt bit masks for the interrupt sources
+ * from the registered function handlers.
+ */
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->num_of_data_sources) {
+ rmi4_data->intr_mask[fhandler->intr_reg_num] |=
+ fhandler->intr_mask;
+ }
+ }
+ }
+
+ /* Enable the interrupt sources */
+ for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) {
+ if (rmi4_data->intr_mask[ii] != 0x00) {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Interrupt enable mask %d = 0x%02x\n",
+ __func__, ii, rmi4_data->intr_mask[ii]);
+ intr_addr = rmi4_data->f01_ctrl_base_addr + 1 + ii;
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ intr_addr,
+ &(rmi4_data->intr_mask[ii]),
+ sizeof(rmi4_data->intr_mask[ii]));
+ if (retval < 0)
+ return retval;
+ }
+ }
+
+ synaptics_rmi4_set_configured(rmi4_data);
+
+ return 0;
+}
+
+static void synaptics_rmi4_set_params(struct synaptics_rmi4_data *rmi4_data)
+{
+ unsigned char ii;
+ struct synaptics_rmi4_f1a_handle *f1a;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_device_info *rmi;
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ if (bdata->disp_maxx && bdata->disp_maxy) {
+ input_set_abs_params(rmi4_data->input_dev, ABS_MT_POSITION_X,
+ 0, bdata->disp_maxx, 0, 0);
+ input_set_abs_params(rmi4_data->input_dev, ABS_MT_POSITION_Y,
+ 0, bdata->disp_maxy, 0, 0);
+ } else {
+ input_set_abs_params(rmi4_data->input_dev, ABS_MT_POSITION_X,
+ 0, rmi4_data->sensor_max_x, 0, 0);
+ input_set_abs_params(rmi4_data->input_dev, ABS_MT_POSITION_Y,
+ 0, rmi4_data->sensor_max_y, 0, 0);
+ }
+
+#ifdef REPORT_2D_W
+ input_set_abs_params(rmi4_data->input_dev,
+ ABS_MT_TOUCH_MAJOR, 0,
+ rmi4_data->max_touch_width, 0, 0);
+ input_set_abs_params(rmi4_data->input_dev,
+ ABS_MT_TOUCH_MINOR, 0,
+ rmi4_data->max_touch_width, 0, 0);
+#endif
+
+#ifdef TYPE_B_PROTOCOL
+ input_mt_init_slots(rmi4_data->input_dev,
+ rmi4_data->num_of_fingers, 0);
+#endif
+
+ f1a = NULL;
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
+ f1a = fhandler->data;
+ }
+ }
+
+ if (f1a) {
+ for (ii = 0; ii < f1a->valid_button_count; ii++) {
+ set_bit(f1a->button_map[ii],
+ rmi4_data->input_dev->keybit);
+ input_set_capability(rmi4_data->input_dev,
+ EV_KEY, f1a->button_map[ii]);
+ }
+ }
+
+ return;
+}
+
+static int synaptics_dsx_virtual_keys_init(struct device *dev,
+ struct synaptics_dsx_board_data *rmi4_pdata)
+{
+ int width, height, center_x, center_y;
+ int x1 = 0, x2 = 0, i, c = 0, rc = 0, border;
+
+ vkey_buf = devm_kzalloc(dev, MAX_BUF_SIZE, GFP_KERNEL);
+ if (!vkey_buf) {
+ dev_err(dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ border = (rmi4_pdata->panel_maxx - rmi4_pdata->disp_maxx) * 2;
+ width = ((rmi4_pdata->disp_maxx -
+ (border * (rmi4_pdata->virtual_key_map->nkeys - 1)))
+ / rmi4_pdata->virtual_key_map->nkeys);
+ height = (rmi4_pdata->panel_maxy - rmi4_pdata->disp_maxy);
+ center_y = rmi4_pdata->disp_maxy + (height / 2);
+ height = height * HEIGHT_SCALE_NUM / HEIGHT_SCALE_DENOM;
+
+ x2 -= border * BORDER_ADJUST_NUM / BORDER_ADJUST_DENOM;
+
+ for (i = 0; i < rmi4_pdata->virtual_key_map->nkeys; i++) {
+ x1 = x2 + border;
+ x2 = x2 + border + width;
+ center_x = x1 + (x2 - x1) / 2;
+ c += snprintf(vkey_buf + c, MAX_BUF_SIZE - c,
+ "%s:%d:%d:%d:%d:%d\n", VKEY_VER_CODE,
+ rmi4_pdata->virtual_key_map->map[i],
+ center_x, center_y, width, height);
+ }
+
+ vkey_buf[c] = '\0';
+
+ vkey_kobj = kobject_create_and_add("board_properties", NULL);
+ if (!vkey_kobj) {
+ dev_err(dev, "unable to create kobject\n");
+ return -ENOMEM;
+ }
+
+ rc = sysfs_create_group(vkey_kobj, &vkey_grp);
+ if (rc) {
+ dev_err(dev, "failed to create attributes\n");
+ kobject_put(vkey_kobj);
+ }
+
+ return rc;
+}
+
+static int synaptics_dsx_get_virtual_keys(struct device *dev,
+ struct property *prop, char *name,
+ struct synaptics_dsx_board_data *rmi4_pdata,
+ struct device_node *np)
+{
+ u32 num_keys;
+ int rc;
+
+ num_keys = prop->length / sizeof(u32);
+
+ rmi4_pdata->virtual_key_map = devm_kzalloc(dev,
+ sizeof(*rmi4_pdata->virtual_key_map),
+ GFP_KERNEL);
+ if (!rmi4_pdata->virtual_key_map)
+ return -ENOMEM;
+
+ rmi4_pdata->virtual_key_map->map = devm_kzalloc(dev,
+ sizeof(*rmi4_pdata->virtual_key_map->map) *
+ num_keys, GFP_KERNEL);
+ if (!rmi4_pdata->virtual_key_map->map)
+ return -ENOMEM;
+
+ rc = of_property_read_u32_array(np, name,
+ rmi4_pdata->virtual_key_map->map,
+ num_keys);
+ if (rc) {
+ dev_err(dev, "Failed to read key codes\n");
+ return -EINVAL;
+ }
+ rmi4_pdata->virtual_key_map->nkeys = num_keys;
+
+ return 0;
+}
+
+static int synaptics_dsx_get_button_map(struct device *dev,
+ struct property *prop, char *name,
+ struct synaptics_dsx_board_data *rmi4_pdata,
+ struct device_node *np)
+{
+ int rc, i;
+ u32 num_buttons;
+ u32 button_map[MAX_NUMBER_OF_BUTTONS];
+
+ num_buttons = prop->length / sizeof(u32);
+
+ rmi4_pdata->cap_button_map = devm_kzalloc(dev,
+ sizeof(*rmi4_pdata->cap_button_map),
+ GFP_KERNEL);
+ if (!rmi4_pdata->cap_button_map)
+ return -ENOMEM;
+
+ rmi4_pdata->cap_button_map->map = devm_kzalloc(dev,
+ sizeof(*rmi4_pdata->cap_button_map->map) *
+ num_buttons, GFP_KERNEL);
+ if (!rmi4_pdata->cap_button_map->map)
+ return -ENOMEM;
+
+ if (num_buttons <= MAX_NUMBER_OF_BUTTONS) {
+ rc = of_property_read_u32_array(np,
+ name, button_map, num_buttons);
+ if (rc) {
+ dev_err(dev, "Unable to read key codes\n");
+ return rc;
+ }
+ for (i = 0; i < num_buttons; i++)
+ rmi4_pdata->cap_button_map->map[i] =
+ button_map[i];
+ rmi4_pdata->cap_button_map->nbuttons = num_buttons;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int synaptics_rmi4_parse_dt_children(struct device *dev,
+ struct synaptics_dsx_board_data *rmi4_pdata,
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ struct synaptics_rmi4_device_info *rmi = &rmi4_data->rmi4_mod_info;
+ struct device_node *node = dev->of_node, *child = NULL;
+ int rc = 0;
+ struct synaptics_rmi4_fn *fhandler = NULL;
+ struct property *prop;
+
+ for_each_child_of_node(node, child) {
+ rc = of_property_read_u32(child, "synaptics,package-id",
+ &rmi4_pdata->package_id);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read package_id\n");
+ return rc;
+ } else if (rc == -EINVAL) {
+ rmi4_pdata->package_id = 0x00;
+ }
+
+ if (rmi4_pdata->package_id) {
+ if (rmi4_pdata->package_id != rmi->package_id) {
+ dev_err(dev,
+ "%s: Synaptics package id don't match %d %d\n",
+ __func__,
+ rmi4_pdata->package_id, rmi->package_id);
+ /*
+ * Iterate over next child if package
+ * id does not match
+ */
+ continue;
+ } else if (of_property_read_bool(child,
+ "synaptics,bypass-sensor-coords-check") &&
+ of_find_property(child,
+ "synaptics,panel-coords", NULL)) {
+ /*
+ * Some unprogrammed panels from touch vendor
+ * and wrongly programmed panels from factory
+ * may return incorrect sensor coordinate range
+ * when their query registers are read, but
+ * they normally work fine in field. In such
+ * a scenario, driver can bypass the comparison
+ * of coordinate range read from sensor and read
+ * from DT and continue normal operation.
+ */
+ synaptics_dsx_get_dt_coords(dev,
+ "synaptics,panel-coords",
+ rmi4_pdata, child);
+ dev_info(dev,
+ "%s Synaptics package id matches %d %d,"
+ "but bypassing the comparison of sensor"
+ "coordinates.\n", __func__,
+ rmi4_pdata->package_id,
+ rmi->package_id);
+ dev_info(dev, "Pmax_x Pmax_y = %d:%d\n",
+ rmi4_pdata->panel_maxx,
+ rmi4_pdata->panel_maxy);
+ dev_info(dev, "Smax_x Smax_y = %d:%d\n",
+ rmi4_data->sensor_max_x,
+ rmi4_data->sensor_max_y);
+ } else {
+ /*
+ * If package id read from DT matches the
+ * package id value read from touch controller,
+ * also check if sensor dimensions read from DT
+ * match those read from controller, before
+ * moving further. For this first check if touch
+ * panel coordinates are defined in DT or not.
+ */
+ if (of_find_property(child,
+ "synaptics,panel-coords", NULL)) {
+ synaptics_dsx_get_dt_coords(dev,
+ "synaptics,panel-coords",
+ rmi4_pdata, child);
+ dev_info(dev, "Pmax_x Pmax_y = %d:%d\n",
+ rmi4_pdata->panel_maxx,
+ rmi4_pdata->panel_maxy);
+ dev_info(dev, "Smax_x Smax_y = %d:%d\n",
+ rmi4_data->sensor_max_x,
+ rmi4_data->sensor_max_y);
+ if ((rmi4_pdata->panel_maxx !=
+ rmi4_data->sensor_max_x) ||
+ (rmi4_pdata->panel_maxy !=
+ rmi4_data->sensor_max_y))
+ continue;
+ } else {
+ dev_info(dev, "Smax_x Smax_y = %d:%d\n",
+ rmi4_data->sensor_max_x,
+ rmi4_data->sensor_max_y);
+ }
+ }
+ }
+
+ rc = synaptics_dsx_get_dt_coords(dev,
+ "synaptics,display-coords", rmi4_pdata, child);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ prop = of_find_property(child, "synaptics,button-map", NULL);
+ if (prop) {
+ rc = synaptics_dsx_get_button_map(dev, prop,
+ "synaptics,button-map", rmi4_pdata, child);
+ if (rc < 0) {
+ dev_err(dev, "Unable to read button map\n");
+ return rc;
+ }
+
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler,
+ &rmi->support_fn_list, link) {
+ if (fhandler->fn_number ==
+ SYNAPTICS_RMI4_F1A)
+ break;
+ }
+ }
+
+ if (fhandler && fhandler->fn_number ==
+ SYNAPTICS_RMI4_F1A) {
+ rc = synaptics_rmi4_f1a_button_map(rmi4_data,
+ fhandler);
+ if (rc < 0) {
+ dev_err(dev,
+ "Fail to register F1A %d\n",
+ rc);
+ return rc;
+ }
+ }
+ }
+
+ prop = of_find_property(child, "synaptics,key-codes", NULL);
+ if (prop) {
+ rc = synaptics_dsx_get_virtual_keys(dev, prop,
+ "synaptics,key-codes", rmi4_pdata, child);
+ if (!rc) {
+ rc = synaptics_dsx_virtual_keys_init(dev,
+ rmi4_pdata);
+ if (!rc)
+ rmi4_data->support_vkeys = true;
+
+ } else {
+ dev_err(dev,
+ "Unable to read virtual key codes\n");
+ return rc;
+ }
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+static int synaptics_rmi4_set_input_dev(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ int temp;
+
+ rmi4_data->input_dev = input_allocate_device();
+ if (rmi4_data->input_dev == NULL) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to allocate input device\n",
+ __func__);
+ retval = -ENOMEM;
+ goto err_input_device;
+ }
+
+ retval = synaptics_rmi4_query_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to query device\n",
+ __func__);
+ goto err_query_device;
+ }
+
+ if (rmi4_data->hw_if->board_data->detect_device) {
+ retval = synaptics_rmi4_parse_dt_children(
+ rmi4_data->pdev->dev.parent,
+ rmi4_data->hw_if->board_data,
+ rmi4_data);
+ if (retval < 0)
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to parse device tree property\n",
+ __func__);
+ }
+
+ rmi4_data->input_dev->name = PLATFORM_DRIVER_NAME;
+ rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
+ rmi4_data->input_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT;
+ rmi4_data->input_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION;
+ rmi4_data->input_dev->dev.parent = rmi4_data->pdev->dev.parent;
+ input_set_drvdata(rmi4_data->input_dev, rmi4_data);
+
+ set_bit(EV_SYN, rmi4_data->input_dev->evbit);
+ set_bit(EV_KEY, rmi4_data->input_dev->evbit);
+ set_bit(EV_ABS, rmi4_data->input_dev->evbit);
+ set_bit(BTN_TOUCH, rmi4_data->input_dev->keybit);
+ set_bit(BTN_TOOL_FINGER, rmi4_data->input_dev->keybit);
+#ifdef INPUT_PROP_DIRECT
+ set_bit(INPUT_PROP_DIRECT, rmi4_data->input_dev->propbit);
+#endif
+
+ if (rmi4_data->hw_if->board_data->swap_axes) {
+ temp = rmi4_data->sensor_max_x;
+ rmi4_data->sensor_max_x = rmi4_data->sensor_max_y;
+ rmi4_data->sensor_max_y = temp;
+ }
+
+ synaptics_rmi4_set_params(rmi4_data);
+
+ retval = input_register_device(rmi4_data->input_dev);
+ if (retval) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to register input device\n",
+ __func__);
+ goto err_register_input;
+ }
+
+ return 0;
+
+err_register_input:
+ if (rmi4_data->support_vkeys) {
+ sysfs_remove_group(vkey_kobj, &vkey_grp);
+ kobject_put(vkey_kobj);
+ }
+err_query_device:
+ synaptics_rmi4_empty_fn_list(rmi4_data);
+ input_free_device(rmi4_data->input_dev);
+
+err_input_device:
+ return retval;
+}
+
+static int synaptics_rmi4_set_gpio(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ int power_on;
+ int reset_on;
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ power_on = bdata->power_on_state;
+ reset_on = bdata->reset_on_state;
+
+ retval = bdata->gpio_config(
+ bdata->irq_gpio,
+ true, 0, 0);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to configure attention GPIO\n",
+ __func__);
+ goto err_gpio_irq;
+ }
+
+ if (bdata->power_gpio >= 0) {
+ retval = bdata->gpio_config(
+ bdata->power_gpio,
+ true, 1, !power_on);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to configure power GPIO\n",
+ __func__);
+ goto err_gpio_power;
+ }
+ }
+
+ if (bdata->reset_gpio >= 0) {
+ retval = bdata->gpio_config(
+ bdata->reset_gpio,
+ true, 1, !reset_on);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to configure reset GPIO\n",
+ __func__);
+ goto err_gpio_reset;
+ }
+ }
+
+ if (bdata->power_gpio >= 0) {
+ gpio_set_value(bdata->power_gpio, power_on);
+ msleep(bdata->power_delay_ms);
+ }
+
+ if (bdata->reset_gpio >= 0) {
+ gpio_set_value(bdata->reset_gpio, reset_on);
+ msleep(bdata->reset_active_ms);
+ gpio_set_value(bdata->reset_gpio, !reset_on);
+ msleep(bdata->reset_delay_ms);
+ }
+
+ return 0;
+
+err_gpio_reset:
+ if (bdata->power_gpio >= 0) {
+ bdata->gpio_config(
+ bdata->power_gpio,
+ false, 0, 0);
+ }
+
+err_gpio_power:
+ bdata->gpio_config(
+ bdata->irq_gpio,
+ false, 0, 0);
+
+err_gpio_irq:
+ return retval;
+}
+
+static int synaptics_dsx_pinctrl_init(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+
+ /* Get pinctrl if target uses pinctrl */
+ rmi4_data->ts_pinctrl = devm_pinctrl_get((rmi4_data->pdev->dev.parent));
+ if (IS_ERR_OR_NULL(rmi4_data->ts_pinctrl)) {
+ retval = PTR_ERR(rmi4_data->ts_pinctrl);
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "Target does not use pinctrl %d\n", retval);
+ goto err_pinctrl_get;
+ }
+
+ rmi4_data->pinctrl_state_active
+ = pinctrl_lookup_state(rmi4_data->ts_pinctrl, "pmx_ts_active");
+ if (IS_ERR_OR_NULL(rmi4_data->pinctrl_state_active)) {
+ retval = PTR_ERR(rmi4_data->pinctrl_state_active);
+ dev_err(rmi4_data->pdev->dev.parent,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_ACTIVE, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ rmi4_data->pinctrl_state_suspend
+ = pinctrl_lookup_state(rmi4_data->ts_pinctrl, "pmx_ts_suspend");
+ if (IS_ERR_OR_NULL(rmi4_data->pinctrl_state_suspend)) {
+ retval = PTR_ERR(rmi4_data->pinctrl_state_suspend);
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_SUSPEND, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ rmi4_data->pinctrl_state_release
+ = pinctrl_lookup_state(rmi4_data->ts_pinctrl, "pmx_ts_release");
+ if (IS_ERR_OR_NULL(rmi4_data->pinctrl_state_release)) {
+ retval = PTR_ERR(rmi4_data->pinctrl_state_release);
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "Can not lookup %s pinstate %d\n",
+ PINCTRL_STATE_RELEASE, retval);
+ }
+
+ return 0;
+
+err_pinctrl_lookup:
+ devm_pinctrl_put(rmi4_data->ts_pinctrl);
+err_pinctrl_get:
+ rmi4_data->ts_pinctrl = NULL;
+ return retval;
+}
+
+static int synaptics_dsx_gpio_configure(struct synaptics_rmi4_data *rmi4_data,
+ bool on)
+{
+ int retval = 0;
+ struct synaptics_rmi4_device_info *rmi;
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ if (on) {
+ if (gpio_is_valid(bdata->irq_gpio)) {
+ /* configure touchscreen irq gpio */
+ retval = gpio_request(bdata->irq_gpio,
+ "rmi4_irq_gpio");
+ if (retval) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "unable to request gpio [%d]\n",
+ bdata->irq_gpio);
+ goto err_irq_gpio_req;
+ }
+ retval = gpio_direction_input(bdata->irq_gpio);
+ if (retval) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "unable to set dir for gpio[%d]\n",
+ bdata->irq_gpio);
+ goto err_irq_gpio_dir;
+ }
+ } else {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "irq gpio not provided\n");
+ goto err_irq_gpio_req;
+ }
+
+ if (gpio_is_valid(bdata->reset_gpio)) {
+ /* configure touchscreen reset out gpio */
+ retval = gpio_request(bdata->reset_gpio,
+ "rmi4_reset_gpio");
+ if (retval) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "unable to request gpio [%d]\n",
+ bdata->reset_gpio);
+ goto err_irq_gpio_dir;
+ }
+
+ retval = gpio_direction_output(bdata->reset_gpio, 1);
+ if (retval) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "unable to set dir for gpio [%d]\n",
+ bdata->reset_gpio);
+ goto err_reset_gpio_dir;
+ }
+
+ gpio_set_value(bdata->reset_gpio, 1);
+ msleep(bdata->reset_delay_ms);
+ }
+
+ return 0;
+ } else {
+ if (bdata->disable_gpios) {
+ if (gpio_is_valid(bdata->irq_gpio))
+ gpio_free(bdata->irq_gpio);
+ if (gpio_is_valid(bdata->reset_gpio)) {
+ /*
+ * This is intended to save leakage current
+ * only. Even if the call(gpio_direction_input)
+ * fails, only leakage current will be more but
+ * functionality will not be affected.
+ */
+ if (rmi->package_id ==
+ SYNA_S332U_PACKAGE_ID &&
+ rmi->package_id_rev ==
+ SYNA_S332U_PACKAGE_ID_REV) {
+ gpio_set_value(bdata->
+ reset_gpio,
+ 0);
+ } else {
+ retval = gpio_direction_input(
+ bdata->reset_gpio);
+ if (retval) {
+ dev_err(rmi4_data->pdev->
+ dev.parent,
+ "unable to set direction for gpio [%d]\n",
+ bdata->irq_gpio);
+ }
+ }
+ gpio_free(bdata->reset_gpio);
+ }
+ }
+
+ return 0;
+ }
+
+err_reset_gpio_dir:
+ if (gpio_is_valid(bdata->reset_gpio))
+ gpio_free(bdata->reset_gpio);
+err_irq_gpio_dir:
+ if (gpio_is_valid(bdata->irq_gpio))
+ gpio_free(bdata->irq_gpio);
+err_irq_gpio_req:
+ return retval;
+}
+
+static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data)
+{
+ unsigned char ii;
+
+#ifdef TYPE_B_PROTOCOL
+ for (ii = 0; ii < rmi4_data->num_of_fingers; ii++) {
+ input_mt_slot(rmi4_data->input_dev, ii);
+ input_mt_report_slot_state(rmi4_data->input_dev,
+ MT_TOOL_FINGER, 0);
+ }
+#endif
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOUCH, 0);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, 0);
+#ifndef TYPE_B_PROTOCOL
+ input_mt_sync(rmi4_data->input_dev);
+#endif
+ input_sync(rmi4_data->input_dev);
+
+ rmi4_data->fingers_on_2d = false;
+
+ return 0;
+}
+
+static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ unsigned char ii;
+ unsigned short intr_addr;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+ struct synaptics_rmi4_device_info *rmi;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ mutex_lock(&(rmi4_data->rmi4_reset_mutex));
+
+ synaptics_rmi4_free_fingers(rmi4_data);
+
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F12) {
+ synaptics_rmi4_f12_set_coords(rmi4_data,
+ fhandler);
+ synaptics_rmi4_f12_set_enables(rmi4_data, 0);
+ break;
+ } else if (fhandler->fn_number == SYNAPTICS_RMI4_F11) {
+ synaptics_rmi4_f11_set_coords(rmi4_data,
+ fhandler);
+ break;
+ }
+
+ }
+ }
+
+ for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) {
+ if (rmi4_data->intr_mask[ii] != 0x00) {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Interrupt enable mask %d = 0x%02x\n",
+ __func__, ii, rmi4_data->intr_mask[ii]);
+ intr_addr = rmi4_data->f01_ctrl_base_addr + 1 + ii;
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ intr_addr,
+ &(rmi4_data->intr_mask[ii]),
+ sizeof(rmi4_data->intr_mask[ii]));
+ if (retval < 0)
+ goto exit;
+ }
+ }
+
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link)
+ if (exp_fhandler->exp_fn->reinit != NULL)
+ exp_fhandler->exp_fn->reinit(rmi4_data);
+ }
+ mutex_unlock(&exp_data.mutex);
+
+ synaptics_rmi4_set_configured(rmi4_data);
+
+ retval = 0;
+
+exit:
+ mutex_unlock(&(rmi4_data->rmi4_reset_mutex));
+ return retval;
+}
+
+static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ int temp;
+ unsigned char command = 0x01;
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+
+ mutex_lock(&(rmi4_data->rmi4_reset_mutex));
+
+ rmi4_data->touch_stopped = true;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ rmi4_data->f01_cmd_base_addr,
+ &command,
+ sizeof(command));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to issue reset command, error = %d\n",
+ __func__, retval);
+ mutex_unlock(&(rmi4_data->rmi4_reset_mutex));
+ return retval;
+ }
+
+ msleep(rmi4_data->hw_if->board_data->reset_delay_ms);
+
+ synaptics_rmi4_free_fingers(rmi4_data);
+
+ synaptics_rmi4_empty_fn_list(rmi4_data);
+
+ retval = synaptics_rmi4_query_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to query device\n",
+ __func__);
+ mutex_unlock(&(rmi4_data->rmi4_reset_mutex));
+ return retval;
+ }
+
+ if (rmi4_data->hw_if->board_data->swap_axes) {
+ temp = rmi4_data->sensor_max_x;
+ rmi4_data->sensor_max_x = rmi4_data->sensor_max_y;
+ rmi4_data->sensor_max_y = temp;
+ }
+
+ synaptics_rmi4_set_params(rmi4_data);
+
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link)
+ if (exp_fhandler->exp_fn->reset != NULL)
+ exp_fhandler->exp_fn->reset(rmi4_data);
+ }
+ mutex_unlock(&exp_data.mutex);
+
+ rmi4_data->touch_stopped = false;
+
+ mutex_unlock(&(rmi4_data->rmi4_reset_mutex));
+
+ return 0;
+}
+
+/**
+* synaptics_rmi4_exp_fn_work()
+*
+* Called by the kernel at the scheduled time.
+*
+* This function is a work thread that checks for the insertion and
+* removal of other expansion Function modules such as rmi_dev and calls
+* their initialization and removal callback functions accordingly.
+*/
+static void synaptics_rmi4_exp_fn_work(struct work_struct *work)
+{
+ int retval;
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler_temp;
+ struct synaptics_rmi4_data *rmi4_data = exp_data.rmi4_data;
+
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry_safe(exp_fhandler,
+ exp_fhandler_temp,
+ &exp_data.list,
+ link) {
+ if ((exp_fhandler->exp_fn->init != NULL) &&
+ exp_fhandler->insert) {
+ retval = exp_fhandler->exp_fn->init(rmi4_data);
+ if (retval < 0) {
+ list_del(&exp_fhandler->link);
+ kfree(exp_fhandler);
+ } else {
+ exp_fhandler->insert = false;
+ }
+ } else if ((exp_fhandler->exp_fn->remove != NULL) &&
+ exp_fhandler->remove) {
+ exp_fhandler->exp_fn->remove(rmi4_data);
+ list_del(&exp_fhandler->link);
+ kfree(exp_fhandler);
+ }
+ }
+ }
+ mutex_unlock(&exp_data.mutex);
+
+ return;
+}
+
+/**
+* synaptics_rmi4_dsx_new_function()
+*
+* Called by other expansion Function modules in their module init and
+* module exit functions.
+*
+* This function is used by other expansion Function modules such as
+* rmi_dev to register themselves with the driver by providing their
+* initialization and removal callback function pointers so that they
+* can be inserted or removed dynamically at module init and exit times,
+* respectively.
+*/
+void synaptics_rmi4_dsx_new_function(struct synaptics_rmi4_exp_fn *exp_fn,
+ bool insert)
+{
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+
+ if (!exp_data.initialized) {
+ mutex_init(&exp_data.mutex);
+ INIT_LIST_HEAD(&exp_data.list);
+ exp_data.initialized = true;
+ }
+
+ mutex_lock(&exp_data.mutex);
+ if (insert) {
+ exp_fhandler = kzalloc(sizeof(*exp_fhandler), GFP_KERNEL);
+ if (!exp_fhandler) {
+ pr_err("%s: Failed to alloc mem for expansion function\n",
+ __func__);
+ goto exit;
+ }
+ exp_fhandler->exp_fn = exp_fn;
+ exp_fhandler->insert = true;
+ exp_fhandler->remove = false;
+ list_add_tail(&exp_fhandler->link, &exp_data.list);
+ } else if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link) {
+ if (exp_fhandler->exp_fn->fn_type == exp_fn->fn_type) {
+ exp_fhandler->insert = false;
+ exp_fhandler->remove = true;
+ goto exit;
+ }
+ }
+ }
+
+exit:
+ mutex_unlock(&exp_data.mutex);
+
+ if (exp_data.queue_work) {
+ queue_delayed_work(exp_data.workqueue,
+ &exp_data.work,
+ msecs_to_jiffies(EXP_FN_WORK_DELAY_MS));
+ }
+
+ return;
+}
+EXPORT_SYMBOL(synaptics_rmi4_dsx_new_function);
+
+static int synaptics_dsx_regulator_configure(struct synaptics_rmi4_data
+ *rmi4_data)
+{
+ int retval;
+ u32 voltage_supply[2];
+ u32 current_supply;
+
+ /* Regulator VDD */
+ rmi4_data->regulator_vdd = regulator_get(rmi4_data->pdev->dev.parent,
+ "vdd");
+ if (IS_ERR(rmi4_data->regulator_vdd)) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to get regulator vdd\n",
+ __func__);
+ retval = PTR_ERR(rmi4_data->regulator_vdd);
+ return retval;
+ }
+
+ /* Read and set vdd regulator voltage and current */
+ retval = of_property_read_u32(rmi4_data->pdev->dev.parent->of_node,
+ "synaptics,vdd-current", &current_supply);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to get regulator vdd current\n",
+ __func__);
+ goto err_vdd_regulator;
+ }
+ rmi4_data->regulator_vdd_current = current_supply;
+
+ retval = regulator_set_load(rmi4_data->regulator_vdd,
+ rmi4_data->regulator_vdd_current);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to set regulator current vdd\n",
+ __func__);
+ goto err_vdd_regulator;
+ }
+
+ retval = of_property_read_u32_array(
+ rmi4_data->pdev->dev.parent->of_node,
+ "synaptics,vdd-voltage", voltage_supply, 2);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to get regulator vdd voltage\n",
+ __func__);
+ goto err_vdd_regulator;
+ }
+ rmi4_data->regulator_vdd_vmin = voltage_supply[0];
+ rmi4_data->regulator_vdd_vmax = voltage_supply[1];
+
+ retval = regulator_set_voltage(rmi4_data->regulator_vdd,
+ rmi4_data->regulator_vdd_vmin,
+ rmi4_data->regulator_vdd_vmax);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to set regulator voltage vdd\n",
+ __func__);
+ goto err_vdd_regulator;
+ }
+
+ /* Regulator AVDD */
+ rmi4_data->regulator_avdd = regulator_get(rmi4_data->pdev->dev.parent,
+ "avdd");
+ if (IS_ERR(rmi4_data->regulator_avdd)) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to get regulator avdd\n",
+ __func__);
+ retval = PTR_ERR(rmi4_data->regulator_avdd);
+ goto err_vdd_regulator;
+ }
+
+ /* Read and set avdd regulator voltage and current */
+ retval = of_property_read_u32(rmi4_data->pdev->dev.parent->of_node,
+ "synaptics,avdd-current", &current_supply);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to get regulator avdd current\n",
+ __func__);
+ goto err_avdd_regulator;
+ }
+ rmi4_data->regulator_avdd_current = current_supply;
+
+ retval = regulator_set_load(rmi4_data->regulator_avdd,
+ rmi4_data->regulator_avdd_current);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to set regulator current avdd\n",
+ __func__);
+ goto err_avdd_regulator;
+ }
+
+ retval = of_property_read_u32_array(
+ rmi4_data->pdev->dev.parent->of_node,
+ "synaptics,avdd-voltage", voltage_supply, 2);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to get regulator avdd voltage\n",
+ __func__);
+ goto err_avdd_regulator;
+ }
+ rmi4_data->regulator_avdd_vmin = voltage_supply[0];
+ rmi4_data->regulator_avdd_vmax = voltage_supply[1];
+
+ retval = regulator_set_voltage(rmi4_data->regulator_avdd,
+ rmi4_data->regulator_avdd_vmin,
+ rmi4_data->regulator_avdd_vmax);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to set regultor voltage avdd\n",
+ __func__);
+ goto err_avdd_regulator;
+ }
+
+ return 0;
+
+err_avdd_regulator:
+ regulator_put(rmi4_data->regulator_avdd);
+err_vdd_regulator:
+ regulator_put(rmi4_data->regulator_vdd);
+
+ return retval;
+};
+
+static int synaptics_dsx_regulator_enable(struct synaptics_rmi4_data
+ *rmi4_data, bool on)
+{
+ int retval;
+
+ if (on) {
+ retval = regulator_enable(rmi4_data->regulator_vdd);
+ if (retval) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to enable regulator vdd\n",
+ __func__);
+ return retval;
+ }
+ retval = regulator_enable(rmi4_data->regulator_avdd);
+ if (retval) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to enable regulator avdd\n",
+ __func__);
+ regulator_disable(rmi4_data->regulator_vdd);
+ return retval;
+ }
+ msleep(rmi4_data->hw_if->board_data->power_delay_ms);
+ } else {
+ regulator_disable(rmi4_data->regulator_vdd);
+ regulator_disable(rmi4_data->regulator_avdd);
+ }
+
+ return 0;
+}
+
+ /**
+ * synaptics_rmi4_probe()
+ *
+ * Called by the kernel when an association with an I2C device of the
+ * same name is made (after doing i2c_add_driver).
+ *
+ * This funtion allocates and initializes the resources for the driver
+ * as an input driver, turns on the power to the sensor, queries the
+ * sensor for its supported Functions and characteristics, registers
+ * the driver to the input subsystem, sets up the interrupt, handles
+ * the registration of the early_suspend and late_resume functions,
+ * and creates a work queue for detection of other expansion Function
+ * modules.
+ */
+static int synaptics_rmi4_probe(struct platform_device *pdev)
+{
+ int retval, len;
+ unsigned char attr_count;
+ struct synaptics_rmi4_data *rmi4_data;
+ const struct synaptics_dsx_hw_interface *hw_if;
+ const struct synaptics_dsx_board_data *bdata;
+ struct dentry *temp;
+
+ hw_if = pdev->dev.platform_data;
+ if (!hw_if) {
+ dev_err(&pdev->dev,
+ "%s: No hardware interface found\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ bdata = hw_if->board_data;
+ if (!bdata) {
+ dev_err(&pdev->dev,
+ "%s: No board data found\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ rmi4_data = kzalloc(sizeof(*rmi4_data), GFP_KERNEL);
+ if (!rmi4_data) {
+ dev_err(&pdev->dev,
+ "%s: Failed to alloc mem for rmi4_data\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ rmi4_data->pdev = pdev;
+ rmi4_data->current_page = MASK_8BIT;
+ rmi4_data->hw_if = hw_if;
+ rmi4_data->touch_stopped = false;
+ rmi4_data->sensor_sleep = false;
+ rmi4_data->irq_enabled = false;
+ rmi4_data->fw_updating = false;
+ rmi4_data->fingers_on_2d = false;
+ rmi4_data->update_coords = true;
+
+ rmi4_data->irq_enable = synaptics_rmi4_irq_enable;
+ rmi4_data->reset_device = synaptics_rmi4_reset_device;
+
+ mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex));
+ mutex_init(&(rmi4_data->rmi4_reset_mutex));
+
+ retval = synaptics_dsx_regulator_configure(rmi4_data);
+ if (retval) {
+ dev_err(&pdev->dev,
+ "%s: regulator configuration failed\n", __func__);
+ goto err_regulator_configure;
+ }
+ retval = synaptics_dsx_regulator_enable(rmi4_data, true);
+ if (retval) {
+ dev_err(&pdev->dev,
+ "%s: regulator enable failed\n", __func__);
+ goto err_regulator_enable;
+ }
+
+ platform_set_drvdata(pdev, rmi4_data);
+
+ if (bdata->gpio_config) {
+ retval = synaptics_rmi4_set_gpio(rmi4_data);
+ if (retval < 0) {
+ dev_err(&pdev->dev,
+ "%s: Failed to set up GPIO's\n",
+ __func__);
+ goto err_set_gpio;
+ }
+ } else {
+ retval = synaptics_dsx_pinctrl_init(rmi4_data);
+ if (!retval && rmi4_data->ts_pinctrl) {
+ /*
+ * Pinctrl handle is optional. If pinctrl handle is found
+ * let pins to be configured in active state. If not
+ * found continue further without error.
+ */
+ retval = pinctrl_select_state(rmi4_data->ts_pinctrl,
+ rmi4_data->pinctrl_state_active);
+ if (retval < 0) {
+ dev_err(&pdev->dev,
+ "%s: Failed to select %s pinstate %d\n",
+ __func__, PINCTRL_STATE_ACTIVE, retval);
+ }
+ }
+
+ retval = synaptics_dsx_gpio_configure(rmi4_data, true);
+ if (retval < 0) {
+ dev_err(&pdev->dev,
+ "%s: Failed to set up GPIO's\n",
+ __func__);
+ goto err_config_gpio;
+ }
+ }
+
+ if (bdata->fw_name) {
+ len = strlen(bdata->fw_name);
+ if (len > SYNA_FW_NAME_MAX_LEN - 1) {
+ dev_err(&pdev->dev, "Invalid firmware name\n");
+ goto err_set_input_dev;
+ }
+
+ strlcpy(rmi4_data->fw_name, bdata->fw_name, len + 1);
+ }
+
+ retval = synaptics_rmi4_set_input_dev(rmi4_data);
+ if (retval < 0) {
+ dev_err(&pdev->dev,
+ "%s: Failed to set up input device\n",
+ __func__);
+ goto err_set_input_dev;
+ }
+
+#ifdef CONFIG_FB
+ INIT_WORK(&rmi4_data->fb_notify_work, fb_notify_resume_work);
+ rmi4_data->fb_notif.notifier_call = fb_notifier_callback;
+
+ retval = fb_register_client(&rmi4_data->fb_notif);
+ if (retval)
+ dev_err(rmi4_data->pdev->dev.parent,
+ "Unable to register fb_notifier: %d\n", retval);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ rmi4_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ rmi4_data->early_suspend.suspend = synaptics_rmi4_early_suspend;
+ rmi4_data->early_suspend.resume = synaptics_rmi4_late_resume;
+ register_early_suspend(&rmi4_data->early_suspend);
+#endif
+
+ rmi4_data->irq = gpio_to_irq(bdata->irq_gpio);
+
+ if (!exp_data.initialized) {
+ mutex_init(&exp_data.mutex);
+ INIT_LIST_HEAD(&exp_data.list);
+ exp_data.initialized = true;
+ }
+
+ retval = synaptics_rmi4_irq_enable(rmi4_data, true);
+ if (retval < 0) {
+ dev_err(&pdev->dev,
+ "%s: Failed to enable attention interrupt\n",
+ __func__);
+ goto err_enable_irq;
+ }
+
+ exp_data.workqueue = create_singlethread_workqueue("dsx_exp_workqueue");
+ if (exp_data.workqueue == NULL) {
+ dev_err(&pdev->dev,
+ "%s: Failed to create workqueue\n", __func__);
+ retval = -ENOMEM;
+ goto err_create_wq;
+ }
+
+ INIT_DELAYED_WORK(&exp_data.work, synaptics_rmi4_exp_fn_work);
+ exp_data.rmi4_data = rmi4_data;
+ exp_data.queue_work = true;
+ queue_delayed_work(exp_data.workqueue,
+ &exp_data.work,
+ msecs_to_jiffies(EXP_FN_WORK_DELAY_MS));
+
+ rmi4_data->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
+ if (rmi4_data->dir == NULL || IS_ERR(rmi4_data->dir)) {
+ retval = rmi4_data->dir ? PTR_ERR(rmi4_data->dir) : -EIO;
+ dev_err(&pdev->dev,
+ "%s: Failed to create debugfs directory, rc = %d\n",
+ __func__, retval);
+ goto err_create_debugfs_dir;
+ }
+
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, rmi4_data->dir,
+ rmi4_data, &debug_suspend_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ retval = temp ? PTR_ERR(temp) : -EIO;
+ dev_err(&pdev->dev,
+ "%s: Failed to create suspend debugfs file, rc = %d\n",
+ __func__, retval);
+ goto err_create_debugfs_file;
+ }
+
+ for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+ retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ if (retval < 0) {
+ dev_err(&pdev->dev,
+ "%s: Failed to create sysfs attributes\n",
+ __func__);
+ goto err_sysfs;
+ }
+ }
+
+ synaptics_secure_touch_init(rmi4_data);
+ synaptics_secure_touch_stop(rmi4_data, 1);
+
+ return retval;
+
+err_sysfs:
+ for (attr_count--; attr_count >= 0; attr_count--) {
+ sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ }
+err_create_debugfs_file:
+ debugfs_remove_recursive(rmi4_data->dir);
+err_create_debugfs_dir:
+ cancel_delayed_work_sync(&exp_data.work);
+ flush_workqueue(exp_data.workqueue);
+ destroy_workqueue(exp_data.workqueue);
+err_create_wq:
+ synaptics_rmi4_irq_enable(rmi4_data, false);
+ free_irq(rmi4_data->irq, rmi4_data);
+
+err_enable_irq:
+#if defined(CONFIG_FB)
+ fb_unregister_client(&rmi4_data->fb_notif);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&rmi4_data->early_suspend);
+#endif
+
+ synaptics_rmi4_empty_fn_list(rmi4_data);
+ input_unregister_device(rmi4_data->input_dev);
+ rmi4_data->input_dev = NULL;
+
+err_set_input_dev:
+ if (bdata->gpio_config) {
+ bdata->gpio_config(
+ bdata->irq_gpio,
+ false, 0, 0);
+
+ if (bdata->reset_gpio >= 0) {
+ bdata->gpio_config(
+ bdata->reset_gpio,
+ false, 0, 0);
+ }
+
+ if (bdata->power_gpio >= 0) {
+ bdata->gpio_config(
+ bdata->power_gpio,
+ false, 0, 0);
+ }
+ } else {
+ synaptics_dsx_gpio_configure(rmi4_data, false);
+ }
+err_config_gpio:
+ if (rmi4_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(rmi4_data->pinctrl_state_release)) {
+ devm_pinctrl_put(rmi4_data->ts_pinctrl);
+ rmi4_data->ts_pinctrl = NULL;
+ } else {
+ retval = pinctrl_select_state(
+ rmi4_data->ts_pinctrl,
+ rmi4_data->pinctrl_state_release);
+ if (retval)
+ dev_err(&pdev->dev,
+ "%s: Failed to create sysfs attributes\n",
+ __func__);
+ }
+ }
+
+err_set_gpio:
+ regulator_disable(rmi4_data->regulator_vdd);
+ regulator_disable(rmi4_data->regulator_avdd);
+err_regulator_enable:
+ regulator_put(rmi4_data->regulator_vdd);
+ regulator_put(rmi4_data->regulator_avdd);
+err_regulator_configure:
+ kfree(rmi4_data);
+
+ return retval;
+}
+
+ /**
+ * synaptics_rmi4_remove()
+ *
+ * Called by the kernel when the association with an I2C device of the
+ * same name is broken (when the driver is unloaded).
+ *
+ * This funtion terminates the work queue, stops sensor data acquisition,
+ * frees the interrupt, unregisters the driver from the input subsystem,
+ * turns off the power to the sensor, and frees other allocated resources.
+ */
+static int synaptics_rmi4_remove(struct platform_device *pdev)
+{
+ unsigned char attr_count;
+ struct synaptics_rmi4_data *rmi4_data = platform_get_drvdata(pdev);
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+ int err;
+
+ if (rmi4_data->support_vkeys) {
+ sysfs_remove_group(vkey_kobj, &vkey_grp);
+ kobject_put(vkey_kobj);
+ }
+
+ for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+ sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ }
+
+ debugfs_remove_recursive(rmi4_data->dir);
+ cancel_delayed_work_sync(&exp_data.work);
+ flush_workqueue(exp_data.workqueue);
+ destroy_workqueue(exp_data.workqueue);
+
+ synaptics_rmi4_irq_enable(rmi4_data, false);
+
+#if defined(CONFIG_FB)
+ fb_unregister_client(&rmi4_data->fb_notif);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&rmi4_data->early_suspend);
+#endif
+
+ synaptics_rmi4_empty_fn_list(rmi4_data);
+ input_unregister_device(rmi4_data->input_dev);
+ rmi4_data->input_dev = NULL;
+
+ if (bdata->gpio_config) {
+ bdata->gpio_config(
+ bdata->irq_gpio,
+ false, 0, 0);
+
+ if (bdata->reset_gpio >= 0) {
+ bdata->gpio_config(
+ bdata->reset_gpio,
+ false, 0, 0);
+ }
+
+ if (bdata->power_gpio >= 0) {
+ bdata->gpio_config(
+ bdata->power_gpio,
+ false, 0, 0);
+ }
+ } else {
+ synaptics_dsx_gpio_configure(rmi4_data, false);
+ if (rmi4_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(rmi4_data->pinctrl_state_release)) {
+ devm_pinctrl_put(rmi4_data->ts_pinctrl);
+ rmi4_data->ts_pinctrl = NULL;
+ } else {
+ err = pinctrl_select_state(
+ rmi4_data->ts_pinctrl,
+ rmi4_data->pinctrl_state_release);
+ if (err)
+ dev_err(&pdev->dev,
+ "Failed to select release pinctrl state %d\n",
+ err);
+ }
+ }
+ }
+
+ if (rmi4_data->regulator_vdd) {
+ regulator_disable(rmi4_data->regulator_vdd);
+ regulator_put(rmi4_data->regulator_vdd);
+ }
+
+ if (rmi4_data->regulator_avdd) {
+ regulator_disable(rmi4_data->regulator_avdd);
+ regulator_put(rmi4_data->regulator_avdd);
+ }
+
+ kfree(rmi4_data);
+
+ return 0;
+}
+
+#if defined(CONFIG_FB)
+static void fb_notify_resume_work(struct work_struct *work)
+{
+ struct synaptics_rmi4_data *rmi4_data =
+ container_of(work, struct synaptics_rmi4_data, fb_notify_work);
+ synaptics_rmi4_resume(&(rmi4_data->input_dev->dev));
+}
+
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct synaptics_rmi4_data *rmi4_data =
+ container_of(self, struct synaptics_rmi4_data, fb_notif);
+
+ if (evdata && evdata->data && rmi4_data) {
+ blank = evdata->data;
+ if (rmi4_data->hw_if->board_data->resume_in_workqueue) {
+ if (event == FB_EARLY_EVENT_BLANK) {
+ synaptics_secure_touch_stop(rmi4_data, 0);
+ if (*blank == FB_BLANK_UNBLANK)
+ schedule_work(
+ &(rmi4_data->fb_notify_work));
+ } else if (event == FB_EVENT_BLANK &&
+ *blank == FB_BLANK_POWERDOWN) {
+ flush_work(
+ &(rmi4_data->fb_notify_work));
+ synaptics_rmi4_suspend(
+ &(rmi4_data->input_dev->dev));
+ }
+ } else {
+ if (event == FB_EARLY_EVENT_BLANK) {
+ synaptics_secure_touch_stop(rmi4_data, 0);
+ } else if (event == FB_EVENT_BLANK) {
+ if (*blank == FB_BLANK_UNBLANK)
+ synaptics_rmi4_resume(
+ &(rmi4_data->input_dev->dev));
+ else if (*blank == FB_BLANK_POWERDOWN)
+ synaptics_rmi4_suspend(
+ &(rmi4_data->input_dev->dev));
+ }
+ }
+ }
+
+ return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ /**
+ * synaptics_rmi4_early_suspend()
+ *
+ * Called by the kernel during the early suspend phase when the system
+ * enters suspend.
+ *
+ * This function calls synaptics_rmi4_sensor_sleep() to stop finger
+ * data acquisition and put the sensor to sleep.
+ */
+static void synaptics_rmi4_early_suspend(struct early_suspend *h)
+{
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+ struct synaptics_rmi4_data *rmi4_data =
+ container_of(h, struct synaptics_rmi4_data,
+ early_suspend);
+
+ if (rmi4_data->stay_awake) {
+ rmi4_data->staying_awake = true;
+ return;
+ } else {
+ rmi4_data->staying_awake = false;
+ }
+
+ synaptics_secure_touch_stop(rmi4_data, 0);
+
+ rmi4_data->touch_stopped = true;
+ synaptics_rmi4_irq_enable(rmi4_data, false);
+ synaptics_rmi4_sensor_sleep(rmi4_data);
+ synaptics_rmi4_free_fingers(rmi4_data);
+
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link)
+ if (exp_fhandler->exp_fn->early_suspend != NULL)
+ exp_fhandler->exp_fn->early_suspend(rmi4_data);
+ }
+ mutex_unlock(&exp_data.mutex);
+
+ if (rmi4_data->full_pm_cycle)
+ synaptics_rmi4_suspend(&(rmi4_data->input_dev->dev));
+
+ return;
+}
+
+ /**
+ * synaptics_rmi4_late_resume()
+ *
+ * Called by the kernel during the late resume phase when the system
+ * wakes up from suspend.
+ *
+ * This function goes through the sensor wake process if the system wakes
+ * up from early suspend (without going into suspend).
+ */
+static void synaptics_rmi4_late_resume(struct early_suspend *h)
+{
+ int retval;
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+ struct synaptics_rmi4_data *rmi4_data =
+ container_of(h, struct synaptics_rmi4_data,
+ early_suspend);
+
+ if (rmi4_data->staying_awake)
+ return;
+
+ synaptics_secure_touch_stop(rmi4_data, 0);
+
+ if (rmi4_data->full_pm_cycle)
+ synaptics_rmi4_resume(&(rmi4_data->input_dev->dev));
+
+ if (rmi4_data->sensor_sleep == true) {
+ synaptics_rmi4_sensor_wake(rmi4_data);
+ synaptics_rmi4_irq_enable(rmi4_data, true);
+ retval = synaptics_rmi4_reinit_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to reinit device\n",
+ __func__);
+ }
+ }
+
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link)
+ if (exp_fhandler->exp_fn->late_resume != NULL)
+ exp_fhandler->exp_fn->late_resume(rmi4_data);
+ }
+ mutex_unlock(&exp_data.mutex);
+
+ rmi4_data->touch_stopped = false;
+
+ return;
+}
+#endif
+
+#ifdef CONFIG_PM
+ /**
+ * synaptics_rmi4_sensor_sleep()
+ *
+ * Called by synaptics_rmi4_early_suspend() and synaptics_rmi4_suspend().
+ *
+ * This function stops finger data acquisition and puts the sensor to sleep.
+ */
+static void synaptics_rmi4_sensor_sleep(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ unsigned char device_ctrl;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to enter sleep mode\n",
+ __func__);
+ rmi4_data->sensor_sleep = false;
+ return;
+ }
+
+ device_ctrl = (device_ctrl & ~MASK_3BIT);
+ device_ctrl = (device_ctrl | NO_SLEEP_OFF | SENSOR_SLEEP);
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to enter sleep mode\n",
+ __func__);
+ rmi4_data->sensor_sleep = false;
+ return;
+ } else {
+ rmi4_data->sensor_sleep = true;
+ }
+
+ return;
+}
+
+ /**
+ * synaptics_rmi4_sensor_wake()
+ *
+ * Called by synaptics_rmi4_resume() and synaptics_rmi4_late_resume().
+ *
+ * This function wakes the sensor from sleep.
+ */
+static void synaptics_rmi4_sensor_wake(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ unsigned char device_ctrl;
+ unsigned char no_sleep_setting = rmi4_data->no_sleep_setting;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to wake from sleep mode\n",
+ __func__);
+ rmi4_data->sensor_sleep = true;
+ return;
+ }
+
+ device_ctrl = (device_ctrl & ~MASK_3BIT);
+ device_ctrl = (device_ctrl | no_sleep_setting | NORMAL_OPERATION);
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ &device_ctrl,
+ sizeof(device_ctrl));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to wake from sleep mode\n",
+ __func__);
+ rmi4_data->sensor_sleep = true;
+ return;
+ } else {
+ rmi4_data->sensor_sleep = false;
+ }
+
+ return;
+}
+
+ /**
+ * synaptics_rmi4_suspend()
+ *
+ * Called by the kernel during the suspend phase when the system
+ * enters suspend.
+ *
+ * This function stops finger data acquisition and puts the sensor to
+ * sleep (if not already done so during the early suspend phase),
+ * disables the interrupt, and turns off the power to the sensor.
+ */
+static int synaptics_rmi4_suspend(struct device *dev)
+{
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+ int retval;
+
+ if (rmi4_data->stay_awake) {
+ rmi4_data->staying_awake = true;
+ return 0;
+ } else {
+ rmi4_data->staying_awake = false;
+ }
+
+ if (rmi4_data->suspended) {
+ dev_info(dev, "Already in suspend state\n");
+ return 0;
+ }
+
+ synaptics_secure_touch_stop(rmi4_data, 1);
+
+ if (!rmi4_data->fw_updating) {
+ if (!rmi4_data->sensor_sleep) {
+ rmi4_data->touch_stopped = true;
+ synaptics_rmi4_irq_enable(rmi4_data, false);
+ synaptics_rmi4_sensor_sleep(rmi4_data);
+ synaptics_rmi4_free_fingers(rmi4_data);
+ }
+
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link)
+ if (exp_fhandler->exp_fn->suspend != NULL)
+ exp_fhandler->exp_fn->suspend(rmi4_data);
+ }
+ mutex_unlock(&exp_data.mutex);
+
+ retval = synaptics_dsx_regulator_enable(rmi4_data, false);
+ if (retval < 0) {
+ dev_err(dev, "failed to enter low power mode\n");
+ goto err_lpm_regulator;
+ }
+ } else {
+ dev_err(dev,
+ "Firmware updating, cannot go into suspend mode\n");
+ return 0;
+ }
+
+ if (bdata->disable_gpios) {
+ if (rmi4_data->ts_pinctrl) {
+ retval = pinctrl_select_state(rmi4_data->ts_pinctrl,
+ rmi4_data->pinctrl_state_suspend);
+ if (retval < 0) {
+ dev_err(dev, "Cannot get idle pinctrl state\n");
+ goto err_pinctrl_select_suspend;
+ }
+ }
+
+ retval = synaptics_dsx_gpio_configure(rmi4_data, false);
+ if (retval < 0) {
+ dev_err(dev, "failed to put gpios in suspend state\n");
+ goto err_gpio_configure;
+ }
+ }
+
+ rmi4_data->suspended = true;
+
+ return 0;
+
+err_gpio_configure:
+ if (rmi4_data->ts_pinctrl) {
+ retval = pinctrl_select_state(rmi4_data->ts_pinctrl,
+ rmi4_data->pinctrl_state_active);
+ if (retval < 0)
+ dev_err(dev, "Cannot get default pinctrl state\n");
+ }
+err_pinctrl_select_suspend:
+ synaptics_dsx_regulator_enable(rmi4_data, true);
+err_lpm_regulator:
+ if (rmi4_data->sensor_sleep) {
+ synaptics_rmi4_sensor_wake(rmi4_data);
+ synaptics_rmi4_irq_enable(rmi4_data, true);
+ rmi4_data->touch_stopped = false;
+ }
+
+ return retval;
+}
+
+ /**
+ * synaptics_rmi4_resume()
+ *
+ * Called by the kernel during the resume phase when the system
+ * wakes up from suspend.
+ *
+ * This function turns on the power to the sensor, wakes the sensor
+ * from sleep, enables the interrupt, and starts finger data
+ * acquisition.
+ */
+static int synaptics_rmi4_resume(struct device *dev)
+{
+ int retval;
+ struct synaptics_rmi4_exp_fhandler *exp_fhandler;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+ struct synaptics_rmi4_device_info *rmi;
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+ if (rmi->package_id == SYNA_S332U_PACKAGE_ID &&
+ rmi->package_id_rev == SYNA_S332U_PACKAGE_ID_REV) {
+ synaptics_rmi4_reset_device(rmi4_data);
+ }
+
+ if (rmi4_data->staying_awake)
+ return 0;
+
+ if (!rmi4_data->suspended)
+ return 0;
+
+ synaptics_secure_touch_stop(rmi4_data, 1);
+
+ synaptics_dsx_regulator_enable(rmi4_data, true);
+
+ if (bdata->disable_gpios) {
+ if (rmi4_data->ts_pinctrl) {
+ retval = pinctrl_select_state(rmi4_data->ts_pinctrl,
+ rmi4_data->pinctrl_state_active);
+ if (retval < 0)
+ dev_err(dev, "Cannot get default pinctrl state\n");
+ }
+
+ retval = synaptics_dsx_gpio_configure(rmi4_data, true);
+ if (retval < 0)
+ dev_err(dev, "Failed to put gpios in active state\n");
+ }
+
+ synaptics_rmi4_sensor_wake(rmi4_data);
+ retval = synaptics_rmi4_reinit_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to reinit device\n",
+ __func__);
+ return retval;
+ }
+
+ mutex_lock(&exp_data.mutex);
+ if (!list_empty(&exp_data.list)) {
+ list_for_each_entry(exp_fhandler, &exp_data.list, link)
+ if (exp_fhandler->exp_fn->resume != NULL)
+ exp_fhandler->exp_fn->resume(rmi4_data);
+ }
+ mutex_unlock(&exp_data.mutex);
+
+ rmi4_data->touch_stopped = false;
+ rmi4_data->suspended = false;
+
+ synaptics_rmi4_irq_enable(rmi4_data, true);
+
+ return 0;
+}
+
+static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = {
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
+ .suspend = synaptics_rmi4_suspend,
+ .resume = synaptics_rmi4_resume,
+#endif
+};
+#else
+static int synaptics_rmi4_suspend(struct device *dev)
+{
+ dev_err(dev, "PM not supported\n");
+ return -EINVAL;
+}
+
+static int synaptics_rmi4_resume(struct device *dev)
+{
+ dev_err(dev, "PM not supported\n");
+ return -EINVAL;
+}
+#endif
+
+static struct platform_driver synaptics_rmi4_driver = {
+ .driver = {
+ .name = PLATFORM_DRIVER_NAME,
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &synaptics_rmi4_dev_pm_ops,
+#endif
+ },
+ .probe = synaptics_rmi4_probe,
+ .remove = synaptics_rmi4_remove,
+};
+
+ /**
+ * synaptics_rmi4_init()
+ *
+ * Called by the kernel during do_initcalls (if built-in)
+ * or when the driver is loaded (if a module).
+ *
+ * This function registers the driver to the I2C subsystem.
+ *
+ */
+static int __init synaptics_rmi4_init(void)
+{
+ int retval;
+
+ retval = synaptics_rmi4_bus_init();
+ if (retval)
+ return retval;
+
+ return platform_driver_register(&synaptics_rmi4_driver);
+}
+
+ /**
+ * synaptics_rmi4_exit()
+ *
+ * Called by the kernel when the driver is unloaded.
+ *
+ * This funtion unregisters the driver from the I2C subsystem.
+ *
+ */
+static void __exit synaptics_rmi4_exit(void)
+{
+ platform_driver_unregister(&synaptics_rmi4_driver);
+
+ synaptics_rmi4_bus_exit();
+
+ return;
+}
+
+module_init(synaptics_rmi4_init);
+module_exit(synaptics_rmi4_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("Synaptics DSX I2C Touch Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h
new file mode 100644
index 000000000000..7d7e045d7917
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h
@@ -0,0 +1,405 @@
+/*
+ * Synaptics DSX touchscreen driver
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef _SYNAPTICS_DSX_RMI4_H_
+#define _SYNAPTICS_DSX_RMI4_H_
+
+#define SYNAPTICS_DS4 (1 << 0)
+#define SYNAPTICS_DS5 (1 << 1)
+#define SYNAPTICS_DSX_DRIVER_PRODUCT (SYNAPTICS_DS4 | SYNAPTICS_DS5)
+#define SYNAPTICS_DSX_DRIVER_VERSION 0x2001
+
+#include <linux/version.h>
+#include <linux/debugfs.h>
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif
+#if defined(CONFIG_SECURE_TOUCH)
+#include <linux/completion.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38))
+#define KERNEL_ABOVE_2_6_38
+#endif
+
+#ifdef KERNEL_ABOVE_2_6_38
+#define sstrtoul(...) kstrtoul(__VA_ARGS__)
+#else
+#define sstrtoul(...) strict_strtoul(__VA_ARGS__)
+#endif
+
+#define PDT_PROPS (0X00EF)
+#define PDT_START (0x00E9)
+#define PDT_END (0x00D0)
+#define PDT_ENTRY_SIZE (0x0006)
+#define PAGES_TO_SERVICE (10)
+#define PAGE_SELECT_LEN (2)
+#define ADDRESS_WORD_LEN (2)
+
+#define SYNAPTICS_RMI4_F01 (0x01)
+#define SYNAPTICS_RMI4_F11 (0x11)
+#define SYNAPTICS_RMI4_F12 (0x12)
+#define SYNAPTICS_RMI4_F1A (0x1a)
+#define SYNAPTICS_RMI4_F34 (0x34)
+#define SYNAPTICS_RMI4_F51 (0x51)
+#define SYNAPTICS_RMI4_F54 (0x54)
+#define SYNAPTICS_RMI4_F55 (0x55)
+
+#define SYNAPTICS_RMI4_PRODUCT_INFO_SIZE 2
+#define SYNAPTICS_RMI4_DATE_CODE_SIZE 3
+#define SYNAPTICS_RMI4_PRODUCT_ID_SIZE 10
+#define SYNAPTICS_RMI4_BUILD_ID_SIZE 3
+
+#define F01_PACKAGE_ID_OFFSET 17
+#define PACKAGE_ID_SIZE 4
+
+#define F12_FINGERS_TO_SUPPORT 10
+#define F12_NO_OBJECT_STATUS 0x00
+#define F12_FINGER_STATUS 0x01
+#define F12_STYLUS_STATUS 0x02
+#define F12_PALM_STATUS 0x03
+#define F12_HOVERING_FINGER_STATUS 0x05
+#define F12_GLOVED_FINGER_STATUS 0x06
+
+#define MAX_NUMBER_OF_BUTTONS 4
+#define MAX_INTR_REGISTERS 4
+
+#define MASK_16BIT 0xFFFF
+#define MASK_8BIT 0xFF
+#define MASK_7BIT 0x7F
+#define MASK_6BIT 0x3F
+#define MASK_5BIT 0x1F
+#define MASK_4BIT 0x0F
+#define MASK_3BIT 0x07
+#define MASK_2BIT 0x03
+#define MASK_1BIT 0x01
+
+#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE "pmx_ts_release"
+
+#define SYNA_FW_NAME_MAX_LEN 50
+
+enum exp_fn {
+ RMI_DEV = 0,
+ RMI_F54,
+ RMI_FW_UPDATER,
+ RMI_PROXIMITY,
+ RMI_ACTIVE_PEN,
+ RMI_LAST,
+};
+
+struct synaptics_dsx_hw_interface {
+ struct synaptics_dsx_board_data *board_data;
+ const struct synaptics_dsx_bus_access *bus_access;
+};
+
+/*
+ * struct synaptics_rmi4_fn_desc - function descriptor fields in PDT
+ * @query_base_addr: base address for query registers
+ * @cmd_base_addr: base address for command registers
+ * @ctrl_base_addr: base address for control registers
+ * @data_base_addr: base address for data registers
+ * @intr_src_count: number of interrupt sources
+ * @fn_number: function number
+ */
+struct synaptics_rmi4_fn_desc {
+ unsigned char query_base_addr;
+ unsigned char cmd_base_addr;
+ unsigned char ctrl_base_addr;
+ unsigned char data_base_addr;
+ unsigned char intr_src_count;
+ unsigned char fn_number;
+};
+
+/*
+ * synaptics_rmi4_fn_full_addr - full 16-bit base addresses
+ * @query_base: 16-bit base address for query registers
+ * @cmd_base: 16-bit base address for data registers
+ * @ctrl_base: 16-bit base address for command registers
+ * @data_base: 16-bit base address for control registers
+ */
+struct synaptics_rmi4_fn_full_addr {
+ unsigned short query_base;
+ unsigned short cmd_base;
+ unsigned short ctrl_base;
+ unsigned short data_base;
+};
+
+struct synaptics_rmi4_f12_extra_data {
+ unsigned char data1_offset;
+ unsigned char data15_offset;
+ unsigned char data15_size;
+ unsigned char data15_data[(F12_FINGERS_TO_SUPPORT + 7) / 8];
+};
+
+/*
+ * struct synaptics_rmi4_fn - function handler data structure
+ * @fn_number: function number
+ * @num_of_data_sources: number of data sources
+ * @num_of_data_points: maximum number of fingers supported
+ * @size_of_data_register_block: data register block size
+ * @intr_reg_num: index to associated interrupt register
+ * @intr_mask: interrupt mask
+ * @full_addr: full 16-bit base addresses of function registers
+ * @link: linked list for function handlers
+ * @data_size: size of private data
+ * @data: pointer to private data
+ */
+struct synaptics_rmi4_fn {
+ unsigned char fn_number;
+ unsigned char num_of_data_sources;
+ unsigned char num_of_data_points;
+ unsigned char size_of_data_register_block;
+ unsigned char intr_reg_num;
+ unsigned char intr_mask;
+ struct synaptics_rmi4_fn_full_addr full_addr;
+ struct list_head link;
+ int data_size;
+ void *data;
+ void *extra;
+};
+
+/*
+ * struct synaptics_rmi4_device_info - device information
+ * @version_major: rmi protocol major version number
+ * @version_minor: rmi protocol minor version number
+ * @manufacturer_id: manufacturer id
+ * @product_props: product properties information
+ * @product_info: product info array
+ * @date_code: device manufacture date
+ * @tester_id: tester id array
+ * @serial_number: device serial number
+ * @product_id_string: device product id
+ * @support_fn_list: linked list for function handlers
+ */
+struct synaptics_rmi4_device_info {
+ unsigned int version_major;
+ unsigned int version_minor;
+ unsigned char manufacturer_id;
+ unsigned char product_props;
+ unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
+ unsigned char date_code[SYNAPTICS_RMI4_DATE_CODE_SIZE];
+ unsigned short tester_id;
+ unsigned short serial_number;
+ unsigned char product_id_string[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
+ unsigned char build_id[SYNAPTICS_RMI4_BUILD_ID_SIZE];
+ struct list_head support_fn_list;
+ unsigned int package_id;
+ unsigned int package_id_rev;
+};
+
+/*
+ * struct synaptics_rmi4_data - rmi4 device instance data
+ * @pdev: pointer to platform device
+ * @input_dev: pointer to associated input device
+ * @hw_if: pointer to hardware interface data
+ * @rmi4_mod_info: device information
+ * @regulator_vdd: pointer to associated vdd regulator
+ * @regulator_add: pointer to associated avdd regulator
+ * @regulator_vdd_vmin: minimum vdd regulator voltage
+ * @regulator_vdd_vmax: maximum vdd regulator voltage
+ * @regulator_vdd_current: vdd regulator current load
+ * @regulator_avdd_vmin: minimum avdd regulator voltage
+ * @regulator_avdd_vmax: maximum avdd regulator voltage
+ * @regulator_avdd_current: avdd regulator current load
+ * @rmi4_io_ctrl_mutex: mutex for i2c i/o control
+ * @early_suspend: instance to support early suspend power management
+ * @current_page: current page in sensor to acess
+ * @button_0d_enabled: flag for 0d button support
+ * @full_pm_cycle: flag for full power management cycle in early suspend stage
+ * @num_of_intr_regs: number of interrupt registers
+ * @f01_query_base_addr: query base address for f01
+ * @f01_cmd_base_addr: command base address for f01
+ * @f01_ctrl_base_addr: control base address for f01
+ * @f01_data_base_addr: data base address for f01
+ * @irq: attention interrupt
+ * @sensor_max_x: sensor maximum x value
+ * @sensor_max_y: sensor maximum y value
+ * @irq_enabled: flag for indicating interrupt enable status
+ * @fingers_on_2d: flag to indicate presence of fingers in 2d area
+ * @sensor_sleep: flag to indicate sleep state of sensor
+ * @wait: wait queue for touch data polling in interrupt thread
+ * @irq_enable: pointer to irq enable function
+ */
+struct synaptics_rmi4_data {
+ struct platform_device *pdev;
+ struct input_dev *input_dev;
+ const struct synaptics_dsx_hw_interface *hw_if;
+ struct synaptics_rmi4_device_info rmi4_mod_info;
+ struct regulator *regulator_vdd;
+ struct regulator *regulator_avdd;
+ int regulator_vdd_vmin;
+ int regulator_vdd_vmax;
+ int regulator_vdd_current;
+ int regulator_avdd_vmin;
+ int regulator_avdd_vmax;
+ int regulator_avdd_current;
+ struct mutex rmi4_reset_mutex;
+ struct mutex rmi4_io_ctrl_mutex;
+#if defined(CONFIG_FB)
+ struct work_struct fb_notify_work;
+ struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+ struct dentry *dir;
+ unsigned char current_page;
+ unsigned char button_0d_enabled;
+ unsigned char full_pm_cycle;
+ unsigned char num_of_rx;
+ unsigned char num_of_tx;
+ unsigned char num_of_fingers;
+ unsigned char max_touch_width;
+ unsigned char report_enable;
+ unsigned char no_sleep_setting;
+ unsigned char intr_mask[MAX_INTR_REGISTERS];
+ unsigned char *button_txrx_mapping;
+ unsigned short num_of_intr_regs;
+ unsigned short f01_query_base_addr;
+ unsigned short f01_cmd_base_addr;
+ unsigned short f01_ctrl_base_addr;
+ unsigned short f01_data_base_addr;
+ unsigned int firmware_id;
+ int irq;
+ int sensor_max_x;
+ int sensor_max_y;
+ bool flash_prog_mode;
+ bool irq_enabled;
+ bool touch_stopped;
+ bool fingers_on_2d;
+ bool sensor_sleep;
+ bool stay_awake;
+ bool staying_awake;
+ bool fw_updating;
+ bool support_vkeys;
+ bool update_coords;
+ int (*irq_enable)(struct synaptics_rmi4_data *rmi4_data, bool enable);
+ int (*reset_device)(struct synaptics_rmi4_data *rmi4_data);
+
+ struct pinctrl *ts_pinctrl;
+ struct pinctrl_state *pinctrl_state_active;
+ struct pinctrl_state *pinctrl_state_suspend;
+ struct pinctrl_state *pinctrl_state_release;
+ char fw_name[SYNA_FW_NAME_MAX_LEN];
+ bool suspended;
+#if defined(CONFIG_SECURE_TOUCH)
+ atomic_t st_enabled;
+ atomic_t st_pending_irqs;
+ bool st_initialized;
+ struct completion st_powerdown;
+ struct completion st_irq_processed;
+ struct clk *core_clk;
+ struct clk *iface_clk;
+#endif
+};
+
+struct synaptics_dsx_bus_access {
+ unsigned char type;
+ int (*read)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
+ unsigned char *data, unsigned short length);
+ int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
+ unsigned char *data, unsigned short length);
+#if defined(CONFIG_SECURE_TOUCH)
+ int (*get)(struct synaptics_rmi4_data *rmi4_data);
+ void (*put)(struct synaptics_rmi4_data *rmi4_data);
+#endif
+};
+
+struct synaptics_rmi4_exp_fn {
+ enum exp_fn fn_type;
+ int (*init)(struct synaptics_rmi4_data *rmi4_data);
+ void (*remove)(struct synaptics_rmi4_data *rmi4_data);
+ void (*reset)(struct synaptics_rmi4_data *rmi4_data);
+ void (*reinit)(struct synaptics_rmi4_data *rmi4_data);
+ void (*early_suspend)(struct synaptics_rmi4_data *rmi4_data);
+ void (*suspend)(struct synaptics_rmi4_data *rmi4_data);
+ void (*resume)(struct synaptics_rmi4_data *rmi4_data);
+ void (*late_resume)(struct synaptics_rmi4_data *rmi4_data);
+ void (*attn)(struct synaptics_rmi4_data *rmi4_data,
+ unsigned char intr_mask);
+};
+
+int synaptics_rmi4_bus_init(void);
+
+void synaptics_rmi4_bus_exit(void);
+
+void synaptics_rmi4_dsx_new_function(struct synaptics_rmi4_exp_fn *exp_fn_mod,
+ bool insert);
+
+int synaptics_dsx_fw_updater(unsigned char *fw_data);
+
+int synaptics_dsx_get_dt_coords(struct device *dev, char *name,
+ struct synaptics_dsx_board_data *pdata,
+ struct device_node *node);
+
+static inline int synaptics_rmi4_reg_read(
+ struct synaptics_rmi4_data *rmi4_data,
+ unsigned short addr,
+ unsigned char *data,
+ unsigned short len)
+{
+ return rmi4_data->hw_if->bus_access->read(rmi4_data, addr, data, len);
+}
+
+static inline int synaptics_rmi4_reg_write(
+ struct synaptics_rmi4_data *rmi4_data,
+ unsigned short addr,
+ unsigned char *data,
+ unsigned short len)
+{
+ return rmi4_data->hw_if->bus_access->write(rmi4_data, addr, data, len);
+}
+
+#if defined(CONFIG_SECURE_TOUCH)
+static inline int synaptics_rmi4_bus_get(struct synaptics_rmi4_data *rmi4_data)
+{
+ return rmi4_data->hw_if->bus_access->get(rmi4_data);
+}
+static inline void synaptics_rmi4_bus_put(struct synaptics_rmi4_data *rmi4_data)
+{
+ rmi4_data->hw_if->bus_access->put(rmi4_data);
+}
+#endif
+
+static inline ssize_t synaptics_rmi4_store_error(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ dev_warn(dev, "%s Attempted to write to read-only attribute %s\n",
+ __func__, attr->attr.name);
+ return -EPERM;
+}
+
+static inline void batohs(unsigned short *dest, unsigned char *src)
+{
+ *dest = src[1] * 0x100 + src[0];
+}
+
+static inline void hstoba(unsigned char *dest, unsigned short src)
+{
+ dest[0] = src % 0x100;
+ dest[1] = src / 0x100;
+}
+#endif
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
new file mode 100644
index 000000000000..13680130c2de
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
@@ -0,0 +1,2163 @@
+/*
+ * Synaptics DSX touchscreen driver
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+#include <linux/input/synaptics_dsx_v2.h>
+#include "synaptics_dsx_core.h"
+
+#define STARTUP_FW_UPDATE_DELAY_MS 1000 /* ms */
+#define FORCE_UPDATE false
+#define DO_LOCKDOWN false
+
+#define MAX_IMAGE_NAME_LEN 256
+#define MAX_FIRMWARE_ID_LEN 10
+
+#define LOCKDOWN_OFFSET 0xb0
+#define FW_IMAGE_OFFSET 0x100
+
+#define BOOTLOADER_ID_OFFSET 0
+#define BLOCK_NUMBER_OFFSET 0
+
+#define V5_PROPERTIES_OFFSET 2
+#define V5_BLOCK_SIZE_OFFSET 3
+#define V5_BLOCK_COUNT_OFFSET 5
+#define V5_BLOCK_DATA_OFFSET 2
+
+#define V6_PROPERTIES_OFFSET 1
+#define V6_BLOCK_SIZE_OFFSET 2
+#define V6_BLOCK_COUNT_OFFSET 3
+#define V6_BLOCK_DATA_OFFSET 1
+#define V6_FLASH_COMMAND_OFFSET 2
+#define V6_FLASH_STATUS_OFFSET 3
+
+#define LOCKDOWN_BLOCK_COUNT 5
+
+#define REG_MAP (1 << 0)
+#define UNLOCKED (1 << 1)
+#define HAS_CONFIG_ID (1 << 2)
+#define HAS_PERM_CONFIG (1 << 3)
+#define HAS_BL_CONFIG (1 << 4)
+#define HAS_DISP_CONFIG (1 << 5)
+#define HAS_CTRL1 (1 << 6)
+
+#define UI_CONFIG_AREA 0x00
+#define PERM_CONFIG_AREA 0x01
+#define BL_CONFIG_AREA 0x02
+#define DISP_CONFIG_AREA 0x03
+
+#define CMD_WRITE_FW_BLOCK 0x2
+#define CMD_ERASE_ALL 0x3
+#define CMD_WRITE_LOCKDOWN_BLOCK 0x4
+#define CMD_READ_CONFIG_BLOCK 0x5
+#define CMD_WRITE_CONFIG_BLOCK 0x6
+#define CMD_ERASE_CONFIG 0x7
+#define CMD_ERASE_BL_CONFIG 0x9
+#define CMD_ERASE_DISP_CONFIG 0xa
+#define CMD_ENABLE_FLASH_PROG 0xf
+
+#define SLEEP_MODE_NORMAL (0x00)
+#define SLEEP_MODE_SENSOR_SLEEP (0x01)
+#define SLEEP_MODE_RESERVED0 (0x02)
+#define SLEEP_MODE_RESERVED1 (0x03)
+
+#define ENABLE_WAIT_MS (1 * 1000)
+#define WRITE_WAIT_MS (3 * 1000)
+#define ERASE_WAIT_MS (5 * 1000)
+
+#define MIN_SLEEP_TIME_US 50
+#define MAX_SLEEP_TIME_US 100
+
+#define SYN_FW_CFG_GREATER(fwu, config_id) \
+ ((fwu->config_data[0] == 0) && (config_id[0] == 0) && \
+ (fwu->config_data[1] == config_id[1]) && \
+ (((fwu->config_data[2] == config_id[2]) && \
+ (fwu->config_data[3] > config_id[3])) || \
+ (fwu->config_data[2] > config_id[2])))
+
+#define SYN_FW_CFG_EQUAL(fwu, config_id) \
+ ((fwu->config_data[0] == 0) && (config_id[0] == 0) && \
+ (fwu->config_data[1] == config_id[1]) && \
+ (fwu->config_data[2] == config_id[2]) && \
+ (fwu->config_data[3] == config_id[3]))
+
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+static ssize_t fwu_sysfs_show_image(struct file *data_file,
+ struct kobject *kobj, struct bin_attribute *attributes,
+ char *buf, loff_t pos, size_t count);
+
+static ssize_t fwu_sysfs_store_image(struct file *data_file,
+ struct kobject *kobj, struct bin_attribute *attributes,
+ char *buf, loff_t pos, size_t count);
+
+static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_write_config_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_read_config_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_config_area_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_image_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_image_name_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_image_size_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t fwu_sysfs_block_size_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_config_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t fwu_sysfs_package_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+#endif
+
+enum bl_version {
+ V5 = 5,
+ V6 = 6,
+};
+
+enum flash_area {
+ NONE,
+ UI_FIRMWARE,
+ CONFIG_AREA,
+};
+
+enum update_mode {
+ NORMAL = 1,
+ FORCE = 2,
+ LOCKDOWN = 8,
+};
+
+struct image_header {
+ /* 0x00 - 0x0f */
+ unsigned char checksum[4];
+ unsigned char reserved_04;
+ unsigned char reserved_05;
+ unsigned char options_firmware_id:1;
+ unsigned char options_contain_bootloader:1;
+ unsigned char options_reserved:6;
+ unsigned char bootloader_version;
+ unsigned char firmware_size[4];
+ unsigned char config_size[4];
+ /* 0x10 - 0x1f */
+ unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE];
+ unsigned char package_id[2];
+ unsigned char package_id_revision[2];
+ unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
+ /* 0x20 - 0x2f */
+ unsigned char reserved_20_2f[16];
+ /* 0x30 - 0x3f */
+ unsigned char ds_id[16];
+ /* 0x40 - 0x4f */
+ unsigned char ds_info[10];
+ unsigned char reserved_4a_4f[6];
+ /* 0x50 - 0x53 */
+ unsigned char firmware_id[4];
+};
+
+struct image_header_data {
+ bool contains_firmware_id;
+ unsigned int firmware_id;
+ unsigned int checksum;
+ unsigned int firmware_size;
+ unsigned int config_size;
+ unsigned char bootloader_version;
+ unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
+ unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
+};
+
+struct pdt_properties {
+ union {
+ struct {
+ unsigned char reserved_1:6;
+ unsigned char has_bsr:1;
+ unsigned char reserved_2:1;
+ } __packed;
+ unsigned char data[1];
+ };
+};
+
+struct f01_device_status {
+ union {
+ struct {
+ unsigned char status_code:4;
+ unsigned char reserved:2;
+ unsigned char flash_prog:1;
+ unsigned char unconfigured:1;
+ } __packed;
+ unsigned char data[1];
+ };
+};
+
+struct f01_device_control {
+ union {
+ struct {
+ unsigned char sleep_mode:2;
+ unsigned char nosleep:1;
+ unsigned char reserved:2;
+ unsigned char charger_connected:1;
+ unsigned char report_rate:1;
+ unsigned char configured:1;
+ } __packed;
+ unsigned char data[1];
+ };
+};
+
+struct synaptics_rmi4_fwu_handle {
+ enum bl_version bl_version;
+ bool initialized;
+ bool program_enabled;
+ bool has_perm_config;
+ bool has_bl_config;
+ bool has_disp_config;
+ bool force_update;
+ bool in_flash_prog_mode;
+ bool do_lockdown;
+ unsigned int data_pos;
+ unsigned int image_size;
+ unsigned char *image_name;
+ unsigned char *ext_data_source;
+ unsigned char *read_config_buf;
+ unsigned char intr_mask;
+ unsigned char command;
+ unsigned char bootloader_id[2];
+ unsigned char flash_properties;
+ unsigned char flash_status;
+ unsigned char productinfo1;
+ unsigned char productinfo2;
+ unsigned char properties_off;
+ unsigned char blk_size_off;
+ unsigned char blk_count_off;
+ unsigned char blk_data_off;
+ unsigned char flash_cmd_off;
+ unsigned char flash_status_off;
+ unsigned short block_size;
+ unsigned short fw_block_count;
+ unsigned short config_block_count;
+ unsigned short lockdown_block_count;
+ unsigned short perm_config_block_count;
+ unsigned short bl_config_block_count;
+ unsigned short disp_config_block_count;
+ unsigned short config_size;
+ unsigned short config_area;
+ char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
+ const unsigned char *firmware_data;
+ const unsigned char *config_data;
+ const unsigned char *lockdown_data;
+ struct delayed_work fwu_work;
+ struct synaptics_rmi4_fn_desc f34_fd;
+ struct synaptics_rmi4_data *rmi4_data;
+};
+
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+static struct bin_attribute dev_attr_data = {
+ .attr = {
+ .name = "data",
+ .mode = (S_IRUGO | S_IWUSR),
+ },
+ .size = 0,
+ .read = fwu_sysfs_show_image,
+ .write = fwu_sysfs_store_image,
+};
+#endif
+
+
+static struct device_attribute attrs[] = {
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+ __ATTR(force_update_fw, S_IWUSR | S_IWGRP,
+ NULL,
+ fwu_sysfs_force_reflash_store),
+ __ATTR(update_fw, S_IWUSR | S_IWGRP,
+ NULL,
+ fwu_sysfs_do_reflash_store),
+ __ATTR(writeconfig, S_IWUSR | S_IWGRP,
+ NULL,
+ fwu_sysfs_write_config_store),
+ __ATTR(readconfig, S_IWUSR | S_IWGRP,
+ NULL,
+ fwu_sysfs_read_config_store),
+ __ATTR(configarea, S_IWUSR | S_IWGRP,
+ NULL,
+ fwu_sysfs_config_area_store),
+ __ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP,
+ fwu_sysfs_image_name_show,
+ fwu_sysfs_image_name_store),
+ __ATTR(imagesize, S_IWUSR | S_IWGRP,
+ NULL,
+ fwu_sysfs_image_size_store),
+ __ATTR(blocksize, S_IRUGO,
+ fwu_sysfs_block_size_show,
+ synaptics_rmi4_store_error),
+ __ATTR(fwblockcount, S_IRUGO,
+ fwu_sysfs_firmware_block_count_show,
+ synaptics_rmi4_store_error),
+ __ATTR(configblockcount, S_IRUGO,
+ fwu_sysfs_configuration_block_count_show,
+ synaptics_rmi4_store_error),
+ __ATTR(permconfigblockcount, S_IRUGO,
+ fwu_sysfs_perm_config_block_count_show,
+ synaptics_rmi4_store_error),
+ __ATTR(blconfigblockcount, S_IRUGO,
+ fwu_sysfs_bl_config_block_count_show,
+ synaptics_rmi4_store_error),
+ __ATTR(dispconfigblockcount, S_IRUGO,
+ fwu_sysfs_disp_config_block_count_show,
+ synaptics_rmi4_store_error),
+ __ATTR(config_id, S_IRUGO,
+ fwu_sysfs_config_id_show,
+ synaptics_rmi4_store_error),
+ __ATTR(package_id, S_IRUGO,
+ fwu_sysfs_package_id_show,
+ synaptics_rmi4_store_error),
+#endif
+};
+
+static struct synaptics_rmi4_fwu_handle *fwu;
+
+DECLARE_COMPLETION(fwu_dsx_remove_complete);
+DEFINE_MUTEX(dsx_fwu_sysfs_mutex);
+
+static unsigned int extract_uint_le(const unsigned char *ptr)
+{
+ return (unsigned int)ptr[0] +
+ (unsigned int)ptr[1] * 0x100 +
+ (unsigned int)ptr[2] * 0x10000 +
+ (unsigned int)ptr[3] * 0x1000000;
+}
+
+static void parse_header(struct image_header_data *header,
+ const unsigned char *fw_image)
+{
+ struct image_header *data = (struct image_header *)fw_image;
+
+ header->checksum = extract_uint_le(data->checksum);
+
+ header->bootloader_version = data->bootloader_version;
+
+ header->firmware_size = extract_uint_le(data->firmware_size);
+
+ header->config_size = extract_uint_le(data->config_size);
+
+ memcpy(header->product_id, data->product_id, sizeof(data->product_id));
+ header->product_id[sizeof(data->product_id)] = 0;
+
+ memcpy(header->product_info, data->product_info,
+ sizeof(data->product_info));
+
+ header->contains_firmware_id = data->options_firmware_id;
+ if (header->contains_firmware_id)
+ header->firmware_id = extract_uint_le(data->firmware_id);
+
+ return;
+}
+
+static int fwu_read_f01_device_status(struct f01_device_status *status)
+{
+ int retval;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_data_base_addr,
+ status->data,
+ sizeof(status->data));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read F01 device status\n",
+ __func__);
+ return retval;
+ }
+
+ return 0;
+}
+
+static int fwu_read_f34_queries(void)
+{
+ int retval;
+ unsigned char count;
+ unsigned char buf[10];
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.query_base_addr + BOOTLOADER_ID_OFFSET,
+ fwu->bootloader_id,
+ sizeof(fwu->bootloader_id));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read bootloader ID\n",
+ __func__);
+ return retval;
+ }
+
+ if (fwu->bootloader_id[1] == '5') {
+ fwu->bl_version = V5;
+ } else if (fwu->bootloader_id[1] == '6') {
+ fwu->bl_version = V6;
+ } else {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Unrecognized bootloader version\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (fwu->bl_version == V5) {
+ fwu->properties_off = V5_PROPERTIES_OFFSET;
+ fwu->blk_size_off = V5_BLOCK_SIZE_OFFSET;
+ fwu->blk_count_off = V5_BLOCK_COUNT_OFFSET;
+ fwu->blk_data_off = V5_BLOCK_DATA_OFFSET;
+ } else if (fwu->bl_version == V6) {
+ fwu->properties_off = V6_PROPERTIES_OFFSET;
+ fwu->blk_size_off = V6_BLOCK_SIZE_OFFSET;
+ fwu->blk_count_off = V6_BLOCK_COUNT_OFFSET;
+ fwu->blk_data_off = V6_BLOCK_DATA_OFFSET;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.query_base_addr + fwu->properties_off,
+ &fwu->flash_properties,
+ sizeof(fwu->flash_properties));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read flash properties\n",
+ __func__);
+ return retval;
+ }
+
+ count = 4;
+
+ if (fwu->flash_properties & HAS_PERM_CONFIG) {
+ fwu->has_perm_config = 1;
+ count += 2;
+ }
+
+ if (fwu->flash_properties & HAS_BL_CONFIG) {
+ fwu->has_bl_config = 1;
+ count += 2;
+ }
+
+ if (fwu->flash_properties & HAS_DISP_CONFIG) {
+ fwu->has_disp_config = 1;
+ count += 2;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.query_base_addr + fwu->blk_size_off,
+ buf,
+ 2);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read block size info\n",
+ __func__);
+ return retval;
+ }
+
+ batohs(&fwu->block_size, &(buf[0]));
+
+ if (fwu->bl_version == V5) {
+ fwu->flash_cmd_off = fwu->blk_data_off + fwu->block_size;
+ fwu->flash_status_off = fwu->flash_cmd_off;
+ } else if (fwu->bl_version == V6) {
+ fwu->flash_cmd_off = V6_FLASH_COMMAND_OFFSET;
+ fwu->flash_status_off = V6_FLASH_STATUS_OFFSET;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.query_base_addr + fwu->blk_count_off,
+ buf,
+ count);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read block count info\n",
+ __func__);
+ return retval;
+ }
+
+ batohs(&fwu->fw_block_count, &(buf[0]));
+ batohs(&fwu->config_block_count, &(buf[2]));
+
+ count = 4;
+
+ if (fwu->has_perm_config) {
+ batohs(&fwu->perm_config_block_count, &(buf[count]));
+ count += 2;
+ }
+
+ if (fwu->has_bl_config) {
+ batohs(&fwu->bl_config_block_count, &(buf[count]));
+ count += 2;
+ }
+
+ if (fwu->has_disp_config)
+ batohs(&fwu->disp_config_block_count, &(buf[count]));
+
+ return 0;
+}
+
+static int fwu_read_f34_flash_status(void)
+{
+ int retval;
+ unsigned char status;
+ unsigned char command;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.data_base_addr + fwu->flash_status_off,
+ &status,
+ sizeof(status));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read flash status\n",
+ __func__);
+ return retval;
+ }
+
+ fwu->program_enabled = status >> 7;
+
+ if (fwu->bl_version == V5)
+ fwu->flash_status = (status >> 4) & MASK_3BIT;
+ else if (fwu->bl_version == V6)
+ fwu->flash_status = status & MASK_3BIT;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.data_base_addr + fwu->flash_cmd_off,
+ &command,
+ sizeof(command));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read flash command\n",
+ __func__);
+ return retval;
+ }
+
+ fwu->command = command & MASK_4BIT;
+
+ return 0;
+}
+
+static int fwu_write_f34_command(unsigned char cmd)
+{
+ int retval;
+ unsigned char command = cmd & MASK_4BIT;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ fwu->command = cmd;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fwu->f34_fd.data_base_addr + fwu->flash_cmd_off,
+ &command,
+ sizeof(command));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write command 0x%02x\n",
+ __func__, command);
+ return retval;
+ }
+
+ return 0;
+}
+
+static int fwu_wait_for_idle(int timeout_ms)
+{
+ int count = 0;
+ int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ do {
+ usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US);
+
+ count++;
+ if (count == timeout_count)
+ fwu_read_f34_flash_status();
+
+ if ((fwu->command == 0x00) && (fwu->flash_status == 0x00))
+ return 0;
+ } while (count < timeout_count);
+
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Timed out waiting for idle status\n",
+ __func__);
+
+ return -ETIMEDOUT;
+}
+
+static enum flash_area fwu_go_nogo(struct image_header_data *header)
+{
+ int retval;
+ enum flash_area flash_area = NONE;
+ unsigned char index = 0;
+ unsigned char config_id[4];
+ unsigned int device_fw_id;
+ unsigned long image_fw_id;
+ char *strptr;
+ char *firmware_id;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ if (fwu->force_update) {
+ flash_area = UI_FIRMWARE;
+ goto exit;
+ }
+
+ /* Update both UI and config if device is in bootloader mode */
+ if (fwu->in_flash_prog_mode) {
+ flash_area = UI_FIRMWARE;
+ goto exit;
+ }
+
+ /* Get device firmware ID */
+ device_fw_id = rmi4_data->firmware_id;
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Device firmware ID = %d\n",
+ __func__, device_fw_id);
+
+ /* Get image firmware ID */
+ if (header->contains_firmware_id) {
+ image_fw_id = header->firmware_id;
+ } else {
+ strptr = strnstr(fwu->image_name, "PR",
+ sizeof(fwu->image_name));
+ if (!strptr) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: No valid PR number (PRxxxxxxx) found in image file name (%s)\n",
+ __func__, fwu->image_name);
+ flash_area = NONE;
+ goto exit;
+ }
+
+ strptr += 2;
+ firmware_id = kzalloc(MAX_FIRMWARE_ID_LEN, GFP_KERNEL);
+ if (!firmware_id) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for firmware id\n",
+ __func__);
+ flash_area = NONE;
+ goto exit;
+ }
+
+ while ((index < MAX_FIRMWARE_ID_LEN - 1) && strptr[index] >= '0'
+ && strptr[index] <= '9') {
+ firmware_id[index] = strptr[index];
+ index++;
+ }
+ firmware_id[index] = '\0';
+
+ retval = sstrtoul(firmware_id, 10, &image_fw_id);
+ kfree(firmware_id);
+ if (retval) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to obtain image firmware ID\n",
+ __func__);
+ flash_area = NONE;
+ goto exit;
+ }
+ }
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Image firmware ID = %d\n",
+ __func__, (unsigned int)image_fw_id);
+
+ if (!rmi4_data->hw_if->board_data->bypass_packrat_id_check) {
+ if (image_fw_id > device_fw_id) {
+ flash_area = UI_FIRMWARE;
+ goto exit;
+ } else if (image_fw_id < device_fw_id) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Image firmware ID older than device firmware ID\n",
+ __func__);
+ flash_area = NONE;
+ goto exit;
+ }
+ }
+
+ /* Get device config ID */
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.ctrl_base_addr,
+ config_id,
+ sizeof(config_id));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read device config ID\n",
+ __func__);
+ flash_area = NONE;
+ goto exit;
+ }
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Device config ID = 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ __func__,
+ config_id[0],
+ config_id[1],
+ config_id[2],
+ config_id[3]);
+
+ /* Get image config ID */
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Image config ID = 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ __func__,
+ fwu->config_data[0],
+ fwu->config_data[1],
+ fwu->config_data[2],
+ fwu->config_data[3]);
+
+ if (SYN_FW_CFG_GREATER(fwu, config_id)) {
+ if (image_fw_id > device_fw_id) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Image file has higher packrat id than device\n",
+ __func__);
+ /*
+ * If packrat id of the firmware file is greater than
+ * the firmware build id in the device(same as packrat
+ * id), then both firmware and config area need to be
+ * upgraded.
+ */
+ flash_area = UI_FIRMWARE;
+ goto exit;
+ } else if (image_fw_id == device_fw_id) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Image file has equal packrat id as is in device\n",
+ __func__);
+ /*
+ * If packrat id of the firmware file equals the
+ * firmware build id in the device(same as packrat id),
+ * then only config area needs to be upgraded.
+ */
+ flash_area = CONFIG_AREA;
+ goto exit;
+ } else if (image_fw_id < device_fw_id) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Image file has lesser packrat id than device, even though config id is greater\n",
+ __func__);
+ /*
+ * If packrat id of the firmware file is lesser than
+ * the firmware build id in the device(same as packrat
+ * id), then it is treated as an error
+ */
+ flash_area = NONE;
+ goto exit;
+ }
+ } else if (SYN_FW_CFG_EQUAL(fwu, config_id)) {
+ if (image_fw_id > device_fw_id) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Image file has higher packrat id than device, though config id is equal\n",
+ __func__);
+ /*
+ * If config id of the firmware file equals the config
+ * id in the device, but packrat id of the firmware is
+ * greater than the firmware build id in the device
+ * (same as packrat id), then both firmware and config
+ * area need to be upgraded.
+ */
+ flash_area = UI_FIRMWARE;
+ goto exit;
+ } else if (image_fw_id == device_fw_id) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Image file has equal packrat id and config id as are in device\n",
+ __func__);
+ /*
+ * If config id of the firmware file equals the config
+ * id in the device and if packrat id of the firmware
+ * is also equal to the firmware build id in the device
+ * (same as packrat id), then no update is needed.
+ */
+ flash_area = NONE;
+ goto exit;
+ } else if (image_fw_id < device_fw_id) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Image file has lesser packrat id than device, though config id is equal\n",
+ __func__);
+ /*
+ * If config id of the firmware file equals the config
+ * id in the device, but the packrat id of the firmware
+ * file is lesser than the firmware build id in the
+ * device(same as packrat id), then it is treated as an
+ * error and no update is needed.
+ */
+ flash_area = NONE;
+ goto exit;
+ }
+ }
+
+ flash_area = NONE;
+
+exit:
+ if (flash_area == NONE) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: No need to do reflash\n",
+ __func__);
+ } else {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Updating %s\n",
+ __func__,
+ flash_area == UI_FIRMWARE ?
+ "UI firmware" :
+ "config only");
+ }
+
+ return flash_area;
+}
+
+static int fwu_scan_pdt(void)
+{
+ int retval;
+ unsigned char ii;
+ unsigned char intr_count = 0;
+ unsigned char intr_off;
+ unsigned char intr_src;
+ unsigned short addr;
+ bool f01found = false;
+ bool f34found = false;
+ struct synaptics_rmi4_fn_desc rmi_fd;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ addr,
+ (unsigned char *)&rmi_fd,
+ sizeof(rmi_fd));
+ if (retval < 0)
+ return retval;
+
+ if (rmi_fd.fn_number) {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Found F%02x\n",
+ __func__, rmi_fd.fn_number);
+ switch (rmi_fd.fn_number) {
+ case SYNAPTICS_RMI4_F01:
+ f01found = true;
+
+ rmi4_data->f01_query_base_addr =
+ rmi_fd.query_base_addr;
+ rmi4_data->f01_ctrl_base_addr =
+ rmi_fd.ctrl_base_addr;
+ rmi4_data->f01_data_base_addr =
+ rmi_fd.data_base_addr;
+ rmi4_data->f01_cmd_base_addr =
+ rmi_fd.cmd_base_addr;
+ break;
+ case SYNAPTICS_RMI4_F34:
+ f34found = true;
+ fwu->f34_fd.query_base_addr =
+ rmi_fd.query_base_addr;
+ fwu->f34_fd.ctrl_base_addr =
+ rmi_fd.ctrl_base_addr;
+ fwu->f34_fd.data_base_addr =
+ rmi_fd.data_base_addr;
+
+ fwu->intr_mask = 0;
+ intr_src = rmi_fd.intr_src_count;
+ intr_off = intr_count % 8;
+ for (ii = intr_off;
+ ii < ((intr_src & MASK_3BIT) +
+ intr_off);
+ ii++) {
+ fwu->intr_mask |= 1 << ii;
+ }
+ break;
+ }
+ } else {
+ break;
+ }
+
+ intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
+ }
+
+ if (!f01found || !f34found) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to find both F01 and F34\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
+ unsigned char command)
+{
+ int retval;
+ unsigned char block_offset[] = {0, 0};
+ unsigned short block_num;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ unsigned int progress;
+ unsigned char command_str[10];
+
+ switch (command) {
+ case CMD_WRITE_CONFIG_BLOCK:
+ progress = 10;
+ strlcpy(command_str, "config", 10);
+ break;
+ case CMD_WRITE_FW_BLOCK:
+ progress = 100;
+ strlcpy(command_str, "firmware", 10);
+ break;
+ case CMD_WRITE_LOCKDOWN_BLOCK:
+ progress = 1;
+ strlcpy(command_str, "lockdown", 10);
+ break;
+ default:
+ progress = 1;
+ strlcpy(command_str, "unknown", 10);
+ break;
+ }
+
+ block_offset[1] |= (fwu->config_area << 5);
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
+ block_offset,
+ sizeof(block_offset));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write to block number registers\n",
+ __func__);
+ return retval;
+ }
+
+ for (block_num = 0; block_num < block_cnt; block_num++) {
+ if (block_num % progress == 0)
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: update %s %3d / %3d\n",
+ __func__, command_str, block_num, block_cnt);
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fwu->f34_fd.data_base_addr + fwu->blk_data_off,
+ block_ptr,
+ fwu->block_size);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write block data (block %d)\n",
+ __func__, block_num);
+ return retval;
+ }
+
+ retval = fwu_write_f34_command(command);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write command for block %d\n",
+ __func__, block_num);
+ return retval;
+ }
+
+ retval = fwu_wait_for_idle(WRITE_WAIT_MS);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to wait for idle status (block %d)\n",
+ __func__, block_num);
+ return retval;
+ }
+
+ block_ptr += fwu->block_size;
+ }
+
+ dev_info(rmi4_data->pdev->dev.parent,
+ "updated %d/%d blocks\n", block_num, block_cnt);
+
+ return 0;
+}
+
+static int fwu_write_firmware(void)
+{
+ return fwu_write_blocks((unsigned char *)fwu->firmware_data,
+ fwu->fw_block_count, CMD_WRITE_FW_BLOCK);
+}
+
+static int fwu_write_configuration(void)
+{
+ return fwu_write_blocks((unsigned char *)fwu->config_data,
+ fwu->config_block_count, CMD_WRITE_CONFIG_BLOCK);
+}
+
+static int fwu_write_lockdown(void)
+{
+ return fwu_write_blocks((unsigned char *)fwu->lockdown_data,
+ fwu->lockdown_block_count, CMD_WRITE_LOCKDOWN_BLOCK);
+}
+
+static int fwu_write_bootloader_id(void)
+{
+ int retval;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fwu->f34_fd.data_base_addr + fwu->blk_data_off,
+ fwu->bootloader_id,
+ sizeof(fwu->bootloader_id));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write bootloader ID\n",
+ __func__);
+ return retval;
+ }
+
+ return 0;
+}
+
+static int fwu_enter_flash_prog(void)
+{
+ int retval;
+ struct f01_device_status f01_device_status;
+ struct f01_device_control f01_device_control;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = fwu_write_bootloader_id();
+ if (retval < 0)
+ return retval;
+
+ retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG);
+ if (retval < 0)
+ return retval;
+
+ retval = fwu_wait_for_idle(ENABLE_WAIT_MS);
+ if (retval < 0)
+ return retval;
+
+ if (!fwu->program_enabled) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Program enabled bit not set\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ retval = fwu_scan_pdt();
+ if (retval < 0)
+ return retval;
+
+ retval = fwu_read_f01_device_status(&f01_device_status);
+ if (retval < 0)
+ return retval;
+
+ if (!f01_device_status.flash_prog) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Not in flash prog mode\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ retval = fwu_read_f34_queries();
+ if (retval < 0)
+ return retval;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ f01_device_control.data,
+ sizeof(f01_device_control.data));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read F01 device control\n",
+ __func__);
+ return retval;
+ }
+
+ f01_device_control.nosleep = true;
+ f01_device_control.sleep_mode = SLEEP_MODE_NORMAL;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ f01_device_control.data,
+ sizeof(f01_device_control.data));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write F01 device control\n",
+ __func__);
+ return retval;
+ }
+
+ return retval;
+}
+
+static int fwu_do_reflash(void)
+{
+ int retval;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = fwu_enter_flash_prog();
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Entered flash prog mode\n",
+ __func__);
+
+ retval = fwu_write_bootloader_id();
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Bootloader ID written\n",
+ __func__);
+
+ retval = fwu_write_f34_command(CMD_ERASE_ALL);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Erase all command written\n",
+ __func__);
+
+ retval = fwu_wait_for_idle(ERASE_WAIT_MS);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Idle status detected\n",
+ __func__);
+
+ if (fwu->firmware_data) {
+ retval = fwu_write_firmware();
+ if (retval < 0)
+ return retval;
+ pr_notice("%s: Firmware programmed\n", __func__);
+ }
+
+ if (fwu->config_data) {
+ retval = fwu_write_configuration();
+ if (retval < 0)
+ return retval;
+ pr_notice("%s: Configuration programmed\n", __func__);
+ }
+
+ return retval;
+}
+
+static int fwu_do_write_config(void)
+{
+ int retval;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = fwu_enter_flash_prog();
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Entered flash prog mode\n",
+ __func__);
+
+ if (fwu->config_area == PERM_CONFIG_AREA) {
+ fwu->config_block_count = fwu->perm_config_block_count;
+ goto write_config;
+ }
+
+ retval = fwu_write_bootloader_id();
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Bootloader ID written\n",
+ __func__);
+
+ switch (fwu->config_area) {
+ case UI_CONFIG_AREA:
+ retval = fwu_write_f34_command(CMD_ERASE_CONFIG);
+ break;
+ case BL_CONFIG_AREA:
+ retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG);
+ fwu->config_block_count = fwu->bl_config_block_count;
+ break;
+ case DISP_CONFIG_AREA:
+ retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG);
+ fwu->config_block_count = fwu->disp_config_block_count;
+ break;
+ }
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Erase command written\n",
+ __func__);
+
+ retval = fwu_wait_for_idle(ERASE_WAIT_MS);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Idle status detected\n",
+ __func__);
+
+write_config:
+ retval = fwu_write_configuration();
+ if (retval < 0)
+ return retval;
+
+ pr_notice("%s: Config written\n", __func__);
+
+ return retval;
+}
+
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+static int fwu_start_write_config(void)
+{
+ int retval;
+ unsigned short block_count;
+ struct image_header_data header;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ switch (fwu->config_area) {
+ case UI_CONFIG_AREA:
+ block_count = fwu->config_block_count;
+ break;
+ case PERM_CONFIG_AREA:
+ if (!fwu->has_perm_config)
+ return -EINVAL;
+ block_count = fwu->perm_config_block_count;
+ break;
+ case BL_CONFIG_AREA:
+ if (!fwu->has_bl_config)
+ return -EINVAL;
+ block_count = fwu->bl_config_block_count;
+ break;
+ case DISP_CONFIG_AREA:
+ if (!fwu->has_disp_config)
+ return -EINVAL;
+ block_count = fwu->disp_config_block_count;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (fwu->ext_data_source)
+ fwu->config_data = fwu->ext_data_source;
+ else
+ return -EINVAL;
+
+ fwu->config_size = fwu->block_size * block_count;
+
+ /* Jump to the config area if given a packrat image */
+ if ((fwu->config_area == UI_CONFIG_AREA) &&
+ (fwu->config_size != fwu->image_size)) {
+ parse_header(&header, fwu->ext_data_source);
+
+ if (header.config_size) {
+ fwu->config_data = fwu->ext_data_source +
+ FW_IMAGE_OFFSET +
+ header.firmware_size;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ pr_notice("%s: Start of write config process\n", __func__);
+
+ retval = fwu_do_write_config();
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write config\n",
+ __func__);
+ }
+
+ rmi4_data->reset_device(rmi4_data);
+
+ pr_notice("%s: End of write config process\n", __func__);
+
+ return retval;
+}
+
+static int fwu_do_read_config(void)
+{
+ int retval;
+ unsigned char block_offset[] = {0, 0};
+ unsigned short block_num;
+ unsigned short block_count;
+ unsigned short index = 0;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = fwu_enter_flash_prog();
+ if (retval < 0)
+ goto exit;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Entered flash prog mode\n",
+ __func__);
+
+ switch (fwu->config_area) {
+ case UI_CONFIG_AREA:
+ block_count = fwu->config_block_count;
+ break;
+ case PERM_CONFIG_AREA:
+ if (!fwu->has_perm_config) {
+ retval = -EINVAL;
+ goto exit;
+ }
+ block_count = fwu->perm_config_block_count;
+ break;
+ case BL_CONFIG_AREA:
+ if (!fwu->has_bl_config) {
+ retval = -EINVAL;
+ goto exit;
+ }
+ block_count = fwu->bl_config_block_count;
+ break;
+ case DISP_CONFIG_AREA:
+ if (!fwu->has_disp_config) {
+ retval = -EINVAL;
+ goto exit;
+ }
+ block_count = fwu->disp_config_block_count;
+ break;
+ default:
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ fwu->config_size = fwu->block_size * block_count;
+
+ kfree(fwu->read_config_buf);
+ fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL);
+ if (!fwu->read_config_buf) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc memory for config buffer\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ block_offset[1] |= (fwu->config_area << 5);
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
+ block_offset,
+ sizeof(block_offset));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write to block number registers\n",
+ __func__);
+ goto exit;
+ }
+
+ for (block_num = 0; block_num < block_count; block_num++) {
+ retval = fwu_write_f34_command(CMD_READ_CONFIG_BLOCK);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write read config command\n",
+ __func__);
+ goto exit;
+ }
+
+ retval = fwu_wait_for_idle(WRITE_WAIT_MS);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to wait for idle status\n",
+ __func__);
+ goto exit;
+ }
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.data_base_addr + fwu->blk_data_off,
+ &fwu->read_config_buf[index],
+ fwu->block_size);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read block data (block %d)\n",
+ __func__, block_num);
+ goto exit;
+ }
+
+ index += fwu->block_size;
+ }
+
+exit:
+ rmi4_data->reset_device(rmi4_data);
+
+ return retval;
+}
+#endif
+
+static int fwu_do_lockdown(void)
+{
+ int retval;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ retval = fwu_enter_flash_prog();
+ if (retval < 0)
+ return retval;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.query_base_addr + fwu->properties_off,
+ &fwu->flash_properties,
+ sizeof(fwu->flash_properties));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read flash properties\n",
+ __func__);
+ return retval;
+ }
+
+ if ((fwu->flash_properties & UNLOCKED) == 0) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: Device already locked down\n",
+ __func__);
+ return retval;
+ }
+
+ retval = fwu_write_lockdown();
+ if (retval < 0)
+ return retval;
+
+ pr_notice("%s: Lockdown programmed\n", __func__);
+
+ return retval;
+}
+
+static int fwu_start_reflash(void)
+{
+ int retval = 0;
+ enum flash_area flash_area;
+ struct image_header_data header;
+ struct f01_device_status f01_device_status;
+ const unsigned char *fw_image;
+ const struct firmware *fw_entry = NULL;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ if (rmi4_data->sensor_sleep) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Sensor sleeping\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ rmi4_data->stay_awake = true;
+
+ pr_notice("%s: Start of reflash process\n", __func__);
+
+ if (fwu->ext_data_source) {
+ fw_image = fwu->ext_data_source;
+ } else {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Requesting firmware image %s\n",
+ __func__, fwu->image_name);
+
+ retval = request_firmware(&fw_entry, fwu->image_name,
+ rmi4_data->pdev->dev.parent);
+ if (retval != 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Firmware image %s not available\n",
+ __func__, fwu->image_name);
+ rmi4_data->stay_awake = false;
+ return retval;
+ }
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Firmware image size = %zu\n",
+ __func__, fw_entry->size);
+
+ fw_image = fw_entry->data;
+ }
+
+ parse_header(&header, fw_image);
+
+ if (fwu->bl_version != header.bootloader_version) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Bootloader version mismatch\n",
+ __func__);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ retval = fwu_read_f01_device_status(&f01_device_status);
+ if (retval < 0)
+ goto exit;
+
+ if (f01_device_status.flash_prog) {
+ dev_info(rmi4_data->pdev->dev.parent,
+ "%s: In flash prog mode\n",
+ __func__);
+ fwu->in_flash_prog_mode = true;
+ } else {
+ fwu->in_flash_prog_mode = false;
+ }
+
+ if (fwu->do_lockdown) {
+ switch (fwu->bl_version) {
+ case V5:
+ case V6:
+ fwu->lockdown_data = fw_image + LOCKDOWN_OFFSET;
+ fwu->lockdown_block_count = LOCKDOWN_BLOCK_COUNT;
+ retval = fwu_do_lockdown();
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to do lockdown\n",
+ __func__);
+ }
+ default:
+ break;
+ }
+ }
+
+ if (header.firmware_size)
+ fwu->firmware_data = fw_image + FW_IMAGE_OFFSET;
+ if (header.config_size) {
+ fwu->config_data = fw_image + FW_IMAGE_OFFSET +
+ header.firmware_size;
+ }
+
+ flash_area = fwu_go_nogo(&header);
+ switch (flash_area) {
+ case UI_FIRMWARE:
+ retval = fwu_do_reflash();
+ break;
+ case CONFIG_AREA:
+ retval = fwu_do_write_config();
+ break;
+ case NONE:
+ default:
+ goto exit;
+ }
+
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to do reflash\n",
+ __func__);
+ }
+
+exit:
+ rmi4_data->reset_device(rmi4_data);
+
+ if (fw_entry)
+ release_firmware(fw_entry);
+
+ pr_notice("%s: End of reflash process\n", __func__);
+
+ rmi4_data->stay_awake = false;
+
+ return retval;
+}
+
+int synaptics_dsx_fw_updater(unsigned char *fw_data)
+{
+ int retval;
+
+ if (!fwu)
+ return -ENODEV;
+
+ if (!fwu->initialized)
+ return -ENODEV;
+
+ fwu->rmi4_data->fw_updating = true;
+ if (fwu->rmi4_data->suspended == true) {
+ fwu->rmi4_data->fw_updating = false;
+ dev_err(fwu->rmi4_data->pdev->dev.parent,
+ "Cannot start fw upgrade: Device is in suspend\n");
+ return -EBUSY;
+ }
+
+ fwu->ext_data_source = fw_data;
+ fwu->config_area = UI_CONFIG_AREA;
+
+ retval = fwu_start_reflash();
+
+ fwu->rmi4_data->fw_updating = false;
+
+ return retval;
+}
+EXPORT_SYMBOL(synaptics_dsx_fw_updater);
+
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+static ssize_t fwu_sysfs_show_image(struct file *data_file,
+ struct kobject *kobj, struct bin_attribute *attributes,
+ char *buf, loff_t pos, size_t count)
+{
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ ssize_t retval;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
+ if (count < fwu->config_size) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Not enough space (%zu bytes) in buffer\n",
+ __func__, count);
+ retval = -EINVAL;
+ goto show_image_exit;
+ }
+
+ memcpy(buf, fwu->read_config_buf, fwu->config_size);
+ retval = fwu->config_size;
+show_image_exit:
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return retval;
+}
+
+static ssize_t fwu_sysfs_store_image(struct file *data_file,
+ struct kobject *kobj, struct bin_attribute *attributes,
+ char *buf, loff_t pos, size_t count)
+{
+ ssize_t retval;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
+ if (count > (fwu->image_size - fwu->data_pos)) {
+ dev_err(fwu->rmi4_data->pdev->dev.parent,
+ "%s: Not enough space in buffer\n",
+ __func__);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (!fwu->ext_data_source) {
+ dev_err(fwu->rmi4_data->pdev->dev.parent,
+ "%s: Need to set imagesize\n",
+ __func__);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
+ (const void *)buf,
+ count);
+
+ fwu->data_pos += count;
+
+exit:
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return count;
+}
+
+static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t retval;
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
+ if (sscanf(buf, "%u", &input) != 1) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (input != 1) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (LOCKDOWN)
+ fwu->do_lockdown = true;
+
+ fwu->force_update = true;
+ retval = synaptics_dsx_fw_updater(fwu->ext_data_source);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to do reflash\n",
+ __func__);
+ goto exit;
+ }
+
+ retval = count;
+exit:
+ kfree(fwu->ext_data_source);
+ fwu->ext_data_source = NULL;
+ fwu->force_update = FORCE_UPDATE;
+ fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->data_pos = 0;
+ fwu->image_size = 0;
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return retval;
+}
+
+static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
+ if (sscanf(buf, "%u", &input) != 1) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (input & LOCKDOWN) {
+ fwu->do_lockdown = true;
+ input &= ~LOCKDOWN;
+ }
+
+ if ((input != NORMAL) && (input != FORCE)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (input == FORCE)
+ fwu->force_update = true;
+
+ retval = synaptics_dsx_fw_updater(fwu->ext_data_source);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to do reflash\n",
+ __func__);
+ goto exit;
+ }
+
+ retval = count;
+
+exit:
+ kfree(fwu->ext_data_source);
+ fwu->ext_data_source = NULL;
+ fwu->force_update = FORCE_UPDATE;
+ fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->data_pos = 0;
+ fwu->image_size = 0;
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return retval;
+}
+
+static ssize_t fwu_sysfs_write_config_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
+ if (sscanf(buf, "%u", &input) != 1) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (input != 1) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ retval = fwu_start_write_config();
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to write config\n",
+ __func__);
+ goto exit;
+ }
+
+ retval = count;
+
+exit:
+ kfree(fwu->ext_data_source);
+ fwu->ext_data_source = NULL;
+ fwu->data_pos = 0;
+ fwu->image_size = 0;
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return retval;
+}
+
+static ssize_t fwu_sysfs_read_config_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+
+ if (input != 1)
+ return -EINVAL;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+ retval = fwu_do_read_config();
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read config\n",
+ __func__);
+ return retval;
+ }
+
+ return count;
+}
+
+static ssize_t fwu_sysfs_config_area_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned long config_area;
+
+ retval = sstrtoul(buf, 10, &config_area);
+ if (retval)
+ return retval;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+ fwu->config_area = config_area;
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+
+ return count;
+}
+
+static ssize_t fwu_sysfs_image_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t retval;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+ if (strnlen(fwu->rmi4_data->fw_name, SYNA_FW_NAME_MAX_LEN) > 0)
+ retval = snprintf(buf, PAGE_SIZE, "%s\n",
+ fwu->rmi4_data->fw_name);
+ else
+ retval = snprintf(buf, PAGE_SIZE, "No firmware name given\n");
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return retval;
+}
+
+static ssize_t fwu_sysfs_image_name_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t retval;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+ retval = sscanf(buf, "%49s", fwu->image_name);
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+
+ if (retval != 1)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t fwu_sysfs_image_size_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned long size;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
+ retval = sstrtoul(buf, 10, &size);
+ if (retval)
+ goto exit;
+
+ fwu->image_size = size;
+ fwu->data_pos = 0;
+
+ kfree(fwu->ext_data_source);
+ fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL);
+ if (!fwu->ext_data_source) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for image data\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ retval = count;
+exit:
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return retval;
+}
+
+static ssize_t fwu_sysfs_block_size_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size);
+}
+
+static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", fwu->fw_block_count);
+}
+
+static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", fwu->config_block_count);
+}
+
+static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", fwu->perm_config_block_count);
+}
+
+static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", fwu->bl_config_block_count);
+}
+
+static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count);
+}
+
+static ssize_t fwu_sysfs_config_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ unsigned char config_id[4];
+ int retval;
+
+ /* device config id */
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ fwu->f34_fd.ctrl_base_addr,
+ config_id,
+ sizeof(config_id));
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read device config ID\n",
+ __func__);
+ return retval;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
+ config_id[0], config_id[1], config_id[2], config_id[3]);
+}
+
+static ssize_t fwu_sysfs_package_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int retval;
+ unsigned char package_id[PACKAGE_ID_SIZE];
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ /* read device package id */
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ rmi4_data->f01_query_base_addr + F01_PACKAGE_ID_OFFSET,
+ package_id,
+ sizeof(package_id));
+
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read device package ID\n",
+ __func__);
+ return retval;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%d rev %d\n",
+ (package_id[1] << 8) | package_id[0],
+ (package_id[3] << 8) | package_id[2]);
+}
+#endif
+
+static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
+ unsigned char intr_mask)
+{
+ if (!fwu)
+ return;
+
+ if (fwu->intr_mask & intr_mask)
+ fwu_read_f34_flash_status();
+
+ return;
+}
+
+static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ unsigned char attr_count;
+ struct pdt_properties pdt_props;
+
+ fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
+ if (!fwu) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to alloc mem for fwu\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ fwu->image_name = rmi4_data->fw_name;
+
+ fwu->rmi4_data = rmi4_data;
+
+ retval = synaptics_rmi4_reg_read(rmi4_data,
+ PDT_PROPS,
+ pdt_props.data,
+ sizeof(pdt_props.data));
+ if (retval < 0) {
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Failed to read PDT properties, assuming 0x00\n",
+ __func__);
+ } else if (pdt_props.has_bsr) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Reflash for LTS not currently supported\n",
+ __func__);
+ retval = -ENODEV;
+ goto exit_free_fwu;
+ }
+
+ retval = fwu_scan_pdt();
+ if (retval < 0)
+ goto exit_free_fwu;
+
+ fwu->productinfo1 = rmi4_data->rmi4_mod_info.product_info[0];
+ fwu->productinfo2 = rmi4_data->rmi4_mod_info.product_info[1];
+ memcpy(fwu->product_id, rmi4_data->rmi4_mod_info.product_id_string,
+ SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
+ fwu->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
+
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: F01 product info: 0x%04x 0x%04x\n",
+ __func__, fwu->productinfo1, fwu->productinfo2);
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: F01 product ID: %s\n",
+ __func__, fwu->product_id);
+
+ retval = fwu_read_f34_queries();
+ if (retval < 0)
+ goto exit_free_fwu;
+
+ fwu->force_update = FORCE_UPDATE;
+ fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->initialized = true;
+
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+ retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj,
+ &dev_attr_data);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to create sysfs bin file\n",
+ __func__);
+ goto exit_free_fwu;
+ }
+#endif
+
+ for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+ retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ if (retval < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to create sysfs attributes\n",
+ __func__);
+ retval = -ENODEV;
+ goto exit_remove_attrs;
+ }
+ }
+
+ return 0;
+
+exit_remove_attrs:
+ for (attr_count--; attr_count >= 0; attr_count--) {
+ sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ }
+
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+ sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+#endif
+
+exit_free_fwu:
+ kfree(fwu);
+ fwu = NULL;
+
+exit:
+ return retval;
+}
+
+static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
+{
+ unsigned char attr_count;
+
+ if (!fwu)
+ goto exit;
+
+ for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+ sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ }
+
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+ sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+#endif
+
+ kfree(fwu->read_config_buf);
+ kfree(fwu);
+ fwu = NULL;
+
+exit:
+ complete(&fwu_dsx_remove_complete);
+
+ return;
+}
+
+static struct synaptics_rmi4_exp_fn fwu_module = {
+ .fn_type = RMI_FW_UPDATER,
+ .init = synaptics_rmi4_fwu_init,
+ .remove = synaptics_rmi4_fwu_remove,
+ .reset = NULL,
+ .reinit = NULL,
+ .early_suspend = NULL,
+ .suspend = NULL,
+ .resume = NULL,
+ .late_resume = NULL,
+ .attn = synaptics_rmi4_fwu_attn,
+};
+
+static int __init rmi4_fw_update_module_init(void)
+{
+ synaptics_rmi4_dsx_new_function(&fwu_module, true);
+
+ return 0;
+}
+
+static void __exit rmi4_fw_update_module_exit(void)
+{
+ synaptics_rmi4_dsx_new_function(&fwu_module, false);
+
+ wait_for_completion(&fwu_dsx_remove_complete);
+
+ return;
+}
+
+module_init(rmi4_fw_update_module_init);
+module_exit(rmi4_fw_update_module_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("Synaptics DSX FW Update Module");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
new file mode 100644
index 000000000000..0b3fbaf9f462
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
@@ -0,0 +1,530 @@
+/*
+ * Synaptics DSX touchscreen driver
+ *
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ *
+ * Linux foundation chooses to take subject only to the GPLv2 license terms,
+ * and distributes only under these terms.
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/input/synaptics_dsx_v2.h>
+#include "synaptics_dsx_core.h"
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#if defined(CONFIG_SECURE_TOUCH)
+#include <linux/pm_runtime.h>
+#endif
+
+#define SYN_I2C_RETRY_TIMES 10
+#define RESET_DELAY 100
+#define DSX_COORDS_ARR_SIZE 4
+
+static int synaptics_rmi4_i2c_set_page(struct synaptics_rmi4_data *rmi4_data,
+ unsigned short addr)
+{
+ int retval;
+ unsigned char retry;
+ unsigned char buf[PAGE_SELECT_LEN];
+ unsigned char page;
+ struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+
+ page = ((addr >> 8) & MASK_8BIT);
+ if (page != rmi4_data->current_page) {
+ buf[0] = MASK_8BIT;
+ buf[1] = page;
+ for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
+ retval = i2c_master_send(i2c, buf, PAGE_SELECT_LEN);
+ if (retval != PAGE_SELECT_LEN) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: I2C retry %d\n",
+ __func__, retry + 1);
+ msleep(20);
+ } else {
+ rmi4_data->current_page = page;
+ break;
+ }
+ }
+ } else {
+ retval = PAGE_SELECT_LEN;
+ }
+
+ return retval;
+}
+
+static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
+ unsigned short addr, unsigned char *data, unsigned short length)
+{
+ int retval;
+ unsigned char retry;
+ unsigned char buf;
+ struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+ struct i2c_msg msg[] = {
+ {
+ .addr = i2c->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &buf,
+ },
+ {
+ .addr = i2c->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = data,
+ },
+ };
+
+ buf = addr & MASK_8BIT;
+
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+ retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr);
+ if (retval != PAGE_SELECT_LEN) {
+ retval = -EIO;
+ goto exit;
+ }
+
+ for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
+ if (i2c_transfer(i2c->adapter, msg, 2) == 2) {
+ retval = length;
+ break;
+ }
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: I2C retry %d\n",
+ __func__, retry + 1);
+ msleep(20);
+ }
+
+ if (retry == SYN_I2C_RETRY_TIMES) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: I2C read over retry limit\n",
+ __func__);
+ retval = -EIO;
+ }
+
+exit:
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+ return retval;
+}
+
+static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data,
+ unsigned short addr, unsigned char *data, unsigned short length)
+{
+ int retval;
+ unsigned char retry;
+ unsigned char buf[length + 1];
+ struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+ struct i2c_msg msg[] = {
+ {
+ .addr = i2c->addr,
+ .flags = 0,
+ .len = length + 1,
+ .buf = buf,
+ }
+ };
+
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+ retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr);
+ if (retval != PAGE_SELECT_LEN) {
+ retval = -EIO;
+ goto exit;
+ }
+
+ buf[0] = addr & MASK_8BIT;
+ memcpy(&buf[1], &data[0], length);
+
+ for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
+ if (i2c_transfer(i2c->adapter, msg, 1) == 1) {
+ retval = length;
+ break;
+ }
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: I2C retry %d\n",
+ __func__, retry + 1);
+ msleep(20);
+ }
+
+ if (retry == SYN_I2C_RETRY_TIMES) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: I2C write over retry limit\n",
+ __func__);
+ retval = -EIO;
+ }
+
+exit:
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+ return retval;
+}
+
+#if defined(CONFIG_SECURE_TOUCH)
+static int synaptics_rmi4_clk_prepare_enable(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ int ret;
+ ret = clk_prepare_enable(rmi4_data->iface_clk);
+ if (ret) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "error on clk_prepare_enable(iface_clk):%d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(rmi4_data->core_clk);
+ if (ret) {
+ clk_disable_unprepare(rmi4_data->iface_clk);
+ dev_err(rmi4_data->pdev->dev.parent,
+ "error clk_prepare_enable(core_clk):%d\n", ret);
+ }
+ return ret;
+}
+
+static void synaptics_rmi4_clk_disable_unprepare(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ clk_disable_unprepare(rmi4_data->core_clk);
+ clk_disable_unprepare(rmi4_data->iface_clk);
+}
+
+static int synaptics_rmi4_i2c_get(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+ retval = pm_runtime_get_sync(i2c->adapter->dev.parent);
+ if (retval >= 0) {
+ retval = synaptics_rmi4_clk_prepare_enable(rmi4_data);
+ if (retval)
+ pm_runtime_put_sync(i2c->adapter->dev.parent);
+ }
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+ return retval;
+}
+
+static void synaptics_rmi4_i2c_put(struct synaptics_rmi4_data *rmi4_data)
+{
+ struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+ synaptics_rmi4_clk_disable_unprepare(rmi4_data);
+ pm_runtime_put_sync(i2c->adapter->dev.parent);
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+}
+#endif
+
+static struct synaptics_dsx_bus_access bus_access = {
+ .type = BUS_I2C,
+ .read = synaptics_rmi4_i2c_read,
+ .write = synaptics_rmi4_i2c_write,
+#if defined(CONFIG_SECURE_TOUCH)
+ .get = synaptics_rmi4_i2c_get,
+ .put = synaptics_rmi4_i2c_put,
+#endif
+};
+
+static struct synaptics_dsx_hw_interface hw_if;
+
+static struct platform_device *synaptics_dsx_i2c_device;
+
+static void synaptics_rmi4_i2c_dev_release(struct device *dev)
+{
+ kfree(synaptics_dsx_i2c_device);
+
+ return;
+}
+#ifdef CONFIG_OF
+int synaptics_dsx_get_dt_coords(struct device *dev, char *name,
+ struct synaptics_dsx_board_data *pdata,
+ struct device_node *node)
+{
+ u32 coords[DSX_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = (node == NULL) ? (dev->of_node) : (node);
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != DSX_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (strcmp(name, "synaptics,panel-coords") == 0) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (strcmp(name, "synaptics,display-coords") == 0) {
+ pdata->disp_minx = coords[0];
+ pdata->disp_miny = coords[1];
+ pdata->disp_maxx = coords[2];
+ pdata->disp_maxy = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int synaptics_dsx_parse_dt(struct device *dev,
+ struct synaptics_dsx_board_data *rmi4_pdata)
+{
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ u32 temp_val, num_buttons;
+ u32 button_map[MAX_NUMBER_OF_BUTTONS];
+ int rc, i;
+
+ rmi4_pdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
+ rmi4_pdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
+
+ rmi4_pdata->disable_gpios = of_property_read_bool(np,
+ "synaptics,disable-gpios");
+
+ rmi4_pdata->bypass_packrat_id_check = of_property_read_bool(np,
+ "synaptics,bypass-packrat-id-check");
+
+ rmi4_pdata->resume_in_workqueue = of_property_read_bool(np,
+ "synaptics,resume-in-workqueue");
+
+ rmi4_pdata->reset_delay_ms = RESET_DELAY;
+ rc = of_property_read_u32(np, "synaptics,reset-delay-ms", &temp_val);
+ if (!rc)
+ rmi4_pdata->reset_delay_ms = temp_val;
+ else if (rc != -EINVAL) {
+ dev_err(dev, "Unable to read reset delay\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "synaptics,config-id",
+ &rmi4_pdata->config_id);
+ if (rc && (rc != -EINVAL))
+ dev_err(dev, "Unable to read config id from DT\n");
+
+ rmi4_pdata->fw_name = "PRXXX_fw.img";
+ rc = of_property_read_string(np, "synaptics,fw-name",
+ &rmi4_pdata->fw_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw name\n");
+ return rc;
+ }
+
+ /* reset, irq gpio info */
+ rmi4_pdata->reset_gpio = of_get_named_gpio_flags(np,
+ "synaptics,reset-gpio", 0, &rmi4_pdata->reset_flags);
+ rmi4_pdata->irq_gpio = of_get_named_gpio_flags(np,
+ "synaptics,irq-gpio", 0, &rmi4_pdata->irq_flags);
+
+ rc = synaptics_dsx_get_dt_coords(dev, "synaptics,display-coords",
+ rmi4_pdata, NULL);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rc = synaptics_dsx_get_dt_coords(dev, "synaptics,panel-coords",
+ rmi4_pdata, NULL);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rmi4_pdata->detect_device = of_property_read_bool(np,
+ "synaptics,detect-device");
+
+ if (rmi4_pdata->detect_device)
+ return 0;
+
+ prop = of_find_property(np, "synaptics,button-map", NULL);
+ if (prop) {
+ num_buttons = prop->length / sizeof(temp_val);
+
+ rmi4_pdata->cap_button_map = devm_kzalloc(dev,
+ sizeof(*rmi4_pdata->cap_button_map),
+ GFP_KERNEL);
+ if (!rmi4_pdata->cap_button_map)
+ return -ENOMEM;
+
+ rmi4_pdata->cap_button_map->map = devm_kzalloc(dev,
+ sizeof(*rmi4_pdata->cap_button_map->map) *
+ MAX_NUMBER_OF_BUTTONS, GFP_KERNEL);
+ if (!rmi4_pdata->cap_button_map->map)
+ return -ENOMEM;
+
+ if (num_buttons <= MAX_NUMBER_OF_BUTTONS) {
+ rc = of_property_read_u32_array(np,
+ "synaptics,button-map", button_map,
+ num_buttons);
+ if (rc) {
+ dev_err(dev, "Unable to read key codes\n");
+ return rc;
+ }
+ for (i = 0; i < num_buttons; i++)
+ rmi4_pdata->cap_button_map->map[i] =
+ button_map[i];
+ rmi4_pdata->cap_button_map->nbuttons =
+ num_buttons;
+ } else {
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+#else
+static inline int synaptics_dsx_parse_dt(struct device *dev,
+ struct synaptics_dsx_board_data *rmi4_pdata)
+{
+ return 0;
+}
+#endif
+
+static int synaptics_rmi4_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ int retval;
+ struct synaptics_dsx_board_data *platform_data;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(&client->dev,
+ "%s: SMBus byte data commands not supported by host\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (client->dev.of_node) {
+ platform_data = devm_kzalloc(&client->dev,
+ sizeof(struct synaptics_dsx_board_data),
+ GFP_KERNEL);
+ if (!platform_data) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ retval = synaptics_dsx_parse_dt(&client->dev, platform_data);
+ if (retval)
+ return retval;
+ } else {
+ platform_data = client->dev.platform_data;
+ }
+
+ if (!platform_data) {
+ dev_err(&client->dev,
+ "%s: No platform data found\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ synaptics_dsx_i2c_device = kzalloc(
+ sizeof(struct platform_device),
+ GFP_KERNEL);
+ if (!synaptics_dsx_i2c_device) {
+ dev_err(&client->dev,
+ "%s: Failed to allocate memory for synaptics_dsx_i2c_device\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ hw_if.board_data = platform_data;
+ hw_if.bus_access = &bus_access;
+
+ synaptics_dsx_i2c_device->name = PLATFORM_DRIVER_NAME;
+ synaptics_dsx_i2c_device->id = 0;
+ synaptics_dsx_i2c_device->num_resources = 0;
+ synaptics_dsx_i2c_device->dev.parent = &client->dev;
+ synaptics_dsx_i2c_device->dev.platform_data = &hw_if;
+ synaptics_dsx_i2c_device->dev.release = synaptics_rmi4_i2c_dev_release;
+
+ retval = platform_device_register(synaptics_dsx_i2c_device);
+ if (retval) {
+ dev_err(&client->dev,
+ "%s: Failed to register platform device\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int synaptics_rmi4_i2c_remove(struct i2c_client *client)
+{
+ platform_device_unregister(synaptics_dsx_i2c_device);
+
+ return 0;
+}
+
+static const struct i2c_device_id synaptics_rmi4_id_table[] = {
+ {I2C_DRIVER_NAME, 0},
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table);
+
+#ifdef CONFIG_OF
+static struct of_device_id dsx_match_table[] = {
+ { .compatible = "synaptics,dsx",},
+ { },
+};
+#else
+#define dsx_match_table NULL
+#endif
+
+static struct i2c_driver synaptics_rmi4_i2c_driver = {
+ .driver = {
+ .name = I2C_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = dsx_match_table,
+ },
+ .probe = synaptics_rmi4_i2c_probe,
+ .remove = synaptics_rmi4_i2c_remove,
+ .id_table = synaptics_rmi4_id_table,
+};
+
+int synaptics_rmi4_bus_init(void)
+{
+ return i2c_add_driver(&synaptics_rmi4_i2c_driver);
+}
+EXPORT_SYMBOL(synaptics_rmi4_bus_init);
+
+void synaptics_rmi4_bus_exit(void)
+{
+ i2c_del_driver(&synaptics_rmi4_i2c_driver);
+
+ return;
+}
+EXPORT_SYMBOL(synaptics_rmi4_bus_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("Synaptics DSX I2C Bus Support Module");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_spi.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_spi.c
new file mode 100755
index 000000000000..dd797eef3be1
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_spi.c
@@ -0,0 +1,335 @@
+/*
+ * Synaptics DSX touchscreen driver
+ *
+ * Copyright (C) 2012 Synaptics Incorporated
+ *
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/input/synaptics_dsx.h>
+#include "synaptics_dsx_core.h"
+
+#define SPI_READ 0x80
+#define SPI_WRITE 0x00
+
+static int synaptics_rmi4_spi_set_page(struct synaptics_rmi4_data *rmi4_data,
+ unsigned short addr)
+{
+ int retval;
+ unsigned int index;
+ unsigned int xfer_count = PAGE_SELECT_LEN + 1;
+ unsigned char txbuf[xfer_count];
+ unsigned char page;
+ struct spi_message msg;
+ struct spi_transfer xfers[xfer_count];
+ struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent);
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ page = ((addr >> 8) & ~MASK_7BIT);
+ if (page != rmi4_data->current_page) {
+ spi_message_init(&msg);
+
+ txbuf[0] = SPI_WRITE;
+ txbuf[1] = MASK_8BIT;
+ txbuf[2] = page;
+
+ for (index = 0; index < xfer_count; index++) {
+ memset(&xfers[index], 0, sizeof(struct spi_transfer));
+ xfers[index].len = 1;
+ xfers[index].delay_usecs = bdata->byte_delay_us;
+ xfers[index].tx_buf = &txbuf[index];
+ spi_message_add_tail(&xfers[index], &msg);
+ }
+
+ if (bdata->block_delay_us)
+ xfers[index - 1].delay_usecs = bdata->block_delay_us;
+
+ retval = spi_sync(spi, &msg);
+ if (retval == 0) {
+ rmi4_data->current_page = page;
+ retval = PAGE_SELECT_LEN;
+ } else {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to complete SPI transfer, error = %d\n",
+ __func__, retval);
+ }
+ } else {
+ retval = PAGE_SELECT_LEN;
+ }
+
+ return retval;
+}
+
+static int synaptics_rmi4_spi_read(struct synaptics_rmi4_data *rmi4_data,
+ unsigned short addr, unsigned char *data, unsigned short length)
+{
+ int retval;
+ unsigned int index;
+ unsigned int xfer_count = length + ADDRESS_WORD_LEN;
+ unsigned char txbuf[ADDRESS_WORD_LEN];
+ unsigned char *rxbuf = NULL;
+ struct spi_message msg;
+ struct spi_transfer *xfers = NULL;
+ struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent);
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ spi_message_init(&msg);
+
+ xfers = kcalloc(xfer_count, sizeof(struct spi_transfer), GFP_KERNEL);
+ if (!xfers) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to allocate memory for xfers\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ txbuf[0] = (addr >> 8) | SPI_READ;
+ txbuf[1] = addr & MASK_8BIT;
+
+ rxbuf = kmalloc(length, GFP_KERNEL);
+ if (!rxbuf) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to allocate memory for rxbuf\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+ retval = synaptics_rmi4_spi_set_page(rmi4_data, addr);
+ if (retval != PAGE_SELECT_LEN) {
+ retval = -EIO;
+ goto exit;
+ }
+
+ for (index = 0; index < xfer_count; index++) {
+ xfers[index].len = 1;
+ xfers[index].delay_usecs = bdata->byte_delay_us;
+ if (index < ADDRESS_WORD_LEN)
+ xfers[index].tx_buf = &txbuf[index];
+ else
+ xfers[index].rx_buf = &rxbuf[index - ADDRESS_WORD_LEN];
+ spi_message_add_tail(&xfers[index], &msg);
+ }
+
+ if (bdata->block_delay_us)
+ xfers[index - 1].delay_usecs = bdata->block_delay_us;
+
+ retval = spi_sync(spi, &msg);
+ if (retval == 0) {
+ retval = length;
+ memcpy(data, rxbuf, length);
+ } else {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to complete SPI transfer, error = %d\n",
+ __func__, retval);
+ }
+
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+exit:
+ kfree(rxbuf);
+ kfree(xfers);
+
+ return retval;
+}
+
+static int synaptics_rmi4_spi_write(struct synaptics_rmi4_data *rmi4_data,
+ unsigned short addr, unsigned char *data, unsigned short length)
+{
+ int retval;
+ unsigned int index;
+ unsigned int xfer_count = length + ADDRESS_WORD_LEN;
+ unsigned char *txbuf = NULL;
+ struct spi_message msg;
+ struct spi_transfer *xfers = NULL;
+ struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent);
+ const struct synaptics_dsx_board_data *bdata =
+ rmi4_data->hw_if->board_data;
+
+ spi_message_init(&msg);
+
+ xfers = kcalloc(xfer_count, sizeof(struct spi_transfer), GFP_KERNEL);
+ if (!xfers) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to allocate memory for xfers\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ txbuf = kmalloc(xfer_count, GFP_KERNEL);
+ if (!txbuf) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to allocate memory for txbuf\n",
+ __func__);
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ txbuf[0] = (addr >> 8) & ~SPI_READ;
+ txbuf[1] = addr & MASK_8BIT;
+ memcpy(&txbuf[ADDRESS_WORD_LEN], data, length);
+
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+ retval = synaptics_rmi4_spi_set_page(rmi4_data, addr);
+ if (retval != PAGE_SELECT_LEN) {
+ retval = -EIO;
+ goto exit;
+ }
+
+ for (index = 0; index < xfer_count; index++) {
+ xfers[index].len = 1;
+ xfers[index].delay_usecs = bdata->byte_delay_us;
+ xfers[index].tx_buf = &txbuf[index];
+ spi_message_add_tail(&xfers[index], &msg);
+ }
+
+ if (bdata->block_delay_us)
+ xfers[index - 1].delay_usecs = bdata->block_delay_us;
+
+ retval = spi_sync(spi, &msg);
+ if (retval == 0) {
+ retval = length;
+ } else {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to complete SPI transfer, error = %d\n",
+ __func__, retval);
+ }
+
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+exit:
+ kfree(txbuf);
+ kfree(xfers);
+
+ return retval;
+}
+
+static struct synaptics_dsx_bus_access bus_access = {
+ .type = BUS_SPI,
+ .read = synaptics_rmi4_spi_read,
+ .write = synaptics_rmi4_spi_write,
+};
+
+static struct synaptics_dsx_hw_interface hw_if;
+
+static struct platform_device *synaptics_dsx_spi_device;
+
+static void synaptics_rmi4_spi_dev_release(struct device *dev)
+{
+ kfree(synaptics_dsx_spi_device);
+
+ return;
+}
+
+static int synaptics_rmi4_spi_probe(struct spi_device *spi)
+{
+ int retval;
+
+ if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) {
+ dev_err(&spi->dev,
+ "%s: Full duplex not supported by host\n",
+ __func__);
+ return -EIO;
+ }
+
+ synaptics_dsx_spi_device = kzalloc(
+ sizeof(struct platform_device),
+ GFP_KERNEL);
+ if (!synaptics_dsx_spi_device) {
+ dev_err(&spi->dev,
+ "%s: Failed to allocate memory for synaptics_dsx_spi_device\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ spi->bits_per_word = 8;
+ spi->mode = SPI_MODE_3;
+
+ retval = spi_setup(spi);
+ if (retval < 0) {
+ dev_err(&spi->dev,
+ "%s: Failed to perform SPI setup\n",
+ __func__);
+ return retval;
+ }
+
+ hw_if.board_data = spi->dev.platform_data;
+ hw_if.bus_access = &bus_access;
+
+ synaptics_dsx_spi_device->name = PLATFORM_DRIVER_NAME;
+ synaptics_dsx_spi_device->id = 0;
+ synaptics_dsx_spi_device->num_resources = 0;
+ synaptics_dsx_spi_device->dev.parent = &spi->dev;
+ synaptics_dsx_spi_device->dev.platform_data = &hw_if;
+ synaptics_dsx_spi_device->dev.release = synaptics_rmi4_spi_dev_release;
+
+ retval = platform_device_register(synaptics_dsx_spi_device);
+ if (retval) {
+ dev_err(&spi->dev,
+ "%s: Failed to register platform device\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int synaptics_rmi4_spi_remove(struct spi_device *spi)
+{
+ platform_device_unregister(synaptics_dsx_spi_device);
+
+ return 0;
+}
+
+static struct spi_driver synaptics_rmi4_spi_driver = {
+ .driver = {
+ .name = SPI_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = synaptics_rmi4_spi_probe,
+ .remove = __devexit_p(synaptics_rmi4_spi_remove),
+};
+
+
+int synaptics_rmi4_bus_init(void)
+{
+ return spi_register_driver(&synaptics_rmi4_spi_driver);
+}
+EXPORT_SYMBOL(synaptics_rmi4_bus_init);
+
+void synaptics_rmi4_bus_exit(void)
+{
+ spi_unregister_driver(&synaptics_rmi4_spi_driver);
+
+ return;
+}
+EXPORT_SYMBOL(synaptics_rmi4_bus_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("Synaptics DSX SPI Bus Support Module");
+MODULE_LICENSE("GPL v2");