summaryrefslogtreecommitdiff
path: root/drivers/sensor
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
committerYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
commit8e4bff4cab0ddac6060645b0715210484d02ff40 (patch)
tree3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/sensor
Initial file dump from open source releaseHEADmaster
Diffstat (limited to 'drivers/sensor')
-rw-r--r--drivers/sensor/Kconfig40
-rw-r--r--drivers/sensor/Makefile11
-rw-r--r--drivers/sensor/bma2x2_driver.c6194
-rw-r--r--drivers/sensor/bmm050.c1159
-rw-r--r--drivers/sensor/bmm050.h580
-rw-r--r--drivers/sensor/bmm050_driver.c1593
-rw-r--r--drivers/sensor/bs_log.h62
-rw-r--r--drivers/sensor/bst_sensor_common.c56
-rw-r--r--drivers/sensor/gp2ap002a00f.c647
-rw-r--r--drivers/sensor/k2hh.c1523
-rw-r--r--drivers/sensor/sensors_core.c110
11 files changed, 11975 insertions, 0 deletions
diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig
new file mode 100644
index 00000000..00b0762c
--- /dev/null
+++ b/drivers/sensor/Kconfig
@@ -0,0 +1,40 @@
+menu "Sensor support"
+
+config SENSORS
+ bool "Support for sensors"
+ help
+ Say Y here to add support for accelerometer sensors
+
+if SENSORS
+
+config SENSORS_GP2A
+ tristate "Sharp GP2AP002A00F I2C Proximity/Opto sensor driver"
+ depends on I2C
+ help
+ Say Y here if you have a Sharp GP2AP002A00F proximity/als combo-chip
+ hooked to an I2C bus.
+ To compile this driver as a module, choose M here: the
+ module will be called gp2ap002a00f.
+
+config SENSORS_BMA2X2
+ tristate "BMA255/BMA250E/BMA222E/BMA280 acceleration sensor support"
+ depends on I2C
+ help
+ If you say yes here you get support for Bosch Sensortec's
+ acceleration sensors BMA255/BMA250E/BMA222E/BMA280.
+
+
+config SENSORS_BMM050
+ tristate "BMM050 Magnetic Sensor Driver"
+ depends on I2C
+ help
+ BMM050 Magnetic Sensor Driver implemented by Bosch-Sensortec.
+
+config SENSORS_K2HH
+ tristate "k2hh accelerometer sensor driver"
+ depends on I2C
+ help
+ k2hh accelerometer sensor driver.
+
+endif
+endmenu
diff --git a/drivers/sensor/Makefile b/drivers/sensor/Makefile
new file mode 100644
index 00000000..d1fe411b
--- /dev/null
+++ b/drivers/sensor/Makefile
@@ -0,0 +1,11 @@
+EXTRA_CFLAGS += -DBMA2X2_SENSOR_IDENTIFICATION_ENABLE
+EXTRA_CFLAGS += -DCONFIG_BMA_USE_PLATFORM_DATA
+
+EXTRA_CFLAGS += -DBMM_USE_BASIC_I2C_FUNC
+EXTRA_CFLAGS += -DCONFIG_BMM_USE_PLATFORM_DATA
+
+obj-$(CONFIG_SENSORS_GP2A) += gp2ap002a00f.o
+obj-$(CONFIG_SENSORS_BMA2X2) += bma2x2_driver.o
+obj-$(CONFIG_SENSORS_K2HH) += k2hh.o
+obj-$(CONFIG_SENSORS_BMM050) += bmm050_driver.o bmm050.o
+obj-y += bst_sensor_common.o sensors_core.o
diff --git a/drivers/sensor/bma2x2_driver.c b/drivers/sensor/bma2x2_driver.c
new file mode 100644
index 00000000..0bcfaa68
--- /dev/null
+++ b/drivers/sensor/bma2x2_driver.c
@@ -0,0 +1,6194 @@
+/* Date: 2013/06/17 22:13:00
+ * Revision: 1.7.2
+ */
+
+/*
+ * 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
+
+ * (C) Copyright 2011 Bosch Sensortec GmbH
+ * All Rights Reserved
+ */
+
+
+/* file BMA2X2.c
+ brief This file contains all function implementations for the BMA2X2 in linux
+
+*/
+
+#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 <linux/fs.h>
+#include <linux/uaccess.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/sensors_core.h>
+#include <linux/bst_sensor_common.h>
+
+
+#define SENSOR_NAME "bma2x2"
+#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 BMA2X2_MAX_DELAY 200
+#define BMA2X2_RANGE_SET 3 /* +/- 2G */
+#define BMA2X2_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 BMA2X2_EEP_OFFSET 0x16
+#define BMA2X2_IMAGE_BASE 0x38
+#define BMA2X2_IMAGE_LEN 22
+
+
+#define BMA2X2_CHIP_ID_REG 0x00
+#define BMA2X2_VERSION_REG 0x01
+#define BMA2X2_X_AXIS_LSB_REG 0x02
+#define BMA2X2_X_AXIS_MSB_REG 0x03
+#define BMA2X2_Y_AXIS_LSB_REG 0x04
+#define BMA2X2_Y_AXIS_MSB_REG 0x05
+#define BMA2X2_Z_AXIS_LSB_REG 0x06
+#define BMA2X2_Z_AXIS_MSB_REG 0x07
+#define BMA2X2_TEMPERATURE_REG 0x08
+#define BMA2X2_STATUS1_REG 0x09
+#define BMA2X2_STATUS2_REG 0x0A
+#define BMA2X2_STATUS_TAP_SLOPE_REG 0x0B
+#define BMA2X2_STATUS_ORIENT_HIGH_REG 0x0C
+#define BMA2X2_STATUS_FIFO_REG 0x0E
+#define BMA2X2_RANGE_SEL_REG 0x0F
+#define BMA2X2_BW_SEL_REG 0x10
+#define BMA2X2_MODE_CTRL_REG 0x11
+#define BMA2X2_LOW_NOISE_CTRL_REG 0x12
+#define BMA2X2_DATA_CTRL_REG 0x13
+#define BMA2X2_RESET_REG 0x14
+#define BMA2X2_INT_ENABLE1_REG 0x16
+#define BMA2X2_INT_ENABLE2_REG 0x17
+#define BMA2X2_INT_SLO_NO_MOT_REG 0x18
+#define BMA2X2_INT1_PAD_SEL_REG 0x19
+#define BMA2X2_INT_DATA_SEL_REG 0x1A
+#define BMA2X2_INT2_PAD_SEL_REG 0x1B
+#define BMA2X2_INT_SRC_REG 0x1E
+#define BMA2X2_INT_SET_REG 0x20
+#define BMA2X2_INT_CTRL_REG 0x21
+#define BMA2X2_LOW_DURN_REG 0x22
+#define BMA2X2_LOW_THRES_REG 0x23
+#define BMA2X2_LOW_HIGH_HYST_REG 0x24
+#define BMA2X2_HIGH_DURN_REG 0x25
+#define BMA2X2_HIGH_THRES_REG 0x26
+#define BMA2X2_SLOPE_DURN_REG 0x27
+#define BMA2X2_SLOPE_THRES_REG 0x28
+#define BMA2X2_SLO_NO_MOT_THRES_REG 0x29
+#define BMA2X2_TAP_PARAM_REG 0x2A
+#define BMA2X2_TAP_THRES_REG 0x2B
+#define BMA2X2_ORIENT_PARAM_REG 0x2C
+#define BMA2X2_THETA_BLOCK_REG 0x2D
+#define BMA2X2_THETA_FLAT_REG 0x2E
+#define BMA2X2_FLAT_HOLD_TIME_REG 0x2F
+#define BMA2X2_FIFO_WML_TRIG 0x30
+#define BMA2X2_SELF_TEST_REG 0x32
+#define BMA2X2_EEPROM_CTRL_REG 0x33
+#define BMA2X2_SERIAL_CTRL_REG 0x34
+#define BMA2X2_EXTMODE_CTRL_REG 0x35
+#define BMA2X2_OFFSET_CTRL_REG 0x36
+#define BMA2X2_OFFSET_PARAMS_REG 0x37
+#define BMA2X2_OFFSET_X_AXIS_REG 0x38
+#define BMA2X2_OFFSET_Y_AXIS_REG 0x39
+#define BMA2X2_OFFSET_Z_AXIS_REG 0x3A
+#define BMA2X2_GP0_REG 0x3B
+#define BMA2X2_GP1_REG 0x3C
+#define BMA2X2_FIFO_MODE_REG 0x3E
+#define BMA2X2_FIFO_DATA_OUTPUT_REG 0x3F
+
+
+
+
+#define BMA2X2_CHIP_ID__POS 0
+#define BMA2X2_CHIP_ID__MSK 0xFF
+#define BMA2X2_CHIP_ID__LEN 8
+#define BMA2X2_CHIP_ID__REG BMA2X2_CHIP_ID_REG
+
+#define BMA2X2_VERSION__POS 0
+#define BMA2X2_VERSION__LEN 8
+#define BMA2X2_VERSION__MSK 0xFF
+#define BMA2X2_VERSION__REG BMA2X2_VERSION_REG
+
+#define BMA2x2_SLO_NO_MOT_DUR__POS 2
+#define BMA2x2_SLO_NO_MOT_DUR__LEN 6
+#define BMA2x2_SLO_NO_MOT_DUR__MSK 0xFC
+#define BMA2x2_SLO_NO_MOT_DUR__REG BMA2X2_SLOPE_DURN_REG
+
+#define BMA2X2_NEW_DATA_X__POS 0
+#define BMA2X2_NEW_DATA_X__LEN 1
+#define BMA2X2_NEW_DATA_X__MSK 0x01
+#define BMA2X2_NEW_DATA_X__REG BMA2X2_X_AXIS_LSB_REG
+
+#define BMA2X2_ACC_X14_LSB__POS 2
+#define BMA2X2_ACC_X14_LSB__LEN 6
+#define BMA2X2_ACC_X14_LSB__MSK 0xFC
+#define BMA2X2_ACC_X14_LSB__REG BMA2X2_X_AXIS_LSB_REG
+
+#define BMA2X2_ACC_X12_LSB__POS 4
+#define BMA2X2_ACC_X12_LSB__LEN 4
+#define BMA2X2_ACC_X12_LSB__MSK 0xF0
+#define BMA2X2_ACC_X12_LSB__REG BMA2X2_X_AXIS_LSB_REG
+
+#define BMA2X2_ACC_X10_LSB__POS 6
+#define BMA2X2_ACC_X10_LSB__LEN 2
+#define BMA2X2_ACC_X10_LSB__MSK 0xC0
+#define BMA2X2_ACC_X10_LSB__REG BMA2X2_X_AXIS_LSB_REG
+
+#define BMA2X2_ACC_X8_LSB__POS 0
+#define BMA2X2_ACC_X8_LSB__LEN 0
+#define BMA2X2_ACC_X8_LSB__MSK 0x00
+#define BMA2X2_ACC_X8_LSB__REG BMA2X2_X_AXIS_LSB_REG
+
+#define BMA2X2_ACC_X_MSB__POS 0
+#define BMA2X2_ACC_X_MSB__LEN 8
+#define BMA2X2_ACC_X_MSB__MSK 0xFF
+#define BMA2X2_ACC_X_MSB__REG BMA2X2_X_AXIS_MSB_REG
+
+#define BMA2X2_NEW_DATA_Y__POS 0
+#define BMA2X2_NEW_DATA_Y__LEN 1
+#define BMA2X2_NEW_DATA_Y__MSK 0x01
+#define BMA2X2_NEW_DATA_Y__REG BMA2X2_Y_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Y14_LSB__POS 2
+#define BMA2X2_ACC_Y14_LSB__LEN 6
+#define BMA2X2_ACC_Y14_LSB__MSK 0xFC
+#define BMA2X2_ACC_Y14_LSB__REG BMA2X2_Y_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Y12_LSB__POS 4
+#define BMA2X2_ACC_Y12_LSB__LEN 4
+#define BMA2X2_ACC_Y12_LSB__MSK 0xF0
+#define BMA2X2_ACC_Y12_LSB__REG BMA2X2_Y_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Y10_LSB__POS 6
+#define BMA2X2_ACC_Y10_LSB__LEN 2
+#define BMA2X2_ACC_Y10_LSB__MSK 0xC0
+#define BMA2X2_ACC_Y10_LSB__REG BMA2X2_Y_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Y8_LSB__POS 0
+#define BMA2X2_ACC_Y8_LSB__LEN 0
+#define BMA2X2_ACC_Y8_LSB__MSK 0x00
+#define BMA2X2_ACC_Y8_LSB__REG BMA2X2_Y_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Y_MSB__POS 0
+#define BMA2X2_ACC_Y_MSB__LEN 8
+#define BMA2X2_ACC_Y_MSB__MSK 0xFF
+#define BMA2X2_ACC_Y_MSB__REG BMA2X2_Y_AXIS_MSB_REG
+
+#define BMA2X2_NEW_DATA_Z__POS 0
+#define BMA2X2_NEW_DATA_Z__LEN 1
+#define BMA2X2_NEW_DATA_Z__MSK 0x01
+#define BMA2X2_NEW_DATA_Z__REG BMA2X2_Z_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Z14_LSB__POS 2
+#define BMA2X2_ACC_Z14_LSB__LEN 6
+#define BMA2X2_ACC_Z14_LSB__MSK 0xFC
+#define BMA2X2_ACC_Z14_LSB__REG BMA2X2_Z_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Z12_LSB__POS 4
+#define BMA2X2_ACC_Z12_LSB__LEN 4
+#define BMA2X2_ACC_Z12_LSB__MSK 0xF0
+#define BMA2X2_ACC_Z12_LSB__REG BMA2X2_Z_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Z10_LSB__POS 6
+#define BMA2X2_ACC_Z10_LSB__LEN 2
+#define BMA2X2_ACC_Z10_LSB__MSK 0xC0
+#define BMA2X2_ACC_Z10_LSB__REG BMA2X2_Z_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Z8_LSB__POS 0
+#define BMA2X2_ACC_Z8_LSB__LEN 0
+#define BMA2X2_ACC_Z8_LSB__MSK 0x00
+#define BMA2X2_ACC_Z8_LSB__REG BMA2X2_Z_AXIS_LSB_REG
+
+#define BMA2X2_ACC_Z_MSB__POS 0
+#define BMA2X2_ACC_Z_MSB__LEN 8
+#define BMA2X2_ACC_Z_MSB__MSK 0xFF
+#define BMA2X2_ACC_Z_MSB__REG BMA2X2_Z_AXIS_MSB_REG
+
+#define BMA2X2_TEMPERATURE__POS 0
+#define BMA2X2_TEMPERATURE__LEN 8
+#define BMA2X2_TEMPERATURE__MSK 0xFF
+#define BMA2X2_TEMPERATURE__REG BMA2X2_TEMP_RD_REG
+
+#define BMA2X2_LOWG_INT_S__POS 0
+#define BMA2X2_LOWG_INT_S__LEN 1
+#define BMA2X2_LOWG_INT_S__MSK 0x01
+#define BMA2X2_LOWG_INT_S__REG BMA2X2_STATUS1_REG
+
+#define BMA2X2_HIGHG_INT_S__POS 1
+#define BMA2X2_HIGHG_INT_S__LEN 1
+#define BMA2X2_HIGHG_INT_S__MSK 0x02
+#define BMA2X2_HIGHG_INT_S__REG BMA2X2_STATUS1_REG
+
+#define BMA2X2_SLOPE_INT_S__POS 2
+#define BMA2X2_SLOPE_INT_S__LEN 1
+#define BMA2X2_SLOPE_INT_S__MSK 0x04
+#define BMA2X2_SLOPE_INT_S__REG BMA2X2_STATUS1_REG
+
+
+#define BMA2X2_SLO_NO_MOT_INT_S__POS 3
+#define BMA2X2_SLO_NO_MOT_INT_S__LEN 1
+#define BMA2X2_SLO_NO_MOT_INT_S__MSK 0x08
+#define BMA2X2_SLO_NO_MOT_INT_S__REG BMA2X2_STATUS1_REG
+
+#define BMA2X2_DOUBLE_TAP_INT_S__POS 4
+#define BMA2X2_DOUBLE_TAP_INT_S__LEN 1
+#define BMA2X2_DOUBLE_TAP_INT_S__MSK 0x10
+#define BMA2X2_DOUBLE_TAP_INT_S__REG BMA2X2_STATUS1_REG
+
+#define BMA2X2_SINGLE_TAP_INT_S__POS 5
+#define BMA2X2_SINGLE_TAP_INT_S__LEN 1
+#define BMA2X2_SINGLE_TAP_INT_S__MSK 0x20
+#define BMA2X2_SINGLE_TAP_INT_S__REG BMA2X2_STATUS1_REG
+
+#define BMA2X2_ORIENT_INT_S__POS 6
+#define BMA2X2_ORIENT_INT_S__LEN 1
+#define BMA2X2_ORIENT_INT_S__MSK 0x40
+#define BMA2X2_ORIENT_INT_S__REG BMA2X2_STATUS1_REG
+
+#define BMA2X2_FLAT_INT_S__POS 7
+#define BMA2X2_FLAT_INT_S__LEN 1
+#define BMA2X2_FLAT_INT_S__MSK 0x80
+#define BMA2X2_FLAT_INT_S__REG BMA2X2_STATUS1_REG
+
+#define BMA2X2_FIFO_FULL_INT_S__POS 5
+#define BMA2X2_FIFO_FULL_INT_S__LEN 1
+#define BMA2X2_FIFO_FULL_INT_S__MSK 0x20
+#define BMA2X2_FIFO_FULL_INT_S__REG BMA2X2_STATUS2_REG
+
+#define BMA2X2_FIFO_WM_INT_S__POS 6
+#define BMA2X2_FIFO_WM_INT_S__LEN 1
+#define BMA2X2_FIFO_WM_INT_S__MSK 0x40
+#define BMA2X2_FIFO_WM_INT_S__REG BMA2X2_STATUS2_REG
+
+#define BMA2X2_DATA_INT_S__POS 7
+#define BMA2X2_DATA_INT_S__LEN 1
+#define BMA2X2_DATA_INT_S__MSK 0x80
+#define BMA2X2_DATA_INT_S__REG BMA2X2_STATUS2_REG
+
+#define BMA2X2_SLOPE_FIRST_X__POS 0
+#define BMA2X2_SLOPE_FIRST_X__LEN 1
+#define BMA2X2_SLOPE_FIRST_X__MSK 0x01
+#define BMA2X2_SLOPE_FIRST_X__REG BMA2X2_STATUS_TAP_SLOPE_REG
+
+#define BMA2X2_SLOPE_FIRST_Y__POS 1
+#define BMA2X2_SLOPE_FIRST_Y__LEN 1
+#define BMA2X2_SLOPE_FIRST_Y__MSK 0x02
+#define BMA2X2_SLOPE_FIRST_Y__REG BMA2X2_STATUS_TAP_SLOPE_REG
+
+#define BMA2X2_SLOPE_FIRST_Z__POS 2
+#define BMA2X2_SLOPE_FIRST_Z__LEN 1
+#define BMA2X2_SLOPE_FIRST_Z__MSK 0x04
+#define BMA2X2_SLOPE_FIRST_Z__REG BMA2X2_STATUS_TAP_SLOPE_REG
+
+#define BMA2X2_SLOPE_SIGN_S__POS 3
+#define BMA2X2_SLOPE_SIGN_S__LEN 1
+#define BMA2X2_SLOPE_SIGN_S__MSK 0x08
+#define BMA2X2_SLOPE_SIGN_S__REG BMA2X2_STATUS_TAP_SLOPE_REG
+
+#define BMA2X2_TAP_FIRST_X__POS 4
+#define BMA2X2_TAP_FIRST_X__LEN 1
+#define BMA2X2_TAP_FIRST_X__MSK 0x10
+#define BMA2X2_TAP_FIRST_X__REG BMA2X2_STATUS_TAP_SLOPE_REG
+
+#define BMA2X2_TAP_FIRST_Y__POS 5
+#define BMA2X2_TAP_FIRST_Y__LEN 1
+#define BMA2X2_TAP_FIRST_Y__MSK 0x20
+#define BMA2X2_TAP_FIRST_Y__REG BMA2X2_STATUS_TAP_SLOPE_REG
+
+#define BMA2X2_TAP_FIRST_Z__POS 6
+#define BMA2X2_TAP_FIRST_Z__LEN 1
+#define BMA2X2_TAP_FIRST_Z__MSK 0x40
+#define BMA2X2_TAP_FIRST_Z__REG BMA2X2_STATUS_TAP_SLOPE_REG
+
+#define BMA2X2_TAP_SIGN_S__POS 7
+#define BMA2X2_TAP_SIGN_S__LEN 1
+#define BMA2X2_TAP_SIGN_S__MSK 0x80
+#define BMA2X2_TAP_SIGN_S__REG BMA2X2_STATUS_TAP_SLOPE_REG
+
+#define BMA2X2_HIGHG_FIRST_X__POS 0
+#define BMA2X2_HIGHG_FIRST_X__LEN 1
+#define BMA2X2_HIGHG_FIRST_X__MSK 0x01
+#define BMA2X2_HIGHG_FIRST_X__REG BMA2X2_STATUS_ORIENT_HIGH_REG
+
+#define BMA2X2_HIGHG_FIRST_Y__POS 1
+#define BMA2X2_HIGHG_FIRST_Y__LEN 1
+#define BMA2X2_HIGHG_FIRST_Y__MSK 0x02
+#define BMA2X2_HIGHG_FIRST_Y__REG BMA2X2_STATUS_ORIENT_HIGH_REG
+
+#define BMA2X2_HIGHG_FIRST_Z__POS 2
+#define BMA2X2_HIGHG_FIRST_Z__LEN 1
+#define BMA2X2_HIGHG_FIRST_Z__MSK 0x04
+#define BMA2X2_HIGHG_FIRST_Z__REG BMA2X2_STATUS_ORIENT_HIGH_REG
+
+#define BMA2X2_HIGHG_SIGN_S__POS 3
+#define BMA2X2_HIGHG_SIGN_S__LEN 1
+#define BMA2X2_HIGHG_SIGN_S__MSK 0x08
+#define BMA2X2_HIGHG_SIGN_S__REG BMA2X2_STATUS_ORIENT_HIGH_REG
+
+#define BMA2X2_ORIENT_S__POS 4
+#define BMA2X2_ORIENT_S__LEN 3
+#define BMA2X2_ORIENT_S__MSK 0x70
+#define BMA2X2_ORIENT_S__REG BMA2X2_STATUS_ORIENT_HIGH_REG
+
+#define BMA2X2_FLAT_S__POS 7
+#define BMA2X2_FLAT_S__LEN 1
+#define BMA2X2_FLAT_S__MSK 0x80
+#define BMA2X2_FLAT_S__REG BMA2X2_STATUS_ORIENT_HIGH_REG
+
+#define BMA2X2_FIFO_FRAME_COUNTER_S__POS 0
+#define BMA2X2_FIFO_FRAME_COUNTER_S__LEN 7
+#define BMA2X2_FIFO_FRAME_COUNTER_S__MSK 0x7F
+#define BMA2X2_FIFO_FRAME_COUNTER_S__REG BMA2X2_STATUS_FIFO_REG
+
+#define BMA2X2_FIFO_OVERRUN_S__POS 7
+#define BMA2X2_FIFO_OVERRUN_S__LEN 1
+#define BMA2X2_FIFO_OVERRUN_S__MSK 0x80
+#define BMA2X2_FIFO_OVERRUN_S__REG BMA2X2_STATUS_FIFO_REG
+
+#define BMA2X2_RANGE_SEL__POS 0
+#define BMA2X2_RANGE_SEL__LEN 4
+#define BMA2X2_RANGE_SEL__MSK 0x0F
+#define BMA2X2_RANGE_SEL__REG BMA2X2_RANGE_SEL_REG
+
+#define BMA2X2_BANDWIDTH__POS 0
+#define BMA2X2_BANDWIDTH__LEN 5
+#define BMA2X2_BANDWIDTH__MSK 0x1F
+#define BMA2X2_BANDWIDTH__REG BMA2X2_BW_SEL_REG
+
+#define BMA2X2_SLEEP_DUR__POS 1
+#define BMA2X2_SLEEP_DUR__LEN 4
+#define BMA2X2_SLEEP_DUR__MSK 0x1E
+#define BMA2X2_SLEEP_DUR__REG BMA2X2_MODE_CTRL_REG
+
+#define BMA2X2_MODE_CTRL__POS 5
+#define BMA2X2_MODE_CTRL__LEN 3
+#define BMA2X2_MODE_CTRL__MSK 0xE0
+#define BMA2X2_MODE_CTRL__REG BMA2X2_MODE_CTRL_REG
+
+#define BMA2X2_DEEP_SUSPEND__POS 5
+#define BMA2X2_DEEP_SUSPEND__LEN 1
+#define BMA2X2_DEEP_SUSPEND__MSK 0x20
+#define BMA2X2_DEEP_SUSPEND__REG BMA2X2_MODE_CTRL_REG
+
+#define BMA2X2_EN_LOW_POWER__POS 6
+#define BMA2X2_EN_LOW_POWER__LEN 1
+#define BMA2X2_EN_LOW_POWER__MSK 0x40
+#define BMA2X2_EN_LOW_POWER__REG BMA2X2_MODE_CTRL_REG
+
+#define BMA2X2_EN_SUSPEND__POS 7
+#define BMA2X2_EN_SUSPEND__LEN 1
+#define BMA2X2_EN_SUSPEND__MSK 0x80
+#define BMA2X2_EN_SUSPEND__REG BMA2X2_MODE_CTRL_REG
+
+#define BMA2X2_SLEEP_TIMER__POS 5
+#define BMA2X2_SLEEP_TIMER__LEN 1
+#define BMA2X2_SLEEP_TIMER__MSK 0x20
+#define BMA2X2_SLEEP_TIMER__REG BMA2X2_LOW_NOISE_CTRL_REG
+
+#define BMA2X2_LOW_POWER_MODE__POS 6
+#define BMA2X2_LOW_POWER_MODE__LEN 1
+#define BMA2X2_LOW_POWER_MODE__MSK 0x40
+#define BMA2X2_LOW_POWER_MODE__REG BMA2X2_LOW_NOISE_CTRL_REG
+
+#define BMA2X2_EN_LOW_NOISE__POS 7
+#define BMA2X2_EN_LOW_NOISE__LEN 1
+#define BMA2X2_EN_LOW_NOISE__MSK 0x80
+#define BMA2X2_EN_LOW_NOISE__REG BMA2X2_LOW_NOISE_CTRL_REG
+
+#define BMA2X2_DIS_SHADOW_PROC__POS 6
+#define BMA2X2_DIS_SHADOW_PROC__LEN 1
+#define BMA2X2_DIS_SHADOW_PROC__MSK 0x40
+#define BMA2X2_DIS_SHADOW_PROC__REG BMA2X2_DATA_CTRL_REG
+
+#define BMA2X2_EN_DATA_HIGH_BW__POS 7
+#define BMA2X2_EN_DATA_HIGH_BW__LEN 1
+#define BMA2X2_EN_DATA_HIGH_BW__MSK 0x80
+#define BMA2X2_EN_DATA_HIGH_BW__REG BMA2X2_DATA_CTRL_REG
+
+#define BMA2X2_EN_SOFT_RESET__POS 0
+#define BMA2X2_EN_SOFT_RESET__LEN 8
+#define BMA2X2_EN_SOFT_RESET__MSK 0xFF
+#define BMA2X2_EN_SOFT_RESET__REG BMA2X2_RESET_REG
+
+#define BMA2X2_EN_SOFT_RESET_VALUE 0xB6
+
+#define BMA2X2_EN_SLOPE_X_INT__POS 0
+#define BMA2X2_EN_SLOPE_X_INT__LEN 1
+#define BMA2X2_EN_SLOPE_X_INT__MSK 0x01
+#define BMA2X2_EN_SLOPE_X_INT__REG BMA2X2_INT_ENABLE1_REG
+
+#define BMA2X2_EN_SLOPE_Y_INT__POS 1
+#define BMA2X2_EN_SLOPE_Y_INT__LEN 1
+#define BMA2X2_EN_SLOPE_Y_INT__MSK 0x02
+#define BMA2X2_EN_SLOPE_Y_INT__REG BMA2X2_INT_ENABLE1_REG
+
+#define BMA2X2_EN_SLOPE_Z_INT__POS 2
+#define BMA2X2_EN_SLOPE_Z_INT__LEN 1
+#define BMA2X2_EN_SLOPE_Z_INT__MSK 0x04
+#define BMA2X2_EN_SLOPE_Z_INT__REG BMA2X2_INT_ENABLE1_REG
+
+#define BMA2X2_EN_DOUBLE_TAP_INT__POS 4
+#define BMA2X2_EN_DOUBLE_TAP_INT__LEN 1
+#define BMA2X2_EN_DOUBLE_TAP_INT__MSK 0x10
+#define BMA2X2_EN_DOUBLE_TAP_INT__REG BMA2X2_INT_ENABLE1_REG
+
+#define BMA2X2_EN_SINGLE_TAP_INT__POS 5
+#define BMA2X2_EN_SINGLE_TAP_INT__LEN 1
+#define BMA2X2_EN_SINGLE_TAP_INT__MSK 0x20
+#define BMA2X2_EN_SINGLE_TAP_INT__REG BMA2X2_INT_ENABLE1_REG
+
+#define BMA2X2_EN_ORIENT_INT__POS 6
+#define BMA2X2_EN_ORIENT_INT__LEN 1
+#define BMA2X2_EN_ORIENT_INT__MSK 0x40
+#define BMA2X2_EN_ORIENT_INT__REG BMA2X2_INT_ENABLE1_REG
+
+#define BMA2X2_EN_FLAT_INT__POS 7
+#define BMA2X2_EN_FLAT_INT__LEN 1
+#define BMA2X2_EN_FLAT_INT__MSK 0x80
+#define BMA2X2_EN_FLAT_INT__REG BMA2X2_INT_ENABLE1_REG
+
+#define BMA2X2_EN_HIGHG_X_INT__POS 0
+#define BMA2X2_EN_HIGHG_X_INT__LEN 1
+#define BMA2X2_EN_HIGHG_X_INT__MSK 0x01
+#define BMA2X2_EN_HIGHG_X_INT__REG BMA2X2_INT_ENABLE2_REG
+
+#define BMA2X2_EN_HIGHG_Y_INT__POS 1
+#define BMA2X2_EN_HIGHG_Y_INT__LEN 1
+#define BMA2X2_EN_HIGHG_Y_INT__MSK 0x02
+#define BMA2X2_EN_HIGHG_Y_INT__REG BMA2X2_INT_ENABLE2_REG
+
+#define BMA2X2_EN_HIGHG_Z_INT__POS 2
+#define BMA2X2_EN_HIGHG_Z_INT__LEN 1
+#define BMA2X2_EN_HIGHG_Z_INT__MSK 0x04
+#define BMA2X2_EN_HIGHG_Z_INT__REG BMA2X2_INT_ENABLE2_REG
+
+#define BMA2X2_EN_LOWG_INT__POS 3
+#define BMA2X2_EN_LOWG_INT__LEN 1
+#define BMA2X2_EN_LOWG_INT__MSK 0x08
+#define BMA2X2_EN_LOWG_INT__REG BMA2X2_INT_ENABLE2_REG
+
+#define BMA2X2_EN_NEW_DATA_INT__POS 4
+#define BMA2X2_EN_NEW_DATA_INT__LEN 1
+#define BMA2X2_EN_NEW_DATA_INT__MSK 0x10
+#define BMA2X2_EN_NEW_DATA_INT__REG BMA2X2_INT_ENABLE2_REG
+
+#define BMA2X2_INT_FFULL_EN_INT__POS 5
+#define BMA2X2_INT_FFULL_EN_INT__LEN 1
+#define BMA2X2_INT_FFULL_EN_INT__MSK 0x20
+#define BMA2X2_INT_FFULL_EN_INT__REG BMA2X2_INT_ENABLE2_REG
+
+#define BMA2X2_INT_FWM_EN_INT__POS 6
+#define BMA2X2_INT_FWM_EN_INT__LEN 1
+#define BMA2X2_INT_FWM_EN_INT__MSK 0x40
+#define BMA2X2_INT_FWM_EN_INT__REG BMA2X2_INT_ENABLE2_REG
+
+#define BMA2X2_INT_SLO_NO_MOT_EN_X_INT__POS 0
+#define BMA2X2_INT_SLO_NO_MOT_EN_X_INT__LEN 1
+#define BMA2X2_INT_SLO_NO_MOT_EN_X_INT__MSK 0x01
+#define BMA2X2_INT_SLO_NO_MOT_EN_X_INT__REG BMA2X2_INT_SLO_NO_MOT_REG
+
+#define BMA2X2_INT_SLO_NO_MOT_EN_Y_INT__POS 1
+#define BMA2X2_INT_SLO_NO_MOT_EN_Y_INT__LEN 1
+#define BMA2X2_INT_SLO_NO_MOT_EN_Y_INT__MSK 0x02
+#define BMA2X2_INT_SLO_NO_MOT_EN_Y_INT__REG BMA2X2_INT_SLO_NO_MOT_REG
+
+#define BMA2X2_INT_SLO_NO_MOT_EN_Z_INT__POS 2
+#define BMA2X2_INT_SLO_NO_MOT_EN_Z_INT__LEN 1
+#define BMA2X2_INT_SLO_NO_MOT_EN_Z_INT__MSK 0x04
+#define BMA2X2_INT_SLO_NO_MOT_EN_Z_INT__REG BMA2X2_INT_SLO_NO_MOT_REG
+
+#define BMA2X2_INT_SLO_NO_MOT_EN_SEL_INT__POS 3
+#define BMA2X2_INT_SLO_NO_MOT_EN_SEL_INT__LEN 1
+#define BMA2X2_INT_SLO_NO_MOT_EN_SEL_INT__MSK 0x08
+#define BMA2X2_INT_SLO_NO_MOT_EN_SEL_INT__REG BMA2X2_INT_SLO_NO_MOT_REG
+
+#define BMA2X2_EN_INT1_PAD_LOWG__POS 0
+#define BMA2X2_EN_INT1_PAD_LOWG__LEN 1
+#define BMA2X2_EN_INT1_PAD_LOWG__MSK 0x01
+#define BMA2X2_EN_INT1_PAD_LOWG__REG BMA2X2_INT1_PAD_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_HIGHG__POS 1
+#define BMA2X2_EN_INT1_PAD_HIGHG__LEN 1
+#define BMA2X2_EN_INT1_PAD_HIGHG__MSK 0x02
+#define BMA2X2_EN_INT1_PAD_HIGHG__REG BMA2X2_INT1_PAD_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_SLOPE__POS 2
+#define BMA2X2_EN_INT1_PAD_SLOPE__LEN 1
+#define BMA2X2_EN_INT1_PAD_SLOPE__MSK 0x04
+#define BMA2X2_EN_INT1_PAD_SLOPE__REG BMA2X2_INT1_PAD_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_SLO_NO_MOT__POS 3
+#define BMA2X2_EN_INT1_PAD_SLO_NO_MOT__LEN 1
+#define BMA2X2_EN_INT1_PAD_SLO_NO_MOT__MSK 0x08
+#define BMA2X2_EN_INT1_PAD_SLO_NO_MOT__REG BMA2X2_INT1_PAD_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_DB_TAP__POS 4
+#define BMA2X2_EN_INT1_PAD_DB_TAP__LEN 1
+#define BMA2X2_EN_INT1_PAD_DB_TAP__MSK 0x10
+#define BMA2X2_EN_INT1_PAD_DB_TAP__REG BMA2X2_INT1_PAD_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_SNG_TAP__POS 5
+#define BMA2X2_EN_INT1_PAD_SNG_TAP__LEN 1
+#define BMA2X2_EN_INT1_PAD_SNG_TAP__MSK 0x20
+#define BMA2X2_EN_INT1_PAD_SNG_TAP__REG BMA2X2_INT1_PAD_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_ORIENT__POS 6
+#define BMA2X2_EN_INT1_PAD_ORIENT__LEN 1
+#define BMA2X2_EN_INT1_PAD_ORIENT__MSK 0x40
+#define BMA2X2_EN_INT1_PAD_ORIENT__REG BMA2X2_INT1_PAD_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_FLAT__POS 7
+#define BMA2X2_EN_INT1_PAD_FLAT__LEN 1
+#define BMA2X2_EN_INT1_PAD_FLAT__MSK 0x80
+#define BMA2X2_EN_INT1_PAD_FLAT__REG BMA2X2_INT1_PAD_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_LOWG__POS 0
+#define BMA2X2_EN_INT2_PAD_LOWG__LEN 1
+#define BMA2X2_EN_INT2_PAD_LOWG__MSK 0x01
+#define BMA2X2_EN_INT2_PAD_LOWG__REG BMA2X2_INT2_PAD_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_HIGHG__POS 1
+#define BMA2X2_EN_INT2_PAD_HIGHG__LEN 1
+#define BMA2X2_EN_INT2_PAD_HIGHG__MSK 0x02
+#define BMA2X2_EN_INT2_PAD_HIGHG__REG BMA2X2_INT2_PAD_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_SLOPE__POS 2
+#define BMA2X2_EN_INT2_PAD_SLOPE__LEN 1
+#define BMA2X2_EN_INT2_PAD_SLOPE__MSK 0x04
+#define BMA2X2_EN_INT2_PAD_SLOPE__REG BMA2X2_INT2_PAD_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_SLO_NO_MOT__POS 3
+#define BMA2X2_EN_INT2_PAD_SLO_NO_MOT__LEN 1
+#define BMA2X2_EN_INT2_PAD_SLO_NO_MOT__MSK 0x08
+#define BMA2X2_EN_INT2_PAD_SLO_NO_MOT__REG BMA2X2_INT2_PAD_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_DB_TAP__POS 4
+#define BMA2X2_EN_INT2_PAD_DB_TAP__LEN 1
+#define BMA2X2_EN_INT2_PAD_DB_TAP__MSK 0x10
+#define BMA2X2_EN_INT2_PAD_DB_TAP__REG BMA2X2_INT2_PAD_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_SNG_TAP__POS 5
+#define BMA2X2_EN_INT2_PAD_SNG_TAP__LEN 1
+#define BMA2X2_EN_INT2_PAD_SNG_TAP__MSK 0x20
+#define BMA2X2_EN_INT2_PAD_SNG_TAP__REG BMA2X2_INT2_PAD_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_ORIENT__POS 6
+#define BMA2X2_EN_INT2_PAD_ORIENT__LEN 1
+#define BMA2X2_EN_INT2_PAD_ORIENT__MSK 0x40
+#define BMA2X2_EN_INT2_PAD_ORIENT__REG BMA2X2_INT2_PAD_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_FLAT__POS 7
+#define BMA2X2_EN_INT2_PAD_FLAT__LEN 1
+#define BMA2X2_EN_INT2_PAD_FLAT__MSK 0x80
+#define BMA2X2_EN_INT2_PAD_FLAT__REG BMA2X2_INT2_PAD_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_NEWDATA__POS 0
+#define BMA2X2_EN_INT1_PAD_NEWDATA__LEN 1
+#define BMA2X2_EN_INT1_PAD_NEWDATA__MSK 0x01
+#define BMA2X2_EN_INT1_PAD_NEWDATA__REG BMA2X2_INT_DATA_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_FWM__POS 1
+#define BMA2X2_EN_INT1_PAD_FWM__LEN 1
+#define BMA2X2_EN_INT1_PAD_FWM__MSK 0x02
+#define BMA2X2_EN_INT1_PAD_FWM__REG BMA2X2_INT_DATA_SEL_REG
+
+#define BMA2X2_EN_INT1_PAD_FFULL__POS 2
+#define BMA2X2_EN_INT1_PAD_FFULL__LEN 1
+#define BMA2X2_EN_INT1_PAD_FFULL__MSK 0x04
+#define BMA2X2_EN_INT1_PAD_FFULL__REG BMA2X2_INT_DATA_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_FFULL__POS 5
+#define BMA2X2_EN_INT2_PAD_FFULL__LEN 1
+#define BMA2X2_EN_INT2_PAD_FFULL__MSK 0x20
+#define BMA2X2_EN_INT2_PAD_FFULL__REG BMA2X2_INT_DATA_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_FWM__POS 6
+#define BMA2X2_EN_INT2_PAD_FWM__LEN 1
+#define BMA2X2_EN_INT2_PAD_FWM__MSK 0x40
+#define BMA2X2_EN_INT2_PAD_FWM__REG BMA2X2_INT_DATA_SEL_REG
+
+#define BMA2X2_EN_INT2_PAD_NEWDATA__POS 7
+#define BMA2X2_EN_INT2_PAD_NEWDATA__LEN 1
+#define BMA2X2_EN_INT2_PAD_NEWDATA__MSK 0x80
+#define BMA2X2_EN_INT2_PAD_NEWDATA__REG BMA2X2_INT_DATA_SEL_REG
+
+#define BMA2X2_UNFILT_INT_SRC_LOWG__POS 0
+#define BMA2X2_UNFILT_INT_SRC_LOWG__LEN 1
+#define BMA2X2_UNFILT_INT_SRC_LOWG__MSK 0x01
+#define BMA2X2_UNFILT_INT_SRC_LOWG__REG BMA2X2_INT_SRC_REG
+
+#define BMA2X2_UNFILT_INT_SRC_HIGHG__POS 1
+#define BMA2X2_UNFILT_INT_SRC_HIGHG__LEN 1
+#define BMA2X2_UNFILT_INT_SRC_HIGHG__MSK 0x02
+#define BMA2X2_UNFILT_INT_SRC_HIGHG__REG BMA2X2_INT_SRC_REG
+
+#define BMA2X2_UNFILT_INT_SRC_SLOPE__POS 2
+#define BMA2X2_UNFILT_INT_SRC_SLOPE__LEN 1
+#define BMA2X2_UNFILT_INT_SRC_SLOPE__MSK 0x04
+#define BMA2X2_UNFILT_INT_SRC_SLOPE__REG BMA2X2_INT_SRC_REG
+
+#define BMA2X2_UNFILT_INT_SRC_SLO_NO_MOT__POS 3
+#define BMA2X2_UNFILT_INT_SRC_SLO_NO_MOT__LEN 1
+#define BMA2X2_UNFILT_INT_SRC_SLO_NO_MOT__MSK 0x08
+#define BMA2X2_UNFILT_INT_SRC_SLO_NO_MOT__REG BMA2X2_INT_SRC_REG
+
+#define BMA2X2_UNFILT_INT_SRC_TAP__POS 4
+#define BMA2X2_UNFILT_INT_SRC_TAP__LEN 1
+#define BMA2X2_UNFILT_INT_SRC_TAP__MSK 0x10
+#define BMA2X2_UNFILT_INT_SRC_TAP__REG BMA2X2_INT_SRC_REG
+
+#define BMA2X2_UNFILT_INT_SRC_DATA__POS 5
+#define BMA2X2_UNFILT_INT_SRC_DATA__LEN 1
+#define BMA2X2_UNFILT_INT_SRC_DATA__MSK 0x20
+#define BMA2X2_UNFILT_INT_SRC_DATA__REG BMA2X2_INT_SRC_REG
+
+#define BMA2X2_INT1_PAD_ACTIVE_LEVEL__POS 0
+#define BMA2X2_INT1_PAD_ACTIVE_LEVEL__LEN 1
+#define BMA2X2_INT1_PAD_ACTIVE_LEVEL__MSK 0x01
+#define BMA2X2_INT1_PAD_ACTIVE_LEVEL__REG BMA2X2_INT_SET_REG
+
+#define BMA2X2_INT2_PAD_ACTIVE_LEVEL__POS 2
+#define BMA2X2_INT2_PAD_ACTIVE_LEVEL__LEN 1
+#define BMA2X2_INT2_PAD_ACTIVE_LEVEL__MSK 0x04
+#define BMA2X2_INT2_PAD_ACTIVE_LEVEL__REG BMA2X2_INT_SET_REG
+
+#define BMA2X2_INT1_PAD_OUTPUT_TYPE__POS 1
+#define BMA2X2_INT1_PAD_OUTPUT_TYPE__LEN 1
+#define BMA2X2_INT1_PAD_OUTPUT_TYPE__MSK 0x02
+#define BMA2X2_INT1_PAD_OUTPUT_TYPE__REG BMA2X2_INT_SET_REG
+
+#define BMA2X2_INT2_PAD_OUTPUT_TYPE__POS 3
+#define BMA2X2_INT2_PAD_OUTPUT_TYPE__LEN 1
+#define BMA2X2_INT2_PAD_OUTPUT_TYPE__MSK 0x08
+#define BMA2X2_INT2_PAD_OUTPUT_TYPE__REG BMA2X2_INT_SET_REG
+
+#define BMA2X2_INT_MODE_SEL__POS 0
+#define BMA2X2_INT_MODE_SEL__LEN 4
+#define BMA2X2_INT_MODE_SEL__MSK 0x0F
+#define BMA2X2_INT_MODE_SEL__REG BMA2X2_INT_CTRL_REG
+
+#define BMA2X2_RESET_INT__POS 7
+#define BMA2X2_RESET_INT__LEN 1
+#define BMA2X2_RESET_INT__MSK 0x80
+#define BMA2X2_RESET_INT__REG BMA2X2_INT_CTRL_REG
+
+#define BMA2X2_LOWG_DUR__POS 0
+#define BMA2X2_LOWG_DUR__LEN 8
+#define BMA2X2_LOWG_DUR__MSK 0xFF
+#define BMA2X2_LOWG_DUR__REG BMA2X2_LOW_DURN_REG
+
+#define BMA2X2_LOWG_THRES__POS 0
+#define BMA2X2_LOWG_THRES__LEN 8
+#define BMA2X2_LOWG_THRES__MSK 0xFF
+#define BMA2X2_LOWG_THRES__REG BMA2X2_LOW_THRES_REG
+
+#define BMA2X2_LOWG_HYST__POS 0
+#define BMA2X2_LOWG_HYST__LEN 2
+#define BMA2X2_LOWG_HYST__MSK 0x03
+#define BMA2X2_LOWG_HYST__REG BMA2X2_LOW_HIGH_HYST_REG
+
+#define BMA2X2_LOWG_INT_MODE__POS 2
+#define BMA2X2_LOWG_INT_MODE__LEN 1
+#define BMA2X2_LOWG_INT_MODE__MSK 0x04
+#define BMA2X2_LOWG_INT_MODE__REG BMA2X2_LOW_HIGH_HYST_REG
+
+#define BMA2X2_HIGHG_DUR__POS 0
+#define BMA2X2_HIGHG_DUR__LEN 8
+#define BMA2X2_HIGHG_DUR__MSK 0xFF
+#define BMA2X2_HIGHG_DUR__REG BMA2X2_HIGH_DURN_REG
+
+#define BMA2X2_HIGHG_THRES__POS 0
+#define BMA2X2_HIGHG_THRES__LEN 8
+#define BMA2X2_HIGHG_THRES__MSK 0xFF
+#define BMA2X2_HIGHG_THRES__REG BMA2X2_HIGH_THRES_REG
+
+#define BMA2X2_HIGHG_HYST__POS 6
+#define BMA2X2_HIGHG_HYST__LEN 2
+#define BMA2X2_HIGHG_HYST__MSK 0xC0
+#define BMA2X2_HIGHG_HYST__REG BMA2X2_LOW_HIGH_HYST_REG
+
+#define BMA2X2_SLOPE_DUR__POS 0
+#define BMA2X2_SLOPE_DUR__LEN 2
+#define BMA2X2_SLOPE_DUR__MSK 0x03
+#define BMA2X2_SLOPE_DUR__REG BMA2X2_SLOPE_DURN_REG
+
+#define BMA2X2_SLO_NO_MOT_DUR__POS 2
+#define BMA2X2_SLO_NO_MOT_DUR__LEN 6
+#define BMA2X2_SLO_NO_MOT_DUR__MSK 0xFC
+#define BMA2X2_SLO_NO_MOT_DUR__REG BMA2X2_SLOPE_DURN_REG
+
+#define BMA2X2_SLOPE_THRES__POS 0
+#define BMA2X2_SLOPE_THRES__LEN 8
+#define BMA2X2_SLOPE_THRES__MSK 0xFF
+#define BMA2X2_SLOPE_THRES__REG BMA2X2_SLOPE_THRES_REG
+
+#define BMA2X2_SLO_NO_MOT_THRES__POS 0
+#define BMA2X2_SLO_NO_MOT_THRES__LEN 8
+#define BMA2X2_SLO_NO_MOT_THRES__MSK 0xFF
+#define BMA2X2_SLO_NO_MOT_THRES__REG BMA2X2_SLO_NO_MOT_THRES_REG
+
+#define BMA2X2_TAP_DUR__POS 0
+#define BMA2X2_TAP_DUR__LEN 3
+#define BMA2X2_TAP_DUR__MSK 0x07
+#define BMA2X2_TAP_DUR__REG BMA2X2_TAP_PARAM_REG
+
+#define BMA2X2_TAP_SHOCK_DURN__POS 6
+#define BMA2X2_TAP_SHOCK_DURN__LEN 1
+#define BMA2X2_TAP_SHOCK_DURN__MSK 0x40
+#define BMA2X2_TAP_SHOCK_DURN__REG BMA2X2_TAP_PARAM_REG
+
+#define BMA2X2_ADV_TAP_INT__POS 5
+#define BMA2X2_ADV_TAP_INT__LEN 1
+#define BMA2X2_ADV_TAP_INT__MSK 0x20
+#define BMA2X2_ADV_TAP_INT__REG BMA2X2_TAP_PARAM_REG
+
+#define BMA2X2_TAP_QUIET_DURN__POS 7
+#define BMA2X2_TAP_QUIET_DURN__LEN 1
+#define BMA2X2_TAP_QUIET_DURN__MSK 0x80
+#define BMA2X2_TAP_QUIET_DURN__REG BMA2X2_TAP_PARAM_REG
+
+#define BMA2X2_TAP_THRES__POS 0
+#define BMA2X2_TAP_THRES__LEN 5
+#define BMA2X2_TAP_THRES__MSK 0x1F
+#define BMA2X2_TAP_THRES__REG BMA2X2_TAP_THRES_REG
+
+#define BMA2X2_TAP_SAMPLES__POS 6
+#define BMA2X2_TAP_SAMPLES__LEN 2
+#define BMA2X2_TAP_SAMPLES__MSK 0xC0
+#define BMA2X2_TAP_SAMPLES__REG BMA2X2_TAP_THRES_REG
+
+#define BMA2X2_ORIENT_MODE__POS 0
+#define BMA2X2_ORIENT_MODE__LEN 2
+#define BMA2X2_ORIENT_MODE__MSK 0x03
+#define BMA2X2_ORIENT_MODE__REG BMA2X2_ORIENT_PARAM_REG
+
+#define BMA2X2_ORIENT_BLOCK__POS 2
+#define BMA2X2_ORIENT_BLOCK__LEN 2
+#define BMA2X2_ORIENT_BLOCK__MSK 0x0C
+#define BMA2X2_ORIENT_BLOCK__REG BMA2X2_ORIENT_PARAM_REG
+
+#define BMA2X2_ORIENT_HYST__POS 4
+#define BMA2X2_ORIENT_HYST__LEN 3
+#define BMA2X2_ORIENT_HYST__MSK 0x70
+#define BMA2X2_ORIENT_HYST__REG BMA2X2_ORIENT_PARAM_REG
+
+#define BMA2X2_ORIENT_AXIS__POS 7
+#define BMA2X2_ORIENT_AXIS__LEN 1
+#define BMA2X2_ORIENT_AXIS__MSK 0x80
+#define BMA2X2_ORIENT_AXIS__REG BMA2X2_THETA_BLOCK_REG
+
+#define BMA2X2_ORIENT_UD_EN__POS 6
+#define BMA2X2_ORIENT_UD_EN__LEN 1
+#define BMA2X2_ORIENT_UD_EN__MSK 0x40
+#define BMA2X2_ORIENT_UD_EN__REG BMA2X2_THETA_BLOCK_REG
+
+#define BMA2X2_THETA_BLOCK__POS 0
+#define BMA2X2_THETA_BLOCK__LEN 6
+#define BMA2X2_THETA_BLOCK__MSK 0x3F
+#define BMA2X2_THETA_BLOCK__REG BMA2X2_THETA_BLOCK_REG
+
+#define BMA2X2_THETA_FLAT__POS 0
+#define BMA2X2_THETA_FLAT__LEN 6
+#define BMA2X2_THETA_FLAT__MSK 0x3F
+#define BMA2X2_THETA_FLAT__REG BMA2X2_THETA_FLAT_REG
+
+#define BMA2X2_FLAT_HOLD_TIME__POS 4
+#define BMA2X2_FLAT_HOLD_TIME__LEN 2
+#define BMA2X2_FLAT_HOLD_TIME__MSK 0x30
+#define BMA2X2_FLAT_HOLD_TIME__REG BMA2X2_FLAT_HOLD_TIME_REG
+
+#define BMA2X2_FLAT_HYS__POS 0
+#define BMA2X2_FLAT_HYS__LEN 3
+#define BMA2X2_FLAT_HYS__MSK 0x07
+#define BMA2X2_FLAT_HYS__REG BMA2X2_FLAT_HOLD_TIME_REG
+
+#define BMA2X2_FIFO_WML_TRIG_RETAIN__POS 0
+#define BMA2X2_FIFO_WML_TRIG_RETAIN__LEN 6
+#define BMA2X2_FIFO_WML_TRIG_RETAIN__MSK 0x3F
+#define BMA2X2_FIFO_WML_TRIG_RETAIN__REG BMA2X2_FIFO_WML_TRIG
+
+#define BMA2X2_EN_SELF_TEST__POS 0
+#define BMA2X2_EN_SELF_TEST__LEN 2
+#define BMA2X2_EN_SELF_TEST__MSK 0x03
+#define BMA2X2_EN_SELF_TEST__REG BMA2X2_SELF_TEST_REG
+
+#define BMA2X2_NEG_SELF_TEST__POS 2
+#define BMA2X2_NEG_SELF_TEST__LEN 1
+#define BMA2X2_NEG_SELF_TEST__MSK 0x04
+#define BMA2X2_NEG_SELF_TEST__REG BMA2X2_SELF_TEST_REG
+
+#define BMA2X2_SELF_TEST_AMP__POS 4
+#define BMA2X2_SELF_TEST_AMP__LEN 1
+#define BMA2X2_SELF_TEST_AMP__MSK 0x10
+#define BMA2X2_SELF_TEST_AMP__REG BMA2X2_SELF_TEST_REG
+
+
+#define BMA2X2_UNLOCK_EE_PROG_MODE__POS 0
+#define BMA2X2_UNLOCK_EE_PROG_MODE__LEN 1
+#define BMA2X2_UNLOCK_EE_PROG_MODE__MSK 0x01
+#define BMA2X2_UNLOCK_EE_PROG_MODE__REG BMA2X2_EEPROM_CTRL_REG
+
+#define BMA2X2_START_EE_PROG_TRIG__POS 1
+#define BMA2X2_START_EE_PROG_TRIG__LEN 1
+#define BMA2X2_START_EE_PROG_TRIG__MSK 0x02
+#define BMA2X2_START_EE_PROG_TRIG__REG BMA2X2_EEPROM_CTRL_REG
+
+#define BMA2X2_EE_PROG_READY__POS 2
+#define BMA2X2_EE_PROG_READY__LEN 1
+#define BMA2X2_EE_PROG_READY__MSK 0x04
+#define BMA2X2_EE_PROG_READY__REG BMA2X2_EEPROM_CTRL_REG
+
+#define BMA2X2_UPDATE_IMAGE__POS 3
+#define BMA2X2_UPDATE_IMAGE__LEN 1
+#define BMA2X2_UPDATE_IMAGE__MSK 0x08
+#define BMA2X2_UPDATE_IMAGE__REG BMA2X2_EEPROM_CTRL_REG
+
+#define BMA2X2_EE_REMAIN__POS 4
+#define BMA2X2_EE_REMAIN__LEN 4
+#define BMA2X2_EE_REMAIN__MSK 0xF0
+#define BMA2X2_EE_REMAIN__REG BMA2X2_EEPROM_CTRL_REG
+
+#define BMA2X2_EN_SPI_MODE_3__POS 0
+#define BMA2X2_EN_SPI_MODE_3__LEN 1
+#define BMA2X2_EN_SPI_MODE_3__MSK 0x01
+#define BMA2X2_EN_SPI_MODE_3__REG BMA2X2_SERIAL_CTRL_REG
+
+#define BMA2X2_I2C_WATCHDOG_PERIOD__POS 1
+#define BMA2X2_I2C_WATCHDOG_PERIOD__LEN 1
+#define BMA2X2_I2C_WATCHDOG_PERIOD__MSK 0x02
+#define BMA2X2_I2C_WATCHDOG_PERIOD__REG BMA2X2_SERIAL_CTRL_REG
+
+#define BMA2X2_EN_I2C_WATCHDOG__POS 2
+#define BMA2X2_EN_I2C_WATCHDOG__LEN 1
+#define BMA2X2_EN_I2C_WATCHDOG__MSK 0x04
+#define BMA2X2_EN_I2C_WATCHDOG__REG BMA2X2_SERIAL_CTRL_REG
+
+#define BMA2X2_EXT_MODE__POS 7
+#define BMA2X2_EXT_MODE__LEN 1
+#define BMA2X2_EXT_MODE__MSK 0x80
+#define BMA2X2_EXT_MODE__REG BMA2X2_EXTMODE_CTRL_REG
+
+#define BMA2X2_ALLOW_UPPER__POS 6
+#define BMA2X2_ALLOW_UPPER__LEN 1
+#define BMA2X2_ALLOW_UPPER__MSK 0x40
+#define BMA2X2_ALLOW_UPPER__REG BMA2X2_EXTMODE_CTRL_REG
+
+#define BMA2X2_MAP_2_LOWER__POS 5
+#define BMA2X2_MAP_2_LOWER__LEN 1
+#define BMA2X2_MAP_2_LOWER__MSK 0x20
+#define BMA2X2_MAP_2_LOWER__REG BMA2X2_EXTMODE_CTRL_REG
+
+#define BMA2X2_MAGIC_NUMBER__POS 0
+#define BMA2X2_MAGIC_NUMBER__LEN 5
+#define BMA2X2_MAGIC_NUMBER__MSK 0x1F
+#define BMA2X2_MAGIC_NUMBER__REG BMA2X2_EXTMODE_CTRL_REG
+
+#define BMA2X2_UNLOCK_EE_WRITE_TRIM__POS 4
+#define BMA2X2_UNLOCK_EE_WRITE_TRIM__LEN 4
+#define BMA2X2_UNLOCK_EE_WRITE_TRIM__MSK 0xF0
+#define BMA2X2_UNLOCK_EE_WRITE_TRIM__REG BMA2X2_CTRL_UNLOCK_REG
+
+#define BMA2X2_EN_SLOW_COMP_X__POS 0
+#define BMA2X2_EN_SLOW_COMP_X__LEN 1
+#define BMA2X2_EN_SLOW_COMP_X__MSK 0x01
+#define BMA2X2_EN_SLOW_COMP_X__REG BMA2X2_OFFSET_CTRL_REG
+
+#define BMA2X2_EN_SLOW_COMP_Y__POS 1
+#define BMA2X2_EN_SLOW_COMP_Y__LEN 1
+#define BMA2X2_EN_SLOW_COMP_Y__MSK 0x02
+#define BMA2X2_EN_SLOW_COMP_Y__REG BMA2X2_OFFSET_CTRL_REG
+
+#define BMA2X2_EN_SLOW_COMP_Z__POS 2
+#define BMA2X2_EN_SLOW_COMP_Z__LEN 1
+#define BMA2X2_EN_SLOW_COMP_Z__MSK 0x04
+#define BMA2X2_EN_SLOW_COMP_Z__REG BMA2X2_OFFSET_CTRL_REG
+
+#define BMA2X2_FAST_CAL_RDY_S__POS 4
+#define BMA2X2_FAST_CAL_RDY_S__LEN 1
+#define BMA2X2_FAST_CAL_RDY_S__MSK 0x10
+#define BMA2X2_FAST_CAL_RDY_S__REG BMA2X2_OFFSET_CTRL_REG
+
+#define BMA2X2_CAL_TRIGGER__POS 5
+#define BMA2X2_CAL_TRIGGER__LEN 2
+#define BMA2X2_CAL_TRIGGER__MSK 0x60
+#define BMA2X2_CAL_TRIGGER__REG BMA2X2_OFFSET_CTRL_REG
+
+#define BMA2X2_RESET_OFFSET_REGS__POS 7
+#define BMA2X2_RESET_OFFSET_REGS__LEN 1
+#define BMA2X2_RESET_OFFSET_REGS__MSK 0x80
+#define BMA2X2_RESET_OFFSET_REGS__REG BMA2X2_OFFSET_CTRL_REG
+
+#define BMA2X2_COMP_CUTOFF__POS 0
+#define BMA2X2_COMP_CUTOFF__LEN 1
+#define BMA2X2_COMP_CUTOFF__MSK 0x01
+#define BMA2X2_COMP_CUTOFF__REG BMA2X2_OFFSET_PARAMS_REG
+
+#define BMA2X2_COMP_TARGET_OFFSET_X__POS 1
+#define BMA2X2_COMP_TARGET_OFFSET_X__LEN 2
+#define BMA2X2_COMP_TARGET_OFFSET_X__MSK 0x06
+#define BMA2X2_COMP_TARGET_OFFSET_X__REG BMA2X2_OFFSET_PARAMS_REG
+
+#define BMA2X2_COMP_TARGET_OFFSET_Y__POS 3
+#define BMA2X2_COMP_TARGET_OFFSET_Y__LEN 2
+#define BMA2X2_COMP_TARGET_OFFSET_Y__MSK 0x18
+#define BMA2X2_COMP_TARGET_OFFSET_Y__REG BMA2X2_OFFSET_PARAMS_REG
+
+#define BMA2X2_COMP_TARGET_OFFSET_Z__POS 5
+#define BMA2X2_COMP_TARGET_OFFSET_Z__LEN 2
+#define BMA2X2_COMP_TARGET_OFFSET_Z__MSK 0x60
+#define BMA2X2_COMP_TARGET_OFFSET_Z__REG BMA2X2_OFFSET_PARAMS_REG
+
+#define BMA2X2_FIFO_DATA_SELECT__POS 0
+#define BMA2X2_FIFO_DATA_SELECT__LEN 2
+#define BMA2X2_FIFO_DATA_SELECT__MSK 0x03
+#define BMA2X2_FIFO_DATA_SELECT__REG BMA2X2_FIFO_MODE_REG
+
+#define BMA2X2_FIFO_TRIGGER_SOURCE__POS 2
+#define BMA2X2_FIFO_TRIGGER_SOURCE__LEN 2
+#define BMA2X2_FIFO_TRIGGER_SOURCE__MSK 0x0C
+#define BMA2X2_FIFO_TRIGGER_SOURCE__REG BMA2X2_FIFO_MODE_REG
+
+#define BMA2X2_FIFO_TRIGGER_ACTION__POS 4
+#define BMA2X2_FIFO_TRIGGER_ACTION__LEN 2
+#define BMA2X2_FIFO_TRIGGER_ACTION__MSK 0x30
+#define BMA2X2_FIFO_TRIGGER_ACTION__REG BMA2X2_FIFO_MODE_REG
+
+#define BMA2X2_FIFO_MODE__POS 6
+#define BMA2X2_FIFO_MODE__LEN 2
+#define BMA2X2_FIFO_MODE__MSK 0xC0
+#define BMA2X2_FIFO_MODE__REG BMA2X2_FIFO_MODE_REG
+
+
+#define BMA2X2_STATUS1 0
+#define BMA2X2_STATUS2 1
+#define BMA2X2_STATUS3 2
+#define BMA2X2_STATUS4 3
+#define BMA2X2_STATUS5 4
+
+
+#define BMA2X2_RANGE_2G 3
+#define BMA2X2_RANGE_4G 5
+#define BMA2X2_RANGE_8G 8
+#define BMA2X2_RANGE_16G 12
+
+
+#define BMA2X2_BW_7_81HZ 0x08
+#define BMA2X2_BW_15_63HZ 0x09
+#define BMA2X2_BW_31_25HZ 0x0A
+#define BMA2X2_BW_62_50HZ 0x0B
+#define BMA2X2_BW_125HZ 0x0C
+#define BMA2X2_BW_250HZ 0x0D
+#define BMA2X2_BW_500HZ 0x0E
+#define BMA2X2_BW_1000HZ 0x0F
+
+#define BMA2X2_SLEEP_DUR_0_5MS 0x05
+#define BMA2X2_SLEEP_DUR_1MS 0x06
+#define BMA2X2_SLEEP_DUR_2MS 0x07
+#define BMA2X2_SLEEP_DUR_4MS 0x08
+#define BMA2X2_SLEEP_DUR_6MS 0x09
+#define BMA2X2_SLEEP_DUR_10MS 0x0A
+#define BMA2X2_SLEEP_DUR_25MS 0x0B
+#define BMA2X2_SLEEP_DUR_50MS 0x0C
+#define BMA2X2_SLEEP_DUR_100MS 0x0D
+#define BMA2X2_SLEEP_DUR_500MS 0x0E
+#define BMA2X2_SLEEP_DUR_1S 0x0F
+
+#define BMA2X2_LATCH_DUR_NON_LATCH 0x00
+#define BMA2X2_LATCH_DUR_250MS 0x01
+#define BMA2X2_LATCH_DUR_500MS 0x02
+#define BMA2X2_LATCH_DUR_1S 0x03
+#define BMA2X2_LATCH_DUR_2S 0x04
+#define BMA2X2_LATCH_DUR_4S 0x05
+#define BMA2X2_LATCH_DUR_8S 0x06
+#define BMA2X2_LATCH_DUR_LATCH 0x07
+#define BMA2X2_LATCH_DUR_NON_LATCH1 0x08
+#define BMA2X2_LATCH_DUR_250US 0x09
+#define BMA2X2_LATCH_DUR_500US 0x0A
+#define BMA2X2_LATCH_DUR_1MS 0x0B
+#define BMA2X2_LATCH_DUR_12_5MS 0x0C
+#define BMA2X2_LATCH_DUR_25MS 0x0D
+#define BMA2X2_LATCH_DUR_50MS 0x0E
+#define BMA2X2_LATCH_DUR_LATCH1 0x0F
+
+#define BMA2X2_MODE_NORMAL 0
+#define BMA2X2_MODE_LOWPOWER1 1
+#define BMA2X2_MODE_SUSPEND 2
+#define BMA2X2_MODE_DEEP_SUSPEND 3
+#define BMA2X2_MODE_LOWPOWER2 4
+#define BMA2X2_MODE_STANDBY 5
+
+#define BMA2X2_X_AXIS 0
+#define BMA2X2_Y_AXIS 1
+#define BMA2X2_Z_AXIS 2
+
+#define BMA2X2_Low_G_Interrupt 0
+#define BMA2X2_High_G_X_Interrupt 1
+#define BMA2X2_High_G_Y_Interrupt 2
+#define BMA2X2_High_G_Z_Interrupt 3
+#define BMA2X2_DATA_EN 4
+#define BMA2X2_Slope_X_Interrupt 5
+#define BMA2X2_Slope_Y_Interrupt 6
+#define BMA2X2_Slope_Z_Interrupt 7
+#define BMA2X2_Single_Tap_Interrupt 8
+#define BMA2X2_Double_Tap_Interrupt 9
+#define BMA2X2_Orient_Interrupt 10
+#define BMA2X2_Flat_Interrupt 11
+#define BMA2X2_FFULL_INTERRUPT 12
+#define BMA2X2_FWM_INTERRUPT 13
+
+#define BMA2X2_INT1_LOWG 0
+#define BMA2X2_INT2_LOWG 1
+#define BMA2X2_INT1_HIGHG 0
+#define BMA2X2_INT2_HIGHG 1
+#define BMA2X2_INT1_SLOPE 0
+#define BMA2X2_INT2_SLOPE 1
+#define BMA2X2_INT1_SLO_NO_MOT 0
+#define BMA2X2_INT2_SLO_NO_MOT 1
+#define BMA2X2_INT1_DTAP 0
+#define BMA2X2_INT2_DTAP 1
+#define BMA2X2_INT1_STAP 0
+#define BMA2X2_INT2_STAP 1
+#define BMA2X2_INT1_ORIENT 0
+#define BMA2X2_INT2_ORIENT 1
+#define BMA2X2_INT1_FLAT 0
+#define BMA2X2_INT2_FLAT 1
+#define BMA2X2_INT1_NDATA 0
+#define BMA2X2_INT2_NDATA 1
+#define BMA2X2_INT1_FWM 0
+#define BMA2X2_INT2_FWM 1
+#define BMA2X2_INT1_FFULL 0
+#define BMA2X2_INT2_FFULL 1
+
+#define BMA2X2_SRC_LOWG 0
+#define BMA2X2_SRC_HIGHG 1
+#define BMA2X2_SRC_SLOPE 2
+#define BMA2X2_SRC_SLO_NO_MOT 3
+#define BMA2X2_SRC_TAP 4
+#define BMA2X2_SRC_DATA 5
+
+#define BMA2X2_INT1_OUTPUT 0
+#define BMA2X2_INT2_OUTPUT 1
+#define BMA2X2_INT1_LEVEL 0
+#define BMA2X2_INT2_LEVEL 1
+
+#define BMA2X2_LOW_DURATION 0
+#define BMA2X2_HIGH_DURATION 1
+#define BMA2X2_SLOPE_DURATION 2
+#define BMA2X2_SLO_NO_MOT_DURATION 3
+
+#define BMA2X2_LOW_THRESHOLD 0
+#define BMA2X2_HIGH_THRESHOLD 1
+#define BMA2X2_SLOPE_THRESHOLD 2
+#define BMA2X2_SLO_NO_MOT_THRESHOLD 3
+
+
+#define BMA2X2_LOWG_HYST 0
+#define BMA2X2_HIGHG_HYST 1
+
+#define BMA2X2_ORIENT_THETA 0
+#define BMA2X2_FLAT_THETA 1
+
+#define BMA2X2_I2C_SELECT 0
+#define BMA2X2_I2C_EN 1
+
+#define BMA2X2_SLOW_COMP_X 0
+#define BMA2X2_SLOW_COMP_Y 1
+#define BMA2X2_SLOW_COMP_Z 2
+
+#define BMA2X2_CUT_OFF 0
+#define BMA2X2_OFFSET_TRIGGER_X 1
+#define BMA2X2_OFFSET_TRIGGER_Y 2
+#define BMA2X2_OFFSET_TRIGGER_Z 3
+
+#define BMA2X2_GP0 0
+#define BMA2X2_GP1 1
+
+#define BMA2X2_SLO_NO_MOT_EN_X 0
+#define BMA2X2_SLO_NO_MOT_EN_Y 1
+#define BMA2X2_SLO_NO_MOT_EN_Z 2
+#define BMA2X2_SLO_NO_MOT_EN_SEL 3
+
+#define BMA2X2_WAKE_UP_DUR_20MS 0
+#define BMA2X2_WAKE_UP_DUR_80MS 1
+#define BMA2X2_WAKE_UP_DUR_320MS 2
+#define BMA2X2_WAKE_UP_DUR_2560MS 3
+
+#define BMA2X2_SELF_TEST0_ON 1
+#define BMA2X2_SELF_TEST1_ON 2
+
+#define BMA2X2_EE_W_OFF 0
+#define BMA2X2_EE_W_ON 1
+
+#define BMA2X2_LOW_TH_IN_G(gthres, range) ((256 * gthres) / range)
+
+
+#define BMA2X2_HIGH_TH_IN_G(gthres, range) ((256 * gthres) / range)
+
+
+#define BMA2X2_LOW_HY_IN_G(ghyst, range) ((32 * ghyst) / range)
+
+
+#define BMA2X2_HIGH_HY_IN_G(ghyst, range) ((32 * ghyst) / range)
+
+
+#define BMA2X2_SLOPE_TH_IN_G(gthres, range) ((128 * gthres) / range)
+
+
+#define BMA2X2_GET_BITSLICE(regvar, bitname)\
+ ((regvar & bitname##__MSK) >> bitname##__POS)
+
+
+#define BMA2X2_SET_BITSLICE(regvar, bitname, val)\
+ ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK))
+
+
+#define BMA255_CHIP_ID 0XFA
+#define BMA250E_CHIP_ID 0XF9
+#define BMA222E_CHIP_ID 0XF8
+#define BMA280_CHIP_ID 0XFB
+
+#define BMA255_TYPE 0
+#define BMA250E_TYPE 1
+#define BMA222E_TYPE 2
+#define BMA280_TYPE 3
+
+#define MAX_FIFO_F_LEVEL 32
+#define MAX_FIFO_F_BYTES 6
+#define BMA_MAX_RETRY_I2C_XFER (100)
+
+static struct device *bma_device = NULL;
+#define CALIBRATION_FILE_PATH "/efs/calibration_data"
+
+unsigned char *sensor_name[] = { "BMA255", "BMA250E", "BMA222E", "BMA280" };
+
+struct bma2x2acc {
+ s16 x,
+ y,
+ z;
+} ;
+
+struct bma2x2_data {
+ struct i2c_client *bma2x2_client;
+ atomic_t delay;
+ atomic_t enable;
+ atomic_t selftest_result;
+ unsigned int chip_id;
+ unsigned char mode;
+ signed char sensor_type;
+ struct input_dev *input;
+ struct bma2x2acc 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
+ int IRQ;
+
+#ifdef CONFIG_BMA_USE_PLATFORM_DATA
+ struct bosch_sensor_specific *bst_pd;
+#endif
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void bma2x2_early_suspend(struct early_suspend *h);
+static void bma2x2_late_resume(struct early_suspend *h);
+#endif
+
+static void bma2x2_remap_sensor_data(struct bma2x2acc *val,
+ struct bma2x2_data *client_data)
+{
+#ifdef CONFIG_BMA_USE_PLATFORM_DATA
+ struct bosch_sensor_data bsd;
+
+ if (NULL == client_data->bst_pd)
+ return;
+
+ bsd.x = val->x;
+ bsd.y = val->y;
+ bsd.z = val->z;
+
+ bst_remap_sensor_data_dft_tab(&bsd,
+ client_data->bst_pd->place);
+
+ val->x = bsd.x;
+ val->y = bsd.y;
+ val->z = bsd.z;
+#else
+ (void)val;
+ (void)client_data;
+#endif
+}
+
+
+static int bma2x2_smbus_read_byte(struct i2c_client *client,
+ unsigned char reg_addr, unsigned char *data)
+{
+ s32 dummy;
+ dummy = i2c_smbus_read_byte_data(client, reg_addr);
+ if (dummy < 0)
+ return -1;
+ *data = dummy & 0x000000ff;
+
+ return 0;
+}
+
+static int bma2x2_smbus_write_byte(struct i2c_client *client,
+ unsigned char reg_addr, unsigned char *data)
+{
+ s32 dummy;
+
+ dummy = i2c_smbus_write_byte_data(client, reg_addr, *data);
+ if (dummy < 0)
+ return -1;
+ return 0;
+}
+
+static int bma2x2_smbus_read_byte_block(struct i2c_client *client,
+ unsigned char reg_addr, unsigned char *data, unsigned char len)
+{
+ s32 dummy;
+ dummy = i2c_smbus_read_i2c_block_data(client, reg_addr, len, data);
+ if (dummy < 0)
+ return -1;
+ return 0;
+}
+
+static int bma_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 < BMA_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ mdelay(1);
+ }
+
+ if (BMA_MAX_RETRY_I2C_XFER <= retry) {
+ printk(KERN_INFO "I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+
+#ifdef BMA2X2_ENABLE_INT1
+static int bma2x2_set_int1_pad_sel(struct i2c_client *client, unsigned char
+ int1sel)
+{
+ int comres = 0;
+ unsigned char data;
+ unsigned char state;
+ state = 0x01;
+
+
+ switch (int1sel) {
+ case 0:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT1_PAD_LOWG__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT1_PAD_LOWG,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT1_PAD_LOWG__REG, &data);
+ break;
+ case 1:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT1_PAD_HIGHG__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT1_PAD_HIGHG,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT1_PAD_HIGHG__REG, &data);
+ break;
+ case 2:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT1_PAD_SLOPE__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT1_PAD_SLOPE,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT1_PAD_SLOPE__REG, &data);
+ break;
+ case 3:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT1_PAD_DB_TAP__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT1_PAD_DB_TAP,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT1_PAD_DB_TAP__REG, &data);
+ break;
+ case 4:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT1_PAD_SNG_TAP__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT1_PAD_SNG_TAP,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT1_PAD_SNG_TAP__REG, &data);
+ break;
+ case 5:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT1_PAD_ORIENT__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT1_PAD_ORIENT,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT1_PAD_ORIENT__REG, &data);
+ break;
+ case 6:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT1_PAD_FLAT__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT1_PAD_FLAT,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT1_PAD_FLAT__REG, &data);
+ break;
+ case 7:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT1_PAD_SLO_NO_MOT__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT1_PAD_SLO_NO_MOT,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT1_PAD_SLO_NO_MOT__REG, &data);
+ break;
+
+ default:
+ break;
+ }
+
+ return comres;
+}
+#endif /* BMA2X2_ENABLE_INT1 */
+#ifdef BMA2X2_ENABLE_INT2
+static int bma2x2_set_int2_pad_sel(struct i2c_client *client, unsigned char
+ int2sel)
+{
+ int comres = 0;
+ unsigned char data;
+ unsigned char state;
+ state = 0x01;
+
+
+ switch (int2sel) {
+ case 0:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT2_PAD_LOWG__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT2_PAD_LOWG,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT2_PAD_LOWG__REG, &data);
+ break;
+ case 1:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT2_PAD_HIGHG__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT2_PAD_HIGHG,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT2_PAD_HIGHG__REG, &data);
+ break;
+ case 2:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT2_PAD_SLOPE__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT2_PAD_SLOPE,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT2_PAD_SLOPE__REG, &data);
+ break;
+ case 3:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT2_PAD_DB_TAP__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT2_PAD_DB_TAP,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT2_PAD_DB_TAP__REG, &data);
+ break;
+ case 4:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT2_PAD_SNG_TAP__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT2_PAD_SNG_TAP,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT2_PAD_SNG_TAP__REG, &data);
+ break;
+ case 5:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT2_PAD_ORIENT__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT2_PAD_ORIENT,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT2_PAD_ORIENT__REG, &data);
+ break;
+ case 6:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT2_PAD_FLAT__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT2_PAD_FLAT,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT2_PAD_FLAT__REG, &data);
+ break;
+ case 7:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_EN_INT2_PAD_SLO_NO_MOT__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_INT2_PAD_SLO_NO_MOT,
+ state);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_EN_INT2_PAD_SLO_NO_MOT__REG, &data);
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+#endif /* BMA2X2_ENABLE_INT2 */
+
+static int bma2x2_set_Int_Enable(struct i2c_client *client, unsigned char
+ InterruptType , unsigned char value)
+{
+ int comres = 0;
+ unsigned char data1, data2;
+
+ if ((11 < InterruptType) && (InterruptType < 16)) {
+ switch (InterruptType) {
+ case 12:
+ /* slow/no motion X Interrupt */
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_INT_SLO_NO_MOT_EN_X_INT__REG, &data1);
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_INT_SLO_NO_MOT_EN_X_INT, value);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_INT_SLO_NO_MOT_EN_X_INT__REG, &data1);
+ break;
+ case 13:
+ /* slow/no motion Y Interrupt */
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_INT_SLO_NO_MOT_EN_Y_INT__REG, &data1);
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_INT_SLO_NO_MOT_EN_Y_INT, value);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_INT_SLO_NO_MOT_EN_Y_INT__REG, &data1);
+ break;
+ case 14:
+ /* slow/no motion Z Interrupt */
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_INT_SLO_NO_MOT_EN_Z_INT__REG, &data1);
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_INT_SLO_NO_MOT_EN_Z_INT, value);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_INT_SLO_NO_MOT_EN_Z_INT__REG, &data1);
+ break;
+ case 15:
+ /* slow / no motion Interrupt select */
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_INT_SLO_NO_MOT_EN_SEL_INT__REG, &data1);
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_INT_SLO_NO_MOT_EN_SEL_INT, value);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_INT_SLO_NO_MOT_EN_SEL_INT__REG, &data1);
+ }
+
+ return comres;
+ }
+
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_INT_ENABLE1_REG, &data1);
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_INT_ENABLE2_REG, &data2);
+
+ value = value & 1;
+ switch (InterruptType) {
+ case 0:
+ /* Low G Interrupt */
+ data2 = BMA2X2_SET_BITSLICE(data2, BMA2X2_EN_LOWG_INT, value);
+ break;
+ case 1:
+ /* High G X Interrupt */
+
+ data2 = BMA2X2_SET_BITSLICE(data2, BMA2X2_EN_HIGHG_X_INT,
+ value);
+ break;
+ case 2:
+ /* High G Y Interrupt */
+
+ data2 = BMA2X2_SET_BITSLICE(data2, BMA2X2_EN_HIGHG_Y_INT,
+ value);
+ break;
+ case 3:
+ /* High G Z Interrupt */
+
+ data2 = BMA2X2_SET_BITSLICE(data2, BMA2X2_EN_HIGHG_Z_INT,
+ value);
+ break;
+ case 4:
+ /* New Data Interrupt */
+
+ data2 = BMA2X2_SET_BITSLICE(data2, BMA2X2_EN_NEW_DATA_INT,
+ value);
+ break;
+ case 5:
+ /* Slope X Interrupt */
+
+ data1 = BMA2X2_SET_BITSLICE(data1, BMA2X2_EN_SLOPE_X_INT,
+ value);
+ break;
+ case 6:
+ /* Slope Y Interrupt */
+
+ data1 = BMA2X2_SET_BITSLICE(data1, BMA2X2_EN_SLOPE_Y_INT,
+ value);
+ break;
+ case 7:
+ /* Slope Z Interrupt */
+
+ data1 = BMA2X2_SET_BITSLICE(data1, BMA2X2_EN_SLOPE_Z_INT,
+ value);
+ break;
+ case 8:
+ /* Single Tap Interrupt */
+
+ data1 = BMA2X2_SET_BITSLICE(data1, BMA2X2_EN_SINGLE_TAP_INT,
+ value);
+ break;
+ case 9:
+ /* Double Tap Interrupt */
+
+ data1 = BMA2X2_SET_BITSLICE(data1, BMA2X2_EN_DOUBLE_TAP_INT,
+ value);
+ break;
+ case 10:
+ /* Orient Interrupt */
+
+ data1 = BMA2X2_SET_BITSLICE(data1, BMA2X2_EN_ORIENT_INT, value);
+ break;
+ case 11:
+ /* Flat Interrupt */
+
+ data1 = BMA2X2_SET_BITSLICE(data1, BMA2X2_EN_FLAT_INT, value);
+ break;
+ default:
+ break;
+ }
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_INT_ENABLE1_REG,
+ &data1);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_INT_ENABLE2_REG,
+ &data2);
+
+ return comres;
+}
+
+
+#if defined(BMA2X2_ENABLE_INT1) || defined(BMA2X2_ENABLE_INT2)
+static int bma2x2_get_interruptstatus1(struct i2c_client *client, unsigned char
+ *intstatus)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_STATUS1_REG, &data);
+ *intstatus = data;
+
+ return comres;
+}
+
+
+static int bma2x2_get_HIGH_first(struct i2c_client *client, unsigned char
+ param, unsigned char *intstatus)
+{
+ int comres = 0;
+ unsigned char data;
+
+ switch (param) {
+ case 0:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_STATUS_ORIENT_HIGH_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_HIGHG_FIRST_X);
+ *intstatus = data;
+ break;
+ case 1:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_STATUS_ORIENT_HIGH_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_HIGHG_FIRST_Y);
+ *intstatus = data;
+ break;
+ case 2:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_STATUS_ORIENT_HIGH_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_HIGHG_FIRST_Z);
+ *intstatus = data;
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+static int bma2x2_get_HIGH_sign(struct i2c_client *client, unsigned char
+ *intstatus)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_STATUS_ORIENT_HIGH_REG,
+ &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_HIGHG_SIGN_S);
+ *intstatus = data;
+
+ return comres;
+}
+
+
+static int bma2x2_get_slope_first(struct i2c_client *client, unsigned char
+ param, unsigned char *intstatus)
+{
+ int comres = 0;
+ unsigned char data;
+
+ switch (param) {
+ case 0:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_STATUS_TAP_SLOPE_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_SLOPE_FIRST_X);
+ *intstatus = data;
+ break;
+ case 1:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_STATUS_TAP_SLOPE_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_SLOPE_FIRST_Y);
+ *intstatus = data;
+ break;
+ case 2:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_STATUS_TAP_SLOPE_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_SLOPE_FIRST_Z);
+ *intstatus = data;
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+static int bma2x2_get_slope_sign(struct i2c_client *client, unsigned char
+ *intstatus)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_STATUS_TAP_SLOPE_REG,
+ &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_SLOPE_SIGN_S);
+ *intstatus = data;
+
+ return comres;
+}
+
+static int bma2x2_get_orient_status(struct i2c_client *client, unsigned char
+ *intstatus)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_STATUS_ORIENT_HIGH_REG,
+ &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_ORIENT_S);
+ *intstatus = data;
+
+ return comres;
+}
+
+static int bma2x2_get_orient_flat_status(struct i2c_client *client, unsigned
+ char *intstatus)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_STATUS_ORIENT_HIGH_REG,
+ &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_FLAT_S);
+ *intstatus = data;
+
+ return comres;
+}
+#endif /* defined(BMA2X2_ENABLE_INT1)||defined(BMA2X2_ENABLE_INT2) */
+static int bma2x2_set_Int_Mode(struct i2c_client *client, unsigned char Mode)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_INT_MODE_SEL__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_INT_MODE_SEL, Mode);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_INT_MODE_SEL__REG, &data);
+
+
+ return comres;
+}
+
+static int bma2x2_get_Int_Mode(struct i2c_client *client, unsigned char *Mode)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_INT_MODE_SEL__REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_INT_MODE_SEL);
+ *Mode = data;
+
+
+ return comres;
+}
+static int bma2x2_set_slope_duration(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_SLOPE_DUR__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_SLOPE_DUR, duration);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_SLOPE_DUR__REG, &data);
+
+
+ return comres;
+}
+
+static int bma2x2_get_slope_duration(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_SLOPE_DURN_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_SLOPE_DUR);
+ *status = data;
+
+
+ return comres;
+}
+
+static int bma2x2_set_slope_no_mot_duration(struct i2c_client *client,
+ unsigned char duration)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2x2_SLO_NO_MOT_DUR__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2x2_SLO_NO_MOT_DUR, duration);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2x2_SLO_NO_MOT_DUR__REG, &data);
+
+
+ return comres;
+}
+
+static int bma2x2_get_slope_no_mot_duration(struct i2c_client *client,
+ unsigned char *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2x2_SLO_NO_MOT_DUR__REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2x2_SLO_NO_MOT_DUR);
+ *status = data;
+
+
+ return comres;
+}
+
+static int bma2x2_set_slope_threshold(struct i2c_client *client,
+ unsigned char threshold)
+{
+ int comres = 0;
+ unsigned char data;
+
+ data = threshold;
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_SLOPE_THRES__REG, &data);
+
+ return comres;
+}
+
+static int bma2x2_get_slope_threshold(struct i2c_client *client,
+ unsigned char *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_SLOPE_THRES_REG, &data);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_slope_no_mot_threshold(struct i2c_client *client,
+ unsigned char threshold)
+{
+ int comres = 0;
+ unsigned char data;
+
+ data = threshold;
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_SLO_NO_MOT_THRES_REG, &data);
+
+ return comres;
+}
+
+static int bma2x2_get_slope_no_mot_threshold(struct i2c_client *client,
+ unsigned char *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_SLO_NO_MOT_THRES_REG, &data);
+ *status = data;
+
+ return comres;
+}
+
+
+static int bma2x2_set_low_g_duration(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data;
+
+ data = duration;
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_LOWG_DUR__REG, &data);
+
+ return comres;
+}
+
+static int bma2x2_get_low_g_duration(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_LOW_DURN_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_LOWG_DUR);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_low_g_threshold(struct i2c_client *client, unsigned char
+ threshold)
+{
+ int comres = 0;
+ unsigned char data;
+
+ data = threshold;
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_LOWG_THRES__REG, &data);
+
+ return comres;
+}
+
+static int bma2x2_get_low_g_threshold(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_LOW_THRES_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_LOWG_THRES);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_high_g_duration(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data;
+
+ data = duration;
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_HIGHG_DUR__REG, &data);
+
+ return comres;
+}
+
+static int bma2x2_get_high_g_duration(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_HIGH_DURN_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_HIGHG_DUR);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_high_g_threshold(struct i2c_client *client, unsigned char
+ threshold)
+{
+ int comres = 0;
+ unsigned char data;
+
+ data = threshold;
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_HIGHG_THRES__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_high_g_threshold(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_HIGH_THRES_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_HIGHG_THRES);
+ *status = data;
+
+ return comres;
+}
+
+
+static int bma2x2_set_tap_duration(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_DUR__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_TAP_DUR, duration);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_TAP_DUR__REG, &data);
+
+ return comres;
+}
+
+static int bma2x2_get_tap_duration(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_PARAM_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_TAP_DUR);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_tap_shock(struct i2c_client *client, unsigned char setval)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_SHOCK_DURN__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_TAP_SHOCK_DURN, setval);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_TAP_SHOCK_DURN__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_tap_shock(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_PARAM_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_TAP_SHOCK_DURN);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_tap_quiet(struct i2c_client *client, unsigned char
+ duration)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_QUIET_DURN__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_TAP_QUIET_DURN, duration);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_TAP_QUIET_DURN__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_tap_quiet(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_PARAM_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_TAP_QUIET_DURN);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_tap_threshold(struct i2c_client *client, unsigned char
+ threshold)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_THRES__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_TAP_THRES, threshold);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_TAP_THRES__REG, &data);
+
+ return comres;
+}
+
+static int bma2x2_get_tap_threshold(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_THRES_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_TAP_THRES);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_tap_samp(struct i2c_client *client, unsigned char samp)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_SAMPLES__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_TAP_SAMPLES, samp);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_TAP_SAMPLES__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_tap_samp(struct i2c_client *client, unsigned char *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TAP_THRES_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_TAP_SAMPLES);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_orient_mode(struct i2c_client *client, unsigned char mode)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_ORIENT_MODE__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_ORIENT_MODE, mode);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_ORIENT_MODE__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_orient_mode(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_ORIENT_PARAM_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_ORIENT_MODE);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_orient_blocking(struct i2c_client *client, unsigned char
+ samp)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_ORIENT_BLOCK__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_ORIENT_BLOCK, samp);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_ORIENT_BLOCK__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_orient_blocking(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_ORIENT_PARAM_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_ORIENT_BLOCK);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_orient_hyst(struct i2c_client *client, unsigned char
+ orienthyst)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_ORIENT_HYST__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_ORIENT_HYST, orienthyst);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_ORIENT_HYST__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_orient_hyst(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_ORIENT_PARAM_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_ORIENT_HYST);
+ *status = data;
+
+ return comres;
+}
+static int bma2x2_set_theta_blocking(struct i2c_client *client, unsigned char
+ thetablk)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_THETA_BLOCK__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_THETA_BLOCK, thetablk);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_THETA_BLOCK__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_theta_blocking(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_THETA_BLOCK_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_THETA_BLOCK);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_theta_flat(struct i2c_client *client, unsigned char
+ thetaflat)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_THETA_FLAT__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_THETA_FLAT, thetaflat);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_THETA_FLAT__REG, &data);
+
+ return comres;
+}
+
+static int bma2x2_get_theta_flat(struct i2c_client *client, unsigned char
+ *status)
+{
+ int comres = 0 ;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_THETA_FLAT_REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_THETA_FLAT);
+ *status = data;
+
+ return comres;
+}
+
+static int bma2x2_set_flat_hold_time(struct i2c_client *client, unsigned char
+ holdtime)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_FLAT_HOLD_TIME__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_FLAT_HOLD_TIME, holdtime);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_FLAT_HOLD_TIME__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_flat_hold_time(struct i2c_client *client, unsigned char
+ *holdtime)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_FLAT_HOLD_TIME_REG,
+ &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_FLAT_HOLD_TIME);
+ *holdtime = data ;
+
+ return comres;
+}
+
+static int bma2x2_set_mode(struct i2c_client *client, unsigned char Mode)
+{
+ int comres = 0;
+ unsigned char data1, data2;
+
+ if (Mode < 6) {
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_MODE_CTRL_REG,
+ &data1);
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_LOW_NOISE_CTRL_REG,
+ &data2);
+ switch (Mode) {
+ case BMA2X2_MODE_NORMAL:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_MODE_CTRL, 0);
+ data2 = BMA2X2_SET_BITSLICE(data2,
+ BMA2X2_LOW_POWER_MODE, 0);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_MODE_CTRL_REG, &data1);
+ mdelay(1);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_LOW_NOISE_CTRL_REG, &data2);
+ break;
+ case BMA2X2_MODE_LOWPOWER1:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_MODE_CTRL, 2);
+ data2 = BMA2X2_SET_BITSLICE(data2,
+ BMA2X2_LOW_POWER_MODE, 0);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_MODE_CTRL_REG, &data1);
+ mdelay(1);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_LOW_NOISE_CTRL_REG, &data2);
+ break;
+ case BMA2X2_MODE_SUSPEND:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_MODE_CTRL, 4);
+ data2 = BMA2X2_SET_BITSLICE(data2,
+ BMA2X2_LOW_POWER_MODE, 0);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_LOW_NOISE_CTRL_REG, &data2);
+ mdelay(1);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_MODE_CTRL_REG, &data1);
+ break;
+ case BMA2X2_MODE_DEEP_SUSPEND:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_MODE_CTRL, 1);
+ data2 = BMA2X2_SET_BITSLICE(data2,
+ BMA2X2_LOW_POWER_MODE, 1);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_MODE_CTRL_REG, &data1);
+ mdelay(1);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_LOW_NOISE_CTRL_REG, &data2);
+ break;
+ case BMA2X2_MODE_LOWPOWER2:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_MODE_CTRL, 2);
+ data2 = BMA2X2_SET_BITSLICE(data2,
+ BMA2X2_LOW_POWER_MODE, 1);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_MODE_CTRL_REG, &data1);
+ mdelay(1);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_LOW_NOISE_CTRL_REG, &data2);
+ break;
+ case BMA2X2_MODE_STANDBY:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_MODE_CTRL, 4);
+ data2 = BMA2X2_SET_BITSLICE(data2,
+ BMA2X2_LOW_POWER_MODE, 1);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_LOW_NOISE_CTRL_REG, &data2);
+ mdelay(1);
+ bma2x2_smbus_write_byte(client,
+ BMA2X2_MODE_CTRL_REG, &data1);
+ break;
+ }
+ } else {
+ comres = -1 ;
+ }
+
+
+ return comres;
+}
+
+
+static int bma2x2_get_mode(struct i2c_client *client, unsigned char *Mode)
+{
+ int comres = 0;
+ unsigned char data1, data2;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_MODE_CTRL_REG, &data1);
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_LOW_NOISE_CTRL_REG,
+ &data2);
+
+ data1 = (data1 & 0xE0) >> 5;
+ data2 = (data2 & 0x40) >> 6;
+
+
+ if ((data1 == 0x00) && (data2 == 0x00)) {
+ *Mode = BMA2X2_MODE_NORMAL;
+ } else {
+ if ((data1 == 0x02) && (data2 == 0x00)) {
+ *Mode = BMA2X2_MODE_LOWPOWER1;
+ } else {
+ if ((data1 == 0x04 || data1 == 0x06) &&
+ (data2 == 0x00)) {
+ *Mode = BMA2X2_MODE_SUSPEND;
+ } else {
+ if (((data1 & 0x01) == 0x01)) {
+ *Mode = BMA2X2_MODE_DEEP_SUSPEND;
+ } else {
+ if ((data1 == 0x02) &&
+ (data2 == 0x01)) {
+ *Mode = BMA2X2_MODE_LOWPOWER2;
+ } else {
+ if ((data1 == 0x04) && (data2 ==
+ 0x01)) {
+ *Mode =
+ BMA2X2_MODE_STANDBY;
+ } else {
+ *Mode =
+ BMA2X2_MODE_DEEP_SUSPEND;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return comres;
+}
+
+static int bma2x2_set_range(struct i2c_client *client, unsigned char Range)
+{
+ int comres = 0 ;
+ unsigned char data1;
+
+ if ((Range == 3) || (Range == 5) || (Range == 8) || (Range == 12)) {
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_RANGE_SEL_REG,
+ &data1);
+ switch (Range) {
+ case BMA2X2_RANGE_2G:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_RANGE_SEL, 3);
+ break;
+ case BMA2X2_RANGE_4G:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_RANGE_SEL, 5);
+ break;
+ case BMA2X2_RANGE_8G:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_RANGE_SEL, 8);
+ break;
+ case BMA2X2_RANGE_16G:
+ data1 = BMA2X2_SET_BITSLICE(data1,
+ BMA2X2_RANGE_SEL, 12);
+ break;
+ }
+ comres += bma2x2_smbus_write_byte(client, BMA2X2_RANGE_SEL_REG,
+ &data1);
+ } else {
+ comres = -1 ;
+ }
+
+ return comres;
+}
+
+static int bma2x2_get_range(struct i2c_client *client, unsigned char *Range)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_RANGE_SEL__REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_RANGE_SEL);
+ *Range = data;
+
+ return comres;
+}
+
+
+static int bma2x2_set_bandwidth(struct i2c_client *client, unsigned char BW)
+{
+ int comres = 0;
+ unsigned char data;
+ int Bandwidth = 0;
+
+ if (BW > 7 && BW < 16) {
+ switch (BW) {
+ case BMA2X2_BW_7_81HZ:
+ Bandwidth = BMA2X2_BW_7_81HZ;
+
+ /* 7.81 Hz 64000 uS */
+ break;
+ case BMA2X2_BW_15_63HZ:
+ Bandwidth = BMA2X2_BW_15_63HZ;
+
+ /* 15.63 Hz 32000 uS */
+ break;
+ case BMA2X2_BW_31_25HZ:
+ Bandwidth = BMA2X2_BW_31_25HZ;
+
+ /* 31.25 Hz 16000 uS */
+ break;
+ case BMA2X2_BW_62_50HZ:
+ Bandwidth = BMA2X2_BW_62_50HZ;
+
+ /* 62.50 Hz 8000 uS */
+ break;
+ case BMA2X2_BW_125HZ:
+ Bandwidth = BMA2X2_BW_125HZ;
+
+ /* 125 Hz 4000 uS */
+ break;
+ case BMA2X2_BW_250HZ:
+ Bandwidth = BMA2X2_BW_250HZ;
+
+ /* 250 Hz 2000 uS */
+ break;
+ case BMA2X2_BW_500HZ:
+ Bandwidth = BMA2X2_BW_500HZ;
+
+ /* 500 Hz 1000 uS */
+ break;
+ case BMA2X2_BW_1000HZ:
+ Bandwidth = BMA2X2_BW_1000HZ;
+
+ /* 1000 Hz 500 uS */
+ break;
+ }
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_BANDWIDTH__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_BANDWIDTH, Bandwidth);
+ comres += bma2x2_smbus_write_byte(client, BMA2X2_BANDWIDTH__REG,
+ &data);
+ } else {
+ comres = -1 ;
+ }
+
+ return comres;
+}
+
+static int bma2x2_get_bandwidth(struct i2c_client *client, unsigned char *BW)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_BANDWIDTH__REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_BANDWIDTH);
+ *BW = data ;
+
+ return comres;
+}
+
+int bma2x2_get_sleep_duration(struct i2c_client *client, unsigned char
+ *sleep_dur)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_SLEEP_DUR__REG, &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_SLEEP_DUR);
+ *sleep_dur = data;
+
+ return comres;
+}
+
+int bma2x2_set_sleep_duration(struct i2c_client *client, unsigned char
+ sleep_dur)
+{
+ int comres = 0;
+ unsigned char data;
+ int sleep_duration = 0;
+
+ if (sleep_dur > 4 && sleep_dur < 16) {
+ switch (sleep_dur) {
+ case BMA2X2_SLEEP_DUR_0_5MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_0_5MS;
+
+ /* 0.5 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_1MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_1MS;
+
+ /* 1 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_2MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_2MS;
+
+ /* 2 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_4MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_4MS;
+
+ /* 4 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_6MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_6MS;
+
+ /* 6 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_10MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_10MS;
+
+ /* 10 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_25MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_25MS;
+
+ /* 25 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_50MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_50MS;
+
+ /* 50 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_100MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_100MS;
+
+ /* 100 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_500MS:
+ sleep_duration = BMA2X2_SLEEP_DUR_500MS;
+
+ /* 500 MS */
+ break;
+ case BMA2X2_SLEEP_DUR_1S:
+ sleep_duration = BMA2X2_SLEEP_DUR_1S;
+
+ /* 1 SECS */
+ break;
+ }
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_SLEEP_DUR__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_SLEEP_DUR,
+ sleep_duration);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_SLEEP_DUR__REG,
+ &data);
+ } else {
+ comres = -1 ;
+ }
+
+
+ return comres;
+}
+
+static int bma2x2_get_fifo_mode(struct i2c_client *client, unsigned char
+ *fifo_mode)
+{
+ int comres;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_FIFO_MODE__REG, &data);
+ *fifo_mode = BMA2X2_GET_BITSLICE(data, BMA2X2_FIFO_MODE);
+
+ return comres;
+}
+
+static int bma2x2_set_fifo_mode(struct i2c_client *client, unsigned char
+ fifo_mode)
+{
+ unsigned char data;
+ int comres = 0;
+
+ if (fifo_mode < 4) {
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_FIFO_MODE__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_FIFO_MODE, fifo_mode);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_FIFO_MODE__REG,
+ &data);
+ } else {
+ comres = -1 ;
+ }
+
+ return comres;
+}
+
+
+static int bma2x2_get_fifo_trig(struct i2c_client *client, unsigned char
+ *fifo_trig)
+{
+ int comres;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_FIFO_TRIGGER_ACTION__REG, &data);
+ *fifo_trig = BMA2X2_GET_BITSLICE(data, BMA2X2_FIFO_TRIGGER_ACTION);
+
+ return comres;
+}
+
+static int bma2x2_set_fifo_trig(struct i2c_client *client, unsigned char
+ fifo_trig)
+{
+ unsigned char data;
+ int comres = 0;
+
+ if (fifo_trig < 4) {
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_FIFO_TRIGGER_ACTION__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_FIFO_TRIGGER_ACTION,
+ fifo_trig);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_FIFO_TRIGGER_ACTION__REG, &data);
+ } else {
+ comres = -1 ;
+ }
+
+ return comres;
+}
+
+static int bma2x2_get_fifo_trig_src(struct i2c_client *client, unsigned char
+ *trig_src)
+{
+ int comres;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_FIFO_TRIGGER_SOURCE__REG, &data);
+ *trig_src = BMA2X2_GET_BITSLICE(data, BMA2X2_FIFO_TRIGGER_SOURCE);
+
+ return comres;
+}
+
+
+static int bma2x2_set_fifo_trig_src(struct i2c_client *client, unsigned char
+ trig_src)
+{
+ unsigned char data;
+ int comres = 0;
+
+ if (trig_src < 4) {
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_FIFO_TRIGGER_SOURCE__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_FIFO_TRIGGER_SOURCE,
+ trig_src);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_FIFO_TRIGGER_SOURCE__REG, &data);
+ } else {
+ comres = -1 ;
+ }
+
+ return comres;
+}
+
+static int bma2x2_get_fifo_framecount(struct i2c_client *client, unsigned char
+ *framecount)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_FIFO_FRAME_COUNTER_S__REG, &data);
+ *framecount = BMA2X2_GET_BITSLICE(data, BMA2X2_FIFO_FRAME_COUNTER_S);
+
+ return comres;
+}
+
+static int bma2x2_get_fifo_data_sel(struct i2c_client *client, unsigned char
+ *data_sel)
+{
+ int comres;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_FIFO_DATA_SELECT__REG, &data);
+ *data_sel = BMA2X2_GET_BITSLICE(data, BMA2X2_FIFO_DATA_SELECT);
+
+ return comres;
+}
+
+static int bma2x2_set_fifo_data_sel(struct i2c_client *client, unsigned char
+ data_sel)
+{
+ unsigned char data;
+ int comres = 0;
+
+ if (data_sel < 4) {
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_FIFO_DATA_SELECT__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_FIFO_DATA_SELECT,
+ data_sel);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_FIFO_DATA_SELECT__REG,
+ &data);
+ } else {
+ comres = -1 ;
+ }
+
+ return comres;
+}
+
+static int bma2x2_get_fifo_data_out_reg(struct i2c_client *client, unsigned char
+ *out_reg)
+{
+ unsigned char data;
+ int comres = 0;
+
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_FIFO_DATA_OUTPUT_REG, &data);
+ *out_reg = data;
+
+ return comres;
+}
+
+static int bma2x2_get_offset_target(struct i2c_client *client, unsigned char
+ channel, unsigned char *offset)
+{
+ unsigned char data;
+ int comres = 0;
+
+ switch (channel) {
+ case BMA2X2_CUT_OFF:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_COMP_CUTOFF__REG, &data);
+ *offset = BMA2X2_GET_BITSLICE(data, BMA2X2_COMP_CUTOFF);
+ break;
+ case BMA2X2_OFFSET_TRIGGER_X:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_COMP_TARGET_OFFSET_X__REG, &data);
+ *offset = BMA2X2_GET_BITSLICE(data,
+ BMA2X2_COMP_TARGET_OFFSET_X);
+ break;
+ case BMA2X2_OFFSET_TRIGGER_Y:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_COMP_TARGET_OFFSET_Y__REG, &data);
+ *offset = BMA2X2_GET_BITSLICE(data,
+ BMA2X2_COMP_TARGET_OFFSET_Y);
+ break;
+ case BMA2X2_OFFSET_TRIGGER_Z:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_COMP_TARGET_OFFSET_Z__REG, &data);
+ *offset = BMA2X2_GET_BITSLICE(data,
+ BMA2X2_COMP_TARGET_OFFSET_Z);
+ break;
+ default:
+ comres = -1;
+ break;
+ }
+
+ return comres;
+}
+
+static int bma2x2_set_offset_target(struct i2c_client *client, unsigned char
+ channel, unsigned char offset)
+{
+ unsigned char data;
+ int comres = 0;
+
+ switch (channel) {
+ case BMA2X2_CUT_OFF:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_COMP_CUTOFF__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_COMP_CUTOFF,
+ offset);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_COMP_CUTOFF__REG, &data);
+ break;
+ case BMA2X2_OFFSET_TRIGGER_X:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_COMP_TARGET_OFFSET_X__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data,
+ BMA2X2_COMP_TARGET_OFFSET_X,
+ offset);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_COMP_TARGET_OFFSET_X__REG,
+ &data);
+ break;
+ case BMA2X2_OFFSET_TRIGGER_Y:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_COMP_TARGET_OFFSET_Y__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data,
+ BMA2X2_COMP_TARGET_OFFSET_Y,
+ offset);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_COMP_TARGET_OFFSET_Y__REG,
+ &data);
+ break;
+ case BMA2X2_OFFSET_TRIGGER_Z:
+ comres = bma2x2_smbus_read_byte(client,
+ BMA2X2_COMP_TARGET_OFFSET_Z__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data,
+ BMA2X2_COMP_TARGET_OFFSET_Z,
+ offset);
+ comres = bma2x2_smbus_write_byte(client,
+ BMA2X2_COMP_TARGET_OFFSET_Z__REG,
+ &data);
+ break;
+ default:
+ comres = -1;
+ break;
+ }
+
+ return comres;
+}
+
+static int bma2x2_get_cal_ready(struct i2c_client *client, unsigned char *calrdy
+ )
+{
+ int comres = 0 ;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_FAST_CAL_RDY_S__REG,
+ &data);
+ data = BMA2X2_GET_BITSLICE(data, BMA2X2_FAST_CAL_RDY_S);
+ *calrdy = data;
+
+ return comres;
+}
+
+static int bma2x2_set_cal_trigger(struct i2c_client *client, unsigned char
+ caltrigger)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_CAL_TRIGGER__REG, &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_CAL_TRIGGER, caltrigger);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_CAL_TRIGGER__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_write_reg(struct i2c_client *client, unsigned char addr,
+ unsigned char *data)
+{
+ int comres = 0 ;
+ comres = bma2x2_smbus_write_byte(client, addr, data);
+
+ return comres;
+}
+
+
+static int bma2x2_set_offset_x(struct i2c_client *client, unsigned char
+ offsetfilt)
+{
+ int comres = 0;
+ unsigned char data;
+
+ data = offsetfilt;
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_OFFSET_X_AXIS_REG,
+ &data);
+
+ return comres;
+}
+
+
+static int bma2x2_get_offset_x(struct i2c_client *client, unsigned char
+ *offsetfilt)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_OFFSET_X_AXIS_REG,
+ &data);
+ *offsetfilt = data;
+
+ return comres;
+}
+
+static int bma2x2_set_offset_y(struct i2c_client *client, unsigned char
+ offsetfilt)
+{
+ int comres = 0;
+ unsigned char data;
+
+ data = offsetfilt;
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_OFFSET_Y_AXIS_REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_offset_y(struct i2c_client *client, unsigned char
+ *offsetfilt)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_OFFSET_Y_AXIS_REG,
+ &data);
+ *offsetfilt = data;
+
+ return comres;
+}
+
+static int bma2x2_set_offset_z(struct i2c_client *client, unsigned char
+ offsetfilt)
+{
+ int comres = 0;
+ unsigned char data;
+
+ data = offsetfilt;
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_OFFSET_Z_AXIS_REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_get_offset_z(struct i2c_client *client, unsigned char
+ *offsetfilt)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_OFFSET_Z_AXIS_REG,
+ &data);
+ *offsetfilt = data;
+
+ return comres;
+}
+
+
+static int bma2x2_set_selftest_st(struct i2c_client *client, unsigned char
+ selftest)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_EN_SELF_TEST__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_EN_SELF_TEST, selftest);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_EN_SELF_TEST__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_set_selftest_stn(struct i2c_client *client, unsigned char stn)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_NEG_SELF_TEST__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_NEG_SELF_TEST, stn);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_NEG_SELF_TEST__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_set_selftest_amp(struct i2c_client *client, unsigned char amp)
+{
+ int comres = 0;
+ unsigned char data;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_SELF_TEST_AMP__REG,
+ &data);
+ data = BMA2X2_SET_BITSLICE(data, BMA2X2_SELF_TEST_AMP, amp);
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_SELF_TEST_AMP__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_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 = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_X12_LSB__REG, data, 2);
+ *a_x = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_X12_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_X_MSB)<<(BMA2X2_ACC_X12_LSB__LEN));
+ *a_x = *a_x << (sizeof(short)*8-(BMA2X2_ACC_X12_LSB__LEN
+ + BMA2X2_ACC_X_MSB__LEN));
+ *a_x = *a_x >> (sizeof(short)*8-(BMA2X2_ACC_X12_LSB__LEN
+ + BMA2X2_ACC_X_MSB__LEN));
+ break;
+ case 1:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_X10_LSB__REG, data, 2);
+ *a_x = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_X10_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_X_MSB)<<(BMA2X2_ACC_X10_LSB__LEN));
+ *a_x = *a_x << (sizeof(short)*8-(BMA2X2_ACC_X10_LSB__LEN
+ + BMA2X2_ACC_X_MSB__LEN));
+ *a_x = *a_x >> (sizeof(short)*8-(BMA2X2_ACC_X10_LSB__LEN
+ + BMA2X2_ACC_X_MSB__LEN));
+ break;
+ case 2:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_X8_LSB__REG, data, 2);
+ *a_x = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_X8_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_X_MSB)<<(BMA2X2_ACC_X8_LSB__LEN));
+ *a_x = *a_x << (sizeof(short)*8-(BMA2X2_ACC_X8_LSB__LEN
+ + BMA2X2_ACC_X_MSB__LEN));
+ *a_x = *a_x >> (sizeof(short)*8-(BMA2X2_ACC_X8_LSB__LEN
+ + BMA2X2_ACC_X_MSB__LEN));
+ break;
+ case 3:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_X14_LSB__REG, data, 2);
+ *a_x = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_X14_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_X_MSB)<<(BMA2X2_ACC_X14_LSB__LEN));
+ *a_x = *a_x << (sizeof(short)*8-(BMA2X2_ACC_X14_LSB__LEN
+ + BMA2X2_ACC_X_MSB__LEN));
+ *a_x = *a_x >> (sizeof(short)*8-(BMA2X2_ACC_X14_LSB__LEN
+ + BMA2X2_ACC_X_MSB__LEN));
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+static int bma2x2_soft_reset(struct i2c_client *client)
+{
+ int comres = 0;
+ unsigned char data = BMA2X2_EN_SOFT_RESET_VALUE ;
+
+ comres = bma2x2_smbus_write_byte(client, BMA2X2_EN_SOFT_RESET__REG,
+ &data);
+
+ return comres;
+}
+
+static int bma2x2_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 = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_Y12_LSB__REG, data, 2);
+ *a_y = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_Y12_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_Y_MSB)<<(BMA2X2_ACC_Y12_LSB__LEN));
+ *a_y = *a_y << (sizeof(short)*8-(BMA2X2_ACC_Y12_LSB__LEN
+ + BMA2X2_ACC_Y_MSB__LEN));
+ *a_y = *a_y >> (sizeof(short)*8-(BMA2X2_ACC_Y12_LSB__LEN
+ + BMA2X2_ACC_Y_MSB__LEN));
+ break;
+ case 1:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_Y10_LSB__REG, data, 2);
+ *a_y = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_Y10_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_Y_MSB)<<(BMA2X2_ACC_Y10_LSB__LEN));
+ *a_y = *a_y << (sizeof(short)*8-(BMA2X2_ACC_Y10_LSB__LEN
+ + BMA2X2_ACC_Y_MSB__LEN));
+ *a_y = *a_y >> (sizeof(short)*8-(BMA2X2_ACC_Y10_LSB__LEN
+ + BMA2X2_ACC_Y_MSB__LEN));
+ break;
+ case 2:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_Y8_LSB__REG, data, 2);
+ *a_y = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_Y8_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_Y_MSB)<<(BMA2X2_ACC_Y8_LSB__LEN));
+ *a_y = *a_y << (sizeof(short)*8-(BMA2X2_ACC_Y8_LSB__LEN
+ + BMA2X2_ACC_Y_MSB__LEN));
+ *a_y = *a_y >> (sizeof(short)*8-(BMA2X2_ACC_Y8_LSB__LEN
+ + BMA2X2_ACC_Y_MSB__LEN));
+ break;
+ case 3:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_Y14_LSB__REG, data, 2);
+ *a_y = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_Y14_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_Y_MSB)<<(BMA2X2_ACC_Y14_LSB__LEN));
+ *a_y = *a_y << (sizeof(short)*8-(BMA2X2_ACC_Y14_LSB__LEN
+ + BMA2X2_ACC_Y_MSB__LEN));
+ *a_y = *a_y >> (sizeof(short)*8-(BMA2X2_ACC_Y14_LSB__LEN
+ + BMA2X2_ACC_Y_MSB__LEN));
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+static int bma2x2_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 = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_Z12_LSB__REG, data, 2);
+ *a_z = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_Z12_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_Z_MSB)<<(BMA2X2_ACC_Z12_LSB__LEN));
+ *a_z = *a_z << (sizeof(short)*8-(BMA2X2_ACC_Z12_LSB__LEN
+ + BMA2X2_ACC_Z_MSB__LEN));
+ *a_z = *a_z >> (sizeof(short)*8-(BMA2X2_ACC_Z12_LSB__LEN
+ + BMA2X2_ACC_Z_MSB__LEN));
+ break;
+ case 1:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_Z10_LSB__REG, data, 2);
+ *a_z = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_Z10_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_Z_MSB)<<(BMA2X2_ACC_Z10_LSB__LEN));
+ *a_z = *a_z << (sizeof(short)*8-(BMA2X2_ACC_Z10_LSB__LEN
+ + BMA2X2_ACC_Z_MSB__LEN));
+ *a_z = *a_z >> (sizeof(short)*8-(BMA2X2_ACC_Z10_LSB__LEN
+ + BMA2X2_ACC_Z_MSB__LEN));
+ break;
+ case 2:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_Z8_LSB__REG, data, 2);
+ *a_z = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_Z8_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_Z_MSB)<<(BMA2X2_ACC_Z8_LSB__LEN));
+ *a_z = *a_z << (sizeof(short)*8-(BMA2X2_ACC_Z8_LSB__LEN
+ + BMA2X2_ACC_Z_MSB__LEN));
+ *a_z = *a_z >> (sizeof(short)*8-(BMA2X2_ACC_Z8_LSB__LEN
+ + BMA2X2_ACC_Z_MSB__LEN));
+ break;
+ case 3:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_Z14_LSB__REG, data, 2);
+ *a_z = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_Z14_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_Z_MSB)<<(BMA2X2_ACC_Z14_LSB__LEN));
+ *a_z = *a_z << (sizeof(short)*8-(BMA2X2_ACC_Z14_LSB__LEN
+ + BMA2X2_ACC_Z_MSB__LEN));
+ *a_z = *a_z >> (sizeof(short)*8-(BMA2X2_ACC_Z14_LSB__LEN
+ + BMA2X2_ACC_Z_MSB__LEN));
+ break;
+ default:
+ break;
+ }
+
+ return comres;
+}
+
+
+static int bma2x2_read_temperature(struct i2c_client *client,
+ signed char *temperature)
+{
+ unsigned char data;
+ int comres = 0;
+
+ comres = bma2x2_smbus_read_byte(client, BMA2X2_TEMPERATURE_REG, &data);
+ *temperature = (signed char)data;
+
+ return comres;
+}
+
+static int bma2x2_open_cal(struct i2c_client *client)
+{
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ int cal_data[3];
+ int err;
+ mm_segment_t old_fs;
+ struct file *cal_filp = NULL;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(CALIBRATION_FILE_PATH,
+ O_RDONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ pr_err("[BMC150] %s: Can't open calibration file\n",
+ __func__);
+ set_fs(old_fs);
+ err = PTR_ERR(cal_filp);
+ return err;
+ }
+
+ err = cal_filp->f_op->read(cal_filp,
+ (char *)cal_data,
+ 3 * sizeof(int), &cal_filp->f_pos);
+ if (err != 3 * sizeof(int)) {
+ pr_err("[BMC150] %s: Can't read the cal data from file\n",
+ __func__);
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+ return -EIO;
+ }
+
+ printk(KERN_INFO "[BMC150] %s (%d,%d,%d)",__func__, cal_data[0],cal_data[1],cal_data[2]);
+
+ bma2x2_set_offset_x(bma2x2->bma2x2_client, (unsigned char)cal_data[0]);
+ bma2x2_set_offset_y(bma2x2->bma2x2_client, (unsigned char)cal_data[1]);
+ bma2x2_set_offset_z(bma2x2->bma2x2_client, (unsigned char)cal_data[2]);
+
+ return 0;
+
+}
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ sscanf(buf, "%d%d", &type, &value);
+
+ if (bma2x2_set_Int_Enable(bma2x2->bma2x2_client, type, value) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+static ssize_t bma2x2_int_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_Int_Mode(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_Int_Mode(bma2x2->bma2x2_client, (unsigned char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t bma2x2_slope_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_slope_duration(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_slope_duration(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_slope_no_mot_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_slope_no_mot_duration(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_slope_no_mot_duration(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+static ssize_t bma2x2_slope_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_slope_threshold(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_slope_threshold(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_slope_no_mot_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_slope_no_mot_threshold(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_slope_no_mot_threshold(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_high_g_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_high_g_duration(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_high_g_duration(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_high_g_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_high_g_threshold(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_high_g_threshold(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_low_g_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_low_g_duration(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_low_g_duration(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_low_g_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_low_g_threshold(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_low_g_threshold(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t bma2x2_tap_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_tap_threshold(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_tap_threshold(bma2x2->bma2x2_client, (unsigned char)data)
+ < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t bma2x2_tap_duration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_tap_duration(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_tap_duration(bma2x2->bma2x2_client, (unsigned char)data)
+ < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t bma2x2_tap_quiet_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_tap_quiet(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_tap_quiet(bma2x2->bma2x2_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_tap_shock_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_tap_shock(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_tap_shock(bma2x2->bma2x2_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_tap_samp_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_tap_samp(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_tap_samp(bma2x2->bma2x2_client, (unsigned char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_orient_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_orient_mode(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_orient_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_orient_mode(bma2x2->bma2x2_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_orient_blocking_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_orient_blocking(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_orient_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_orient_blocking(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t bma2x2_orient_hyst_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_orient_hyst(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_orient_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_orient_hyst(bma2x2->bma2x2_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_orient_theta_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_theta_blocking(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_orient_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_theta_blocking(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_flat_theta_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_theta_flat(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_theta_flat(bma2x2->bma2x2_client, (unsigned char)data) <
+ 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t bma2x2_flat_hold_time_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_flat_hold_time(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+static ssize_t bma2x2_selftest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", atomic_read(&bma2x2->selftest_result));
+
+}
+
+static ssize_t bma2x2_softreset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_soft_reset(bma2x2->bma2x2_client) < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t bma2x2_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;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ bma2x2_soft_reset(bma2x2->bma2x2_client);
+ mdelay(5);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (data != 1)
+ return -EINVAL;
+
+ bma2x2_write_reg(bma2x2->bma2x2_client, 0x32, &clear_value);
+
+ if ((bma2x2->sensor_type == BMA280_TYPE) ||
+ (bma2x2->sensor_type == BMA255_TYPE)) {
+ /* set to 4 G range */
+ if (bma2x2_set_range(bma2x2->bma2x2_client, 5) < 0)
+ return -EINVAL;
+ }
+
+ if ((bma2x2->sensor_type == BMA250E_TYPE) ||
+ (bma2x2->sensor_type == BMA222E_TYPE)) {
+ /* set to 8 G range */
+ if (bma2x2_set_range(bma2x2->bma2x2_client, 8) < 0)
+ return -EINVAL;
+ if (bma2x2_set_selftest_amp(bma2x2->bma2x2_client, 1) < 0)
+ return -EINVAL;
+ }
+
+ bma2x2_set_selftest_st(bma2x2->bma2x2_client, 1); /* 1 for x-axis*/
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 0); /* positive
+ direction*/
+ mdelay(10);
+ bma2x2_read_accel_x(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value1);
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 1); /* negative
+ direction*/
+ mdelay(10);
+ bma2x2_read_accel_x(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value2);
+ diff = value1-value2;
+
+ printk(KERN_INFO "diff x is %d,value1 is %d, value2 is %d\n", diff,
+ value1, value2);
+
+ if (bma2x2->sensor_type == BMA280_TYPE) {
+ if (abs(diff) < 1638)
+ result |= 1;
+ }
+ if (bma2x2->sensor_type == BMA255_TYPE) {
+ if (abs(diff) < 409)
+ result |= 1;
+ }
+ if (bma2x2->sensor_type == BMA250E_TYPE) {
+ if (abs(diff) < 51)
+ result |= 1;
+ }
+ if (bma2x2->sensor_type == BMA222E_TYPE) {
+ if (abs(diff) < 12)
+ result |= 1;
+ }
+
+ bma2x2_set_selftest_st(bma2x2->bma2x2_client, 2); /* 2 for y-axis*/
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 0); /* positive
+ direction*/
+ mdelay(10);
+ bma2x2_read_accel_y(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value1);
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 1); /* negative
+ direction*/
+ mdelay(10);
+ bma2x2_read_accel_y(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value2);
+ diff = value1-value2;
+ printk(KERN_INFO "diff y is %d,value1 is %d, value2 is %d\n", diff,
+ value1, value2);
+
+ if (bma2x2->sensor_type == BMA280_TYPE) {
+ if (abs(diff) < 1638)
+ result |= 2;
+ }
+ if (bma2x2->sensor_type == BMA255_TYPE) {
+ if (abs(diff) < 409)
+ result |= 2;
+ }
+ if (bma2x2->sensor_type == BMA250E_TYPE) {
+ if (abs(diff) < 51)
+ result |= 2;
+ }
+ if (bma2x2->sensor_type == BMA222E_TYPE) {
+ if (abs(diff) < 12)
+ result |= 2;
+ }
+
+
+ bma2x2_set_selftest_st(bma2x2->bma2x2_client, 3); /* 3 for z-axis*/
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 0); /* positive
+ direction*/
+ mdelay(10);
+ bma2x2_read_accel_z(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value1);
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 1); /* negative
+ direction*/
+ mdelay(10);
+ bma2x2_read_accel_z(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value2);
+ diff = value1-value2;
+
+ printk(KERN_INFO "diff z is %d,value1 is %d, value2 is %d\n", diff,
+ value1, value2);
+
+ if (bma2x2->sensor_type == BMA280_TYPE) {
+ if (abs(diff) < 819)
+ result |= 4;
+ }
+ if (bma2x2->sensor_type == BMA255_TYPE) {
+ if (abs(diff) < 204)
+ result |= 4;
+ }
+ if (bma2x2->sensor_type == BMA250E_TYPE) {
+ if (abs(diff) < 25)
+ result |= 4;
+ }
+ if (bma2x2->sensor_type == BMA222E_TYPE) {
+ if (abs(diff) < 6)
+ result |= 4;
+ }
+
+ /* self test for bma254 */
+ if ((bma2x2->sensor_type == BMA255_TYPE) && (result > 0)) {
+ result = 0;
+ bma2x2_soft_reset(bma2x2->bma2x2_client);
+ mdelay(5);
+ bma2x2_write_reg(bma2x2->bma2x2_client, 0x32, &clear_value);
+ /* set to 8 G range */
+ if (bma2x2_set_range(bma2x2->bma2x2_client, 8) < 0)
+ return -EINVAL;
+ if (bma2x2_set_selftest_amp(bma2x2->bma2x2_client, 1) < 0)
+ return -EINVAL;
+
+ bma2x2_set_selftest_st(bma2x2->bma2x2_client, 1); /* 1
+ for x-axis*/
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 0); /*
+ positive direction*/
+ mdelay(10);
+ bma2x2_read_accel_x(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value1);
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 1); /*
+ negative direction*/
+ mdelay(10);
+ bma2x2_read_accel_x(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value2);
+ diff = value1-value2;
+
+ printk(KERN_INFO "diff x is %d,value1 is %d, value2 is %d\n",
+ diff, value1, value2);
+ if (abs(diff) < 204)
+ result |= 1;
+
+ bma2x2_set_selftest_st(bma2x2->bma2x2_client, 2); /* 2
+ for y-axis*/
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 0); /*
+ positive direction*/
+ mdelay(10);
+ bma2x2_read_accel_y(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value1);
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 1); /*
+ negative direction*/
+ mdelay(10);
+ bma2x2_read_accel_y(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value2);
+ diff = value1-value2;
+ printk(KERN_INFO "diff y is %d,value1 is %d, value2 is %d\n",
+ diff, value1, value2);
+
+ if (abs(diff) < 204)
+ result |= 2;
+
+ bma2x2_set_selftest_st(bma2x2->bma2x2_client, 3); /* 3
+ for z-axis*/
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 0); /*
+ positive direction*/
+ mdelay(10);
+ bma2x2_read_accel_z(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value1);
+ bma2x2_set_selftest_stn(bma2x2->bma2x2_client, 1); /*
+ negative direction*/
+ mdelay(10);
+ bma2x2_read_accel_z(bma2x2->bma2x2_client,
+ bma2x2->sensor_type, &value2);
+ diff = value1-value2;
+
+ printk(KERN_INFO "diff z is %d,value1 is %d, value2 is %d\n",
+ diff, value1, value2);
+ if (abs(diff) < 102)
+ result |= 4;
+ }
+
+ atomic_set(&bma2x2->selftest_result, (unsigned int)result);
+
+ bma2x2_soft_reset(bma2x2->bma2x2_client);
+ mdelay(5);
+ printk(KERN_INFO "self test finished\n");
+
+ return count;
+}
+
+
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_flat_hold_time(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+
+static int bma2x2_read_accel_xyz(struct i2c_client *client,
+ signed char sensor_type, struct bma2x2acc *acc)
+{
+ int comres = 0;
+ unsigned char data[6];
+ struct bma2x2_data *client_data = i2c_get_clientdata(client);
+
+#ifdef BMA2X2_SENSOR_IDENTIFICATION_ENABLE
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_X12_LSB__REG, data, 6);
+ acc->x = (data[1]<<8)|data[0];
+ acc->y = (data[3]<<8)|data[2];
+ acc->z = (data[5]<<8)|data[4];
+
+#else
+ switch (sensor_type) {
+ case 0:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_X12_LSB__REG, data, 6);
+ acc->x = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_X12_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_X_MSB)<<(BMA2X2_ACC_X12_LSB__LEN));
+ acc->x = acc->x << (sizeof(short)*8-(BMA2X2_ACC_X12_LSB__LEN +
+ BMA2X2_ACC_X_MSB__LEN));
+ acc->x = acc->x >> (sizeof(short)*8-(BMA2X2_ACC_X12_LSB__LEN +
+ BMA2X2_ACC_X_MSB__LEN));
+
+ acc->y = BMA2X2_GET_BITSLICE(data[2], BMA2X2_ACC_Y12_LSB)|
+ (BMA2X2_GET_BITSLICE(data[3],
+ BMA2X2_ACC_Y_MSB)<<(BMA2X2_ACC_Y12_LSB__LEN
+ ));
+ acc->y = acc->y << (sizeof(short)*8-(BMA2X2_ACC_Y12_LSB__LEN +
+ BMA2X2_ACC_Y_MSB__LEN));
+ acc->y = acc->y >> (sizeof(short)*8-(BMA2X2_ACC_Y12_LSB__LEN +
+ BMA2X2_ACC_Y_MSB__LEN));
+
+ acc->z = BMA2X2_GET_BITSLICE(data[4], BMA2X2_ACC_Z12_LSB)|
+ (BMA2X2_GET_BITSLICE(data[5],
+ BMA2X2_ACC_Z_MSB)<<(BMA2X2_ACC_Z12_LSB__LEN));
+ acc->z = acc->z << (sizeof(short)*8-(BMA2X2_ACC_Z12_LSB__LEN +
+ BMA2X2_ACC_Z_MSB__LEN));
+ acc->z = acc->z >> (sizeof(short)*8-(BMA2X2_ACC_Z12_LSB__LEN +
+ BMA2X2_ACC_Z_MSB__LEN));
+ break;
+ case 1:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_X10_LSB__REG, data, 6);
+ acc->x = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_X10_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_X_MSB)<<(BMA2X2_ACC_X10_LSB__LEN));
+ acc->x = acc->x << (sizeof(short)*8-(BMA2X2_ACC_X10_LSB__LEN +
+ BMA2X2_ACC_X_MSB__LEN));
+ acc->x = acc->x >> (sizeof(short)*8-(BMA2X2_ACC_X10_LSB__LEN +
+ BMA2X2_ACC_X_MSB__LEN));
+
+ acc->y = BMA2X2_GET_BITSLICE(data[2], BMA2X2_ACC_Y10_LSB)|
+ (BMA2X2_GET_BITSLICE(data[3],
+ BMA2X2_ACC_Y_MSB)<<(BMA2X2_ACC_Y10_LSB__LEN
+ ));
+ acc->y = acc->y << (sizeof(short)*8-(BMA2X2_ACC_Y10_LSB__LEN +
+ BMA2X2_ACC_Y_MSB__LEN));
+ acc->y = acc->y >> (sizeof(short)*8-(BMA2X2_ACC_Y10_LSB__LEN +
+ BMA2X2_ACC_Y_MSB__LEN));
+
+ acc->z = BMA2X2_GET_BITSLICE(data[4], BMA2X2_ACC_Z10_LSB)|
+ (BMA2X2_GET_BITSLICE(data[5],
+ BMA2X2_ACC_Z_MSB)<<(BMA2X2_ACC_Z10_LSB__LEN));
+ acc->z = acc->z << (sizeof(short)*8-(BMA2X2_ACC_Z10_LSB__LEN +
+ BMA2X2_ACC_Z_MSB__LEN));
+ acc->z = acc->z >> (sizeof(short)*8-(BMA2X2_ACC_Z10_LSB__LEN +
+ BMA2X2_ACC_Z_MSB__LEN));
+ break;
+ case 2:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_X8_LSB__REG, data, 6);
+ acc->x = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_X8_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_X_MSB)<<(BMA2X2_ACC_X8_LSB__LEN));
+ acc->x = acc->x << (sizeof(short)*8-(BMA2X2_ACC_X8_LSB__LEN +
+ BMA2X2_ACC_X_MSB__LEN));
+ acc->x = acc->x >> (sizeof(short)*8-(BMA2X2_ACC_X8_LSB__LEN +
+ BMA2X2_ACC_X_MSB__LEN));
+
+ acc->y = BMA2X2_GET_BITSLICE(data[2], BMA2X2_ACC_Y8_LSB)|
+ (BMA2X2_GET_BITSLICE(data[3],
+ BMA2X2_ACC_Y_MSB)<<(BMA2X2_ACC_Y8_LSB__LEN
+ ));
+ acc->y = acc->y << (sizeof(short)*8-(BMA2X2_ACC_Y8_LSB__LEN +
+ BMA2X2_ACC_Y_MSB__LEN));
+ acc->y = acc->y >> (sizeof(short)*8-(BMA2X2_ACC_Y8_LSB__LEN +
+ BMA2X2_ACC_Y_MSB__LEN));
+
+ acc->z = BMA2X2_GET_BITSLICE(data[4], BMA2X2_ACC_Z8_LSB)|
+ (BMA2X2_GET_BITSLICE(data[5],
+ BMA2X2_ACC_Z_MSB)<<(BMA2X2_ACC_Z8_LSB__LEN));
+ acc->z = acc->z << (sizeof(short)*8-(BMA2X2_ACC_Z8_LSB__LEN +
+ BMA2X2_ACC_Z_MSB__LEN));
+ acc->z = acc->z >> (sizeof(short)*8-(BMA2X2_ACC_Z8_LSB__LEN +
+ BMA2X2_ACC_Z_MSB__LEN));
+ break;
+ case 3:
+ comres = bma2x2_smbus_read_byte_block(client,
+ BMA2X2_ACC_X14_LSB__REG, data, 6);
+ acc->x = BMA2X2_GET_BITSLICE(data[0], BMA2X2_ACC_X14_LSB)|
+ (BMA2X2_GET_BITSLICE(data[1],
+ BMA2X2_ACC_X_MSB)<<(BMA2X2_ACC_X14_LSB__LEN));
+ acc->x = acc->x << (sizeof(short)*8-(BMA2X2_ACC_X14_LSB__LEN +
+ BMA2X2_ACC_X_MSB__LEN));
+ acc->x = acc->x >> (sizeof(short)*8-(BMA2X2_ACC_X14_LSB__LEN +
+ BMA2X2_ACC_X_MSB__LEN));
+
+ acc->y = BMA2X2_GET_BITSLICE(data[2], BMA2X2_ACC_Y14_LSB)|
+ (BMA2X2_GET_BITSLICE(data[3],
+ BMA2X2_ACC_Y_MSB)<<(BMA2X2_ACC_Y14_LSB__LEN
+ ));
+ acc->y = acc->y << (sizeof(short)*8-(BMA2X2_ACC_Y14_LSB__LEN +
+ BMA2X2_ACC_Y_MSB__LEN));
+ acc->y = acc->y >> (sizeof(short)*8-(BMA2X2_ACC_Y14_LSB__LEN +
+ BMA2X2_ACC_Y_MSB__LEN));
+
+ acc->z = BMA2X2_GET_BITSLICE(data[4], BMA2X2_ACC_Z14_LSB)|
+ (BMA2X2_GET_BITSLICE(data[5],
+ BMA2X2_ACC_Z_MSB)<<(BMA2X2_ACC_Z14_LSB__LEN));
+ acc->z = acc->z << (sizeof(short)*8-(BMA2X2_ACC_Z14_LSB__LEN +
+ BMA2X2_ACC_Z_MSB__LEN));
+ acc->z = acc->z >> (sizeof(short)*8-(BMA2X2_ACC_Z14_LSB__LEN +
+ BMA2X2_ACC_Z_MSB__LEN));
+ break;
+ default:
+ break;
+ }
+#endif
+
+ bma2x2_remap_sensor_data(acc, client_data);
+ return comres;
+}
+
+static void bma2x2_work_func(struct work_struct *work)
+{
+ struct bma2x2_data *bma2x2 = container_of((struct delayed_work *)work,
+ struct bma2x2_data, work);
+ static struct bma2x2acc acc;
+ unsigned long delay = msecs_to_jiffies(atomic_read(&bma2x2->delay));
+
+ bma2x2_read_accel_xyz(bma2x2->bma2x2_client, bma2x2->sensor_type,
+ &acc);
+ input_report_abs(bma2x2->input, ABS_X, acc.x);
+ input_report_abs(bma2x2->input, ABS_Y, acc.y);
+ input_report_abs(bma2x2->input, ABS_Z, acc.z);
+ input_sync(bma2x2->input);
+
+ mutex_lock(&bma2x2->value_mutex);
+ bma2x2->value.x = acc.x;
+ bma2x2->value.y = acc.y;
+ bma2x2->value.z = acc.z;
+ mutex_unlock(&bma2x2->value_mutex);
+
+ schedule_delayed_work(&bma2x2->work, delay);
+}
+
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ sscanf(buf, "%d%d", &address, &value);
+ if (bma2x2_write_reg(bma2x2->bma2x2_client, (unsigned char)address,
+ (unsigned char *)&value) < 0)
+ return -EINVAL;
+ return count;
+}
+static ssize_t bma2x2_register_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ size_t count = 0;
+ u8 reg[0x40];
+ int i;
+
+ for (i = 0; i < 0x40; i++) {
+ bma2x2_smbus_read_byte(bma2x2->bma2x2_client, i, reg+i);
+
+ count += sprintf(&buf[count], "0x%x: %d\n", i, reg[i]);
+ }
+ return count;
+
+
+}
+
+static ssize_t bma2x2_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_range(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_range(bma2x2->bma2x2_client, (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_bandwidth_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_bandwidth(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2->sensor_type == BMA280_TYPE)
+ if ((unsigned char) data > 14)
+ return -EINVAL;
+
+ if (bma2x2_set_bandwidth(bma2x2->bma2x2_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_mode(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_mode(bma2x2->bma2x2_client, (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+static ssize_t bma2x2_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bma2x2_data *bma2x2 = input_get_drvdata(input);
+ struct bma2x2acc acc_value;
+
+#if 0
+ bma2x2_read_accel_xyz(bma2x2->bma2x2_client, bma2x2->sensor_type,
+ &acc_value);
+#else
+ /* cache of last input event */
+ mutex_lock(&bma2x2->value_mutex);
+ acc_value.x = bma2x2->value.x;
+ acc_value.y = bma2x2->value.y;
+ acc_value.z = bma2x2->value.z;
+ mutex_unlock(&bma2x2->value_mutex);
+#endif
+
+ return sprintf(buf, "%d %d %d\n", acc_value.x, acc_value.y,
+ acc_value.z);
+}
+
+/* raw-data for sensor test */
+static ssize_t bma2x2_raw_data_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bma2x2_data *bma2x2 = input_get_drvdata(input);
+ struct bma2x2acc acc_value;
+#if 0
+ bma2x2_read_accel_xyz(bma2x2->bma2x2_client, bma2x2->sensor_type,
+ &acc_value);
+#else
+ /* cache of last input event */
+ mutex_lock(&bma2x2->value_mutex);
+ acc_value.x = bma2x2->value.x;
+ acc_value.y = bma2x2->value.y;
+ acc_value.z = bma2x2->value.z;
+ mutex_unlock(&bma2x2->value_mutex);
+
+#endif
+
+ acc_value.x = acc_value.x >>4;
+ acc_value.y = acc_value.y >>4;
+ acc_value.z = acc_value.z >>4;
+
+ return sprintf(buf, "%d,%d,%d\n", acc_value.x, acc_value.y,
+ acc_value.z);
+}
+
+static ssize_t bma2x2_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", atomic_read(&bma2x2->delay));
+
+}
+
+static ssize_t bma2x2_chip_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", bma2x2->chip_id);
+
+}
+
+
+static ssize_t bma2x2_place_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+#ifdef CONFIG_BMA_USE_PLATFORM_DATA
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+#endif
+ int place = BOSCH_SENSOR_PLACE_UNKNOWN;
+
+#ifdef CONFIG_BMA_USE_PLATFORM_DATA
+ if (NULL != bma2x2->bst_pd)
+ place = bma2x2->bst_pd->place;
+#endif
+
+ return sprintf(buf, "%d\n", place);
+}
+
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (data > BMA2X2_MAX_DELAY)
+ data = BMA2X2_MAX_DELAY;
+ atomic_set(&bma2x2->delay, (unsigned int) data);
+
+ return count;
+}
+
+
+static ssize_t bma2x2_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", atomic_read(&bma2x2->enable));
+
+}
+
+static void bma2x2_set_enable(struct device *dev, int enable)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+ int pre_enable = atomic_read(&bma2x2->enable);
+
+ mutex_lock(&bma2x2->enable_mutex);
+ if (enable) {
+ if (pre_enable == 0) {
+ bma2x2_set_mode(bma2x2->bma2x2_client,
+ BMA2X2_MODE_NORMAL);
+ schedule_delayed_work(&bma2x2->work,
+ msecs_to_jiffies(atomic_read(&bma2x2->delay)));
+ atomic_set(&bma2x2->enable, 1);
+ }
+
+ } else {
+ if (pre_enable == 1) {
+ bma2x2_set_mode(bma2x2->bma2x2_client,
+ BMA2X2_MODE_SUSPEND);
+ cancel_delayed_work_sync(&bma2x2->work);
+ atomic_set(&bma2x2->enable, 0);
+ }
+ }
+ mutex_unlock(&bma2x2->enable_mutex);
+
+}
+
+static ssize_t bma2x2_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if ((data == 0) || (data == 1))
+ bma2x2_set_enable(dev, data);
+
+
+ return count;
+}
+static ssize_t bma2x2_fast_calibration_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_offset_target(bma2x2->bma2x2_client, 1, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_offset_target(bma2x2->bma2x2_client, 1, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ if (bma2x2_set_cal_trigger(bma2x2->bma2x2_client, 1) < 0)
+ return -EINVAL;
+
+ do {
+ mdelay(2);
+ bma2x2_get_cal_ready(bma2x2->bma2x2_client, &tmp);
+
+/* printk(KERN_INFO "wait 2ms cal ready flag is %d\n", tmp);
+ */
+ timeout++;
+ if (timeout == 50) {
+ printk(KERN_INFO "get fast calibration ready error\n");
+ return -EINVAL;
+ };
+
+ } while (tmp == 0);
+
+ printk(KERN_INFO "x axis fast calibration finished\n");
+ return count;
+}
+
+static ssize_t bma2x2_fast_calibration_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_offset_target(bma2x2->bma2x2_client, 2, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_offset_target(bma2x2->bma2x2_client, 2, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ if (bma2x2_set_cal_trigger(bma2x2->bma2x2_client, 2) < 0)
+ return -EINVAL;
+
+ do {
+ mdelay(2);
+ bma2x2_get_cal_ready(bma2x2->bma2x2_client, &tmp);
+
+/* printk(KERN_INFO "wait 2ms cal ready flag is %d\n", tmp);
+ */
+ timeout++;
+ if (timeout == 50) {
+ printk(KERN_INFO "get fast calibration ready error\n");
+ return -EINVAL;
+ };
+
+ } while (tmp == 0);
+
+ printk(KERN_INFO "y axis fast calibration finished\n");
+ return count;
+}
+
+static ssize_t bma2x2_fast_calibration_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_offset_target(bma2x2->bma2x2_client, 3, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_offset_target(bma2x2->bma2x2_client, 3, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ if (bma2x2_set_cal_trigger(bma2x2->bma2x2_client, 3) < 0)
+ return -EINVAL;
+
+ do {
+ mdelay(2);
+ bma2x2_get_cal_ready(bma2x2->bma2x2_client, &tmp);
+
+/* printk(KERN_INFO "wait 2ms cal ready flag is %d\n", tmp);
+ */
+ timeout++;
+ if (timeout == 50) {
+ printk(KERN_INFO "get fast calibration ready error\n");
+ return -EINVAL;
+ };
+
+ } while (tmp == 0);
+
+ printk(KERN_INFO "z axis fast calibration finished\n");
+ return count;
+}
+static ssize_t accel_calibration_open(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ bma2x2_open_cal(client);
+ return 1;
+}
+
+
+static ssize_t bma2x2_calibration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ /*struct i2c_client *client = to_i2c_client(dev);*/
+ /*struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);*/
+ int cal_data[3];
+ int err;
+ mm_segment_t old_fs;
+ struct file *cal_filp = NULL;
+ int result = 1;
+
+ printk(KERN_INFO "[BMC150] %s\n", __func__);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(CALIBRATION_FILE_PATH,
+ O_RDONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ pr_err("[BMC150] %s: Can't open calibration file\n",
+ __func__);
+ set_fs(old_fs);
+ err = PTR_ERR(cal_filp);
+ return err;
+ }
+ err = cal_filp->f_op->read(cal_filp,
+ (char *)cal_data,
+ 3 * sizeof(int), &cal_filp->f_pos);
+ if (err != 3 * sizeof(int)) {
+ pr_err("[BMC150] %s: Can't read the cal data from file\n",
+ __func__);
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+ return -EIO;
+ }
+ if (((cal_data[0] == 0) &&(cal_data[1] == 0) &&(cal_data[2] == 0)))
+ result = 0;
+
+ printk(KERN_INFO "[BMC150] %s: result=%d, (%d,%d,%d)",__func__, result, cal_data[0],cal_data[1],cal_data[2]);
+
+ return sprintf(buf, "%d %d %d %d\n", result, cal_data[0],cal_data[1],cal_data[2]);
+
+}
+
+static ssize_t bma2x2_calibration_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+ int cal_data[3];
+ unsigned long data;
+ unsigned char mode;
+ signed char tmp;
+ unsigned char timeout = 0;
+ int err;
+ mm_segment_t old_fs;
+ struct file *cal_filp = NULL;
+
+ err = strict_strtoul(buf, 10, &data);
+ if (err) {
+ printk(KERN_ERR "[BMC150] %s: error(%d)\n", __func__, (unsigned char) data);
+ return err;
+ }
+
+ printk(KERN_INFO "[BMC150] %s: %d\n", __func__, (unsigned char) data);
+
+ if (bma2x2_get_mode(bma2x2->bma2x2_client, &mode) < 0) {
+ printk(KERN_ERR "[BMC150] %s: bma2x2_get_mode error\n", __func__);
+ return -EINVAL;
+ }
+
+ if (mode != BMA2X2_MODE_NORMAL) {
+ printk(KERN_INFO "[BMC150] %s: bma2x2_get_mode %d\n", __func__, mode);
+ bma2x2_set_mode(bma2x2->bma2x2_client, BMA2X2_MODE_NORMAL);
+ }
+
+ if(data){
+ /* check the current z value and set offset_target_z based on it */
+ short acc_value_z = 0;
+ unsigned char offset_target_z = 0;
+ bma2x2_read_accel_z(bma2x2->bma2x2_client, bma2x2->sensor_type,
+ &acc_value_z);
+ printk(KERN_INFO "[BMC150] acc_value_z = [%d], while accel calibration\n", acc_value_z);
+ if(acc_value_z > 0)
+ offset_target_z = 1;
+ else
+ offset_target_z = 2;
+
+ /* x axis fast calibration */
+ if (bma2x2_set_offset_target(bma2x2->bma2x2_client, 1, (unsigned
+ char)0) < 0)
+ return -EINVAL;
+
+ if (bma2x2_set_cal_trigger(bma2x2->bma2x2_client, 1) < 0)
+ return -EINVAL;
+
+
+ do {
+ mdelay(50);
+ bma2x2_get_cal_ready(bma2x2->bma2x2_client, &tmp);
+ timeout++;
+ if (timeout == 50) {
+ printk(KERN_INFO "[BMC150] x get fast calibration ready error\n");
+ return -EINVAL;
+ };
+ } while (tmp == 0);
+
+ printk(KERN_INFO "[BMC150] x axis fast calibration DONE\n");
+
+ /* y axis fast calibration */
+ if (bma2x2_set_offset_target(bma2x2->bma2x2_client, 2, (unsigned
+ char)0) < 0)
+ return -EINVAL;
+
+ if (bma2x2_set_cal_trigger(bma2x2->bma2x2_client, 2) < 0)
+ return -EINVAL;
+
+ do {
+ mdelay(50);
+ bma2x2_get_cal_ready(bma2x2->bma2x2_client, &tmp);
+ timeout++;
+ if (timeout == 50) {
+ printk(KERN_INFO "[BMC150] y get fast calibration ready error\n");
+ return -EINVAL;
+ };
+ } while (tmp == 0);
+
+ printk(KERN_INFO "[BMC150] y axis fast calibration DONE\n");
+ /* z axis fast calibration */
+ /* check the current z value and set offset_target_z based on it */
+ if (bma2x2_set_offset_target(bma2x2->bma2x2_client, 3, offset_target_z) < 0)
+ return -EINVAL;
+
+ if (bma2x2_set_cal_trigger(bma2x2->bma2x2_client, 3) < 0)
+ return -EINVAL;
+
+ do {
+ mdelay(50);
+ bma2x2_get_cal_ready(bma2x2->bma2x2_client, &tmp);
+ timeout++;
+ if (timeout == 50) {
+ printk(KERN_INFO "[BMC150] z get fast calibration ready error\n");
+ return -EINVAL;
+ };
+ printk(KERN_INFO "[BMC150] z axis fast calibration DONE\n");
+ } while (tmp == 0);
+
+ /* calibration */
+ bma2x2_get_offset_x(bma2x2->bma2x2_client, (unsigned char*)&cal_data[0]);
+ bma2x2_get_offset_y(bma2x2->bma2x2_client, (unsigned char*)&cal_data[1]);
+ bma2x2_get_offset_z(bma2x2->bma2x2_client, (unsigned char*)&cal_data[2]);
+
+ printk(KERN_INFO "[BMC150] %s: (%d,%d,%d)",__func__, cal_data[0],cal_data[1],cal_data[2]);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ cal_filp = filp_open(CALIBRATION_FILE_PATH,
+ O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666);
+ if (IS_ERR(cal_filp)) {
+ pr_err("[BMC150] %s: Can't open calibration file\n",
+ __func__);
+ set_fs(old_fs);
+ err = PTR_ERR(cal_filp);
+ return err;
+ }
+
+ err = cal_filp->f_op->write(cal_filp,
+ (char *)cal_data,
+ 3 * sizeof(int), &cal_filp->f_pos);
+ if (err != 3 * sizeof(int)) {
+ pr_err("[BMC150] %s: Can't write the cal data to file\n",
+ __func__);
+ err = -EIO;
+ }
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+ }
+ else
+ {
+ /* erase cal data */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ cal_filp = filp_open(CALIBRATION_FILE_PATH,
+ O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666);
+ if (IS_ERR(cal_filp)) {
+ pr_err("[BMC150] %s: Can't open calibration file\n",
+ __func__);
+ set_fs(old_fs);
+ err = PTR_ERR(cal_filp);
+ return err;
+ }
+ cal_data[0] = 0;
+ cal_data[1] = 0;
+ cal_data[2] = 0;
+
+ err = cal_filp->f_op->write(cal_filp,
+ (char *)cal_data,
+ 3 * sizeof(int), &cal_filp->f_pos);
+ if (err != 3 * sizeof(int)) {
+ pr_err("[BMC150] %s: Can't write the cal data to file\n",
+ __func__);
+ err = -EIO;
+ }
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+
+ bma2x2_set_offset_x(bma2x2->bma2x2_client, (unsigned char)cal_data[0]);
+ bma2x2_set_offset_y(bma2x2->bma2x2_client, (unsigned char)cal_data[1]);
+ bma2x2_set_offset_z(bma2x2->bma2x2_client, (unsigned char)cal_data[2]);
+ }
+
+ return count;
+}
+
+
+static ssize_t bma2x2_SleepDur_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_sleep_duration(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_sleep_duration(bma2x2->bma2x2_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_fifo_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_fifo_mode(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_fifo_mode(bma2x2->bma2x2_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+
+static ssize_t bma2x2_fifo_trig_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_fifo_trig(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_fifo_trig(bma2x2->bma2x2_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+
+static ssize_t bma2x2_fifo_trig_src_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_fifo_trig_src(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_fifo_trig_src(bma2x2->bma2x2_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+
+static ssize_t bma2x2_fifo_data_sel_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_fifo_data_sel(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_fifo_framecount_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_fifo_framecount(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_temperature_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_read_temperature(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (bma2x2_set_fifo_data_sel(bma2x2->bma2x2_client,
+ (unsigned char) data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+
+static ssize_t bma2x2_fifo_data_out_frame_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ int err, i, len;
+ signed char fifo_data_out[MAX_FIFO_F_LEVEL * MAX_FIFO_F_BYTES] = {0};
+ unsigned char f_count, f_len = 0;
+ unsigned char fifo_datasel = 0;
+
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_fifo_data_sel(bma2x2->bma2x2_client, &fifo_datasel) < 0)
+ return sprintf(buf, "Read data sel error\n");
+
+ if (fifo_datasel)
+ f_len = 2;
+ else
+ f_len = 6;
+
+ if (bma2x2_get_fifo_framecount(bma2x2->bma2x2_client, &f_count) < 0)
+ return sprintf(buf, "Read frame count error\n");
+
+
+ if (bma_i2c_burst_read(bma2x2->bma2x2_client,
+ BMA2X2_FIFO_DATA_OUTPUT_REG, fifo_data_out,
+ f_count * f_len) < 0)
+ return sprintf(buf, "Read byte block error\n");
+
+
+ if (bma2x2_get_fifo_data_out_reg(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ err = 0;
+
+ len = sprintf(buf, "%lu ", jiffies);
+ buf += len;
+ err += len;
+
+ len = sprintf(buf, "%u ", f_count);
+ buf += len;
+ err += len;
+
+ len = sprintf(buf, "%u ", f_len);
+ buf += len;
+ err += len;
+
+ for (i = 0; i < f_count * f_len; i++) {
+ len = sprintf(buf, "%d ", fifo_data_out[i]);
+ buf += len;
+ err += len;
+ }
+
+ return err;
+
+}
+
+
+
+
+static ssize_t bma2x2_offset_x_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_offset_x(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_offset_x(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_offset_y_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_offset_y(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_offset_y(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t bma2x2_offset_z_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ if (bma2x2_get_offset_z(bma2x2->bma2x2_client, &data) < 0)
+ return sprintf(buf, "Read error\n");
+
+ return sprintf(buf, "%d\n", data);
+
+}
+
+static ssize_t bma2x2_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 bma2x2_data *bma2x2 = i2c_get_clientdata(client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+
+ if (bma2x2_set_offset_z(bma2x2->bma2x2_client, (unsigned
+ char)data) < 0)
+ return -EINVAL;
+
+ return count;
+}
+
+
+static DEVICE_ATTR(range, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_range_show, bma2x2_range_store);
+static DEVICE_ATTR(bandwidth, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_bandwidth_show, bma2x2_bandwidth_store);
+static DEVICE_ATTR(mode, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_mode_show, bma2x2_mode_store);
+static DEVICE_ATTR(value, S_IRUGO,
+ bma2x2_value_show, NULL);
+static DEVICE_ATTR(raw_data, S_IRUGO | S_IWUSR | S_IWGRP,
+ bma2x2_raw_data_show, NULL);
+static DEVICE_ATTR(delay, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_delay_show, bma2x2_delay_store);
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_enable_show, bma2x2_enable_store);
+static DEVICE_ATTR(SleepDur, S_IRUGO|S_IWUSR|S_IWGRP,
+ bma2x2_SleepDur_show, bma2x2_SleepDur_store);
+static DEVICE_ATTR(fast_calibration_x, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_fast_calibration_x_show,
+ bma2x2_fast_calibration_x_store);
+static DEVICE_ATTR(fast_calibration_y, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_fast_calibration_y_show,
+ bma2x2_fast_calibration_y_store);
+static DEVICE_ATTR(fast_calibration_z, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_fast_calibration_z_show,
+ bma2x2_fast_calibration_z_store);
+static DEVICE_ATTR(fifo_mode, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_fifo_mode_show, bma2x2_fifo_mode_store);
+static DEVICE_ATTR(fifo_framecount, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_fifo_framecount_show, NULL);
+static DEVICE_ATTR(fifo_trig, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_fifo_trig_show, bma2x2_fifo_trig_store);
+static DEVICE_ATTR(fifo_trig_src, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_fifo_trig_src_show, bma2x2_fifo_trig_src_store);
+static DEVICE_ATTR(fifo_data_sel, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_fifo_data_sel_show, bma2x2_fifo_data_sel_store);
+static DEVICE_ATTR(fifo_data_out_frame, S_IRUGO,
+ bma2x2_fifo_data_out_frame_show, NULL);
+static DEVICE_ATTR(reg, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_register_show, bma2x2_register_store);
+static DEVICE_ATTR(chip_id, S_IRUGO,
+ bma2x2_chip_id_show, NULL);
+static DEVICE_ATTR(offset_x, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_offset_x_show,
+ bma2x2_offset_x_store);
+static DEVICE_ATTR(offset_y, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_offset_y_show,
+ bma2x2_offset_y_store);
+static DEVICE_ATTR(offset_z, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_offset_z_show,
+ bma2x2_offset_z_store);
+static DEVICE_ATTR(enable_int, S_IWUSR|S_IWGRP|S_IWOTH,
+ NULL, bma2x2_enable_int_store);
+static DEVICE_ATTR(int_mode, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_int_mode_show, bma2x2_int_mode_store);
+static DEVICE_ATTR(slope_duration, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_slope_duration_show, bma2x2_slope_duration_store);
+static DEVICE_ATTR(slope_threshold, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_slope_threshold_show, bma2x2_slope_threshold_store);
+static DEVICE_ATTR(slope_no_mot_duration, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_slope_no_mot_duration_show,
+ bma2x2_slope_no_mot_duration_store);
+static DEVICE_ATTR(slope_no_mot_threshold, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_slope_no_mot_threshold_show,
+ bma2x2_slope_no_mot_threshold_store);
+static DEVICE_ATTR(high_g_duration, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_high_g_duration_show, bma2x2_high_g_duration_store);
+static DEVICE_ATTR(high_g_threshold, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_high_g_threshold_show, bma2x2_high_g_threshold_store);
+static DEVICE_ATTR(low_g_duration, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_low_g_duration_show, bma2x2_low_g_duration_store);
+static DEVICE_ATTR(low_g_threshold, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_low_g_threshold_show, bma2x2_low_g_threshold_store);
+static DEVICE_ATTR(tap_duration, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_tap_duration_show, bma2x2_tap_duration_store);
+static DEVICE_ATTR(tap_threshold, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_tap_threshold_show, bma2x2_tap_threshold_store);
+static DEVICE_ATTR(tap_quiet, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_tap_quiet_show, bma2x2_tap_quiet_store);
+static DEVICE_ATTR(tap_shock, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_tap_shock_show, bma2x2_tap_shock_store);
+static DEVICE_ATTR(tap_samp, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_tap_samp_show, bma2x2_tap_samp_store);
+static DEVICE_ATTR(orient_mode, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_orient_mode_show, bma2x2_orient_mode_store);
+static DEVICE_ATTR(orient_blocking, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_orient_blocking_show, bma2x2_orient_blocking_store);
+static DEVICE_ATTR(orient_hyst, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_orient_hyst_show, bma2x2_orient_hyst_store);
+static DEVICE_ATTR(orient_theta, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_orient_theta_show, bma2x2_orient_theta_store);
+static DEVICE_ATTR(flat_theta, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_flat_theta_show, bma2x2_flat_theta_store);
+static DEVICE_ATTR(flat_hold_time, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_flat_hold_time_show, bma2x2_flat_hold_time_store);
+static DEVICE_ATTR(selftest, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_selftest_show, bma2x2_selftest_store);
+static DEVICE_ATTR(softreset, S_IWUSR|S_IWGRP|S_IWOTH,
+ NULL, bma2x2_softreset_store);
+static DEVICE_ATTR(temperature, S_IRUGO,
+ bma2x2_temperature_show, NULL);
+static DEVICE_ATTR(place, S_IRUGO,
+ bma2x2_place_show, NULL);
+static DEVICE_ATTR(calibration, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
+ bma2x2_calibration_show,
+ bma2x2_calibration_store);
+static DEVICE_ATTR(accel_cal_open, S_IRUGO,
+ accel_calibration_open,NULL);
+
+static struct attribute *bma2x2_attributes[] = {
+ &dev_attr_range.attr,
+ &dev_attr_bandwidth.attr,
+ &dev_attr_mode.attr,
+ &dev_attr_value.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_out_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_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_mode.attr,
+ &dev_attr_orient_blocking.attr,
+ &dev_attr_orient_hyst.attr,
+ &dev_attr_orient_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_calibration.attr,
+ NULL
+};
+
+static struct attribute_group bma2x2_attribute_group = {
+ .attrs = bma2x2_attributes
+};
+
+
+
+
+#if defined(BMA2X2_ENABLE_INT1) || defined(BMA2X2_ENABLE_INT2)
+unsigned char *orient[] = {"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 bma2x2_irq_work_func(struct work_struct *work)
+{
+ struct bma2x2_data *bma2x2 = container_of((struct work_struct *)work,
+ struct bma2x2_data, irq_work);
+
+ unsigned char status = 0;
+ unsigned char i;
+ unsigned char first_value = 0;
+ unsigned char sign_value = 0;
+
+ bma2x2_get_interruptstatus1(bma2x2->bma2x2_client, &status);
+
+ switch (status) {
+
+ case 0x01:
+ printk(KERN_INFO "Low G interrupt happened\n");
+ input_report_rel(bma2x2->input, LOW_G_INTERRUPT,
+ LOW_G_INTERRUPT_HAPPENED);
+ break;
+ case 0x02:
+ for (i = 0; i < 3; i++) {
+ bma2x2_get_HIGH_first(bma2x2->bma2x2_client, i,
+ &first_value);
+ if (first_value == 1) {
+
+ bma2x2_get_HIGH_sign(bma2x2->bma2x2_client,
+ &sign_value);
+
+ if (sign_value == 1) {
+ if (i == 0)
+ input_report_rel(bma2x2->input,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_X_NEGATIVE_HAPPENED);
+ if (i == 1)
+ input_report_rel(bma2x2->input,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_Y_NEGATIVE_HAPPENED);
+ if (i == 2)
+ input_report_rel(bma2x2->input,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_Z_NEGATIVE_HAPPENED);
+ } else {
+ if (i == 0)
+ input_report_rel(bma2x2->input,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_X_HAPPENED);
+ if (i == 1)
+ input_report_rel(bma2x2->input,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_Y_HAPPENED);
+ if (i == 2)
+ input_report_rel(bma2x2->input,
+ HIGH_G_INTERRUPT,
+ HIGH_G_INTERRUPT_Z_HAPPENED);
+
+ }
+ }
+
+ printk(KERN_INFO "High G interrupt happened,exis is %d,"
+ "first is %d,sign is %d\n", i,
+ first_value, sign_value);
+ }
+ break;
+ case 0x04:
+ for (i = 0; i < 3; i++) {
+ bma2x2_get_slope_first(bma2x2->bma2x2_client, i,
+ &first_value);
+ if (first_value == 1) {
+
+ bma2x2_get_slope_sign(bma2x2->bma2x2_client,
+ &sign_value);
+
+ if (sign_value == 1) {
+ if (i == 0)
+ input_report_rel(bma2x2->input,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_X_NEGATIVE_HAPPENED);
+ else if (i == 1)
+ input_report_rel(bma2x2->input,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_Y_NEGATIVE_HAPPENED);
+ else if (i == 2)
+ input_report_rel(bma2x2->input,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_Z_NEGATIVE_HAPPENED);
+ } else {
+ if (i == 0)
+ input_report_rel(bma2x2->input,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_X_HAPPENED);
+ else if (i == 1)
+ input_report_rel(bma2x2->input,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_Y_HAPPENED);
+ else if (i == 2)
+ input_report_rel(bma2x2->input,
+ SLOP_INTERRUPT,
+ SLOPE_INTERRUPT_Z_HAPPENED);
+
+ }
+ }
+
+ printk(KERN_INFO "Slop interrupt happened,exis is %d,"
+ "first is %d,sign is %d\n", i,
+ first_value, sign_value);
+ }
+ break;
+
+ case 0x08:
+ printk(KERN_INFO "slow/ no motion interrupt happened\n");
+ input_report_rel(bma2x2->input, SLOW_NO_MOTION_INTERRUPT,
+ SLOW_NO_MOTION_INTERRUPT_HAPPENED);
+ break;
+
+ case 0x10:
+ printk(KERN_INFO "double tap interrupt happened\n");
+ input_report_rel(bma2x2->input, DOUBLE_TAP_INTERRUPT,
+ DOUBLE_TAP_INTERRUPT_HAPPENED);
+ break;
+ case 0x20:
+ printk(KERN_INFO "single tap interrupt happened\n");
+ input_report_rel(bma2x2->input, SINGLE_TAP_INTERRUPT,
+ SINGLE_TAP_INTERRUPT_HAPPENED);
+ break;
+ case 0x40:
+ bma2x2_get_orient_status(bma2x2->bma2x2_client,
+ &first_value);
+ printk(KERN_INFO "orient interrupt happened,%s\n",
+ orient[first_value]);
+ if (first_value == 0)
+ input_report_abs(bma2x2->input, ORIENT_INTERRUPT,
+ UPWARD_PORTRAIT_UP_INTERRUPT_HAPPENED);
+ else if (first_value == 1)
+ input_report_abs(bma2x2->input, ORIENT_INTERRUPT,
+ UPWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED);
+ else if (first_value == 2)
+ input_report_abs(bma2x2->input, ORIENT_INTERRUPT,
+ UPWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED);
+ else if (first_value == 3)
+ input_report_abs(bma2x2->input, ORIENT_INTERRUPT,
+ UPWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED);
+ else if (first_value == 4)
+ input_report_abs(bma2x2->input, ORIENT_INTERRUPT,
+ DOWNWARD_PORTRAIT_UP_INTERRUPT_HAPPENED);
+ else if (first_value == 5)
+ input_report_abs(bma2x2->input, ORIENT_INTERRUPT,
+ DOWNWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED);
+ else if (first_value == 6)
+ input_report_abs(bma2x2->input, ORIENT_INTERRUPT,
+ DOWNWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED);
+ else if (first_value == 7)
+ input_report_abs(bma2x2->input, ORIENT_INTERRUPT,
+ DOWNWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED);
+ break;
+ case 0x80:
+ bma2x2_get_orient_flat_status(bma2x2->bma2x2_client,
+ &sign_value);
+ printk(KERN_INFO "flat interrupt happened,flat status is %d\n",
+ sign_value);
+ if (sign_value == 1) {
+ input_report_abs(bma2x2->input, FLAT_INTERRUPT,
+ FLAT_INTERRUPT_TURE_HAPPENED);
+ } else {
+ input_report_abs(bma2x2->input, FLAT_INTERRUPT,
+ FLAT_INTERRUPT_FALSE_HAPPENED);
+ }
+ break;
+ default:
+ break;
+ }
+
+}
+
+static irqreturn_t bma2x2_irq_handler(int irq, void *handle)
+{
+
+
+ struct bma2x2_data *data = handle;
+
+
+ if (data == NULL)
+ return IRQ_HANDLED;
+ if (data->bma2x2_client == NULL)
+ return IRQ_HANDLED;
+
+
+ schedule_work(&data->irq_work);
+
+ return IRQ_HANDLED;
+
+
+}
+#endif /* defined(BMA2X2_ENABLE_INT1)||defined(BMA2X2_ENABLE_INT2) */
+
+
+
+static struct device_attribute *bma2X2_attrs[] = {
+ &dev_attr_raw_data,
+ &dev_attr_fast_calibration_x,
+ &dev_attr_fast_calibration_y,
+ &dev_attr_fast_calibration_z,
+ &dev_attr_calibration,
+ &dev_attr_accel_cal_open,
+ NULL,
+ };
+
+static int bma2x2_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+ int tempvalue;
+ unsigned char tmp_chip_id;
+ struct bma2x2_data *data;
+ struct input_dev *dev;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ printk(KERN_INFO "i2c_check_functionality error\n");
+ goto exit;
+ }
+ data = kzalloc(sizeof(struct bma2x2_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ /* read chip id */
+ tempvalue = i2c_smbus_read_word_data(client, BMA2X2_CHIP_ID_REG);
+ tmp_chip_id = tempvalue&0x00ff;
+ printk(KERN_ALERT" %s : CHIP ID vlaue of accel sensor \n",__func__);
+
+ switch (tmp_chip_id) {
+ case BMA255_CHIP_ID:
+ data->sensor_type = BMA255_TYPE;
+ break;
+ case BMA250E_CHIP_ID:
+ data->sensor_type = BMA250E_TYPE;
+ break;
+ case BMA222E_CHIP_ID:
+ data->sensor_type = BMA222E_TYPE;
+ break;
+ case BMA280_CHIP_ID:
+ data->sensor_type = BMA280_TYPE;
+ break;
+ default:
+ data->sensor_type = -1;
+ }
+ if (data->sensor_type != -1) {
+ data->chip_id = tmp_chip_id;
+ printk(KERN_INFO "Bosch Sensortec Device detected!\n"
+ "%s registered I2C driver!\n",
+ sensor_name[data->sensor_type]);
+ } else{
+ printk(KERN_INFO "Bosch Sensortec Device not found"
+ "i2c error %d\n", tempvalue);
+ err = -ENODEV;
+ goto kfree_exit;
+ }
+ i2c_set_clientdata(client, data);
+ data->bma2x2_client = client;
+ mutex_init(&data->value_mutex);
+ mutex_init(&data->mode_mutex);
+ mutex_init(&data->enable_mutex);
+
+ err = bma2x2_set_bandwidth(client, BMA2X2_BW_SET);
+ if (err < 0){
+ printk(KERN_INFO "%s set bandwidth failed!\n",
+ sensor_name[data->sensor_type]);
+ }
+
+ err = bma2x2_set_range(client, BMA2X2_RANGE_SET);
+ if (err < 0){
+ printk(KERN_INFO "%s set g-range failed!\n",
+ sensor_name[data->sensor_type]);
+ }
+
+
+#if defined(BMA2X2_ENABLE_INT1) || defined(BMA2X2_ENABLE_INT2)
+ bma2x2_set_Int_Mode(client, 1);/*latch interrupt 250ms*/
+#endif
+
+#ifdef BMA2X2_ENABLE_INT1
+ /* maps interrupt to INT1 pin */
+ bma2x2_set_int1_pad_sel(client, PAD_LOWG);
+ bma2x2_set_int1_pad_sel(client, PAD_HIGHG);
+ bma2x2_set_int1_pad_sel(client, PAD_SLOP);
+ bma2x2_set_int1_pad_sel(client, PAD_DOUBLE_TAP);
+ bma2x2_set_int1_pad_sel(client, PAD_SINGLE_TAP);
+ bma2x2_set_int1_pad_sel(client, PAD_ORIENT);
+ bma2x2_set_int1_pad_sel(client, PAD_FLAT);
+ bma2x2_set_int1_pad_sel(client, PAD_SLOW_NO_MOTION);
+#endif
+
+#ifdef BMA2X2_ENABLE_INT2
+ /* maps interrupt to INT2 pin */
+ bma2x2_set_int2_pad_sel(client, PAD_LOWG);
+ bma2x2_set_int2_pad_sel(client, PAD_HIGHG);
+ bma2x2_set_int2_pad_sel(client, PAD_SLOP);
+ bma2x2_set_int2_pad_sel(client, PAD_DOUBLE_TAP);
+ bma2x2_set_int2_pad_sel(client, PAD_SINGLE_TAP);
+ bma2x2_set_int2_pad_sel(client, PAD_ORIENT);
+ bma2x2_set_int2_pad_sel(client, PAD_FLAT);
+ bma2x2_set_int2_pad_sel(client, PAD_SLOW_NO_MOTION);
+#endif
+
+#if defined(BMA2X2_ENABLE_INT1) || defined(BMA2X2_ENABLE_INT2)
+ data->IRQ = client->irq;
+ err = request_irq(data->IRQ, bma2x2_irq_handler, IRQF_TRIGGER_RISING,
+ "bma2x2", data);
+ if (err)
+ printk(KERN_ERR "could not request irq\n");
+
+ INIT_WORK(&data->irq_work, bma2x2_irq_work_func);
+#endif
+
+
+ INIT_DELAYED_WORK(&data->work, bma2x2_work_func);
+ atomic_set(&data->delay, BMA2X2_MAX_DELAY);
+ atomic_set(&data->enable, 0);
+
+ dev = input_allocate_device();
+ if (!dev)
+ return -ENOMEM;
+ dev->name = SENSOR_NAME;
+ dev->id.bustype = BUS_I2C;
+
+ input_set_capability(dev, EV_REL, SLOW_NO_MOTION_INTERRUPT);
+ input_set_capability(dev, EV_REL, LOW_G_INTERRUPT);
+ input_set_capability(dev, EV_REL, HIGH_G_INTERRUPT);
+ input_set_capability(dev, EV_REL, SLOP_INTERRUPT);
+ input_set_capability(dev, EV_REL, DOUBLE_TAP_INTERRUPT);
+ input_set_capability(dev, EV_REL, SINGLE_TAP_INTERRUPT);
+ input_set_capability(dev, EV_ABS, ORIENT_INTERRUPT);
+ input_set_capability(dev, EV_ABS, FLAT_INTERRUPT);
+ 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_drvdata(dev, data);
+
+ err = input_register_device(dev);
+ if (err < 0) {
+ input_free_device(dev);
+ goto kfree_exit;
+ }
+
+ data->input = dev;
+
+ err = sysfs_create_group(&data->input->dev.kobj,
+ &bma2x2_attribute_group);
+ if (err < 0)
+ goto error_sysfs;
+
+#ifdef CONFIG_BMA_USE_PLATFORM_DATA
+ if (NULL != client->dev.platform_data) {
+ data->bst_pd = kzalloc(sizeof(*data->bst_pd),
+ GFP_KERNEL);
+
+ if (NULL != data->bst_pd) {
+ memcpy(data->bst_pd, client->dev.platform_data,
+ sizeof(*data->bst_pd));
+ printk(KERN_ALERT"bma2x2 "
+ "place of bma in %s: %d",
+ data->bst_pd->name,
+ data->bst_pd->place);
+ }
+ }
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ data->early_suspend.suspend = bma2x2_early_suspend;
+ data->early_suspend.resume = bma2x2_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+
+ err = sensors_register(&bma_device, data,bma2X2_attrs, "accelerometer_sensor");
+ if (err < 0 )
+ {
+ pr_err("%s: could not register" "accelerometer_sensor device(%d).\n", __func__, err);
+ goto error_sysfs;
+ }
+
+ return 0;
+
+error_sysfs:
+ input_unregister_device(data->input);
+
+kfree_exit:
+#ifdef CONFIG_BMA_USE_PLATFORM_DATA
+ if ((NULL != data) && (NULL != data->bst_pd)) {
+ kfree(data->bst_pd);
+ data->bst_pd = NULL;
+ }
+#endif
+ kfree(data);
+exit:
+ return err;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void bma2x2_early_suspend(struct early_suspend *h)
+{
+ struct bma2x2_data *data =
+ container_of(h, struct bma2x2_data, early_suspend);
+
+ mutex_lock(&data->enable_mutex);
+ if (atomic_read(&data->enable) == 1) {
+ bma2x2_set_mode(data->bma2x2_client, BMA2X2_MODE_SUSPEND);
+ cancel_delayed_work_sync(&data->work);
+ }
+ mutex_unlock(&data->enable_mutex);
+}
+
+
+static void bma2x2_late_resume(struct early_suspend *h)
+{
+ struct bma2x2_data *data =
+ container_of(h, struct bma2x2_data, early_suspend);
+
+ mutex_lock(&data->enable_mutex);
+ if (atomic_read(&data->enable) == 1) {
+ bma2x2_set_mode(data->bma2x2_client, BMA2X2_MODE_NORMAL);
+ schedule_delayed_work(&data->work,
+ msecs_to_jiffies(atomic_read(&data->delay)));
+ }
+ mutex_unlock(&data->enable_mutex);
+}
+#endif
+
+static int __exit bma2x2_remove(struct i2c_client *client)
+{
+ struct bma2x2_data *data = i2c_get_clientdata(client);
+
+ bma2x2_set_enable(&client->dev, 0);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&data->early_suspend);
+#endif
+ sensors_unregister(bma_device, bma2X2_attrs);
+ sysfs_remove_group(&data->input->dev.kobj, &bma2x2_attribute_group);
+ input_unregister_device(data->input);
+
+#ifdef CONFIG_BMA_USE_PLATFORM_DATA
+ if (NULL != data->bst_pd) {
+ kfree(data->bst_pd);
+ data->bst_pd = NULL;
+ }
+#endif
+
+ kfree(data);
+
+ return 0;
+}
+#ifdef CONFIG_PM
+
+static int bma2x2_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ struct bma2x2_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->enable_mutex);
+ if (atomic_read(&data->enable) == 1) {
+ bma2x2_set_mode(data->bma2x2_client, BMA2X2_MODE_SUSPEND);
+ cancel_delayed_work_sync(&data->work);
+ }
+ mutex_unlock(&data->enable_mutex);
+
+ return 0;
+}
+
+static int bma2x2_resume(struct i2c_client *client)
+{
+ struct bma2x2_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->enable_mutex);
+ if (atomic_read(&data->enable) == 1) {
+ bma2x2_set_mode(data->bma2x2_client, BMA2X2_MODE_NORMAL);
+ schedule_delayed_work(&data->work,
+ msecs_to_jiffies(atomic_read(&data->delay)));
+ }
+ mutex_unlock(&data->enable_mutex);
+
+ return 0;
+}
+
+#else
+
+#define bma2x2_suspend NULL
+#define bma2x2_resume NULL
+
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id bma2x2_id[] = {
+ { SENSOR_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, bma2x2_id);
+
+static struct i2c_driver bma2x2_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+ },
+ .suspend = bma2x2_suspend,
+ .resume = bma2x2_resume,
+ .id_table = bma2x2_id,
+ .probe = bma2x2_probe,
+ .remove = bma2x2_remove,
+
+};
+
+static int __init BMA2X2_init(void)
+{
+ return i2c_add_driver(&bma2x2_driver);
+}
+
+static void __exit BMA2X2_exit(void)
+{
+ i2c_del_driver(&bma2x2_driver);
+}
+
+MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>");
+MODULE_DESCRIPTION("BMA2X2 accelerometer sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(BMA2X2_init);
+module_exit(BMA2X2_exit);
diff --git a/drivers/sensor/bmm050.c b/drivers/sensor/bmm050.c
new file mode 100644
index 00000000..fb3f3fcb
--- /dev/null
+++ b/drivers/sensor/bmm050.c
@@ -0,0 +1,1159 @@
+/*
+ * (C) Copyright 2013 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
+ *
+ * @date Mar 11th, 2013
+ * @version v1.0.1
+ * @brief BMM050 Linux Driver API
+ */
+
+#include "bmm050.h"
+#include <linux/kernel.h>
+static struct bmm050 *p_bmm050;
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_init(struct bmm050 *bmm050)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char a_data_u8r[2];
+ p_bmm050 = bmm050;
+
+ p_bmm050->dev_addr = BMM050_I2C_ADDRESS;
+
+ /* set device from suspend into sleep mode */
+ bmm050_set_powermode(BMM050_ON);
+
+ /* wait two millisecond for bmc to settle */
+ p_bmm050->delay_msec(BMM050_DELAY_SETTLING_TIME);
+
+ /*Read CHIP_ID and REv. info */
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_CHIP_ID, a_data_u8r, 1);
+ p_bmm050->company_id = a_data_u8r[0];
+
+ /* Function to initialise trim values */
+ bmm050_init_trim_registers();
+ bmm050_set_presetmode(BMM050_PRESETMODE_REGULAR);
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_presetmode(unsigned char mode)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ switch (mode) {
+ case BMM050_PRESETMODE_LOWPOWER:
+ /* Set the data rate for Low Power mode */
+ comres = bmm050_set_datarate(BMM050_LOWPOWER_DR);
+ /* Set the XY-repetitions number for Low Power mode */
+ comres |= bmm050_set_repetitions_XY(BMM050_LOWPOWER_REPXY);
+ /* Set the Z-repetitions number for Low Power mode */
+ comres |= bmm050_set_repetitions_Z(BMM050_LOWPOWER_REPZ);
+ break;
+ case BMM050_PRESETMODE_REGULAR:
+ /* Set the data rate for Regular mode */
+ comres = bmm050_set_datarate(BMM050_REGULAR_DR);
+ /* Set the XY-repetitions number for Regular mode */
+ comres |= bmm050_set_repetitions_XY(BMM050_REGULAR_REPXY);
+ /* Set the Z-repetitions number for Regular mode */
+ comres |= bmm050_set_repetitions_Z(BMM050_REGULAR_REPZ);
+ break;
+ case BMM050_PRESETMODE_HIGHACCURACY:
+ /* Set the data rate for High Accuracy mode */
+ comres = bmm050_set_datarate(BMM050_HIGHACCURACY_DR);
+ /* Set the XY-repetitions number for High Accuracy mode */
+ comres |= bmm050_set_repetitions_XY(BMM050_HIGHACCURACY_REPXY);
+ /* Set the Z-repetitions number for High Accuracyr mode */
+ comres |= bmm050_set_repetitions_Z(BMM050_HIGHACCURACY_REPZ);
+ break;
+ case BMM050_PRESETMODE_ENHANCED:
+ /* Set the data rate for Enhanced Accuracy mode */
+ comres = bmm050_set_datarate(BMM050_ENHANCED_DR);
+ /* Set the XY-repetitions number for High Enhanced mode */
+ comres |= bmm050_set_repetitions_XY(BMM050_ENHANCED_REPXY);
+ /* Set the Z-repetitions number for High Enhanced mode */
+ comres |= bmm050_set_repetitions_Z(BMM050_ENHANCED_REPZ);
+ break;
+ default:
+ comres = E_BMM050_OUT_OF_RANGE;
+ break;
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_functional_state(
+ unsigned char functional_state)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data1_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ switch (functional_state) {
+ case BMM050_NORMAL_MODE:
+ comres = bmm050_get_powermode(&v_data1_u8r);
+ if (v_data1_u8r == BMM050_OFF) {
+ comres |= bmm050_set_powermode(BMM050_ON);
+ p_bmm050->delay_msec(
+ BMM050_DELAY_SUSPEND_SLEEP);
+ }
+ {
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_OPMODE__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(
+ v_data1_u8r,
+ BMM050_CNTL_OPMODE,
+ BMM050_NORMAL_MODE);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_OPMODE__REG,
+ &v_data1_u8r, 1);
+ }
+ break;
+ case BMM050_SUSPEND_MODE:
+ comres = bmm050_set_powermode(BMM050_OFF);
+ break;
+ case BMM050_FORCED_MODE:
+ comres = bmm050_get_powermode(&v_data1_u8r);
+ if (v_data1_u8r == BMM050_OFF) {
+ comres = bmm050_set_powermode(BMM050_ON);
+ p_bmm050->delay_msec(
+ BMM050_DELAY_SUSPEND_SLEEP);
+ }
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_OPMODE__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(
+ v_data1_u8r,
+ BMM050_CNTL_OPMODE, BMM050_ON);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_OPMODE__REG,
+ &v_data1_u8r, 1);
+ break;
+ case BMM050_SLEEP_MODE:
+ bmm050_get_powermode(&v_data1_u8r);
+ if (v_data1_u8r == BMM050_OFF) {
+ comres = bmm050_set_powermode(BMM050_ON);
+ p_bmm050->delay_msec(
+ BMM050_DELAY_SUSPEND_SLEEP);
+ }
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_OPMODE__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(
+ v_data1_u8r,
+ BMM050_CNTL_OPMODE,
+ BMM050_SLEEP_MODE);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_OPMODE__REG,
+ &v_data1_u8r, 1);
+ break;
+ default:
+ comres = E_BMM050_OUT_OF_RANGE;
+ break;
+ }
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_functional_state(
+ unsigned char *functional_state)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_OPMODE__REG,
+ &v_data_u8r, 1);
+ *functional_state = BMM050_GET_BITSLICE(
+ v_data_u8r, BMM050_CNTL_OPMODE);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_read_mdataXYZ(struct bmm050_mdata *mdata)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres;
+
+ unsigned char a_data_u8r[8];
+
+ struct {
+ BMM050_S16 raw_dataX;
+ BMM050_S16 raw_dataY;
+ BMM050_S16 raw_dataZ;
+ BMM050_U16 raw_dataR;
+ } raw_dataXYZ;
+
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DATAX_LSB, a_data_u8r, 8);
+
+ /* Reading data for X axis */
+ a_data_u8r[0] = BMM050_GET_BITSLICE(a_data_u8r[0],
+ BMM050_DATAX_LSB_VALUEX);
+ raw_dataXYZ.raw_dataX = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[1])) <<
+ SHIFT_LEFT_5_POSITION) | a_data_u8r[0]);
+
+ /* Reading data for Y axis */
+ a_data_u8r[2] = BMM050_GET_BITSLICE(a_data_u8r[2],
+ BMM050_DATAY_LSB_VALUEY);
+ raw_dataXYZ.raw_dataY = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[3])) <<
+ SHIFT_LEFT_5_POSITION) | a_data_u8r[2]);
+
+ /* Reading data for Z axis */
+ a_data_u8r[4] = BMM050_GET_BITSLICE(a_data_u8r[4],
+ BMM050_DATAZ_LSB_VALUEZ);
+ raw_dataXYZ.raw_dataZ = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[5])) <<
+ SHIFT_LEFT_7_POSITION) | a_data_u8r[4]);
+
+ /* Reading data for Resistance*/
+ a_data_u8r[6] = BMM050_GET_BITSLICE(a_data_u8r[6],
+ BMM050_R_LSB_VALUE);
+ raw_dataXYZ.raw_dataR = (BMM050_U16)((((BMM050_U16)
+ a_data_u8r[7]) <<
+ SHIFT_LEFT_6_POSITION) | a_data_u8r[6]);
+
+ /* Compensation for X axis */
+ mdata->datax = bmm050_compensate_X(raw_dataXYZ.raw_dataX,
+ raw_dataXYZ.raw_dataR);
+
+ /* Compensation for Y axis */
+ mdata->datay = bmm050_compensate_Y(raw_dataXYZ.raw_dataY,
+ raw_dataXYZ.raw_dataR);
+
+ /* Compensation for Z axis */
+ mdata->dataz = bmm050_compensate_Z(raw_dataXYZ.raw_dataZ,
+ raw_dataXYZ.raw_dataR);
+
+ /* Output raw resistance value */
+ mdata->resistance = raw_dataXYZ.raw_dataR;
+
+ }
+
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_read_mdataXYZ_s32(
+ struct bmm050_mdata_s32 *mdata)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres;
+
+ unsigned char a_data_u8r[8] = "";
+
+ struct {
+ BMM050_S16 raw_dataX;
+ BMM050_S16 raw_dataY;
+ BMM050_S16 raw_dataZ;
+ BMM050_U16 raw_dataR;
+ } raw_dataXYZ;
+
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DATAX_LSB, a_data_u8r, 8);
+
+ /* Reading data for X axis */
+ a_data_u8r[0] = BMM050_GET_BITSLICE(a_data_u8r[0],
+ BMM050_DATAX_LSB_VALUEX);
+ raw_dataXYZ.raw_dataX = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[1])) <<
+ SHIFT_LEFT_5_POSITION) | a_data_u8r[0]);
+
+ /* Reading data for Y axis */
+ a_data_u8r[2] = BMM050_GET_BITSLICE(a_data_u8r[2],
+ BMM050_DATAY_LSB_VALUEY);
+ raw_dataXYZ.raw_dataY = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[3])) <<
+ SHIFT_LEFT_5_POSITION) | a_data_u8r[2]);
+
+ /* Reading data for Z axis */
+ a_data_u8r[4] = BMM050_GET_BITSLICE(a_data_u8r[4],
+ BMM050_DATAZ_LSB_VALUEZ);
+ raw_dataXYZ.raw_dataZ = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[5])) <<
+ SHIFT_LEFT_7_POSITION) | a_data_u8r[4]);
+
+ /* Reading data for Resistance*/
+ if (!comres)
+ mdata->drdy = BMM050_GET_BITSLICE(a_data_u8r[6],
+ BMM050_DATA_RDYSTAT);
+
+ a_data_u8r[6] = BMM050_GET_BITSLICE(a_data_u8r[6],
+ BMM050_R_LSB_VALUE);
+ raw_dataXYZ.raw_dataR = (BMM050_U16)((((BMM050_U16)
+ a_data_u8r[7]) <<
+ SHIFT_LEFT_6_POSITION) | a_data_u8r[6]);
+
+ /* Compensation for X axis */
+ mdata->datax = bmm050_compensate_X_s32(raw_dataXYZ.raw_dataX,
+ raw_dataXYZ.raw_dataR);
+
+ /* Compensation for Y axis */
+ mdata->datay = bmm050_compensate_Y_s32(raw_dataXYZ.raw_dataY,
+ raw_dataXYZ.raw_dataR);
+
+ /* Compensation for Z axis */
+ mdata->dataz = bmm050_compensate_Z_s32(raw_dataXYZ.raw_dataZ,
+ raw_dataXYZ.raw_dataR);
+
+ /* Output raw resistance value */
+ mdata->resistance = raw_dataXYZ.raw_dataR;
+ }
+ return comres;
+}
+
+#ifdef ENABLE_FLOAT
+BMM050_RETURN_FUNCTION_TYPE bmm050_read_mdataXYZ_float(
+ struct bmm050_mdata_float *mdata)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres;
+
+ unsigned char a_data_u8r[8];
+
+ struct {
+ BMM050_S16 raw_dataX;
+ BMM050_S16 raw_dataY;
+ BMM050_S16 raw_dataZ;
+ BMM050_U16 raw_dataR;
+ } raw_dataXYZ;
+
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DATAX_LSB, a_data_u8r, 8);
+
+ /* Reading data for X axis */
+ a_data_u8r[0] = BMM050_GET_BITSLICE(a_data_u8r[0],
+ BMM050_DATAX_LSB_VALUEX);
+ raw_dataXYZ.raw_dataX = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[1])) <<
+ SHIFT_LEFT_5_POSITION) | a_data_u8r[0]);
+
+ /* Reading data for Y axis */
+ a_data_u8r[2] = BMM050_GET_BITSLICE(a_data_u8r[2],
+ BMM050_DATAY_LSB_VALUEY);
+ raw_dataXYZ.raw_dataY = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[3])) <<
+ SHIFT_LEFT_5_POSITION) | a_data_u8r[2]);
+
+ /* Reading data for Z axis */
+ a_data_u8r[4] = BMM050_GET_BITSLICE(a_data_u8r[4],
+ BMM050_DATAZ_LSB_VALUEZ);
+ raw_dataXYZ.raw_dataZ = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[5])) <<
+ SHIFT_LEFT_7_POSITION) | a_data_u8r[4]);
+
+ /* Reading data for Resistance*/
+ a_data_u8r[6] = BMM050_GET_BITSLICE(a_data_u8r[6],
+ BMM050_R_LSB_VALUE);
+ raw_dataXYZ.raw_dataR = (BMM050_U16)((((BMM050_U16)
+ a_data_u8r[7]) <<
+ SHIFT_LEFT_6_POSITION) | a_data_u8r[6]);
+
+ /* Compensation for X axis */
+ mdata->datax = bmm050_compensate_X_float(raw_dataXYZ.raw_dataX,
+ raw_dataXYZ.raw_dataR);
+
+ /* Compensation for Y axis */
+ mdata->datay = bmm050_compensate_Y_float(raw_dataXYZ.raw_dataY,
+ raw_dataXYZ.raw_dataR);
+
+ /* Compensation for Z axis */
+ mdata->dataz = bmm050_compensate_Z_float(raw_dataXYZ.raw_dataZ,
+ raw_dataXYZ.raw_dataR);
+
+ /* Output raw resistance value */
+ mdata->resistance = raw_dataXYZ.raw_dataR;
+ }
+ return comres;
+}
+#endif
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_read_register(unsigned char addr,
+ unsigned char *data, unsigned char len)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ addr, data, len);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_write_register(unsigned char addr,
+ unsigned char *data, unsigned char len)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_WRITE_FUNC(p_bmm050->dev_addr,
+ addr, data, len);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_selftest(unsigned char selftest)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data1_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr, BMM050_CNTL_S_TEST__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(
+ v_data1_u8r, BMM050_CNTL_S_TEST, selftest);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr, BMM050_CNTL_S_TEST__REG,
+ &v_data1_u8r, 1);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_self_test_XYZ(
+ unsigned char *self_testxyz)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char a_data_u8r[5], v_result_u8r = 0x00;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr, BMM050_DATAX_LSB_TESTX__REG,
+ a_data_u8r, 5);
+
+ v_result_u8r = BMM050_GET_BITSLICE(a_data_u8r[4],
+ BMM050_DATAZ_LSB_TESTZ);
+
+ v_result_u8r = (v_result_u8r << 1);
+ v_result_u8r = (v_result_u8r | BMM050_GET_BITSLICE(
+ a_data_u8r[2], BMM050_DATAY_LSB_TESTY));
+
+ v_result_u8r = (v_result_u8r << 1);
+ v_result_u8r = (v_result_u8r | BMM050_GET_BITSLICE(
+ a_data_u8r[0], BMM050_DATAX_LSB_TESTX));
+
+ *self_testxyz = v_result_u8r;
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_spi3(unsigned char value)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data1_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_POWER_CNTL_SPI3_EN__REG, &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(v_data1_u8r,
+ BMM050_POWER_CNTL_SPI3_EN, value);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(p_bmm050->dev_addr,
+ BMM050_POWER_CNTL_SPI3_EN__REG, &v_data1_u8r, 1);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_datarate(unsigned char data_rate)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data1_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_DR__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(v_data1_u8r,
+ BMM050_CNTL_DR, data_rate);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_DR__REG,
+ &v_data1_u8r, 1);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_datarate(unsigned char *data_rate)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_DR__REG,
+ &v_data_u8r, 1);
+ *data_rate = BMM050_GET_BITSLICE(v_data_u8r,
+ BMM050_CNTL_DR);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_perform_advanced_selftest(
+ BMM050_S16 *diff_z)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres;
+ BMM050_S16 result_positive, result_negative;
+ struct bmm050_mdata mdata;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ /* set sleep mode to prepare for forced measurement.
+ * If sensor is off, this will turn it on
+ * and respect needed delays. */
+ comres = bmm050_set_functional_state(BMM050_SLEEP_MODE);
+
+ /* set normal accuracy mode */
+ comres |= bmm050_set_repetitions_Z(BMM050_LOWPOWER_REPZ);
+ /* 14 repetitions Z in normal accuracy mode */
+
+ /* disable X, Y channel */
+ comres |= bmm050_set_control_measurement_x(
+ BMM050_CHANNEL_DISABLE);
+ comres |= bmm050_set_control_measurement_y(
+ BMM050_CHANNEL_DISABLE);
+
+ /* enable positive current and force a
+ * measurement with positive field */
+ comres |= bmm050_set_adv_selftest(
+ BMM050_ADVANCED_SELFTEST_POSITIVE);
+ comres |= bmm050_set_functional_state(BMM050_FORCED_MODE);
+ /* wait for measurement to complete */
+ p_bmm050->delay_msec(4);
+
+ /* read result from positive field measurement */
+ comres |= bmm050_read_mdataXYZ(&mdata);
+ result_positive = mdata.dataz;
+
+ /* enable negative current and force a
+ * measurement with negative field */
+ comres |= bmm050_set_adv_selftest(
+ BMM050_ADVANCED_SELFTEST_NEGATIVE);
+ comres |= bmm050_set_functional_state(BMM050_FORCED_MODE);
+ p_bmm050->delay_msec(4); /* wait for measurement to complete */
+
+ /* read result from negative field measurement */
+ comres |= bmm050_read_mdataXYZ(&mdata);
+ result_negative = mdata.dataz;
+
+ /* turn off self test current */
+ comres |= bmm050_set_adv_selftest(
+ BMM050_ADVANCED_SELFTEST_OFF);
+
+ /* enable X, Y channel */
+ comres |= bmm050_set_control_measurement_x(
+ BMM050_CHANNEL_ENABLE);
+ comres |= bmm050_set_control_measurement_y(
+ BMM050_CHANNEL_ENABLE);
+
+ /* write out difference in positive and negative field.
+ * This should be ~ 200 mT = 3200 LSB */
+ *diff_z = (result_positive - result_negative);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_init_trim_registers(void)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char a_data_u8r[2];
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_X1, (unsigned char *)&p_bmm050->dig_x1, 1);
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_Y1, (unsigned char *)&p_bmm050->dig_y1, 1);
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_X2, (unsigned char *)&p_bmm050->dig_x2, 1);
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_Y2, (unsigned char *)&p_bmm050->dig_y2, 1);
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_XY1, (unsigned char *)&p_bmm050->dig_xy1, 1);
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_XY2, (unsigned char *)&p_bmm050->dig_xy2, 1);
+
+ /* shorts can not be recasted into (unsigned char*)
+ * due to possible mixup between trim data
+ * arrangement and memory arrangement */
+
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_Z1_LSB, a_data_u8r, 2);
+ p_bmm050->dig_z1 = (BMM050_U16)((((BMM050_U16)((unsigned char)
+ a_data_u8r[1])) <<
+ SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
+
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_Z2_LSB, a_data_u8r, 2);
+ p_bmm050->dig_z2 = (BMM050_S16)((((BMM050_S16)(
+ (signed char)a_data_u8r[1])) <<
+ SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
+
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_Z3_LSB, a_data_u8r, 2);
+ p_bmm050->dig_z3 = (BMM050_S16)((((BMM050_S16)(
+ (signed char)a_data_u8r[1])) <<
+ SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
+
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_Z4_LSB, a_data_u8r, 2);
+ p_bmm050->dig_z4 = (BMM050_S16)((((BMM050_S16)(
+ (signed char)a_data_u8r[1])) <<
+ SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
+
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DIG_XYZ1_LSB, a_data_u8r, 2);
+ a_data_u8r[1] = BMM050_GET_BITSLICE(a_data_u8r[1], BMM050_DIG_XYZ1_MSB);
+ p_bmm050->dig_xyz1 = (BMM050_U16)((((BMM050_U16)
+ ((unsigned char)a_data_u8r[1])) <<
+ SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_adv_selftest(unsigned char adv_selftest)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data1_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ switch (adv_selftest) {
+ case BMM050_ADVANCED_SELFTEST_OFF:
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_ADV_ST__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(
+ v_data1_u8r,
+ BMM050_CNTL_ADV_ST,
+ BMM050_ADVANCED_SELFTEST_OFF);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_ADV_ST__REG,
+ &v_data1_u8r, 1);
+ break;
+ case BMM050_ADVANCED_SELFTEST_POSITIVE:
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_ADV_ST__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(
+ v_data1_u8r,
+ BMM050_CNTL_ADV_ST,
+ BMM050_ADVANCED_SELFTEST_POSITIVE);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_ADV_ST__REG,
+ &v_data1_u8r, 1);
+ break;
+ case BMM050_ADVANCED_SELFTEST_NEGATIVE:
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_ADV_ST__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(
+ v_data1_u8r,
+ BMM050_CNTL_ADV_ST,
+ BMM050_ADVANCED_SELFTEST_NEGATIVE);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_CNTL_ADV_ST__REG,
+ &v_data1_u8r, 1);
+ break;
+ default:
+ break;
+ }
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_adv_selftest(unsigned char *adv_selftest)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_CNTL_ADV_ST__REG, &v_data_u8r, 1);
+ *adv_selftest = BMM050_GET_BITSLICE(v_data_u8r,
+ BMM050_CNTL_ADV_ST);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_presetmode(
+ unsigned char *mode)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char data_rate = 0;
+ unsigned char repetitionsxy = 0;
+ unsigned char repetitionsz = 0;
+
+ /* Get the current data rate */
+ comres = bmm050_get_datarate(&data_rate);
+ /* Get the preset number of XY Repetitions */
+ comres |= bmm050_get_repetitions_XY(&repetitionsxy);
+ /* Get the preset number of Z Repetitions */
+ comres |= bmm050_get_repetitions_Z(&repetitionsz);
+ if ((data_rate == BMM050_LOWPOWER_DR) && (
+ repetitionsxy == BMM050_LOWPOWER_REPXY) && (
+ repetitionsz == BMM050_LOWPOWER_REPZ)) {
+ *mode = BMM050_PRESETMODE_LOWPOWER;
+ } else {
+ if ((data_rate == BMM050_REGULAR_DR) && (
+ repetitionsxy == BMM050_REGULAR_REPXY) && (
+ repetitionsz == BMM050_REGULAR_REPZ)) {
+ *mode = BMM050_PRESETMODE_REGULAR;
+ } else {
+ if ((data_rate == BMM050_HIGHACCURACY_DR) && (
+ repetitionsxy == BMM050_HIGHACCURACY_REPXY) && (
+ repetitionsz == BMM050_HIGHACCURACY_REPZ)) {
+ *mode = BMM050_PRESETMODE_HIGHACCURACY;
+ } else {
+ if ((data_rate == BMM050_ENHANCED_DR) && (
+ repetitionsxy == BMM050_ENHANCED_REPXY) && (
+ repetitionsz == BMM050_ENHANCED_REPZ)) {
+ *mode = BMM050_PRESETMODE_ENHANCED;
+ } else {
+ *mode = E_BMM050_UNDEFINED_MODE;
+ }
+ }
+ }
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_powermode(unsigned char *mode)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_POWER_CNTL_PCB__REG,
+ &v_data_u8r, 1);
+ *mode = BMM050_GET_BITSLICE(v_data_u8r,
+ BMM050_POWER_CNTL_PCB);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_powermode(unsigned char mode)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_POWER_CNTL_PCB__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = BMM050_SET_BITSLICE(v_data_u8r,
+ BMM050_POWER_CNTL_PCB, mode);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_POWER_CNTL_PCB__REG,
+ &v_data_u8r, 1);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_repetitions_XY(
+ unsigned char *no_repetitions_xy)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_NO_REPETITIONS_XY,
+ &v_data_u8r, 1);
+ *no_repetitions_xy = v_data_u8r;
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_repetitions_XY(
+ unsigned char no_repetitions_xy)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ v_data_u8r = no_repetitions_xy;
+ comres = p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_NO_REPETITIONS_XY,
+ &v_data_u8r, 1);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_repetitions_Z(
+ unsigned char *no_repetitions_z)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_NO_REPETITIONS_Z,
+ &v_data_u8r, 1);
+ *no_repetitions_z = v_data_u8r;
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_repetitions_Z(
+ unsigned char no_repetitions_z)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ v_data_u8r = no_repetitions_z;
+ comres = p_bmm050->BMM050_BUS_WRITE_FUNC(p_bmm050->dev_addr,
+ BMM050_NO_REPETITIONS_Z, &v_data_u8r, 1);
+ }
+ return comres;
+}
+
+BMM050_S16 bmm050_compensate_X(BMM050_S16 mdata_x, BMM050_U16 data_R)
+{
+ BMM050_S16 inter_retval;
+ if (mdata_x != BMM050_FLIP_OVERFLOW_ADCVAL /* no overflow */
+ ) {
+ inter_retval = ((BMM050_S16)(((BMM050_U16)
+ ((((BMM050_S32)p_bmm050->dig_xyz1) << 14) /
+ (data_R != 0 ? data_R : p_bmm050->dig_xyz1))) -
+ ((BMM050_U16)0x4000)));
+ inter_retval = ((BMM050_S16)((((BMM050_S32)mdata_x) *
+ ((((((((BMM050_S32)p_bmm050->dig_xy2) *
+ ((((BMM050_S32)inter_retval) *
+ ((BMM050_S32)inter_retval)) >> 7)) +
+ (((BMM050_S32)inter_retval) *
+ ((BMM050_S32)(((BMM050_S16)p_bmm050->dig_xy1)
+ << 7)))) >> 9) +
+ ((BMM050_S32)0x100000)) *
+ ((BMM050_S32)(((BMM050_S16)p_bmm050->dig_x2) +
+ ((BMM050_S16)0xA0)))) >> 12)) >> 13)) +
+ (((BMM050_S16)p_bmm050->dig_x1) << 3);
+ } else {
+ /* overflow */
+ inter_retval = BMM050_OVERFLOW_OUTPUT;
+ }
+ return inter_retval;
+}
+
+BMM050_S32 bmm050_compensate_X_s32 (BMM050_S16 mdata_x, BMM050_U16 data_R)
+{
+ BMM050_S32 retval;
+
+ retval = bmm050_compensate_X(mdata_x, data_R);
+ if (retval == (BMM050_S32)BMM050_OVERFLOW_OUTPUT)
+ retval = BMM050_OVERFLOW_OUTPUT_S32;
+ return retval;
+}
+
+#ifdef ENABLE_FLOAT
+float bmm050_compensate_X_float (BMM050_S16 mdata_x, BMM050_U16 data_R)
+{
+ float inter_retval;
+ if (mdata_x != BMM050_FLIP_OVERFLOW_ADCVAL /* no overflow */
+ ) {
+ if (data_R != 0) {
+ inter_retval = ((((float)p_bmm050->dig_xyz1)*16384.0f
+ /data_R)-16384.0f);
+ } else {
+ inter_retval = 0;
+ }
+ inter_retval = (((mdata_x * ((((((float)p_bmm050->dig_xy2) *
+ (inter_retval*inter_retval / 268435456.0f) +
+ inter_retval*((float)p_bmm050->dig_xy1)/16384.0f))
+ + 256.0f) * (((float)p_bmm050->dig_x2) + 160.0f)))
+ / 8192.0f) + (((float)p_bmm050->dig_x1) * 8.0f))/16.0f;
+ } else {
+ inter_retval = BMM050_OVERFLOW_OUTPUT_FLOAT;
+ }
+ return inter_retval;
+}
+#endif
+
+BMM050_S16 bmm050_compensate_Y(BMM050_S16 mdata_y, BMM050_U16 data_R)
+{
+ BMM050_S16 inter_retval;
+ if (mdata_y != BMM050_FLIP_OVERFLOW_ADCVAL /* no overflow */
+ ) {
+ inter_retval = ((BMM050_S16)(((BMM050_U16)(((
+ (BMM050_S32)p_bmm050->dig_xyz1) << 14) /
+ (data_R != 0 ?
+ data_R : p_bmm050->dig_xyz1))) -
+ ((BMM050_U16)0x4000)));
+ inter_retval = ((BMM050_S16)((((BMM050_S32)mdata_y) *
+ ((((((((BMM050_S32)
+ p_bmm050->dig_xy2) *
+ ((((BMM050_S32) inter_retval) *
+ ((BMM050_S32)inter_retval)) >> 7)) +
+ (((BMM050_S32)inter_retval) *
+ ((BMM050_S32)(((BMM050_S16)
+ p_bmm050->dig_xy1) << 7)))) >> 9) +
+ ((BMM050_S32)0x100000)) *
+ ((BMM050_S32)(((BMM050_S16)p_bmm050->dig_y2)
+ + ((BMM050_S16)0xA0))))
+ >> 12)) >> 13)) +
+ (((BMM050_S16)p_bmm050->dig_y1) << 3);
+ } else {
+ /* overflow */
+ inter_retval = BMM050_OVERFLOW_OUTPUT;
+ }
+ return inter_retval;
+}
+
+BMM050_S32 bmm050_compensate_Y_s32 (BMM050_S16 mdata_y, BMM050_U16 data_R)
+{
+ BMM050_S32 retval;
+
+ retval = bmm050_compensate_Y(mdata_y, data_R);
+ if (retval == BMM050_OVERFLOW_OUTPUT)
+ retval = BMM050_OVERFLOW_OUTPUT_S32;
+ return retval;
+}
+
+#ifdef ENABLE_FLOAT
+float bmm050_compensate_Y_float(BMM050_S16 mdata_y, BMM050_U16 data_R)
+{
+ float inter_retval;
+ if (mdata_y != BMM050_FLIP_OVERFLOW_ADCVAL /* no overflow */
+ ) {
+ if (data_R != 0) {
+ inter_retval = ((((float)p_bmm050->dig_xyz1)*16384.0f
+ /data_R)-16384.0f);
+ } else {
+ inter_retval = 0;
+ }
+ inter_retval = (((mdata_y * ((((((float)p_bmm050->dig_xy2) *
+ (inter_retval*inter_retval / 268435456.0f) +
+ inter_retval * ((float)p_bmm050->dig_xy1)/16384.0f)) +
+ 256.0f) * (((float)p_bmm050->dig_y2) + 160.0f)))
+ / 8192.0f) + (((float)p_bmm050->dig_y1) * 8.0f))/16.0f;
+ } else {
+ /* overflow, set output to 0.0f */
+ inter_retval = BMM050_OVERFLOW_OUTPUT_FLOAT;
+ }
+ return inter_retval;
+}
+#endif
+
+BMM050_S16 bmm050_compensate_Z(BMM050_S16 mdata_z, BMM050_U16 data_R)
+{
+ BMM050_S32 retval;
+ if ((mdata_z != BMM050_HALL_OVERFLOW_ADCVAL) /* no overflow */
+ ) {
+ retval = (((((BMM050_S32)(mdata_z - p_bmm050->dig_z4)) << 15) -
+ ((((BMM050_S32)p_bmm050->dig_z3) *
+ ((BMM050_S32)(((BMM050_S16)data_R) -
+ ((BMM050_S16)
+ p_bmm050->dig_xyz1))))>>2)) /
+ (p_bmm050->dig_z2 +
+ ((BMM050_S16)(((((BMM050_S32)
+ p_bmm050->dig_z1) *
+ ((((BMM050_S16)data_R) << 1)))+
+ (1<<15))>>16))));
+ /* saturate result to +/- 2 mT */
+ if (retval > BMM050_POSITIVE_SATURATION_Z) {
+ retval = BMM050_POSITIVE_SATURATION_Z;
+ } else {
+ if (retval < BMM050_NEGATIVE_SATURATION_Z)
+ retval = BMM050_NEGATIVE_SATURATION_Z;
+ }
+ } else {
+ /* overflow */
+ retval = BMM050_OVERFLOW_OUTPUT;
+ }
+ return (BMM050_S16)retval;
+}
+
+BMM050_S32 bmm050_compensate_Z_s32(BMM050_S16 mdata_z, BMM050_U16 data_R)
+{
+ BMM050_S32 retval;
+ if (mdata_z != BMM050_HALL_OVERFLOW_ADCVAL) {
+ retval = (((((BMM050_S32)(mdata_z - p_bmm050->dig_z4)) << 15) -
+ ((((BMM050_S32)p_bmm050->dig_z3) *
+ ((BMM050_S32)(((BMM050_S16)data_R) -
+ ((BMM050_S16)p_bmm050->dig_xyz1))))>>2)) /
+ (p_bmm050->dig_z2 +
+ ((BMM050_S16)(((((BMM050_S32)p_bmm050->dig_z1) *
+ ((((BMM050_S16)data_R) << 1)))+(1<<15))>>16))));
+ } else {
+ retval = BMM050_OVERFLOW_OUTPUT_S32;
+ }
+ return retval;
+}
+
+#ifdef ENABLE_FLOAT
+float bmm050_compensate_Z_float (BMM050_S16 mdata_z, BMM050_U16 data_R)
+{
+ float inter_retval;
+ if (mdata_z != BMM050_HALL_OVERFLOW_ADCVAL /* no overflow */
+ ) {
+ inter_retval = ((((((float)mdata_z)-((float)p_bmm050->dig_z4))*
+ 131072.0f)-(((float)p_bmm050->dig_z3)*(((float)data_R)-
+ ((float)p_bmm050->dig_xyz1))))/((((float)p_bmm050->dig_z2)+
+ ((float)p_bmm050->dig_z1)*((float)data_R)/32768.0)*4.0))/16.0;
+ } else {
+ /* overflow, set output to 0.0f */
+ inter_retval = BMM050_OVERFLOW_OUTPUT_FLOAT;
+ }
+ return inter_retval;
+}
+#endif
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_control_measurement_x(
+ unsigned char enable_disable)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data1_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_SENS_CNTL_CHANNELX__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(v_data1_u8r,
+ BMM050_SENS_CNTL_CHANNELX,
+ enable_disable);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_SENS_CNTL_CHANNELX__REG,
+ &v_data1_u8r, 1);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_control_measurement_y(
+ unsigned char enable_disable)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data1_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_SENS_CNTL_CHANNELY__REG,
+ &v_data1_u8r, 1);
+ v_data1_u8r = BMM050_SET_BITSLICE(
+ v_data1_u8r,
+ BMM050_SENS_CNTL_CHANNELY,
+ enable_disable);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_SENS_CNTL_CHANNELY__REG,
+ &v_data1_u8r, 1);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_soft_reset(void)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres = 0;
+ unsigned char v_data_u8r;
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ v_data_u8r = BMM050_ON;
+
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_POWER_CNTL_SRST7__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = BMM050_SET_BITSLICE(v_data_u8r,
+ BMM050_POWER_CNTL_SRST7,
+ BMM050_SOFT_RESET7_ON);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_POWER_CNTL_SRST7__REG, &v_data_u8r, 1);
+
+ comres |= p_bmm050->BMM050_BUS_READ_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_POWER_CNTL_SRST1__REG,
+ &v_data_u8r, 1);
+ v_data_u8r = BMM050_SET_BITSLICE(v_data_u8r,
+ BMM050_POWER_CNTL_SRST1,
+ BMM050_SOFT_RESET1_ON);
+ comres |= p_bmm050->BMM050_BUS_WRITE_FUNC(
+ p_bmm050->dev_addr,
+ BMM050_POWER_CNTL_SRST1__REG,
+ &v_data_u8r, 1);
+
+ p_bmm050->delay_msec(BMM050_DELAY_SOFTRESET);
+ }
+ return comres;
+}
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_raw_xyz(struct bmm050_mdata *mdata)
+{
+ BMM050_RETURN_FUNCTION_TYPE comres;
+ unsigned char a_data_u8r[6];
+ if (p_bmm050 == BMM050_NULL) {
+ comres = E_BMM050_NULL_PTR;
+ } else {
+ comres = p_bmm050->BMM050_BUS_READ_FUNC(p_bmm050->dev_addr,
+ BMM050_DATAX_LSB, a_data_u8r, 6);
+
+ a_data_u8r[0] = BMM050_GET_BITSLICE(a_data_u8r[0],
+ BMM050_DATAX_LSB_VALUEX);
+ mdata->datax = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[1]))
+ << SHIFT_LEFT_5_POSITION)
+ | a_data_u8r[0]);
+
+ a_data_u8r[2] = BMM050_GET_BITSLICE(a_data_u8r[2],
+ BMM050_DATAY_LSB_VALUEY);
+ mdata->datay = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[3]))
+ << SHIFT_LEFT_5_POSITION)
+ | a_data_u8r[2]);
+
+ a_data_u8r[4] = BMM050_GET_BITSLICE(a_data_u8r[4],
+ BMM050_DATAZ_LSB_VALUEZ);
+ mdata->dataz = (BMM050_S16)((((BMM050_S16)
+ ((signed char)a_data_u8r[5]))
+ << SHIFT_LEFT_7_POSITION)
+ | a_data_u8r[4]);
+ }
+ return comres;
+}
diff --git a/drivers/sensor/bmm050.h b/drivers/sensor/bmm050.h
new file mode 100644
index 00000000..e6ecaf00
--- /dev/null
+++ b/drivers/sensor/bmm050.h
@@ -0,0 +1,580 @@
+/*
+ * (C) Copyright 2013 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
+ *
+ * @date Apr 28th, 2011
+ * @version v1.0
+ * @brief BMM050 Linux Driver API
+ */
+
+
+#ifndef __BMM050_H__
+#define __BMM050_H__
+
+
+#define BMM050_U16 unsigned short
+#define BMM050_S16 signed short
+#define BMM050_S32 signed int
+
+
+#define BMM050_BUS_WR_RETURN_TYPE char
+#define BMM050_BUS_WR_PARAM_TYPES\
+ unsigned char, unsigned char, unsigned char *, unsigned char
+#define BMM050_BUS_WR_PARAM_ORDER\
+ (device_addr, register_addr, register_data, wr_len)
+#define BMM050_BUS_WRITE_FUNC(\
+ device_addr, register_addr, register_data, wr_len)\
+ bus_write(device_addr, register_addr, register_data, wr_len)
+
+#define BMM050_BUS_RD_RETURN_TYPE char
+
+#define BMM050_BUS_RD_PARAM_TYPES\
+ unsigned char, unsigned char, unsigned char *, unsigned char
+
+#define BMM050_BUS_RD_PARAM_ORDER (device_addr, register_addr, register_data)
+
+#define BMM050_BUS_READ_FUNC(device_addr, register_addr, register_data, rd_len)\
+ bus_read(device_addr, register_addr, register_data, rd_len)
+
+
+#define BMM050_DELAY_RETURN_TYPE void
+
+#define BMM050_DELAY_PARAM_TYPES unsigned int
+
+#define BMM050_DELAY_FUNC(delay_in_msec)\
+ delay_func(delay_in_msec)
+
+#define BMM050_DELAY_POWEROFF_SUSPEND 1
+#define BMM050_DELAY_SUSPEND_SLEEP 2
+#define BMM050_DELAY_SLEEP_ACTIVE 1
+#define BMM050_DELAY_ACTIVE_SLEEP 1
+#define BMM050_DELAY_SLEEP_SUSPEND 1
+#define BMM050_DELAY_ACTIVE_SUSPEND 1
+#define BMM050_DELAY_SLEEP_POWEROFF 1
+#define BMM050_DELAY_ACTIVE_POWEROFF 1
+#define BMM050_DELAY_SETTLING_TIME 2
+
+
+#define BMM050_RETURN_FUNCTION_TYPE char
+#define BMM050_I2C_ADDRESS 0x12
+
+/*General Info datas*/
+#define BMM050_SOFT_RESET7_ON 1
+#define BMM050_SOFT_RESET1_ON 1
+#define BMM050_SOFT_RESET7_OFF 0
+#define BMM050_SOFT_RESET1_OFF 0
+#define BMM050_DELAY_SOFTRESET 1
+
+/* Fixed Data Registers */
+#define BMM050_CHIP_ID 0x40
+
+/* Data Registers */
+#define BMM050_DATAX_LSB 0x42
+#define BMM050_DATAX_MSB 0x43
+#define BMM050_DATAY_LSB 0x44
+#define BMM050_DATAY_MSB 0x45
+#define BMM050_DATAZ_LSB 0x46
+#define BMM050_DATAZ_MSB 0x47
+#define BMM050_R_LSB 0x48
+#define BMM050_R_MSB 0x49
+
+/* Status Registers */
+#define BMM050_INT_STAT 0x4A
+
+/* Control Registers */
+#define BMM050_POWER_CNTL 0x4B
+#define BMM050_CONTROL 0x4C
+#define BMM050_INT_CNTL 0x4D
+#define BMM050_SENS_CNTL 0x4E
+#define BMM050_LOW_THRES 0x4F
+#define BMM050_HIGH_THRES 0x50
+#define BMM050_NO_REPETITIONS_XY 0x51
+#define BMM050_NO_REPETITIONS_Z 0x52
+
+/* 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
+
+
+/* Data X LSB Regsiter */
+#define BMM050_DATAX_LSB_VALUEX__POS 3
+#define BMM050_DATAX_LSB_VALUEX__LEN 5
+#define BMM050_DATAX_LSB_VALUEX__MSK 0xF8
+#define BMM050_DATAX_LSB_VALUEX__REG BMM050_DATAX_LSB
+
+#define BMM050_DATAX_LSB_TESTX__POS 0
+#define BMM050_DATAX_LSB_TESTX__LEN 1
+#define BMM050_DATAX_LSB_TESTX__MSK 0x01
+#define BMM050_DATAX_LSB_TESTX__REG BMM050_DATAX_LSB
+
+/* Data Y LSB Regsiter */
+#define BMM050_DATAY_LSB_VALUEY__POS 3
+#define BMM050_DATAY_LSB_VALUEY__LEN 5
+#define BMM050_DATAY_LSB_VALUEY__MSK 0xF8
+#define BMM050_DATAY_LSB_VALUEY__REG BMM050_DATAY_LSB
+
+#define BMM050_DATAY_LSB_TESTY__POS 0
+#define BMM050_DATAY_LSB_TESTY__LEN 1
+#define BMM050_DATAY_LSB_TESTY__MSK 0x01
+#define BMM050_DATAY_LSB_TESTY__REG BMM050_DATAY_LSB
+
+/* Data Z LSB Regsiter */
+#define BMM050_DATAZ_LSB_VALUEZ__POS 1
+#define BMM050_DATAZ_LSB_VALUEZ__LEN 7
+#define BMM050_DATAZ_LSB_VALUEZ__MSK 0xFE
+#define BMM050_DATAZ_LSB_VALUEZ__REG BMM050_DATAZ_LSB
+
+#define BMM050_DATAZ_LSB_TESTZ__POS 0
+#define BMM050_DATAZ_LSB_TESTZ__LEN 1
+#define BMM050_DATAZ_LSB_TESTZ__MSK 0x01
+#define BMM050_DATAZ_LSB_TESTZ__REG BMM050_DATAZ_LSB
+
+/* Hall Resistance LSB Regsiter */
+#define BMM050_R_LSB_VALUE__POS 2
+#define BMM050_R_LSB_VALUE__LEN 6
+#define BMM050_R_LSB_VALUE__MSK 0xFC
+#define BMM050_R_LSB_VALUE__REG BMM050_R_LSB
+
+#define BMM050_DATA_RDYSTAT__POS 0
+#define BMM050_DATA_RDYSTAT__LEN 1
+#define BMM050_DATA_RDYSTAT__MSK 0x01
+#define BMM050_DATA_RDYSTAT__REG BMM050_R_LSB
+
+/* Interupt Status Register */
+#define BMM050_INT_STAT_DOR__POS 7
+#define BMM050_INT_STAT_DOR__LEN 1
+#define BMM050_INT_STAT_DOR__MSK 0x80
+#define BMM050_INT_STAT_DOR__REG BMM050_INT_STAT
+
+#define BMM050_INT_STAT_OVRFLOW__POS 6
+#define BMM050_INT_STAT_OVRFLOW__LEN 1
+#define BMM050_INT_STAT_OVRFLOW__MSK 0x40
+#define BMM050_INT_STAT_OVRFLOW__REG BMM050_INT_STAT
+
+#define BMM050_INT_STAT_HIGH_THZ__POS 5
+#define BMM050_INT_STAT_HIGH_THZ__LEN 1
+#define BMM050_INT_STAT_HIGH_THZ__MSK 0x20
+#define BMM050_INT_STAT_HIGH_THZ__REG BMM050_INT_STAT
+
+#define BMM050_INT_STAT_HIGH_THY__POS 4
+#define BMM050_INT_STAT_HIGH_THY__LEN 1
+#define BMM050_INT_STAT_HIGH_THY__MSK 0x10
+#define BMM050_INT_STAT_HIGH_THY__REG BMM050_INT_STAT
+
+#define BMM050_INT_STAT_HIGH_THX__POS 3
+#define BMM050_INT_STAT_HIGH_THX__LEN 1
+#define BMM050_INT_STAT_HIGH_THX__MSK 0x08
+#define BMM050_INT_STAT_HIGH_THX__REG BMM050_INT_STAT
+
+#define BMM050_INT_STAT_LOW_THZ__POS 2
+#define BMM050_INT_STAT_LOW_THZ__LEN 1
+#define BMM050_INT_STAT_LOW_THZ__MSK 0x04
+#define BMM050_INT_STAT_LOW_THZ__REG BMM050_INT_STAT
+
+#define BMM050_INT_STAT_LOW_THY__POS 1
+#define BMM050_INT_STAT_LOW_THY__LEN 1
+#define BMM050_INT_STAT_LOW_THY__MSK 0x02
+#define BMM050_INT_STAT_LOW_THY__REG BMM050_INT_STAT
+
+#define BMM050_INT_STAT_LOW_THX__POS 0
+#define BMM050_INT_STAT_LOW_THX__LEN 1
+#define BMM050_INT_STAT_LOW_THX__MSK 0x01
+#define BMM050_INT_STAT_LOW_THX__REG BMM050_INT_STAT
+
+/* Power Control Register */
+#define BMM050_POWER_CNTL_SRST7__POS 7
+#define BMM050_POWER_CNTL_SRST7__LEN 1
+#define BMM050_POWER_CNTL_SRST7__MSK 0x80
+#define BMM050_POWER_CNTL_SRST7__REG BMM050_POWER_CNTL
+
+#define BMM050_POWER_CNTL_SPI3_EN__POS 2
+#define BMM050_POWER_CNTL_SPI3_EN__LEN 1
+#define BMM050_POWER_CNTL_SPI3_EN__MSK 0x04
+#define BMM050_POWER_CNTL_SPI3_EN__REG BMM050_POWER_CNTL
+
+#define BMM050_POWER_CNTL_SRST1__POS 1
+#define BMM050_POWER_CNTL_SRST1__LEN 1
+#define BMM050_POWER_CNTL_SRST1__MSK 0x02
+#define BMM050_POWER_CNTL_SRST1__REG BMM050_POWER_CNTL
+
+#define BMM050_POWER_CNTL_PCB__POS 0
+#define BMM050_POWER_CNTL_PCB__LEN 1
+#define BMM050_POWER_CNTL_PCB__MSK 0x01
+#define BMM050_POWER_CNTL_PCB__REG BMM050_POWER_CNTL
+
+/* Control Register */
+#define BMM050_CNTL_ADV_ST__POS 6
+#define BMM050_CNTL_ADV_ST__LEN 2
+#define BMM050_CNTL_ADV_ST__MSK 0xC0
+#define BMM050_CNTL_ADV_ST__REG BMM050_CONTROL
+
+#define BMM050_CNTL_DR__POS 3
+#define BMM050_CNTL_DR__LEN 3
+#define BMM050_CNTL_DR__MSK 0x38
+#define BMM050_CNTL_DR__REG BMM050_CONTROL
+
+#define BMM050_CNTL_OPMODE__POS 1
+#define BMM050_CNTL_OPMODE__LEN 2
+#define BMM050_CNTL_OPMODE__MSK 0x06
+#define BMM050_CNTL_OPMODE__REG BMM050_CONTROL
+
+#define BMM050_CNTL_S_TEST__POS 0
+#define BMM050_CNTL_S_TEST__LEN 1
+#define BMM050_CNTL_S_TEST__MSK 0x01
+#define BMM050_CNTL_S_TEST__REG BMM050_CONTROL
+
+/* Interupt Control Register */
+#define BMM050_INT_CNTL_DOR_EN__POS 7
+#define BMM050_INT_CNTL_DOR_EN__LEN 1
+#define BMM050_INT_CNTL_DOR_EN__MSK 0x80
+#define BMM050_INT_CNTL_DOR_EN__REG BMM050_INT_CNTL
+
+#define BMM050_INT_CNTL_OVRFLOW_EN__POS 6
+#define BMM050_INT_CNTL_OVRFLOW_EN__LEN 1
+#define BMM050_INT_CNTL_OVRFLOW_EN__MSK 0x40
+#define BMM050_INT_CNTL_OVRFLOW_EN__REG BMM050_INT_CNTL
+
+#define BMM050_INT_CNTL_HIGH_THZ_EN__POS 5
+#define BMM050_INT_CNTL_HIGH_THZ_EN__LEN 1
+#define BMM050_INT_CNTL_HIGH_THZ_EN__MSK 0x20
+#define BMM050_INT_CNTL_HIGH_THZ_EN__REG BMM050_INT_CNTL
+
+#define BMM050_INT_CNTL_HIGH_THY_EN__POS 4
+#define BMM050_INT_CNTL_HIGH_THY_EN__LEN 1
+#define BMM050_INT_CNTL_HIGH_THY_EN__MSK 0x10
+#define BMM050_INT_CNTL_HIGH_THY_EN__REG BMM050_INT_CNTL
+
+#define BMM050_INT_CNTL_HIGH_THX_EN__POS 3
+#define BMM050_INT_CNTL_HIGH_THX_EN__LEN 1
+#define BMM050_INT_CNTL_HIGH_THX_EN__MSK 0x08
+#define BMM050_INT_CNTL_HIGH_THX_EN__REG BMM050_INT_CNTL
+
+#define BMM050_INT_CNTL_LOW_THZ_EN__POS 2
+#define BMM050_INT_CNTL_LOW_THZ_EN__LEN 1
+#define BMM050_INT_CNTL_LOW_THZ_EN__MSK 0x04
+#define BMM050_INT_CNTL_LOW_THZ_EN__REG BMM050_INT_CNTL
+
+#define BMM050_INT_CNTL_LOW_THY_EN__POS 1
+#define BMM050_INT_CNTL_LOW_THY_EN__LEN 1
+#define BMM050_INT_CNTL_LOW_THY_EN__MSK 0x02
+#define BMM050_INT_CNTL_LOW_THY_EN__REG BMM050_INT_CNTL
+
+#define BMM050_INT_CNTL_LOW_THX_EN__POS 0
+#define BMM050_INT_CNTL_LOW_THX_EN__LEN 1
+#define BMM050_INT_CNTL_LOW_THX_EN__MSK 0x01
+#define BMM050_INT_CNTL_LOW_THX_EN__REG BMM050_INT_CNTL
+
+/* Sensor Control Register */
+#define BMM050_SENS_CNTL_DRDY_EN__POS 7
+#define BMM050_SENS_CNTL_DRDY_EN__LEN 1
+#define BMM050_SENS_CNTL_DRDY_EN__MSK 0x80
+#define BMM050_SENS_CNTL_DRDY_EN__REG BMM050_SENS_CNTL
+
+#define BMM050_SENS_CNTL_IE__POS 6
+#define BMM050_SENS_CNTL_IE__LEN 1
+#define BMM050_SENS_CNTL_IE__MSK 0x40
+#define BMM050_SENS_CNTL_IE__REG BMM050_SENS_CNTL
+
+#define BMM050_SENS_CNTL_CHANNELZ__POS 5
+#define BMM050_SENS_CNTL_CHANNELZ__LEN 1
+#define BMM050_SENS_CNTL_CHANNELZ__MSK 0x20
+#define BMM050_SENS_CNTL_CHANNELZ__REG BMM050_SENS_CNTL
+
+#define BMM050_SENS_CNTL_CHANNELY__POS 4
+#define BMM050_SENS_CNTL_CHANNELY__LEN 1
+#define BMM050_SENS_CNTL_CHANNELY__MSK 0x10
+#define BMM050_SENS_CNTL_CHANNELY__REG BMM050_SENS_CNTL
+
+#define BMM050_SENS_CNTL_CHANNELX__POS 3
+#define BMM050_SENS_CNTL_CHANNELX__LEN 1
+#define BMM050_SENS_CNTL_CHANNELX__MSK 0x08
+#define BMM050_SENS_CNTL_CHANNELX__REG BMM050_SENS_CNTL
+
+#define BMM050_SENS_CNTL_DR_POLARITY__POS 2
+#define BMM050_SENS_CNTL_DR_POLARITY__LEN 1
+#define BMM050_SENS_CNTL_DR_POLARITY__MSK 0x04
+#define BMM050_SENS_CNTL_DR_POLARITY__REG BMM050_SENS_CNTL
+
+#define BMM050_SENS_CNTL_INTERRUPT_LATCH__POS 1
+#define BMM050_SENS_CNTL_INTERRUPT_LATCH__LEN 1
+#define BMM050_SENS_CNTL_INTERRUPT_LATCH__MSK 0x02
+#define BMM050_SENS_CNTL_INTERRUPT_LATCH__REG BMM050_SENS_CNTL
+
+#define BMM050_SENS_CNTL_INTERRUPT_POLARITY__POS 0
+#define BMM050_SENS_CNTL_INTERRUPT_POLARITY__LEN 1
+#define BMM050_SENS_CNTL_INTERRUPT_POLARITY__MSK 0x01
+#define BMM050_SENS_CNTL_INTERRUPT_POLARITY__REG BMM050_SENS_CNTL
+
+/* Register 6D */
+#define BMM050_DIG_XYZ1_MSB__POS 0
+#define BMM050_DIG_XYZ1_MSB__LEN 7
+#define BMM050_DIG_XYZ1_MSB__MSK 0x7F
+#define BMM050_DIG_XYZ1_MSB__REG BMM050_DIG_XYZ1_MSB
+
+
+#define BMM050_X_AXIS 0
+#define BMM050_Y_AXIS 1
+#define BMM050_Z_AXIS 2
+#define BMM050_RESISTANCE 3
+#define BMM050_X 1
+#define BMM050_Y 2
+#define BMM050_Z 4
+#define BMM050_XYZ 7
+
+/* Constants */
+#define BMM050_NULL 0
+#define BMM050_DISABLE 0
+#define BMM050_ENABLE 1
+#define BMM050_CHANNEL_DISABLE 1
+#define BMM050_CHANNEL_ENABLE 0
+#define BMM050_INTPIN_LATCH_ENABLE 1
+#define BMM050_INTPIN_LATCH_DISABLE 0
+#define BMM050_OFF 0
+#define BMM050_ON 1
+
+#define BMM050_NORMAL_MODE 0x00
+#define BMM050_FORCED_MODE 0x01
+#define BMM050_SUSPEND_MODE 0x02
+#define BMM050_SLEEP_MODE 0x03
+
+#define BMM050_ADVANCED_SELFTEST_OFF 0
+#define BMM050_ADVANCED_SELFTEST_NEGATIVE 2
+#define BMM050_ADVANCED_SELFTEST_POSITIVE 3
+
+#define BMM050_NEGATIVE_SATURATION_Z -32767
+#define BMM050_POSITIVE_SATURATION_Z 32767
+
+#define BMM050_SPI_RD_MASK 0x80
+#define BMM050_READ_SET 0x01
+
+#define E_BMM050_NULL_PTR ((char)-127)
+#define E_BMM050_COMM_RES ((char)-1)
+#define E_BMM050_OUT_OF_RANGE ((char)-2)
+#define E_BMM050_UNDEFINED_MODE 0
+
+#define BMM050_WR_FUNC_PTR\
+ char (*bus_write)(unsigned char, unsigned char,\
+ unsigned char *, unsigned char)
+
+#define BMM050_RD_FUNC_PTR\
+ char (*bus_read)(unsigned char, unsigned char,\
+ unsigned char *, unsigned char)
+#define BMM050_MDELAY_DATA_TYPE unsigned int
+
+/*Shifting Constants*/
+#define SHIFT_RIGHT_1_POSITION 1
+#define SHIFT_RIGHT_2_POSITION 2
+#define SHIFT_RIGHT_3_POSITION 3
+#define SHIFT_RIGHT_4_POSITION 4
+#define SHIFT_RIGHT_5_POSITION 5
+#define SHIFT_RIGHT_6_POSITION 6
+#define SHIFT_RIGHT_7_POSITION 7
+#define SHIFT_RIGHT_8_POSITION 8
+
+#define SHIFT_LEFT_1_POSITION 1
+#define SHIFT_LEFT_2_POSITION 2
+#define SHIFT_LEFT_3_POSITION 3
+#define SHIFT_LEFT_4_POSITION 4
+#define SHIFT_LEFT_5_POSITION 5
+#define SHIFT_LEFT_6_POSITION 6
+#define SHIFT_LEFT_7_POSITION 7
+#define SHIFT_LEFT_8_POSITION 8
+
+/* Conversion factors*/
+#define BMM050_CONVFACTOR_LSB_UT 6
+
+/* get bit slice */
+#define BMM050_GET_BITSLICE(regvar, bitname)\
+ ((regvar & bitname##__MSK) >> bitname##__POS)
+
+/* Set bit slice */
+#define BMM050_SET_BITSLICE(regvar, bitname, val)\
+ ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK))
+
+/* compensated output value returned if sensor had overflow */
+#define BMM050_OVERFLOW_OUTPUT -32768
+#define BMM050_OVERFLOW_OUTPUT_S32 ((BMM050_S32)(-2147483647-1))
+#define BMM050_OVERFLOW_OUTPUT_FLOAT 0.0f
+#define BMM050_FLIP_OVERFLOW_ADCVAL -4096
+#define BMM050_HALL_OVERFLOW_ADCVAL -16384
+
+
+#define BMM050_PRESETMODE_LOWPOWER 1
+#define BMM050_PRESETMODE_REGULAR 2
+#define BMM050_PRESETMODE_HIGHACCURACY 3
+#define BMM050_PRESETMODE_ENHANCED 4
+
+/* PRESET MODES - DATA RATES */
+#define BMM050_LOWPOWER_DR BMM050_DR_10HZ
+#define BMM050_REGULAR_DR BMM050_DR_10HZ
+#define BMM050_HIGHACCURACY_DR BMM050_DR_20HZ
+#define BMM050_ENHANCED_DR BMM050_DR_10HZ
+
+/* PRESET MODES - REPETITIONS-XY RATES */
+#define BMM050_LOWPOWER_REPXY 1
+#define BMM050_REGULAR_REPXY 4
+#define BMM050_HIGHACCURACY_REPXY 23
+#define BMM050_ENHANCED_REPXY 7
+
+/* PRESET MODES - REPETITIONS-Z RATES */
+#define BMM050_LOWPOWER_REPZ 2
+#define BMM050_REGULAR_REPZ 15
+#define BMM050_HIGHACCURACY_REPZ 82
+#define BMM050_ENHANCED_REPZ 26
+
+/* Data Rates */
+
+#define BMM050_DR_10HZ 0
+#define BMM050_DR_02HZ 1
+#define BMM050_DR_06HZ 2
+#define BMM050_DR_08HZ 3
+#define BMM050_DR_15HZ 4
+#define BMM050_DR_20HZ 5
+#define BMM050_DR_25HZ 6
+#define BMM050_DR_30HZ 7
+
+/*user defined Structures*/
+struct bmm050_mdata {
+ BMM050_S16 datax;
+ BMM050_S16 datay;
+ BMM050_S16 dataz;
+ BMM050_U16 resistance;
+};
+struct bmm050_mdata_s32 {
+ BMM050_S32 datax;
+ BMM050_S32 datay;
+ BMM050_S32 dataz;
+ BMM050_U16 resistance;
+ BMM050_U16 drdy;
+};
+struct bmm050_mdata_float {
+ float datax;
+ float datay;
+ float dataz;
+ BMM050_U16 resistance;
+};
+
+struct bmm050 {
+ unsigned char company_id;
+ unsigned char dev_addr;
+
+ BMM050_WR_FUNC_PTR;
+ BMM050_RD_FUNC_PTR;
+ void(*delay_msec)(BMM050_MDELAY_DATA_TYPE);
+
+ signed char dig_x1;
+ signed char dig_y1;
+
+ signed char dig_x2;
+ signed char dig_y2;
+
+ BMM050_U16 dig_z1;
+ BMM050_S16 dig_z2;
+ BMM050_S16 dig_z3;
+ BMM050_S16 dig_z4;
+
+ unsigned char dig_xy1;
+ signed char dig_xy2;
+
+ BMM050_U16 dig_xyz1;
+};
+
+
+BMM050_RETURN_FUNCTION_TYPE bmm050_init(struct bmm050 *p_bmm050);
+BMM050_RETURN_FUNCTION_TYPE bmm050_read_mdataXYZ(
+ struct bmm050_mdata *mdata);
+BMM050_RETURN_FUNCTION_TYPE bmm050_read_mdataXYZ_s32(
+ struct bmm050_mdata_s32 *mdata);
+#ifdef ENABLE_FLOAT
+BMM050_RETURN_FUNCTION_TYPE bmm050_read_mdataXYZ_float(
+ struct bmm050_mdata_float *mdata);
+#endif
+BMM050_RETURN_FUNCTION_TYPE bmm050_read_register(
+ unsigned char addr, unsigned char *data, unsigned char len);
+BMM050_RETURN_FUNCTION_TYPE bmm050_write_register(
+ unsigned char addr, unsigned char *data, unsigned char len);
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_self_test_XYZ(
+ unsigned char *self_testxyz);
+BMM050_S16 bmm050_compensate_X(
+ BMM050_S16 mdata_x, BMM050_U16 data_R);
+BMM050_S32 bmm050_compensate_X_s32(
+ BMM050_S16 mdata_x, BMM050_U16 data_R);
+#ifdef ENABLE_FLOAT
+float bmm050_compensate_X_float(
+ BMM050_S16 mdata_x, BMM050_U16 data_R);
+#endif
+BMM050_S16 bmm050_compensate_Y(
+ BMM050_S16 mdata_y, BMM050_U16 data_R);
+BMM050_S32 bmm050_compensate_Y_s32(
+ BMM050_S16 mdata_y, BMM050_U16 data_R);
+#ifdef ENABLE_FLOAT
+float bmm050_compensate_Y_float(
+ BMM050_S16 mdata_y, BMM050_U16 data_R);
+#endif
+BMM050_S16 bmm050_compensate_Z(
+ BMM050_S16 mdata_z, BMM050_U16 data_R);
+BMM050_S32 bmm050_compensate_Z_s32(
+ BMM050_S16 mdata_z, BMM050_U16 data_R);
+#ifdef ENABLE_FLOAT
+float bmm050_compensate_Z_float(
+ BMM050_S16 mdata_z, BMM050_U16 data_R);
+#endif
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_raw_xyz(
+ struct bmm050_mdata *mdata);
+BMM050_RETURN_FUNCTION_TYPE bmm050_init_trim_registers(void);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_spi3(
+ unsigned char value);
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_powermode(
+ unsigned char *mode);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_powermode(
+ unsigned char mode);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_adv_selftest(
+ unsigned char adv_selftest);
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_adv_selftest(
+ unsigned char *adv_selftest);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_datarate(
+ unsigned char data_rate);
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_datarate(
+ unsigned char *data_rate);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_functional_state(
+ unsigned char functional_state);
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_functional_state(
+ unsigned char *functional_state);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_selftest(
+ unsigned char selftest);
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_selftest(
+ unsigned char *selftest);
+BMM050_RETURN_FUNCTION_TYPE bmm050_perform_advanced_selftest(
+ BMM050_S16 *diff_z);
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_repetitions_XY(
+ unsigned char *no_repetitions_xy);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_repetitions_XY(
+ unsigned char no_repetitions_xy);
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_repetitions_Z(
+ unsigned char *no_repetitions_z);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_repetitions_Z(
+ unsigned char no_repetitions_z);
+BMM050_RETURN_FUNCTION_TYPE bmm050_get_presetmode(unsigned char *mode);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_presetmode(unsigned char mode);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_control_measurement_x(
+ unsigned char enable_disable);
+BMM050_RETURN_FUNCTION_TYPE bmm050_set_control_measurement_y(
+ unsigned char enable_disable);
+BMM050_RETURN_FUNCTION_TYPE bmm050_soft_reset(void);
+#endif
diff --git a/drivers/sensor/bmm050_driver.c b/drivers/sensor/bmm050_driver.c
new file mode 100644
index 00000000..662f8ca1
--- /dev/null
+++ b/drivers/sensor/bmm050_driver.c
@@ -0,0 +1,1593 @@
+/*
+ * (C) Copyright 2013 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
+ *
+ * @date Jun 12th, 2013
+ * @version v2.5.5
+ * @brief BMM050 Linux Driver
+ */
+
+#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/sensors_core.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#define DEBUG 1
+
+#include <linux/bst_sensor_common.h>
+
+#include "bmm050.h"
+#include "bs_log.h"
+
+/* sensor specific */
+#define SENSOR_NAME "bmm050"
+
+#define SENSOR_CHIP_ID_BMM (0x32)
+
+#define BMM_REG_NAME(name) BMM050_##name
+#define BMM_VAL_NAME(name) BMM050_##name
+#define BMM_CALL_API(name) bmm050_##name
+
+#define BMM_I2C_WRITE_DELAY_TIME 1
+
+#define BMM_DEFAULT_REPETITION_XY BMM_VAL_NAME(REGULAR_REPXY)
+#define BMM_DEFAULT_REPETITION_Z BMM_VAL_NAME(REGULAR_REPZ)
+#define BMM_DEFAULT_ODR BMM_VAL_NAME(REGULAR_DR)
+/* generic */
+#define BMM_MAX_RETRY_I2C_XFER (100)
+#define BMM_MAX_RETRY_WAKEUP (5)
+#define BMM_MAX_RETRY_WAIT_DRDY (100)
+
+#define BMM_DELAY_MIN (1)
+#define BMM_DELAY_DEFAULT (200)
+
+#define MAG_VALUE_MAX (32767)
+#define MAG_VALUE_MIN (-32768)
+
+#define BYTES_PER_LINE (16)
+
+#define BMM_SELF_TEST 1
+#define BMM_ADV_TEST 2
+
+#define BMM_OP_MODE_UNKNOWN (-1)
+
+static struct device *bmm_device = NULL;
+struct op_mode_map {
+ char *op_mode_name;
+ long op_mode;
+};
+
+static const u8 odr_map[] = {10, 2, 6, 8, 15, 20, 25, 30};
+static const struct op_mode_map op_mode_maps[] = {
+ {"normal", BMM_VAL_NAME(NORMAL_MODE)},
+ {"forced", BMM_VAL_NAME(FORCED_MODE)},
+ {"suspend", BMM_VAL_NAME(SUSPEND_MODE)},
+ {"sleep", BMM_VAL_NAME(SLEEP_MODE)},
+};
+
+
+struct bmm_client_data {
+ struct bmm050 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;
+ /* whether the system in suspend state */
+ atomic_t in_suspend;
+
+ struct bmm050_mdata_s32 value;
+ u8 enable:1;
+ s8 op_mode:4;
+ u8 odr;
+ u8 rept_xy;
+ u8 rept_z;
+
+ s16 result_test;
+
+ struct mutex mutex_power_mode;
+
+ /* controls not only reg, but also workqueue */
+ struct mutex mutex_op_mode;
+ struct mutex mutex_enable;
+ struct mutex mutex_odr;
+ struct mutex mutex_rept_xy;
+ struct mutex mutex_rept_z;
+
+ struct mutex mutex_value;
+#ifdef CONFIG_BMM_USE_PLATFORM_DATA
+ struct bosch_sensor_specific *bst_pd;
+#endif
+};
+
+static struct i2c_client *bmm_client;
+/* i2c operation for API */
+static void bmm_delay(u32 msec);
+static char bmm_i2c_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len);
+static char bmm_i2c_write(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len);
+
+static void bmm_dump_reg(struct i2c_client *client);
+static int bmm_wakeup(struct i2c_client *client);
+static int bmm_check_chip_id(struct i2c_client *client);
+
+static int bmm_pre_suspend(struct i2c_client *client);
+static int bmm_post_resume(struct i2c_client *client);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void bmm_early_suspend(struct early_suspend *handler);
+static void bmm_late_resume(struct early_suspend *handler);
+#endif
+
+static int bmm_restore_hw_cfg(struct i2c_client *client);
+
+static void bmm_remap_sensor_data(struct bmm050_mdata_s32 *val,
+ struct bmm_client_data *client_data)
+{
+#ifdef CONFIG_BMM_USE_PLATFORM_DATA
+ struct bosch_sensor_data bsd;
+
+ if (NULL == client_data->bst_pd)
+ return;
+
+ bsd.x = val->datax;
+ bsd.y = val->datay;
+ bsd.z = val->dataz;
+
+ bst_remap_sensor_data_dft_tab(&bsd,
+ client_data->bst_pd->place);
+
+ val->datax = bsd.x;
+ val->datay = bsd.y;
+ val->dataz = bsd.z;
+#else
+ (void)val;
+ (void)client_data;
+#endif
+}
+
+static int bmm_check_chip_id(struct i2c_client *client)
+{
+ int err = 0;
+ u8 chip_id = 0;
+
+ bmm_i2c_read(client, BMM_REG_NAME(CHIP_ID), &chip_id, 1);
+ PINFO("read chip id result: %#x", chip_id);
+
+ if ((chip_id & 0xff) != SENSOR_CHIP_ID_BMM)
+ err = -1;
+
+ return err;
+}
+
+static void bmm_delay(u32 msec)
+{
+ mdelay(msec);
+}
+
+static inline int bmm_get_forced_drdy_time(int rept_xy, int rept_z)
+{
+ return (145 * rept_xy + 500 * rept_z + 980 + (1000 - 1)) / 1000;
+}
+
+
+static void bmm_dump_reg(struct i2c_client *client)
+{
+#ifdef DEBUG
+ 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;
+ sprintf(dbg_buf_str + i * 3, "%02x%c",
+ dbg_buf[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ printk(KERN_DEBUG "%s\n", dbg_buf_str);
+
+ bmm_i2c_read(client, BMM_REG_NAME(CHIP_ID), dbg_buf, 64);
+ for (i = 0; i < 64; i++) {
+ sprintf(dbg_buf_str + i * 3, "%02x%c",
+ dbg_buf[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ printk(KERN_DEBUG "%s\n", dbg_buf_str);
+#endif
+}
+
+static int bmm_wakeup(struct i2c_client *client)
+{
+ int err = 0;
+ int try_times = BMM_MAX_RETRY_WAKEUP;
+ const u8 value = 0x01;
+ u8 dummy;
+
+ PINFO("waking up the chip...");
+
+ while (try_times) {
+ err = bmm_i2c_write(client,
+ BMM_REG_NAME(POWER_CNTL), (u8 *)&value, 1);
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+ dummy = 0;
+
+ err = bmm_i2c_read(client, BMM_REG_NAME(POWER_CNTL), &dummy, 1);
+ if (value == dummy)
+ break;
+
+ try_times--;
+ }
+
+ PINFO("wake up result: %s, tried times: %d",
+ (try_times > 0) ? "succeed" : "fail",
+ BMM_MAX_RETRY_WAKEUP - try_times + 1);
+
+ err = (try_times > 0) ? 0 : -1;
+
+ return err;
+}
+
+/* i2c read routine for API*/
+static char bmm_i2c_read(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len)
+{
+#if !defined BMM_USE_BASIC_I2C_FUNC
+ s32 dummy;
+ if (NULL == client)
+ return -1;
+
+ while (0 != len--) {
+#ifdef BMM_SMBUS
+ dummy = i2c_smbus_read_byte_data(client, reg_addr);
+ if (dummy < 0) {
+ PERR("i2c bus read error");
+ return -1;
+ }
+ *data = (u8)(dummy & 0xff);
+#else
+ dummy = i2c_master_send(client, (char *)&reg_addr, 1);
+ if (dummy < 0)
+ return -1;
+
+ dummy = i2c_master_recv(client, (char *)data, 1);
+ if (dummy < 0)
+ return -1;
+#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 < BMM_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+ }
+
+ if (BMM_MAX_RETRY_I2C_XFER <= retry) {
+ PERR("I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+#endif
+}
+
+/* i2c write routine for */
+static char bmm_i2c_write(struct i2c_client *client, u8 reg_addr,
+ u8 *data, u8 len)
+{
+#if !defined BMM_USE_BASIC_I2C_FUNC
+ s32 dummy;
+
+#ifndef BMM_SMBUS
+ u8 buffer[2];
+#endif
+
+ if (NULL == client)
+ return -1;
+
+ while (0 != len--) {
+#ifdef BMM_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 -1;
+ }
+
+ }
+ 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 < BMM_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(client->adapter, msg,
+ ARRAY_SIZE(msg)) > 0) {
+ break;
+ } else {
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+ }
+ }
+ if (BMM_MAX_RETRY_I2C_XFER <= retry) {
+ PERR("I2C xfer error");
+ return -EIO;
+ }
+ reg_addr++;
+ data++;
+ }
+
+ return 0;
+#endif
+}
+
+static char bmm_i2c_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ char err = 0;
+ err = bmm_i2c_read(bmm_client, reg_addr, data, len);
+
+ return err;
+}
+
+static char bmm_i2c_write_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
+{
+ char err = 0;
+ err = bmm_i2c_write(bmm_client, reg_addr, data, len);
+ return err;
+}
+
+/* this function exists for optimization of speed,
+ * because it is frequently called */
+static inline int bmm_set_forced_mode(struct i2c_client *client)
+{
+ int err = 0;
+
+ /* FORCED_MODE */
+ const u8 value = 0x02;
+ err = bmm_i2c_write(client, BMM_REG_NAME(CONTROL), (u8 *)&value, 1);
+
+ return err;
+}
+
+static void bmm_work_func(struct work_struct *work)
+{
+ struct bmm_client_data *client_data =
+ container_of((struct delayed_work *)work,
+ struct bmm_client_data, work);
+ struct i2c_client *client = client_data->client;
+ unsigned long delay =
+ msecs_to_jiffies(atomic_read(&client_data->delay));
+
+ mutex_lock(&client_data->mutex_value);
+
+ mutex_lock(&client_data->mutex_op_mode);
+ if (BMM_VAL_NAME(NORMAL_MODE) != client_data->op_mode)
+ bmm_set_forced_mode(client);
+
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ BMM_CALL_API(read_mdataXYZ_s32)(&client_data->value);
+ bmm_remap_sensor_data(&client_data->value, client_data);
+
+ input_report_abs(client_data->input, ABS_X, client_data->value.datax);
+ input_report_abs(client_data->input, ABS_Y, client_data->value.datay);
+ input_report_abs(client_data->input, ABS_Z, client_data->value.dataz);
+ mutex_unlock(&client_data->mutex_value);
+
+ input_sync(client_data->input);
+
+ schedule_delayed_work(&client_data->work, delay);
+}
+
+
+static int bmm_set_odr(struct i2c_client *client, u8 odr)
+{
+ int err = 0;
+
+ err = BMM_CALL_API(set_datarate)(odr);
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+
+ return err;
+}
+
+static int bmm_get_odr(struct i2c_client *client, u8 *podr)
+{
+ int err = 0;
+ u8 value;
+
+ err = BMM_CALL_API(get_datarate)(&value);
+ if (!err)
+ *podr = value;
+
+ return err;
+}
+
+static ssize_t bmm_show_chip_id(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", SENSOR_CHIP_ID_BMM);
+}
+
+static ssize_t bmm_show_op_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ u8 op_mode = 0xff;
+ u8 power_mode;
+
+ mutex_lock(&client_data->mutex_power_mode);
+ BMM_CALL_API(get_powermode)(&power_mode);
+ if (power_mode) {
+ mutex_lock(&client_data->mutex_op_mode);
+ BMM_CALL_API(get_functional_state)(&op_mode);
+ mutex_unlock(&client_data->mutex_op_mode);
+ } else {
+ op_mode = BMM_VAL_NAME(SUSPEND_MODE);
+ }
+
+ mutex_unlock(&client_data->mutex_power_mode);
+
+ PDEBUG("op_mode: %d", op_mode);
+
+ ret = sprintf(buf, "%d\n", op_mode);
+
+ return ret;
+}
+
+
+static inline int bmm_get_op_mode_idx(u8 op_mode)
+{
+ int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(op_mode_maps); i++) {
+ if (op_mode_maps[i].op_mode == op_mode)
+ break;
+ }
+
+ if (i < ARRAY_SIZE(op_mode_maps))
+ return i;
+ else
+ return -1;
+}
+
+
+static int bmm_set_op_mode(struct bmm_client_data *client_data, int op_mode)
+{
+ int err = 0;
+
+ err = BMM_CALL_API(set_functional_state)(
+ op_mode);
+
+ if (BMM_VAL_NAME(SUSPEND_MODE) == op_mode)
+ atomic_set(&client_data->in_suspend, 1);
+ else
+ atomic_set(&client_data->in_suspend, 0);
+
+ return err;
+}
+
+static ssize_t bmm_store_op_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err = 0;
+ int i;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ struct i2c_client *client = client_data->client;
+ long op_mode;
+
+ err = strict_strtoul(buf, 10, &op_mode);
+ if (err)
+ return err;
+
+ mutex_lock(&client_data->mutex_power_mode);
+
+ i = bmm_get_op_mode_idx(op_mode);
+
+ if (i != -1) {
+ mutex_lock(&client_data->mutex_op_mode);
+ if (op_mode != client_data->op_mode) {
+ if (BMM_VAL_NAME(FORCED_MODE) == op_mode) {
+ /* special treat of forced mode
+ * for optimization */
+ err = bmm_set_forced_mode(client);
+ } else {
+ err = bmm_set_op_mode(client_data, op_mode);
+ }
+
+ if (!err) {
+ if (BMM_VAL_NAME(FORCED_MODE) == op_mode)
+ client_data->op_mode =
+ BMM_OP_MODE_UNKNOWN;
+ else
+ client_data->op_mode = op_mode;
+ }
+ }
+ mutex_unlock(&client_data->mutex_op_mode);
+ } else {
+ err = -EINVAL;
+ }
+
+ mutex_unlock(&client_data->mutex_power_mode);
+
+ if (err)
+ return err;
+ else
+ return count;
+}
+
+static ssize_t bmm_show_odr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ struct i2c_client *client = client_data->client;
+ int err;
+ u8 power_mode;
+
+ mutex_lock(&client_data->mutex_power_mode);
+ BMM_CALL_API(get_powermode)(&power_mode);
+ if (power_mode) {
+ mutex_lock(&client_data->mutex_odr);
+ err = bmm_get_odr(client, &data);
+ mutex_unlock(&client_data->mutex_odr);
+ } else {
+ err = -EIO;
+ }
+ mutex_unlock(&client_data->mutex_power_mode);
+
+ if (!err) {
+ if (data < ARRAY_SIZE(odr_map))
+ err = sprintf(buf, "%d\n", odr_map[data]);
+ else
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static ssize_t bmm_store_odr(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char data;
+ int err;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ struct i2c_client *client = client_data->client;
+ u8 power_mode;
+ int i;
+
+ err = strict_strtoul(buf, 10, &tmp);
+ if (err)
+ return err;
+
+ if (tmp > 255)
+ return -EINVAL;
+
+ data = (unsigned char)tmp;
+
+ mutex_lock(&client_data->mutex_power_mode);
+ BMM_CALL_API(get_powermode)(&power_mode);
+ if (power_mode) {
+ for (i = 0; i < ARRAY_SIZE(odr_map); i++) {
+ if (odr_map[i] == data)
+ break;
+ }
+
+ if (i < ARRAY_SIZE(odr_map)) {
+ mutex_lock(&client_data->mutex_odr);
+ err = bmm_set_odr(client, i);
+ if (!err)
+ client_data->odr = i;
+
+ mutex_unlock(&client_data->mutex_odr);
+ } else {
+ err = -EINVAL;
+ }
+ } else {
+ err = -EIO;
+ }
+
+ mutex_unlock(&client_data->mutex_power_mode);
+ if (err)
+ return err;
+
+ return count;
+}
+
+static ssize_t bmm_show_rept_xy(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ int err;
+ u8 power_mode;
+
+ mutex_lock(&client_data->mutex_power_mode);
+ BMM_CALL_API(get_powermode)(&power_mode);
+ printk(KERN_ALERT"%s : value of power_mode after get_powermode %u \n",__func__, power_mode);
+
+ if (power_mode) {
+ mutex_lock(&client_data->mutex_rept_xy);
+ err = BMM_CALL_API(get_repetitions_XY)(&data);
+ printk(KERN_ALERT"%s : value of power_mode after get_repretitions_XY %u \n",__func__, data);
+ mutex_unlock(&client_data->mutex_rept_xy);
+ } else {
+ err = -EIO;
+ }
+
+ mutex_unlock(&client_data->mutex_power_mode);
+
+ if (err)
+ return err;
+
+ return sprintf(buf, "%d\n", data);
+}
+
+static ssize_t bmm_store_rept_xy(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long tmp = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ int err;
+ u8 data;
+ u8 power_mode;
+
+ err = strict_strtoul(buf, 10, &tmp);
+ if (err)
+ return err;
+
+ if (tmp > 255)
+ return -EINVAL;
+
+ data = (unsigned char)tmp;
+
+ mutex_lock(&client_data->mutex_power_mode);
+ BMM_CALL_API(get_powermode)(&power_mode);
+ printk(KERN_ALERT"%s : value of power_mode after get_powermode %u\n",__func__, power_mode);
+
+ if (power_mode) {
+ mutex_lock(&client_data->mutex_rept_xy);
+ err = BMM_CALL_API(set_repetitions_XY)(data);
+ printk(KERN_ALERT "%s : value of power_mode after set_repretitions_XY %u \n",__func__,data);
+
+ if (!err) {
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+ client_data->rept_xy = data;
+ }
+ mutex_unlock(&client_data->mutex_rept_xy);
+ } else {
+ err = -EIO;
+ }
+ mutex_unlock(&client_data->mutex_power_mode);
+
+ if (err)
+ return err;
+
+ return count;
+}
+
+static ssize_t bmm_show_rept_z(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned char data = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ int err;
+ u8 power_mode;
+
+ mutex_lock(&client_data->mutex_power_mode);
+ BMM_CALL_API(get_powermode)(&power_mode);
+ printk(KERN_ALERT"%s : value of power_mode after get_powermode %u\n",__func__, power_mode);
+ if (power_mode) {
+ mutex_lock(&client_data->mutex_rept_z);
+ err = BMM_CALL_API(get_repetitions_Z)(&data);
+ printk(KERN_ALERT"%s : value of power_mode after get_repretitions_XY %u \n",__func__, data);
+ mutex_unlock(&client_data->mutex_rept_z);
+ } else {
+ err = -EIO;
+ }
+
+ mutex_unlock(&client_data->mutex_power_mode);
+
+ if (err)
+ return err;
+
+ return sprintf(buf, "%d\n", data);
+}
+
+static ssize_t bmm_store_rept_z(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long tmp = 0;
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ int err;
+ u8 data;
+ u8 power_mode;
+
+ err = strict_strtoul(buf, 10, &tmp);
+ if (err)
+ return err;
+
+ if (tmp > 255)
+ return -EINVAL;
+
+ data = (unsigned char)tmp;
+
+ mutex_lock(&client_data->mutex_power_mode);
+ BMM_CALL_API(get_powermode)(&power_mode);
+ printk(KERN_ALERT" %s : value of power_mode after get_powermode %u\n",__func__, power_mode);
+ if (power_mode) {
+ mutex_lock(&client_data->mutex_rept_z);
+ err = BMM_CALL_API(set_repetitions_Z)(data);
+ printk(KERN_ALERT"%s : value of power_mode after set_repretitions_XY %u \n",__func__, data);
+ if (!err) {
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+ client_data->rept_z = data;
+ }
+ mutex_unlock(&client_data->mutex_rept_z);
+ } else {
+ err = -EIO;
+ }
+ mutex_unlock(&client_data->mutex_power_mode);
+
+ if (err)
+ return err;
+
+ return count;
+}
+
+
+static ssize_t bmm_show_value(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ int count;
+ struct bmm050_mdata_s32 value = {0, 0, 0, 0, 0};
+
+ BMM_CALL_API(read_mdataXYZ_s32)(&value);
+ if (value.drdy) {
+ bmm_remap_sensor_data(&value, client_data);
+ client_data->value = value;
+ } else
+ PERR("data not ready");
+
+ count = sprintf(buf, "%d %d %d\n",
+ client_data->value.datax,
+ client_data->value.datay,
+ client_data->value.dataz);
+ PDEBUG("%d %d %d",
+ client_data->value.datax,
+ client_data->value.datay,
+ client_data->value.dataz);
+
+ return count;
+}
+
+
+static ssize_t bmm_show_value_raw(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bmm050_mdata value;
+ int count;
+
+ BMM_CALL_API(get_raw_xyz)(&value);
+
+ count = sprintf(buf, "%hd %hd %hd\n",
+ value.datax,
+ value.datay,
+ value.dataz);
+
+ return count;
+}
+
+
+static ssize_t bmm_show_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ int err;
+
+ mutex_lock(&client_data->mutex_enable);
+ err = sprintf(buf, "%d\n", client_data->enable);
+ mutex_unlock(&client_data->mutex_enable);
+ return err;
+}
+
+static void bmm_input_destroy(struct bmm_client_data *client_data)
+{
+ struct input_dev *dev = client_data->input;
+
+ input_unregister_device(dev);
+ input_free_device(dev);
+}
+
+static ssize_t bmm_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 bmm_client_data *client_data = input_get_drvdata(input);
+
+ err = strict_strtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ data = data ? 1 : 0;
+ mutex_lock(&client_data->mutex_enable);
+
+ if (data != client_data->enable) {
+ if (data) {
+
+ err = bmm_set_op_mode(client_data, BMM_VAL_NAME(NORMAL_MODE));
+ if (err)
+ {
+ PERR(" %s : fail to init h/w of %s",__func__, SENSOR_NAME);
+ err = -EIO;
+ goto exit_err_sysfs;
+ }
+ schedule_delayed_work(
+ &client_data->work,
+ msecs_to_jiffies(atomic_read(
+ &client_data->delay)));
+ } else {
+
+ err = bmm_set_op_mode(client_data, BMM_VAL_NAME(SUSPEND_MODE));
+ if (err)
+ {
+ PERR(" %s : fail to init h/w of %s",__func__, SENSOR_NAME);
+ err = -EIO;
+ goto exit_err_sysfs;
+ }
+ cancel_delayed_work_sync(&client_data->work);
+ }
+
+ client_data->enable = data;
+ }
+ mutex_unlock(&client_data->mutex_enable);
+
+exit_err_sysfs:
+ if (err)
+ bmm_input_destroy(client_data);
+
+ return count;
+}
+
+static ssize_t bmm_show_delay(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+
+ return sprintf(buf, "%d\n", atomic_read(&client_data->delay));
+
+}
+
+static ssize_t bmm_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 bmm_client_data *client_data = input_get_drvdata(input);
+
+ err = strict_strtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ if (data <= 0) {
+ err = -EINVAL;
+ return err;
+ }
+
+ if (data < BMM_DELAY_MIN)
+ data = BMM_DELAY_MIN;
+
+ atomic_set(&client_data->delay, data);
+
+ return count;
+}
+
+static ssize_t bmm_show_test(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ int err;
+
+ err = sprintf(buf, "%d\n", client_data->result_test);
+ return err;
+}
+
+static ssize_t bmm_store_test(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 bmm_client_data *client_data = input_get_drvdata(input);
+ struct i2c_client *client = client_data->client;
+ u8 dummy;
+
+ err = strict_strtoul(buf, 10, &data);
+ if (err)
+ return err;
+
+ /* the following code assumes the work thread is not running */
+ if (BMM_SELF_TEST == data) {
+ /* self test */
+ err = bmm_set_op_mode(client_data, BMM_VAL_NAME(SLEEP_MODE));
+ mdelay(3);
+ err = BMM_CALL_API(set_selftest)(1);
+ mdelay(3);
+ err = BMM_CALL_API(get_self_test_XYZ)(&dummy);
+ client_data->result_test = dummy;
+ } else if (BMM_ADV_TEST == data) {
+ /* advanced self test */
+ err = BMM_CALL_API(perform_advanced_selftest)(
+ &client_data->result_test);
+ } else {
+ err = -EINVAL;
+ }
+
+ if (!err) {
+ BMM_CALL_API(soft_reset)();
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+ bmm_restore_hw_cfg(client);
+ }
+
+ if (err)
+ count = -1;
+
+ return count;
+}
+
+
+static ssize_t bmm_show_reg(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err = 0;
+ int i;
+ u8 dbg_buf[64];
+ u8 dbg_buf_str[64 * 3 + 1] = "";
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+ struct i2c_client *client = client_data->client;
+
+ for (i = 0; i < BYTES_PER_LINE; i++) {
+ dbg_buf[i] = i;
+ sprintf(dbg_buf_str + i * 3, "%02x%c",
+ dbg_buf[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ memcpy(buf, dbg_buf_str, BYTES_PER_LINE * 3);
+
+ for (i = 0; i < BYTES_PER_LINE * 3 - 1; i++)
+ dbg_buf_str[i] = '-';
+
+ dbg_buf_str[i] = '\n';
+ memcpy(buf + BYTES_PER_LINE * 3, dbg_buf_str, BYTES_PER_LINE * 3);
+
+
+ bmm_i2c_read(client, BMM_REG_NAME(CHIP_ID), dbg_buf, 64);
+ for (i = 0; i < 64; i++) {
+ sprintf(dbg_buf_str + i * 3, "%02x%c",
+ dbg_buf[i],
+ (((i + 1) % BYTES_PER_LINE == 0) ? '\n' : ' '));
+ }
+ memcpy(buf + BYTES_PER_LINE * 3 + BYTES_PER_LINE * 3,
+ dbg_buf_str, 64 * 3);
+
+ err = BYTES_PER_LINE * 3 + BYTES_PER_LINE * 3 + 64 * 3;
+ return err;
+}
+
+
+static ssize_t bmm_show_place(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+#ifdef CONFIG_BMM_USE_PLATFORM_DATA
+ struct input_dev *input = to_input_dev(dev);
+ struct bmm_client_data *client_data = input_get_drvdata(input);
+#endif
+ int place = BOSCH_SENSOR_PLACE_UNKNOWN;
+
+#ifdef CONFIG_BMM_USE_PLATFORM_DATA
+ if (NULL != client_data->bst_pd)
+ place = client_data->bst_pd->place;
+#endif
+ return sprintf(buf, "%d\n", place);
+}
+
+
+static DEVICE_ATTR(chip_id, S_IRUGO,
+ bmm_show_chip_id, NULL);
+static DEVICE_ATTR(op_mode, S_IRUGO|S_IWUSR,
+ bmm_show_op_mode, bmm_store_op_mode);
+static DEVICE_ATTR(odr, S_IRUGO|S_IWUSR,
+ bmm_show_odr, bmm_store_odr);
+static DEVICE_ATTR(rept_xy, S_IRUGO|S_IWUSR,
+ bmm_show_rept_xy, bmm_store_rept_xy);
+static DEVICE_ATTR(rept_z, S_IRUGO|S_IWUSR,
+ bmm_show_rept_z, bmm_store_rept_z);
+static DEVICE_ATTR(value, S_IRUGO,
+ bmm_show_value, NULL);
+static DEVICE_ATTR(value_raw, S_IRUGO,
+ bmm_show_value_raw, NULL);
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
+ bmm_show_enable, bmm_store_enable);
+static DEVICE_ATTR(delay, S_IRUGO|S_IWUSR,
+ bmm_show_delay, bmm_store_delay);
+static DEVICE_ATTR(test, S_IRUGO|S_IWUSR,
+ bmm_show_test, bmm_store_test);
+static DEVICE_ATTR(reg, S_IRUGO,
+ bmm_show_reg, NULL);
+static DEVICE_ATTR(place, S_IRUGO,
+ bmm_show_place, NULL);
+
+static struct attribute *bmm_attributes[] = {
+ &dev_attr_chip_id.attr,
+ &dev_attr_op_mode.attr,
+ &dev_attr_odr.attr,
+ &dev_attr_rept_xy.attr,
+ &dev_attr_rept_z.attr,
+ &dev_attr_value.attr,
+ &dev_attr_value_raw.attr,
+ &dev_attr_enable.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_test.attr,
+ &dev_attr_reg.attr,
+ &dev_attr_place.attr,
+ NULL
+};
+
+
+static struct attribute_group bmm_attribute_group = {
+ .attrs = bmm_attributes
+};
+
+
+static struct device_attribute *bmm050_attr[] = {
+ &dev_attr_value,
+ &dev_attr_value_raw,
+ &dev_attr_enable,
+ NULL,
+ };
+
+static int bmm_input_init(struct bmm_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, MAG_VALUE_MIN, MAG_VALUE_MAX, 0, 0);
+ input_set_abs_params(dev, ABS_Y, MAG_VALUE_MIN, MAG_VALUE_MAX, 0, 0);
+ input_set_abs_params(dev, ABS_Z, MAG_VALUE_MIN, MAG_VALUE_MAX, 0, 0);
+ 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 int bmm_restore_hw_cfg(struct i2c_client *client)
+{
+ int err = 0;
+ u8 value;
+ struct bmm_client_data *client_data =
+ (struct bmm_client_data *)i2c_get_clientdata(client);
+ int op_mode;
+
+ mutex_lock(&client_data->mutex_op_mode);
+ err = bmm_set_op_mode(client_data, BMM_VAL_NAME(SLEEP_MODE));
+
+ if (bmm_get_op_mode_idx(client_data->op_mode) != -1)
+ err = bmm_set_op_mode(client_data, client_data->op_mode);
+
+ op_mode = client_data->op_mode;
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ if (BMM_VAL_NAME(SUSPEND_MODE) == op_mode)
+ return err;
+
+ PINFO("app did not close this sensor before suspend");
+
+ mutex_lock(&client_data->mutex_odr);
+ BMM_CALL_API(set_datarate)(client_data->odr);
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+ mutex_unlock(&client_data->mutex_odr);
+
+ mutex_lock(&client_data->mutex_rept_xy);
+ err = bmm_i2c_write(client, BMM_REG_NAME(NO_REPETITIONS_XY),
+ &client_data->rept_xy, 1);
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+ err = bmm_i2c_read(client, BMM_REG_NAME(NO_REPETITIONS_XY), &value, 1);
+ PINFO("BMM_NO_REPETITIONS_XY: %02x", value);
+ mutex_unlock(&client_data->mutex_rept_xy);
+
+ mutex_lock(&client_data->mutex_rept_z);
+ err = bmm_i2c_write(client, BMM_REG_NAME(NO_REPETITIONS_Z),
+ &client_data->rept_z, 1);
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+ err = bmm_i2c_read(client, BMM_REG_NAME(NO_REPETITIONS_Z), &value, 1);
+ PINFO("BMM_NO_REPETITIONS_Z: %02x", value);
+ mutex_unlock(&client_data->mutex_rept_z);
+
+ mutex_lock(&client_data->mutex_op_mode);
+ if (BMM_OP_MODE_UNKNOWN == (int)client_data->op_mode) {
+ bmm_set_forced_mode(client);
+ PINFO("set forced mode after hw_restore");
+ mdelay(bmm_get_forced_drdy_time(client_data->rept_xy,
+ client_data->rept_z));
+ }
+ mutex_unlock(&client_data->mutex_op_mode);
+
+
+ PINFO("register dump after init");
+ bmm_dump_reg(client);
+
+ return err;
+}
+
+static int bmm_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct bmm_client_data *client_data = NULL;
+ int dummy;
+
+ printk(KERN_ALERT"%s : function entrance\n",__func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ PERR("%s : i2c_check_functionality error!\n",__func__);
+ err = -EIO;
+ goto exit_err_clean;
+ }
+
+ if (NULL == bmm_client) {
+ bmm_client = client;
+ } else {
+ PERR("this driver does not support multiple clients");
+ err = -EBUSY;
+ return err;
+ }
+
+ /* wake up the chip */
+ dummy = bmm_wakeup(client);
+ if (dummy < 0) {
+ PERR("Cannot wake up %s, I2C xfer error", SENSOR_NAME);
+ err = -EIO;
+ goto exit_err_clean;
+ }
+
+ PINFO("register dump after waking up");
+ bmm_dump_reg(client);
+ /* check chip id */
+ err = bmm_check_chip_id(client);
+ if (!err) {
+ PNOTICE("Bosch Sensortec Device %s detected: %#x",
+ SENSOR_NAME, client->addr);
+ } else {
+ PERR("Bosch Sensortec Device not found, chip id mismatch");
+ err = -1;
+ goto exit_err_clean;
+ }
+
+ client_data = kzalloc(sizeof(struct bmm_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_power_mode);
+ mutex_init(&client_data->mutex_op_mode);
+ mutex_init(&client_data->mutex_enable);
+ mutex_init(&client_data->mutex_odr);
+ mutex_init(&client_data->mutex_rept_xy);
+ mutex_init(&client_data->mutex_rept_z);
+ mutex_init(&client_data->mutex_value);
+
+ /* input device init */
+ err = bmm_input_init(client_data);
+ if (err < 0)
+ goto exit_err_clean;
+
+ /* sysfs node creation */
+ err = sysfs_create_group(&client_data->input->dev.kobj,
+ &bmm_attribute_group);
+ printk(KERN_ALERT"%s : sysfs for magnetic created \n",__func__);
+
+ if (err < 0)
+ goto exit_err_sysfs;
+
+#ifdef CONFIG_BMM_USE_PLATFORM_DATA
+
+ printk(KERN_ALERT"%s Entering Plat Data bmm \n",__func__);
+ if (NULL != client->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, client->dev.platform_data,
+ sizeof(*client_data->bst_pd));
+
+ printk(KERN_ALERT" %s : platform data of bmm %s: place: %d, irq: %d",__func__,
+ client_data->bst_pd->name,
+ client_data->bst_pd->place,
+ client_data->bst_pd->irq);
+ }
+ }
+#endif
+
+
+ /* workqueue init */
+ INIT_DELAYED_WORK(&client_data->work, bmm_work_func);
+ atomic_set(&client_data->delay, BMM_DELAY_DEFAULT);
+
+ /* h/w init */
+ client_data->device.bus_read = bmm_i2c_read_wrapper;
+ client_data->device.bus_write = bmm_i2c_write_wrapper;
+ client_data->device.delay_msec = bmm_delay;
+
+ BMM_CALL_API(init)(&client_data->device);
+
+ bmm_dump_reg(client);
+
+ PDEBUG(" %s : trimming_reg x1: %d y1: %d x2: %d y2: %d xy1: %d xy2: %d\n",__func__,
+ client_data->device.dig_x1,
+ client_data->device.dig_y1,
+ client_data->device.dig_x2,
+ client_data->device.dig_y2,
+ client_data->device.dig_xy1,
+ client_data->device.dig_xy2);
+
+ PDEBUG(" %s : trimming_reg z1: %d z2: %d z3: %d z4: %d xyz1: %d\n",__func__,
+ client_data->device.dig_z1,
+ client_data->device.dig_z2,
+ client_data->device.dig_z3,
+ client_data->device.dig_z4,
+ client_data->device.dig_xyz1);
+
+ client_data->enable = 0;
+ /* now it's power on which is considered as resuming from suspend */
+ client_data->op_mode = BMM_VAL_NAME(SUSPEND_MODE);
+ client_data->odr = BMM_DEFAULT_ODR;
+ client_data->rept_xy = BMM_DEFAULT_REPETITION_XY;
+ client_data->rept_z = BMM_DEFAULT_REPETITION_Z;
+
+
+#if 0
+ err = bmm_restore_hw_cfg(client);
+#else
+
+ err = bmm_set_op_mode(client_data, BMM_VAL_NAME(SUSPEND_MODE));
+ if (err) {
+ PERR(" %s : fail to init h/w of %s",__func__, SENSOR_NAME);
+ err = -EIO;
+ goto exit_err_sysfs;
+ }
+#endif
+ printk(KERN_ALERT"%s ... Removed SUSPEND_MODE \n",__func__);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ client_data->early_suspend_handler.level =
+ EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ client_data->early_suspend_handler.suspend = bmm_early_suspend;
+ client_data->early_suspend_handler.resume = bmm_late_resume;
+ register_early_suspend(&client_data->early_suspend_handler);
+#endif
+
+ err = sensors_register(&bmm_device,client_data,bmm050_attr, "magnetic_sensor");
+ if (err < 0 )
+ {
+ pr_err("%s: could not register" "magnetic_sensor device(%d).\n", __func__, err);
+ goto exit_err_sysfs;
+ }
+
+ PNOTICE(" %s : sensor %s probed successfully \n",__func__, SENSOR_NAME);
+
+ PDEBUG(" %s : i2c_client: %p client_data: %p i2c_device: %p input: %p\n",__func__,
+ client, client_data, &client->dev, client_data->input);
+
+ return 0;
+
+exit_err_sysfs:
+ if (err)
+ bmm_input_destroy(client_data);
+
+exit_err_clean:
+ if (err) {
+ if (client_data != NULL) {
+#ifdef CONFIG_BMM_USE_PLATFORM_DATA
+ if (NULL != client_data->bst_pd) {
+ kfree(client_data->bst_pd);
+ client_data->bst_pd = NULL;
+ }
+#endif
+ kfree(client_data);
+ client_data = NULL;
+ }
+
+ bmm_client = NULL;
+ }
+
+ return err;
+}
+
+static int bmm_pre_suspend(struct i2c_client *client)
+{
+ int err = 0;
+ struct bmm_client_data *client_data =
+ (struct bmm_client_data *)i2c_get_clientdata(client);
+ PDEBUG("function entrance");
+
+ mutex_lock(&client_data->mutex_enable);
+ if (client_data->enable) {
+ cancel_delayed_work_sync(&client_data->work);
+ PDEBUG("cancel work");
+ }
+ mutex_unlock(&client_data->mutex_enable);
+
+ return err;
+}
+
+static int bmm_post_resume(struct i2c_client *client)
+{
+ int err = 0;
+ struct bmm_client_data *client_data =
+ (struct bmm_client_data *)i2c_get_clientdata(client);
+
+ 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);
+
+ return err;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void bmm_early_suspend(struct early_suspend *handler)
+{
+ int err = 0;
+ struct bmm_client_data *client_data =
+ (struct bmm_client_data *)container_of(handler,
+ struct bmm_client_data, early_suspend_handler);
+ struct i2c_client *client = client_data->client;
+ u8 power_mode;
+ PDEBUG("function entrance");
+
+ mutex_lock(&client_data->mutex_power_mode);
+ BMM_CALL_API(get_powermode)(&power_mode);
+ if (power_mode) {
+ err = bmm_pre_suspend(client);
+ err = bmm_set_op_mode(client_data, BMM_VAL_NAME(SUSPEND_MODE));
+ }
+ mutex_unlock(&client_data->mutex_power_mode);
+
+}
+
+static void bmm_late_resume(struct early_suspend *handler)
+{
+ int err = 0;
+ struct bmm_client_data *client_data =
+ (struct bmm_client_data *)container_of(handler,
+ struct bmm_client_data, early_suspend_handler);
+ struct i2c_client *client = client_data->client;
+ PDEBUG("function entrance");
+
+ mutex_lock(&client_data->mutex_power_mode);
+
+ err = bmm_restore_hw_cfg(client);
+ /* post resume operation */
+ bmm_post_resume(client);
+
+ mutex_unlock(&client_data->mutex_power_mode);
+}
+#else
+static int bmm_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ int err = 0;
+ struct bmm_client_data *client_data =
+ (struct bmm_client_data *)i2c_get_clientdata(client);
+ u8 power_mode;
+
+ PDEBUG("function entrance");
+
+ mutex_lock(&client_data->mutex_power_mode);
+ BMM_CALL_API(get_powermode)(&power_mode);
+ if (power_mode) {
+ err = bmm_pre_suspend(client);
+ err = bmm_set_op_mode(client_data, BMM_VAL_NAME(SUSPEND_MODE));
+ }
+ mutex_unlock(&client_data->mutex_power_mode);
+
+ return err;
+}
+
+static int bmm_resume(struct i2c_client *client)
+{
+ int err = 0;
+ struct bmm_client_data *client_data =
+ (struct bmm_client_data *)i2c_get_clientdata(client);
+
+ PDEBUG("function entrance");
+
+ mutex_lock(&client_data->mutex_power_mode);
+ err = bmm_restore_hw_cfg(client);
+ /* post resume operation */
+ bmm_post_resume(client);
+
+ mutex_unlock(&client_data->mutex_power_mode);
+
+ return err;
+}
+#endif
+
+static int bmm_remove(struct i2c_client *client)
+{
+ int err = 0;
+ struct bmm_client_data *client_data =
+ (struct bmm_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);
+ if (BMM_VAL_NAME(NORMAL_MODE) == client_data->op_mode) {
+ cancel_delayed_work_sync(&client_data->work);
+ PDEBUG("cancel work");
+ }
+ mutex_unlock(&client_data->mutex_op_mode);
+
+ err = bmm_set_op_mode(client_data, BMM_VAL_NAME(SUSPEND_MODE));
+ mdelay(BMM_I2C_WRITE_DELAY_TIME);
+
+ sensors_unregister(bmm_device, bmm050_attr);
+
+ sysfs_remove_group(&client_data->input->dev.kobj,
+ &bmm_attribute_group);
+ bmm_input_destroy(client_data);
+
+#ifdef CONFIG_BMM_USE_PLATFORM_DATA
+ if (NULL != client_data->bst_pd) {
+ kfree(client_data->bst_pd);
+ client_data->bst_pd = NULL;
+ }
+#endif
+ kfree(client_data);
+
+ bmm_client = NULL;
+ }
+
+ return err;
+}
+
+static const struct i2c_device_id bmm_id[] = {
+ {SENSOR_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, bmm_id);
+
+static struct i2c_driver bmm_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+ },
+ .class = I2C_CLASS_HWMON,
+ .id_table = bmm_id,
+ .probe = bmm_probe,
+ .remove = bmm_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = bmm_suspend,
+ .resume = bmm_resume,
+#endif
+};
+
+static int __init BMM_init(void)
+{
+ return i2c_add_driver(&bmm_driver);
+}
+
+static void __exit BMM_exit(void)
+{
+ i2c_del_driver(&bmm_driver);
+}
+
+MODULE_AUTHOR("Zhengguang.Guo <Zhengguang.Guo@bosch-sensortec.com>");
+MODULE_DESCRIPTION("driver for " SENSOR_NAME);
+MODULE_LICENSE("GPL");
+
+module_init(BMM_init);
+module_exit(BMM_exit);
diff --git a/drivers/sensor/bs_log.h b/drivers/sensor/bs_log.h
new file mode 100644
index 00000000..ec3286aa
--- /dev/null
+++ b/drivers/sensor/bs_log.h
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2013 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
+ *
+ * @date Apr 28th, 2011
+ * @version v1.0
+ * @brief Log API for Bosch MEMS Sensor drivers
+ */
+
+#ifndef __BS_LOG_H
+#define __BS_LOG_H
+
+#include <linux/kernel.h>
+
+#define LOG_LEVEL_E 3
+#define LOG_LEVEL_N 5
+#define LOG_LEVEL_I 6
+#define LOG_LEVEL_D 7
+
+#ifndef LOG_LEVEL
+#define LOG_LEVEL LOG_LEVEL_I
+#endif
+
+#ifndef MODULE_TAG
+#define MODULE_TAG "<>"
+#endif
+
+#if (LOG_LEVEL >= LOG_LEVEL_E)
+#define PERR(fmt, args...) printk(KERN_ERR\
+ "\n" "[E]" KERN_ERR MODULE_TAG "<%s><%d>" fmt "\n",\
+ __func__, __LINE__, ##args)
+#else
+#define PERR(fmt, args...)
+#endif
+
+#if (LOG_LEVEL >= LOG_LEVEL_N)
+#define PNOTICE(fmt, args...) printk(KERN_NOTICE\
+ "\n" "[N]" KERN_NOTICE MODULE_TAG "<%s><%d>" fmt "\n",\
+ __func__, __LINE__, ##args)
+#else
+#define PNOTICE(fmt, args...)
+#endif
+
+#if (LOG_LEVEL >= LOG_LEVEL_I)
+#define PINFO(fmt, args...) printk(KERN_INFO\
+ "\n" "[I]" KERN_INFO MODULE_TAG "<%s><%d>" fmt "\n",\
+ __func__, __LINE__, ##args)
+#else
+#define PINFO(fmt, args...)
+#endif
+
+#if (LOG_LEVEL >= LOG_LEVEL_D)
+#define PDEBUG(fmt, args...) printk(KERN_DEBUG\
+ "\n" "[D]" KERN_DEBUG MODULE_TAG "<%s><%d>" fmt "\n",\
+ __func__, __LINE__, ##args)
+#else
+#define PDEBUG(fmt, args...)
+#endif
+
+#endif
diff --git a/drivers/sensor/bst_sensor_common.c b/drivers/sensor/bst_sensor_common.c
new file mode 100644
index 00000000..503b6239
--- /dev/null
+++ b/drivers/sensor/bst_sensor_common.c
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2013 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
+ *
+ * @date Sep 19th, 2012
+ * @version v1.0
+ * @brief Common APIs for Bosch MEMS sensor drivers
+ */
+
+#include <linux/bst_sensor_common.h>
+
+#define MAX_AXIS_REMAP_TAB_SZ 8 /*P0~P7*/
+static const struct bosch_sensor_axis_remap
+bst_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 */
+};
+
+
+void bst_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));
+}
+EXPORT_SYMBOL(bst_remap_sensor_data);
+
+
+void bst_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;
+
+ bst_remap_sensor_data(data, &bst_axis_remap_tab_dft[place]);
+}
+EXPORT_SYMBOL(bst_remap_sensor_data_dft_tab);
+
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/sensor/gp2ap002a00f.c b/drivers/sensor/gp2ap002a00f.c
new file mode 100644
index 00000000..397a3451
--- /dev/null
+++ b/drivers/sensor/gp2ap002a00f.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright (C) 2011 Sony Ericsson Mobile Communications Inc.
+ *
+ * Author: Courtney Cavin <courtney.cavin@sonyericsson.com>
+ * Prepared for up-stream by: Oskar Andero <oskar.andero@sonyericsson.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/i2c.h>
+#include <linux/irq.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/gp2ap002a00f.h>
+#include <linux/sensors_core.h>
+
+static struct device *proximity_sensor_device = NULL;
+
+#define OFFSET_FILE_PATH "/efs/prox_cal"
+
+
+#define PROX_NONDETECT 0x2F
+#define PROX_DETECT 0x0C
+
+#define PROX_NONDETECT_MODE1 0x43
+#define PROX_DETECT_MODE1 0x28
+
+#define PROX_NONDETECT_MODE2 0x48
+#define PROX_DETECT_MODE2 0x42
+
+struct gp2a_data {
+ struct input_dev *input;
+ const struct gp2a_platform_data *pdata;
+ struct i2c_client *i2c_client;
+ int proximity_enabled;
+ int irq;
+ int value;
+
+ char cal_mode;
+
+};
+
+static int nondetect;
+static int detect;
+
+
+enum gp2a_addr {
+ GP2A_ADDR_PROX = 0x0,
+ GP2A_ADDR_GAIN = 0x1,
+ GP2A_ADDR_HYS = 0x2,
+ GP2A_ADDR_CYCLE = 0x3,
+ GP2A_ADDR_OPMOD = 0x4,
+ GP2A_ADDR_CON = 0x6
+};
+
+enum gp2a_controls {
+ /* Software Shutdown control: 0 = shutdown, 1 = normal operation */
+ GP2A_CTRL_SSD = 0x01
+};
+
+static int gp2a_report(struct gp2a_data *dt)
+{
+ int vo = gpio_get_value(dt->pdata->vout_gpio);
+
+ dt->value = vo;
+
+ input_report_switch(dt->input, SW_FRONT_PROXIMITY, vo);
+ input_sync(dt->input);
+
+ return 0;
+}
+
+static irqreturn_t gp2a_irq(int irq, void *handle)
+{
+ struct gp2a_data *dt = handle;
+
+ printk(KERN_EMERG"Proximity Interrupts ::%d\n",irq);
+
+ gp2a_report(dt);
+
+ return IRQ_HANDLED;
+}
+
+static int gp2a_enable(struct gp2a_data *dt)
+{
+ return i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_OPMOD,
+ GP2A_CTRL_SSD);
+}
+
+static int gp2a_disable(struct gp2a_data *dt)
+{
+ return i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_OPMOD,
+ 0x00);
+}
+
+
+/*Only One Read Only register, so word address need not be specified (from Data Sheet)*/
+static int gp2a_i2c_read(u8 reg, u8 *value,struct gp2a_data *gp2a_cal_data)
+{
+ int ret =0;
+ int count=0;
+ u8 buf[3];
+ struct i2c_msg msg[1];
+
+ buf[0] = reg;
+
+ /*first byte read(buf[0]) is dummy read*/
+ msg[0].addr = gp2a_cal_data->i2c_client->addr;
+ msg[0].flags = I2C_M_RD;
+ msg[0].len = 2;
+ msg[0].buf = buf;
+ count = i2c_transfer(gp2a_cal_data->i2c_client->adapter, msg, 1);
+
+ if(count < 0)
+ {
+ ret =-1;
+ }
+ else
+ {
+ *value = buf[0] << 8 | buf[1];
+ }
+
+ return ret;
+}
+
+static int gp2a_i2c_write( u8 reg, u8 *value,struct gp2a_data *gp2a_cal_data)
+{
+ int ret =0;
+ int count=0;
+ struct i2c_msg msg[1];
+ u8 data[2];
+
+ printk(KERN_INFO "[GP2A] %s : start \n", __func__);
+
+ if( (gp2a_cal_data->i2c_client == NULL) || (!gp2a_cal_data->i2c_client->adapter) ){
+ return -ENODEV;
+ }
+
+ data[0] = reg;
+ data[1] = *value;
+
+ msg[0].addr = gp2a_cal_data->i2c_client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 2;
+ msg[0].buf = data;
+ count = i2c_transfer(gp2a_cal_data->i2c_client->adapter,msg,1);
+
+ if(count < 0)
+ ret =-1;
+
+
+ printk(KERN_INFO "[GP2A] %s : stop \n", __func__);
+
+ return ret;
+}
+
+static ssize_t proximity_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gp2a_data *dt = dev_get_drvdata(dev);
+
+ pr_info("%s, %d \n", __func__, __LINE__);
+ return snprintf(buf, PAGE_SIZE, "%d\n", dt->proximity_enabled);
+}
+
+static ssize_t proximity_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gp2a_data *dt = dev_get_drvdata(dev);
+
+ pr_info("%s, %d \n", __func__, __LINE__);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", dt->value);
+}
+
+static ssize_t proximity_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct gp2a_data *dt = dev_get_drvdata(dev);
+
+ unsigned long value = 0;
+ int err = 0;
+
+ err = strict_strtoul(buf, 10, &value);
+ if (err)
+ pr_err("%s, kstrtoint failed.", __func__);
+
+ if (value != 0 && value != 1)
+ return count;
+
+ printk(KERN_ALERT"%s :: Request for State(%d->%d)\n",__func__,dt->proximity_enabled,value);
+
+ //check for multiple times disable and enable sensor
+ if (dt->proximity_enabled && !value) { /* Prox power off */
+
+ disable_irq(dt->irq);
+
+ gp2a_disable(dt);
+
+ if (dt->pdata->hw_pwr)
+ dt->pdata->hw_pwr(false);
+
+ dt->proximity_enabled = 0;
+ }
+ if (!dt->proximity_enabled && value) { /* prox power on */
+
+ if (dt->pdata->hw_pwr)
+ dt->pdata->hw_pwr(true);
+
+ msleep(20);
+
+ gp2a_enable(dt);
+
+ enable_irq(dt->irq);
+ dt->proximity_enabled = 1;
+
+ gp2a_report(dt);
+ }
+
+ return count;
+}
+
+static int __init gp2a_initialize(struct gp2a_data *dt)
+{
+ int error;
+
+ error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_GAIN,
+ 0x08);
+ if (error < 0)
+ return error;
+
+ error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_HYS,
+ 0xc2);
+ if (error < 0)
+ return error;
+
+ error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_CYCLE,
+ 0x04);
+ if (error < 0)
+ return error;
+
+ error = gp2a_disable(dt);
+
+ return error;
+}
+
+static int gp2a_prox_offset(unsigned char vout,struct gp2a_data *gp2a_cal_data)
+{
+ u8 reg_value;
+ int ret=0;
+
+ printk(KERN_INFO "[GP2A] %s called\n", __func__);
+
+ /* Write HYS Register */
+ if(!vout)
+ reg_value = nondetect;
+ else
+ reg_value = detect;
+
+ if((ret=gp2a_i2c_write(GP2A_ADDR_HYS/*0x02*/,&reg_value,gp2a_cal_data))<0)
+ printk(KERN_INFO "[GP2A]gp2a_i2c_write 2 failed\n", __func__);
+
+ return ret;
+}
+
+static int gp2a_prox_cal_mode(char mode,struct gp2a_data *gp2a_cal_data)
+{
+ int ret=0;
+ u8 reg_value;
+
+ printk(KERN_INFO "[GP2A] %s : start \n", __func__);
+
+ if (mode == 1)
+ {
+ nondetect = PROX_NONDETECT_MODE1;
+ detect = PROX_DETECT_MODE1;
+ }
+ else if (mode == 2)
+ {
+ nondetect = PROX_NONDETECT_MODE2;
+ detect = PROX_DETECT_MODE2;
+ }
+ else
+ {
+ nondetect = PROX_NONDETECT;
+ detect = PROX_DETECT;
+ }
+
+
+ reg_value = 0x08;
+ if((ret=gp2a_i2c_write(GP2A_ADDR_GAIN/*0x01*/,&reg_value,gp2a_cal_data))<0)
+ printk(KERN_INFO "[GP2A]gp2a_i2c_write 1 failed\n", __func__);
+
+ gp2a_prox_offset(0,gp2a_cal_data);
+
+ reg_value = 0x04;
+ if((ret=gp2a_i2c_write(GP2A_ADDR_CYCLE/*0x03*/,&reg_value,gp2a_cal_data))<0)
+ printk(KERN_INFO "[GP2A]gp2a_i2c_write 2 failed\n", __func__);
+
+ reg_value = 0x03;
+ if((ret=gp2a_i2c_write(GP2A_ADDR_OPMOD,&reg_value,gp2a_cal_data))<0)
+ printk(KERN_INFO "[GP2A]gp2a_i2c_write 3 failed\n", __func__);
+
+ reg_value = 0x00;
+ if((ret=gp2a_i2c_write(GP2A_ADDR_CON,&reg_value,gp2a_cal_data))<0)
+ printk(KERN_INFO "[GP2A]gp2a_i2c_write 4 failed\n", __func__);
+
+ printk(KERN_INFO "[GP2A] %s : stop \n", __func__);
+
+ return ret;
+
+}
+
+static int gp2a_cal_mode_read_file(char *mode,struct gp2a_data *gp2a_cal_data)
+{
+ int err = 0;
+ mm_segment_t old_fs;
+ struct file *cal_mode_filp = NULL;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_mode_filp = filp_open(OFFSET_FILE_PATH, O_RDONLY, 0666);
+ if (IS_ERR(cal_mode_filp)) {
+ printk(KERN_INFO "[GP2A] %s: no cal_mode file\n", __func__);
+ err = PTR_ERR(cal_mode_filp);
+ if (err != -ENOENT)
+ pr_err("[GP2A] %s: Can't open cal_mode file\n", __func__);
+ set_fs(old_fs);
+ return err;
+ }
+ err = cal_mode_filp->f_op->read(cal_mode_filp, mode, sizeof(u8), &cal_mode_filp->f_pos);
+
+ if (err != sizeof(u8)) {
+ pr_err("%s: Can't read the cal_mode from file\n", __func__);
+ filp_close(cal_mode_filp, current->files);
+ set_fs(old_fs);
+ return -EIO;
+ }
+
+ filp_close(cal_mode_filp, current->files);
+ set_fs(old_fs);
+
+ return err;
+}
+
+static int gp2a_cal_mode_save_file(char mode,struct gp2a_data *gp2a_cal_data)
+{
+ struct file *cal_mode_filp = NULL;
+ int err = 0;
+ mm_segment_t old_fs;
+
+ printk(KERN_INFO "[GP2A] %s : start \n", __func__);
+
+ gp2a_prox_cal_mode(mode,gp2a_cal_data);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_mode_filp = filp_open(OFFSET_FILE_PATH, O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666);
+ if (IS_ERR(cal_mode_filp))
+ {
+ pr_err("%s: Can't open cal_mode file\n", __func__);
+ set_fs(old_fs);
+ err = PTR_ERR(cal_mode_filp);
+ pr_err("%s: err = %d\n", __func__, err);
+ return err;
+ }
+
+ err = cal_mode_filp->f_op->write(cal_mode_filp, (char *)&mode, sizeof(u8), &cal_mode_filp->f_pos);
+ if (err != sizeof(u8)) {
+ pr_err("%s: Can't read the cal_mode from file\n", __func__);
+ err = -EIO;
+ }
+ printk(KERN_INFO "[GP2A] %s : stop \n", __func__);
+
+ filp_close(cal_mode_filp, current->files);
+ set_fs(old_fs);
+
+ return err;
+}
+static ssize_t proximity_cal_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int result = 0;
+
+ struct gp2a_data *gp2a_cal_data=dev_get_drvdata(dev);
+
+
+ result = gp2a_cal_data->cal_mode;
+ printk(KERN_INFO "[GP2A] prox_cal_read = %d\n", result);
+
+ return sprintf(buf, "%d\n", result);
+}
+
+static ssize_t proximity_cal_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct gp2a_data *gp2a_cal_data=dev_get_drvdata(dev);
+
+ if (sysfs_streq(buf, "1"))
+ gp2a_cal_data->cal_mode = 1;
+ else if (sysfs_streq(buf, "2"))
+ gp2a_cal_data->cal_mode = 2;
+ else if (sysfs_streq(buf, "0"))
+ gp2a_cal_data->cal_mode = 0;
+ else {
+ pr_err("[GP2A] %s: invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ printk(KERN_INFO "[GP2A] prox_cal_write =%d\n", gp2a_cal_data->cal_mode);
+
+ gp2a_cal_mode_save_file(gp2a_cal_data->cal_mode,gp2a_cal_data);
+
+ return size;
+}
+
+
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
+ proximity_enable_show, proximity_enable_store);
+
+static DEVICE_ATTR(value, S_IRUGO | S_IWUSR | S_IWGRP,
+ proximity_value_show, NULL);
+
+static DEVICE_ATTR(prox_cal, S_IRUGO | S_IWUSR |S_IWGRP|S_IWOTH, proximity_cal_show, proximity_cal_store);
+
+static struct attribute *gp2a_attrs[] = {
+ &dev_attr_enable.attr,
+ NULL,
+};
+
+static struct attribute_group gp2a_attribute_group = {
+ .attrs = gp2a_attrs,
+};
+
+static struct device_attribute *proximity_sensor_attr[] = {
+ &dev_attr_value,
+ &dev_attr_enable,
+
+ &dev_attr_prox_cal,
+
+ NULL,
+ };
+
+static int __init gp2a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ const struct gp2a_platform_data *pdata = client->dev.platform_data;
+ struct gp2a_data *dt;
+ int error;
+
+ if (!pdata)
+ return -EINVAL;
+
+ if (pdata->hw_setup) {
+ error = pdata->hw_setup(client);
+ if (error < 0)
+ return error;
+ }
+
+ error = gpio_request_one(pdata->vout_gpio, GPIOF_IN, GP2A_I2C_NAME);
+ if (error)
+ goto err_hw_shutdown;
+
+ dt = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL);
+ if (!dt) {
+ error = -ENOMEM;
+ goto err_free_gpio;
+ }
+
+ dt->pdata = pdata;
+ dt->i2c_client = client;
+
+ error = gp2a_initialize(dt);
+ if (error < 0)
+ goto err_free_mem;
+
+ dt->input = input_allocate_device();
+ if (!dt->input) {
+ error = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ input_set_drvdata(dt->input, dt);
+
+// dt->input->open = gp2a_device_open;
+// dt->input->close = gp2a_device_close;
+ dt->input->name = GP2A_I2C_NAME;
+ dt->input->id.bustype = BUS_I2C;
+ dt->input->dev.parent = &client->dev;
+ dt->proximity_enabled = 0;
+ dt->irq = client->irq;
+ dt->value = 0;
+
+ input_set_capability(dt->input, EV_SW, SW_FRONT_PROXIMITY);
+
+ error = request_threaded_irq(client->irq, NULL, gp2a_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT | IRQF_NO_SUSPEND ,
+ GP2A_I2C_NAME, dt);
+ if (error) {
+ dev_err(&client->dev, "irq request failed\n");
+ goto err_free_input_dev;
+ }
+
+ error = input_register_device(dt->input);
+ if (error) {
+ dev_err(&client->dev, "device registration failed\n");
+ goto err_free_irq;
+ }
+
+ error = sysfs_create_group(&dt->input->dev.kobj, &gp2a_attribute_group);
+ if (error) {
+ dev_err(&client->dev, "sysfs create failed\n");
+ goto err_unregister_input;
+ }
+
+ device_init_wakeup(&client->dev, pdata->wakeup);
+ i2c_set_clientdata(client, dt);
+ dev_set_drvdata(&client->dev, dt);
+
+ error = sensors_register(&proximity_sensor_device, dt,proximity_sensor_attr, "proximity_sensor");
+
+ if (error < 0)
+ {
+ pr_err("%s: could not register""proximity sensor device(%d).\n",__func__, error);
+ goto err_unregister_input;
+ }
+ disable_irq(client->irq);
+
+ if (dt->pdata->hw_pwr)
+ {
+ dt->pdata->hw_pwr(false);
+ printk(KERN_ALERT"%s :: chip power down\n",__func__);
+ }
+ return 0;
+
+err_unregister_input:
+ input_unregister_device(dt->input);
+err_free_irq:
+ free_irq(client->irq, dt);
+err_free_input_dev:
+ input_free_device(dt->input);
+err_free_mem:
+ kfree(dt);
+err_free_gpio:
+ gpio_free(pdata->vout_gpio);
+err_hw_shutdown:
+ if (pdata->hw_shutdown)
+ pdata->hw_shutdown(client);
+ if (pdata->hw_pwr)
+ pdata->hw_pwr(false);
+ return error;
+}
+
+static int __exit gp2a_remove(struct i2c_client *client)
+{
+ struct gp2a_data *dt = i2c_get_clientdata(client);
+ const struct gp2a_platform_data *pdata = dt->pdata;
+
+ device_init_wakeup(&client->dev, false);
+
+ free_irq(client->irq, dt);
+
+ sensors_unregister(proximity_sensor_device, proximity_sensor_attr);
+ input_unregister_device(dt->input);
+ kfree(dt);
+
+ gpio_free(pdata->vout_gpio);
+
+ if (pdata->hw_shutdown)
+ pdata->hw_shutdown(client);
+
+ if (pdata->hw_pwr)
+ pdata->hw_pwr(false);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int gp2a_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct gp2a_data *dt = i2c_get_clientdata(client);
+ int retval = 0;
+ printk(KERN_ALERT"%s\n",__func__);
+ if (device_may_wakeup(&client->dev)) {
+ enable_irq_wake(client->irq);
+ } else {
+ mutex_lock(&dt->input->mutex);
+ if (dt->input->users)
+ retval = gp2a_disable(dt);
+ mutex_unlock(&dt->input->mutex);
+ }
+
+ return retval;
+}
+
+static int gp2a_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct gp2a_data *dt = i2c_get_clientdata(client);
+ int retval = 0;
+ printk(KERN_ALERT"%s\n",__func__);
+ if (device_may_wakeup(&client->dev)) {
+ disable_irq_wake(client->irq);
+ } else {
+ mutex_lock(&dt->input->mutex);
+ if (dt->input->users)
+ retval = gp2a_enable(dt);
+ mutex_unlock(&dt->input->mutex);
+ }
+
+ return retval;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(gp2a_pm, gp2a_suspend, gp2a_resume);
+
+static const struct i2c_device_id gp2a_i2c_id[] = {
+ { GP2A_I2C_NAME, 0 },
+ { }
+};
+
+static struct i2c_driver gp2a_i2c_driver = {
+ .driver = {
+ .name = GP2A_I2C_NAME,
+ .owner = THIS_MODULE,
+ .pm = &gp2a_pm,
+ },
+ .probe = gp2a_probe,
+ .remove = gp2a_remove,
+ .id_table = gp2a_i2c_id,
+};
+
+module_i2c_driver(gp2a_i2c_driver);
+
+MODULE_AUTHOR("Courtney Cavin <courtney.cavin@sonyericsson.com>");
+MODULE_DESCRIPTION("Sharp GP2AP002A00F I2C Proximity/Opto sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/sensor/k2hh.c b/drivers/sensor/k2hh.c
new file mode 100644
index 00000000..aa0831cc
--- /dev/null
+++ b/drivers/sensor/k2hh.c
@@ -0,0 +1,1523 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics. 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 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/of_gpio.h>
+#include <linux/wakelock.h>
+#include <linux/regulator/consumer.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/sensors_core.h>
+
+
+#define I2C_M_WR 0 /* for i2c Write */
+#define I2c_M_RD 1 /* for i2c Read */
+#define READ_DATA_LENTH 6
+
+#define VENDOR_NAME "STM"
+#define MODEL_NAME "K2HH"
+#define MODULE_NAME "accelerometer_sensor"
+
+#define CALIBRATION_FILE_PATH "/efs/accel_calibration_data"
+#define CALIBRATION_DATA_AMOUNT 20
+#define MAX_ACCEL_1G 16384
+
+#define K2HH_DEFAULT_DELAY 200000000LL
+
+#define CHIP_ID_RETRIES 3
+#define ACCEL_LOG_TIME 15 /* 15 sec */
+
+#define K2HH_MODE_SUSPEND 0
+#define K2HH_MODE_NORMAL 1
+
+#define SENSITIVITY_2G 61
+#define SENSITIVITY_4G 122
+#define SENSITIVITY_8G 244
+
+#define K2HH_RANGE_2G 0
+#define K2HH_RANGE_4G 1
+#define K2HH_RANGE_8G 2
+
+#define WHOAMI_REG 0x0F
+#define AXISDATA_REG 0x28
+
+#define CTRL1_REG 0x20
+#define CTRL2_REG 0x21
+#define CTRL3_REG 0x22
+#define CTRL4_REG 0x23
+#define CTRL5_REG 0x24
+#define CTRL6_REG 0x25
+#define CTRL7_REG 0x26
+#define STATUS_REG 0x27
+
+/* CTRL1 */
+#define CTRL1_HR_DISABLE 0x00
+#define CTRL1_HR_ENABLE 0x80
+#define CTRL1_HR_MASK 0x80
+#define CTRL1_BDU_ENABLE 0x08
+#define CTRL1_BDU_MASK 0x08
+
+/* CTRL2 */
+#define CTRL2_IG1_INT1 0x08
+
+/* CTRL3 */
+#define CTRL3_IG1_INT1 0x08
+
+/* CTRL7 */
+#define CTRL7_LIR2 0x08
+#define CTRL7_LIR1 0x04
+
+#define ACC_PM_OFF 0x00
+#define ACC_ENABLE_ALL_AXES 0x07
+
+#define INT_CFG1_REG 0x30
+#define INT_SRC1_REG 0x31
+#define K2HH_CHIP_ID 0x41
+
+#define K2HH_ACC_FS_MASK 0x30
+#define K2HH_ACC_ODR_MASK 0x70
+#define K2HH_ACC_AXES_MASK 0x07
+
+#define SELF_TEST_2G_MAX_LSB 24576
+#define SELF_TEST_2G_MIN_LSB 1146
+
+#define K2HH_ACC_FS_2G 0x00
+#define K2HH_ACC_FS_4G 0x20
+#define K2HH_ACC_FS_8G 0x30
+
+#define INT_THSX1_REG 0x32
+#define INT_THSY1_REG 0x33
+#define INT_THSZ1_REG 0x34
+
+#define DYNAMIC_THRESHOLD 5000
+
+enum {
+ OFF = 0,
+ ON = 1
+};
+
+struct k2hh_v {
+ union {
+ s16 v[3];
+ struct {
+ s16 x;
+ s16 y;
+ s16 z;
+ };
+ };
+};
+
+struct k2hh_p {
+ struct wake_lock reactive_wake_lock;
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct delayed_work irq_work;
+ struct device *factory_device;
+ struct k2hh_v accdata;
+ struct k2hh_v caldata;
+ struct mutex mode_mutex;
+ struct hrtimer accel_timer;
+ struct workqueue_struct *accel_wq;
+ struct work_struct work;
+ struct regulator *vdd;
+ //struct regulator *vio;
+ ktime_t poll_delay;
+ atomic_t enable;
+
+ int recog_flag;
+ int irq1;
+ int irq_state;
+ int acc_int1;
+ int sda_gpio;
+ int scl_gpio;
+ int time_count;
+
+ u8 axis_map_x;
+ u8 axis_map_y;
+ u8 axis_map_z;
+
+ u8 negate_x;
+ u8 negate_y;
+ u8 negate_z;
+};
+
+#define ACC_ODR10 0x10 /* 10Hz output data rate */
+#define ACC_ODR50 0x20 /* 50Hz output data rate */
+#define ACC_ODR100 0x30 /* 100Hz output data rate */
+#define ACC_ODR200 0x40 /* 200Hz output data rate */
+#define ACC_ODR400 0x50 /* 400Hz output data rate */
+#define ACC_ODR800 0x60 /* 800Hz output data rate */
+#define ACC_ODR_MASK 0X70
+
+struct k2hh_acc_odr {
+ unsigned int cutoff_ms;
+ unsigned int mask;
+};
+
+#define OUTPUT_ALWAYS_ANTI_ALIASED
+
+const struct k2hh_acc_odr k2hh_acc_odr_table[] = {
+ { 2, ACC_ODR800},
+ { 3, ACC_ODR400},
+ { 5, ACC_ODR200},
+ { 10, ACC_ODR100},
+#ifndef OUTPUT_ALWAYS_ANTI_ALIASED
+ { 20, ACC_ODR50},
+ {100, ACC_ODR10},
+#endif
+};
+
+static int k2hh_open_calibration(struct k2hh_p *);
+static int k2hh_regulator_onoff(struct k2hh_p *data, bool onoff);
+#if 0
+static int k2hh_i2c_recovery(struct k2hh_p *data)
+{
+ int ret = 0;
+ struct gpiomux_setting old_config[2];
+ struct gpiomux_setting recovery_config = {
+ .func = GPIOMUX_FUNC_3,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_IN,
+ };
+
+ if (data->sda_gpio < 0 || data->scl_gpio < 0) {
+ pr_err("[SENSOR]: %s - no sda, scl gpio\n", __func__);
+ return -EINVAL;
+ }
+
+ pr_err("[SENSOR] ################# %s #################\n", __func__);
+
+ /*If LDO's are disabled then enable, Fallback LDO off scenario*/
+ do {
+ if( 0 == regulator_is_enabled(data->vdd) ) {
+ ret = regulator_enable(data->vdd);
+ if (ret){
+ pr_err(KERN_ERR "%s: vdd enable failed (%d)\n",__func__, ret);
+ break;
+ }
+ ret++;
+ }
+ if( 0 == regulator_is_enabled(data->vio) ) {
+ ret = regulator_enable(data->vio);
+ if (ret){
+ pr_err(KERN_ERR "%s: vio enable failed (%d)\n",__func__, ret);
+ break;
+ }
+ ret++;
+ }
+ if(ret)
+ msleep(30);
+ }while(0);
+
+ if(ret){
+ pr_err("RECOVERY called as one of regulator was off:****\n Regulator \
+ on/recovery complete****\n ");
+ }
+
+
+ ret = msm_gpiomux_write(data->sda_gpio, GPIOMUX_ACTIVE,
+ &recovery_config, &old_config[0]);
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s sda_gpio have no active setting %d\n",
+ __func__, ret);
+ goto exit;
+ }
+
+ ret = msm_gpiomux_write(data->scl_gpio, GPIOMUX_ACTIVE,
+ &recovery_config, &old_config[1]);
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s scl_gpio have no active setting %d\n",
+ __func__, ret);
+ goto exit;
+ }
+
+ ret = gpio_request(data->sda_gpio, "SENSOR_SDA");
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - gpio %d request failed (%d)\n",
+ __func__, data->sda_gpio, ret);
+ goto exit;
+ }
+
+ ret = gpio_request(data->scl_gpio, "SENSOR_SCL");
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - gpio %d request failed (%d)\n",
+ __func__, data->scl_gpio, ret);
+ gpio_free(data->scl_gpio);
+ goto exit;
+ }
+
+ ret = gpio_direction_input(data->sda_gpio);
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - failed to set gpio %d as output (%d)\n",
+ __func__, data->sda_gpio, ret);
+ goto exit_to_free;
+ }
+
+ ret = gpio_direction_input(data->scl_gpio);
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - failed to set gpio %d as output (%d)\n",
+ __func__, data->scl_gpio, ret);
+ goto exit_to_free;
+ }
+
+ /*Setting initial value after recovery*/
+ udelay(100);
+ gpio_set_value_cansleep(data->sda_gpio, 0);
+ gpio_set_value_cansleep(data->scl_gpio, 0);
+ udelay(100);
+ gpio_set_value_cansleep(data->sda_gpio, 1);
+ gpio_set_value_cansleep(data->scl_gpio, 1);
+
+
+exit_to_free:
+ gpio_free(data->sda_gpio);
+ gpio_free(data->scl_gpio);
+exit:
+ msm_gpiomux_write(data->sda_gpio, GPIOMUX_ACTIVE, &old_config[0], NULL);
+ msm_gpiomux_write(data->scl_gpio, GPIOMUX_ACTIVE, &old_config[1], NULL);
+
+ return ret;
+}
+#endif
+
+static int k2hh_i2c_read(struct k2hh_p *data,
+ unsigned char reg_addr, unsigned char *buf, unsigned int len)
+{
+ int ret, retries = 0;
+ struct i2c_msg msg[2];
+
+ msg[0].addr = data->client->addr;
+ msg[0].flags = I2C_M_WR;
+ msg[0].len = 1;
+ msg[0].buf = &reg_addr;
+
+ msg[1].addr = data->client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = len;
+ msg[1].buf = buf;
+
+ do {
+ ret = i2c_transfer(data->client->adapter, msg, 2);
+ if (ret >= 0)
+ break;
+ //else
+ // k2hh_i2c_recovery(data);
+ } while (retries++ < 2);
+
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - i2c read error %d\n", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int k2hh_i2c_write(struct k2hh_p *data,
+ unsigned char reg_addr, unsigned char buf)
+{
+ int ret, retries = 0;
+ struct i2c_msg msg;
+ unsigned char w_buf[2];
+
+ w_buf[0] = reg_addr;
+ w_buf[1] = buf;
+
+ msg.addr = data->client->addr;
+ msg.flags = I2C_M_WR;
+ msg.len = 2;
+ msg.buf = (char *)w_buf;
+
+ do {
+ ret = i2c_transfer(data->client->adapter, &msg, 1);
+ if (ret >= 0)
+ break;
+ //else
+ // k2hh_i2c_recovery(data);
+ } while (retries++ < 2);
+
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - i2c write error %d\n", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int k2hh_set_range(struct k2hh_p *data, unsigned char range)
+{
+ int ret = 0;
+ unsigned char temp, new_range, buf, mask;
+
+ switch (range) {
+ case K2HH_RANGE_2G:
+ new_range = K2HH_ACC_FS_2G;
+ break;
+ case K2HH_RANGE_4G:
+ new_range = K2HH_ACC_FS_4G;
+ break;
+ case K2HH_RANGE_8G:
+ new_range = K2HH_ACC_FS_8G;
+ break;
+ default:
+ new_range = K2HH_ACC_FS_2G;
+ break;
+ }
+
+ mask = K2HH_ACC_FS_MASK;
+ ret = k2hh_i2c_read(data, CTRL4_REG, &temp, 1);
+#ifndef OUTPUT_ALWAYS_ANTI_ALIASED
+ buf = (mask & new_range) | ((~mask) & temp);
+#else
+ buf = 0xCC;
+#endif
+ ret += k2hh_i2c_write(data, CTRL4_REG, buf);
+
+ return ret;
+}
+
+static int k2hh_set_odr(struct k2hh_p *data)
+{
+ int ret = 0, i;
+ unsigned char buf, new_odr, mask, temp;
+
+ /* Following, looks for the longest possible odr interval scrolling the
+ * odr_table vector from the end (shortest interval) backward (longest
+ * interval), to support the poll_interval requested by the system.
+ * It must be the longest interval lower then the poll interval.*/
+ for (i = ARRAY_SIZE(k2hh_acc_odr_table) - 1; i >= 0; i--) {
+ if ((k2hh_acc_odr_table[i].cutoff_ms <= \
+ ktime_to_ms(data->poll_delay)) || (i == 0))
+ break;
+ }
+
+ if (data->recog_flag == ON)
+ i = ARRAY_SIZE(k2hh_acc_odr_table) - 1;
+
+ new_odr = k2hh_acc_odr_table[i].mask;
+
+ mask = K2HH_ACC_ODR_MASK;
+ ret = k2hh_i2c_read(data, CTRL1_REG, &temp, 1);
+ buf = ((mask & new_odr) | ((~mask) & temp));
+ ret += k2hh_i2c_write(data, CTRL1_REG, buf);
+
+ pr_info("[SENSOR]: %s - change odr %d\n", __func__, i);
+ return ret;
+}
+
+static int k2hh_set_mode(struct k2hh_p *data, unsigned char mode)
+{
+ int ret = 0;
+ unsigned char buf, mask, temp;
+
+ mutex_lock(&data->mode_mutex);
+
+ switch (mode) {
+ case K2HH_MODE_NORMAL:
+ mask = K2HH_ACC_AXES_MASK;
+ ret = k2hh_i2c_read(data, CTRL1_REG, &temp, 1);
+ buf = ((mask & ACC_ENABLE_ALL_AXES) | ((~mask) & temp));
+ ret += k2hh_i2c_write(data, CTRL1_REG, buf);
+ k2hh_set_odr(data);
+ pr_info("[SENSOR]: %s - normal mode\n", __func__);
+ break;
+
+ case K2HH_MODE_SUSPEND:
+ if (data->recog_flag == ON)
+ break;
+
+ mask = K2HH_ACC_AXES_MASK | K2HH_ACC_ODR_MASK;
+ ret = k2hh_i2c_read(data, CTRL1_REG, &temp, 1);
+ buf = ((mask & ACC_PM_OFF) | ((~mask) & temp));
+ ret += k2hh_i2c_write(data, CTRL1_REG, buf);
+ pr_info("[SENSOR]: %s - suspend mode\n", __func__);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&data->mode_mutex);
+ return ret;
+}
+
+static int k2hh_read_accel_xyz(struct k2hh_p *data, struct k2hh_v *acc)
+{
+ int ret = 0;
+ struct k2hh_v rawdata;
+ unsigned char buf[READ_DATA_LENTH];
+
+ ret += k2hh_i2c_read(data, AXISDATA_REG, buf, READ_DATA_LENTH);
+
+ if (ret < 0)
+ goto exit;
+
+ rawdata.v[0] = ((s16) ((buf[1] << 8) | buf[0]));
+ rawdata.v[1] = ((s16) ((buf[3] << 8) | buf[2]));
+ rawdata.v[2] = ((s16) ((buf[5] << 8) | buf[4]));
+
+ acc->v[0] = ((data->negate_x) ? (-rawdata.v[data->axis_map_x])
+ : (rawdata.v[data->axis_map_x]));
+ acc->v[1] = ((data->negate_y) ? (-rawdata.v[data->axis_map_y])
+ : (rawdata.v[data->axis_map_y]));
+ acc->v[2] = ((data->negate_z) ? (-rawdata.v[data->axis_map_z])
+ : (rawdata.v[data->axis_map_z]));
+
+exit:
+ return ret;
+}
+
+static enum hrtimer_restart k2hh_timer_func(struct hrtimer *timer)
+{
+ struct k2hh_p *data = container_of(timer,
+ struct k2hh_p, accel_timer);
+
+ if (!work_pending(&data->work))
+ queue_work(data->accel_wq, &data->work);
+
+ hrtimer_forward_now(&data->accel_timer, data->poll_delay);
+
+ return HRTIMER_RESTART;
+}
+
+static void k2hh_work_func(struct work_struct *work)
+{
+ int ret;
+ struct k2hh_v acc;
+ struct k2hh_p *data = container_of(work, struct k2hh_p, work);
+
+ ret = k2hh_read_accel_xyz(data, &acc);
+ if (ret < 0)
+ goto exit;
+
+ data->accdata.x = acc.x - data->caldata.x;
+ data->accdata.y = acc.y - data->caldata.y;
+ data->accdata.z = acc.z - data->caldata.z;
+
+ input_report_rel(data->input, REL_X, data->accdata.x);
+ input_report_rel(data->input, REL_Y, data->accdata.y);
+ input_report_rel(data->input, REL_Z, data->accdata.z);
+ input_sync(data->input);
+
+exit:
+ if ((ktime_to_ns(data->poll_delay) * (int64_t)data->time_count)
+ >= ((int64_t)ACCEL_LOG_TIME * NSEC_PER_SEC)) {
+ pr_info("[SENSOR]: %s - x = %d, y = %d, z = %d (ra:%d)\n",
+ __func__, data->accdata.x, data->accdata.y,
+ data->accdata.z, data->recog_flag);
+ data->time_count = 0;
+ } else
+ data->time_count++;
+}
+
+static void k2hh_set_enable(struct k2hh_p *data, int enable)
+{
+ if (enable == ON) {
+ hrtimer_start(&data->accel_timer, data->poll_delay,
+ HRTIMER_MODE_REL);
+ } else {
+ hrtimer_cancel(&data->accel_timer);
+ cancel_work_sync(&data->work);
+ }
+}
+
+static ssize_t k2hh_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&data->enable));
+}
+
+static ssize_t k2hh_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ u8 enable;
+ int ret, pre_enable;
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ ret = kstrtou8(buf, 2, &enable);
+ if (ret) {
+ pr_err("[SENSOR]: %s - Invalid Argument\n", __func__);
+ return ret;
+ }
+
+ pr_info("[SENSOR]: %s - new_value = %u\n", __func__, enable);
+ pre_enable = atomic_read(&data->enable);
+
+ if (enable) {
+ if (pre_enable == OFF) {
+ k2hh_regulator_onoff(data, true);
+ k2hh_open_calibration(data);
+ k2hh_set_range(data, K2HH_RANGE_2G);
+
+ k2hh_set_mode(data, K2HH_MODE_NORMAL);
+ atomic_set(&data->enable, ON);
+ k2hh_set_enable(data, ON);
+ }
+ } else {
+ if (pre_enable == ON) {
+ atomic_set(&data->enable, OFF);
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+ k2hh_set_enable(data, OFF);
+ k2hh_regulator_onoff(data, false);
+ }
+ }
+
+ return size;
+}
+
+static ssize_t k2hh_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%lld\n",
+ ktime_to_ns(data->poll_delay));
+}
+
+static ssize_t k2hh_delay_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int ret;
+ int64_t delay;
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ ret = kstrtoll(buf, 10, &delay);
+ if (ret) {
+ pr_err("[SENSOR]: %s - Invalid Argument\n", __func__);
+ return ret;
+ }
+
+ data->poll_delay = ns_to_ktime(delay);
+ k2hh_set_odr(data);
+
+ if (atomic_read(&data->enable) == ON) {
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+ k2hh_set_mode(data, K2HH_MODE_NORMAL);
+ }
+
+ pr_info("[SENSOR]: %s - poll_delay = %lld\n", __func__, delay);
+ return size;
+}
+
+static DEVICE_ATTR(poll_delay, S_IRUGO | S_IWUSR | S_IWGRP,
+ k2hh_delay_show, k2hh_delay_store);
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP,
+ k2hh_enable_show, k2hh_enable_store);
+
+static struct attribute *k2hh_attributes[] = {
+ &dev_attr_poll_delay.attr,
+ &dev_attr_enable.attr,
+ NULL
+};
+
+static struct attribute_group k2hh_attribute_group = {
+ .attrs = k2hh_attributes
+};
+
+
+static ssize_t k2hh_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR_NAME);
+}
+
+static ssize_t k2hh_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", MODEL_NAME);
+}
+
+static int k2hh_open_calibration(struct k2hh_p *data)
+{
+ int ret = 0;
+ mm_segment_t old_fs;
+ struct file *cal_filp = NULL;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ set_fs(old_fs);
+ ret = PTR_ERR(cal_filp);
+
+ data->caldata.x = 0;
+ data->caldata.y = 0;
+ data->caldata.z = 0;
+
+ pr_info("[SENSOR]: %s - No Calibration\n", __func__);
+
+ return ret;
+ }
+
+ ret = cal_filp->f_op->read(cal_filp, (char *)&data->caldata.v,
+ 3 * sizeof(s16), &cal_filp->f_pos);
+ if (ret != 3 * sizeof(s16)) {
+ pr_err("[SENSOR] %s: - Can't read the cal data\n", __func__);
+ ret = -EIO;
+ }
+
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+
+ pr_info("[SENSOR]: open accel calibration %d, %d, %d\n",
+ data->caldata.x, data->caldata.y, data->caldata.z);
+
+ if ((data->caldata.x == 0) && (data->caldata.y == 0)
+ && (data->caldata.z == 0))
+ return -EIO;
+
+ return ret;
+}
+
+static int k2hh_do_calibrate(struct k2hh_p *data, int enable)
+{
+ int sum[3] = { 0, };
+ int ret = 0, cnt;
+ struct file *cal_filp = NULL;
+ struct k2hh_v acc;
+ mm_segment_t old_fs;
+
+ if (enable) {
+ data->caldata.x = 0;
+ data->caldata.y = 0;
+ data->caldata.z = 0;
+
+ if (atomic_read(&data->enable) == ON)
+ k2hh_set_enable(data, OFF);
+ else
+ k2hh_set_mode(data, K2HH_MODE_NORMAL);
+
+ msleep(300);
+
+ for (cnt = 0; cnt < CALIBRATION_DATA_AMOUNT; cnt++) {
+ k2hh_read_accel_xyz(data, &acc);
+ sum[0] += acc.x;
+ sum[1] += acc.y;
+ sum[2] += acc.z;
+ mdelay(10);
+ }
+
+ if (atomic_read(&data->enable) == ON)
+ k2hh_set_enable(data, ON);
+ else
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+
+ data->caldata.x = (sum[0] / CALIBRATION_DATA_AMOUNT);
+ data->caldata.y = (sum[1] / CALIBRATION_DATA_AMOUNT);
+ data->caldata.z = (sum[2] / CALIBRATION_DATA_AMOUNT);
+
+ if (data->caldata.z > 0)
+ data->caldata.z -= MAX_ACCEL_1G;
+ else if (data->caldata.z < 0)
+ data->caldata.z += MAX_ACCEL_1G;
+ } else {
+ data->caldata.x = 0;
+ data->caldata.y = 0;
+ data->caldata.z = 0;
+ }
+
+ pr_info("[SENSOR]: %s - do accel calibrate %d, %d, %d\n", __func__,
+ data->caldata.x, data->caldata.y, data->caldata.z);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(CALIBRATION_FILE_PATH,
+ O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ pr_err("[SENSOR]: %s - Can't open calibration file\n",
+ __func__);
+ set_fs(old_fs);
+ ret = PTR_ERR(cal_filp);
+ return ret;
+ }
+
+ ret = cal_filp->f_op->write(cal_filp, (char *)&data->caldata.v,
+ 3 * sizeof(s16), &cal_filp->f_pos);
+ if (ret != 3 * sizeof(s16)) {
+ pr_err("[SENSOR]: %s - Can't write the caldata to file\n",
+ __func__);
+ ret = -EIO;
+ }
+
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+
+ return ret;
+}
+
+static ssize_t k2hh_calibration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ ret = k2hh_open_calibration(data);
+ if (ret < 0)
+ pr_err("[SENSOR]: %s - calibration open failed(%d)\n",
+ __func__, ret);
+
+ pr_info("[SENSOR]: %s - cal data %d %d %d - ret : %d\n", __func__,
+ data->caldata.x, data->caldata.y, data->caldata.z, ret);
+
+ return snprintf(buf, PAGE_SIZE, "%d %d %d %d\n", ret, data->caldata.x,
+ data->caldata.y, data->caldata.z);
+}
+
+static ssize_t k2hh_calibration_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int ret;
+ int64_t dEnable;
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ ret = kstrtoll(buf, 10, &dEnable);
+ if (ret < 0)
+ return ret;
+
+ ret = k2hh_do_calibrate(data, (int)dEnable);
+ if (ret < 0)
+ pr_err("[SENSOR]: %s - accel calibrate failed\n", __func__);
+
+ return size;
+}
+
+static ssize_t k2hh_raw_data_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct k2hh_v acc;
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ if (atomic_read(&data->enable) == OFF) {
+ k2hh_set_mode(data, K2HH_MODE_NORMAL);
+ msleep(20);
+ k2hh_read_accel_xyz(data, &acc);
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+
+ acc.x = acc.x - data->caldata.x;
+ acc.y = acc.y - data->caldata.y;
+ acc.z = acc.z - data->caldata.z;
+ } else {
+ acc = data->accdata;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
+ acc.x, acc.y, acc.z);
+}
+
+static ssize_t k2hh_reactive_alert_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ unsigned char threshx, threshy, threshz;
+ int enable = OFF, factory_mode = OFF;
+ struct k2hh_v acc;
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ if (sysfs_streq(buf, "0")) {
+ enable = OFF;
+ factory_mode = OFF;
+ pr_info("[SENSOR]: %s - disable\n", __func__);
+ } else if (sysfs_streq(buf, "1")) {
+ enable = ON;
+ factory_mode = OFF;
+ pr_info("[SENSOR]: %s - enable\n", __func__);
+ } else if (sysfs_streq(buf, "2")) {
+ enable = ON;
+ factory_mode = ON;
+ pr_info("[SENSOR]: %s - factory mode\n", __func__);
+ } else {
+ pr_err("[SENSOR]: %s - invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ if ((enable == ON) && (data->recog_flag == OFF)) {
+ data->irq_state = 0;
+ data->recog_flag = ON;
+
+ if (factory_mode == ON) {
+ k2hh_i2c_write(data, INT_THSX1_REG, 0x00);
+ k2hh_i2c_write(data, INT_THSY1_REG, 0x00);
+ k2hh_i2c_write(data, INT_THSZ1_REG, 0x00);
+ k2hh_i2c_write(data, INT_CFG1_REG, 0x3f);
+ } else {
+ k2hh_set_odr(data);
+ if (atomic_read(&data->enable) == OFF) {
+ k2hh_set_mode(data, K2HH_MODE_NORMAL);
+ msleep(20);
+ k2hh_read_accel_xyz(data, &acc);
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+ } else {
+ acc.x = data->accdata.x;
+ acc.y = data->accdata.y;
+ acc.z = data->accdata.z;
+ }
+
+ threshx = (abs(acc.v[data->axis_map_x]) \
+ + DYNAMIC_THRESHOLD) >> 8;
+ threshy = (abs(acc.v[data->axis_map_y]) \
+ + DYNAMIC_THRESHOLD) >> 8;
+ threshz = (abs(acc.v[data->axis_map_z]) \
+ + DYNAMIC_THRESHOLD) >> 8;
+
+ k2hh_i2c_write(data, INT_THSX1_REG, threshx);
+ k2hh_i2c_write(data, INT_THSY1_REG, threshy);
+ k2hh_i2c_write(data, INT_THSZ1_REG, threshz);
+ k2hh_i2c_write(data, INT_CFG1_REG, 0x0a);
+ }
+
+ k2hh_i2c_write(data, CTRL7_REG, CTRL7_LIR1);
+ k2hh_i2c_write(data, CTRL3_REG, CTRL3_IG1_INT1);
+
+ enable_irq(data->irq1);
+ enable_irq_wake(data->irq1);
+
+ pr_info("[SENSOR]: %s - reactive alert is on!\n", __func__);
+ } else if ((enable == OFF) && (data->recog_flag == ON)) {
+ k2hh_i2c_write(data, CTRL3_REG, 0x00);
+
+ disable_irq_wake(data->irq1);
+ disable_irq_nosync(data->irq1);
+ data->recog_flag = OFF;
+ pr_info("[SENSOR]: %s - reactive alert is off! irq = %d\n",
+ __func__, data->irq_state);
+ }
+
+ return size;
+}
+
+static ssize_t k2hh_reactive_alert_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", data->irq_state);
+}
+
+static ssize_t k2hh_selftest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct k2hh_p *data = dev_get_drvdata(dev);
+ struct k2hh_v acc;
+ unsigned char temp;
+ int result = 1, i;
+ ssize_t ret;
+ s32 NO_ST[3] = {0, 0, 0};
+ s32 ST[3] = {0, 0, 0};
+
+ if (atomic_read(&data->enable) == OFF)
+ k2hh_set_mode(data, K2HH_MODE_NORMAL);
+ else
+ k2hh_set_enable(data, OFF);
+
+ k2hh_i2c_write(data, CTRL1_REG, 0x3f);
+ k2hh_i2c_write(data, CTRL4_REG, 0x04);
+ k2hh_i2c_write(data, CTRL5_REG, 0x00);
+ k2hh_i2c_write(data, CTRL6_REG, 0x00);
+
+ mdelay(80);
+
+ k2hh_read_accel_xyz(data, &acc);
+
+ for (i = 0; i < 5; i++) {
+ while (1) {
+ if (k2hh_i2c_read(data, STATUS_REG, &temp, 1) < 0) {
+ pr_err("[SENSOR] %s: i2c error", __func__);
+ goto exit_status_err;
+ }
+
+ if (temp & 0x08)
+ break;
+ }
+
+ k2hh_read_accel_xyz(data, &acc);
+ NO_ST[0] += acc.x;
+ NO_ST[1] += acc.y;
+ NO_ST[2] += acc.z;
+ }
+ NO_ST[0] /= 5;
+ NO_ST[1] /= 5;
+ NO_ST[2] /= 5;
+
+ k2hh_i2c_write(data, CTRL5_REG, 0x04);
+
+ mdelay(80);
+
+ k2hh_read_accel_xyz(data, &acc);
+
+ for (i = 0; i < 5; i++) {
+ while (1) {
+ if (k2hh_i2c_read(data, STATUS_REG, &temp, 1) < 0) {
+ pr_err("[SENSOR] %s: i2c error", __func__);
+ goto exit_status_err;
+ }
+
+ if (temp & 0x08)
+ break;
+ }
+
+ k2hh_read_accel_xyz(data, &acc);
+ ST[0] += acc.x;
+ ST[1] += acc.y;
+ ST[2] += acc.z;
+ }
+
+ ST[0] /= 5;
+ ST[1] /= 5;
+ ST[2] /= 5;
+
+ for (i = 0; i < 3; i++) {
+ ST[i] -= NO_ST[i];
+ ST[i] = abs(ST[i]);
+
+ if ((SELF_TEST_2G_MIN_LSB > ST[i]) \
+ || (ST[i] > SELF_TEST_2G_MAX_LSB)) {
+ pr_info("[SENSOR] %s: %d Out of range!! (%d)\n",
+ __func__, i, ST[i]);
+ result = 0;
+ }
+ }
+
+ if (result)
+ ret = sprintf(buf, "1,%d,%d,%d\n", ST[0], ST[1], ST[2]);
+ else
+ ret = sprintf(buf, "0,%d,%d,%d\n", ST[0], ST[1], ST[2]);
+
+ goto exit;
+
+exit_status_err:
+ ret = sprintf(buf, "-1,0,0,0\n");
+exit:
+ k2hh_i2c_write(data, CTRL1_REG, 0x00);
+ k2hh_i2c_write(data, CTRL5_REG, 0x00);
+
+ if (atomic_read(&data->enable) == OFF) {
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+ } else {
+ k2hh_set_mode(data, K2HH_MODE_NORMAL);
+ k2hh_set_enable(data, ON);
+ }
+
+ return ret;
+}
+
+static DEVICE_ATTR(selftest, S_IRUGO, k2hh_selftest_show, NULL);
+static DEVICE_ATTR(name, S_IRUGO, k2hh_name_show, NULL);
+static DEVICE_ATTR(vendor, S_IRUGO, k2hh_vendor_show, NULL);
+static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR | S_IWGRP,
+ k2hh_calibration_show, k2hh_calibration_store);
+static DEVICE_ATTR(raw_data, S_IRUGO, k2hh_raw_data_read, NULL);
+static DEVICE_ATTR(reactive_alert, S_IRUGO | S_IWUSR | S_IWGRP,
+ k2hh_reactive_alert_show, k2hh_reactive_alert_store);
+
+static struct device_attribute *sensor_attrs[] = {
+ &dev_attr_name,
+ &dev_attr_vendor,
+ &dev_attr_calibration,
+ &dev_attr_raw_data,
+ &dev_attr_reactive_alert,
+ &dev_attr_selftest,
+ NULL,
+};
+
+static void k2hh_irq_work_func(struct work_struct *work)
+{
+ struct k2hh_p *data = container_of((struct delayed_work *)work,
+ struct k2hh_p, irq_work);
+ unsigned char buf;
+
+ k2hh_i2c_write(data, INT_CFG1_REG, 0x00);
+ k2hh_i2c_read(data, INT_SRC1_REG, &buf, 1);
+}
+
+static irqreturn_t k2hh_irq_thread(int irq, void *k2hh_data_p)
+{
+ struct k2hh_p *data = k2hh_data_p;
+
+ data->irq_state = 1;
+ wake_lock_timeout(&data->reactive_wake_lock,
+ msecs_to_jiffies(2000));
+ schedule_delayed_work(&data->irq_work, msecs_to_jiffies(100));
+ pr_info("###### [SENSOR]: %s reactive irq ######\n", __func__);
+
+ return IRQ_HANDLED;
+}
+
+static int k2hh_setup_pin(struct k2hh_p *data)
+{
+ int ret;
+
+ ret = gpio_request(data->acc_int1, "ACC_INT1");
+ if (ret < 0) {
+ pr_err("[SENSOR] %s - gpio %d request failed (%d)\n",
+ __func__, data->acc_int1, ret);
+ goto exit;
+ }
+
+ ret = gpio_direction_input(data->acc_int1);
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - failed to set gpio %d as input (%d)\n",
+ __func__, data->acc_int1, ret);
+ goto exit_acc_int1;
+ }
+
+ wake_lock_init(&data->reactive_wake_lock, WAKE_LOCK_SUSPEND,
+ "reactive_wake_lock");
+
+ data->irq1 = gpio_to_irq(data->acc_int1);
+ ret = request_threaded_irq(data->irq1, NULL, k2hh_irq_thread,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "k2hh_accel", data);
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - can't allocate irq.\n", __func__);
+ goto exit_reactive_irq;
+ }
+
+ disable_irq(data->irq1);
+ goto exit;
+
+exit_reactive_irq:
+ wake_lock_destroy(&data->reactive_wake_lock);
+exit_acc_int1:
+ gpio_free(data->acc_int1);
+exit:
+ return ret;
+}
+
+static int k2hh_input_init(struct k2hh_p *data)
+{
+ int ret = 0;
+ struct input_dev *dev;
+
+ dev = input_allocate_device();
+ if (!dev)
+ return -ENOMEM;
+
+ dev->name = MODULE_NAME;
+ dev->id.bustype = BUS_I2C;
+
+ input_set_capability(dev, EV_REL, REL_X);
+ input_set_capability(dev, EV_REL, REL_Y);
+ input_set_capability(dev, EV_REL, REL_Z);
+ input_set_drvdata(dev, data);
+
+ ret = input_register_device(dev);
+ if (ret < 0) {
+ input_free_device(dev);
+ return ret;
+ }
+ /* sysfs node creation */
+ ret = sysfs_create_group(&dev->dev.kobj, &k2hh_attribute_group);
+ if (ret < 0) {
+ input_unregister_device(dev);
+ return ret;
+ }
+
+ data->input = dev;
+ return 0;
+}
+
+static int k2hh_parse_dt(struct k2hh_p *data, struct device *dev)
+{
+ struct device_node *dNode = dev->of_node;
+ enum of_gpio_flags flags;
+ int ret;
+ u32 temp;
+
+ if (dNode == NULL)
+ return -ENODEV;
+
+ data->acc_int1 = of_get_named_gpio_flags(dNode,
+ "stm,irq_gpio", 0, &flags);
+ if (data->acc_int1 < 0) {
+ pr_err("[SENSOR]: %s - get acc_int1 error\n", __func__);
+ return -ENODEV;
+ }
+
+ data->sda_gpio = of_get_named_gpio_flags(dNode,
+ "stm,sda", 0, &flags);
+ if (data->sda_gpio < 0)
+ pr_info("[SENSOR]: %s - no sda_gpio\n", __func__);
+
+ data->scl_gpio = of_get_named_gpio_flags(dNode,
+ "stm,scl", 0, &flags);
+ if (data->scl_gpio < 0)
+ pr_info("[SENSOR]: %s - no scl_gpio\n", __func__);
+
+ ret = of_property_read_u32(dNode,"stm,axis_map_x", &temp);
+ if ((data->axis_map_x > 2) || (ret < 0)) {
+ pr_err("%s: invalid x axis_map value %u\n",
+ __func__, data->axis_map_x);
+ data->axis_map_x = 0;
+ } else {
+ data->axis_map_x= (u8)temp;
+ }
+
+ ret = of_property_read_u32(dNode,"stm,axis_map_y", &temp);
+ if ((data->axis_map_y > 2) || (ret < 0)) {
+ pr_err("%s: invalid y axis_map value %u\n",
+ __func__, data->axis_map_y);
+ data->axis_map_y = 1;
+ } else {
+ data->axis_map_y= (u8)temp;
+ }
+
+ ret = of_property_read_u32(dNode,"stm,axis_map_z", &temp);
+ if ((data->axis_map_z > 2) || (ret < 0)) {
+ pr_err("%s: invalid z axis_map value %u\n",
+ __func__, data->axis_map_z);
+ data->axis_map_z = 2;
+ } else {
+ data->axis_map_z= (u8)temp;
+ }
+
+ ret = of_property_read_u32(dNode,"stm,negate_x", &temp);
+ if ((data->negate_x > 1) || (ret < 0)) {
+ pr_err("%s: invalid x axis_map value %u\n",
+ __func__, data->negate_x);
+ data->negate_x = 0;
+ } else {
+ data->negate_x= (u8)temp;
+ }
+
+ ret = of_property_read_u32(dNode,"stm,negate_y", &temp);
+ if ((data->negate_y > 1) || (ret < 0)) {
+ pr_err("%s: invalid y axis_map value %u\n",
+ __func__, data->negate_y);
+ data->negate_y = 0;
+ } else {
+ data->negate_y= (u8)temp;
+ }
+
+ ret = of_property_read_u32(dNode,"stm,negate_z", &temp);
+ if ((data->negate_z > 1) || (ret < 0)) {
+ pr_err("%s: invalid z axis_map value %u\n",
+ __func__, data->negate_z);
+ data->negate_z = 0;
+ } else {
+ data->negate_z= (u8)temp;
+ }
+
+ return 0;
+}
+
+static int k2hh_regulator_onoff(struct k2hh_p *data, bool onoff)
+{
+#if 0
+ int ret = -1;
+
+ if (!data->vdd) {
+ data->vdd = regulator_get(&data->client->dev, "stm,reg_vdd");
+ if (!data->vdd) {
+ pr_err("%s: regulator pointer null vdd, rc=%d\n",
+ __func__, ret);
+ return ret;
+ }
+ ret = regulator_set_voltage(data->vdd, 3000000, 3000000);
+ if (ret) {
+ pr_err("%s: set voltage failed on vdd, rc=%d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+ /*if (!data->vio) {
+ data->vio = regulator_get(&data->client->dev, "stm,reg_vio");
+ if(!data->vio){
+ pr_err("%s: regulator_get for vio failed\n",
+ __func__);
+ return 0;
+ }
+ }*/
+ if(onoff){
+ ret = regulator_enable(data->vdd);
+ if (ret) {
+ pr_err("%s: Failed to enable regulator vdd.\n",
+ __func__);
+ return ret;
+ }
+ /*ret = regulator_enable(data->vio);
+ if (ret) {
+ pr_err("%s: Failed to enable regulator vio.\n",
+ __func__);
+ return ret;
+ }
+ msleep(30);*/
+ }
+ else {
+ ret = regulator_disable(data->vdd);
+ if (ret) {
+ pr_err("%s: Failed to disable regulator vdd.\n",
+ __func__);
+ return ret;
+ }
+ /*ret = regulator_disable(data->vio);
+ if (ret) {
+ pr_err("%s: Failed to disable regulator vio.\n",
+ __func__);
+ return ret;
+ }*/
+ }
+#endif
+ return 0;
+}
+
+
+static int k2hh_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ u8 temp;
+ int ret = -ENODEV, i;
+ struct k2hh_p *data = NULL;
+
+ pr_err("[SENSOR]: %s - Probe Start!\n", __func__);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("[SENSOR]: %s - i2c_check_functionality error\n",
+ __func__);
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct k2hh_p), GFP_KERNEL);
+ if (data == NULL) {
+ pr_err("[SENSOR]: %s - kzalloc error\n", __func__);
+ ret = -ENOMEM;
+ goto exit_kzalloc;
+ }
+
+ i2c_set_clientdata(client, data);
+ data->client = client;
+
+ ret = k2hh_parse_dt(data, &client->dev);
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - of_node error\n", __func__);
+ ret = -ENODEV;
+ goto exit_of_node;
+ }
+
+ ret = k2hh_regulator_onoff(data, true);
+ if (ret < 0)
+ pr_err("[SENSOR]: %s - No regulator\n", __func__);
+
+ ret = k2hh_setup_pin(data);
+ if (ret < 0) {
+ pr_err("[SENSOR]: %s - could not setup pin\n", __func__);
+ goto exit_setup_pin;
+ }
+
+ mutex_init(&data->mode_mutex);
+
+ /* read chip id */
+ k2hh_set_mode(data, K2HH_MODE_NORMAL);
+ for (i = 0; i < CHIP_ID_RETRIES; i++) {
+ ret = k2hh_i2c_read(data, WHOAMI_REG, &temp, 1);
+ if (temp != K2HH_CHIP_ID) {
+ pr_err("[SENSOR]: %s - chip id failed 0x%x : %d\n",
+ __func__, temp, ret);
+ } else {
+ pr_info("[SENSOR]: %s - chip id success 0x%x\n",
+ __func__, temp);
+ break;
+ }
+ msleep(20);
+ }
+
+ if (i >= CHIP_ID_RETRIES) {
+ ret = -ENODEV;
+ goto exit_read_chipid;
+ }
+
+ /* input device init */
+ ret = k2hh_input_init(data);
+ if (ret < 0)
+ goto exit_input_init;
+
+ sensors_register(data->factory_device, data, sensor_attrs, MODULE_NAME);
+
+ /* accel_timer settings. we poll for light values using a timer. */
+ hrtimer_init(&data->accel_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ data->poll_delay = ns_to_ktime(K2HH_DEFAULT_DELAY);
+ data->accel_timer.function = k2hh_timer_func;
+
+ /* the timer just fires off a work queue request. we need a thread
+ to read the i2c (can be slow and blocking). */
+ data->accel_wq = create_singlethread_workqueue("accel_wq");
+ if (!data->accel_wq) {
+ ret = -ENOMEM;
+ pr_err("[SENSOR]: %s - could not create workqueue\n", __func__);
+ goto exit_create_workqueue;
+ }
+
+ /* this is the thread function we run on the work queue */
+ INIT_WORK(&data->work, k2hh_work_func);
+ INIT_DELAYED_WORK(&data->irq_work, k2hh_irq_work_func);
+
+ atomic_set(&data->enable, OFF);
+ data->time_count = 0;
+ data->irq_state = 0;
+ data->recog_flag = OFF;
+
+ k2hh_set_range(data, K2HH_RANGE_2G);
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+
+ /*power off the regulators, for next enable power will be on*/
+ ret = k2hh_regulator_onoff(data, false);
+
+ pr_err("[SENSOR]: %s - Probe done!\n", __func__);
+
+ return 0;
+
+exit_create_workqueue:
+ sensors_unregister(data->factory_device, sensor_attrs);
+ sysfs_remove_group(&data->input->dev.kobj, &k2hh_attribute_group);
+ input_unregister_device(data->input);
+exit_input_init:
+exit_read_chipid:
+ mutex_destroy(&data->mode_mutex);
+ free_irq(data->irq1, data);
+ wake_lock_destroy(&data->reactive_wake_lock);
+ gpio_free(data->acc_int1);
+exit_setup_pin:
+exit_of_node:
+ kfree(data);
+exit_kzalloc:
+exit:
+ pr_err("[SENSOR]: %s - Probe fail!\n", __func__);
+ return ret;
+}
+
+static void k2hh_shutdown(struct i2c_client *client)
+{
+ struct k2hh_p *data = (struct k2hh_p *)i2c_get_clientdata(client);
+
+ pr_info("[SENSOR]: %s\n", __func__);
+
+ if (atomic_read(&data->enable) == ON)
+ k2hh_set_enable(data, OFF);
+
+ atomic_set(&data->enable, OFF);
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+}
+
+/*
+static int k2hh_remove(struct i2c_client *client)
+{
+ struct k2hh_p *data = (struct k2hh_p *)i2c_get_clientdata(client);
+
+ if (atomic_read(&data->enable) == ON)
+ k2hh_set_enable(data, OFF);
+
+ atomic_set(&data->enable, OFF);
+ cancel_delayed_work_sync(&data->irq_work);
+
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+ sensors_unregister(data->factory_device, sensor_attrs);
+
+ sysfs_remove_group(&data->input->dev.kobj, &k2hh_attribute_group);
+ input_unregister_device(data->input);
+
+ free_irq(data->irq1, data);
+ wake_lock_destroy(&data->reactive_wake_lock);
+ mutex_destroy(&data->mode_mutex);
+ gpio_free(data->acc_int1);
+ kfree(data);
+
+ return 0;
+}
+*/
+
+static int k2hh_suspend(struct device *dev)
+{
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ pr_info("[SENSOR]: %s\n", __func__);
+
+ if (atomic_read(&data->enable) == ON) {
+ k2hh_set_mode(data, K2HH_MODE_SUSPEND);
+ k2hh_set_enable(data, OFF);
+ }
+
+ return 0;
+}
+
+static int k2hh_resume(struct device *dev)
+{
+ struct k2hh_p *data = dev_get_drvdata(dev);
+
+ pr_info("[SENSOR]: %s\n", __func__);
+
+ if (atomic_read(&data->enable) == ON) {
+ k2hh_set_mode(data, K2HH_MODE_NORMAL);
+ k2hh_set_enable(data, ON);
+ }
+
+ return 0;
+}
+
+static struct of_device_id k2hh_match_table[] = {
+ { .compatible = "stm,k2hh",},
+ {},
+};
+
+static const struct i2c_device_id k2hh_id[] = {
+ { "k2hh_match_table", 0 },
+ { }
+};
+
+static const struct dev_pm_ops k2hh_pm_ops = {
+ .suspend = k2hh_suspend,
+ .resume = k2hh_resume
+};
+
+static struct i2c_driver k2hh_driver = {
+ .driver = {
+ .name = MODEL_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = k2hh_match_table,
+ .pm = &k2hh_pm_ops
+ },
+ .probe = k2hh_probe,
+ .shutdown = k2hh_shutdown,
+/* .remove = k2hh_remove, */
+ .id_table = k2hh_id,
+};
+
+static int __init k2hh_init(void)
+{
+ return i2c_add_driver(&k2hh_driver);
+}
+
+static void __exit k2hh_exit(void)
+{
+ i2c_del_driver(&k2hh_driver);
+}
+
+module_init(k2hh_init);
+module_exit(k2hh_exit);
+
+MODULE_DESCRIPTION("k2hh accelerometer sensor driver");
+MODULE_AUTHOR("Samsung Electronics");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/sensor/sensors_core.c b/drivers/sensor/sensors_core.c
new file mode 100644
index 00000000..5a192f95
--- /dev/null
+++ b/drivers/sensor/sensors_core.c
@@ -0,0 +1,110 @@
+/* /driver/sensors/core/sensors_core.c
+ * Copyright (C) 2011 Samsung Electronics. 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 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+
+
+struct class *sensors_class;
+EXPORT_SYMBOL_GPL(sensors_class);
+
+
+/**
+ * Create sysfs interface
+ */
+static void set_sensor_attr(struct device *dev,
+ struct device_attribute *attributes[])
+{
+ int i;
+
+ for (i = 0 ; attributes[i] != NULL ; i++) {
+ if ((device_create_file(dev, attributes[i])) < 0)
+ pr_err("Create_dev_file fail(attributes[%d] )\n", i);
+ }
+}
+
+int sensors_register(struct device *dev, void * drvdata,
+ struct device_attribute *attributes[], char *name)
+{
+ int ret = 0;
+
+ if (!sensors_class) {
+ sensors_class = class_create(THIS_MODULE, "sensors");
+ if (IS_ERR(sensors_class))
+ return PTR_ERR(sensors_class);
+ }
+
+
+ dev = device_create(sensors_class, NULL, 0, drvdata, "%s", name);
+
+ if (IS_ERR(dev)) {
+ ret = PTR_ERR(dev);
+ pr_err("[SENSORS CORE] device_create failed! [%d]\n", ret);
+ return ret;
+ }
+
+ set_sensor_attr(dev, attributes);
+
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sensors_register);
+
+void sensors_unregister(struct device *dev,struct device_attribute *attributes[])
+{
+ int i;
+
+ if (sensors_class != NULL) {
+ for (i = 0 ; attributes[i] != NULL ; i++)
+ device_remove_file(dev, attributes[i]);
+ }
+}
+EXPORT_SYMBOL_GPL(sensors_unregister);
+
+static int __init sensors_class_init(void)
+{
+ pr_debug("[SENSORS CORE] sensors_class_init\n");
+ sensors_class = class_create(THIS_MODULE, "sensors");
+
+ if (IS_ERR(sensors_class))
+ return PTR_ERR(sensors_class);
+
+ sensors_class->dev_uevent = NULL;
+
+ return 0;
+}
+
+static void __exit sensors_class_exit(void)
+{
+ class_destroy(sensors_class);
+}
+
+
+/* exported for the APM Power driver, APM emulation */
+
+subsys_initcall(sensors_class_init);
+module_exit(sensors_class_exit);
+
+MODULE_DESCRIPTION("Universal sensors core class");
+MODULE_AUTHOR("Ryunkyun Park <ryun.park@samsung.com>");
+MODULE_LICENSE("GPL");
+