summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/iio/st_lsm6ds3.txt19
-rw-r--r--arch/arm/boot/dts/omap3.dtsi9
-rw-r--r--arch/arm/boot/dts/omap3_h1.dts59
-rw-r--r--arch/arm/configs/omap3_h1_defconfig2
-rw-r--r--arch/arm/mach-omap2/Kconfig29
-rw-r--r--arch/arm/mach-omap2/board-omap3h1-bluetooth.c27
-rw-r--r--arch/arm/mach-omap2/board-omap3h1.c88
-rw-r--r--arch/arm/mach-omap2/serial.c1
-rw-r--r--drivers/iio/Kconfig3
-rw-r--r--drivers/iio/Makefile2
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/Kconfig40
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/Makefile56
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/README659
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/dmpDefaultMPU6050.c384
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/dmpKey.h607
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/dmpmap.h263
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_mpu3050_iio.c271
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_mpu_core.c3135
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_mpu_dts.c270
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_mpu_dts.h30
-rw-r--r--drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_iio.h1078
-rw-r--r--drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_misc.c2041
-rw-r--r--drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_ring.c1899
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_mpu_trigger.c94
-rw-r--r--drivers/iio/imu-aosp/inv_mpu6515/inv_slave_bma250.c315
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_slave_compass.c854
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_slave_pressure.c522
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_test/Kconfig13
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_test/Makefile6
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_test/inv_counters.c154
-rwxr-xr-xdrivers/iio/imu-aosp/inv_mpu6515/inv_test/inv_counters.h72
-rw-r--r--drivers/iio/imu/Kconfig (renamed from drivers/iio/imu-aosp/Kconfig)3
-rw-r--r--drivers/iio/imu/Makefile (renamed from drivers/iio/imu-aosp/Makefile)2
-rw-r--r--drivers/iio/imu/adis.c (renamed from drivers/iio/imu-aosp/adis.c)0
-rw-r--r--drivers/iio/imu/adis16400.h (renamed from drivers/iio/imu-aosp/adis16400.h)0
-rw-r--r--drivers/iio/imu/adis16400_buffer.c (renamed from drivers/iio/imu-aosp/adis16400_buffer.c)0
-rw-r--r--drivers/iio/imu/adis16400_core.c (renamed from drivers/iio/imu-aosp/adis16400_core.c)0
-rw-r--r--drivers/iio/imu/adis16480.c (renamed from drivers/iio/imu-aosp/adis16480.c)0
-rw-r--r--drivers/iio/imu/adis_buffer.c (renamed from drivers/iio/imu-aosp/adis_buffer.c)0
-rw-r--r--drivers/iio/imu/adis_trigger.c (renamed from drivers/iio/imu-aosp/adis_trigger.c)0
-rw-r--r--drivers/iio/imu/inv_mpu6050/Kconfig (renamed from drivers/iio/imu-aosp/inv_mpu6050/Kconfig)0
-rw-r--r--drivers/iio/imu/inv_mpu6050/Makefile (renamed from drivers/iio/imu-aosp/inv_mpu6050/Makefile)0
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c (renamed from drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_core.c)0
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h (renamed from drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_iio.h)0
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c (renamed from drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_ring.c)0
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c (renamed from drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_trigger.c)0
-rw-r--r--drivers/iio/imu/st_lsm6ds3/Kconfig75
-rw-r--r--drivers/iio/imu/st_lsm6ds3/Makefile11
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3.h280
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_buffer.c448
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_core.c2137
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_i2c.c159
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_i2c_master.c1387
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_spi.c180
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_trigger.c175
-rw-r--r--drivers/iio/industrialio-core.c9
-rw-r--r--drivers/iio/magnetometer/Makefile2
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/Kconfig47
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/Makefile48
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/README176
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ak09911_core.c512
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ak09911_iio.h115
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ak09911_ring.c139
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ak09911_trigger.c75
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ak89xx_core.c590
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ak89xx_iio.h144
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ak89xx_ring.c138
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ak89xx_trigger.c75
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ami306_core.c570
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ami306_iio.h159
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ami306_ring.c163
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_ami306_trigger.c90
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_yas53x_core.c969
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_yas53x_iio.h172
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_yas53x_ring.c165
-rwxr-xr-xdrivers/iio/magnetometer/inv_compass/inv_yas53x_trigger.c91
-rw-r--r--drivers/tty/serial/omap-serial.c41
-rw-r--r--include/linux/iio/types.h4
-rw-r--r--include/linux/platform_data/serial-omap.h4
79 files changed, 5079 insertions, 17278 deletions
diff --git a/Documentation/devicetree/bindings/iio/st_lsm6ds3.txt b/Documentation/devicetree/bindings/iio/st_lsm6ds3.txt
new file mode 100644
index 00000000000..bef52f2e290
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/st_lsm6ds3.txt
@@ -0,0 +1,19 @@
+/* STMicroelectronics lsm6ds3 sensor */
+
+Required properties:
+ - compatible : should be "st,lsm6ds3"
+ - reg : the I2C address of the sensor
+
+Optional properties:
+ - interrupt-parent : should be the phandle for the interrupt controller
+ - interrupts : interrupt mapping for GPIO IRQ, it should by configured with
+ flags IRQ_TYPE_EDGE_RISING
+
+Example:
+
+lsm6ds3@6b {
+ compatible = "st,lsm6ds3";
+ reg = <0x6b>;
+ interrupt-parent = <&gpio>;
+ interrupts = <1 IRQ_TYPE_EDGE_RISING>;
+}; \ No newline at end of file
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index f5ddf6aac1e..cae4e9725d0 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -13,12 +13,13 @@
/ {
compatible = "ti,omap3430", "ti,omap3";
interrupt-parent = <&intc>;
-
+/*
aliases {
serial0 = &uart1;
serial1 = &uart2;
serial2 = &uart3;
};
+ */
cpus {
cpu@0 {
@@ -207,7 +208,7 @@
<&omap3_pmx_core 26 0xd9 1>,
<&omap3_pmx_core 28 0xc1 4>;
};
-
+/*
uart1: serial@4806a000 {
compatible = "ti,omap3-uart";
ti,hwmods = "uart1";
@@ -224,8 +225,8 @@
compatible = "ti,omap3-uart";
ti,hwmods = "uart3";
clock-frequency = <48000000>;
- };
-
+ }; */
+
i2c1: i2c@48070000 {
compatible = "ti,omap3-i2c";
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/omap3_h1.dts b/arch/arm/boot/dts/omap3_h1.dts
index e570db34a7c..9111ebf872e 100644
--- a/arch/arm/boot/dts/omap3_h1.dts
+++ b/arch/arm/boot/dts/omap3_h1.dts
@@ -193,13 +193,21 @@
0x188 0x100 /* HSUSB0_DATA7, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT) */
/* pin for controlling bluetooth chip, settings from uboot */
+ 0x1a8 0x004 /* CONTROL_PADCONF_MCSPI2_SIMO, (IDIS | PI | M4 ) */
0x1aa 0x004 /* CONTROL_PADCONF_MCSPI2_SOMI, (IDIS | PI | M4 ) */
/* BT_WAKE_GPIO - for waking up BT */
- /* OMAP_OFF_ENABLE and OMAP_OFF_PULL_EN for sleep modes. */
- 0x0da 0x1204 /* DSS_DATA23, (IDIS | PI | M4 ) */
+ /* OMAP_OFF_ENABLE, OMAP_OFF_PULL_EN, OMAP_OFF_OUTENABLE for sleep modes. */
+ 0x0da 0x1604 /* DSS_DATA23, (IDIS | PI | M4 ) */
+ /* UART3 pins */
+ 0x16e 0x4100 /* RX, input, off wake up */
+ 0x170 0x000 /* TX, output */
+
+ /* BT_HOST_WAKE */
+ /*0x9f4 0x4104 */ /* JTAG_EMU0 , (OMAP_MUX_MODE4 | OMAP_PIN_INPUT | OMAP_WAKEUPENABLE) */
/* Accelerometer interrupt */
+
/* I've tried configuring this both in the wkup pinmux (below) and here,
but this location makes it not function as an interrupt... ??? */
/* 0x9f6 0x4104 */ /* JTAG_EMU1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT |
@@ -213,29 +221,15 @@
0x18c 0x118 /* I2C1_SCA, MODE0 | INPUT_PULLUP */
>;
};
-
+
+ /*
i2c2_pins: pinmux_i2c2_pins {
pinctrl-single,pins = <
- 0x18e 0x118 /* I2C2_SCL, MODE0 | INPUT_PULLUP */
- 0x190 0x118 /* I2C2_SDA, MODE0 | INPUT_PULLUP */
- >;
- };
-
- uart1_pins: pinmux_uart1_pins {
- pinctrl-single,pins = <
- /* uart1 */
- 0x152 0x118 /* UART1_RX, MODEO | (uboot: ien, pullup, m0 */
- 0x146 0x000 /* UART1_TX, MODE0 | OUTPUT, MODE0 */
- >;
- };
-
- uart3_pins: pinmux_uart3_pins {
- pinctrl-single,pins = <
- /* uart3 */
- 0x16e 0x4118 /* UART3_RX, MODEO | INPUT_PULLUP | OFFWAKEUP*/
- 0x170 0x000 /* UART3_TX, MODE0 | OUTPUT */
- >;
- };
+ 0x18e 0x118 */ /* I2C2_SCL, MODE0 | INPUT_PULLUP */
+ /* 0x190 0x118 */ /* I2C2_SDA, MODE0 | INPUT_PULLUP */
+ /* >; */
+ /* }; */
+
};
&omap3_pmx_wkup { /* pinmux@0x48002a00 */
@@ -248,11 +242,12 @@
0x018 0x000 /* SYS_OFF_MODE, MODE0 */
0x01a 0x10c /* SYS_CLKOUT1, MODE4 | INPUT_PULLDOWN */
/* Wakeup from Bluetooth */
- /* 0x024 0x4104 */ /* JTAG_EMU0, OMAP_MUX_MODE4 | OMAP_PIN_INPUT |
+ 0x024 0x4104 /* JTAG_EMU0, OMAP_MUX_MODE4 | OMAP_PIN_INPUT |
OMAP_PIN_OFF_WAKEUPENABLE */
/* Accelerometer interrupt */
0x026 0x410C /* JTAG_EMU1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT |
OMAP_PIN_OFF_WAKEUPENABLE */
+
>;
};
};
@@ -439,19 +434,3 @@
};
-
-&uart1 {
- pinctrl-0 = <&uart1_pins>;
- pinctrl-names = "default";
-};
-
-&uart2 {
- status = "disabled";
-};
-
-&uart3 {
- pinctrl-0 = <&uart3_pins>;
- pinctrl-names = "default";
- autosuspend-delay = <(-1)>; /* -1 = infinity. Negative value needs parens */
- wakeup-capable;
-};
diff --git a/arch/arm/configs/omap3_h1_defconfig b/arch/arm/configs/omap3_h1_defconfig
index 7ecf2b83edb..e50a5475d7b 100644
--- a/arch/arm/configs/omap3_h1_defconfig
+++ b/arch/arm/configs/omap3_h1_defconfig
@@ -935,7 +935,7 @@ CONFIG_FIB_RULES=y
# CONFIG_WIMAX is not set
CONFIG_RFKILL=y
# CONFIG_RFKILL_PM is not set
-CONFIG_RFKILL_INPUT=y
+# CONFIG_RFKILL_INPUT is not set
# CONFIG_RFKILL_REGULATOR is not set
CONFIG_RFKILL_GPIO=y
# CONFIG_RFKILL_WL18XX is not set
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index c3fdbc0f08a..2793feafaae 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -216,7 +216,7 @@ config MACH_OMAP3_H1
choice
prompt "Olio H1B build version"
- default MACH_OMAP3_H1_EVT2
+ default MACH_OMAP3_H1_PV2
config MACH_OMAP3_H1_EVT1
bool "EVT1 Build of the H1 board"
@@ -231,9 +231,32 @@ config MACH_OMAP3_H1_DVT1
depends on MACH_OMAP3_H1
config MACH_OMAP3_H1_DVT2
- bool "DVT2 Build of the H1 board"
- depends on MACH_OMAP3_H1
+ bool "DVT2 Build of the H1 board"
+ depends on MACH_OMAP3_H1
+
+config MACH_OMAP3_H1_PV
+ bool "PV Build of the H1 board"
+ depends on MACH_OMAP3_H1
+endchoice
+
+choice
+ prompt "Olio H1B PV build version"
+
+config MACH_OMAP3_H1_PV1
+ bool "PV Board with Invensense accelerometer."
+ depends on MACH_OMAP3_H1_PV
+ help
+ This is our first PV board, with Invensense accelerometer. Hopefully
+ it'll be extinct soon. Don't forget to add the invensense driver to
+ the kernel as well.
+config MACH_OMAP3_H1_PV2
+ bool "PV Board with ST accelerometer."
+ depends on MACH_OMAP3_H1_PV
+ help
+ This is the better PV board, with a more capable accelerometer from ST.
+ Might be our last board! Don't forget to configure the accelerometer in
+ the kernel as well.
endchoice
config MACH_DEVKIT8000
diff --git a/arch/arm/mach-omap2/board-omap3h1-bluetooth.c b/arch/arm/mach-omap2/board-omap3h1-bluetooth.c
index 323ec99ac6b..84108a79258 100644
--- a/arch/arm/mach-omap2/board-omap3h1-bluetooth.c
+++ b/arch/arm/mach-omap2/board-omap3h1-bluetooth.c
@@ -36,16 +36,19 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <asm/mach-types.h>
+#include <linux/platform_data/serial-omap.h>
#include "serial.h"
#include "board-omap3h1.h"
#include <linux/regulator/driver.h>
static void update_host_wake_locked(int);
+#define BT_RESET_GPIO 179
#define BT_REG_GPIO 180
#define BT_RESET_GPIO 179
#define BT_WAKE_GPIO 93
#define BT_HOST_WAKE_GPIO 11
+#define UART_PORT 1
static struct rfkill *bt_rfkill;
static struct regulator *clk32ksys_reg;
@@ -76,13 +79,14 @@ static int bcm20702_bt_rfkill_set_power(void *data, bool blocked)
gpio_set_value(BT_RESET_GPIO, 1);
gpio_set_value(BT_REG_GPIO, 1);
+ gpio_set_value(BT_RESET_GPIO, 1);
} else {
// Chip won't toggle host_wake after reset. Make sure
// we don't hold the wake_lock until chip wakes up again.
update_host_wake_locked(0);
-
- gpio_set_value(BT_RESET_GPIO, 0);
+
+ gpio_set_value(BT_RESET_GPIO, 0);
gpio_set_value(BT_REG_GPIO, 0);
if (clk32ksys_reg && bt_enabled)
regulator_disable(clk32ksys_reg);
@@ -104,13 +108,13 @@ static void set_wake_locked(int wake)
if (!wake)
wake_unlock(&bt_lpm.wake_lock);
- //if (!wake_uart_enabled && wake)
- //omap_uart_enable(2);
+ if (!wake_uart_enabled && wake)
+ omap_serial_ext_uart_enable(UART_PORT);
gpio_set_value(BT_WAKE_GPIO, wake);
- //if (wake_uart_enabled && !wake)
- //omap_uart_disable(2);
+ if (wake_uart_enabled && !wake)
+ omap_serial_ext_uart_disable(UART_PORT);
wake_uart_enabled = wake;
}
@@ -146,11 +150,11 @@ static void update_host_wake_locked(int host_wake)
if (host_wake) {
wake_lock(&bt_lpm.wake_lock);
if (!host_wake_uart_enabled) {
- //omap_uart_enable(2);
+ omap_serial_ext_uart_enable(UART_PORT);
}
} else {
if (host_wake_uart_enabled) {
- //omap_uart_disable(2);
+ omap_serial_ext_uart_disable(UART_PORT);
}
// Take a timed wakelock, so that upper layers can take it.
// The chipset deasserts the hostwake lock, when there is no
@@ -259,15 +263,16 @@ static int bcm20702_bluetooth_probe(struct platform_device *pdev)
int rc = 0;
int ret = 0;
- rc = gpio_request(BT_RESET_GPIO, "bcm20702_nreset_gpip");
+ rc = gpio_request(BT_RESET_GPIO, "bcm20702_nreset_gpip");
+
if (unlikely(rc)) {
return rc;
}
rc = gpio_request(BT_REG_GPIO, "bcm20702_nshutdown_gpio");
if (unlikely(rc)) {
- gpio_free(BT_RESET_GPIO);
- return rc;
+ gpio_free(BT_RESET_GPIO);
+ return rc;
}
clk32ksys_reg = regulator_get(0, "clk32ksys");
diff --git a/arch/arm/mach-omap2/board-omap3h1.c b/arch/arm/mach-omap2/board-omap3h1.c
index 05dadc33c0f..0d3214c4150 100644
--- a/arch/arm/mach-omap2/board-omap3h1.c
+++ b/arch/arm/mach-omap2/board-omap3h1.c
@@ -82,7 +82,7 @@
#define DEFAULT_RXDMA_BUFSIZE 4096 /* RX DMA buffer size */
#define DEFAULT_RXDMA_TIMEOUT (3 * HZ)/* RX DMA timeout (jiffies) */
-#if defined(CONFIG_MACH_OMAP3_H1_DVT1) || defined(CONFIG_MACH_OMAP3_H1_DVT2)
+#if defined(CONFIG_MACH_OMAP3_H1_DVT1) || defined(CONFIG_MACH_OMAP3_H1_DVT2) || defined (CONFIG_MACH_OMAP3_H1_PV)
#define LCD_RESET_GPIO 94
#else
#define LCD_RESET_GPIO 122
@@ -185,6 +185,7 @@ static int __init omap3h1_spi_init(void) {
* (0 means VLogic, which I'm not sure what it is).
*/
+#ifndef CONFIG_MACH_OMAP3_H1_PV2
static struct mpu_platform_data mpu_data = {
.int_config = 0x00,
.level_shifter = 1,
@@ -192,6 +193,7 @@ static struct mpu_platform_data mpu_data = {
-1, 0, 0,
0, 0, 1 },
};
+#endif
static struct lm3530_platform_data omap3h1_backlight_platform_data = {
.mode = LM3530_BL_MODE_MANUAL,
@@ -267,16 +269,17 @@ static struct platform_device nop_phy_device = {
static struct i2c_board_info __initdata omap3h1_i2c1_board_info[] = {
{
},
-#ifdef CONFIG_MACH_OMAP3_H1_DVT2
+#if defined (CONFIG_MACH_OMAP3_H1_DVT2) || defined (CONFIG_MACH_OMAP3_H1_PV)
};
static struct i2c_board_info __initdata omap3h1_i2c2_board_info[] = {
#endif
{
+#ifdef CONFIG_MACH_OMAP3_H1_PV2
+ I2C_BOARD_INFO("lsm6ds3", 0x6a),
+#else
I2C_BOARD_INFO("mpu6515", 0x68),
- // This is needed for the interrupt wake. IH_GPIO_BASE changed in 3.10
- // .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
- .irq = 0,
.platform_data = &mpu_data,
+#endif
},
{
/* Backlight */
@@ -299,6 +302,70 @@ static struct i2c_board_info __initdata omap3h1_i2c3_board_info[] = {
},
};
+
+/***************************************************************************
+ * omap_uart data
+ */
+
+/* Some notes:
+ .dma_enabled = false,
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .autosuspend_timeout = DEFAULT_AUTOSUSPEND_DELAY, ( -1 or X ms. )
+
+ .wakelock_timeout - for minnow, this is 150 (BT) or 50 (M4 debug).
+ Can be left out.
+
+ .DTR_* -> can be left out. I can't find anyone using it.
+
+ int DTR_gpio;
+ int DTR_inverted;
+ int DTR_present;
+ bool wakeup_capable;
+
+ bool open_close_pm; - Minnow uses this for c55 only
+ unsigned int rx_trig; Minnow, BT & debug only
+*/
+
+static struct omap_uart_port_info omap_uart_ports[] = {
+ {
+ .dma_enabled = false, /* To specify DMA Mode */
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .autosuspend_timeout = 1000,
+ .wakelock_timeout = 150,
+ .wake_peer = bcm_bt_lpm_exit_lpm_locked,
+ .wakeup_capable = true,
+ },
+ {
+ .dma_enabled = false, /* To specify DMA Mode */
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .autosuspend_timeout = 0,
+ .wakeup_capable = false,
+ },
+ {
+ .dma_enabled = false, /* To specify DMA Mode */
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .autosuspend_timeout = -1,
+ .wakeup_capable = true,
+ },
+ {
+ .dma_enabled = false, /* To specify DMA Mode */
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .autosuspend_timeout = 0,
+ .wakeup_capable = false,
+ },
+};
+
+
/***************************************************************************
* omap3_h1_i2c_init - init the i2c buses
*
@@ -314,16 +381,13 @@ static int __init omap3_h1_i2c_init(void)
*/
gpio_request_one(ATMEL_MXT_GPIO, GPIOF_IN, "atmel_mxt_ts CHG");
- gpio_request_one(MPUIRQ_GPIO, GPIOF_IN, "mpu6515 IRQ pin");
+ gpio_request_one(MPUIRQ_GPIO, GPIOF_IN, "Accl IRQ pin");
acc_irq = gpio_to_irq(MPUIRQ_GPIO);
-#ifdef CONFIG_MACH_OMAP3_H1_DVT2
+#if defined (CONFIG_MACH_OMAP3_H1_DVT2) || defined (CONFIG_MACH_OMAP3_H1_PV)
omap3h1_i2c2_board_info[2].irq = gpio_to_irq(ATMEL_MXT_GPIO);
omap3h1_i2c2_board_info[0].irq = acc_irq;
-
- // ((struct tps65910_board *) (omap3h1_i2c1_board_info[0].platform_data))->irq =
- // gpio_to_irq (TPS_SYS_NIRQ);
#else
omap3h1_i2c1_board_info[3].irq = gpio_to_irq(ATMEL_MXT_GPIO);
omap3h1_i2c1_board_info[1].irq = acc_irq;
@@ -334,7 +398,7 @@ static int __init omap3_h1_i2c_init(void)
/* Register buses */
// omap_register_i2c_bus(1, 400, omap3h1_i2c1_board_info, ARRAY_SIZE(omap3h1_i2c1_board_info));
-#ifdef CONFIG_MACH_OMAP3_H1_DVT2
+#if defined (CONFIG_MACH_OMAP3_H1_DVT2) || defined (CONFIG_MACH_OMAP3_H1_PV)
omap_register_i2c_bus(2, 400, omap3h1_i2c2_board_info, ARRAY_SIZE(omap3h1_i2c2_board_info));
#else
omap_register_i2c_bus(2, 400, NULL, 0);
@@ -372,6 +436,8 @@ static void __init omap3_h1_init(void)
omap3h1_spi_init();
+ omap_serial_board_init(omap_uart_ports);
+
omap_display_init(&omap3h1_dss_data);
usb_bind_phy("musb-hdrc.0.auto", 0, "nop_usb_xceiv"); /* "tusb-usb-h1" */
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index b570d93cbb7..b1f3fb1d396 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -301,6 +301,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
omap_up.dma_rx_timeout = info->dma_rx_timeout;
omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
omap_up.autosuspend_timeout = info->autosuspend_timeout;
+ omap_up.wake_peer = info->wake_peer;
omap_up.DTR_gpio = info->DTR_gpio;
omap_up.DTR_inverted = info->DTR_inverted;
omap_up.DTR_present = info->DTR_present;
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index a37b074755d..b2f963be399 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -4,6 +4,7 @@
menuconfig IIO
tristate "Industrial I/O support"
+ depends on GENERIC_HARDIRQS
help
The industrial I/O subsystem provides a unified framework for
drivers for many different types of embedded sensors using a
@@ -66,7 +67,7 @@ source "drivers/iio/common/Kconfig"
source "drivers/iio/dac/Kconfig"
source "drivers/iio/frequency/Kconfig"
source "drivers/iio/gyro/Kconfig"
-# source "drivers/iio/imu/Kconfig"
+source "drivers/iio/imu/Kconfig"
source "drivers/iio/light/Kconfig"
source "drivers/iio/magnetometer/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 35a17226827..a0e8cdd67e4 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -18,6 +18,6 @@ obj-y += common/
obj-y += dac/
obj-y += gyro/
obj-y += frequency/
-# obj-y += imu/
+obj-y += imu/
obj-y += light/
obj-y += magnetometer/
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/Kconfig b/drivers/iio/imu-aosp/inv_mpu6515/Kconfig
deleted file mode 100755
index 18ccddb1f4e..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/Kconfig
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# inv-mpu-iio driver for Invensense MPU devices and combos
-#
-
-config INV_MPU_IIO
- tristate "Invensense MPU devices"
- depends on I2C && SYSFS && IIO && IIO_KFIFO_BUF && IIO_TRIGGER && !INV_MPU
- default n
- help
- This driver supports the Invensense MPU devices.
- This includes MPU6050/MPU3050/MPU9150/ITG3500/MPU6500/MPU9250.
- This driver can be built as a module. The module will be called
- inv-mpu-iio.
-
-config INV_IIO_MPU3050_ACCEL_SLAVE_BMA250
- bool "Invensense MPU3050 slave accelerometer device for bma250"
- depends on INV_MPU_IIO
- default n
- help
- This is slave device enable MPU3050 accelerometer slave device.
- Right now, it is only bma250. For other acceleromter device,
- it can be added to this menu if the proper interface is filled.
- There are some interface function to be defined.
-
-config DTS_INV_MPU_IIO
- bool "Invensense MPU driver using Device Tree Structure (DTS)"
- depends on INV_MPU_IIO
- default n
- help
- This enables Invensense MPU devices to use Device Tree Structure.
- DTS must be enabled in the system.
-
-config INV_KERNEL_3_10
- bool "Invensense MPU driver support for 3.10 kernel"
- depends on INV_MPU_IIO
- default n
- help
- This enables Invensense MPU devices for 3.10 kernel
-
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/Makefile b/drivers/iio/imu-aosp/inv_mpu6515/Makefile
deleted file mode 100755
index 6e3c2475889..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# Makefile for Invensense inv-mpu-iio device.
-#
-
-obj-$(CONFIG_INV_MPU_IIO) += inv-mpu-iio.o
-
-inv-mpu-iio-objs := inv_mpu_core.o
-inv-mpu-iio-objs += inv_mpu_ring.o
-inv-mpu-iio-objs += inv_mpu_trigger.o
-inv-mpu-iio-objs += inv_mpu_misc.o
-inv-mpu-iio-objs += inv_mpu3050_iio.o
-inv-mpu-iio-objs += dmpDefaultMPU6050.o
-inv-mpu-iio-objs += inv_slave_compass.o
-inv-mpu-iio-objs += inv_slave_pressure.o
-
-ifeq ($(CONFIG_INV_KERNEL_3_10), y)
-CFLAGS_inv_mpu_core.o += -Idrivers/iio -Iinclude/linux/iio
-CFLAGS_inv_mpu_ring.o += -Idrivers/iio -Iinclude/linux/iio
-CFLAGS_inv_mpu_trigger.o += -Idrivers/iio -Iinclude/linux/iio
-CFLAGS_inv_mpu_misc.o += -Idrivers/iio -Iinclude/linux/iio
-CFLAGS_inv_mpu3050_iio.o += -Idrivers/iio -Iinclude/linux/iio
-CFLAGS_dmpDefaultMPU6050.o += -Idrivers/iio -Iinclude/linux/iio
-CFLAGS_inv_slave_compass.o += -Idrivers/iio -Iinclude/linux/iio
-CFLAGS_inv_slave_pressure.o += -Idrivers/iio -Iinclude/linux/iio
-else
-CFLAGS_inv_mpu_core.o += -Idrivers/staging/iio
-CFLAGS_inv_mpu_ring.o += -Idrivers/staging/iio
-CFLAGS_inv_mpu_trigger.o += -Idrivers/staging/iio
-CFLAGS_inv_mpu_misc.o += -Idrivers/staging/iio
-CFLAGS_inv_mpu3050_iio.o += -Idrivers/staging/iio
-CFLAGS_dmpDefaultMPU6050.o += -Idrivers/staging/iio
-CFLAGS_inv_slave_compass.o += -Idrivers/staging/iio
-CFLAGS_inv_slave_pressure.o += -Idrivers/staging/iio
-endif
-
-# the Bosch BMA250 driver is added to the inv-mpu device driver because it
-# must be connected to an MPU3050 device on the secondary slave bus.
-ifeq ($(CONFIG_INV_IIO_MPU3050_ACCEL_SLAVE_BMA250), y)
-inv-mpu-iio-objs += inv_slave_bma250.o
-ifeq ($(CONFIG_INV_KERNEL_3_10), y)
-CFLAGS_inv_slave_bma250.o += -Idrivers/iio
-else
-CFLAGS_inv_slave_bma250.o += -Idrivers/staging/iio
-endif
-endif
-
-# compile Invensense MPU IIO driver as DTS
-ifeq ($(CONFIG_DTS_INV_MPU_IIO), y)
-inv-mpu-iio-objs += inv_mpu_dts.o
-ifeq ($(CONFIG_INV_KERNEL_3_10), y)
-CFLAGS_inv_mpu_dts.o += -Idrivers/iio
-else
-CFLAGS_inv_mpu_dts.o += -Idrivers/staging/iio
-endif
-endif
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/README b/drivers/iio/imu-aosp/inv_mpu6515/README
deleted file mode 100755
index 0963954a844..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/README
+++ /dev/null
@@ -1,659 +0,0 @@
-Kernel driver inv-mpu-iio
-Author: Invensense <http://invensense.com>
-
-Table of Contents:
-==================
-- Description
-- Integrating the Driver in the Linux Kernel
-- Board and Platform Data
- > Interrupt Pin
- > Platform Data
-- Board File Modifications for Secondary I2C Configuration
- > MPU-6050 + AKM8963 on the secondary I2C interface
- > MPU-6500 + AKM8963 on the secondary I2C interface
- > MPU-6515 + AKM8975 and BMP280 on the secondary I2C interface
- > MPU-9150
- > MPU-9250
- > MPU-3050 + BMA250 on the secondary I2C interface
-- Board File Modifications for Invensense Devices
- > MPU-3050
- > ITG-3500
- > MPU-6050
- > MPU-6515
- > MPU-6500
- > MPU-6XXX
- > MPU-9150
- > MPU-9250
-- IIO Subsystem
- > Communicating with the Driver in Userspace
- > ITG-3500
- > MPU-6050 and MPU-6500
- > MPU-9150
- > MPU-9250
- > MPU-3050 + BMA250 on the secondary I2C interface
-- Suspend and Resume
-- Wake up CPU using event interrupt
-- DMP Event
-- Motion Event
-- Streaming Data to an Userspace Application
-- Recommended Sysfs Entry Setup Sequence
- > With DMP Firmware
- > Without DMP Firmware
-- Test Applications
- > Running Test Applications with MPU-9150/MPU-6050/MPU-6500/MPU-9250
- > Running Test Applications with MPU-3050/ITG-3500
-
-
-Description
-===========
-This document describes how to install the Invensense device driver into a
-Linux kernel. The Invensense driver currently supports the following sensors:
-- ITG-3500
-- MPU-6050
-- MPU-9150
-- MPU-6500
-- MPU-9250
-- MPU-3050
-- MPU-6XXX(either MPU6050 or MPU6500, driver to do auto detection)
-
-The slave address of each device is either 0x68 or 0x69, depending on the AD0
-pin value of the device. Please refer to the appropriate product specification
-document for further information regarding the AD0 pin. The driver supports both
-addresses.
-
-The following files are included in this package:
-- Kconfig
-- Makefile
-- inv_mpu_core.c
-- inv_mpu_misc.c
-- inv_mpu_trigger.c
-- inv_mpu3050_iio.c
-- inv_mpu_iio.h
-- inv_mpu_ring.c
-- inv_slave_bma250.c
-- inv_slave_compass.c
-- dmpDefaultMPU6050.c
-- dmpkey.h
-- dmpmap.h
-- mpu.h
-
-
-Integrating the Driver in the Linux Kernel
-==========================================
-Please add the files as follows:
-- Add mpu.h to "kernel/include/linux".
-- Add all other files to drivers/staging/iio/imu/inv_mpu
-(another directory is acceptable, but this is the recommended destination)
-
-In order to see the driver in menuconfig when building the kernel, please
-make modifications as shown below:
-
- modify "drivers/staging/iio/imu/Kconfig" with:
- >> source "drivers/staging/iio/imu/inv_mpu/Kconfig"
-
- modify "drivers/staging/iio/imu/Makefile" with:
- >> obj-y += inv_mpu/
-
-
-Board and Platform Data
-=======================
-In order to recognize the Invensense device on the I2C bus, the board file must
-be modified.
-The i2c_board_info instance must be defined as shown below.
-
-Interrupt Pin
--------------
-The hardcoded value of 140 corresponds to the GPIO input pin connected to the
-Invensense device's interrupt pin.
-This pin will most likely be different for your platform, and the value should
-be changed accordingly.
-
-Platform Data
--------------
-The platform data (orientation matrix and secondary bus configurations) must be
-modified as show below, according to your particular platform configuration.
-
-Please note that the MPU-9150 it is treated as a MPU-6050 with AKM8975 on the
-device's secondary I2C interface. Thus the secondary I2C address must be
-provided.
-
-Please note that the MPU-9250 it is treated as a MPU-6500 with AKM8963 on the
-device's secondary I2C interface. Thus the secondary I2C address must be
-provided.
-
-Board File Modifications for Secondary I2C Configuration
-========================================================
-For the Panda Board, the board file can be found at
-arch/arm/mach-omap2/board-omap4panda.c.
-Please modify the pertinent baord file in your system according to the examples
-shown below:
-
-MPU-6050 + AKM8963 on the secondary I2C interface
--------------------------------------------------
-static struct mpu_platform_data gyro_platform_data = {
- .int_config = 0x00,
- .level_shifter = 0,
- .orientation = { -1, 0, 0,
- 0, 1, 0,
- 0, 0, -1 },
- .sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
- .sec_slave_id = COMPASS_ID_AK8963,
- .secondary_i2c_addr = 0x0E,
- .secondary_orientation = { 0, 1, 0,
- 1, 0, 0,
- 0, 0, -1 },
-};
-
-MPU-6500 + AKM8963 on the secondary I2C interface
--------------------------------------------------
-static struct mpu_platform_data gyro_platform_data = {
- .int_config = 0x00,
- .level_shifter = 0,
- .orientation = { -1, 0, 0,
- 0, 1, 0,
- 0, 0, -1 },
- .sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
- .sec_slave_id = COMPASS_ID_AK8963,
- .secondary_i2c_addr = 0x0E,
- .secondary_orientation = { 0, 1, 0,
- 1, 0, 0,
- 0, 0, -1 },
-};
-
-MPU-6500 + AK09911 on the secondary I2C interface
--------------------------------------------------
-static struct mpu_platform_data gyro_platform_data = {
- .int_config = 0x00,
- .level_shifter = 0,
- .orientation = { -1, 0, 0,
- 0, 1, 0,
- 0, 0, -1 },
- .sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
- .sec_slave_id = COMPASS_ID_AK09911,
- .secondary_i2c_addr = 0x0D,
- .secondary_orientation = { 0, 1, 0,
- 1, 0, 0,
- 0, 0, -1 },
-};
-
-MPU-6515 + AK8975 + BMP280 on the secondary I2C interface
-Note: sec_slave_XXX can only be compass or accelerometer in 3050 case.
- aux_slave_XXX can only be pressure.
---------------------------------------------------
-static struct mpu_platform_data mpu_data = {
- .int_config = 0x00,
- .level_shifter = 0,
- .orientation = { -1, 0, 0,
- 0, 1, 0,
- 0, 0, -1 },
- .sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
- .sec_slave_id = COMPASS_ID_AK8975,
- .secondary_i2c_addr = 0x0E,
- .secondary_orientation = { 0, 1, 0,
- 1, 0, 0,
- 0, 0, -1 },
- .aux_slave_type = SECONDARY_SLAVE_TYPE_PRESSURE,
- .aux_slave_id = PRESSURE_ID_BMP280,
- .aux_i2c_addr = 0x77,
-};
-static struct i2c_board_info __initdata chip_board_info[] = {
- {
- I2C_BOARD_INFO("mpu6515", 0x68),
- .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
- .platform_data = &mpu_data,
- }
-};
-
-MPU-9150
---------
-For MPU-9150, please provide the following secondary I2C bus information.
-
-static struct mpu_platform_data gyro_platform_data = {
- .int_config = 0x10,
- .level_shifter = 0,
- .orientation = { 1, 0, 0,
- 0, 1, 0,
- 0, 0, 1 },
- .sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
- .sec_slave_id = COMPASS_ID_AK8975,
- .secondary_i2c_addr = 0x0C,
- .secondary_orientation = { 0, 1, 0,
- 1, 0, 0,
- 0, 0, -1 },
-};
-
-MPU-9250
---------
-For MPU-9250, please provide the following secondary I2C bus information.
-
-static struct mpu_platform_data gyro_platform_data = {
- .int_config = 0x00,
- .level_shifter = 0,
- .orientation = { 1, 0, 0,
- 0, 1, 0,
- 0, 0, 1 },
- .sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
- .sec_slave_id = COMPASS_ID_AK8963,
- .secondary_i2c_addr = 0x0C,
- .secondary_orientation = { 0, 1, 0,
- -1, 0, 0,
- 0, 0, 1 },
-};
-
-MPU-3050 + BMA250 on the secondary I2C interface
-------------------------------------------------
-For BMA250 on the secondary I2C bus, please provide the following information.
-
-static struct mpu_platform_data gyro_platform_data = {
- .int_config = 0x10,
- .level_shifter = 0,
- .orientation = { -1, 0, 0,
- 0, 1, 0,
- 0, 0, -1 },
- .sec_slave_type = SECONDARY_SLAVE_TYPE_ACCEL,
- .sec_slave_id = ACCEL_ID_BMA250,
- .secondary_i2c_addr = 0x18,
-};
-
-
-Board File Modifications for Invensense Devices
-===============================================
-For Invensense devices, please provide the i2c init data as shown in the
-examples below.
-
-In the _i2c_init function, the device is registered in the following manner:
-
- // arch/arm/mach-omap2/board-omap4panda.c
- // in static int __init omap4_panda_i2c_init(void)
- omap_register_i2c_bus(4, 400,
- single_chip_board_info,
- ARRAY_SIZE(single_chip_board_info));
-
-MPU-3050
---------
-static struct i2c_board_info __initdata single_chip_board_info[] = {
- {
- I2C_BOARD_INFO("mpu3050", 0x68),
- .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
- .platform_data = &gyro_platform_data,
- },
-};
-
-ITG-3500
---------
-static struct i2c_board_info __initdata single_chip_board_info[] = {
- {
- I2C_BOARD_INFO("itg3500", 0x68),
- .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
- .platform_data = &gyro_platform_data,
- },
-};
-
-MPU6050
--------
-static struct i2c_board_info __initdata single_chip_board_info[] = {
- {
- I2C_BOARD_INFO("mpu6050", 0x68),
- .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
- .platform_data = &gyro_platform_data,
- },
-};
-
-MPU6500
--------
-static struct i2c_board_info __initdata single_chip_board_info[] = {
- {
- I2C_BOARD_INFO("mpu6500", 0x68),
- .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
- .platform_data = &gyro_platform_data,
- },
-};
-
-MPU6XXX
--------
-static struct i2c_board_info __initdata single_chip_board_info[] = {
- {
- I2C_BOARD_INFO("mpu6xxx", 0x68),
- .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
- .platform_data = &gyro_platform_data,
- },
-};
-
-MPU9150
--------
-arch/arm/mach-omap2/board-omap4panda.c
-static struct i2c_board_info __initdata single_chip_board_info[] = {
- {
- I2C_BOARD_INFO("mpu9150", 0x68),
- .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
- .platform_data = &gyro_platform_data,
- },
-};
-
-MPU9250
--------
-arch/arm/mach-omap2/board-omap4panda.c
-static struct i2c_board_info __initdata single_chip_board_info[] = {
- {
- I2C_BOARD_INFO("mpu9250", 0x68),
- .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
- .platform_data = &gyro_platform_data,
- },
-};
-
-IIO subsystem
-=============
-A successful installation will create the following two new directories under
-/sys/bus/iio/devices:
- - iio:device0
- - trigger0
-
-Also, a new file, "iio:device0", will be created in the /dev/ diretory.
-(if you have more than one IIO device, the file will be named "iio:deviceX",
-where X is a number)
-
-
-Communicating with the Driver in Userspace
-------------------------------------------
-The driver generates several files in sysfs upon installation.
-These files are used to communicate with the driver. The files can be found
-at /sys/bus/iio/devices/iio:device0 (or ../iio:deviceX as shown above).
-
-A brief description of the pertinent files for each Invensense device is shown
-below:
-
-ITG-3500
---------
-temperature (Read-only)
---Read temperature data directly from the temperature register.
-
-sampling_frequency (Read/write)
---Configure the ADC sampling rate and FIFO output rate.
-
-sampling_frequency_available(read-only)
---show commonly used frequency
-
-clock_source (Read-only)
---Check which clock-source is used by the chip.
-
-power_state (Read/write)
---turn on/off the power supply
-
-self_test (read-only)
---read this entry trigger self test. The return value is D.
-D is the success/fail.
-For different chip, the result is different for success/fail.
-1 means success 0 means fail. The LSB of D is for gyro; the bit
-next to LSB of D is for accel. The bit 2 of D is for compass result.
-
-key (read-only)
---show the key value of this driver. Used by MPL.
-
-gyro_matrix (read-only)
---show the orientation matrix obtained from the board file.
-
-MPU-6050 and MPU-6500
----------------------
-MPU-6050 and MPU-6500 have all sysfs files belonging to ITG-3500 (shown above).
-In addition, it has the files below:
-
-gyro_enable (read/write)
---enable/disable gyro functionality. Affects raw_gyro. Turning this off this
- will shut down gyro and save power.
-
-accl_enable (read/write)
---enable/disable accelerometer functionality. Affects raw_accl.
-Turning this off this will shut down accel and save power.
-
-firmware_loaded (read/write)
---Flag indicating the whether firmware is loaded or not in the DMP engine.
-0 means no firmware loaded. 1 means firmware is already loaded . This
-flag can only be written as 0. It internally updates to 1.
-
-dmp_on(read/write)
---This entry controls whether to run DMP or not.
-Write 1 to enable DMP and write 0 to disable dmp.
-Please note that firmware_loaded must be 1 in order to enable DMP.
-
-dmp_int_on(read/write)
---This entry controls whether dmp interrupt is on/off.
-Please note that firmware_loaded must be 1.
-Also, we'd like to remind you that it is sometimes advantageous to
-turn interrupts off while the DMP is running.
-
-dmp_output_rate
---control dmp output rate when dmp is on.
-
-dmp_event_int_on(read/write)
---This entry controls whether dmp event interrupt is on/off.
-Please note that turning this on will turn off the data interrupt.
-Interrupts will be generated only when events occur.
-This is useful for saving power when the system is waiting for a special event
-to wake up.
-
-dmp_firmware (write only binary file)
---DMP firmware code is loaded into this entry.
-If loading is successful, the firmware_loaded flag will be updated to 1.
-In order to load new firmware, the firmware_loaded flag must be first set to 0.
-
-accel_matrix
---orientation matrix for accelerometer.
-
-quaternion_on
---Turn on/off quaterniion data output. DMP is required for this feature.
-
-pedometer_time
-pedometer_steps,
---Pedometer related entries
-
-event_tap
-event_display_orientation
-event_accel_motion
-event_smd
---Event related entries.
-Please poll these entries to read their values. Direct reads will yield
-meaningless results.
-Further details are provided in the DMP Events section of this README.
-
-tap_on
---Controls tap function of DMP
-
-tap_time
-tap_min_count
-tap_threshold
---Tap related entries. Controls various parameters of tap function.
-
-display_orientation_on
---Turn on/off display orientation function of DMP.
-
-smd_enable
-enable SMD(Significant Motion Detection) detection.
-
-smd_threshold
-This set the threshold of the motion when SMD start to be triggered. The
-value is in acclerometer counts.
-
-smd_delay_threshold
-This sets the threshold of time after which SMD can be triggered.
-The value is in seconds.
-
-smd_delay_threshold2
-This sets the threshold of time during which SMD can be triggered (after the
-smd_delay_threshold timer has expired).
-The value is in seconds.
-
-quaternion_on
---Turn on/off quaterniion data output. DMP is required for this feature.
-
-Low power accel motion interrupt related settings.
-if motion_lpa_on is set, this will disable all engines except accel. Accel will
-enter low power mode and the whole chip will be turned on/off at specific frequency.
------------------------------------------------------------------------------
-motion_lpa_threshold
---set motion threshold. in mg. The maximum is 1020mg and resolution is 32mg.
-
-motion_lpa_on
---turn on/off motion function.
-
-motion_lpa_freq
---motion lpa frequency. which determines power on/off frequency.
-------------------------------------------------------------------------------
-MPU-9150
---------
-MPU-9150 has all of MPU-6050's entries. It also has two additional entries,
-described below.
-
-compass_enable (read/write)
---Enables compass function.
-
-compass_matrix (read-only)
---Compass orientation matrix
-
-MPU-3050 with BMA250 on secondary I2C interface
------------------------------------------------
-MPU-3050 with BMA250 on the secondary I2C interface has ever ITG-3500 entry.
-It also has two additional entries, shown below:
-
-accl_matrix
-
-accl_enable
-
-Suspend and Resume
-===================================================
-The suspend and resume functions are call backs registered to the system
-and executed when the system goes in suspend and resumes.
-It is enabled when CONFIG_PM is defined.
-The current behavior is simple:
-- suspend will turn off the chip
-- resume will turn on the chip
-
-However, it is possible for the driver to do more complex things;
-for example, leaving pedometers running when system is off. This can save whole
-system power while letting pedometer working. Other behaviors are possible
-too.
-
-Wake up CPU using event interrupt
-====================================================
-It is common practice in current mobile device to save power as much as
-possible. Ususally the device can sleep when not use and only be wake up when in use.
-Invensense MPU series provides an efficient way of waking up CPU by events.
-The events could be pedometer steps, tap action, SMD(significant Motion Detection),
-or any customer defined actions. CPU can sleep to save power, when event happens,
-DMP will calculate the motion data to detemine whether a pre-defined event happens
-or not. If an pre-defined happens, an interrupt is generated to wake up the CPU
-to do further processing.
-The requirements of doing event wake is the following:
-1. Add enable_irq_wake() either in the driver or in the board file.
-2. Connect the interrupt pin to the CPU wake up pin.
-3. Configure CPU to be woken up by wake up pin.
-
-DMP Event
-=========
-A DMP Event is an event that is output by the DMP unit within the Invensense
-device (MPU).
-Only the MPU-6050, MPU-6500, MPU-9250, MPU-9150, MPU-9250 feature the DMP.
-
-There are four sysfs entries for DMP events:
-- event_tap
-- event_display_orientation
-- event_accel_motion
-- event_smd
-
-These events must be polled before reading.
-
-The proper method to poll sysfs is as follows:
-1. open file.
-2. dummy read.
-3. poll.
-4. once the poll passed, use fopen and fread to read the sysfs entry.
-5. interpret the data.
-
-Streaming Data to an Userspace Application
-==========================================
-When streaming data to an userspace application, we recommend that you access
-gyro/accel/compass data via /dev/iio:device0.
-
-Please follow the steps below to read data at a constant rate from the driver:
-
-1. Write a 1 to power_state to turn on the chip. This is the default setting
- after installing the driver.
-2. Write the desired output rate to fifo_rate.
-3. Write 1 to enable to turn on the event.
-4. Read /dev/iio:device0 to get a string of gyro/accel/compass data.
-5. Parse this string to obtain each gyro/accel/compass element.
-6. If dmp firmware code is loaded, use "dmp_on" to enable/disable dmp.
-7. If compass is enabled, the output will contain compass data.
-
-
-Recommended Sysfs Entry Setup Senquence
-=======================================
-
-Without DMP Firmware
---------------------
-1. Set "power_state" to 1,
-2. Set the scale and fifo rate values according to your needs.
-3. Set gyro_enable, accel_enable, and compass_enable according to your needs.
- For example:
- - If you only want gyro data, set accel_enable to 0 (and compass_enable to
- 0, if applicable).
- - If you only want accel data, set gyro_enable to 0 (and compass_enable to
- 0, if applicable).
- - If you only want compass data, set gyro_enable to 0 and accel_enable to 0.
-4. Set "enable" to 1.
-5. You will now get the output that you want.
-
-With DMP Firmware
------------------
-1. Set "power_state" to 1.
-2. Write "0" to firmware_loaded if it is not zero already.
-3. Load firmware into "dmp_firmware" as a whole. Don't split the DMP firmware
- image.
-4. Make sure firmware_loaded is 1 after loading the DMP image.
-5. Make appropriate configurations as shown above in the "without DMP firmware"
- case.
-6. Set dmp_on to 1.
-7. Set "enable" to 1.
-
-Please note that the enable function uses the enable entry under
-"/sys/bus/iio/devices/iio:device0/buffer"
-
-Test Applications
-=================
-A test application is located under software/simple_apps/mpu_iio.
-This application is stand-alone in that it cannot be run concurrently with other
-entities trying to access the device node(s) or sysfs entries; in particular,
-the
-
-Running Test Applications with MPU-9150/MPU-6050/MPU-6500/MPU-9250
----------------------------------------------------------
-To run test applications with MPU-9150, MPU-9250, MPU-6050, or MPU-6500 devices,
-please use the following commands:
-
-1. For tap/display orientation events:
- mpu_iio -c 10 -l 3 -p
-
-2. In addition, to test the motion interrupt (and no_motion on MPU6050) use:
- mpu_iio -c 10 -l 3 -p -m
-
-3. For printing data normally:
- mpu_iio -c 10 -l 3 -r
-
-Running Test Applications with MPU-3050/ITG-3500
-------------------------------------------------
-To run test applications with MPU-3050 or ITG-3500 devices,
-please use the following command:
-
-1. For printing data normally:
- mpu_iio -c 10 -l 3 -r
-
-Please use mpu_iio.c and iio_utils.h as example code for your development
-purposes.
-
-Stress test application
-=================================
-A stress test application is located under software/simple_apps/stress_iio.
-This application simulates HAL's usage calls to the driver. It creates three
-threads. One for data read; one for event read; one for sysfs control.
-It can run without any parameters or run with some control parameters. Please
-see README in the same directories for details.
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/dmpDefaultMPU6050.c b/drivers/iio/imu-aosp/inv_mpu6515/dmpDefaultMPU6050.c
deleted file mode 100755
index 892e62dc14f..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/dmpDefaultMPU6050.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2012 Invensense, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include "inv_mpu_iio.h"
-#include "dmpKey.h"
-#include "dmpmap.h"
-
-#define CFG_OUT_PRESS (1872)
-#define CFG_PED_ENABLE (1985)
-#define CFG_OUT_GYRO (1804)
-#define CFG_PEDSTEP_DET (2807)
-#define OUT_GYRO_DAT (1813)
-#define CFG_FIFO_INT (1983)
-#define OUT_CPASS_DAT (1847)
-#define CFG_AUTH (1099)
-#define OUT_ACCL_DAT (1779)
-#define FCFG_1 (1127)
-#define FCFG_3 (1152)
-#define FCFG_2 (1131)
-#define CFG_OUT_CPASS (1838)
-#define FCFG_7 (1138)
-#define CFG_OUT_3QUAT (1666)
-#define OUT_PRESS_DAT (1881)
-#define OUT_3QUAT_DAT (1676)
-#define CFG_7 (1349)
-#define OUT_PQUAT_DAT (1745)
-#define CFG_OUT_6QUAT (1701)
-#define CFG_PED_INT (2796)
-#define SMD_TP2 (1314)
-#define SMD_TP1 (1293)
-#define CFG_MOTION_BIAS (1351)
-#define CFG_OUT_ACCL (1770)
-#define CFG_OUT_STEPDET (1636)
-#define OUT_6QUAT_DAT (1711)
-#define CFG_OUT_PQUAT (1736)
-
-#define D_0_22 (22+512)
-#define D_0_24 (24+512)
-
-#define D_0_36 (36)
-#define D_0_52 (52)
-#define D_0_96 (96)
-#define D_0_104 (104)
-#define D_0_108 (108)
-#define D_0_163 (163)
-#define D_0_188 (188)
-#define D_0_192 (192)
-#define D_0_224 (224)
-#define D_0_228 (228)
-#define D_0_232 (232)
-#define D_0_236 (236)
-
-#define D_1_2 (256 + 2)
-#define D_1_4 (256 + 4)
-#define D_1_8 (256 + 8)
-#define D_1_10 (256 + 10)
-#define D_1_24 (256 + 24)
-#define D_1_28 (256 + 28)
-#define D_1_36 (256 + 36)
-#define D_1_40 (256 + 40)
-#define D_1_44 (256 + 44)
-#define D_1_72 (256 + 72)
-#define D_1_74 (256 + 74)
-#define D_1_79 (256 + 79)
-#define D_1_88 (256 + 88)
-#define D_1_90 (256 + 90)
-#define D_1_92 (256 + 92)
-#define D_1_96 (256 + 96)
-#define D_1_98 (256 + 98)
-#define D_1_106 (256 + 106)
-#define D_1_108 (256 + 108)
-#define D_1_112 (256 + 112)
-#define D_1_128 (256 + 144)
-#define D_1_152 (256 + 12)
-#define D_1_160 (256 + 160)
-#define D_1_176 (256 + 176)
-#define D_1_178 (256 + 178)
-#define D_1_218 (256 + 218)
-#define D_1_232 (256 + 232)
-#define D_1_236 (256 + 236)
-#define D_1_240 (256 + 240)
-#define D_1_244 (256 + 244)
-#define D_1_250 (256 + 250)
-#define D_1_252 (256 + 252)
-#define D_2_12 (512 + 12)
-#define D_2_96 (512 + 96)
-#define D_2_108 (512 + 108)
-#define D_2_208 (512 + 208)
-#define D_2_224 (512 + 224)
-#define D_2_236 (512 + 236)
-#define D_2_244 (512 + 244)
-#define D_2_248 (512 + 248)
-#define D_2_252 (512 + 252)
-#define CPASS_BIAS_X (30 * 16 + 4)
-#define CPASS_BIAS_Y (30 * 16 + 8)
-#define CPASS_BIAS_Z (30 * 16 + 12)
-#define CPASS_MTX_00 (32 * 16 + 4)
-#define CPASS_MTX_01 (32 * 16 + 8)
-#define CPASS_MTX_02 (36 * 16 + 12)
-#define CPASS_MTX_10 (33 * 16)
-#define CPASS_MTX_11 (33 * 16 + 4)
-#define CPASS_MTX_12 (33 * 16 + 8)
-#define CPASS_MTX_20 (33 * 16 + 12)
-#define CPASS_MTX_21 (34 * 16 + 4)
-#define CPASS_MTX_22 (34 * 16 + 8)
-#define D_EXT_GYRO_BIAS_X (61 * 16)
-#define D_EXT_GYRO_BIAS_Y (61 * 16 + 4)
-#define D_EXT_GYRO_BIAS_Z (61 * 16 + 8)
-#define D_ACT0 (40 * 16)
-#define D_ACSX (40 * 16 + 4)
-#define D_ACSY (40 * 16 + 8)
-#define D_ACSZ (40 * 16 + 12)
-
-#define FLICK_MSG (45 * 16 + 4)
-#define FLICK_COUNTER (45 * 16 + 8)
-#define FLICK_LOWER (45 * 16 + 12)
-#define FLICK_UPPER (46 * 16 + 12)
-
-#define D_SMD_ENABLE (18 * 16)
-#define D_SMD_MOT_THLD (21 * 16 + 8)
-#define D_SMD_DELAY_THLD (21 * 16 + 4)
-#define D_SMD_DELAY2_THLD (21 * 16 + 12)
-#define D_SMD_EXE_STATE (22 * 16)
-#define D_SMD_DELAY_CNTR (21 * 16)
-
-#define D_WF_GESTURE_TIME_THRSH (25 * 16 + 8)
-#define D_WF_GESTURE_TILT_ERROR (25 * 16 + 12)
-#define D_WF_GESTURE_TILT_THRSH (26 * 16 + 8)
-#define D_WF_GESTURE_TILT_REJECT_THRSH (26 * 16 + 12)
-
-#define D_AUTH_OUT (992)
-#define D_AUTH_IN (996)
-#define D_AUTH_A (1000)
-#define D_AUTH_B (1004)
-
-#define D_PEDSTD_BP_B (768 + 0x1C)
-#define D_PEDSTD_BP_A4 (768 + 0x40)
-#define D_PEDSTD_BP_A3 (768 + 0x44)
-#define D_PEDSTD_BP_A2 (768 + 0x48)
-#define D_PEDSTD_BP_A1 (768 + 0x4C)
-#define D_PEDSTD_SB (768 + 0x28)
-#define D_PEDSTD_SB_TIME (768 + 0x2C)
-#define D_PEDSTD_PEAKTHRSH (768 + 0x98)
-#define D_PEDSTD_TIML (768 + 0x2A)
-#define D_PEDSTD_TIMH (768 + 0x2E)
-#define D_PEDSTD_PEAK (768 + 0X94)
-#define D_PEDSTD_STEPCTR (768 + 0x60)
-#define D_PEDSTD_STEPCTR2 (58 * 16 + 8)
-#define D_PEDSTD_TIMECTR (964)
-#define D_PEDSTD_DECI (768 + 0xA0)
-#define D_PEDSTD_SB2 (60 * 16 + 14)
-#define D_STPDET_TIMESTAMP (28 * 16 + 8)
-#define D_PEDSTD_DRIVE_STATE (58)
-
-#define D_HOST_NO_MOT (976)
-#define D_ACCEL_BIAS (660)
-
-#define D_BM_BATCH_CNTR (27 * 16 + 4)
-#define D_BM_BATCH_THLD (27 * 16 + 12)
-#define D_BM_ENABLE (28 * 16 + 6)
-#define D_BM_NUMWORD_TOFILL (28 * 16 + 4)
-
-#define D_SO_DATA (4 * 16 + 2)
-
-#define D_P_HW_ID (22 * 16 + 10)
-#define D_P_INIT (22 * 16 + 2)
-
-#define D_DMP_RUN_CNTR (24*16)
-
-#define D_ODR_S0 (45*16+8)
-#define D_ODR_S1 (45*16+12)
-#define D_ODR_S2 (45*16+10)
-#define D_ODR_S3 (45*16+14)
-#define D_ODR_S4 (46*16+8)
-#define D_ODR_S5 (46*16+12)
-#define D_ODR_S6 (46*16+10)
-#define D_ODR_S7 (46*16+14)
-#define D_ODR_S8 (42*16+8)
-#define D_ODR_S9 (42*16+12)
-
-#define D_ODR_CNTR_S0 (45*16)
-#define D_ODR_CNTR_S1 (45*16+4)
-#define D_ODR_CNTR_S2 (45*16+2)
-#define D_ODR_CNTR_S3 (45*16+6)
-#define D_ODR_CNTR_S4 (46*16)
-#define D_ODR_CNTR_S5 (46*16+4)
-#define D_ODR_CNTR_S6 (46*16+2)
-#define D_ODR_CNTR_S7 (46*16+6)
-#define D_ODR_CNTR_S8 (42*16)
-#define D_ODR_CNTR_S9 (42*16+4)
-
-#define D_FS_LPQ0 (59*16)
-#define D_FS_LPQ1 (59*16 + 4)
-#define D_FS_LPQ2 (59*16 + 8)
-#define D_FS_LPQ3 (59*16 + 12)
-
-#define D_FS_Q0 (12*16)
-#define D_FS_Q1 (12*16 + 4)
-#define D_FS_Q2 (12*16 + 8)
-#define D_FS_Q3 (12*16 + 12)
-
-#define D_FS_9Q0 (2*16)
-#define D_FS_9Q1 (2*16 + 4)
-#define D_FS_9Q2 (2*16 + 8)
-#define D_FS_9Q3 (2*16 + 12)
-
-#define D_CPASS_STATUS_CHK (22*16 + 8)
-
-static const struct tKeyLabel dmpTConfig[] = {
- {KEY_CFG_OUT_ACCL, CFG_OUT_ACCL},
- {KEY_CFG_OUT_GYRO, CFG_OUT_GYRO},
- {KEY_CFG_OUT_3QUAT, CFG_OUT_3QUAT},
- {KEY_CFG_OUT_6QUAT, CFG_OUT_6QUAT},
- {KEY_CFG_OUT_PQUAT, CFG_OUT_PQUAT},
- {KEY_CFG_PED_ENABLE, CFG_PED_ENABLE},
- {KEY_CFG_FIFO_INT, CFG_FIFO_INT},
- {KEY_CFG_AUTH, CFG_AUTH},
- {KEY_FCFG_1, FCFG_1},
- {KEY_FCFG_3, FCFG_3},
- {KEY_FCFG_2, FCFG_2},
- {KEY_FCFG_7, FCFG_7},
- {KEY_CFG_7, CFG_7},
- {KEY_CFG_MOTION_BIAS, CFG_MOTION_BIAS},
- {KEY_CFG_PEDSTEP_DET, CFG_PEDSTEP_DET},
- {KEY_D_0_22, D_0_22},
- {KEY_D_0_96, D_0_96},
- {KEY_D_0_104, D_0_104},
- {KEY_D_0_108, D_0_108},
- {KEY_D_1_36, D_1_36},
- {KEY_D_1_40, D_1_40},
- {KEY_D_1_44, D_1_44},
- {KEY_D_1_72, D_1_72},
- {KEY_D_1_74, D_1_74},
- {KEY_D_1_79, D_1_79},
- {KEY_D_1_88, D_1_88},
- {KEY_D_1_90, D_1_90},
- {KEY_D_1_92, D_1_92},
- {KEY_D_1_160, D_1_160},
- {KEY_D_1_176, D_1_176},
- {KEY_D_1_218, D_1_218},
- {KEY_D_1_232, D_1_232},
- {KEY_D_1_250, D_1_250},
- {KEY_DMP_SH_TH_Y, DMP_SH_TH_Y},
- {KEY_DMP_SH_TH_X, DMP_SH_TH_X},
- {KEY_DMP_SH_TH_Z, DMP_SH_TH_Z},
- {KEY_DMP_ORIENT, DMP_ORIENT},
- {KEY_D_AUTH_OUT, D_AUTH_OUT},
- {KEY_D_AUTH_IN, D_AUTH_IN},
- {KEY_D_AUTH_A, D_AUTH_A},
- {KEY_D_AUTH_B, D_AUTH_B},
- {KEY_CPASS_BIAS_X, CPASS_BIAS_X},
- {KEY_CPASS_BIAS_Y, CPASS_BIAS_Y},
- {KEY_CPASS_BIAS_Z, CPASS_BIAS_Z},
- {KEY_CPASS_MTX_00, CPASS_MTX_00},
- {KEY_CPASS_MTX_01, CPASS_MTX_01},
- {KEY_CPASS_MTX_02, CPASS_MTX_02},
- {KEY_CPASS_MTX_10, CPASS_MTX_10},
- {KEY_CPASS_MTX_11, CPASS_MTX_11},
- {KEY_CPASS_MTX_12, CPASS_MTX_12},
- {KEY_CPASS_MTX_20, CPASS_MTX_20},
- {KEY_CPASS_MTX_21, CPASS_MTX_21},
- {KEY_CPASS_MTX_22, CPASS_MTX_22},
- {KEY_D_ACT0, D_ACT0},
- {KEY_D_ACSX, D_ACSX},
- {KEY_D_ACSY, D_ACSY},
- {KEY_D_ACSZ, D_ACSZ},
- {KEY_D_PEDSTD_BP_B, D_PEDSTD_BP_B},
- {KEY_D_PEDSTD_BP_A4, D_PEDSTD_BP_A4},
- {KEY_D_PEDSTD_BP_A3, D_PEDSTD_BP_A3},
- {KEY_D_PEDSTD_BP_A2, D_PEDSTD_BP_A2},
- {KEY_D_PEDSTD_BP_A1, D_PEDSTD_BP_A1},
- {KEY_D_PEDSTD_SB, D_PEDSTD_SB},
- {KEY_D_PEDSTD_SB_TIME, D_PEDSTD_SB_TIME},
- {KEY_D_PEDSTD_PEAKTHRSH, D_PEDSTD_PEAKTHRSH},
- {KEY_D_PEDSTD_TIML, D_PEDSTD_TIML},
- {KEY_D_PEDSTD_TIMH, D_PEDSTD_TIMH},
- {KEY_D_PEDSTD_PEAK, D_PEDSTD_PEAK},
- {KEY_D_PEDSTD_STEPCTR, D_PEDSTD_STEPCTR},
- {KEY_D_PEDSTD_STEPCTR2, D_PEDSTD_STEPCTR2},
- {KEY_D_PEDSTD_TIMECTR, D_PEDSTD_TIMECTR},
- {KEY_D_PEDSTD_DECI, D_PEDSTD_DECI},
- {KEY_D_PEDSTD_SB2, D_PEDSTD_SB2},
- {KEY_D_PEDSTD_DRIVE_STATE, D_PEDSTD_DRIVE_STATE},
- {KEY_D_STPDET_TIMESTAMP, D_STPDET_TIMESTAMP},
- {KEY_D_HOST_NO_MOT, D_HOST_NO_MOT},
- {KEY_D_ACCEL_BIAS, D_ACCEL_BIAS},
- {KEY_CFG_EXT_GYRO_BIAS_X, D_EXT_GYRO_BIAS_X},
- {KEY_CFG_EXT_GYRO_BIAS_Y, D_EXT_GYRO_BIAS_Y},
- {KEY_CFG_EXT_GYRO_BIAS_Z, D_EXT_GYRO_BIAS_Z},
- {KEY_CFG_PED_INT, CFG_PED_INT},
- {KEY_SMD_ENABLE, D_SMD_ENABLE},
- {KEY_SMD_ACCEL_THLD, D_SMD_MOT_THLD},
- {KEY_SMD_DELAY_THLD, D_SMD_DELAY_THLD},
- {KEY_SMD_DELAY2_THLD, D_SMD_DELAY2_THLD},
- {KEY_SMD_ENABLE_TESTPT1, SMD_TP1},
- {KEY_SMD_ENABLE_TESTPT2, SMD_TP2},
- {KEY_SMD_EXE_STATE, D_SMD_EXE_STATE},
- {KEY_SMD_DELAY_CNTR, D_SMD_DELAY_CNTR},
- {KEY_BM_ENABLE, D_BM_ENABLE},
- {KEY_BM_BATCH_CNTR, D_BM_BATCH_CNTR},
- {KEY_BM_BATCH_THLD, D_BM_BATCH_THLD},
- {KEY_BM_NUMWORD_TOFILL, D_BM_NUMWORD_TOFILL},
- {KEY_SO_DATA, D_SO_DATA},
- {KEY_P_INIT, D_P_INIT},
- {KEY_CFG_OUT_CPASS, CFG_OUT_CPASS},
- {KEY_CFG_OUT_PRESS, CFG_OUT_PRESS},
- {KEY_CFG_OUT_STEPDET, CFG_OUT_STEPDET},
- {KEY_CFG_3QUAT_ODR, D_ODR_S1},
- {KEY_CFG_6QUAT_ODR, D_ODR_S2},
- {KEY_CFG_PQUAT6_ODR, D_ODR_S3},
- {KEY_CFG_ACCL_ODR, D_ODR_S4},
- {KEY_CFG_GYRO_ODR, D_ODR_S5},
- {KEY_CFG_CPASS_ODR, D_ODR_S6},
- {KEY_CFG_PRESS_ODR, D_ODR_S7},
- {KEY_CFG_9QUAT_ODR, D_ODR_S8},
- {KEY_CFG_PQUAT9_ODR, D_ODR_S9},
- {KEY_ODR_CNTR_3QUAT, D_ODR_CNTR_S1},
- {KEY_ODR_CNTR_6QUAT, D_ODR_CNTR_S2},
- {KEY_ODR_CNTR_PQUAT, D_ODR_CNTR_S3},
- {KEY_ODR_CNTR_ACCL, D_ODR_CNTR_S4},
- {KEY_ODR_CNTR_GYRO, D_ODR_CNTR_S5},
- {KEY_ODR_CNTR_CPASS, D_ODR_CNTR_S6},
- {KEY_ODR_CNTR_PRESS, D_ODR_CNTR_S7},
- {KEY_ODR_CNTR_9QUAT, D_ODR_CNTR_S8},
- {KEY_ODR_CNTR_PQUAT9, D_ODR_CNTR_S9},
- {KEY_DMP_RUN_CNTR, D_DMP_RUN_CNTR},
- {KEY_DMP_LPQ0, D_FS_LPQ0},
- {KEY_DMP_LPQ1, D_FS_LPQ1},
- {KEY_DMP_LPQ2, D_FS_LPQ2},
- {KEY_DMP_LPQ3, D_FS_LPQ3},
- {KEY_DMP_Q0, D_FS_Q0},
- {KEY_DMP_Q1, D_FS_Q1},
- {KEY_DMP_Q2, D_FS_Q2},
- {KEY_DMP_Q3, D_FS_Q3},
- {KEY_DMP_9Q0, D_FS_9Q0},
- {KEY_DMP_9Q1, D_FS_9Q1},
- {KEY_DMP_9Q2, D_FS_9Q2},
- {KEY_DMP_9Q3, D_FS_9Q3},
- {KEY_CPASS_STATUS_CHK, D_CPASS_STATUS_CHK},
- {KEY_TEST_01, OUT_ACCL_DAT},
- {KEY_TEST_02, OUT_GYRO_DAT},
- {KEY_TEST_03, OUT_CPASS_DAT},
- {KEY_TEST_04, OUT_PRESS_DAT},
- {KEY_TEST_05, OUT_3QUAT_DAT},
- {KEY_TEST_06, OUT_6QUAT_DAT},
- {KEY_TEST_07, OUT_PQUAT_DAT}
-};
-#define NUM_LOCAL_KEYS (sizeof(dmpTConfig)/sizeof(dmpTConfig[0]))
-
-static struct tKeyLabel keys[NUM_KEYS];
-
-unsigned short inv_dmp_get_address(unsigned short key)
-{
- static int isSorted;
-
- if (!isSorted) {
- int kk;
- for (kk = 0; kk < NUM_KEYS; ++kk) {
- keys[kk].addr = 0xffff;
- keys[kk].key = kk;
- }
- for (kk = 0; kk < NUM_LOCAL_KEYS; ++kk)
- keys[dmpTConfig[kk].key].addr = dmpTConfig[kk].addr;
- isSorted = 1;
- }
- if (key >= NUM_KEYS) {
- pr_err("ERROR!! key not exist=%d!\n", key);
- return 0xffff;
- }
- if (0xffff == keys[key].addr)
- pr_err("ERROR!!key not local=%d!\n", key);
- return keys[key].addr;
-}
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/dmpKey.h b/drivers/iio/imu-aosp/inv_mpu6515/dmpKey.h
deleted file mode 100755
index 20b28478785..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/dmpKey.h
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * Copyright (C) 2012 Invensense, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#ifndef DMPKEY_H__
-#define DMPKEY_H__
-
-#define KEY_CFG_25 (0)
-#define KEY_CFG_24 (KEY_CFG_25 + 1)
-#define KEY_CFG_26 (KEY_CFG_24 + 1)
-#define KEY_CFG_27 (KEY_CFG_26 + 1)
-#define KEY_CFG_21 (KEY_CFG_27 + 1)
-#define KEY_CFG_20 (KEY_CFG_21 + 1)
-#define KEY_CFG_TAP4 (KEY_CFG_20 + 1)
-#define KEY_CFG_TAP5 (KEY_CFG_TAP4 + 1)
-#define KEY_CFG_TAP6 (KEY_CFG_TAP5 + 1)
-#define KEY_CFG_TAP7 (KEY_CFG_TAP6 + 1)
-#define KEY_CFG_TAP0 (KEY_CFG_TAP7 + 1)
-#define KEY_CFG_TAP1 (KEY_CFG_TAP0 + 1)
-#define KEY_CFG_TAP2 (KEY_CFG_TAP1 + 1)
-#define KEY_CFG_TAP3 (KEY_CFG_TAP2 + 1)
-#define KEY_CFG_TAP_QUANTIZE (KEY_CFG_TAP3 + 1)
-#define KEY_CFG_TAP_JERK (KEY_CFG_TAP_QUANTIZE + 1)
-#define KEY_CFG_DR_INT (KEY_CFG_TAP_JERK + 1)
-#define KEY_CFG_AUTH (KEY_CFG_DR_INT + 1)
-#define KEY_CFG_TAP_SAVE_ACCB (KEY_CFG_AUTH + 1)
-#define KEY_CFG_TAP_CLEAR_STICKY (KEY_CFG_TAP_SAVE_ACCB + 1)
-#define KEY_CFG_FIFO_ON_EVENT (KEY_CFG_TAP_CLEAR_STICKY + 1)
-#define KEY_FCFG_ACCEL_INPUT (KEY_CFG_FIFO_ON_EVENT + 1)
-#define KEY_FCFG_ACCEL_INIT (KEY_FCFG_ACCEL_INPUT + 1)
-#define KEY_CFG_23 (KEY_FCFG_ACCEL_INIT + 1)
-#define KEY_FCFG_1 (KEY_CFG_23 + 1)
-#define KEY_FCFG_3 (KEY_FCFG_1 + 1)
-#define KEY_FCFG_2 (KEY_FCFG_3 + 1)
-#define KEY_CFG_3D (KEY_FCFG_2 + 1)
-#define KEY_CFG_3B (KEY_CFG_3D + 1)
-#define KEY_CFG_3C (KEY_CFG_3B + 1)
-#define KEY_FCFG_5 (KEY_CFG_3C + 1)
-#define KEY_FCFG_4 (KEY_FCFG_5 + 1)
-#define KEY_FCFG_7 (KEY_FCFG_4 + 1)
-#define KEY_FCFG_FSCALE (KEY_FCFG_7 + 1)
-#define KEY_FCFG_AZ (KEY_FCFG_FSCALE + 1)
-#define KEY_FCFG_6 (KEY_FCFG_AZ + 1)
-#define KEY_FCFG_LSB4 (KEY_FCFG_6 + 1)
-#define KEY_CFG_12 (KEY_FCFG_LSB4 + 1)
-#define KEY_CFG_14 (KEY_CFG_12 + 1)
-#define KEY_CFG_15 (KEY_CFG_14 + 1)
-#define KEY_CFG_16 (KEY_CFG_15 + 1)
-#define KEY_CFG_18 (KEY_CFG_16 + 1)
-#define KEY_CFG_6 (KEY_CFG_18 + 1)
-#define KEY_CFG_7 (KEY_CFG_6 + 1)
-#define KEY_CFG_4 (KEY_CFG_7 + 1)
-#define KEY_CFG_5 (KEY_CFG_4 + 1)
-#define KEY_CFG_2 (KEY_CFG_5 + 1)
-#define KEY_CFG_3 (KEY_CFG_2 + 1)
-#define KEY_CFG_1 (KEY_CFG_3 + 1)
-#define KEY_CFG_EXTERNAL (KEY_CFG_1 + 1)
-#define KEY_CFG_8 (KEY_CFG_EXTERNAL + 1)
-#define KEY_CFG_9 (KEY_CFG_8 + 1)
-#define KEY_CFG_ORIENT_3 (KEY_CFG_9 + 1)
-#define KEY_CFG_ORIENT_2 (KEY_CFG_ORIENT_3 + 1)
-#define KEY_CFG_ORIENT_1 (KEY_CFG_ORIENT_2 + 1)
-#define KEY_CFG_GYRO_SOURCE (KEY_CFG_ORIENT_1 + 1)
-#define KEY_CFG_ORIENT_IRQ_1 (KEY_CFG_GYRO_SOURCE + 1)
-#define KEY_CFG_ORIENT_IRQ_2 (KEY_CFG_ORIENT_IRQ_1 + 1)
-#define KEY_CFG_ORIENT_IRQ_3 (KEY_CFG_ORIENT_IRQ_2 + 1)
-#define KEY_FCFG_MAG_VAL (KEY_CFG_ORIENT_IRQ_3 + 1)
-#define KEY_FCFG_MAG_MOV (KEY_FCFG_MAG_VAL + 1)
-#define KEY_CFG_LP_QUAT (KEY_FCFG_MAG_MOV + 1)
-#define KEY_CFG_GYRO_RAW_DATA (KEY_CFG_LP_QUAT + 1)
-#define KEY_CFG_EXT_GYRO_BIAS (KEY_CFG_GYRO_RAW_DATA + 1)
-#define KEY_CFG_EXT_GYRO_BIAS_X (KEY_CFG_EXT_GYRO_BIAS + 1)
-#define KEY_CFG_EXT_GYRO_BIAS_Y (KEY_CFG_EXT_GYRO_BIAS_X + 1)
-#define KEY_CFG_EXT_GYRO_BIAS_Z (KEY_CFG_EXT_GYRO_BIAS_Y + 1)
-#define KEY_bad_compass (KEY_CFG_EXT_GYRO_BIAS_Z + 1)
-#define KEY_COMPASS_CHG_SENSITIVITY (KEY_bad_compass + 1)
-#define KEY_CCS_HEADING_THLD (KEY_COMPASS_CHG_SENSITIVITY + 1)
-#define KEY_CCS_TIME_THLD (KEY_CCS_HEADING_THLD + 1)
-#define KEY_CCS_DOTP_THLD (KEY_CCS_TIME_THLD + 1)
-#define KEY_CCS_COMP_CNTR (KEY_CCS_DOTP_THLD + 1)
-#define KEY_CFG_NM_DET (KEY_CCS_COMP_CNTR + 1)
-#define KEY_SMD_ENABLE (KEY_CFG_NM_DET + 1)
-#define KEY_SMD_ACCEL_THLD (KEY_SMD_ENABLE + 1)
-#define KEY_SMD_DELAY_THLD (KEY_SMD_ACCEL_THLD + 1)
-#define KEY_SMD_DELAY2_THLD (KEY_SMD_DELAY_THLD + 1)
-#define KEY_SMD_ENABLE_TESTPT1 (KEY_SMD_DELAY2_THLD + 1)
-#define KEY_SMD_ENABLE_TESTPT2 (KEY_SMD_ENABLE_TESTPT1 + 1)
-#define KEY_SMD_EXE_STATE (KEY_SMD_ENABLE_TESTPT2 + 1)
-#define KEY_SMD_DELAY_CNTR (KEY_SMD_EXE_STATE + 1)
-
-#define KEY_BREAK (81)
-#if KEY_SMD_DELAY_CNTR != KEY_BREAK
-#error
-#endif
-
-/* MPU6050 keys */
-#define KEY_CFG_ACCEL_FILTER (KEY_BREAK + 1)
-#define KEY_CFG_MOTION_BIAS (KEY_CFG_ACCEL_FILTER + 1)
-#define KEY_TEMPLABEL (KEY_CFG_MOTION_BIAS + 1)
-
-#define KEY_D_0_22 (KEY_TEMPLABEL + 1)
-#define KEY_D_0_24 (KEY_D_0_22 + 1)
-#define KEY_D_0_36 (KEY_D_0_24 + 1)
-#define KEY_D_0_52 (KEY_D_0_36 + 1)
-#define KEY_D_0_96 (KEY_D_0_52 + 1)
-#define KEY_D_0_104 (KEY_D_0_96 + 1)
-#define KEY_D_0_108 (KEY_D_0_104 + 1)
-#define KEY_D_0_163 (KEY_D_0_108 + 1)
-#define KEY_D_0_188 (KEY_D_0_163 + 1)
-#define KEY_D_0_192 (KEY_D_0_188 + 1)
-#define KEY_D_0_224 (KEY_D_0_192 + 1)
-#define KEY_D_0_228 (KEY_D_0_224 + 1)
-#define KEY_D_0_232 (KEY_D_0_228 + 1)
-#define KEY_D_0_236 (KEY_D_0_232 + 1)
-
-#define KEY_DMP_PREVPTAT (KEY_D_0_236 + 1)
-#define KEY_D_1_2 (KEY_DMP_PREVPTAT + 1)
-#define KEY_D_1_4 (KEY_D_1_2 + 1)
-#define KEY_D_1_8 (KEY_D_1_4 + 1)
-#define KEY_D_1_10 (KEY_D_1_8 + 1)
-#define KEY_D_1_24 (KEY_D_1_10 + 1)
-#define KEY_D_1_28 (KEY_D_1_24 + 1)
-#define KEY_D_1_36 (KEY_D_1_28 + 1)
-#define KEY_D_1_40 (KEY_D_1_36 + 1)
-#define KEY_D_1_44 (KEY_D_1_40 + 1)
-#define KEY_D_1_72 (KEY_D_1_44 + 1)
-#define KEY_D_1_74 (KEY_D_1_72 + 1)
-#define KEY_D_1_79 (KEY_D_1_74 + 1)
-#define KEY_D_1_88 (KEY_D_1_79 + 1)
-#define KEY_D_1_90 (KEY_D_1_88 + 1)
-#define KEY_D_1_92 (KEY_D_1_90 + 1)
-#define KEY_D_1_96 (KEY_D_1_92 + 1)
-#define KEY_D_1_98 (KEY_D_1_96 + 1)
-#define KEY_D_1_100 (KEY_D_1_98 + 1)
-#define KEY_D_1_106 (KEY_D_1_100 + 1)
-#define KEY_D_1_108 (KEY_D_1_106 + 1)
-#define KEY_D_1_112 (KEY_D_1_108 + 1)
-#define KEY_D_1_128 (KEY_D_1_112 + 1)
-#define KEY_D_1_152 (KEY_D_1_128 + 1)
-#define KEY_D_1_160 (KEY_D_1_152 + 1)
-#define KEY_D_1_168 (KEY_D_1_160 + 1)
-#define KEY_D_1_175 (KEY_D_1_168 + 1)
-#define KEY_D_1_176 (KEY_D_1_175 + 1)
-#define KEY_D_1_178 (KEY_D_1_176 + 1)
-#define KEY_D_1_179 (KEY_D_1_178 + 1)
-#define KEY_D_1_218 (KEY_D_1_179 + 1)
-#define KEY_D_1_232 (KEY_D_1_218 + 1)
-#define KEY_D_1_236 (KEY_D_1_232 + 1)
-#define KEY_D_1_240 (KEY_D_1_236 + 1)
-#define KEY_D_1_244 (KEY_D_1_240 + 1)
-#define KEY_D_1_250 (KEY_D_1_244 + 1)
-#define KEY_D_1_252 (KEY_D_1_250 + 1)
-#define KEY_D_2_12 (KEY_D_1_252 + 1)
-#define KEY_D_2_96 (KEY_D_2_12 + 1)
-#define KEY_D_2_108 (KEY_D_2_96 + 1)
-#define KEY_D_2_208 (KEY_D_2_108 + 1)
-#define KEY_FLICK_MSG (KEY_D_2_208 + 1)
-#define KEY_FLICK_COUNTER (KEY_FLICK_MSG + 1)
-#define KEY_FLICK_LOWER (KEY_FLICK_COUNTER + 1)
-#define KEY_CFG_FLICK_IN (KEY_FLICK_LOWER + 1)
-#define KEY_FLICK_UPPER (KEY_CFG_FLICK_IN + 1)
-#define KEY_CGNOTICE_INTR (KEY_FLICK_UPPER + 1)
-#define KEY_D_2_224 (KEY_CGNOTICE_INTR + 1)
-#define KEY_D_2_244 (KEY_D_2_224 + 1)
-#define KEY_D_2_248 (KEY_D_2_244 + 1)
-#define KEY_D_2_252 (KEY_D_2_248 + 1)
-
-#define KEY_D_GYRO_BIAS_X (KEY_D_2_252 + 1)
-#define KEY_D_GYRO_BIAS_Y (KEY_D_GYRO_BIAS_X + 1)
-#define KEY_D_GYRO_BIAS_Z (KEY_D_GYRO_BIAS_Y + 1)
-#define KEY_D_ACC_BIAS_X (KEY_D_GYRO_BIAS_Z + 1)
-#define KEY_D_ACC_BIAS_Y (KEY_D_ACC_BIAS_X + 1)
-#define KEY_D_ACC_BIAS_Z (KEY_D_ACC_BIAS_Y + 1)
-#define KEY_D_GYRO_ENABLE (KEY_D_ACC_BIAS_Z + 1)
-#define KEY_D_ACCEL_ENABLE (KEY_D_GYRO_ENABLE + 1)
-#define KEY_D_QUAT_ENABLE (KEY_D_ACCEL_ENABLE + 1)
-#define KEY_D_OUTPUT_ENABLE (KEY_D_QUAT_ENABLE + 1)
-#define KEY_D_ACCEL_CNTR (KEY_D_OUTPUT_ENABLE + 1)
-#define KEY_D_GYRO_CNTR (KEY_D_ACCEL_CNTR + 1)
-#define KEY_D_QUAT0_CNTR (KEY_D_GYRO_CNTR + 1)
-#define KEY_D_QUAT1_CNTR (KEY_D_QUAT0_CNTR + 1)
-#define KEY_D_QUAT2_CNTR (KEY_D_QUAT1_CNTR + 1)
-#define KEY_D_CR_TIME_G (KEY_D_QUAT2_CNTR + 1)
-#define KEY_D_CR_TIME_A (KEY_D_CR_TIME_G + 1)
-#define KEY_D_CR_TIME_Q (KEY_D_CR_TIME_A + 1)
-#define KEY_D_CS_TAX (KEY_D_CR_TIME_Q + 1)
-#define KEY_D_CS_TAY (KEY_D_CS_TAX + 1)
-#define KEY_D_CS_TAZ (KEY_D_CS_TAY + 1)
-#define KEY_D_CS_TGX (KEY_D_CS_TAZ + 1)
-#define KEY_D_CS_TGY (KEY_D_CS_TGX + 1)
-#define KEY_D_CS_TGZ (KEY_D_CS_TGY + 1)
-#define KEY_D_CS_TQ0 (KEY_D_CS_TGZ + 1)
-#define KEY_D_CS_TQ1 (KEY_D_CS_TQ0 + 1)
-#define KEY_D_CS_TQ2 (KEY_D_CS_TQ1 + 1)
-#define KEY_D_CS_TQ3 (KEY_D_CS_TQ2 + 1)
-
-/* Compass keys */
-#define KEY_CPASS_GAIN (KEY_D_CS_TQ3 + 1)
-#define KEY_CPASS_BIAS_X (KEY_CPASS_GAIN + 1)
-#define KEY_CPASS_BIAS_Y (KEY_CPASS_BIAS_X + 1)
-#define KEY_CPASS_BIAS_Z (KEY_CPASS_BIAS_Y + 1)
-#define KEY_CPASS_MTX_00 (KEY_CPASS_BIAS_Z + 1)
-#define KEY_CPASS_MTX_01 (KEY_CPASS_MTX_00 + 1)
-#define KEY_CPASS_MTX_02 (KEY_CPASS_MTX_01 + 1)
-#define KEY_CPASS_MTX_10 (KEY_CPASS_MTX_02 + 1)
-#define KEY_CPASS_MTX_11 (KEY_CPASS_MTX_10 + 1)
-#define KEY_CPASS_MTX_12 (KEY_CPASS_MTX_11 + 1)
-#define KEY_CPASS_MTX_20 (KEY_CPASS_MTX_12 + 1)
-#define KEY_CPASS_MTX_21 (KEY_CPASS_MTX_20 + 1)
-#define KEY_CPASS_MTX_22 (KEY_CPASS_MTX_21 + 1)
-#define KEY_CPASS_STATUS_CHK (KEY_CPASS_MTX_22 + 1)
-/* Tap Keys */
-#define KEY_DMP_TAP_GATE (KEY_CPASS_STATUS_CHK + 1)
-#define KEY_DMP_TAPW_MIN (KEY_DMP_TAP_GATE + 1)
-#define KEY_DMP_TAP_THR_Z (KEY_DMP_TAPW_MIN + 1)
-#define KEY_DMP_TAP_PREV_JERK_Z (KEY_DMP_TAP_THR_Z + 1)
-#define KEY_DMP_TAP_MIN_TAPS (KEY_DMP_TAP_PREV_JERK_Z + 1)
-#define KEY_DMP_TAP_NEXT_TAP_THRES (KEY_DMP_TAP_MIN_TAPS + 1)
-#define KEY_DMP_TAP_SHAKE_REJECT (KEY_DMP_TAP_NEXT_TAP_THRES + 1)
-#define KEY_DMP_TAP_SHAKE_COUNT_MAX (KEY_DMP_TAP_SHAKE_REJECT + 1)
-#define KEY_DMP_TAP_SHAKE_TIMEOUT_MAX (KEY_DMP_TAP_SHAKE_COUNT_MAX + 1)
-#define KEY_DMP_TAP_DIRECTION (KEY_DMP_TAP_SHAKE_TIMEOUT_MAX + 1)
-#define KEY_DMP_TAP_COUNT (KEY_DMP_TAP_DIRECTION + 1)
-/* Gesture Keys */
-#define KEY_DMP_SH_TH_Y (KEY_DMP_TAP_COUNT + 1)
-#define KEY_DMP_SH_TH_X (KEY_DMP_SH_TH_Y + 1)
-#define KEY_DMP_SH_TH_Z (KEY_DMP_SH_TH_X + 1)
-#define KEY_DMP_ORIENT (KEY_DMP_SH_TH_Z + 1)
-#define KEY_D_ACT0 (KEY_DMP_ORIENT + 1)
-#define KEY_D_ACSX (KEY_D_ACT0 + 1)
-#define KEY_D_ACSY (KEY_D_ACSX + 1)
-#define KEY_D_ACSZ (KEY_D_ACSY + 1)
-
-#define KEY_CFG_DISPLAY_ORIENT_INT (KEY_D_ACSZ + 1)
-#define KEY_NO_ORIENT_INTERRUPT (KEY_CFG_DISPLAY_ORIENT_INT + 1)
-#define KEY_X_GRT_Y_TMP2 (KEY_NO_ORIENT_INTERRUPT + 1)
-
-/*Shake Keys */
-#define KEY_D_0_64 (KEY_X_GRT_Y_TMP2 + 1)
-#define KEY_D_2_4 (KEY_D_0_64 + 1)
-#define KEY_D_2_8 (KEY_D_2_4 + 1)
-#define KEY_D_2_48 (KEY_D_2_8 + 1)
-#define KEY_D_2_92 (KEY_D_2_48 + 1)
-#define KEY_D_2_94 (KEY_D_2_92 + 1)
-#define KEY_D_2_160 (KEY_D_2_94 + 1)
-#define KEY_D_3_180 (KEY_D_2_160 + 1)
-#define KEY_D_3_184 (KEY_D_3_180 + 1)
-#define KEY_D_3_188 (KEY_D_3_184 + 1)
-#define KEY_D_3_208 (KEY_D_3_188 + 1)
-#define KEY_D_3_240 (KEY_D_3_208 + 1)
-#define KEY_RETRACTION_1 (KEY_D_3_240 + 1)
-#define KEY_RETRACTION_2 (KEY_RETRACTION_1 + 1)
-#define KEY_RETRACTION_3 (KEY_RETRACTION_2 + 1)
-#define KEY_RETRACTION_4 (KEY_RETRACTION_3 + 1)
-#define KEY_CFG_SHAKE_INT (KEY_RETRACTION_4 + 1)
-
-/* Authenticate Keys */
-#define KEY_D_AUTH_OUT (KEY_CFG_SHAKE_INT + 1)
-#define KEY_D_AUTH_IN (KEY_D_AUTH_OUT + 1)
-#define KEY_D_AUTH_A (KEY_D_AUTH_IN + 1)
-#define KEY_D_AUTH_B (KEY_D_AUTH_A + 1)
-
-/* Pedometer standalone only keys */
-#define KEY_D_PEDSTD_BP_B (KEY_D_AUTH_B + 1)
-#define KEY_D_PEDSTD_HP_A (KEY_D_PEDSTD_BP_B + 1)
-#define KEY_D_PEDSTD_HP_B (KEY_D_PEDSTD_HP_A + 1)
-#define KEY_D_PEDSTD_BP_A4 (KEY_D_PEDSTD_HP_B + 1)
-#define KEY_D_PEDSTD_BP_A3 (KEY_D_PEDSTD_BP_A4 + 1)
-#define KEY_D_PEDSTD_BP_A2 (KEY_D_PEDSTD_BP_A3 + 1)
-#define KEY_D_PEDSTD_BP_A1 (KEY_D_PEDSTD_BP_A2 + 1)
-#define KEY_D_PEDSTD_INT_THRSH (KEY_D_PEDSTD_BP_A1 + 1)
-#define KEY_D_PEDSTD_CLIP (KEY_D_PEDSTD_INT_THRSH + 1)
-#define KEY_D_PEDSTD_SB (KEY_D_PEDSTD_CLIP + 1)
-#define KEY_D_PEDSTD_SB_TIME (KEY_D_PEDSTD_SB + 1)
-#define KEY_D_PEDSTD_PEAKTHRSH (KEY_D_PEDSTD_SB_TIME + 1)
-#define KEY_D_PEDSTD_TIML (KEY_D_PEDSTD_PEAKTHRSH + 1)
-#define KEY_D_PEDSTD_TIMH (KEY_D_PEDSTD_TIML + 1)
-#define KEY_D_PEDSTD_PEAK (KEY_D_PEDSTD_TIMH + 1)
-#define KEY_D_PEDSTD_TIMECTR (KEY_D_PEDSTD_PEAK + 1)
-#define KEY_D_PEDSTD_STEPCTR (KEY_D_PEDSTD_TIMECTR + 1)
-#define KEY_D_PEDSTD_STEPCTR2 (KEY_D_PEDSTD_STEPCTR + 1)
-#define KEY_D_PEDSTD_WALKTIME (KEY_D_PEDSTD_STEPCTR2 + 1)
-#define KEY_D_PEDSTD_DECI (KEY_D_PEDSTD_WALKTIME + 1)
-#define KEY_D_PEDSTD_SB2 (KEY_D_PEDSTD_DECI + 1)
-#define KEY_D_PEDSTD_DRIVE_STATE (KEY_D_PEDSTD_SB2 + 1)
-#define KEY_CFG_PED_INT (KEY_D_PEDSTD_DRIVE_STATE + 1)
-#define KEY_CFG_PED_ENABLE (KEY_CFG_PED_INT + 1)
-#define KEY_D_STPDET_TIMESTAMP (KEY_CFG_PED_ENABLE + 1)
-
-/*Host Based No Motion*/
-#define KEY_D_HOST_NO_MOT (KEY_D_STPDET_TIMESTAMP + 1)
-
-/*Host Based Accel Bias*/
-#define KEY_D_ACCEL_BIAS (KEY_D_HOST_NO_MOT + 1)
-
-/*Screen/Display Orientation Keys*/
-#define KEY_D_ORIENT_GAP (KEY_D_ACCEL_BIAS + 1)
-#define KEY_D_TILT0_H (KEY_D_ORIENT_GAP + 1)
-#define KEY_D_TILT0_L (KEY_D_TILT0_H + 1)
-#define KEY_D_TILT1_H (KEY_D_TILT0_L + 1)
-#define KEY_D_TILT1_L (KEY_D_TILT1_H + 1)
-#define KEY_D_TILT2_H (KEY_D_TILT1_L + 1)
-#define KEY_D_TILT2_L (KEY_D_TILT2_H + 1)
-#define KEY_D_TILT3_H (KEY_D_TILT2_L + 1)
-#define KEY_D_TILT3_L (KEY_D_TILT3_H + 1)
-
-#define KEY_STREAM_P_ACCEL_Z (KEY_D_TILT3_L + 1)
-
-/* Batch mode */
-#define KEY_BM_ENABLE (KEY_STREAM_P_ACCEL_Z + 1)
-#define KEY_BM_BATCH_THLD (KEY_BM_ENABLE + 1)
-#define KEY_BM_BATCH_CNTR (KEY_BM_BATCH_THLD + 1)
-#define KEY_BM_NUMWORD_TOFILL (KEY_BM_BATCH_CNTR + 1)
-
-/* Watermark */
-#define KEY_CFG_WATERMARK_H (KEY_BM_NUMWORD_TOFILL + 1)
-#define KEY_CFG_WATERMARK_L (KEY_CFG_WATERMARK_H + 1)
-
-/* FIFO output control */
-#define KEY_CFG_OUT_ACCL (KEY_CFG_WATERMARK_L + 1)
-#define KEY_CFG_OUT_GYRO (KEY_CFG_OUT_ACCL + 1)
-#define KEY_CFG_OUT_3QUAT (KEY_CFG_OUT_GYRO + 1)
-#define KEY_CFG_OUT_6QUAT (KEY_CFG_OUT_3QUAT + 1)
-#define KEY_CFG_OUT_9QUAT (KEY_CFG_OUT_6QUAT + 1)
-#define KEY_CFG_OUT_PQUAT (KEY_CFG_OUT_9QUAT + 1)
-#define KEY_CFG_OUT_PQUAT9 (KEY_CFG_OUT_PQUAT + 1)
-#define KEY_CFG_OUT_CPASS (KEY_CFG_OUT_PQUAT9 + 1)
-#define KEY_CFG_OUT_PRESS (KEY_CFG_OUT_CPASS + 1)
-#define KEY_CFG_OUT_STEPDET (KEY_CFG_OUT_PRESS + 1)
-#define KEY_CFG_FIFO_INT (KEY_CFG_OUT_STEPDET + 1)
-
-/* Ped Step detection */
-#define KEY_CFG_PEDSTEP_DET (KEY_CFG_FIFO_INT + 1)
-
-/* Screen Orientation data */
-#define KEY_SO_DATA (KEY_CFG_PEDSTEP_DET + 1)
-
-/* MPU for DMP Android K */
-#define KEY_P_INIT (KEY_SO_DATA + 1)
-#define KEY_P_HW_ID (KEY_P_INIT + 1)
-
-/* DMP running counter */
-#define KEY_DMP_RUN_CNTR (KEY_P_HW_ID + 1)
-
-/* Sensor's ODR */
-#define KEY_CFG_3QUAT_ODR (KEY_DMP_RUN_CNTR + 1)
-#define KEY_CFG_6QUAT_ODR (KEY_CFG_3QUAT_ODR + 1)
-#define KEY_CFG_9QUAT_ODR (KEY_CFG_6QUAT_ODR + 1)
-#define KEY_CFG_PQUAT6_ODR (KEY_CFG_9QUAT_ODR + 1)
-#define KEY_CFG_PQUAT9_ODR (KEY_CFG_PQUAT6_ODR + 1)
-#define KEY_CFG_ACCL_ODR (KEY_CFG_PQUAT9_ODR + 1)
-#define KEY_CFG_GYRO_ODR (KEY_CFG_ACCL_ODR + 1)
-#define KEY_CFG_CPASS_ODR (KEY_CFG_GYRO_ODR + 1)
-#define KEY_CFG_PRESS_ODR (KEY_CFG_CPASS_ODR + 1)
-
-#define KEY_ODR_CNTR_3QUAT (KEY_CFG_PRESS_ODR + 1)
-#define KEY_ODR_CNTR_6QUAT (KEY_ODR_CNTR_3QUAT + 1)
-#define KEY_ODR_CNTR_9QUAT (KEY_ODR_CNTR_6QUAT + 1)
-#define KEY_ODR_CNTR_PQUAT (KEY_ODR_CNTR_9QUAT + 1)
-#define KEY_ODR_CNTR_PQUAT9 (KEY_ODR_CNTR_PQUAT + 1)
-#define KEY_ODR_CNTR_ACCL (KEY_ODR_CNTR_PQUAT9 + 1)
-#define KEY_ODR_CNTR_GYRO (KEY_ODR_CNTR_ACCL + 1)
-#define KEY_ODR_CNTR_CPASS (KEY_ODR_CNTR_GYRO + 1)
-#define KEY_ODR_CNTR_PRESS (KEY_ODR_CNTR_CPASS + 1)
-
-/* DMP fusion LP-Quat */
-#define KEY_DMP_LPQ0 (KEY_ODR_CNTR_PRESS + 1)
-#define KEY_DMP_LPQ1 (KEY_DMP_LPQ0 + 1)
-#define KEY_DMP_LPQ2 (KEY_DMP_LPQ1 + 1)
-#define KEY_DMP_LPQ3 (KEY_DMP_LPQ2 + 1)
-
-/* DMP fusion 6-axis Quat */
-#define KEY_DMP_Q0 (KEY_DMP_LPQ3 + 1)
-#define KEY_DMP_Q1 (KEY_DMP_Q0 + 1)
-#define KEY_DMP_Q2 (KEY_DMP_Q1 + 1)
-#define KEY_DMP_Q3 (KEY_DMP_Q2 + 1)
-
-/* 9-axis fusion */
-#define KEY_CPASS_VALID (KEY_DMP_Q3 + 1)
-#define KEY_9AXIS_ACCURACY (KEY_CPASS_VALID + 1)
-#define KEY_DMP_9Q0 (KEY_9AXIS_ACCURACY + 1)
-#define KEY_DMP_9Q1 (KEY_DMP_9Q0 + 1)
-#define KEY_DMP_9Q2 (KEY_DMP_9Q1 + 1)
-#define KEY_DMP_9Q3 (KEY_DMP_9Q2 + 1)
-
-/* Test key */
-#define KEY_TEST_01 (KEY_DMP_9Q3 + 1)
-#define KEY_TEST_02 (KEY_TEST_01 + 1)
-#define KEY_TEST_03 (KEY_TEST_02 + 1)
-#define KEY_TEST_04 (KEY_TEST_03 + 1)
-#define KEY_TEST_05 (KEY_TEST_04 + 1)
-#define KEY_TEST_06 (KEY_TEST_05 + 1)
-#define KEY_TEST_07 (KEY_TEST_06 + 1)
-#define KEY_TEST_XX (KEY_TEST_07 + 1)
-
-#define NUM_KEYS (KEY_TEST_XX + 1)
-
-struct tKeyLabel {
- unsigned short key;
- unsigned short addr;
-};
-
-#define DINA0A 0x0a
-#define DINA22 0x22
-#define DINA42 0x42
-#define DINA5A 0x5a
-
-#define DINA06 0x06
-#define DINA0E 0x0e
-#define DINA16 0x16
-#define DINA1E 0x1e
-#define DINA26 0x26
-#define DINA2E 0x2e
-#define DINA36 0x36
-#define DINA3E 0x3e
-#define DINA46 0x46
-#define DINA4E 0x4e
-#define DINA56 0x56
-#define DINA5E 0x5e
-#define DINA66 0x66
-#define DINA6E 0x6e
-#define DINA76 0x76
-#define DINA7E 0x7e
-
-#define DINA00 0x00
-#define DINA08 0x08
-#define DINA10 0x10
-#define DINA18 0x18
-#define DINA20 0x20
-#define DINA28 0x28
-#define DINA30 0x30
-#define DINA38 0x38
-#define DINA40 0x40
-#define DINA48 0x48
-#define DINA50 0x50
-#define DINA58 0x58
-#define DINA60 0x60
-#define DINA68 0x68
-#define DINA70 0x70
-#define DINA78 0x78
-
-#define DINA04 0x04
-#define DINA0C 0x0c
-#define DINA14 0x14
-#define DINA1C 0x1C
-#define DINA24 0x24
-#define DINA2C 0x2c
-#define DINA34 0x34
-#define DINA3C 0x3c
-#define DINA44 0x44
-#define DINA4C 0x4c
-#define DINA54 0x54
-#define DINA5C 0x5c
-#define DINA64 0x64
-#define DINA6C 0x6c
-#define DINA74 0x74
-#define DINA7C 0x7c
-
-#define DINA01 0x01
-#define DINA09 0x09
-#define DINA11 0x11
-#define DINA19 0x19
-#define DINA21 0x21
-#define DINA29 0x29
-#define DINA31 0x31
-#define DINA39 0x39
-#define DINA41 0x41
-#define DINA49 0x49
-#define DINA51 0x51
-#define DINA59 0x59
-#define DINA61 0x61
-#define DINA69 0x69
-#define DINA71 0x71
-#define DINA79 0x79
-
-#define DINA25 0x25
-#define DINA2D 0x2d
-#define DINA35 0x35
-#define DINA3D 0x3d
-#define DINA4D 0x4d
-#define DINA55 0x55
-#define DINA5D 0x5D
-#define DINA6D 0x6d
-#define DINA75 0x75
-#define DINA7D 0x7d
-
-#define DINADC 0xdc
-#define DINAF2 0xf2
-#define DINAAB 0xab
-#define DINAAA 0xaa
-#define DINAF1 0xf1
-#define DINADF 0xdf
-#define DINADA 0xda
-#define DINAB1 0xb1
-#define DINAB9 0xb9
-#define DINAF3 0xf3
-#define DINA8B 0x8b
-#define DINAA3 0xa3
-#define DINA91 0x91
-#define DINAB6 0xb6
-#define DINAB4 0xb4
-
-#define DINC00 0x00
-#define DINC01 0x01
-#define DINC02 0x02
-#define DINC03 0x03
-#define DINC08 0x08
-#define DINC09 0x09
-#define DINC0A 0x0a
-#define DINC0B 0x0b
-#define DINC10 0x10
-#define DINC11 0x11
-#define DINC12 0x12
-#define DINC13 0x13
-#define DINC18 0x18
-#define DINC19 0x19
-#define DINC1A 0x1a
-#define DINC1B 0x1b
-
-#define DINC20 0x20
-#define DINC21 0x21
-#define DINC22 0x22
-#define DINC23 0x23
-#define DINC28 0x28
-#define DINC29 0x29
-#define DINC2A 0x2a
-#define DINC2B 0x2b
-#define DINC30 0x30
-#define DINC31 0x31
-#define DINC32 0x32
-#define DINC33 0x33
-#define DINC38 0x38
-#define DINC39 0x39
-#define DINC3A 0x3a
-#define DINC3B 0x3b
-
-#define DINC40 0x40
-#define DINC41 0x41
-#define DINC42 0x42
-#define DINC43 0x43
-#define DINC48 0x48
-#define DINC49 0x49
-#define DINC4A 0x4a
-#define DINC4B 0x4b
-#define DINC50 0x50
-#define DINC51 0x51
-#define DINC52 0x52
-#define DINC53 0x53
-#define DINC58 0x58
-#define DINC59 0x59
-#define DINC5A 0x5a
-#define DINC5B 0x5b
-
-#define DINC60 0x60
-#define DINC61 0x61
-#define DINC62 0x62
-#define DINC63 0x63
-#define DINC68 0x68
-#define DINC69 0x69
-#define DINC6A 0x6a
-#define DINC6B 0x6b
-#define DINC70 0x70
-#define DINC71 0x71
-#define DINC72 0x72
-#define DINC73 0x73
-#define DINC78 0x78
-#define DINC79 0x79
-#define DINC7A 0x7a
-#define DINC7B 0x7b
-#define DIND40 0x40
-#define DINA80 0x80
-#define DINA90 0x90
-#define DINAA0 0xa0
-#define DINAC9 0xc9
-#define DINACB 0xcb
-#define DINACD 0xcd
-#define DINACF 0xcf
-#define DINAC8 0xc8
-#define DINACA 0xca
-#define DINACC 0xcc
-#define DINACE 0xce
-#define DINAD8 0xd8
-#define DINADD 0xdd
-#define DINAF8 0xf0
-#define DINAFE 0xfe
-
-#define DINBF8 0xf8
-#define DINAC0 0xb0
-#define DINAC1 0xb1
-#define DINAC2 0xb4
-#define DINAC3 0xb5
-#define DINAC4 0xb8
-#define DINAC5 0xb9
-#define DINBC0 0xc0
-#define DINBC2 0xc2
-#define DINBC4 0xc4
-#define DINBC6 0xc6
-
-#endif
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/dmpmap.h b/drivers/iio/imu-aosp/inv_mpu6515/dmpmap.h
deleted file mode 100755
index 92936372224..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/dmpmap.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#ifndef DMPMAP_H
-#define DMPMAP_H
-
-#define DMP_PTAT 0
-#define DMP_XGYR 2
-#define DMP_YGYR 4
-#define DMP_ZGYR 6
-#define DMP_XACC 8
-#define DMP_YACC 10
-#define DMP_ZACC 12
-#define DMP_ADC1 14
-#define DMP_ADC2 16
-#define DMP_ADC3 18
-#define DMP_BIASUNC 20
-#define DMP_FIFORT 22
-#define DMP_INVGSFH 24
-#define DMP_INVGSFL 26
-#define DMP_1H 28
-#define DMP_1L 30
-#define DMP_BLPFSTCH 32
-#define DMP_BLPFSTCL 34
-#define DMP_BLPFSXH 36
-#define DMP_BLPFSXL 38
-#define DMP_BLPFSYH 40
-#define DMP_BLPFSYL 42
-#define DMP_BLPFSZH 44
-#define DMP_BLPFSZL 46
-#define DMP_BLPFMTC 48
-#define DMP_SMC 50
-#define DMP_BLPFMXH 52
-#define DMP_BLPFMXL 54
-#define DMP_BLPFMYH 56
-#define DMP_BLPFMYL 58
-#define DMP_BLPFMZH 60
-#define DMP_BLPFMZL 62
-#define DMP_BLPFC 64
-#define DMP_SMCTH 66
-#define DMP_TAP_DIRECTION 68
-#define DMP_TAP_COUNT 70
-#define DMP_TAP_GATE 72
-#define DMP_TAP_MIN_TAPS 74
-#define DMP_BERR2NH 76
-#define DMP_SMCINC 78
-#define DMP_TAP_SHAKE_REJECT 80
-#define DMP_ANGVBXL 82
-#define DMP_TAP_SHAKE_COUNT_MAX 84
-#define DMP_TAP_SHAKE_TIMEOUT_MAX 86
-#define DMP_TAP_THZ 88
-#define DMP_TAPW_MIN 90
-#define DMP_TAP_PREV_JERK_Z 92
-#define DMP_TAP_NEXT_TAP_THRES 94
-#define DMP_ATCH 96
-#define DMP_BIASUNCSF 98
-#define DMP_ACT2H 100
-#define DMP_ACT2L 102
-#define DMP_GSFH 104
-#define DMP_GSFL 106
-#define DMP_GH 108
-#define DMP_GL 110
-#define DMP_0_5H 112
-#define DMP_0_5L 114
-#define DMP_0_0H 116
-#define DMP_0_0L 118
-#define DMP_1_0H 120
-#define DMP_1_0L 122
-#define DMP_1_5H 124
-#define DMP_1_5L 126
-#define DMP_TMP1AH 128
-#define DMP_TMP1AL 130
-#define DMP_TMP2AH 132
-#define DMP_TMP2AL 134
-#define DMP_TMP3AH 136
-#define DMP_TMP3AL 138
-#define DMP_TMP4AH 140
-#define DMP_TMP4AL 142
-#define DMP_XACCW 144
-#define DMP_TMP5 146
-#define DMP_XACCB 148
-#define DMP_TMP8 150
-#define DMP_YACCB 152
-#define DMP_TMP9 154
-#define DMP_ZACCB 156
-#define DMP_TMP10 158
-#define DMP_DZH 160
-#define DMP_DZL 162
-#define DMP_XGCH 164
-#define DMP_XGCL 166
-#define DMP_YGCH 168
-#define DMP_YGCL 170
-#define DMP_ZGCH 172
-#define DMP_ZGCL 174
-#define DMP_YACCW 176
-#define DMP_TMP7 178
-#define DMP_AFB1H 180
-#define DMP_AFB1L 182
-#define DMP_AFB2H 184
-#define DMP_AFB2L 186
-#define DMP_MAGFBH 188
-#define DMP_MAGFBL 190
-#define DMP_QT1H 192
-#define DMP_QT1L 194
-#define DMP_QT2H 196
-#define DMP_QT2L 198
-#define DMP_QT3H 200
-#define DMP_QT3L 202
-#define DMP_QT4H 204
-#define DMP_QT4L 206
-#define DMP_CTRL1H 208
-#define DMP_CTRL1L 210
-#define DMP_CTRL2H 212
-#define DMP_CTRL2L 214
-#define DMP_CTRL3H 216
-#define DMP_CTRL3L 218
-#define DMP_CTRL4H 220
-#define DMP_CTRL4L 222
-#define DMP_CTRLS1 224
-#define DMP_CTRLSF1 226
-#define DMP_CTRLS2 228
-#define DMP_CTRLSF2 230
-#define DMP_CTRLS3 232
-#define DMP_CTRLSFNLL 234
-#define DMP_CTRLS4 236
-#define DMP_CTRLSFNL2 238
-#define DMP_CTRLSFNL 240
-#define DMP_TMP30 242
-#define DMP_CTRLSFJT 244
-#define DMP_TMP31 246
-#define DMP_TMP11 248
-#define DMP_CTRLSF2_2 250
-#define DMP_TMP12 252
-#define DMP_CTRLSF1_2 254
-#define DMP_PREVPTAT 256
-#define DMP_ACCZB 258
-#define DMP_ACCXB 264
-#define DMP_ACCYB 266
-#define DMP_1HB 272
-#define DMP_1LB 274
-#define DMP_0H 276
-#define DMP_0L 278
-#define DMP_ASR22H 280
-#define DMP_ASR22L 282
-#define DMP_ASR6H 284
-#define DMP_ASR6L 286
-#define DMP_TMP13 288
-#define DMP_TMP14 290
-#define DMP_FINTXH 292
-#define DMP_FINTXL 294
-#define DMP_FINTYH 296
-#define DMP_FINTYL 298
-#define DMP_FINTZH 300
-#define DMP_FINTZL 302
-#define DMP_TMP1BH 304
-#define DMP_TMP1BL 306
-#define DMP_TMP2BH 308
-#define DMP_TMP2BL 310
-#define DMP_TMP3BH 312
-#define DMP_TMP3BL 314
-#define DMP_TMP4BH 316
-#define DMP_TMP4BL 318
-#define DMP_STXG 320
-#define DMP_ZCTXG 322
-#define DMP_STYG 324
-#define DMP_ZCTYG 326
-#define DMP_STZG 328
-#define DMP_ZCTZG 330
-#define DMP_CTRLSFJT2 332
-#define DMP_CTRLSFJTCNT 334
-#define DMP_PVXG 336
-#define DMP_TMP15 338
-#define DMP_PVYG 340
-#define DMP_TMP16 342
-#define DMP_PVZG 344
-#define DMP_TMP17 346
-#define DMP_MNMFLAGH 352
-#define DMP_MNMFLAGL 354
-#define DMP_MNMTMH 356
-#define DMP_MNMTML 358
-#define DMP_MNMTMTHRH 360
-#define DMP_MNMTMTHRL 362
-#define DMP_MNMTHRH 364
-#define DMP_MNMTHRL 366
-#define DMP_ACCQD4H 368
-#define DMP_ACCQD4L 370
-#define DMP_ACCQD5H 372
-#define DMP_ACCQD5L 374
-#define DMP_ACCQD6H 376
-#define DMP_ACCQD6L 378
-#define DMP_ACCQD7H 380
-#define DMP_ACCQD7L 382
-#define DMP_ACCQD0H 384
-#define DMP_ACCQD0L 386
-#define DMP_ACCQD1H 388
-#define DMP_ACCQD1L 390
-#define DMP_ACCQD2H 392
-#define DMP_ACCQD2L 394
-#define DMP_ACCQD3H 396
-#define DMP_ACCQD3L 398
-#define DMP_XN2H 400
-#define DMP_XN2L 402
-#define DMP_XN1H 404
-#define DMP_XN1L 406
-#define DMP_YN2H 408
-#define DMP_YN2L 410
-#define DMP_YN1H 412
-#define DMP_YN1L 414
-#define DMP_YH 416
-#define DMP_YL 418
-#define DMP_B0H 420
-#define DMP_B0L 422
-#define DMP_A1H 424
-#define DMP_A1L 426
-#define DMP_A2H 428
-#define DMP_A2L 430
-#define DMP_SEM1 432
-#define DMP_FIFOCNT 434
-#define DMP_SH_TH_X 436
-#define DMP_PACKET 438
-#define DMP_SH_TH_Y 440
-#define DMP_FOOTER 442
-#define DMP_SH_TH_Z 444
-#define DMP_TEMP29 448
-#define DMP_TEMP30 450
-#define DMP_XACCB_PRE 452
-#define DMP_XACCB_PREL 454
-#define DMP_YACCB_PRE 456
-#define DMP_YACCB_PREL 458
-#define DMP_ZACCB_PRE 460
-#define DMP_ZACCB_PREL 462
-#define DMP_TMP22 464
-#define DMP_TAP_TIMER 466
-#define DMP_TAP_THX 468
-#define DMP_TAP_THY 472
-#define DMP_TMP25 480
-#define DMP_TMP26 482
-#define DMP_TMP27 484
-#define DMP_TMP28 486
-#define DMP_ORIENT 488
-#define DMP_THRSH 490
-#define DMP_ENDIANH 492
-#define DMP_ENDIANL 494
-#define DMP_BLPFNMTCH 496
-#define DMP_BLPFNMTCL 498
-#define DMP_BLPFNMXH 500
-#define DMP_BLPFNMXL 502
-#define DMP_BLPFNMYH 504
-#define DMP_BLPFNMYL 506
-#define DMP_BLPFNMZH 508
-#define DMP_BLPFNMZL 510
-
-#endif
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu3050_iio.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu3050_iio.c
deleted file mode 100755
index 1fc5ff98097..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu3050_iio.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "inv_mpu_iio.h"
-#define MPU3050_NACK_MIN_TIME (2 * 1000)
-#define MPU3050_NACK_MAX_TIME (3 * 1000)
-
-#define MPU3050_ONE_MPU_TIME 20
-#define MPU3050_BOGUS_ADDR 0x7F
-int __attribute__((weak)) inv_register_mpu3050_slave(struct inv_mpu_state *st)
-{
- return 0;
-}
-
-int set_3050_bypass(struct inv_mpu_state *st, bool enable)
-{
- struct inv_reg_map_s *reg;
- int result;
- u8 b;
-
- reg = &st->reg;
- result = inv_i2c_read(st, reg->user_ctrl, 1, &b);
- if (result)
- return result;
- if (((b & BIT_3050_AUX_IF_EN) == 0) && enable)
- return 0;
- if ((b & BIT_3050_AUX_IF_EN) && (enable == 0))
- return 0;
- b &= ~BIT_3050_AUX_IF_EN;
- if (!enable) {
- b |= BIT_3050_AUX_IF_EN;
- result = inv_i2c_single_write(st, reg->user_ctrl, b);
- return result;
- } else {
- /* Coming out of I2C is tricky due to several erratta. Do not
- * modify this algorithm
- */
- /*
- * 1) wait for the right time and send the command to change
- * the aux i2c slave address to an invalid address that will
- * get nack'ed
- *
- * 0x00 is broadcast. 0x7F is unlikely to be used by any aux.
- */
- result = inv_i2c_single_write(st, REG_3050_SLAVE_ADDR,
- MPU3050_BOGUS_ADDR);
- if (result)
- return result;
- /*
- * 2) wait enough time for a nack to occur, then go into
- * bypass mode:
- */
- usleep_range(MPU3050_NACK_MIN_TIME, MPU3050_NACK_MAX_TIME);
- result = inv_i2c_single_write(st, reg->user_ctrl, b);
- if (result)
- return result;
- /*
- * 3) wait for up to one MPU cycle then restore the slave
- * address
- */
- msleep(MPU3050_ONE_MPU_TIME);
-
- result = inv_i2c_single_write(st, REG_3050_SLAVE_ADDR,
- st->plat_data.secondary_i2c_addr);
- if (result)
- return result;
- result = inv_i2c_single_write(st, reg->user_ctrl, b);
- if (result)
- return result;
- usleep_range(MPU3050_NACK_MIN_TIME, MPU3050_NACK_MAX_TIME);
- }
- return 0;
-}
-
-void inv_setup_reg_mpu3050(struct inv_reg_map_s *reg)
-{
- reg->fifo_en = REG_3050_FIFO_EN;
- reg->sample_rate_div = REG_3050_SAMPLE_RATE_DIV;
- reg->lpf = REG_3050_LPF;
- reg->fifo_count_h = REG_3050_FIFO_COUNT_H;
- reg->fifo_r_w = REG_3050_FIFO_R_W;
- reg->user_ctrl = REG_3050_USER_CTRL;
- reg->pwr_mgmt_1 = REG_3050_PWR_MGMT_1;
- reg->raw_accel = REG_3050_AUX_XOUT_H;
- reg->temperature = REG_3050_TEMPERATURE;
- reg->int_enable = REG_3050_INT_ENABLE;
- reg->int_status = REG_3050_INT_STATUS;
-}
-
-int inv_switch_3050_gyro_engine(struct inv_mpu_state *st, bool en)
-{
- struct inv_reg_map_s *reg;
- u8 data, p;
- int result;
- reg = &st->reg;
- if (en) {
- data = INV_CLK_PLL;
- p = (BITS_3050_POWER1 | data);
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, p);
- if (result)
- return result;
- p = (BITS_3050_POWER2 | data);
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, p);
- if (result)
- return result;
- p = data;
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, p);
- msleep(SENSOR_UP_TIME);
- } else {
- p = BITS_3050_GYRO_STANDBY;
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, p);
- }
-
- return result;
-}
-
-int inv_switch_3050_accel_engine(struct inv_mpu_state *st, bool en)
-{
- int result;
- if (NULL == st->slave_accel)
- return -EPERM;
- if (en)
- result = st->slave_accel->resume(st);
- else
- result = st->slave_accel->suspend(st);
-
- return result;
-}
-
-/**
- * inv_init_config_mpu3050() - Initialize hardware, disable FIFO.
- * @st: Device driver instance.
- * Initial configuration:
- * FSR: +/- 2000DPS
- * DLPF: 42Hz
- * FIFO rate: 50Hz
- * Clock source: Gyro PLL
- */
-int inv_init_config_mpu3050(struct iio_dev *indio_dev)
-{
- struct inv_reg_map_s *reg;
- int result;
- u8 data;
- struct inv_mpu_state *st = iio_priv(indio_dev);
-
- if (st->chip_config.is_asleep)
- return -EPERM;
- /*reading AUX VDDIO register */
- result = inv_i2c_read(st, REG_3050_AUX_VDDIO, 1, &data);
- if (result)
- return result;
- data &= ~BIT_3050_VDDIO;
- if (st->plat_data.level_shifter)
- data |= BIT_3050_VDDIO;
- result = inv_i2c_single_write(st, REG_3050_AUX_VDDIO, data);
- if (result)
- return result;
-
- reg = &st->reg;
- /*2000dps full scale range*/
- result = inv_i2c_single_write(st, reg->lpf,
- (INV_FSR_2000DPS << GYRO_CONFIG_FSR_SHIFT)
- | INV_FILTER_42HZ);
- if (result)
- return result;
- st->chip_config.fsr = INV_FSR_2000DPS;
- st->chip_config.lpf = INV_FILTER_42HZ;
- st->chip_info.multi = 1;
- result = inv_i2c_single_write(st, reg->sample_rate_div,
- ONE_K_HZ/INIT_FIFO_RATE - 1);
- if (result)
- return result;
- st->chip_config.fifo_rate = INIT_FIFO_RATE;
- st->irq_dur_ns = INIT_DUR_TIME;
- st->chip_config.prog_start_addr = DMP_START_ADDR;
- if ((SECONDARY_SLAVE_TYPE_ACCEL == st->plat_data.sec_slave_type) &&
- st->slave_accel) {
- result = st->slave_accel->setup(st);
- if (result)
- return result;
- result = st->slave_accel->set_fs(st, INV_FS_02G);
- if (result)
- return result;
- result = st->slave_accel->set_lpf(st, INIT_FIFO_RATE);
- if (result)
- return result;
- }
-
- return 0;
-}
-
-/**
- * set_power_mpu3050() - set power of mpu3050.
- * @st: Device driver instance.
- * @power_on: on/off
- */
-int set_power_mpu3050(struct inv_mpu_state *st, bool power_on)
-{
- struct inv_reg_map_s *reg;
- u8 data, p;
- int result;
- reg = &st->reg;
- if (power_on) {
- data = 0;
- } else {
- if (st->slave_accel) {
- result = st->slave_accel->suspend(st);
- if (result)
- return result;
- }
- data = BIT_SLEEP;
- }
- if (st->chip_config.gyro_enable) {
- p = (BITS_3050_POWER1 | INV_CLK_PLL);
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, data | p);
- if (result)
- return result;
-
- p = (BITS_3050_POWER2 | INV_CLK_PLL);
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, data | p);
- if (result)
- return result;
-
- p = INV_CLK_PLL;
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, data | p);
- if (result)
- return result;
- } else {
- data |= (BITS_3050_GYRO_STANDBY | INV_CLK_INTERNAL);
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, data);
- if (result)
- return result;
- }
- if (power_on) {
- msleep(POWER_UP_TIME);
- if (st->slave_accel) {
- result = st->slave_accel->resume(st);
- if (result)
- return result;
- }
- }
- st->chip_config.is_asleep = !power_on;
-
- return 0;
-}
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_core.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_core.c
deleted file mode 100755
index 6f5a131dac5..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_core.c
+++ /dev/null
@@ -1,3135 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "inv_mpu_iio.h"
-#include "sysfs.h"
-#include "inv_test/inv_counters.h"
-
-#ifdef CONFIG_DTS_INV_MPU_IIO
-#include "inv_mpu_dts.h"
-#endif
-
-s64 get_time_ns(void)
-{
- struct timespec ts;
- ts = CURRENT_TIME;
- return timespec_to_ns(&ts);
-}
-
-/* This is for compatibility for power state. Should remove once HAL
- does not use power_state sysfs entry */
-static bool fake_asleep;
-
-static const struct inv_hw_s hw_info[INV_NUM_PARTS] = {
- {119, "ITG3500"},
- { 63, "MPU3050"},
- {117, "MPU6050"},
- {118, "MPU9150"},
- {128, "MPU6500"},
- {128, "MPU9250"},
- {128, "MPU9350"},
- {128, "MPU6515"},
-};
-
-static const u8 reg_gyro_offset[] = {REG_XG_OFFS_USRH,
- REG_XG_OFFS_USRH + 2,
- REG_XG_OFFS_USRH + 4};
-
-const u8 reg_6050_accel_offset[] = {REG_XA_OFFS_H,
- REG_XA_OFFS_H + 2,
- REG_XA_OFFS_H + 4};
-
-const u8 reg_6500_accel_offset[] = {REG_6500_XA_OFFS_H,
- REG_6500_YA_OFFS_H,
- REG_6500_ZA_OFFS_H};
-#ifdef CONFIG_INV_TESTING
-static bool suspend_state;
-static int inv_mpu_suspend(struct device *dev);
-static int inv_mpu_resume(struct device *dev);
-struct test_data_out {
- bool gyro;
- bool accel;
- bool compass;
- bool pressure;
- bool LPQ;
- bool SIXQ;
- bool PEDQ;
-};
-static struct test_data_out data_out_control;
-#endif
-
-static void inv_setup_reg(struct inv_reg_map_s *reg)
-{
- reg->sample_rate_div = REG_SAMPLE_RATE_DIV;
- reg->lpf = REG_CONFIG;
- reg->bank_sel = REG_BANK_SEL;
- reg->user_ctrl = REG_USER_CTRL;
- reg->fifo_en = REG_FIFO_EN;
- reg->gyro_config = REG_GYRO_CONFIG;
- reg->accel_config = REG_ACCEL_CONFIG;
- reg->fifo_count_h = REG_FIFO_COUNT_H;
- reg->fifo_r_w = REG_FIFO_R_W;
- reg->raw_accel = REG_RAW_ACCEL;
- reg->temperature = REG_TEMPERATURE;
- reg->int_enable = REG_INT_ENABLE;
- reg->int_status = REG_INT_STATUS;
- reg->pwr_mgmt_1 = REG_PWR_MGMT_1;
- reg->pwr_mgmt_2 = REG_PWR_MGMT_2;
- reg->mem_start_addr = REG_MEM_START_ADDR;
- reg->mem_r_w = REG_MEM_RW;
- reg->prgm_strt_addrh = REG_PRGM_STRT_ADDRH;
-};
-
-/**
- * inv_i2c_read_base() - Read one or more bytes from the device registers.
- * @st: Device driver instance.
- * @i2c_addr: i2c address of device.
- * @reg: First device register to be read from.
- * @length: Number of bytes to read.
- * @data: Data read from device.
- * NOTE:This is not re-implementation of i2c_smbus_read because i2c
- * address could be specified in this case. We could have two different
- * i2c address due to secondary i2c interface.
- */
-int inv_i2c_read_base(struct inv_mpu_state *st, u16 i2c_addr,
- u8 reg, u16 length, u8 *data)
-{
- struct i2c_msg msgs[2];
- int res;
-
- if (!data)
- return -EINVAL;
-
- msgs[0].addr = i2c_addr;
- msgs[0].flags = 0; /* write */
- msgs[0].buf = &reg;
- msgs[0].len = 1;
-
- msgs[1].addr = i2c_addr;
- msgs[1].flags = I2C_M_RD;
- msgs[1].buf = data;
- msgs[1].len = length;
-
- res = i2c_transfer(st->sl_handle, msgs, 2);
-
- if (res < 2) {
- if (res >= 0)
- res = -EIO;
- } else
- res = 0;
-
- INV_I2C_INC_MPUWRITE(3);
- INV_I2C_INC_MPUREAD(length);
-#if CONFIG_DYNAMIC_DEBUG
- {
- char *read = 0;
- pr_debug("%s RD%02X%02X%02X -> %s%s\n", st->hw->name,
- i2c_addr, reg, length,
- wr_pr_debug_begin(data, length, read),
- wr_pr_debug_end(read));
- }
-#endif
- return res;
-}
-
-/**
- * inv_i2c_single_write_base() - Write a byte to a device register.
- * @st: Device driver instance.
- * @i2c_addr: I2C address of the device.
- * @reg: Device register to be written to.
- * @data: Byte to write to device.
- * NOTE:This is not re-implementation of i2c_smbus_write because i2c
- * address could be specified in this case. We could have two different
- * i2c address due to secondary i2c interface.
- */
-int inv_i2c_single_write_base(struct inv_mpu_state *st,
- u16 i2c_addr, u8 reg, u8 data)
-{
- u8 tmp[2];
- struct i2c_msg msg;
- int res;
- tmp[0] = reg;
- tmp[1] = data;
-
- msg.addr = i2c_addr;
- msg.flags = 0; /* write */
- msg.buf = tmp;
- msg.len = 2;
-
- pr_debug("%s WR%02X%02X%02X\n", st->hw->name, i2c_addr, reg, data);
- INV_I2C_INC_MPUWRITE(3);
-
- res = i2c_transfer(st->sl_handle, &msg, 1);
- if (res < 1) {
- if (res == 0)
- res = -EIO;
- return res;
- } else
- return 0;
-}
-
-static int inv_switch_engine(struct inv_mpu_state *st, bool en, u32 mask)
-{
- struct inv_reg_map_s *reg;
- u8 data, mgmt_1;
- int result;
-
- reg = &st->reg;
- /* Only when gyro is on, can
- clock source be switched to gyro. Otherwise, it must be set to
- internal clock */
- if (BIT_PWR_GYRO_STBY == mask) {
- result = inv_i2c_read(st, reg->pwr_mgmt_1, 1, &mgmt_1);
- if (result)
- return result;
-
- mgmt_1 &= ~BIT_CLK_MASK;
- }
-
- if ((BIT_PWR_GYRO_STBY == mask) && (!en)) {
- /* turning off gyro requires switch to internal clock first.
- Then turn off gyro engine */
- mgmt_1 |= INV_CLK_INTERNAL;
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1,
- mgmt_1);
- if (result)
- return result;
- }
-
- result = inv_i2c_read(st, reg->pwr_mgmt_2, 1, &data);
- if (result)
- return result;
- if (en)
- data &= (~mask);
- else
- data |= mask;
- result = inv_i2c_single_write(st, reg->pwr_mgmt_2, data);
- if (result)
- return result;
-
- if ((BIT_PWR_GYRO_STBY == mask) && en) {
- /* only gyro on needs sensor up time */
- msleep(SENSOR_UP_TIME);
- /* after gyro is on & stable, switch internal clock to PLL */
- mgmt_1 |= INV_CLK_PLL;
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1,
- mgmt_1);
- if (result)
- return result;
- }
- if ((BIT_PWR_ACCEL_STBY == mask) && en)
- msleep(REG_UP_TIME);
-
- return 0;
-}
-
-/*
- * inv_lpa_freq() - store current low power frequency setting.
- */
-static int inv_lpa_freq(struct inv_mpu_state *st, int lpa_freq)
-{
- unsigned long result;
- u8 d;
- /* 2, 4, 6, 7 corresponds to 0.98, 3.91, 15.63, 31.25 */
- const u8 mpu6500_lpa_mapping[] = {2, 4, 6, 7};
-
- if (lpa_freq > MAX_LPA_FREQ_PARAM)
- return -EINVAL;
-
- if (INV_MPU6500 == st->chip_type) {
- d = mpu6500_lpa_mapping[lpa_freq];
- result = inv_i2c_single_write(st, REG_6500_LP_ACCEL_ODR, d);
- if (result)
- return result;
- }
- st->chip_config.lpa_freq = lpa_freq;
-
- return 0;
-}
-
-static int set_power_itg(struct inv_mpu_state *st, bool power_on)
-{
- struct inv_reg_map_s *reg;
- u8 data;
- int result;
-
- if ((!power_on) == st->chip_config.is_asleep)
- return 0;
- reg = &st->reg;
- if (power_on)
- data = 0;
- else
- data = BIT_SLEEP;
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, data);
- if (result)
- return result;
-
- if (power_on)
- msleep(REG_UP_TIME);
-
- st->chip_config.is_asleep = !power_on;
-
- return 0;
-}
-
-/**
- * inv_init_config() - Initialize hardware, disable FIFO.
- * @indio_dev: Device driver instance.
- * Initial configuration:
- * FSR: +/- 2000DPS
- * DLPF: 42Hz
- * FIFO rate: 50Hz
- */
-static int inv_init_config(struct iio_dev *indio_dev)
-{
- struct inv_reg_map_s *reg;
- int result, i;
- struct inv_mpu_state *st = iio_priv(indio_dev);
- const u8 *ch;
- u8 d[2];
-
- reg = &st->reg;
-
- result = inv_i2c_single_write(st, reg->gyro_config,
- INV_FSR_2000DPS << GYRO_CONFIG_FSR_SHIFT);
- if (result)
- return result;
-
- st->chip_config.fsr = INV_FSR_2000DPS;
-
- result = inv_i2c_single_write(st, reg->lpf, INV_FILTER_42HZ);
- if (result)
- return result;
- st->chip_config.lpf = INV_FILTER_42HZ;
-
- result = inv_i2c_single_write(st, reg->sample_rate_div,
- ONE_K_HZ / INIT_FIFO_RATE - 1);
- if (result)
- return result;
- st->chip_config.fifo_rate = INIT_FIFO_RATE;
- st->irq_dur_ns = INIT_DUR_TIME;
- st->chip_config.prog_start_addr = DMP_START_ADDR;
- if (INV_MPU6050 == st->chip_type)
- st->self_test.samples = INIT_ST_MPU6050_SAMPLES;
- else
- st->self_test.samples = INIT_ST_SAMPLES;
- st->self_test.threshold = INIT_ST_THRESHOLD;
- st->batch.wake_fifo_on = true;
- st->suspend_state = false;
- if (INV_ITG3500 != st->chip_type) {
- st->chip_config.accel_fs = INV_FS_02G;
- result = inv_i2c_single_write(st, reg->accel_config,
- (INV_FS_02G << ACCEL_CONFIG_FSR_SHIFT));
- if (result)
- return result;
- st->tap.time = INIT_TAP_TIME;
- st->tap.thresh = INIT_TAP_THRESHOLD;
- st->tap.min_count = INIT_TAP_MIN_COUNT;
- st->sample_divider = INIT_SAMPLE_DIVIDER;
- st->smd.threshold = MPU_INIT_SMD_THLD;
- st->smd.delay = MPU_INIT_SMD_DELAY_THLD;
- st->smd.delay2 = MPU_INIT_SMD_DELAY2_THLD;
- st->ped.int_thresh = INIT_PED_INT_THRESH;
- st->ped.step_thresh = INIT_PED_THRESH;
- st->sensor[SENSOR_STEP].rate = MAX_DMP_OUTPUT_RATE;
-
- result = inv_i2c_single_write(st, REG_ACCEL_MOT_DUR,
- INIT_MOT_DUR);
- if (result)
- return result;
- st->mot_int.mot_dur = INIT_MOT_DUR;
-
- result = inv_i2c_single_write(st, REG_ACCEL_MOT_THR,
- INIT_MOT_THR);
- if (result)
- return result;
- st->mot_int.mot_thr = INIT_MOT_THR;
-
- for (i = 0; i < 3; i++) {
- result = inv_i2c_read(st, reg_gyro_offset[i], 2, d);
- if (result)
- return result;
- st->rom_gyro_offset[i] =
- (short)be16_to_cpup((__be16 *)(d));
- st->input_gyro_offset[i] = 0;
- st->input_gyro_dmp_bias[i] = 0;
- }
- if (INV_MPU6050 == st->chip_type)
- ch = reg_6050_accel_offset;
- else
- ch = reg_6500_accel_offset;
- for (i = 0; i < 3; i++) {
- result = inv_i2c_read(st, ch[i], 2, d);
- if (result)
- return result;
- st->rom_accel_offset[i] =
- (short)be16_to_cpup((__be16 *)(d));
- st->input_accel_offset[i] = 0;
- st->input_accel_dmp_bias[i] = 0;
- }
- st->ped.step = 0;
- st->ped.time = 0;
- }
-
- return 0;
-}
-
-/*
- * inv_write_fsr() - Configure the gyro's scale range.
- */
-static int inv_write_fsr(struct inv_mpu_state *st, int fsr)
-{
- struct inv_reg_map_s *reg;
- int result;
-
- reg = &st->reg;
- if ((fsr < 0) || (fsr > MAX_GYRO_FS_PARAM))
- return -EINVAL;
- if (fsr == st->chip_config.fsr)
- return 0;
-
- if (INV_MPU3050 == st->chip_type)
- result = inv_i2c_single_write(st, reg->lpf,
- (fsr << GYRO_CONFIG_FSR_SHIFT) | st->chip_config.lpf);
- else
- result = inv_i2c_single_write(st, reg->gyro_config,
- fsr << GYRO_CONFIG_FSR_SHIFT);
-
- if (result)
- return result;
- st->chip_config.fsr = fsr;
-
- return 0;
-}
-
-/*
- * inv_write_accel_fs() - Configure the accelerometer's scale range.
- */
-static int inv_write_accel_fs(struct inv_mpu_state *st, int fs)
-{
- int result;
- struct inv_reg_map_s *reg;
-
- reg = &st->reg;
- if (fs < 0 || fs > MAX_ACCEL_FS_PARAM)
- return -EINVAL;
- if (fs == st->chip_config.accel_fs)
- return 0;
- if (INV_MPU3050 == st->chip_type)
- result = st->slave_accel->set_fs(st, fs);
- else
- result = inv_i2c_single_write(st, reg->accel_config,
- (fs << ACCEL_CONFIG_FSR_SHIFT));
- if (result)
- return result;
-
- st->chip_config.accel_fs = fs;
-
- return 0;
-}
-
-static int inv_set_offset_reg(struct inv_mpu_state *st, int reg, int val)
-{
- int result;
- u8 d;
-
- d = ((val >> 8) & 0xff);
- result = inv_i2c_single_write(st, reg, d);
- if (result)
- return result;
-
- d = (val & 0xff);
- result = inv_i2c_single_write(st, reg + 1, d);
-
- return result;
-}
-
-int inv_reset_offset_reg(struct inv_mpu_state *st, bool en)
-{
- const u8 *ch;
- int i, result;
- s16 gyro[3], accel[3];
-
- if (en) {
- for (i = 0; i < 3; i++) {
- gyro[i] = st->rom_gyro_offset[i];
- accel[i] = st->rom_accel_offset[i];
- }
- } else {
- for (i = 0; i < 3; i++) {
- gyro[i] = st->rom_gyro_offset[i] +
- st->input_gyro_offset[i];
- accel[i] = st->rom_accel_offset[i] +
- (st->input_accel_offset[i] << 1);
- }
- }
- if (INV_MPU6050 == st->chip_type)
- ch = reg_6050_accel_offset;
- else
- ch = reg_6500_accel_offset;
-
- for (i = 0; i < 3; i++) {
- result = inv_set_offset_reg(st, reg_gyro_offset[i], gyro[i]);
- if (result)
- return result;
- result = inv_set_offset_reg(st, ch[i], accel[i]);
- if (result)
- return result;
- }
-
- return 0;
-}
-/*
- * inv_fifo_rate_store() - Set fifo rate.
- */
-static int inv_fifo_rate_store(struct inv_mpu_state *st, int fifo_rate)
-{
- if ((fifo_rate < MIN_FIFO_RATE) || (fifo_rate > MAX_FIFO_RATE))
- return -EINVAL;
- if (fifo_rate == st->chip_config.fifo_rate)
- return 0;
-
- st->irq_dur_ns = NSEC_PER_SEC / fifo_rate;
- st->chip_config.fifo_rate = fifo_rate;
-
- return 0;
-}
-
-/*
- * inv_reg_dump_show() - Register dump for testing.
- */
-static ssize_t inv_reg_dump_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- int ii;
- char data;
- ssize_t bytes_printed = 0;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
-
- mutex_lock(&indio_dev->mlock);
- for (ii = 0; ii < st->hw->num_reg; ii++) {
- /* don't read fifo r/w register */
- if (ii == st->reg.fifo_r_w)
- data = 0;
- else
- inv_i2c_read(st, ii, 1, &data);
- bytes_printed += sprintf(buf + bytes_printed, "%#2x: %#2x\n",
- ii, data);
- }
- mutex_unlock(&indio_dev->mlock);
-
- return bytes_printed;
-}
-
-int write_be32_key_to_mem(struct inv_mpu_state *st,
- u32 data, int key)
-{
- cpu_to_be32s(&data);
- return mem_w_key(key, sizeof(data), (u8 *)&data);
-}
-
-int inv_write_2bytes(struct inv_mpu_state *st, int k, int data)
-{
- u8 d[2];
-
- if (data < 0 || data > USHRT_MAX)
- return -EINVAL;
-
- d[0] = (u8)((data >> 8) & 0xff);
- d[1] = (u8)(data & 0xff);
-
- return mem_w_key(k, ARRAY_SIZE(d), d);
-}
-
-static ssize_t _dmp_bias_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int result, data, tmp;
-
- if (!st->chip_config.firmware_loaded)
- return -EINVAL;
-
- if (!st->chip_config.enable) {
- result = st->set_power_state(st, true);
- if (result)
- return result;
- }
-
- result = kstrtoint(buf, 10, &data);
- if (result)
- goto dmp_bias_store_fail;
- switch (this_attr->address) {
- case ATTR_DMP_ACCEL_X_DMP_BIAS:
- tmp = st->input_accel_dmp_bias[0];
- st->input_accel_dmp_bias[0] = data;
- result = inv_set_accel_bias_dmp(st);
- if (result)
- st->input_accel_dmp_bias[0] = tmp;
- break;
- case ATTR_DMP_ACCEL_Y_DMP_BIAS:
- tmp = st->input_accel_dmp_bias[1];
- st->input_accel_dmp_bias[1] = data;
- result = inv_set_accel_bias_dmp(st);
- if (result)
- st->input_accel_dmp_bias[1] = tmp;
- break;
- case ATTR_DMP_ACCEL_Z_DMP_BIAS:
- tmp = st->input_accel_dmp_bias[2];
- st->input_accel_dmp_bias[2] = data;
- result = inv_set_accel_bias_dmp(st);
- if (result)
- st->input_accel_dmp_bias[2] = tmp;
- break;
- case ATTR_DMP_GYRO_X_DMP_BIAS:
- result = write_be32_key_to_mem(st, data,
- KEY_CFG_EXT_GYRO_BIAS_X);
- if (result)
- goto dmp_bias_store_fail;
- st->input_gyro_dmp_bias[0] = data;
- break;
- case ATTR_DMP_GYRO_Y_DMP_BIAS:
- result = write_be32_key_to_mem(st, data,
- KEY_CFG_EXT_GYRO_BIAS_Y);
- if (result)
- goto dmp_bias_store_fail;
- st->input_gyro_dmp_bias[1] = data;
- break;
- case ATTR_DMP_GYRO_Z_DMP_BIAS:
- result = write_be32_key_to_mem(st, data,
- KEY_CFG_EXT_GYRO_BIAS_Z);
- if (result)
- goto dmp_bias_store_fail;
- st->input_gyro_dmp_bias[2] = data;
- break;
- default:
- break;
- }
-
-dmp_bias_store_fail:
- if (!st->chip_config.enable)
- result |= st->set_power_state(st, false);
- if (result)
- return result;
-
- return count;
-}
-
-static ssize_t inv_dmp_bias_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- int result;
-
- mutex_lock(&indio_dev->mlock);
- result = _dmp_bias_store(dev, attr, buf, count);
- mutex_unlock(&indio_dev->mlock);
-
- return result;
-}
-
-static ssize_t _dmp_attr_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int result, data;
-
- if (st->chip_config.enable)
- return -EBUSY;
- result = kstrtoint(buf, 10, &data);
- if (result)
- return -EINVAL;
- switch (this_attr->address) {
- /* power of chip is not turned on */
- case ATTR_DMP_ON:
- st->chip_config.dmp_on = !!data;
- break;
- case ATTR_DMP_INT_ON:
- st->chip_config.dmp_int_on = !!data;
- break;
- case ATTR_DMP_EVENT_INT_ON:
- st->chip_config.dmp_event_int_on = !!data;
- break;
- case ATTR_DMP_STEP_INDICATOR_ON:
- st->chip_config.step_indicator_on = !!data;
- break;
- case ATTR_DMP_BATCHMODE_TIMEOUT:
- if (data < 0 || data > INT_MAX)
- return -EINVAL;
- st->batch.timeout = data;
- break;
- case ATTR_DMP_BATCHMODE_WAKE_FIFO_FULL:
- st->batch.wake_fifo_on = !!data;
- st->batch.overflow_on = 0;
- break;
- case ATTR_DMP_SIX_Q_ON:
- st->sensor[SENSOR_SIXQ].on = !!data;
- break;
- case ATTR_DMP_SIX_Q_RATE:
- if (data > MPU_DEFAULT_DMP_FREQ || data < 0)
- return -EINVAL;
- st->sensor[SENSOR_SIXQ].rate = data;
- st->sensor[SENSOR_SIXQ].dur = MPU_DEFAULT_DMP_FREQ / data;
- st->sensor[SENSOR_SIXQ].dur *= DMP_INTERVAL_INIT;
- break;
- case ATTR_DMP_LPQ_ON:
- st->sensor[SENSOR_LPQ].on = !!data;
- break;
- case ATTR_DMP_LPQ_RATE:
- if (data > MPU_DEFAULT_DMP_FREQ || data < 0)
- return -EINVAL;
- st->sensor[SENSOR_LPQ].rate = data;
- st->sensor[SENSOR_LPQ].dur = MPU_DEFAULT_DMP_FREQ / data;
- st->sensor[SENSOR_LPQ].dur *= DMP_INTERVAL_INIT;
- break;
- case ATTR_DMP_PED_Q_ON:
- st->sensor[SENSOR_PEDQ].on = !!data;
- break;
- case ATTR_DMP_PED_Q_RATE:
- if (data > MPU_DEFAULT_DMP_FREQ || data < 0)
- return -EINVAL;
- st->sensor[SENSOR_PEDQ].rate = data;
- st->sensor[SENSOR_PEDQ].dur = MPU_DEFAULT_DMP_FREQ / data;
- st->sensor[SENSOR_PEDQ].dur *= DMP_INTERVAL_INIT;
- break;
- case ATTR_DMP_STEP_DETECTOR_ON:
- st->sensor[SENSOR_STEP].on = !!data;
- break;
- default:
- return -EINVAL;
- }
-
- return count;
-}
-
-/*
- * inv_dmp_attr_store() - calling this function will store DMP attributes
- */
-static ssize_t inv_dmp_attr_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- int result;
-
- mutex_lock(&indio_dev->mlock);
- result = _dmp_attr_store(dev, attr, buf, count);
- mutex_unlock(&indio_dev->mlock);
-
- return result;
-}
-
-static ssize_t _dmp_mem_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int result, data;
-
- if (st->chip_config.enable)
- return -EBUSY;
- if (!st->chip_config.firmware_loaded)
- return -EINVAL;
- result = st->set_power_state(st, true);
- if (result)
- return result;
-
- result = kstrtoint(buf, 10, &data);
- if (result)
- goto dmp_mem_store_fail;
- switch (this_attr->address) {
- case ATTR_DMP_PED_INT_ON:
- result = inv_enable_pedometer_interrupt(st, !!data);
- if (result)
- goto dmp_mem_store_fail;
- st->ped.int_on = !!data;
- break;
- case ATTR_DMP_PED_ON:
- {
- result = inv_enable_pedometer(st, !!data);
- if (result)
- goto dmp_mem_store_fail;
- st->ped.on = !!data;
- break;
- }
- case ATTR_DMP_PED_STEP_THRESH:
- {
- result = inv_write_2bytes(st, KEY_D_PEDSTD_SB, data);
- if (result)
- goto dmp_mem_store_fail;
- st->ped.step_thresh = data;
- break;
- }
- case ATTR_DMP_PED_INT_THRESH:
- {
- result = inv_write_2bytes(st, KEY_D_PEDSTD_SB2, data);
- if (result)
- goto dmp_mem_store_fail;
- st->ped.int_thresh = data;
- break;
- }
- case ATTR_DMP_SMD_ENABLE:
- result = inv_write_2bytes(st, KEY_SMD_ENABLE, !!data);
- if (result)
- goto dmp_mem_store_fail;
- st->chip_config.smd_enable = !!data;
- break;
- case ATTR_DMP_SMD_THLD:
- if (data < 0 || data > SHRT_MAX)
- goto dmp_mem_store_fail;
- result = write_be32_key_to_mem(st, data << 16,
- KEY_SMD_ACCEL_THLD);
- if (result)
- goto dmp_mem_store_fail;
- st->smd.threshold = data;
- break;
- case ATTR_DMP_SMD_DELAY_THLD:
- if (data < 0 || data > INT_MAX / MPU_DEFAULT_DMP_FREQ)
- goto dmp_mem_store_fail;
- result = write_be32_key_to_mem(st, data * MPU_DEFAULT_DMP_FREQ,
- KEY_SMD_DELAY_THLD);
- if (result)
- goto dmp_mem_store_fail;
- st->smd.delay = data;
- break;
- case ATTR_DMP_SMD_DELAY_THLD2:
- if (data < 0 || data > INT_MAX / MPU_DEFAULT_DMP_FREQ)
- goto dmp_mem_store_fail;
- result = write_be32_key_to_mem(st, data * MPU_DEFAULT_DMP_FREQ,
- KEY_SMD_DELAY2_THLD);
- if (result)
- goto dmp_mem_store_fail;
- st->smd.delay2 = data;
- break;
- case ATTR_DMP_TAP_ON:
- result = inv_enable_tap_dmp(st, !!data);
- if (result)
- goto dmp_mem_store_fail;
- st->tap.on = !!data;
- break;
- case ATTR_DMP_TAP_THRESHOLD:
- if (data < 0 || data > USHRT_MAX) {
- result = -EINVAL;
- goto dmp_mem_store_fail;
- }
- result = inv_set_tap_threshold_dmp(st, data);
- if (result)
- goto dmp_mem_store_fail;
- st->tap.thresh = data;
- break;
- case ATTR_DMP_TAP_MIN_COUNT:
- if (data < 0 || data > USHRT_MAX) {
- result = -EINVAL;
- goto dmp_mem_store_fail;
- }
- result = inv_set_min_taps_dmp(st, data);
- if (result)
- goto dmp_mem_store_fail;
- st->tap.min_count = data;
- break;
- case ATTR_DMP_TAP_TIME:
- if (data < 0 || data > USHRT_MAX) {
- result = -EINVAL;
- goto dmp_mem_store_fail;
- }
- result = inv_set_tap_time_dmp(st, data);
- if (result)
- goto dmp_mem_store_fail;
- st->tap.time = data;
- break;
- case ATTR_DMP_DISPLAY_ORIENTATION_ON:
- result = inv_set_display_orient_interrupt_dmp(st, !!data);
- if (result)
- goto dmp_mem_store_fail;
- st->chip_config.display_orient_on = !!data;
- break;
-#ifdef CONFIG_INV_TESTING
- case ATTR_DEBUG_SMD_ENABLE_TESTP1:
- {
- u8 d[] = {0x42};
- result = st->set_power_state(st, true);
- if (result)
- goto dmp_mem_store_fail;
- result = mem_w_key(KEY_SMD_ENABLE_TESTPT1, ARRAY_SIZE(d), d);
- if (result)
- goto dmp_mem_store_fail;
- }
- break;
- case ATTR_DEBUG_SMD_ENABLE_TESTP2:
- {
- u8 d[] = {0x42};
- result = st->set_power_state(st, true);
- if (result)
- goto dmp_mem_store_fail;
- result = mem_w_key(KEY_SMD_ENABLE_TESTPT2, ARRAY_SIZE(d), d);
- if (result)
- goto dmp_mem_store_fail;
- }
- break;
-#endif
- default:
- result = -EINVAL;
- goto dmp_mem_store_fail;
- }
-
-dmp_mem_store_fail:
- result |= st->set_power_state(st, false);
- if (result)
- return result;
-
- return count;
-}
-
-/*
- * inv_dmp_mem_store() - calling this function will store DMP memory data
- */
-static ssize_t inv_dmp_mem_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- int result;
-
- mutex_lock(&indio_dev->mlock);
- result = _dmp_mem_store(dev, attr, buf, count);
- mutex_unlock(&indio_dev->mlock);
-
- return result;
-}
-
-static ssize_t inv_attr64_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int result;
- u64 tmp;
- u32 ped;
-
- mutex_lock(&indio_dev->mlock);
- if (!st->chip_config.enable || !st->chip_config.dmp_on) {
- mutex_unlock(&indio_dev->mlock);
- return -EINVAL;
- }
- result = 0;
- switch (this_attr->address) {
- case ATTR_DMP_PEDOMETER_STEPS:
- result = inv_get_pedometer_steps(st, &ped);
- result |= inv_read_pedometer_counter(st);
- tmp = st->ped.step + ped;
- break;
- case ATTR_DMP_PEDOMETER_TIME:
- result = inv_get_pedometer_time(st, &ped);
- tmp = (u64)st->ped.time + ((u64)ped) * MS_PER_PED_TICKS;
- break;
- case ATTR_DMP_PEDOMETER_COUNTER:
- tmp = st->ped.last_step_time;
- break;
- default:
- result = -EINVAL;
- break;
- }
- mutex_unlock(&indio_dev->mlock);
- if (result)
- return -EINVAL;
- return sprintf(buf, "%lld\n", tmp);
-}
-
-static ssize_t inv_attr64_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int result;
- u64 data;
-
- mutex_lock(&indio_dev->mlock);
- if (st->chip_config.enable || (!st->chip_config.firmware_loaded)) {
- mutex_unlock(&indio_dev->mlock);
- return -EINVAL;
- }
- result = st->set_power_state(st, true);
- if (result) {
- mutex_unlock(&indio_dev->mlock);
- return result;
- }
- result = kstrtoull(buf, 10, &data);
- if (result)
- goto attr64_store_fail;
- switch (this_attr->address) {
- case ATTR_DMP_PEDOMETER_STEPS:
- result = write_be32_key_to_mem(st, 0, KEY_D_PEDSTD_STEPCTR);
- if (result)
- goto attr64_store_fail;
- st->ped.step = data;
- break;
- case ATTR_DMP_PEDOMETER_TIME:
- result = write_be32_key_to_mem(st, 0, KEY_D_PEDSTD_TIMECTR);
- if (result)
- goto attr64_store_fail;
- st->ped.time = data;
- break;
- default:
- result = -EINVAL;
- break;
- }
-attr64_store_fail:
- mutex_unlock(&indio_dev->mlock);
- result = st->set_power_state(st, false);
- if (result)
- return result;
-
- return count;
-}
-/*
- * inv_attr_show() - calling this function will show current
- * dmp parameters.
- */
-static ssize_t inv_attr_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int result, axis;
- s8 *m;
-
- switch (this_attr->address) {
- case ATTR_GYRO_SCALE:
- {
- const s16 gyro_scale[] = {250, 500, 1000, 2000};
-
- return sprintf(buf, "%d\n", gyro_scale[st->chip_config.fsr]);
- }
- case ATTR_ACCEL_SCALE:
- {
- const s16 accel_scale[] = {2, 4, 8, 16};
- return sprintf(buf, "%d\n",
- accel_scale[st->chip_config.accel_fs] *
- st->chip_info.multi);
- }
- case ATTR_COMPASS_SCALE:
- st->slave_compass->get_scale(st, &result);
-
- return sprintf(buf, "%d\n", result);
- case ATTR_ACCEL_X_CALIBBIAS:
- case ATTR_ACCEL_Y_CALIBBIAS:
- case ATTR_ACCEL_Z_CALIBBIAS:
- axis = this_attr->address - ATTR_ACCEL_X_CALIBBIAS;
- return sprintf(buf, "%d\n", st->accel_bias[axis] *
- st->chip_info.multi);
- case ATTR_GYRO_X_CALIBBIAS:
- case ATTR_GYRO_Y_CALIBBIAS:
- case ATTR_GYRO_Z_CALIBBIAS:
- axis = this_attr->address - ATTR_GYRO_X_CALIBBIAS;
- return sprintf(buf, "%d\n", st->gyro_bias[axis]);
- case ATTR_SELF_TEST_GYRO_SCALE:
- return sprintf(buf, "%d\n", SELF_TEST_GYRO_FULL_SCALE);
- case ATTR_SELF_TEST_ACCEL_SCALE:
- if (INV_MPU6500 == st->chip_type)
- return sprintf(buf, "%d\n", SELF_TEST_ACCEL_6500_SCALE);
- else
- return sprintf(buf, "%d\n", SELF_TEST_ACCEL_FULL_SCALE);
- case ATTR_GYRO_X_OFFSET:
- case ATTR_GYRO_Y_OFFSET:
- case ATTR_GYRO_Z_OFFSET:
- axis = this_attr->address - ATTR_GYRO_X_OFFSET;
- return sprintf(buf, "%d\n", st->input_gyro_offset[axis]);
- case ATTR_ACCEL_X_OFFSET:
- case ATTR_ACCEL_Y_OFFSET:
- case ATTR_ACCEL_Z_OFFSET:
- axis = this_attr->address - ATTR_ACCEL_X_OFFSET;
- return sprintf(buf, "%d\n", st->input_accel_offset[axis]);
- case ATTR_DMP_ACCEL_X_DMP_BIAS:
- return sprintf(buf, "%d\n", st->input_accel_dmp_bias[0]);
- case ATTR_DMP_ACCEL_Y_DMP_BIAS:
- return sprintf(buf, "%d\n", st->input_accel_dmp_bias[1]);
- case ATTR_DMP_ACCEL_Z_DMP_BIAS:
- return sprintf(buf, "%d\n", st->input_accel_dmp_bias[2]);
- case ATTR_DMP_GYRO_X_DMP_BIAS:
- return sprintf(buf, "%d\n", st->input_gyro_dmp_bias[0]);
- case ATTR_DMP_GYRO_Y_DMP_BIAS:
- return sprintf(buf, "%d\n", st->input_gyro_dmp_bias[1]);
- case ATTR_DMP_GYRO_Z_DMP_BIAS:
- return sprintf(buf, "%d\n", st->input_gyro_dmp_bias[2]);
- case ATTR_DMP_PED_INT_ON:
- return sprintf(buf, "%d\n", st->ped.int_on);
- case ATTR_DMP_PED_ON:
- return sprintf(buf, "%d\n", st->ped.on);
- case ATTR_DMP_PED_STEP_THRESH:
- return sprintf(buf, "%d\n", st->ped.step_thresh);
- case ATTR_DMP_PED_INT_THRESH:
- return sprintf(buf, "%d\n", st->ped.int_thresh);
- case ATTR_DMP_SMD_ENABLE:
- return sprintf(buf, "%d\n", st->chip_config.smd_enable);
- case ATTR_DMP_SMD_THLD:
- return sprintf(buf, "%d\n", st->smd.threshold);
- case ATTR_DMP_SMD_DELAY_THLD:
- return sprintf(buf, "%d\n", st->smd.delay);
- case ATTR_DMP_SMD_DELAY_THLD2:
- return sprintf(buf, "%d\n", st->smd.delay2);
- case ATTR_DMP_TAP_ON:
- return sprintf(buf, "%d\n", st->tap.on);
- case ATTR_DMP_TAP_THRESHOLD:
- return sprintf(buf, "%d\n", st->tap.thresh);
- case ATTR_DMP_TAP_MIN_COUNT:
- return sprintf(buf, "%d\n", st->tap.min_count);
- case ATTR_DMP_TAP_TIME:
- return sprintf(buf, "%d\n", st->tap.time);
- case ATTR_DMP_DISPLAY_ORIENTATION_ON:
- return sprintf(buf, "%d\n",
- st->chip_config.display_orient_on);
- case ATTR_DMP_ON:
- return sprintf(buf, "%d\n", st->chip_config.dmp_on);
- case ATTR_DMP_INT_ON:
- return sprintf(buf, "%d\n", st->chip_config.dmp_int_on);
- case ATTR_DMP_EVENT_INT_ON:
- return sprintf(buf, "%d\n", st->chip_config.dmp_event_int_on);
- case ATTR_DMP_STEP_INDICATOR_ON:
- return sprintf(buf, "%d\n", st->chip_config.step_indicator_on);
- case ATTR_DMP_BATCHMODE_TIMEOUT:
- return sprintf(buf, "%d\n",
- st->batch.timeout);
- case ATTR_DMP_BATCHMODE_WAKE_FIFO_FULL:
- return sprintf(buf, "%d\n",
- st->batch.wake_fifo_on);
- case ATTR_DMP_SIX_Q_ON:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_SIXQ].on);
- case ATTR_DMP_SIX_Q_RATE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_SIXQ].rate);
- case ATTR_DMP_LPQ_ON:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_LPQ].on);
- case ATTR_DMP_LPQ_RATE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_LPQ].rate);
- case ATTR_DMP_PED_Q_ON:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_PEDQ].on);
- case ATTR_DMP_PED_Q_RATE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_PEDQ].rate);
- case ATTR_DMP_STEP_DETECTOR_ON:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_STEP].on);
- case ATTR_MOTION_LPA_ON:
- return sprintf(buf, "%d\n", st->mot_int.mot_on);
- case ATTR_MOTION_LPA_FREQ:{
- const char *f[] = {"1.25", "5", "20", "40"};
- return sprintf(buf, "%s\n", f[st->chip_config.lpa_freq]);
- }
- case ATTR_MOTION_LPA_THRESHOLD:
- return sprintf(buf, "%d\n", st->mot_int.mot_thr);
-
- case ATTR_SELF_TEST_SAMPLES:
- return sprintf(buf, "%d\n", st->self_test.samples);
- case ATTR_SELF_TEST_THRESHOLD:
- return sprintf(buf, "%d\n", st->self_test.threshold);
- case ATTR_GYRO_ENABLE:
- return sprintf(buf, "%d\n", st->chip_config.gyro_enable);
- case ATTR_GYRO_FIFO_ENABLE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_GYRO].on);
- case ATTR_GYRO_RATE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_GYRO].rate);
- case ATTR_ACCEL_ENABLE:
- return sprintf(buf, "%d\n", st->chip_config.accel_enable);
- case ATTR_ACCEL_FIFO_ENABLE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_ACCEL].on);
- case ATTR_ACCEL_RATE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_ACCEL].rate);
- case ATTR_COMPASS_ENABLE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_COMPASS].on);
- case ATTR_COMPASS_RATE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_COMPASS].rate);
- case ATTR_PRESSURE_ENABLE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_PRESSURE].on);
- case ATTR_PRESSURE_RATE:
- return sprintf(buf, "%d\n", st->sensor[SENSOR_PRESSURE].rate);
- case ATTR_POWER_STATE:
- return sprintf(buf, "%d\n", !fake_asleep);
- case ATTR_FIRMWARE_LOADED:
- return sprintf(buf, "%d\n", st->chip_config.firmware_loaded);
- case ATTR_SAMPLING_FREQ:
- return sprintf(buf, "%d\n", st->chip_config.fifo_rate);
- case ATTR_SELF_TEST:
- mutex_lock(&indio_dev->mlock);
- if (st->chip_config.enable) {
- mutex_unlock(&indio_dev->mlock);
- return -EBUSY;
- }
- if (INV_MPU3050 == st->chip_type)
- result = 1;
- else
- result = inv_hw_self_test(st);
- mutex_unlock(&indio_dev->mlock);
- return sprintf(buf, "%d\n", result);
- case ATTR_GYRO_MATRIX:
- m = st->plat_data.orientation;
- return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
- m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
- case ATTR_ACCEL_MATRIX:
- if (st->plat_data.sec_slave_type ==
- SECONDARY_SLAVE_TYPE_ACCEL)
- m =
- st->plat_data.secondary_orientation;
- else
- m = st->plat_data.orientation;
- return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
- m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
- case ATTR_COMPASS_MATRIX:
- if (st->plat_data.sec_slave_type ==
- SECONDARY_SLAVE_TYPE_COMPASS)
- m =
- st->plat_data.secondary_orientation;
- else
- return -ENODEV;
- return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
- m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
- case ATTR_SECONDARY_NAME:
- {
- const char *n[] = {"NULL", "AK8975", "AK8972", "AK8963",
- "BMA250", "MLX90399", "AK09911"};
- switch (st->plat_data.sec_slave_id) {
- case COMPASS_ID_AK8975:
- return sprintf(buf, "%s\n", n[1]);
- case COMPASS_ID_AK8972:
- return sprintf(buf, "%s\n", n[2]);
- case COMPASS_ID_AK8963:
- return sprintf(buf, "%s\n", n[3]);
- case ACCEL_ID_BMA250:
- return sprintf(buf, "%s\n", n[4]);
- case COMPASS_ID_MLX90399:
- return sprintf(buf, "%s\n", n[5]);
- case COMPASS_ID_AK09911:
- return sprintf(buf, "%s\n", n[6]);
- default:
- return sprintf(buf, "%s\n", n[0]);
- }
- }
-#ifdef CONFIG_INV_TESTING
- case ATTR_REG_WRITE:
- return sprintf(buf, "1\n");
- case ATTR_COMPASS_SENS:
- {
- /* these 2 conditions should never be met, since the
- 'compass_sens' sysfs entry should be hidden if the compass
- is not an AKM */
- if (st->plat_data.sec_slave_type !=
- SECONDARY_SLAVE_TYPE_COMPASS)
- return -ENODEV;
- if (st->plat_data.sec_slave_id != COMPASS_ID_AK8975 &&
- st->plat_data.sec_slave_id != COMPASS_ID_AK8972 &&
- st->plat_data.sec_slave_id != COMPASS_ID_AK8963)
- return -ENODEV;
- m = st->chip_info.compass_sens;
- return sprintf(buf, "%d,%d,%d\n", m[0], m[1], m[2]);
- }
- case ATTR_DEBUG_SMD_EXE_STATE:
- {
- u8 d[2];
-
- result = st->set_power_state(st, true);
- mpu_memory_read(st, st->i2c_addr,
- inv_dmp_get_address(KEY_SMD_EXE_STATE), 2, d);
- return sprintf(buf, "%d\n", (short)be16_to_cpup((__be16 *)(d)));
- }
- case ATTR_DEBUG_SMD_DELAY_CNTR:
- {
- u8 d[4];
-
- result = st->set_power_state(st, true);
- mpu_memory_read(st, st->i2c_addr,
- inv_dmp_get_address(KEY_SMD_DELAY_CNTR), 4, d);
- return sprintf(buf, "%d\n", (int)be32_to_cpup((__be32 *)(d)));
- }
-#endif
- default:
- return -EPERM;
- }
-}
-
-/*
- * inv_dmp_display_orient_show() - calling this function will
- * show orientation This event must use poll.
- */
-static ssize_t inv_dmp_display_orient_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct inv_mpu_state *st = iio_priv(dev_get_drvdata(dev));
-
- return sprintf(buf, "%d\n", st->display_orient_data);
-}
-
-/*
- * inv_accel_motion_show() - calling this function showes motion interrupt.
- * This event must use poll.
- */
-static ssize_t inv_accel_motion_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "1\n");
-}
-
-/*
- * inv_smd_show() - calling this function showes smd interrupt.
- * This event must use poll.
- */
-static ssize_t inv_smd_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "1\n");
-}
-
-/*
- * inv_ped_show() - calling this function showes pedometer interrupt.
- * This event must use poll.
- */
-static ssize_t inv_ped_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "1\n");
-}
-
-/*
- * inv_dmp_tap_show() - calling this function will show tap
- * This event must use poll.
- */
-static ssize_t inv_dmp_tap_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct inv_mpu_state *st = iio_priv(dev_get_drvdata(dev));
- return sprintf(buf, "%d\n", st->tap_data);
-}
-
-/*
- * inv_temperature_show() - Read temperature data directly from registers.
- */
-static ssize_t inv_temperature_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
-
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct inv_reg_map_s *reg;
- int result, cur_scale, cur_off;
- short temp;
- long scale_t;
- u8 data[2];
- const long scale[] = {3834792L, 3158064L, 3340827L};
- const long offset[] = {5383314L, 2394184L, 1376256L};
-
- reg = &st->reg;
- mutex_lock(&indio_dev->mlock);
- if (!st->chip_config.enable)
- result = st->set_power_state(st, true);
- else
- result = 0;
- if (result) {
- mutex_unlock(&indio_dev->mlock);
- return result;
- }
- result = inv_i2c_read(st, reg->temperature, 2, data);
- if (!st->chip_config.enable)
- result |= st->set_power_state(st, false);
- mutex_unlock(&indio_dev->mlock);
- if (result) {
- pr_err("Could not read temperature register.\n");
- return result;
- }
- temp = (signed short)(be16_to_cpup((short *)&data[0]));
- switch (st->chip_type) {
- case INV_MPU3050:
- cur_scale = scale[0];
- cur_off = offset[0];
- break;
- case INV_MPU6050:
- cur_scale = scale[1];
- cur_off = offset[1];
- break;
- case INV_MPU6500:
- cur_scale = scale[2];
- cur_off = offset[2];
- break;
- default:
- return -EINVAL;
- };
- scale_t = cur_off +
- inv_q30_mult((int)temp << MPU_TEMP_SHIFT, cur_scale);
-
- INV_I2C_INC_TEMPREAD(1);
-
- return sprintf(buf, "%ld %lld\n", scale_t, get_time_ns());
-}
-
-static ssize_t inv_flush_batch_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- int result;
- bool has_data;
-
- mutex_lock(&indio_dev->mlock);
- result = inv_flush_batch_data(indio_dev, &has_data);
- mutex_unlock(&indio_dev->mlock);
- if (result)
- return sprintf(buf, "%d\n", result);
- else
- return sprintf(buf, "%d\n", has_data);
-}
-
-/*
- * inv_firmware_loaded() - calling this function will change
- * firmware load
- */
-static int inv_firmware_loaded(struct inv_mpu_state *st, int data)
-{
- if (data)
- return -EINVAL;
- st->chip_config.firmware_loaded = 0;
-
- return 0;
-}
-
-static int inv_switch_gyro_engine(struct inv_mpu_state *st, bool en)
-{
- return inv_switch_engine(st, en, BIT_PWR_GYRO_STBY);
-}
-
-static int inv_switch_accel_engine(struct inv_mpu_state *st, bool en)
-{
- return inv_switch_engine(st, en, BIT_PWR_ACCEL_STBY);
-}
-
-static ssize_t _attr_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int data;
- u8 d, axis;
- int result;
-
- result = 0;
- if (st->chip_config.enable)
- return -EBUSY;
- if (this_attr->address <= ATTR_MOTION_LPA_THRESHOLD) {
- result = st->set_power_state(st, true);
- if (result)
- return result;
- }
-
- /* check the input and validate it's format */
- switch (this_attr->address) {
-#ifdef CONFIG_INV_TESTING
- /* these inputs are strings */
- case ATTR_COMPASS_MATRIX:
- case ATTR_COMPASS_SENS:
- break;
-#endif
- /* these inputs are integers */
- default:
- result = kstrtoint(buf, 10, &data);
- if (result)
- goto attr_store_fail;
- break;
- }
-
- switch (this_attr->address) {
- case ATTR_GYRO_X_OFFSET:
- case ATTR_GYRO_Y_OFFSET:
- case ATTR_GYRO_Z_OFFSET:
- if ((data > MPU_MAX_G_OFFSET_VALUE) ||
- (data < MPU_MIN_G_OFFSET_VALUE))
- return -EINVAL;
- axis = this_attr->address - ATTR_GYRO_X_OFFSET;
- result = inv_set_offset_reg(st,
- reg_gyro_offset[axis],
- st->rom_gyro_offset[axis] + data);
-
- if (result)
- goto attr_store_fail;
- st->input_gyro_offset[axis] = data;
- break;
- case ATTR_ACCEL_X_OFFSET:
- case ATTR_ACCEL_Y_OFFSET:
- case ATTR_ACCEL_Z_OFFSET:
- {
- const u8 *ch;
-
- if ((data > MPU_MAX_A_OFFSET_VALUE) ||
- (data < MPU_MIN_A_OFFSET_VALUE))
- return -EINVAL;
-
- axis = this_attr->address - ATTR_ACCEL_X_OFFSET;
- if (INV_MPU6050 == st->chip_type)
- ch = reg_6050_accel_offset;
- else
- ch = reg_6500_accel_offset;
-
- result = inv_set_offset_reg(st, ch[axis],
- st->rom_accel_offset[axis] + (data << 1));
- if (result)
- goto attr_store_fail;
- st->input_accel_offset[axis] = data;
- break;
- }
- case ATTR_GYRO_SCALE:
- result = inv_write_fsr(st, data);
- break;
- case ATTR_ACCEL_SCALE:
- result = inv_write_accel_fs(st, data);
- break;
- case ATTR_COMPASS_SCALE:
- result = st->slave_compass->set_scale(st, data);
- break;
- case ATTR_MOTION_LPA_ON:
- if (INV_MPU6500 == st->chip_type) {
- if (data)
- /* enable and put in MPU6500 mode */
- d = BIT_ACCEL_INTEL_ENABLE
- | BIT_ACCEL_INTEL_MODE;
- else
- d = 0;
- result = inv_i2c_single_write(st,
- REG_6500_ACCEL_INTEL_CTRL, d);
- if (result)
- goto attr_store_fail;
- }
- st->mot_int.mot_on = !!data;
- st->chip_config.lpa_mode = !!data;
- break;
- case ATTR_MOTION_LPA_FREQ:
- result = inv_lpa_freq(st, data);
- break;
- case ATTR_MOTION_LPA_THRESHOLD:
- if ((data > MPU6XXX_MAX_MOTION_THRESH) || (data < 0)) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- if (INV_MPU6500 == st->chip_type) {
- d = (u8)(data >> MPU6500_MOTION_THRESH_SHIFT);
- data = (d << MPU6500_MOTION_THRESH_SHIFT);
- } else {
- d = (u8)(data >> MPU6050_MOTION_THRESH_SHIFT);
- data = (d << MPU6050_MOTION_THRESH_SHIFT);
- }
-
- result = inv_i2c_single_write(st, REG_ACCEL_MOT_THR, d);
- if (result)
- goto attr_store_fail;
- st->mot_int.mot_thr = data;
- break;
- /* from now on, power is not turned on */
- case ATTR_SELF_TEST_SAMPLES:
- if (data > ST_MAX_SAMPLES || data < 0) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- st->self_test.samples = data;
- break;
- case ATTR_SELF_TEST_THRESHOLD:
- if (data > ST_MAX_THRESHOLD || data < 0) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- st->self_test.threshold = data;
- case ATTR_GYRO_ENABLE:
- st->chip_config.gyro_enable = !!data;
- break;
- case ATTR_GYRO_FIFO_ENABLE:
- st->sensor[SENSOR_GYRO].on = !!data;
- break;
- case ATTR_GYRO_RATE:
- st->sensor[SENSOR_GYRO].rate = data;
- st->sensor[SENSOR_GYRO].dur = MPU_DEFAULT_DMP_FREQ / data;
- st->sensor[SENSOR_GYRO].dur *= DMP_INTERVAL_INIT;
- break;
- case ATTR_ACCEL_ENABLE:
- st->chip_config.accel_enable = !!data;
- break;
- case ATTR_ACCEL_FIFO_ENABLE:
- st->sensor[SENSOR_ACCEL].on = !!data;
- break;
- case ATTR_ACCEL_RATE:
- st->sensor[SENSOR_ACCEL].rate = data;
- st->sensor[SENSOR_ACCEL].dur = MPU_DEFAULT_DMP_FREQ / data;
- st->sensor[SENSOR_ACCEL].dur *= DMP_INTERVAL_INIT;
- break;
- case ATTR_COMPASS_ENABLE:
- st->sensor[SENSOR_COMPASS].on = !!data;
- break;
- case ATTR_COMPASS_RATE:
- if (data <= 0) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- if ((MSEC_PER_SEC / st->slave_compass->rate_scale) < data)
- data = MSEC_PER_SEC / st->slave_compass->rate_scale;
-
- st->sensor[SENSOR_COMPASS].rate = data;
- st->sensor[SENSOR_COMPASS].dur = MPU_DEFAULT_DMP_FREQ / data;
- st->sensor[SENSOR_COMPASS].dur *= DMP_INTERVAL_INIT;
- break;
- case ATTR_PRESSURE_ENABLE:
- st->sensor[SENSOR_PRESSURE].on = !!data;
- break;
- case ATTR_PRESSURE_RATE:
- if (data <= 0) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- if ((MSEC_PER_SEC / st->slave_pressure->rate_scale) < data)
- data = MSEC_PER_SEC / st->slave_pressure->rate_scale;
-
- st->sensor[SENSOR_PRESSURE].rate = data;
- st->sensor[SENSOR_PRESSURE].dur = MPU_DEFAULT_DMP_FREQ / data;
- st->sensor[SENSOR_PRESSURE].dur *= DMP_INTERVAL_INIT;
- break;
- case ATTR_POWER_STATE:
- fake_asleep = !data;
- break;
- case ATTR_FIRMWARE_LOADED:
- result = inv_firmware_loaded(st, data);
- break;
- case ATTR_SAMPLING_FREQ:
- result = inv_fifo_rate_store(st, data);
- break;
-#ifdef CONFIG_INV_TESTING
- case ATTR_COMPASS_MATRIX:
- {
- char *str;
- __s8 m[9];
- d = 0;
- if (st->plat_data.sec_slave_type == SECONDARY_SLAVE_TYPE_NONE)
- return -ENODEV;
- while ((str = strsep((char **)&buf, ","))) {
- if (d >= 9) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- result = kstrtoint(str, 10, &data);
- if (result)
- goto attr_store_fail;
- if (data < -1 || data > 1) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- m[d] = data;
- d++;
- }
- if (d < 9) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- memcpy(st->plat_data.secondary_orientation, m, sizeof(m));
- pr_debug(KERN_INFO
- "compass_matrix: %d,%d,%d,%d,%d,%d,%d,%d,%d\n",
- m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
- break;
- }
- case ATTR_COMPASS_SENS:
- {
- char *str;
- __s8 s[3];
- d = 0;
- /* these 2 conditions should never be met, since the
- 'compass_sens' sysfs entry should be hidden if the compass
- is not an AKM */
- if (st->plat_data.sec_slave_type == SECONDARY_SLAVE_TYPE_NONE)
- return -ENODEV;
- if (st->plat_data.sec_slave_id != COMPASS_ID_AK8975 &&
- st->plat_data.sec_slave_id != COMPASS_ID_AK8972 &&
- st->plat_data.sec_slave_id != COMPASS_ID_AK8963)
- return -ENODEV;
- /* read the input data, expecting 3 comma separated values */
- while ((str = strsep((char **)&buf, ","))) {
- if (d >= 3) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- result = kstrtoint(str, 10, &data);
- if (result)
- goto attr_store_fail;
- if (data < 0 || data > 255) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- s[d] = data;
- d++;
- }
- if (d < 3) {
- result = -EINVAL;
- goto attr_store_fail;
- }
- /* store the new compass sensitivity adjustment */
- memcpy(st->chip_info.compass_sens, s, sizeof(s));
- pr_debug(KERN_INFO
- "compass_sens: %d,%d,%d\n", s[0], s[1], s[2]);
- break;
- }
-#endif
- default:
- result = -EINVAL;
- goto attr_store_fail;
- };
-
-attr_store_fail:
- if (this_attr->address <= ATTR_MOTION_LPA_THRESHOLD)
- result |= st->set_power_state(st, false);
- if (result)
- return result;
-
- return count;
-}
-
-/*
- * inv_attr_store() - calling this function will store current
- * non-dmp parameter settings
- */
-static ssize_t inv_attr_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- int result;
-
- mutex_lock(&indio_dev->mlock);
- result = _attr_store(dev, attr, buf, count);
- mutex_unlock(&indio_dev->mlock);
-
- return result;
-}
-
-static ssize_t inv_master_enable_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- int data;
- int result;
-
- result = kstrtoint(buf, 10, &data);
- if (result)
- return result;
-
- mutex_lock(&indio_dev->mlock);
- if (st->chip_config.enable == (!!data)) {
- result = count;
- goto end_enable;
- }
- if (!!data) {
- result = st->set_power_state(st, true);
- if (result)
- goto end_enable;
- }
- result = set_inv_enable(indio_dev, !!data);
- if (result)
- goto end_enable;
- if (!data) {
- result = st->set_power_state(st, false);
- if (result)
- goto end_enable;
- }
- result = count;
-
-end_enable:
- mutex_unlock(&indio_dev->mlock);
-
- return result;
-}
-
-static ssize_t inv_master_enable_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct inv_mpu_state *st = iio_priv(dev_get_drvdata(dev));
-
- return sprintf(buf, "%d\n", st->chip_config.enable);
-}
-
-#ifdef CONFIG_INV_TESTING
-static ssize_t inv_test_suspend_resume_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int data;
- int result;
-
- result = kstrtoint(buf, 10, &data);
- if (result)
- return result;
- if (data)
- inv_mpu_suspend(dev);
- else
- inv_mpu_resume(dev);
- suspend_state = !!data;
-
- return count;
-}
-
-static ssize_t inv_test_suspend_resume_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
-
- return sprintf(buf, "%d\n", suspend_state);
-}
-
-/*
- * inv_reg_write_store() - register write command for testing.
- * Format: WSRRDD, where RR is the register in hex,
- * and DD is the data in hex.
- */
-static ssize_t inv_reg_write_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- u32 result;
- u8 wreg, wval;
- int temp;
- char local_buf[10];
-
- if ((buf[0] != 'W' && buf[0] != 'w') ||
- (buf[1] != 'S' && buf[1] != 's'))
- return -EINVAL;
- if (strlen(buf) < 6)
- return -EINVAL;
-
- strncpy(local_buf, buf, 7);
- local_buf[6] = 0;
- result = sscanf(&local_buf[4], "%x", &temp);
- if (result == 0)
- return -EINVAL;
- wval = temp;
- local_buf[4] = 0;
- sscanf(&local_buf[2], "%x", &temp);
- if (result == 0)
- return -EINVAL;
- wreg = temp;
-
- result = inv_i2c_single_write(st, wreg, wval);
- if (result)
- return result;
-
- return count;
-}
-
-static ssize_t inv_test_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int data;
- u8 *m;
- int result;
-
- if (st->chip_config.enable)
- return -EBUSY;
- result = kstrtoint(buf, 10, &data);
- if (result)
- return -EINVAL;
-
- result = st->set_power_state(st, true);
- if (result)
- return result;
-
- switch (this_attr->address) {
- case ATTR_DEBUG_ACCEL_COUNTER:
- {
- u8 D[6] = {0xf2, 0xb0, 0x80, 0xc0, 0xc8, 0xc2};
- u8 E[6] = {0xf3, 0xb1, 0x88, 0xc0, 0xc0, 0xc0};
-
- if (data)
- m = E;
- else
- m = D;
- result = mem_w_key(KEY_TEST_01, ARRAY_SIZE(D), m);
- data_out_control.accel = !!data;
- break;
- }
- case ATTR_DEBUG_GYRO_COUNTER:
- {
- u8 D[6] = {0xf2, 0xb0, 0x80, 0xc4, 0xcc, 0xc6};
- u8 E[6] = {0xf3, 0xb1, 0x88, 0xc0, 0xc0, 0xc0};
-
- if (data)
- m = E;
- else
- m = D;
- result = mem_w_key(KEY_TEST_02, ARRAY_SIZE(D), m);
- data_out_control.gyro = !!data;
- break;
- }
- case ATTR_DEBUG_COMPASS_COUNTER:
- {
- u8 D[6] = {0xf2, 0xb0, 0x81, 0xc0, 0xc8, 0xc2};
- u8 E[6] = {0xf3, 0xb1, 0x88, 0xc0, 0xc0, 0xc0};
-
- if (data)
- m = E;
- else
- m = D;
- result = mem_w_key(KEY_TEST_03, ARRAY_SIZE(D), m);
- data_out_control.compass = !!data;
- break;
- }
- case ATTR_DEBUG_PRESSURE_COUNTER:
- {
- u8 D[6] = {0xf2, 0xb0, 0x81, 0xc4, 0xcc, 0xc6};
- u8 E[6] = {0xf3, 0xb1, 0x88, 0xc0, 0xc0, 0xc0};
-
- if (data)
- m = E;
- else
- m = D;
- result = mem_w_key(KEY_TEST_04, ARRAY_SIZE(D), m);
- data_out_control.pressure = !!data;
- break;
- }
- case ATTR_DEBUG_LPQ_COUNTER:
- {
- u8 D[6] = {0xf1, 0xb1, 0x83, 0xc2, 0xc4, 0xc6};
- u8 E[6] = {0xf1, 0xb1, 0x88, 0xc0, 0xc0, 0xc0};
-
- if (data)
- m = E;
- else
- m = D;
- result = mem_w_key(KEY_TEST_05, ARRAY_SIZE(D), m);
- data_out_control.LPQ = !!data;
- break;
- }
- case ATTR_DEBUG_SIXQ_COUNTER:
- {
- u8 D[6] = {0xf1, 0xb1, 0x89, 0xc2, 0xc4, 0xc6};
- u8 E[6] = {0xf1, 0xb1, 0x88, 0xc0, 0xc0, 0xc0};
-
- if (data)
- m = E;
- else
- m = D;
- result = mem_w_key(KEY_TEST_06, ARRAY_SIZE(D), m);
- data_out_control.SIXQ = !!data;
- break;
- }
- case ATTR_DEBUG_PEDQ_COUNTER:
- {
- u8 D[6] = {0xf2, 0xf2, 0x88, 0xc2, 0xc4, 0xc6};
- u8 E[6] = {0xf3, 0xb1, 0x88, 0xc0, 0xc0, 0xc0};
-
- if (data)
- m = E;
- else
- m = D;
- result = mem_w_key(KEY_TEST_07, ARRAY_SIZE(D), m);
- data_out_control.PEDQ = !!data;
- break;
- }
- default:
- return -EINVAL;
- }
-
- return count;
-}
-
-static ssize_t inv_test_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- switch (this_attr->address) {
- case ATTR_DEBUG_ACCEL_COUNTER:
- return sprintf(buf, "%d\n", data_out_control.accel);
- case ATTR_DEBUG_GYRO_COUNTER:
- return sprintf(buf, "%d\n", data_out_control.gyro);
- case ATTR_DEBUG_COMPASS_COUNTER:
- return sprintf(buf, "%d\n", data_out_control.compass);
- case ATTR_DEBUG_PRESSURE_COUNTER:
- return sprintf(buf, "%d\n", data_out_control.pressure);
- case ATTR_DEBUG_LPQ_COUNTER:
- return sprintf(buf, "%d\n", data_out_control.LPQ);
- case ATTR_DEBUG_SIXQ_COUNTER:
- return sprintf(buf, "%d\n", data_out_control.SIXQ);
- case ATTR_DEBUG_PEDQ_COUNTER:
- return sprintf(buf, "%d\n", data_out_control.PEDQ);
- default:
- return -EINVAL;
- }
-}
-
-#endif /* CONFIG_INV_TESTING */
-
-static const struct iio_chan_spec inv_mpu_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(INV_MPU_SCAN_TIMESTAMP),
-};
-
-/*constant IIO attribute */
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500");
-
-/* special sysfs */
-static DEVICE_ATTR(reg_dump, S_IRUGO, inv_reg_dump_show, NULL);
-static DEVICE_ATTR(temperature, S_IRUGO, inv_temperature_show, NULL);
-
-/* event based sysfs, needs poll to read */
-static DEVICE_ATTR(event_tap, S_IRUGO, inv_dmp_tap_show, NULL);
-static DEVICE_ATTR(event_display_orientation, S_IRUGO,
- inv_dmp_display_orient_show, NULL);
-static DEVICE_ATTR(event_accel_motion, S_IRUGO, inv_accel_motion_show, NULL);
-static DEVICE_ATTR(event_smd, S_IRUGO, inv_smd_show, NULL);
-static DEVICE_ATTR(event_pedometer, S_IRUGO, inv_ped_show, NULL);
-
-/* master enable method */
-static DEVICE_ATTR(master_enable, S_IRUGO | S_IWUSR, inv_master_enable_show,
- inv_master_enable_store);
-
-/* special run time sysfs entry, read only */
-static DEVICE_ATTR(flush_batch, S_IRUGO, inv_flush_batch_show, NULL);
-
-/* DMP sysfs with power on/off */
-static IIO_DEVICE_ATTR(in_accel_x_dmp_bias, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_bias_store, ATTR_DMP_ACCEL_X_DMP_BIAS);
-static IIO_DEVICE_ATTR(in_accel_y_dmp_bias, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_bias_store, ATTR_DMP_ACCEL_Y_DMP_BIAS);
-static IIO_DEVICE_ATTR(in_accel_z_dmp_bias, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_bias_store, ATTR_DMP_ACCEL_Z_DMP_BIAS);
-
-static IIO_DEVICE_ATTR(in_anglvel_x_dmp_bias, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_bias_store, ATTR_DMP_GYRO_X_DMP_BIAS);
-static IIO_DEVICE_ATTR(in_anglvel_y_dmp_bias, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_bias_store, ATTR_DMP_GYRO_Y_DMP_BIAS);
-static IIO_DEVICE_ATTR(in_anglvel_z_dmp_bias, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_bias_store, ATTR_DMP_GYRO_Z_DMP_BIAS);
-
-static IIO_DEVICE_ATTR(pedometer_int_on, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_PED_INT_ON);
-static IIO_DEVICE_ATTR(pedometer_on, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_PED_ON);
-static IIO_DEVICE_ATTR(pedometer_step_thresh, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_PED_STEP_THRESH);
-static IIO_DEVICE_ATTR(pedometer_int_thresh, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_PED_INT_THRESH);
-
-static IIO_DEVICE_ATTR(smd_enable, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_SMD_ENABLE);
-static IIO_DEVICE_ATTR(smd_threshold, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_SMD_THLD);
-static IIO_DEVICE_ATTR(smd_delay_threshold, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_SMD_DELAY_THLD);
-static IIO_DEVICE_ATTR(smd_delay_threshold2, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_SMD_DELAY_THLD2);
-
-static IIO_DEVICE_ATTR(pedometer_steps, S_IRUGO | S_IWUSR, inv_attr64_show,
- inv_attr64_store, ATTR_DMP_PEDOMETER_STEPS);
-static IIO_DEVICE_ATTR(pedometer_time, S_IRUGO | S_IWUSR, inv_attr64_show,
- inv_attr64_store, ATTR_DMP_PEDOMETER_TIME);
-static IIO_DEVICE_ATTR(pedometer_counter, S_IRUGO | S_IWUSR, inv_attr64_show,
- NULL, ATTR_DMP_PEDOMETER_COUNTER);
-
-static IIO_DEVICE_ATTR(tap_on, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_TAP_ON);
-static IIO_DEVICE_ATTR(tap_threshold, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_TAP_THRESHOLD);
-static IIO_DEVICE_ATTR(tap_min_count, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_TAP_MIN_COUNT);
-static IIO_DEVICE_ATTR(tap_time, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_TAP_TIME);
-static IIO_DEVICE_ATTR(display_orientation_on, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_mem_store, ATTR_DMP_DISPLAY_ORIENTATION_ON);
-
-/* DMP sysfs without power on/off */
-static IIO_DEVICE_ATTR(dmp_on, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_ON);
-static IIO_DEVICE_ATTR(dmp_int_on, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_INT_ON);
-static IIO_DEVICE_ATTR(dmp_event_int_on, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_EVENT_INT_ON);
-static IIO_DEVICE_ATTR(step_indicator_on, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_STEP_INDICATOR_ON);
-static IIO_DEVICE_ATTR(batchmode_timeout, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_attr_store, ATTR_DMP_BATCHMODE_TIMEOUT);
-static IIO_DEVICE_ATTR(batchmode_wake_fifo_full_on, S_IRUGO | S_IWUSR,
- inv_attr_show, inv_dmp_attr_store, ATTR_DMP_BATCHMODE_WAKE_FIFO_FULL);
-
-static IIO_DEVICE_ATTR(six_axes_q_on, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_SIX_Q_ON);
-static IIO_DEVICE_ATTR(six_axes_q_rate, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_SIX_Q_RATE);
-
-static IIO_DEVICE_ATTR(three_axes_q_on, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_LPQ_ON);
-static IIO_DEVICE_ATTR(three_axes_q_rate, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_LPQ_RATE);
-
-static IIO_DEVICE_ATTR(ped_q_on, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_PED_Q_ON);
-static IIO_DEVICE_ATTR(ped_q_rate, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_PED_Q_RATE);
-
-static IIO_DEVICE_ATTR(step_detector_on, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_dmp_attr_store, ATTR_DMP_STEP_DETECTOR_ON);
-
-/* non DMP sysfs with power on/off */
-static IIO_DEVICE_ATTR(motion_lpa_on, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_MOTION_LPA_ON);
-static IIO_DEVICE_ATTR(motion_lpa_freq, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_MOTION_LPA_FREQ);
-static IIO_DEVICE_ATTR(motion_lpa_threshold, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_MOTION_LPA_THRESHOLD);
-
-static IIO_DEVICE_ATTR(in_accel_scale, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_ACCEL_SCALE);
-static IIO_DEVICE_ATTR(in_anglvel_scale, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_GYRO_SCALE);
-static IIO_DEVICE_ATTR(in_magn_scale, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_COMPASS_SCALE);
-
-static IIO_DEVICE_ATTR(in_anglvel_x_offset, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_GYRO_X_OFFSET);
-static IIO_DEVICE_ATTR(in_anglvel_y_offset, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_GYRO_Y_OFFSET);
-static IIO_DEVICE_ATTR(in_anglvel_z_offset, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_GYRO_Z_OFFSET);
-
-static IIO_DEVICE_ATTR(in_accel_x_offset, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_ACCEL_X_OFFSET);
-static IIO_DEVICE_ATTR(in_accel_y_offset, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_ACCEL_Y_OFFSET);
-static IIO_DEVICE_ATTR(in_accel_z_offset, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_ACCEL_Z_OFFSET);
-
-/* non DMP sysfs without power on/off */
-static IIO_DEVICE_ATTR(self_test_samples, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_SELF_TEST_SAMPLES);
-static IIO_DEVICE_ATTR(self_test_threshold, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_SELF_TEST_THRESHOLD);
-
-static IIO_DEVICE_ATTR(gyro_enable, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_GYRO_ENABLE);
-static IIO_DEVICE_ATTR(gyro_fifo_enable, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_GYRO_FIFO_ENABLE);
-static IIO_DEVICE_ATTR(gyro_rate, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_GYRO_RATE);
-
-static IIO_DEVICE_ATTR(accel_enable, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_ACCEL_ENABLE);
-static IIO_DEVICE_ATTR(accel_fifo_enable, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_ACCEL_FIFO_ENABLE);
-static IIO_DEVICE_ATTR(accel_rate, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_ACCEL_RATE);
-
-static IIO_DEVICE_ATTR(compass_enable, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_COMPASS_ENABLE);
-static IIO_DEVICE_ATTR(compass_rate, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_COMPASS_RATE);
-
-static IIO_DEVICE_ATTR(pressure_enable, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_PRESSURE_ENABLE);
-static IIO_DEVICE_ATTR(pressure_rate, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_PRESSURE_RATE);
-
-static IIO_DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_POWER_STATE);
-static IIO_DEVICE_ATTR(firmware_loaded, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_FIRMWARE_LOADED);
-static IIO_DEVICE_ATTR(sampling_frequency, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_SAMPLING_FREQ);
-
-/* show method only sysfs but with power on/off */
-static IIO_DEVICE_ATTR(self_test, S_IRUGO, inv_attr_show, NULL,
- ATTR_SELF_TEST);
-
-/* show method only sysfs */
-static IIO_DEVICE_ATTR(in_accel_x_calibbias, S_IRUGO, inv_attr_show,
- NULL, ATTR_ACCEL_X_CALIBBIAS);
-static IIO_DEVICE_ATTR(in_accel_y_calibbias, S_IRUGO, inv_attr_show,
- NULL, ATTR_ACCEL_Y_CALIBBIAS);
-static IIO_DEVICE_ATTR(in_accel_z_calibbias, S_IRUGO, inv_attr_show,
- NULL, ATTR_ACCEL_Z_CALIBBIAS);
-
-static IIO_DEVICE_ATTR(in_anglvel_x_calibbias, S_IRUGO,
- inv_attr_show, NULL, ATTR_GYRO_X_CALIBBIAS);
-static IIO_DEVICE_ATTR(in_anglvel_y_calibbias, S_IRUGO,
- inv_attr_show, NULL, ATTR_GYRO_Y_CALIBBIAS);
-static IIO_DEVICE_ATTR(in_anglvel_z_calibbias, S_IRUGO,
- inv_attr_show, NULL, ATTR_GYRO_Z_CALIBBIAS);
-
-static IIO_DEVICE_ATTR(in_anglvel_self_test_scale, S_IRUGO,
- inv_attr_show, NULL, ATTR_SELF_TEST_GYRO_SCALE);
-static IIO_DEVICE_ATTR(in_accel_self_test_scale, S_IRUGO,
- inv_attr_show, NULL, ATTR_SELF_TEST_ACCEL_SCALE);
-
-static IIO_DEVICE_ATTR(gyro_matrix, S_IRUGO, inv_attr_show, NULL,
- ATTR_GYRO_MATRIX);
-static IIO_DEVICE_ATTR(accel_matrix, S_IRUGO, inv_attr_show, NULL,
- ATTR_ACCEL_MATRIX);
-#ifdef CONFIG_INV_TESTING /* read/write in test mode */
-static IIO_DEVICE_ATTR(compass_matrix, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_COMPASS_MATRIX);
-static IIO_DEVICE_ATTR(compass_sens, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_attr_store, ATTR_COMPASS_SENS);
-#else
-static IIO_DEVICE_ATTR(compass_matrix, S_IRUGO, inv_attr_show, NULL,
- ATTR_COMPASS_MATRIX);
-#endif
-static IIO_DEVICE_ATTR(secondary_name, S_IRUGO, inv_attr_show, NULL,
- ATTR_SECONDARY_NAME);
-
-#ifdef CONFIG_INV_TESTING
-static IIO_DEVICE_ATTR(reg_write, S_IRUGO | S_IWUSR, inv_attr_show,
- inv_reg_write_store, ATTR_REG_WRITE);
-/* smd debug related sysfs */
-static IIO_DEVICE_ATTR(debug_smd_enable_testp1, S_IWUSR, NULL,
- inv_dmp_attr_store, ATTR_DEBUG_SMD_ENABLE_TESTP1);
-static IIO_DEVICE_ATTR(debug_smd_enable_testp2, S_IWUSR, NULL,
- inv_dmp_attr_store, ATTR_DEBUG_SMD_ENABLE_TESTP2);
-static IIO_DEVICE_ATTR(debug_smd_exe_state, S_IRUGO, inv_attr_show,
- NULL, ATTR_DEBUG_SMD_EXE_STATE);
-static IIO_DEVICE_ATTR(debug_smd_delay_cntr, S_IRUGO, inv_attr_show,
- NULL, ATTR_DEBUG_SMD_DELAY_CNTR);
-static DEVICE_ATTR(test_suspend_resume, S_IRUGO | S_IWUSR,
- inv_test_suspend_resume_show, inv_test_suspend_resume_store);
-
-static IIO_DEVICE_ATTR(test_gyro_counter, S_IRUGO | S_IWUSR, inv_test_show,
- inv_test_store, ATTR_DEBUG_GYRO_COUNTER);
-static IIO_DEVICE_ATTR(test_accel_counter, S_IRUGO | S_IWUSR, inv_test_show,
- inv_test_store, ATTR_DEBUG_ACCEL_COUNTER);
-static IIO_DEVICE_ATTR(test_compass_counter, S_IRUGO | S_IWUSR, inv_test_show,
- inv_test_store, ATTR_DEBUG_COMPASS_COUNTER);
-static IIO_DEVICE_ATTR(test_pressure_counter, S_IRUGO | S_IWUSR, inv_test_show,
- inv_test_store, ATTR_DEBUG_PRESSURE_COUNTER);
-static IIO_DEVICE_ATTR(test_LPQ_counter, S_IRUGO | S_IWUSR, inv_test_show,
- inv_test_store, ATTR_DEBUG_LPQ_COUNTER);
-static IIO_DEVICE_ATTR(test_SIXQ_counter, S_IRUGO | S_IWUSR, inv_test_show,
- inv_test_store, ATTR_DEBUG_SIXQ_COUNTER);
-static IIO_DEVICE_ATTR(test_PEDQ_counter, S_IRUGO | S_IWUSR, inv_test_show,
- inv_test_store, ATTR_DEBUG_PEDQ_COUNTER);
-#endif
-
-static const struct attribute *inv_gyro_attributes[] = {
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
- &dev_attr_reg_dump.attr,
- &dev_attr_temperature.attr,
- &dev_attr_master_enable.attr,
- &iio_dev_attr_in_anglvel_scale.dev_attr.attr,
- &iio_dev_attr_in_anglvel_x_calibbias.dev_attr.attr,
- &iio_dev_attr_in_anglvel_y_calibbias.dev_attr.attr,
- &iio_dev_attr_in_anglvel_z_calibbias.dev_attr.attr,
- &iio_dev_attr_in_anglvel_x_offset.dev_attr.attr,
- &iio_dev_attr_in_anglvel_y_offset.dev_attr.attr,
- &iio_dev_attr_in_anglvel_z_offset.dev_attr.attr,
- &iio_dev_attr_in_anglvel_self_test_scale.dev_attr.attr,
- &iio_dev_attr_self_test_samples.dev_attr.attr,
- &iio_dev_attr_self_test_threshold.dev_attr.attr,
- &iio_dev_attr_gyro_enable.dev_attr.attr,
- &iio_dev_attr_gyro_fifo_enable.dev_attr.attr,
- &iio_dev_attr_gyro_rate.dev_attr.attr,
- &iio_dev_attr_power_state.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- &iio_dev_attr_self_test.dev_attr.attr,
- &iio_dev_attr_gyro_matrix.dev_attr.attr,
- &iio_dev_attr_secondary_name.dev_attr.attr,
-#ifdef CONFIG_INV_TESTING
- &iio_dev_attr_reg_write.dev_attr.attr,
- &iio_dev_attr_debug_smd_enable_testp1.dev_attr.attr,
- &iio_dev_attr_debug_smd_enable_testp2.dev_attr.attr,
- &iio_dev_attr_debug_smd_exe_state.dev_attr.attr,
- &iio_dev_attr_debug_smd_delay_cntr.dev_attr.attr,
- &dev_attr_test_suspend_resume.attr,
- &iio_dev_attr_test_gyro_counter.dev_attr.attr,
- &iio_dev_attr_test_accel_counter.dev_attr.attr,
- &iio_dev_attr_test_compass_counter.dev_attr.attr,
- &iio_dev_attr_test_pressure_counter.dev_attr.attr,
- &iio_dev_attr_test_LPQ_counter.dev_attr.attr,
- &iio_dev_attr_test_SIXQ_counter.dev_attr.attr,
- &iio_dev_attr_test_PEDQ_counter.dev_attr.attr,
-#endif
-};
-
-static const struct attribute *inv_mpu6xxx_attributes[] = {
- &dev_attr_event_accel_motion.attr,
- &dev_attr_event_smd.attr,
- &dev_attr_event_pedometer.attr,
- &dev_attr_flush_batch.attr,
- &iio_dev_attr_in_accel_scale.dev_attr.attr,
- &iio_dev_attr_in_accel_x_calibbias.dev_attr.attr,
- &iio_dev_attr_in_accel_y_calibbias.dev_attr.attr,
- &iio_dev_attr_in_accel_z_calibbias.dev_attr.attr,
- &iio_dev_attr_in_accel_self_test_scale.dev_attr.attr,
- &iio_dev_attr_in_accel_x_offset.dev_attr.attr,
- &iio_dev_attr_in_accel_y_offset.dev_attr.attr,
- &iio_dev_attr_in_accel_z_offset.dev_attr.attr,
- &iio_dev_attr_in_accel_x_dmp_bias.dev_attr.attr,
- &iio_dev_attr_in_accel_y_dmp_bias.dev_attr.attr,
- &iio_dev_attr_in_accel_z_dmp_bias.dev_attr.attr,
- &iio_dev_attr_in_anglvel_x_dmp_bias.dev_attr.attr,
- &iio_dev_attr_in_anglvel_y_dmp_bias.dev_attr.attr,
- &iio_dev_attr_in_anglvel_z_dmp_bias.dev_attr.attr,
- &iio_dev_attr_pedometer_int_on.dev_attr.attr,
- &iio_dev_attr_pedometer_on.dev_attr.attr,
- &iio_dev_attr_pedometer_steps.dev_attr.attr,
- &iio_dev_attr_pedometer_time.dev_attr.attr,
- &iio_dev_attr_pedometer_counter.dev_attr.attr,
- &iio_dev_attr_pedometer_step_thresh.dev_attr.attr,
- &iio_dev_attr_pedometer_int_thresh.dev_attr.attr,
- &iio_dev_attr_smd_enable.dev_attr.attr,
- &iio_dev_attr_smd_threshold.dev_attr.attr,
- &iio_dev_attr_smd_delay_threshold.dev_attr.attr,
- &iio_dev_attr_smd_delay_threshold2.dev_attr.attr,
- &iio_dev_attr_dmp_on.dev_attr.attr,
- &iio_dev_attr_dmp_int_on.dev_attr.attr,
- &iio_dev_attr_dmp_event_int_on.dev_attr.attr,
- &iio_dev_attr_step_indicator_on.dev_attr.attr,
- &iio_dev_attr_batchmode_timeout.dev_attr.attr,
- &iio_dev_attr_batchmode_wake_fifo_full_on.dev_attr.attr,
- &iio_dev_attr_six_axes_q_on.dev_attr.attr,
- &iio_dev_attr_six_axes_q_rate.dev_attr.attr,
- &iio_dev_attr_three_axes_q_on.dev_attr.attr,
- &iio_dev_attr_three_axes_q_rate.dev_attr.attr,
- &iio_dev_attr_ped_q_on.dev_attr.attr,
- &iio_dev_attr_ped_q_rate.dev_attr.attr,
- &iio_dev_attr_step_detector_on.dev_attr.attr,
- &iio_dev_attr_accel_enable.dev_attr.attr,
- &iio_dev_attr_accel_fifo_enable.dev_attr.attr,
- &iio_dev_attr_accel_rate.dev_attr.attr,
- &iio_dev_attr_firmware_loaded.dev_attr.attr,
- &iio_dev_attr_accel_matrix.dev_attr.attr,
-};
-
-static const struct attribute *inv_mpu6500_attributes[] = {
- &iio_dev_attr_motion_lpa_on.dev_attr.attr,
- &iio_dev_attr_motion_lpa_freq.dev_attr.attr,
- &iio_dev_attr_motion_lpa_threshold.dev_attr.attr,
-};
-
-static const struct attribute *inv_tap_attributes[] = {
- &dev_attr_event_tap.attr,
- &iio_dev_attr_tap_on.dev_attr.attr,
- &iio_dev_attr_tap_threshold.dev_attr.attr,
- &iio_dev_attr_tap_min_count.dev_attr.attr,
- &iio_dev_attr_tap_time.dev_attr.attr,
-};
-
-static const struct attribute *inv_display_orient_attributes[] = {
- &dev_attr_event_display_orientation.attr,
- &iio_dev_attr_display_orientation_on.dev_attr.attr,
-};
-
-static const struct attribute *inv_compass_attributes[] = {
- &iio_dev_attr_in_magn_scale.dev_attr.attr,
- &iio_dev_attr_compass_enable.dev_attr.attr,
- &iio_dev_attr_compass_rate.dev_attr.attr,
- &iio_dev_attr_compass_matrix.dev_attr.attr,
-};
-
-static const struct attribute *inv_akxxxx_attributes[] = {
-#ifdef CONFIG_INV_TESTING
- &iio_dev_attr_compass_sens.dev_attr.attr,
-#endif
-};
-
-static const struct attribute *inv_pressure_attributes[] = {
- &iio_dev_attr_pressure_enable.dev_attr.attr,
- &iio_dev_attr_pressure_rate.dev_attr.attr,
-};
-
-static const struct attribute *inv_mpu3050_attributes[] = {
- &iio_dev_attr_in_accel_scale.dev_attr.attr,
- &iio_dev_attr_accel_enable.dev_attr.attr,
- &iio_dev_attr_accel_fifo_enable.dev_attr.attr,
- &iio_dev_attr_accel_matrix.dev_attr.attr,
-};
-
-static struct attribute *inv_attributes[
- ARRAY_SIZE(inv_gyro_attributes) +
- ARRAY_SIZE(inv_mpu6xxx_attributes) +
- ARRAY_SIZE(inv_mpu6500_attributes) +
- ARRAY_SIZE(inv_compass_attributes) +
- ARRAY_SIZE(inv_akxxxx_attributes) +
- ARRAY_SIZE(inv_pressure_attributes) +
- ARRAY_SIZE(inv_tap_attributes) +
- ARRAY_SIZE(inv_display_orient_attributes) +
- 1
-];
-
-static const struct attribute_group inv_attribute_group = {
- .name = "mpu",
- .attrs = inv_attributes
-};
-
-static const struct iio_info mpu_info = {
- .driver_module = THIS_MODULE,
- .attrs = &inv_attribute_group,
-};
-
-static void inv_setup_func_ptr(struct inv_mpu_state *st)
-{
- if (st->chip_type == INV_MPU3050) {
- st->set_power_state = set_power_mpu3050;
- st->switch_gyro_engine = inv_switch_3050_gyro_engine;
- st->switch_accel_engine = inv_switch_3050_accel_engine;
- st->init_config = inv_init_config_mpu3050;
- st->setup_reg = inv_setup_reg_mpu3050;
- } else {
- st->set_power_state = set_power_itg;
- st->switch_gyro_engine = inv_switch_gyro_engine;
- st->switch_accel_engine = inv_switch_accel_engine;
- st->init_config = inv_init_config;
- st->setup_reg = inv_setup_reg;
- }
-}
-
-static int inv_detect_6xxx(struct inv_mpu_state *st)
-{
- int result;
- u8 d;
-
- result = inv_i2c_read(st, REG_WHOAMI, 1, &d);
- if (result)
- return result;
- if ((d == MPU6500_ID) || (d == MPU6515_ID)) {
- st->chip_type = INV_MPU6500;
- strcpy(st->name, "mpu6500");
- } else {
- strcpy(st->name, "mpu6050");
- }
-
- return 0;
-}
-
-static int inv_setup_vddio(struct inv_mpu_state *st)
-{
- int result;
- u8 data[1];
-
- if (INV_MPU6050 == st->chip_type) {
- result = inv_i2c_read(st, REG_YGOFFS_TC, 1, data);
- if (result)
- return result;
- data[0] &= ~BIT_I2C_MST_VDDIO;
- if (st->plat_data.level_shifter)
- data[0] |= BIT_I2C_MST_VDDIO;
- /*set up VDDIO register */
- result = inv_i2c_single_write(st, REG_YGOFFS_TC, data[0]);
- if (result)
- return result;
- }
-
- return 0;
-}
-
-/*
- * inv_check_chip_type() - check and setup chip type.
- */
-static int inv_check_chip_type(struct inv_mpu_state *st,
- const struct i2c_device_id *id, bool reset_needed)
-{
- struct inv_reg_map_s *reg;
- int result;
- int t_ind;
- struct inv_chip_config_s *conf;
- struct mpu_platform_data *plat;
-
- conf = &st->chip_config;
- plat = &st->plat_data;
- if (!strcmp(id->name, "itg3500")) {
- st->chip_type = INV_ITG3500;
- } else if (!strcmp(id->name, "mpu3050")) {
- st->chip_type = INV_MPU3050;
- } else if (!strcmp(id->name, "mpu6050")) {
- st->chip_type = INV_MPU6050;
- } else if (!strcmp(id->name, "mpu9150")) {
- st->chip_type = INV_MPU6050;
- plat->sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS;
- plat->sec_slave_id = COMPASS_ID_AK8975;
- } else if (!strcmp(id->name, "mpu6500")) {
- st->chip_type = INV_MPU6500;
- } else if (!strcmp(id->name, "mpu9250")) {
- st->chip_type = INV_MPU6500;
- plat->sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS;
- plat->sec_slave_id = COMPASS_ID_AK8963;
- } else if (!strcmp(id->name, "mpu6xxx")) {
- st->chip_type = INV_MPU6050;
- } else if (!strcmp(id->name, "mpu9350")) {
- st->chip_type = INV_MPU6500;
- plat->sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS;
- plat->sec_slave_id = COMPASS_ID_MLX90399;
- /* block use of MPU9350 in this build
- since it's not production ready */
- pr_err("MPU9350 support is not officially available yet.\n");
- return -EPERM;
- } else if (!strcmp(id->name, "mpu6515")) {
- st->chip_type = INV_MPU6500;
- } else {
- return -EPERM;
- }
- inv_setup_func_ptr(st);
- st->hw = &hw_info[st->chip_type];
- reg = &st->reg;
- st->setup_reg(reg);
-
- if (reset_needed) {
- /* reset to make sure previous state are not there */
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, BIT_H_RESET);
- if (result)
- return result;
- msleep(POWER_UP_TIME);
- }
- /* toggle power state */
- result = st->set_power_state(st, false);
- if (result)
- return result;
-
- result = st->set_power_state(st, true);
- if (result)
- return result;
-
- if (!strcmp(id->name, "mpu6xxx")) {
- /* for MPU6500, reading register need more time */
- msleep(POWER_UP_TIME);
- result = inv_detect_6xxx(st);
- if (result)
- return result;
- }
-
- if ((plat->sec_slave_type != SECONDARY_SLAVE_TYPE_NONE) ||
- (plat->aux_slave_type != SECONDARY_SLAVE_TYPE_NONE)) {
- result = inv_setup_vddio(st);
- if (result)
- return result;
- }
-
- switch (st->chip_type) {
- case INV_ITG3500:
- break;
- case INV_MPU6050:
- case INV_MPU6500:
- if (SECONDARY_SLAVE_TYPE_COMPASS == plat->sec_slave_type)
- conf->has_compass = 1;
- else
- conf->has_compass = 0;
- if (SECONDARY_SLAVE_TYPE_PRESSURE == plat->aux_slave_type)
- conf->has_pressure = 1;
- else
- conf->has_pressure = 0;
-
- break;
- case INV_MPU3050:
- if (SECONDARY_SLAVE_TYPE_ACCEL == plat->sec_slave_type) {
- if (ACCEL_ID_BMA250 == plat->sec_slave_id)
- inv_register_mpu3050_slave(st);
- }
- break;
- default:
- result = st->set_power_state(st, false);
- return -ENODEV;
- }
- if (conf->has_compass && conf->has_pressure &&
- (COMPASS_ID_MLX90399 == plat->sec_slave_id)) {
- pr_err("MLX90399 can't share slaves with others\n");
- return -EINVAL;
- }
- switch (st->chip_type) {
- case INV_MPU6050:
- result = inv_get_silicon_rev_mpu6050(st);
- break;
- case INV_MPU6500:
- result = inv_get_silicon_rev_mpu6500(st);
- break;
- default:
- result = 0;
- break;
- }
- if (result) {
- pr_err("read silicon rev error\n");
- st->set_power_state(st, false);
- return result;
- }
-
- /* turn off the gyro engine after OTP reading */
- result = st->switch_gyro_engine(st, false);
- if (result)
- return result;
- result = st->switch_accel_engine(st, false);
- if (result)
- return result;
-
- if (conf->has_compass) {
- result = inv_mpu_setup_compass_slave(st);
- if (result) {
- pr_err("compass setup failed\n");
- st->set_power_state(st, false);
- return result;
- }
- }
- if (conf->has_pressure) {
- result = inv_mpu_setup_pressure_slave(st);
- if (result) {
- pr_err("pressure setup failed\n");
- st->set_power_state(st, false);
- return result;
- }
- }
-
- t_ind = 0;
- memcpy(&inv_attributes[t_ind], inv_gyro_attributes,
- sizeof(inv_gyro_attributes));
- t_ind += ARRAY_SIZE(inv_gyro_attributes);
-
- if (INV_MPU3050 == st->chip_type && st->slave_accel != NULL) {
- memcpy(&inv_attributes[t_ind], inv_mpu3050_attributes,
- sizeof(inv_mpu3050_attributes));
- t_ind += ARRAY_SIZE(inv_mpu3050_attributes);
- inv_attributes[t_ind] = NULL;
- return 0;
- }
-
- /* all MPU6xxx based parts */
- if ((INV_MPU6050 == st->chip_type) || (INV_MPU6500 == st->chip_type)) {
- memcpy(&inv_attributes[t_ind], inv_mpu6xxx_attributes,
- sizeof(inv_mpu6xxx_attributes));
- t_ind += ARRAY_SIZE(inv_mpu6xxx_attributes);
- }
-
- /* MPU6500 only */
- if (INV_MPU6500 == st->chip_type) {
- memcpy(&inv_attributes[t_ind], inv_mpu6500_attributes,
- sizeof(inv_mpu6500_attributes));
- t_ind += ARRAY_SIZE(inv_mpu6500_attributes);
- }
-
- if (conf->has_compass) {
- memcpy(&inv_attributes[t_ind], inv_compass_attributes,
- sizeof(inv_compass_attributes));
- t_ind += ARRAY_SIZE(inv_compass_attributes);
-
- /* AKM only */
- if (st->plat_data.sec_slave_id == COMPASS_ID_AK8975 ||
- st->plat_data.sec_slave_id == COMPASS_ID_AK8972 ||
- st->plat_data.sec_slave_id == COMPASS_ID_AK09911 ||
- st->plat_data.sec_slave_id == COMPASS_ID_AK8963) {
- memcpy(&inv_attributes[t_ind], inv_akxxxx_attributes,
- sizeof(inv_akxxxx_attributes));
- t_ind += ARRAY_SIZE(inv_akxxxx_attributes);
- }
- }
-
- if (conf->has_pressure) {
- memcpy(&inv_attributes[t_ind], inv_pressure_attributes,
- sizeof(inv_pressure_attributes));
- t_ind += ARRAY_SIZE(inv_pressure_attributes);
- }
-
- inv_attributes[t_ind] = NULL;
-
- return 0;
-}
-
-/*
- * inv_create_dmp_sysfs() - create binary sysfs dmp entry.
- */
-static const struct bin_attribute dmp_firmware = {
- .attr = {
- .name = "dmp_firmware",
- .mode = S_IRUGO | S_IWUSR
- },
- .size = DMP_IMAGE_SIZE + 32,
- .read = inv_dmp_firmware_read,
- .write = inv_dmp_firmware_write,
-};
-
-static const struct bin_attribute six_q_value = {
- .attr = {
- .name = "six_axes_q_value",
- .mode = S_IWUSR
- },
- .size = QUATERNION_BYTES,
- .read = NULL,
- .write = inv_six_q_write,
-};
-
-static int inv_create_dmp_sysfs(struct iio_dev *ind)
-{
- int result;
-
- result = sysfs_create_bin_file(&ind->dev.kobj, &dmp_firmware);
- if (result)
- return result;
- result = sysfs_create_bin_file(&ind->dev.kobj, &six_q_value);
-
- return result;
-}
-
-/*
- * inv_mpu_probe() - probe function.
- */
-static int inv_mpu_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct inv_mpu_state *st;
- struct iio_dev *indio_dev;
- int result;
-
- /*
- * If we're not coming from a power-off condition, we need to
- * reset the chip as we may have gotten here via a watchdog
- * reboot, in which case the status of the chip is unknown
- * (i.e. chip is not reset by hardware on a watchdog reboot).
- */
- bool reset_needed = true;
-
-#ifdef CONFIG_DTS_INV_MPU_IIO
- enable_irq_wake(client->irq);
-#endif
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- result = -ENOSYS;
- pr_err("I2c function error\n");
- goto out_no_free;
- }
-#ifdef CONFIG_INV_KERNEL_3_10
- indio_dev = iio_device_alloc(sizeof(*st));
-#else
- indio_dev = iio_allocate_device(sizeof(*st));
-#endif
- if (indio_dev == NULL) {
- pr_err("memory allocation failed\n");
- result = -ENOMEM;
- goto out_no_free;
- }
- st = iio_priv(indio_dev);
- st->client = client;
- st->sl_handle = client->adapter;
- st->i2c_addr = client->addr;
-#ifdef CONFIG_DTS_INV_MPU_IIO
- result = invensense_mpu_parse_dt(&client->dev, &st->plat_data);
- if (result)
- goto out_free;
-
- /*Power on device.*/
- if (st->plat_data.power_on) {
- result = st->plat_data.power_on(&st->plat_data);
- if (result < 0) {
- dev_err(&client->dev,
- "power_on failed: %d\n", result);
- return result;
- }
- msleep(POWER_UP_TIME);
-
- /*
- * We don't need subsequent reset of chip as it's coming
- * from a power-off condition
- */
- reset_needed = false;
- }
-#else
- /* power is turned on inside check chip type */
- st->plat_data =
- *(struct mpu_platform_data *)dev_get_platdata(&client->dev);
-#endif
- result = inv_check_chip_type(st, id, reset_needed);
- if (result)
- goto out_free;
-
- result = st->init_config(indio_dev);
- if (result) {
- dev_err(&client->adapter->dev,
- "Could not initialize device.\n");
- goto out_free;
- }
- /* Make state variables available to all _show and _store functions. */
- i2c_set_clientdata(client, indio_dev);
- indio_dev->dev.parent = &client->dev;
- if (!strcmp(id->name, "mpu6xxx"))
- indio_dev->name = st->name;
- else
- indio_dev->name = id->name;
- indio_dev->channels = inv_mpu_channels;
- indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
-
- indio_dev->info = &mpu_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->currentmode = INDIO_DIRECT_MODE;
-
- result = inv_mpu_configure_ring(indio_dev);
- if (result) {
- pr_err("configure ring buffer fail\n");
- goto out_free;
- }
- result = iio_buffer_register(indio_dev, indio_dev->channels,
- indio_dev->num_channels);
- if (result) {
- pr_err("ring buffer register fail\n");
- goto out_unreg_ring;
- }
- st->irq = client->irq;
- result = inv_mpu_probe_trigger(indio_dev);
- if (result) {
- pr_err("trigger probe fail\n");
- goto out_remove_ring;
- }
-
- /* Tell the i2c counter, we have an IRQ */
- INV_I2C_SETIRQ(IRQ_MPU, client->irq);
-
- result = iio_device_register(indio_dev);
- if (result) {
- pr_err("IIO device register fail\n");
- goto out_remove_trigger;
- }
-
- if (INV_MPU6050 == st->chip_type ||
- INV_MPU6500 == st->chip_type) {
- result = inv_create_dmp_sysfs(indio_dev);
- if (result) {
- pr_err("create dmp sysfs failed\n");
- goto out_unreg_iio;
- }
- }
- INIT_KFIFO(st->timestamps);
- spin_lock_init(&st->time_stamp_lock);
- mutex_init(&st->suspend_resume_lock);
- result = st->set_power_state(st, false);
- if (result) {
- dev_err(&client->adapter->dev,
- "%s could not be turned off.\n", st->hw->name);
- goto out_unreg_iio;
- }
- inv_init_sensor_struct(st);
- dev_info(&client->dev, "%s is ready to go!\n",
- indio_dev->name);
-
- return 0;
-out_unreg_iio:
- iio_device_unregister(indio_dev);
-out_remove_trigger:
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
- inv_mpu_remove_trigger(indio_dev);
-out_remove_ring:
- iio_buffer_unregister(indio_dev);
-out_unreg_ring:
- inv_mpu_unconfigure_ring(indio_dev);
-out_free:
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_device_free(indio_dev);
-#else
- iio_free_device(indio_dev);
-#endif
-out_no_free:
- dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
- return -EIO;
-}
-
-static void inv_mpu_shutdown(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct inv_reg_map_s *reg;
- int result;
-
- reg = &st->reg;
- mutex_lock(&indio_dev->mlock);
- dev_dbg(&client->adapter->dev, "Shutting down %s...\n", st->hw->name);
-
- /* reset to make sure previous state are not there */
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, BIT_H_RESET);
- if (result)
- dev_err(&client->adapter->dev, "Failed to reset %s\n",
- st->hw->name);
- msleep(POWER_UP_TIME);
- /* turn off power to ensure gyro engine is off */
- result = st->set_power_state(st, false);
- if (result)
- dev_err(&client->adapter->dev, "Failed to turn off %s\n",
- st->hw->name);
- mutex_unlock(&indio_dev->mlock);
-}
-
-/*
- * inv_mpu_remove() - remove function.
- */
-static int inv_mpu_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct inv_mpu_state *st = iio_priv(indio_dev);
-
- kfifo_free(&st->timestamps);
- iio_device_unregister(indio_dev);
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
- inv_mpu_remove_trigger(indio_dev);
- iio_buffer_unregister(indio_dev);
- inv_mpu_unconfigure_ring(indio_dev);
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_device_free(indio_dev);
-#else
- iio_free_device(indio_dev);
-#endif
- dev_info(&client->adapter->dev, "inv-mpu-iio module removed.\n");
-
- return 0;
-}
-
-static int inv_setup_suspend_batchmode(struct iio_dev *indio_dev, bool suspend)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
- int result;
- int counter;
-
- if (st->chip_config.dmp_on &&
- st->chip_config.enable &&
- (!st->chip_config.dmp_event_int_on)) {
- /* turn off data interrupt in suspend mode;turn on resume */
- result = inv_set_interrupt_on_gesture_event(st, suspend);
- if (result)
- return result;
- if (suspend)
- counter = INT_MAX;
- else
- counter = st->batch.counter;
- result = write_be32_key_to_mem(st, counter, KEY_BM_BATCH_THLD);
- if (result)
- return result;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static void inv_disable_nonwake_sensors(struct inv_mpu_state *st)
-{
- int err = 0;
- if (st->chip_config.gyro_enable) {
- err = inv_switch_gyro_engine(st, false);
- if (err)
- pr_err("%s: ERROR %d disabling gyro\n", __func__, err);
- }
-
- /* don't disable accel if pedometer or significant motion is enabled */
- if (!st->ped.on && !st->chip_config.smd_enable &&
- st->chip_config.accel_enable) {
- err = inv_switch_accel_engine(st, false);
- if (err)
- pr_err("%s: ERROR %d disabling accelerometer\n",
- __func__, err);
- }
-
- if (st->sensor[SENSOR_COMPASS].on) {
- err = st->slave_compass->suspend(st);
- if (err)
- pr_err("%s: ERROR %d disabling compass\n",
- __func__, err);
- }
-}
-
-static void inv_enable_nonwake_sensors(struct inv_mpu_state *st)
-{
- int err = 0;
- if (st->chip_config.gyro_enable) {
- err = inv_switch_gyro_engine(st, true);
- if (err)
- pr_err("%s: ERROR %d restoring gyro state\n",
- __func__, err);
- }
-
- if (!st->ped.on && !st->chip_config.smd_enable &&
- st->chip_config.accel_enable) {
- err = inv_switch_accel_engine(st, true);
- if (err)
- pr_err("%s: ERROR %d restoring accelerometer state\n",
- __func__, err);
- }
-
- if (st->sensor[SENSOR_COMPASS].on) {
- err = st->slave_compass->resume(st);
- if (err)
- pr_err("%s: ERROR %d restoring compass state\n",
- __func__, err);
- }
-}
-
-/*
- * inv_mpu_resume(): resume method for this driver.
- * This method can be modified according to the request of different
- * customers. It basically undo everything suspend_noirq is doing
- * and recover the chip to what it was before suspend.
- */
-static int inv_mpu_resume(struct device *dev)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
- struct inv_mpu_state *st = iio_priv(indio_dev);
- int result;
-
- /* add code according to different request Start */
- pr_debug("%s inv_mpu_resume\n", st->hw->name);
- mutex_lock(&indio_dev->mlock);
- st->suspend_state = false;
-
- result = 0;
- if (st->chip_config.dmp_on && st->chip_config.enable) {
- result = st->set_power_state(st, true);
- enable_irq(st->client->irq);
- result |= inv_read_time_and_ticks(st, true);
- if (st->ped.int_on)
- result |= inv_enable_pedometer_interrupt(st, true);
- if (st->chip_config.display_orient_on)
- result |= inv_set_display_orient_interrupt_dmp(st,
- true);
- result |= inv_setup_suspend_batchmode(indio_dev, false);
-
- /* restore enable state all non-wakeup sensors */
- inv_enable_nonwake_sensors(st);
-
- } else if (st->chip_config.enable) {
- result = st->set_power_state(st, true);
- enable_irq(st->client->irq);
- }
- mutex_unlock(&indio_dev->mlock);
- /* add code according to different request End */
-
- return result;
-}
-
-/*
- * inv_mpu_suspend(): suspend method for this driver.
- * This method can be modified according to the request of different
- * customers. If customer want some events, such as SMD to wake up the CPU,
- * then data interrupt should be disabled in this interrupt to avoid
- * unnecessary interrupts. If customer want pedometer running while CPU is
- * asleep, then pedometer should be turned on while pedometer interrupt
- * should be turned off.
- */
-static int inv_mpu_suspend(struct device *dev)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
- struct inv_mpu_state *st = iio_priv(indio_dev);
- int result;
-
- /* add code according to different request Start */
- pr_debug("%s inv_mpu_suspend\n", st->hw->name);
-
- result = 0;
- if (st->chip_config.dmp_on && st->chip_config.enable) {
- /* turn off pedometer interrupt during suspend */
- if (st->ped.int_on)
- result |= inv_enable_pedometer_interrupt(st, false);
- /* turn off orientation interrupt during suspend */
- if (st->chip_config.display_orient_on)
- result |= inv_set_display_orient_interrupt_dmp(st,
- false);
- /* setup batch mode related during suspend */
- result = inv_setup_suspend_batchmode(indio_dev, true);
-
- /* disable all non-wakeup sensors */
- inv_disable_nonwake_sensors(st);
-
- /* disable irq's to assure inv_read_fifo() runs if pending */
- disable_irq(st->client->irq);
-
- /* only in DMP non-batch data mode, turn off the power */
- if ((!st->batch.on) && (!st->chip_config.smd_enable) &&
- (!st->ped.on))
- result |= st->set_power_state(st, false);
- } else if (st->chip_config.enable) {
- /* disable irq's to assure inv_read_fifo() runs if pending */
- disable_irq(st->client->irq);
-
- /* in non DMP case, just turn off the power */
- result |= st->set_power_state(st, false);
- }
- st->suspend_state = true;
- /* add code according to different request End */
-
- return 0;
-}
-
-static const struct dev_pm_ops inv_mpu_pmops = {
- .suspend = inv_mpu_suspend,
- .resume = inv_mpu_resume,
-};
-#define INV_MPU_PMOPS (&inv_mpu_pmops)
-#else
-#define INV_MPU_PMOPS NULL
-#endif /* CONFIG_PM */
-
-static const u16 normal_i2c[] = { I2C_CLIENT_END };
-/* device id table is used to identify what device can be
- * supported by this driver
- */
-static const struct i2c_device_id inv_mpu_id[] = {
- {"itg3500", INV_ITG3500},
- {"mpu3050", INV_MPU3050},
- {"mpu6050", INV_MPU6050},
- {"mpu9150", INV_MPU9150},
- {"mpu6500", INV_MPU6500},
- {"mpu9250", INV_MPU9250},
- {"mpu6xxx", INV_MPU6XXX},
- {"mpu9350", INV_MPU9350},
- {"mpu6515", INV_MPU6515},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
-
-static struct i2c_driver inv_mpu_driver = {
- .class = I2C_CLASS_HWMON,
- .probe = inv_mpu_probe,
- .remove = inv_mpu_remove,
- .shutdown = inv_mpu_shutdown,
- .id_table = inv_mpu_id,
- .driver = {
- .owner = THIS_MODULE,
- .name = "inv-mpu-iio",
- .pm = INV_MPU_PMOPS,
- },
- .address_list = normal_i2c,
-};
-
-static int __init inv_mpu_init(void)
-{
- int result = i2c_add_driver(&inv_mpu_driver);
- if (result) {
- pr_err("failed\n");
- return result;
- }
- return 0;
-}
-
-static void __exit inv_mpu_exit(void)
-{
- i2c_del_driver(&inv_mpu_driver);
-}
-
-module_init(inv_mpu_init);
-module_exit(inv_mpu_exit);
-
-MODULE_AUTHOR("Invensense Corporation");
-MODULE_DESCRIPTION("Invensense device driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("inv-mpu-iio");
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_dts.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_dts.c
deleted file mode 100755
index 276d5bcfea7..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_dts.c
+++ /dev/null
@@ -1,270 +0,0 @@
-#include <linux/err.h>
-#include <linux/of_gpio.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/regulator/consumer.h>
-
-#include <linux/i2c.h>
-#include <linux/mpu.h>
-#include "inv_mpu_dts.h"
-
-int inv_mpu_power_on(struct mpu_platform_data *pdata)
-{
- int err ;
-
- err = regulator_enable(pdata->vdd_ana);
- err = regulator_enable(pdata->vdd_i2c);
- pr_debug(KERN_INFO "inv_mpu_power_on call");
-
- return err ;
-
-}
-
-int inv_mpu_power_off(struct mpu_platform_data *pdata)
-{
- int err ;
-
- err = regulator_disable(pdata->vdd_ana);
- err = regulator_disable(pdata->vdd_i2c);
- pr_debug(KERN_INFO "inv_mpu_power_off call");
-
- return err;
-}
-
-int inv_parse_orientation_matrix(struct device *dev, s8 *orient)
-{
- int rc, i;
- struct device_node *np = dev->of_node;
- u32 temp_val, temp_val2;
-
- for (i = 0; i < 9; i++)
- orient[i] = 0;
-
- /* parsing axis x orientation matrix*/
- rc = of_property_read_u32(np, "axis_map_x", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read axis_map_x\n");
- return rc;
- }
- rc = of_property_read_u32(np, "negate_x", &temp_val2);
- if (rc) {
- dev_err(dev, "Unable to read negate_x\n");
- return rc;
- }
- if (temp_val2)
- orient[temp_val] = -1;
- else
- orient[temp_val] = 1;
-
- /* parsing axis y orientation matrix*/
- rc = of_property_read_u32(np, "axis_map_y", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read axis_map_y\n");
- return rc;
- }
- rc = of_property_read_u32(np, "negate_y", &temp_val2);
- if (rc) {
- dev_err(dev, "Unable to read negate_y\n");
- return rc;
- }
- if (temp_val2)
- orient[3 + temp_val] = -1;
- else
- orient[3 + temp_val] = 1;
-
- /* parsing axis z orientation matrix*/
- rc = of_property_read_u32(np, "axis_map_z", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read axis_map_z\n");
- return rc;
- }
- rc = of_property_read_u32(np, "negate_z", &temp_val2);
- if (rc) {
- dev_err(dev, "Unable to read negate_z\n");
- return rc;
- }
- if (temp_val2)
- orient[6 + temp_val] = -1;
- else
- orient[6 + temp_val] = 1;
-
- return 0;
-}
-
-int inv_parse_secondary_orientation_matrix(struct device *dev,
- s8 *orient)
-{
- int rc, i;
- struct device_node *np = dev->of_node;
- u32 temp_val, temp_val2;
-
- for (i = 0; i < 9; i++)
- orient[i] = 0;
-
- /* parsing axis x orientation matrix*/
- rc = of_property_read_u32(np, "inven,secondary_axis_map_x", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read secondary axis_map_x\n");
- return rc;
- }
- rc = of_property_read_u32(np, "inven,secondary_negate_x", &temp_val2);
- if (rc) {
- dev_err(dev, "Unable to read secondary negate_x\n");
- return rc;
- }
- if (temp_val2)
- orient[temp_val] = -1;
- else
- orient[temp_val] = 1;
-
- /* parsing axis y orientation matrix*/
- rc = of_property_read_u32(np, "inven,secondary_axis_map_y", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read secondary axis_map_y\n");
- return rc;
- }
- rc = of_property_read_u32(np, "inven,secondary_negate_y", &temp_val2);
- if (rc) {
- dev_err(dev, "Unable to read secondary negate_y\n");
- return rc;
- }
- if (temp_val2)
- orient[3 + temp_val] = -1;
- else
- orient[3 + temp_val] = 1;
-
- /* parsing axis z orientation matrix*/
- rc = of_property_read_u32(np, "inven,secondary_axis_map_z", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read secondary axis_map_z\n");
- return rc;
- }
- rc = of_property_read_u32(np, "inven,secondary_negate_z", &temp_val2);
- if (rc) {
- dev_err(dev, "Unable to read secondary negate_z\n");
- return rc;
- }
- if (temp_val2)
- orient[6 + temp_val] = -1;
- else
- orient[6 + temp_val] = 1;
-
- return 0;
-}
-
-int inv_parse_secondary(struct device *dev, struct mpu_platform_data *pdata)
-{
- int rc;
- struct device_node *np = dev->of_node;
- u32 temp_val;
- const char *name;
-
- if (of_property_read_string(np, "inven,secondary_type", &name)) {
- dev_err(dev, "Missing secondary type.\n");
- return -EINVAL;
- }
- if (!strcmp(name, "compass")) {
- pdata->sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS;
- } else if (!strcmp(name, "none")) {
- pdata->sec_slave_type = SECONDARY_SLAVE_TYPE_NONE;
- return 0;
- } else {
- return -EINVAL;
- }
-
- if (of_property_read_string(np, "inven,secondary_name", &name)) {
- dev_err(dev, "Missing secondary name.\n");
- return -EINVAL;
- }
- if (!strcmp(name, "ak8963"))
- pdata->sec_slave_id = COMPASS_ID_AK8963;
- else if (!strcmp(name, "ak8975"))
- pdata->sec_slave_id = COMPASS_ID_AK8975;
- else if (!strcmp(name, "ak8972"))
- pdata->sec_slave_id = COMPASS_ID_AK8972;
- else
- return -EINVAL;
- rc = of_property_read_u32(np, "inven,secondary_reg", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read secondary register\n");
- return rc;
- }
- pdata->secondary_i2c_addr = temp_val;
- rc = inv_parse_secondary_orientation_matrix(dev,
- pdata->secondary_orientation);
-
- return rc;
-}
-
-int inv_parse_aux(struct device *dev, struct mpu_platform_data *pdata)
-{
- int rc;
- struct device_node *np = dev->of_node;
- u32 temp_val;
- const char *name;
-
- if (of_property_read_string(np, "inven,aux_type", &name)) {
- dev_err(dev, "Missing aux type.\n");
- return -EINVAL;
- }
- if (!strcmp(name, "pressure")) {
- pdata->aux_slave_type = SECONDARY_SLAVE_TYPE_PRESSURE;
- } else if (!strcmp(name, "none")) {
- pdata->aux_slave_type = SECONDARY_SLAVE_TYPE_NONE;
- return 0;
- } else {
- return -EINVAL;
- }
-
- if (of_property_read_string(np, "inven,aux_name", &name)) {
- dev_err(dev, "Missing aux name.\n");
- return -EINVAL;
- }
- if (!strcmp(name, "bmp280"))
- pdata->aux_slave_id = PRESSURE_ID_BMP280;
- else
- return -EINVAL;
-
- rc = of_property_read_u32(np, "inven,aux_reg", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read aux register\n");
- return rc;
- }
- pdata->aux_i2c_addr = temp_val;
-
- return 0;
-}
-
-int invensense_mpu_parse_dt(struct device *dev, struct mpu_platform_data *pdata)
-{
- int rc;
- pr_debug("Invensense MPU parse_dt started.\n");
-
- rc = inv_parse_orientation_matrix(dev, pdata->orientation);
- if (rc)
- return rc;
-
- rc = inv_parse_secondary(dev, pdata);
- if (rc)
- return rc;
-
- inv_parse_aux(dev, pdata);
-
- pdata->vdd_ana = regulator_get(dev, "inven,vdd_ana");
- if (IS_ERR(pdata->vdd_ana)) {
- rc = PTR_ERR(pdata->vdd_ana);
- dev_err(dev, "Regulator get failed vdd_ana-supply rc=%d\n", rc);
- return rc;
- }
- pdata->vdd_i2c = regulator_get(dev, "inven,vcc_i2c");
- if (IS_ERR(pdata->vdd_i2c)) {
- rc = PTR_ERR(pdata->vdd_i2c);
- dev_err(dev, "Regulator get failed vcc-i2c-supply rc=%d\n", rc);
- return rc;
- }
- pdata->power_on = inv_mpu_power_on;
- pdata->power_off = inv_mpu_power_off;
- pr_debug("Invensense MPU parse_dt complete.\n");
- return rc;
-}
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_dts.h b/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_dts.h
deleted file mode 100755
index 151ac74ea05..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_dts.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#ifndef _INV_MPU_DTS_H_
-#define _INV_MPU_DTS_H_
-
-#include <linux/i2c.h>
-#include <linux/mpu.h>
-
-int inv_mpu_power_on(struct mpu_platform_data *pdata);
-int inv_mpu_power_off(struct mpu_platform_data *pdata);
-int inv_parse_orientation_matrix(struct device *dev, s8 *orient);
-int inv_parse_secondary_orientation_matrix(struct device *dev,
- s8 *orient);
-int inv_parse_secondary(struct device *dev, struct mpu_platform_data *pdata);
-int inv_parse_aux(struct device *dev, struct mpu_platform_data *pdata);
-int invensense_mpu_parse_dt(struct device *dev,
- struct mpu_platform_data *pdata);
-
-#endif /* #ifndef _INV_MPU_DTS_H_ */
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_iio.h b/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_iio.h
deleted file mode 100644
index 701d4db78ed..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_iio.h
+++ /dev/null
@@ -1,1078 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#ifndef _INV_MPU_IIO_H_
-#define _INV_MPU_IIO_H_
-
-#include <linux/i2c.h>
-#include <linux/kfifo.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-#include <linux/mpu.h>
-
-#include "iio.h"
-#include "buffer.h"
-
-#include "dmpKey.h"
-
-/*register and associated bit definition*/
-#define REG_3050_FIFO_EN 0x12
-#define BITS_3050_ACCEL_OUT 0x0E
-
-#define REG_3050_AUX_VDDIO 0x13
-#define BIT_3050_VDDIO 0x04
-
-#define REG_3050_SLAVE_ADDR 0x14
-#define REG_3050_SAMPLE_RATE_DIV 0x15
-#define REG_3050_LPF 0x16
-#define REG_3050_INT_ENABLE 0x17
-#define REG_3050_AUX_BST_ADDR 0x18
-#define REG_3050_INT_STATUS 0x1A
-#define REG_3050_TEMPERATURE 0x1B
-#define REG_3050_RAW_GYRO 0x1D
-#define REG_3050_AUX_XOUT_H 0x23
-#define REG_3050_FIFO_COUNT_H 0x3A
-#define REG_3050_FIFO_R_W 0x3C
-
-#define REG_3050_USER_CTRL 0x3D
-#define BIT_3050_AUX_IF_EN 0x20
-#define BIT_3050_FIFO_RST 0x02
-
-#define REG_3050_PWR_MGMT_1 0x3E
-#define BITS_3050_POWER1 0x30
-#define BITS_3050_POWER2 0x10
-#define BITS_3050_GYRO_STANDBY 0x38
-
-#define REG_3500_OTP 0x0
-
-#define REG_YGOFFS_TC 0x1
-#define BIT_I2C_MST_VDDIO 0x80
-
-#define REG_XA_OFFS_H 0x6
-#define REG_XA_OFFS_L_TC 0x7
-#define REG_PRODUCT_ID 0xC
-#define REG_ST_GCT_X 0xD
-#define REG_XG_OFFS_USRH 0x13
-#define REG_SAMPLE_RATE_DIV 0x19
-#define REG_CONFIG 0x1A
-
-#define REG_GYRO_CONFIG 0x1B
-#define BITS_SELF_TEST_EN 0xE0
-
-#define REG_ACCEL_CONFIG 0x1C
-#define REG_ACCEL_MOT_THR 0x1F
-#define REG_ACCEL_MOT_DUR 0x20
-
-#define REG_FIFO_EN 0x23
-#define BIT_ACCEL_OUT 0x08
-#define BITS_GYRO_OUT 0x70
-
-#define REG_I2C_MST_CTRL 0x24
-#define BIT_WAIT_FOR_ES 0x40
-
-#define REG_I2C_SLV0_ADDR 0x25
-#define REG_I2C_SLV0_REG 0x26
-#define REG_I2C_SLV0_CTRL 0x27
-#define REG_I2C_SLV1_ADDR 0x28
-#define REG_I2C_SLV1_REG 0x29
-#define REG_I2C_SLV1_CTRL 0x2A
-#define REG_I2C_SLV2_ADDR 0x2B
-#define REG_I2C_SLV2_REG 0x2C
-#define REG_I2C_SLV2_CTRL 0x2D
-#define REG_I2C_SLV3_ADDR 0x2E
-#define REG_I2C_SLV3_REG 0x2F
-#define REG_I2C_SLV3_CTRL 0x30
-#define REG_I2C_SLV4_CTRL 0x34
-
-#define INV_MPU_BIT_SLV_EN 0x80
-#define INV_MPU_BIT_BYTE_SW 0x40
-#define INV_MPU_BIT_REG_DIS 0x20
-#define INV_MPU_BIT_GRP 0x10
-#define INV_MPU_BIT_I2C_READ 0x80
-
-#define REG_INT_PIN_CFG 0x37
-#define BIT_BYPASS_EN 0x2
-
-#define REG_INT_ENABLE 0x38
-#define BIT_DATA_RDY_EN 0x01
-#define BIT_DMP_INT_EN 0x02
-#define BIT_ZMOT_EN 0x20
-#define BIT_MOT_EN 0x40
-#define BIT_6500_WOM_EN 0x40
-
-#define REG_DMP_INT_STATUS 0x39
-#define BIT_DMP_INT_CI 0x01
-
-#define REG_INT_STATUS 0x3A
-#define BIT_MOT_INT 0x40
-#define BIT_ZMOT_INT 0x20
-
-#define REG_RAW_ACCEL 0x3B
-#define REG_TEMPERATURE 0x41
-#define REG_EXT_SENS_DATA_00 0x49
-#define REG_EXT_SENS_DATA_08 0x51
-#define REG_EXT_SENS_DATA_09 0x52
-
-#define REG_ACCEL_INTEL_STATUS 0x61
-
-#define INV_MPU_REG_I2C_SLV0_DO 0x63
-#define INV_MPU_REG_I2C_SLV1_DO 0x64
-#define INV_MPU_REG_I2C_SLV2_DO 0x65
-#define INV_MPU_REG_I2C_SLV3_DO 0x66
-
-#define REG_I2C_MST_DELAY_CTRL 0x67
-#define BIT_SLV0_DLY_EN 0x01
-#define BIT_SLV1_DLY_EN 0x02
-#define BIT_SLV2_DLY_EN 0x04
-#define BIT_SLV3_DLY_EN 0x08
-
-#define REG_USER_CTRL 0x6A
-#define BIT_FIFO_RST 0x04
-#define BIT_DMP_RST 0x08
-#define BIT_I2C_MST_EN 0x20
-#define BIT_FIFO_EN 0x40
-#define BIT_DMP_EN 0x80
-
-#define REG_PWR_MGMT_1 0x6B
-#define BIT_H_RESET 0x80
-#define BIT_SLEEP 0x40
-#define BIT_CYCLE 0x20
-#define BIT_CLK_MASK 0x7
-
-#define REG_PWR_MGMT_2 0x6C
-#define BIT_PWR_ACCEL_STBY 0x38
-#define BIT_PWR_GYRO_STBY 0x07
-#define BIT_LPA_FREQ 0xC0
-
-#define REG_BANK_SEL 0x6D
-#define REG_MEM_START_ADDR 0x6E
-#define REG_MEM_RW 0x6F
-#define REG_PRGM_STRT_ADDRH 0x70
-#define REG_FIFO_COUNT_H 0x72
-#define REG_FIFO_R_W 0x74
-#define REG_WHOAMI 0x75
-
-#define REG_6500_XG_ST_DATA 0x0
-#define REG_6500_XA_ST_DATA 0xD
-#define REG_6500_XA_OFFS_H 0x77
-#define REG_6500_YA_OFFS_H 0x7A
-#define REG_6500_ZA_OFFS_H 0x7D
-#define REG_6500_ACCEL_CONFIG2 0x1D
-#define BIT_ACCEL_FCHOCIE_B 0x08
-#define BIT_FIFO_SIZE_1K 0x40
-
-#define REG_6500_LP_ACCEL_ODR 0x1E
-#define REG_6500_ACCEL_WOM_THR 0x1F
-
-#define REG_6500_ACCEL_INTEL_CTRL 0x69
-#define BIT_ACCEL_INTEL_ENABLE 0x80
-#define BIT_ACCEL_INTEL_MODE 0x40
-
-/* data definitions */
-#define DMP_START_ADDR 0x400
-#define DMP_MASK_TAP 0x3f
-#define DMP_MASK_DIS_ORIEN 0xC0
-#define DMP_DIS_ORIEN_SHIFT 6
-/* this is derived from 1000 divided by 50, which is the pedometer
- running frequency */
-#define MS_PER_PED_TICKS 20
-
-
-#define BYTES_FOR_DMP 8
-#define BYTES_FOR_EVENTS 4
-#define QUATERNION_BYTES 16
-#define BYTES_PER_SENSOR 6
-#define MPU3050_FOOTER_SIZE 2
-#define FIFO_COUNT_BYTE 2
-#define FIFO_THRESHOLD 800
-#define FIFO_SIZE 992
-#define HARDWARE_FIFO_SIZE 1024
-#define MAX_READ_SIZE 64
-#define POWER_UP_TIME 100
-#define SENSOR_UP_TIME 30
-#define REG_UP_TIME 2
-#define INV_MPU_SAMPLE_RATE_CHANGE_STABLE 50
-#define MPU_MEM_BANK_SIZE 256
-#define SELF_TEST_GYRO_FULL_SCALE 250
-#define SELF_TEST_ACCEL_FULL_SCALE 8
-#define SELF_TEST_ACCEL_6500_SCALE 2
-
-/* data header defines */
-#define PRESSURE_HDR 0x8000
-#define ACCEL_HDR 0x4000
-#define GYRO_HDR 0x2000
-#define COMPASS_HDR 0x1000
-#define COMPASS_HDR_2 0x1800
-#define LPQUAT_HDR 0x0800
-#define SIXQUAT_HDR 0x0400
-#define PEDQUAT_HDR 0x0200
-#define STEP_DETECTOR_HDR 0x0100
-#define STEP_INDICATOR_MASK 0xf
-
-#define MAX_BYTES_PER_SAMPLE 80
-#define MAX_HW_FIFO_BYTES (BYTES_PER_SENSOR * 2)
-#define IIO_BUFFER_BYTES 8
-#define HEADERED_NORMAL_BYTES 8
-#define HEADERED_Q_BYTES 16
-
-#define MPU6XXX_MAX_MOTION_THRESH (255*4)
-#define MPU6050_MOTION_THRESH_SHIFT 5
-#define MPU6500_MOTION_THRESH_SHIFT 2
-#define MPU6050_MOTION_DUR_DEFAULT 1
-#define MPU6050_ID 0x68
-#define MPU6050_MAX_MOTION_DUR 255
-#define MPU_TEMP_SHIFT 16
-#define LPA_FREQ_SHIFT 6
-#define COMPASS_RATE_SCALE 10
-#define MAX_GYRO_FS_PARAM 3
-#define MAX_ACCEL_FS_PARAM 3
-#define MAX_LPA_FREQ_PARAM 3
-#define MPU_MAX_A_OFFSET_VALUE 16383
-#define MPU_MIN_A_OFFSET_VALUE -16384
-#define MPU_MAX_G_OFFSET_VALUE 32767
-#define MPU_MIN_G_OFFSET_VALUE -32767
-#define MPU6XXX_MAX_MPU_MEM (256 * 12)
-
-#define INIT_MOT_DUR 128
-#define INIT_MOT_THR 128
-#define INIT_ZMOT_DUR 128
-#define INIT_ZMOT_THR 128
-#define INIT_ST_SAMPLES 200
-#define INIT_ST_MPU6050_SAMPLES 600
-#define INIT_ST_THRESHOLD 50
-#define INIT_PED_INT_THRESH 2
-#define INIT_PED_THRESH 9
-#define ST_THRESHOLD_MULTIPLIER 10
-#define ST_MAX_SAMPLES 500
-#define ST_MAX_THRESHOLD 100
-#define DMP_INTERVAL_INIT (5 * NSEC_PER_MSEC)
-#define DMP_INTERVAL_MIN_ADJ (50 * NSEC_PER_USEC)
-
-/*---- MPU6500 ----*/
-#define MPU6500_ID 0x70 /* unique WHOAMI */
-#define MPU6515_ID 0x74 /* unique WHOAMI */
-#define MPU6500_PRODUCT_REVISION 1
-#define MPU6500_MEM_REV_ADDR 0x16
-#define INV_MPU_REV_MASK 0x0F
-#define MPU6500_REV 2
-#define MPU_DMP_LOAD_START 0x20
-
-/*---- MPU9250 ----*/
-#define MPU9250_ID 0x71 /* unique WHOAMI */
-
-/* ----MPU9350 ----*/
-#define MPU9350_ID 0x72
-
-#define THREE_AXIS 3
-#define GYRO_CONFIG_FSR_SHIFT 3
-#define ACCEL_CONFIG_FSR_SHIFT 3
-#define GYRO_DPS_SCALE 250
-#define MEM_ADDR_PROD_REV 0x6
-#define SOFT_PROD_VER_BYTES 5
-#define CRC_FIRMWARE_SEED 0
-#define SELF_TEST_SUCCESS 1
-#define MS_PER_DMP_TICK 20
-#define DMP_IMAGE_SIZE 2943
-
-/* init parameters */
-#define INIT_FIFO_RATE 50
-#define INIT_DMP_OUTPUT_RATE 25
-#define INIT_DUR_TIME (NSEC_PER_SEC / INIT_FIFO_RATE)
-#define INIT_TAP_THRESHOLD 100
-#define INIT_TAP_TIME 100
-#define INIT_TAP_MIN_COUNT 2
-#define INIT_SAMPLE_DIVIDER 4
-#define MPU_INIT_SMD_DELAY_THLD 3
-#define MPU_INIT_SMD_DELAY2_THLD 1
-#define MPU_INIT_SMD_THLD 1500
-#define MPU_DEFAULT_DMP_FREQ 200
-#define MPL_PROD_KEY(ver, rev) (ver * 100 + rev)
-#define NUM_OF_PROD_REVS (ARRAY_SIZE(prod_rev_map))
-/*---- MPU6050 Silicon Revisions ----*/
-#define MPU_SILICON_REV_A2 1 /* MPU6050A2 Device */
-#define MPU_SILICON_REV_B1 2 /* MPU6050B1 Device */
-
-#define BIT_PRFTCH_EN 0x40
-#define BIT_CFG_USER_BANK 0x20
-#define BITS_MEM_SEL 0x1f
-
-#define TIME_STAMP_TOR 5
-#define MAX_CATCH_UP 5
-#define DMP_TICK_DUR 5
-#define DEFAULT_ACCEL_TRIM 16384
-#define DEFAULT_GYRO_TRIM 131
-#define MAX_FIFO_RATE 1000
-#define MAX_DMP_OUTPUT_RATE 200
-#define MIN_FIFO_RATE 4
-#define ONE_K_HZ 1000
-#define NS_PER_MS_SHIFT 20
-#define END_MARKER 0x0010
-#define EMPTY_MARKER 0x0020
-
-/*tap related defines */
-#define INV_TAP 0x08
-#define INV_NUM_TAP_AXES 3
-
-#define INV_TAP_AXIS_X_POS 0x20
-#define INV_TAP_AXIS_X_NEG 0x10
-#define INV_TAP_AXIS_Y_POS 0x08
-#define INV_TAP_AXIS_Y_NEG 0x04
-#define INV_TAP_AXIS_Z_POS 0x02
-#define INV_TAP_AXIS_Z_NEG 0x01
-#define INV_TAP_ALL_DIRECTIONS 0x3f
-
-#define INV_TAP_AXIS_X 0x1
-#define INV_TAP_AXIS_Y 0x2
-#define INV_TAP_AXIS_Z 0x4
-
-#define INV_TAP_AXIS_ALL \
- (INV_TAP_AXIS_X | \
- INV_TAP_AXIS_Y | \
- INV_TAP_AXIS_Z)
-
-#define INT_SRC_TAP 0x01
-#define INT_SRC_DISPLAY_ORIENT 0x08
-#define INT_SRC_SHAKE 0x10
-
-#define INV_X_AXIS_INDEX 0x00
-#define INV_Y_AXIS_INDEX 0x01
-#define INV_Z_AXIS_INDEX 0x02
-
-#define INV_ELEMENT_1 0x0001
-#define INV_ELEMENT_2 0x0002
-#define INV_ELEMENT_3 0x0004
-#define INV_ELEMENT_4 0x0008
-#define INV_ELEMENT_5 0x0010
-#define INV_ELEMENT_6 0x0020
-#define INV_ELEMENT_7 0x0040
-#define INV_ELEMENT_8 0x0080
-#define INV_ALL 0xFFFF
-#define INV_ELEMENT_MASK 0x00FF
-#define INV_GYRO_ACC_MASK 0x007E
-#define INV_ACCEL_MASK 0x70
-#define INV_GYRO_MASK 0xE
-
-struct inv_mpu_state;
-
-/**
- * struct inv_reg_map_s - Notable slave registers.
- * @sample_rate_div: Divider applied to gyro output rate.
- * @lpf: Configures internal LPF.
- * @bank_sel: Selects between memory banks.
- * @user_ctrl: Enables/resets the FIFO.
- * @fifo_en: Determines which data will appear in FIFO.
- * @gyro_config: gyro config register.
- * @accel_config: accel config register
- * @fifo_count_h: Upper byte of FIFO count.
- * @fifo_r_w: FIFO register.
- * @raw_accel Address of first accel register.
- * @temperature temperature register
- * @int_enable: Interrupt enable register.
- * @int_status: Interrupt flags.
- * @pwr_mgmt_1: Controls chip's power state and clock source.
- * @pwr_mgmt_2: Controls power state of individual sensors.
- * @mem_start_addr: Address of first memory read.
- * @mem_r_w: Access to memory.
- * @prgm_strt_addrh firmware program start address register
- */
-struct inv_reg_map_s {
- u8 sample_rate_div;
- u8 lpf;
- u8 bank_sel;
- u8 user_ctrl;
- u8 fifo_en;
- u8 gyro_config;
- u8 accel_config;
- u8 fifo_count_h;
- u8 fifo_r_w;
- u8 raw_accel;
- u8 temperature;
- u8 int_enable;
- u8 int_status;
- u8 pwr_mgmt_1;
- u8 pwr_mgmt_2;
- u8 mem_start_addr;
- u8 mem_r_w;
- u8 prgm_strt_addrh;
-};
-
-/* device enum */
-enum inv_devices {
- INV_ITG3500,
- INV_MPU3050,
- INV_MPU6050,
- INV_MPU9150,
- INV_MPU6500,
- INV_MPU9250,
- INV_MPU6XXX,
- INV_MPU9350,
- INV_MPU6515,
- INV_NUM_PARTS
-};
-
-/**
- * struct inv_hw_s - Other important hardware information.
- * @num_reg: Number of registers on device.
- * @name: name of the chip
- */
-struct inv_hw_s {
- u8 num_reg;
- u8 *name;
-};
-
-/* enum for sensor */
-enum INV_SENSORS {
- SENSOR_GYRO = 0,
- SENSOR_ACCEL,
- SENSOR_COMPASS,
- SENSOR_PRESSURE,
- SENSOR_STEP,
- SENSOR_PEDQ,
- SENSOR_SIXQ,
- SENSOR_LPQ,
- SENSOR_NUM_MAX,
- SENSOR_INVALID,
-};
-
-/**
- * struct inv_sensor - information for each sensor.
- * @ts: this sensors timestamp.
- * @dur: duration between samples in ns.
- * @rate: sensor data rate.
- * @counter: dmp tick counter corresponding to rate.
- * @on: sensor on/off.
- * @sample_size: number of bytes for the sensor.
- * @send_data: function pointer to send data or not.
- * @set_rate: funcition pointer to set data rate.
- */
-struct inv_sensor {
- u64 ts;
- int dur;
- int rate;
- int counter;
- bool on;
- u8 sample_size;
- int (*send_data)(struct inv_mpu_state *st, bool on);
- int (*set_rate)(struct inv_mpu_state *st);
-};
-
-/**
- * struct inv_batch - information batchmode.
- * @on: derived variable for batch mode.
- * @overflow_on: overflow mode for batchmode.
- * @wake_fifo_on: overflow for suspend mode.
- * @counter: counter for batch mode.
- * @timeout: nominal timeout value for batchmode in milliseconds.
- * @min_rate: minimum sensor rate that is turned on.
- */
-struct inv_batch {
- bool on;
- bool overflow_on;
- bool wake_fifo_on;
- u32 counter;
- u32 timeout;
- u32 min_rate;
-};
-
-/**
- * struct inv_chip_config_s - Cached chip configuration data.
- * @fsr: Full scale range.
- * @lpf: Digital low pass filter frequency.
- * @accel_fs: accel full scale range.
- * @has_footer: MPU3050 specific work around.
- * @has_compass: has compass or not.
- * @has_pressure: has pressure sensor or not.
- * @enable: master enable to enable output
- * @accel_enable: enable accel functionality
- * @gyro_enable: enable gyro functionality
- * @is_asleep: 1 if chip is powered down.
- * @dmp_on: dmp is on/off.
- * @dmp_int_on: dmp interrupt on/off.
- * @step_indicator_on: step indicate bit added to the sensor or not.
- * @dmp_event_int_on: dmp event interrupt on/off.
- * @firmware_loaded: flag indicate firmware loaded or not.
- * @lpa_mod: low power mode.
- * @display_orient_on: display orientation on/off.
- * @normal_compass_measure: discard first compass data after reset.
- * @normal_pressure_measure: discard first pressure data after reset.
- * @smd_enable: disable/enable SMD function.
- * @adjust_time: flag to indicate whether adjust chip clock or not.
- * @smd_triggered: smd is triggered.
- * @lpa_freq: low power frequency
- * @prog_start_addr: firmware program start address.
- * @fifo_rate: current FIFO update rate.
- * @bytes_per_datum: number of bytes for 1 sample data.
- */
-struct inv_chip_config_s {
- u32 fsr:2;
- u32 lpf:3;
- u32 accel_fs:2;
- u32 has_footer:1;
- u32 has_compass:1;
- u32 has_pressure:1;
- u32 enable:1;
- u32 accel_enable:1;
- u32 gyro_enable:1;
- u32 is_asleep:1;
- u32 dmp_on:1;
- u32 dmp_int_on:1;
- u32 dmp_event_int_on:1;
- u32 step_indicator_on:1;
- u32 firmware_loaded:1;
- u32 lpa_mode:1;
- u32 display_orient_on:1;
- u32 normal_compass_measure:1;
- u32 normal_pressure_measure:1;
- u32 smd_enable:1;
- u32 adjust_time:1;
- u32 smd_triggered:1;
- u16 lpa_freq;
- u16 prog_start_addr;
- u16 fifo_rate;
- u16 bytes_per_datum;
-};
-
-/**
- * struct inv_chip_info_s - Chip related information.
- * @product_id: Product id.
- * @product_revision: Product revision.
- * @silicon_revision: Silicon revision.
- * @software_revision: software revision.
- * @multi: accel specific multiplier.
- * @compass_sens: compass sensitivity.
- * @gyro_sens_trim: Gyro sensitivity trim factor.
- * @accel_sens_trim: accel sensitivity trim factor.
- */
-struct inv_chip_info_s {
- u8 product_id;
- u8 product_revision;
- u8 silicon_revision;
- u8 software_revision;
- u8 multi;
- u8 compass_sens[3];
- u32 gyro_sens_trim;
- u32 accel_sens_trim;
-};
-
-/**
- * struct inv_tap structure to store tap data.
- * @min_count: minimum taps counted.
- * @thresh: tap threshold.
- * @time: tap time.
- * @on: tap on/off.
- */
-struct inv_tap {
- u16 min_count;
- u16 thresh;
- u16 time;
- bool on;
-};
-
-/**
- * struct accel_mot_int_s structure to store motion interrupt data
- * @mot_thr: motion threshold.
- * @mot_dur: motion duration.
- * @mot_on: flag to indicate motion detection on;
- */
-struct accel_mot_int {
- u16 mot_thr;
- u32 mot_dur;
- u8 mot_on:1;
-};
-
-/**
- * struct self_test_setting - self test settables from sysfs
- * samples: number of samples used in self test.
- * threshold: threshold fail/pass criterion in self test.
- * This value is in the percentage multiplied by 100.
- * So 14% would be 14.
- */
-struct self_test_setting {
- u16 samples;
- u16 threshold;
-};
-
-/**
- * struct inv_smd significant motion detection structure.
- * @threshold: accel threshold for motion detection.
- * @delay: delay time to confirm 2nd motion.
- * @delay2: delay window parameter.
- */
-struct inv_smd {
- u32 threshold;
- u32 delay;
- u32 delay2;
-};
-
-/**
- * struct inv_ped pedometer related data structure.
- * @step: steps taken.
- * @time: time taken during the period.
- * @last_step_time: last time the step is taken.
- * @step_thresh: step threshold to show steps.
- * @int_thresh: step threshold to generate interrupt.
- * @int_on: pedometer interrupt enable/disable.
- * @on: pedometer on/off.
- */
-struct inv_ped {
- u64 step;
- u64 time;
- u64 last_step_time;
- u16 step_thresh;
- u16 int_thresh;
- bool int_on;
- bool on;
-};
-
-struct inv_mpu_slave;
-/**
- * struct inv_mpu_state - Driver state variables.
- * @chip_config: Cached attribute information.
- * @chip_info: Chip information from read-only registers.
- * @trig; iio trigger.
- * @tap: tap data structure.
- * @smd: SMD data structure.
- * @ped: pedometer data structure.
- * @batch: batchmode data structure.
- * @reg: Map of important registers.
- * @self_test: self test settings.
- * @hw: Other hardware-specific information.
- * @chip_type: chip type.
- * @time_stamp_lock: spin lock to time stamp.
- * @suspend_resume_lock: mutex lock for suspend/resume.
- * @client: i2c client handle.
- * @plat_data: platform data.
- * @slave_accel: mpu slave handle for accelerometer(MPU3050 only).
- * @slave_compass: mpu slave handle for magnetometer.
- * @slave_pressure: mpu slave handle for pressure sensor.
- * (*set_power_state)(struct inv_mpu_state *, int on): function ptr
- * (*switch_gyro_engine)(struct inv_mpu_state *, int on): function ptr
- * (*switch_accel_engine)(struct inv_mpu_state *, int on): function ptr
- * (*init_config)(struct iio_dev *indio_dev): function ptr
- * (*setup_reg)(struct inv_reg_map_s *reg): function ptr
- * @timestamps: kfifo queue to store time stamp.
- * @irq: irq number store.
- * @accel_bias: accel bias store.
- * @gyro_bias: gyro bias store.
- * @input_gyro_offset[3]: gyro offset from sysfs.
- * @input_accel_offset[3]: accel offset from sysfs.
- * @input_accel_dmp_bias[3]: accel bias for dmp.
- * @input_gyro_dmp_bias[3];: gyro bias for dmp.
- * @rom_gyro_bias[3]: gyro bias from sysfs.
- * @rom_accel_bias[3]: accel bias from sysfs.
- * @fifo_data[6]: fifo data storage.
- * @i2c_addr: i2c address.
- * @sample_divider: sample divider for dmp.
- * @fifo_divider: fifo divider for dmp.
- * @display_orient_data:display orient data.
- * @tap_data: tap data.
- * @bytes_per_sec: bytes per seconds when in DMP mode.
- * @left_over[HEADERED_Q_BYTES]: left over bytes storage.
- * @left_over_size: left over size.
- * @sensor{SENSOR_NUM_MAX]: sensor individual properties.
- * @fifo_count: current fifo_count;
- * @dmp_counter: dmp_counter;
- * @dmp_ticks: DMP ticks past since the previous read.
- * @sl_handle: Handle to I2C port.
- * @irq_dur_ns: duration between each irq.
- * @ts_counter: time stamp counter.
- * @suspend_state: state indicator suspend.
- * @dmp_interval: dmp interval. nomial value is 5 ms.
- * @dmp_interval_accum: dmp interval accumlater.
- * @diff_accumulater: accumlator for the difference of nominal and actual.
- * @last_ts: last time stamp.
- * @step_detector_base_ts: base time stamp for step detector calculation.
- * @prev_ts: previous time stamp.
- * @pedometer_step: pedometer steps stored in driver.
- * @pedometer_time: pedometer time stored in driver.
- * @last_run_time: last time the post ISR runs.
- * @name: name for distiguish MPU6050 and MPU6500 in MPU6XXX.
- * @secondary_name: name for the slave device in the secondary I2C.
- */
-struct inv_mpu_state {
-#define TIMESTAMP_FIFO_SIZE 64
- struct inv_chip_config_s chip_config;
- struct inv_chip_info_s chip_info;
- struct iio_trigger *trig;
- struct inv_tap tap;
- struct inv_smd smd;
- struct inv_ped ped;
- struct inv_batch batch;
- struct inv_reg_map_s reg;
- struct self_test_setting self_test;
- const struct inv_hw_s *hw;
- enum inv_devices chip_type;
- spinlock_t time_stamp_lock;
- struct mutex suspend_resume_lock;
- struct i2c_client *client;
- struct mpu_platform_data plat_data;
- struct inv_mpu_slave *slave_accel;
- struct inv_mpu_slave *slave_compass;
- struct inv_mpu_slave *slave_pressure;
- struct accel_mot_int mot_int;
- int (*set_power_state)(struct inv_mpu_state *, bool on);
- int (*switch_gyro_engine)(struct inv_mpu_state *, bool on);
- int (*switch_accel_engine)(struct inv_mpu_state *, bool on);
- int (*init_config)(struct iio_dev *indio_dev);
- void (*setup_reg)(struct inv_reg_map_s *reg);
- DECLARE_KFIFO(timestamps, u64, TIMESTAMP_FIFO_SIZE);
- short irq;
- int accel_bias[3];
- int gyro_bias[3];
- s16 input_gyro_offset[3];
- s16 input_accel_offset[3];
- int input_accel_dmp_bias[3];
- int input_gyro_dmp_bias[3];
- s16 rom_gyro_offset[3];
- s16 rom_accel_offset[3];
- u8 fifo_data[6];
- u8 i2c_addr;
- u8 sample_divider;
- u8 fifo_divider;
- u8 display_orient_data;
- u8 tap_data;
- u16 bytes_per_sec;
- u8 left_over[HEADERED_Q_BYTES];
- u32 left_over_size;
- struct inv_sensor sensor[SENSOR_NUM_MAX];
- u32 fifo_count;
- u32 dmp_counter;
- u32 dmp_ticks;
- void *sl_handle;
- u32 irq_dur_ns;
- u32 ts_counter;
- bool suspend_state;
- u32 dmp_interval;
- s32 dmp_interval_accum;
- s64 diff_accumulater;
- u64 last_ts;
- u64 step_detector_base_ts;
- u64 prev_ts;
- u64 last_run_time;
- u8 name[20];
- u8 secondary_name[20];
-};
-
-/* produces an unique identifier for each device based on the
- combination of product version and product revision */
-struct prod_rev_map_t {
- u16 mpl_product_key;
- u8 silicon_rev;
- u16 gyro_trim;
- u16 accel_trim;
-};
-
-/**
- * struct inv_mpu_slave - MPU slave structure.
- * @st_upper: compass self test upper limit.
- * @st_lower: compass self test lower limit.
- * @scale: compass scale.
- * @rate_scale: decide how fast a compass can read.
- * @min_read_time: minimum time between each reading.
- * @self_test: self test method of the slave.
- * @set_scale: set scale of slave
- * @get_scale: read scale back of the slave.
- * @suspend: suspend operation.
- * @resume: resume operation.
- * @setup: setup chip. initialization.
- * @combine_data: combine raw data into meaningful data.
- * @read_data: read external sensor and output
- * @get_mode: get current chip mode.
- * @set_lpf: set low pass filter.
- * @set_fs: set full scale
- * @prev_ts: last time it is read.
- */
-struct inv_mpu_slave {
- const short *st_upper;
- const short *st_lower;
- int scale;
- int rate_scale;
- int min_read_time;
- int (*self_test)(struct inv_mpu_state *);
- int (*set_scale)(struct inv_mpu_state *, int scale);
- int (*get_scale)(struct inv_mpu_state *, int *val);
- int (*suspend)(struct inv_mpu_state *);
- int (*resume)(struct inv_mpu_state *);
- int (*setup)(struct inv_mpu_state *);
- int (*combine_data)(u8 *in, short *out);
- int (*read_data)(struct inv_mpu_state *, short *out);
- int (*get_mode)(void);
- int (*set_lpf)(struct inv_mpu_state *, int rate);
- int (*set_fs)(struct inv_mpu_state *, int fs);
- u64 prev_ts;
-};
-
-/* scan element definition */
-enum inv_mpu_scan {
- INV_MPU_SCAN_QUAT_R = 0,
- INV_MPU_SCAN_QUAT_X,
- INV_MPU_SCAN_QUAT_Y,
- INV_MPU_SCAN_QUAT_Z,
- INV_MPU_SCAN_ACCEL_X,
- INV_MPU_SCAN_ACCEL_Y,
- INV_MPU_SCAN_ACCEL_Z,
- INV_MPU_SCAN_GYRO_X,
- INV_MPU_SCAN_GYRO_Y,
- INV_MPU_SCAN_GYRO_Z,
- INV_MPU_SCAN_MAGN_X,
- INV_MPU_SCAN_MAGN_Y,
- INV_MPU_SCAN_MAGN_Z,
- INV_MPU_SCAN_TIMESTAMP,
-};
-
-enum inv_filter_e {
- INV_FILTER_256HZ_NOLPF2 = 0,
- INV_FILTER_188HZ,
- INV_FILTER_98HZ,
- INV_FILTER_42HZ,
- INV_FILTER_20HZ,
- INV_FILTER_10HZ,
- INV_FILTER_5HZ,
- INV_FILTER_2100HZ_NOLPF,
- NUM_FILTER
-};
-
-enum inv_slave_mode {
- INV_MODE_SUSPEND,
- INV_MODE_NORMAL,
-};
-
-/*==== MPU6050B1 MEMORY ====*/
-enum MPU_MEMORY_BANKS {
- MEM_RAM_BANK_0 = 0,
- MEM_RAM_BANK_1,
- MEM_RAM_BANK_2,
- MEM_RAM_BANK_3,
- MEM_RAM_BANK_4,
- MEM_RAM_BANK_5,
- MEM_RAM_BANK_6,
- MEM_RAM_BANK_7,
- MEM_RAM_BANK_8,
- MEM_RAM_BANK_9,
- MEM_RAM_BANK_10,
- MEM_RAM_BANK_11,
- MPU_MEM_NUM_RAM_BANKS,
- MPU_MEM_OTP_BANK_0 = 16
-};
-
-/* IIO attribute address */
-enum MPU_IIO_ATTR_ADDR {
- ATTR_DMP_GYRO_X_DMP_BIAS,
- ATTR_DMP_GYRO_Y_DMP_BIAS,
- ATTR_DMP_GYRO_Z_DMP_BIAS,
- ATTR_DMP_ACCEL_X_DMP_BIAS,
- ATTR_DMP_ACCEL_Y_DMP_BIAS,
- ATTR_DMP_ACCEL_Z_DMP_BIAS,
- ATTR_DMP_PED_INT_ON,
- ATTR_DMP_PED_STEP_THRESH,
- ATTR_DMP_PED_INT_THRESH,
- ATTR_DMP_PED_ON,
- ATTR_DMP_SMD_ENABLE,
- ATTR_DMP_SMD_THLD,
- ATTR_DMP_SMD_DELAY_THLD,
- ATTR_DMP_SMD_DELAY_THLD2,
- ATTR_DMP_PEDOMETER_STEPS,
- ATTR_DMP_PEDOMETER_TIME,
- ATTR_DMP_PEDOMETER_COUNTER,
- ATTR_DMP_TAP_ON,
- ATTR_DMP_TAP_THRESHOLD,
- ATTR_DMP_TAP_MIN_COUNT,
- ATTR_DMP_TAP_TIME,
- ATTR_DMP_DISPLAY_ORIENTATION_ON,
-/* *****above this line, are DMP features, power needs on/off */
-/* *****below this line, are DMP features, no power needed */
- ATTR_DMP_ON,
- ATTR_DMP_INT_ON,
- ATTR_DMP_EVENT_INT_ON,
- ATTR_DMP_STEP_INDICATOR_ON,
- ATTR_DMP_BATCHMODE_TIMEOUT,
- ATTR_DMP_BATCHMODE_WAKE_FIFO_FULL,
- ATTR_DMP_SIX_Q_ON,
- ATTR_DMP_SIX_Q_RATE,
- ATTR_DMP_LPQ_ON,
- ATTR_DMP_LPQ_RATE,
- ATTR_DMP_PED_Q_ON,
- ATTR_DMP_PED_Q_RATE,
- ATTR_DMP_STEP_DETECTOR_ON,
- ATTR_DMP_STEP_DETECTOR_RATE,
-/* *****above this line, it is all DMP related features */
-/* *****below this line, it is all non-DMP related features */
- ATTR_GYRO_SCALE,
- ATTR_ACCEL_SCALE,
- ATTR_COMPASS_SCALE,
- ATTR_GYRO_X_OFFSET,
- ATTR_GYRO_Y_OFFSET,
- ATTR_GYRO_Z_OFFSET,
- ATTR_ACCEL_X_OFFSET,
- ATTR_ACCEL_Y_OFFSET,
- ATTR_ACCEL_Z_OFFSET,
- ATTR_MOTION_LPA_ON,
- ATTR_MOTION_LPA_FREQ,
- ATTR_MOTION_LPA_THRESHOLD,
-/* *****above this line, it is non-DMP, power needs on/off */
-/* *****below this line, it is non-DMP, no needs to on/off power */
- ATTR_SELF_TEST_SAMPLES,
- ATTR_SELF_TEST_THRESHOLD,
- ATTR_GYRO_ENABLE,
- ATTR_GYRO_FIFO_ENABLE,
- ATTR_GYRO_RATE,
- ATTR_ACCEL_ENABLE,
- ATTR_ACCEL_FIFO_ENABLE,
- ATTR_ACCEL_RATE,
- ATTR_COMPASS_ENABLE,
- ATTR_COMPASS_RATE,
- ATTR_PRESSURE_ENABLE,
- ATTR_PRESSURE_RATE,
- ATTR_POWER_STATE, /* this is fake sysfs for compatibility */
- ATTR_FIRMWARE_LOADED,
- ATTR_SAMPLING_FREQ,
-/* *****below this line, it is attributes only has show methods */
- ATTR_SELF_TEST, /* this has show-only methods needs power on/off */
- ATTR_GYRO_X_CALIBBIAS,
- ATTR_GYRO_Y_CALIBBIAS,
- ATTR_GYRO_Z_CALIBBIAS,
- ATTR_ACCEL_X_CALIBBIAS,
- ATTR_ACCEL_Y_CALIBBIAS,
- ATTR_ACCEL_Z_CALIBBIAS,
- ATTR_SELF_TEST_GYRO_SCALE,
- ATTR_SELF_TEST_ACCEL_SCALE,
- ATTR_GYRO_MATRIX,
- ATTR_ACCEL_MATRIX,
- ATTR_COMPASS_MATRIX,
- ATTR_SECONDARY_NAME,
-#ifdef CONFIG_INV_TESTING
- ATTR_COMPASS_SENS,
- ATTR_I2C_COUNTERS,
- ATTR_REG_WRITE,
- ATTR_DEBUG_SMD_ENABLE_TESTP1,
- ATTR_DEBUG_SMD_ENABLE_TESTP2,
- ATTR_DEBUG_SMD_EXE_STATE,
- ATTR_DEBUG_SMD_DELAY_CNTR,
- ATTR_DEBUG_GYRO_COUNTER,
- ATTR_DEBUG_ACCEL_COUNTER,
- ATTR_DEBUG_COMPASS_COUNTER,
- ATTR_DEBUG_PRESSURE_COUNTER,
- ATTR_DEBUG_LPQ_COUNTER,
- ATTR_DEBUG_SIXQ_COUNTER,
- ATTR_DEBUG_PEDQ_COUNTER,
-#endif
-};
-
-enum inv_accel_fs_e {
- INV_FS_02G = 0,
- INV_FS_04G,
- INV_FS_08G,
- INV_FS_16G,
- NUM_ACCEL_FSR
-};
-
-enum inv_fsr_e {
- INV_FSR_250DPS = 0,
- INV_FSR_500DPS,
- INV_FSR_1000DPS,
- INV_FSR_2000DPS,
- NUM_FSR
-};
-
-enum inv_clock_sel_e {
- INV_CLK_INTERNAL = 0,
- INV_CLK_PLL,
- NUM_CLK
-};
-
-ssize_t inv_dmp_firmware_write(struct file *fp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t pos, size_t size);
-ssize_t inv_dmp_firmware_read(struct file *filp,
- struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count);
-ssize_t inv_six_q_write(struct file *fp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t pos, size_t size);
-
-int inv_mpu_configure_ring(struct iio_dev *indio_dev);
-int inv_mpu_probe_trigger(struct iio_dev *indio_dev);
-void inv_mpu_unconfigure_ring(struct iio_dev *indio_dev);
-void inv_mpu_remove_trigger(struct iio_dev *indio_dev);
-int inv_init_config_mpu3050(struct iio_dev *indio_dev);
-int inv_get_silicon_rev_mpu6050(struct inv_mpu_state *st);
-int inv_get_silicon_rev_mpu6500(struct inv_mpu_state *st);
-int set_3050_bypass(struct inv_mpu_state *st, bool enable);
-int inv_register_mpu3050_slave(struct inv_mpu_state *st);
-void inv_setup_reg_mpu3050(struct inv_reg_map_s *reg);
-int inv_switch_3050_gyro_engine(struct inv_mpu_state *st, bool en);
-int inv_switch_3050_accel_engine(struct inv_mpu_state *st, bool en);
-int set_power_mpu3050(struct inv_mpu_state *st, bool power_on);
-int inv_set_interrupt_on_gesture_event(struct inv_mpu_state *st, bool on);
-int inv_set_display_orient_interrupt_dmp(struct inv_mpu_state *st, bool on);
-u16 inv_dmp_get_address(u16 key);
-int inv_q30_mult(int a, int b);
-int inv_set_tap_threshold_dmp(struct inv_mpu_state *st, u16 threshold);
-int inv_write_2bytes(struct inv_mpu_state *st, int k, int data);
-int inv_set_min_taps_dmp(struct inv_mpu_state *st, u16 min_taps);
-int inv_set_tap_time_dmp(struct inv_mpu_state *st, u16 time);
-int inv_enable_tap_dmp(struct inv_mpu_state *st, bool on);
-int inv_i2c_read_base(struct inv_mpu_state *st, u16 i2c_addr,
- u8 reg, u16 length, u8 *data);
-int inv_i2c_single_write_base(struct inv_mpu_state *st,
- u16 i2c_addr, u8 reg, u8 data);
-int inv_hw_self_test(struct inv_mpu_state *st);
-s64 get_time_ns(void);
-int write_be32_key_to_mem(struct inv_mpu_state *st,
- u32 data, int key);
-int inv_set_accel_bias_dmp(struct inv_mpu_state *st);
-int inv_mpu_setup_compass_slave(struct inv_mpu_state *st);
-int inv_mpu_setup_pressure_slave(struct inv_mpu_state *st);
-int mpu_memory_write(struct inv_mpu_state *st, u8 mpu_addr, u16 mem_addr,
- u32 len, u8 const *data);
-int mpu_memory_read(struct inv_mpu_state *st, u8 mpu_addr, u16 mem_addr,
- u32 len, u8 *data);
-int mpu_memory_write_unaligned(struct inv_mpu_state *st, u16 key, int len,
- u8 const *d);
-int inv_quaternion_on(struct inv_mpu_state *st,
- struct iio_buffer *ring, bool en);
-int inv_enable_pedometer_interrupt(struct inv_mpu_state *st, bool en);
-int inv_read_pedometer_counter(struct inv_mpu_state *st);
-int inv_enable_pedometer(struct inv_mpu_state *st, bool en);
-int inv_get_pedometer_steps(struct inv_mpu_state *st, u32 *steps);
-int inv_get_pedometer_time(struct inv_mpu_state *st, u32 *time);
-int inv_reset_fifo(struct iio_dev *indio_dev);
-int inv_reset_offset_reg(struct inv_mpu_state *st, bool en);
-int inv_batchmode_setup(struct inv_mpu_state *st);
-void inv_init_sensor_struct(struct inv_mpu_state *st);
-int inv_read_time_and_ticks(struct inv_mpu_state *st, bool resume);
-int inv_flush_batch_data(struct iio_dev *indio_dev, bool *has_data);
-int set_inv_enable(struct iio_dev *indio_dev, bool enable);
-/* used to print i2c data using pr_debug */
-char *wr_pr_debug_begin(u8 const *data, u32 len, char *string);
-char *wr_pr_debug_end(char *string);
-
-#define mem_w(a, b, c) \
- mpu_memory_write(st, st->i2c_addr, a, b, c)
-#define mem_w_key(key, b, c) mpu_memory_write_unaligned(st, key, b, c)
-#define inv_i2c_read(st, reg, len, data) \
- inv_i2c_read_base(st, st->i2c_addr, reg, len, data)
-#define inv_i2c_single_write(st, reg, data) \
- inv_i2c_single_write_base(st, st->i2c_addr, reg, data)
-#define inv_secondary_read(reg, len, data) \
- inv_i2c_read_base(st, st->plat_data.secondary_i2c_addr, reg, len, data)
-#define inv_secondary_write(reg, data) \
- inv_i2c_single_write_base(st, st->plat_data.secondary_i2c_addr, \
- reg, data)
-#define inv_aux_read(reg, len, data) \
- inv_i2c_read_base(st, st->plat_data.aux_i2c_addr, reg, len, data)
-#define inv_aux_write(reg, data) \
- inv_i2c_single_write_base(st, st->plat_data.aux_i2c_addr, \
- reg, data)
-
-#endif /* #ifndef _INV_MPU_IIO_H_ */
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_misc.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_misc.c
deleted file mode 100644
index 73b883679c9..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_misc.c
+++ /dev/null
@@ -1,2041 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/crc32.h>
-
-#include "inv_mpu_iio.h"
-#include "inv_test/inv_counters.h"
-
-/* DMP defines */
-#define DMP_ORIENTATION_TIME 500
-#define DMP_ORIENTATION_ANGLE 60
-#define DMP_DEFAULT_FIFO_RATE 200
-#define DMP_TAP_SCALE (767603923 / 5)
-#define DMP_MULTI_SHIFT 30
-#define DMP_MULTI_TAP_TIME 500
-#define DMP_SHAKE_REJECT_THRESH 100
-#define DMP_SHAKE_REJECT_TIME 10
-#define DMP_SHAKE_REJECT_TIMEOUT 10
-#define DMP_ANGLE_SCALE 15
-#define DMP_PRECISION 1000
-#define DMP_MAX_DIVIDER 4
-#define DMP_MAX_MIN_TAPS 4
-#define DMP_IMAGE_CRC_VALUE 0xa7e2110d
-
-/*--- Test parameters defaults --- */
-#define DEF_OLDEST_SUPP_PROD_REV 8
-#define DEF_OLDEST_SUPP_SW_REV 2
-
-/* sample rate */
-#define DEF_SELFTEST_SAMPLE_RATE 0
-/* full scale setting dps */
-#define DEF_SELFTEST_GYRO_FS (0 << 3)
-#define DEF_SELFTEST_ACCEL_FS (2 << 3)
-#define DEF_SELFTEST_GYRO_SENS (32768 / 250)
-/* wait time before collecting data */
-#define DEF_GYRO_WAIT_TIME 10
-#define DEF_ST_STABLE_TIME 20
-#define DEF_ST_6500_STABLE_TIME 20
-#define DEF_GYRO_SCALE 131
-#define DEF_ST_PRECISION 1000
-#define DEF_ST_ACCEL_FS_MG 8000UL
-#define DEF_ST_SCALE (1L << 15)
-#define DEF_ST_TRY_TIMES 2
-#define DEF_ST_COMPASS_RESULT_SHIFT 2
-#define DEF_ST_ACCEL_RESULT_SHIFT 1
-#define DEF_ST_OTP0_THRESH 60
-#define DEF_ST_ABS_THRESH 20
-#define DEF_ST_TOR 2
-
-#define X 0
-#define Y 1
-#define Z 2
-/*---- MPU6050 notable product revisions ----*/
-#define MPU_PRODUCT_KEY_B1_E1_5 105
-#define MPU_PRODUCT_KEY_B2_F1 431
-/* accelerometer Hw self test min and max bias shift (mg) */
-#define DEF_ACCEL_ST_SHIFT_MIN 300
-#define DEF_ACCEL_ST_SHIFT_MAX 950
-
-#define DEF_ACCEL_ST_SHIFT_DELTA 500
-#define DEF_GYRO_CT_SHIFT_DELTA 500
-/* gyroscope Coriolis self test min and max bias shift (dps) */
-#define DEF_GYRO_CT_SHIFT_MIN 10
-#define DEF_GYRO_CT_SHIFT_MAX 105
-
-/*---- MPU6500 Self Test Pass/Fail Criteria ----*/
-/* Gyro Offset Max Value (dps) */
-#define DEF_GYRO_OFFSET_MAX 20
-/* Gyro Self Test Absolute Limits ST_AL (dps) */
-#define DEF_GYRO_ST_AL 60
-/* Accel Self Test Absolute Limits ST_AL (mg) */
-#define DEF_ACCEL_ST_AL_MIN 225
-#define DEF_ACCEL_ST_AL_MAX 675
-#define DEF_6500_ACCEL_ST_SHIFT_DELTA 500
-#define DEF_6500_GYRO_CT_SHIFT_DELTA 500
-#define DEF_ST_MPU6500_ACCEL_LPF 2
-#define DEF_ST_6500_ACCEL_FS_MG 2000UL
-#define DEF_SELFTEST_6500_ACCEL_FS (0 << 3)
-
-/* Note: The ST_AL values are only used when ST_OTP = 0,
- * i.e no factory self test values for reference
- */
-
-/* NOTE: product entries are in chronological order */
-static const struct prod_rev_map_t prod_rev_map[] = {
- /* prod_ver = 0 */
- {MPL_PROD_KEY(0, 1), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 2), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 3), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 4), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 5), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 6), MPU_SILICON_REV_A2, 131, 16384},
- /* prod_ver = 1 */
- {MPL_PROD_KEY(0, 7), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 8), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 9), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 10), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 11), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 12), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 13), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 14), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 15), MPU_SILICON_REV_A2, 131, 16384},
- {MPL_PROD_KEY(0, 27), MPU_SILICON_REV_A2, 131, 16384},
- /* prod_ver = 1 */
- {MPL_PROD_KEY(1, 16), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 17), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 18), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 19), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 20), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 28), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 1), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 2), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 3), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 4), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 5), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(1, 6), MPU_SILICON_REV_B1, 131, 16384},
- /* prod_ver = 2 */
- {MPL_PROD_KEY(2, 7), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(2, 8), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(2, 9), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(2, 10), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(2, 11), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(2, 12), MPU_SILICON_REV_B1, 131, 16384},
- {MPL_PROD_KEY(2, 29), MPU_SILICON_REV_B1, 131, 16384},
- /* prod_ver = 3 */
- {MPL_PROD_KEY(3, 30), MPU_SILICON_REV_B1, 131, 16384},
- /* prod_ver = 4 */
- {MPL_PROD_KEY(4, 31), MPU_SILICON_REV_B1, 131, 8192},
- {MPL_PROD_KEY(4, 1), MPU_SILICON_REV_B1, 131, 8192},
- {MPL_PROD_KEY(4, 3), MPU_SILICON_REV_B1, 131, 8192},
- /* prod_ver = 5 */
- {MPL_PROD_KEY(5, 3), MPU_SILICON_REV_B1, 131, 16384},
- /* prod_ver = 6 */
- {MPL_PROD_KEY(6, 19), MPU_SILICON_REV_B1, 131, 16384},
- /* prod_ver = 7 */
- {MPL_PROD_KEY(7, 19), MPU_SILICON_REV_B1, 131, 16384},
- /* prod_ver = 8 */
- {MPL_PROD_KEY(8, 19), MPU_SILICON_REV_B1, 131, 16384},
- /* prod_ver = 9 */
- {MPL_PROD_KEY(9, 19), MPU_SILICON_REV_B1, 131, 16384},
- /* prod_ver = 10 */
- {MPL_PROD_KEY(10, 19), MPU_SILICON_REV_B1, 131, 16384}
-};
-
-/*
-* List of product software revisions
-*
-* NOTE :
-* software revision 0 falls back to the old detection method
-* based off the product version and product revision per the
-* table above
-*/
-static const struct prod_rev_map_t sw_rev_map[] = {
- {0, 0, 0, 0},
- {1, MPU_SILICON_REV_B1, 131, 8192}, /* rev C */
- {2, MPU_SILICON_REV_B1, 131, 16384} /* rev D */
-};
-
-static const u16 mpu_6500_st_tb[256] = {
- 2620, 2646, 2672, 2699, 2726, 2753, 2781, 2808,
- 2837, 2865, 2894, 2923, 2952, 2981, 3011, 3041,
- 3072, 3102, 3133, 3165, 3196, 3228, 3261, 3293,
- 3326, 3359, 3393, 3427, 3461, 3496, 3531, 3566,
- 3602, 3638, 3674, 3711, 3748, 3786, 3823, 3862,
- 3900, 3939, 3979, 4019, 4059, 4099, 4140, 4182,
- 4224, 4266, 4308, 4352, 4395, 4439, 4483, 4528,
- 4574, 4619, 4665, 4712, 4759, 4807, 4855, 4903,
- 4953, 5002, 5052, 5103, 5154, 5205, 5257, 5310,
- 5363, 5417, 5471, 5525, 5581, 5636, 5693, 5750,
- 5807, 5865, 5924, 5983, 6043, 6104, 6165, 6226,
- 6289, 6351, 6415, 6479, 6544, 6609, 6675, 6742,
- 6810, 6878, 6946, 7016, 7086, 7157, 7229, 7301,
- 7374, 7448, 7522, 7597, 7673, 7750, 7828, 7906,
- 7985, 8065, 8145, 8227, 8309, 8392, 8476, 8561,
- 8647, 8733, 8820, 8909, 8998, 9088, 9178, 9270,
- 9363, 9457, 9551, 9647, 9743, 9841, 9939, 10038,
- 10139, 10240, 10343, 10446, 10550, 10656, 10763, 10870,
- 10979, 11089, 11200, 11312, 11425, 11539, 11654, 11771,
- 11889, 12008, 12128, 12249, 12371, 12495, 12620, 12746,
- 12874, 13002, 13132, 13264, 13396, 13530, 13666, 13802,
- 13940, 14080, 14221, 14363, 14506, 14652, 14798, 14946,
- 15096, 15247, 15399, 15553, 15709, 15866, 16024, 16184,
- 16346, 16510, 16675, 16842, 17010, 17180, 17352, 17526,
- 17701, 17878, 18057, 18237, 18420, 18604, 18790, 18978,
- 19167, 19359, 19553, 19748, 19946, 20145, 20347, 20550,
- 20756, 20963, 21173, 21385, 21598, 21814, 22033, 22253,
- 22475, 22700, 22927, 23156, 23388, 23622, 23858, 24097,
- 24338, 24581, 24827, 25075, 25326, 25579, 25835, 26093,
- 26354, 26618, 26884, 27153, 27424, 27699, 27976, 28255,
- 28538, 28823, 29112, 29403, 29697, 29994, 30294, 30597,
- 30903, 31212, 31524, 31839, 32157, 32479, 32804
-};
-
-static const int accel_st_tb[31] = {
- 340, 351, 363, 375, 388, 401, 414, 428,
- 443, 458, 473, 489, 506, 523, 541, 559,
- 578, 597, 617, 638, 660, 682, 705, 729,
- 753, 779, 805, 832, 860, 889, 919
-};
-
-static const int gyro_6050_st_tb[31] = {
- 3275, 3425, 3583, 3748, 3920, 4100, 4289, 4486,
- 4693, 4909, 5134, 5371, 5618, 5876, 6146, 6429,
- 6725, 7034, 7358, 7696, 8050, 8421, 8808, 9213,
- 9637, 10080, 10544, 11029, 11537, 12067, 12622
-};
-
-static const int gyro_3500_st_tb[255] = {
- 2620, 2646, 2672, 2699, 2726, 2753, 2781, 2808,
- 2837, 2865, 2894, 2923, 2952, 2981, 3011, 3041,
- 3072, 3102, 3133, 3165, 3196, 3228, 3261, 3293,
- 3326, 3359, 3393, 3427, 3461, 3496, 3531, 3566,
- 3602, 3638, 3674, 3711, 3748, 3786, 3823, 3862,
- 3900, 3939, 3979, 4019, 4059, 4099, 4140, 4182,
- 4224, 4266, 4308, 4352, 4395, 4439, 4483, 4528,
- 4574, 4619, 4665, 4712, 4759, 4807, 4855, 4903,
- 4953, 5002, 5052, 5103, 5154, 5205, 5257, 5310,
- 5363, 5417, 5471, 5525, 5581, 5636, 5693, 5750,
- 5807, 5865, 5924, 5983, 6043, 6104, 6165, 6226,
- 6289, 6351, 6415, 6479, 6544, 6609, 6675, 6742,
- 6810, 6878, 6946, 7016, 7086, 7157, 7229, 7301,
- 7374, 7448, 7522, 7597, 7673, 7750, 7828, 7906,
- 7985, 8065, 8145, 8227, 8309, 8392, 8476, 8561,
- 8647, 8733, 8820, 8909, 8998, 9088, 9178, 9270,
- 9363, 9457, 9551, 9647, 9743, 9841, 9939, 10038,
- 10139, 10240, 10343, 10446, 10550, 10656, 10763, 10870,
- 10979, 11089, 11200, 11312, 11425, 11539, 11654, 11771,
- 11889, 12008, 12128, 12249, 12371, 12495, 12620, 12746,
- 12874, 13002, 13132, 13264, 13396, 13530, 13666, 13802,
- 13940, 14080, 14221, 14363, 14506, 14652, 14798, 14946,
- 15096, 15247, 15399, 15553, 15709, 15866, 16024, 16184,
- 16346, 16510, 16675, 16842, 17010, 17180, 17352, 17526,
- 17701, 17878, 18057, 18237, 18420, 18604, 18790, 18978,
- 19167, 19359, 19553, 19748, 19946, 20145, 20347, 20550,
- 20756, 20963, 21173, 21385, 21598, 21814, 22033, 22253,
- 22475, 22700, 22927, 23156, 23388, 23622, 23858, 24097,
- 24338, 24581, 24827, 25075, 25326, 25579, 25835, 26093,
- 26354, 26618, 26884, 27153, 27424, 27699, 27976, 28255,
- 28538, 28823, 29112, 29403, 29697, 29994, 30294, 30597,
- 30903, 31212, 31524, 31839, 32157, 32479, 32804
-};
-
-char *wr_pr_debug_begin(u8 const *data, u32 len, char *string)
-{
- int ii;
- string = kmalloc(len * 2 + 1, GFP_KERNEL);
- for (ii = 0; ii < len; ii++)
- sprintf(&string[ii * 2], "%02X", data[ii]);
- string[len * 2] = 0;
- return string;
-}
-
-char *wr_pr_debug_end(char *string)
-{
- kfree(string);
- return "";
-}
-
-int mpu_memory_write(struct inv_mpu_state *st, u8 mpu_addr, u16 mem_addr,
- u32 len, u8 const *data)
-{
- u8 bank[2];
- u8 addr[2];
- u8 buf[513];
-
- struct i2c_msg msgs[3];
- int res;
-
- if (!data || !st)
- return -EINVAL;
-
- if (len >= (sizeof(buf) - 1))
- return -ENOMEM;
-
- bank[0] = REG_BANK_SEL;
- bank[1] = mem_addr >> 8;
-
- addr[0] = REG_MEM_START_ADDR;
- addr[1] = mem_addr & 0xFF;
-
- buf[0] = REG_MEM_RW;
- memcpy(buf + 1, data, len);
-
- /* write message */
- msgs[0].addr = mpu_addr;
- msgs[0].flags = 0;
- msgs[0].buf = bank;
- msgs[0].len = sizeof(bank);
-
- msgs[1].addr = mpu_addr;
- msgs[1].flags = 0;
- msgs[1].buf = addr;
- msgs[1].len = sizeof(addr);
-
- msgs[2].addr = mpu_addr;
- msgs[2].flags = 0;
- msgs[2].buf = (u8 *)buf;
- msgs[2].len = len + 1;
-
- INV_I2C_INC_MPUWRITE(3 + 3 + (2 + len));
-#if CONFIG_DYNAMIC_DEBUG
- {
- char *write = 0;
- pr_debug("%s WM%02X%02X%02X%s%s - %d\n", st->hw->name,
- mpu_addr, bank[1], addr[1],
- wr_pr_debug_begin(data, len, write),
- wr_pr_debug_end(write),
- len);
- }
-#endif
-
- res = i2c_transfer(st->sl_handle, msgs, 3);
- if (res != 3) {
- if (res >= 0)
- res = -EIO;
- return res;
- } else {
- return 0;
- }
-}
-
-int mpu_memory_read(struct inv_mpu_state *st, u8 mpu_addr, u16 mem_addr,
- u32 len, u8 *data)
-{
- u8 bank[2];
- u8 addr[2];
- u8 buf;
-
- struct i2c_msg msgs[4];
- int res;
-
- if (!data || !st)
- return -EINVAL;
-
- bank[0] = REG_BANK_SEL;
- bank[1] = mem_addr >> 8;
-
- addr[0] = REG_MEM_START_ADDR;
- addr[1] = mem_addr & 0xFF;
-
- buf = REG_MEM_RW;
-
- /* write message */
- msgs[0].addr = mpu_addr;
- msgs[0].flags = 0;
- msgs[0].buf = bank;
- msgs[0].len = sizeof(bank);
-
- msgs[1].addr = mpu_addr;
- msgs[1].flags = 0;
- msgs[1].buf = addr;
- msgs[1].len = sizeof(addr);
-
- msgs[2].addr = mpu_addr;
- msgs[2].flags = 0;
- msgs[2].buf = &buf;
- msgs[2].len = 1;
-
- msgs[3].addr = mpu_addr;
- msgs[3].flags = I2C_M_RD;
- msgs[3].buf = data;
- msgs[3].len = len;
-
- res = i2c_transfer(st->sl_handle, msgs, 4);
- if (res != 4) {
- if (res >= 0)
- res = -EIO;
- } else
- res = 0;
-
- INV_I2C_INC_MPUWRITE(3 + 3 + 3);
- INV_I2C_INC_MPUREAD(len);
-#if CONFIG_DYNAMIC_DEBUG
- {
- char *read = 0;
- pr_debug("%s RM%02X%02X%02X%02X - %s%s\n", st->hw->name,
- mpu_addr, bank[1], addr[1], len,
- wr_pr_debug_begin(data, len, read),
- wr_pr_debug_end(read));
- }
-#endif
-
- return res;
-}
-
-int mpu_memory_write_unaligned(struct inv_mpu_state *st, u16 key, int len,
- u8 const *d)
-{
- u32 addr;
- int start, end;
- int len1, len2;
- int result = 0;
-
- if (len > MPU_MEM_BANK_SIZE)
- return -EINVAL;
- addr = inv_dmp_get_address(key);
- if (addr > MPU6XXX_MAX_MPU_MEM)
- return -EINVAL;
-
- start = (addr >> 8);
- end = ((addr + len - 1) >> 8);
- if (start == end) {
- result = mpu_memory_write(st, st->i2c_addr, addr, len, d);
- } else {
- end <<= 8;
- len1 = end - addr;
- len2 = len - len1;
- result = mpu_memory_write(st, st->i2c_addr, addr, len1, d);
- result |= mpu_memory_write(st, st->i2c_addr, end, len2,
- d + len1);
- }
-
- return result;
-}
-
-/**
- * index_of_key()- Inverse lookup of the index of an MPL product key .
- * @key: the MPL product indentifier also referred to as 'key'.
- */
-static short index_of_key(u16 key)
-{
- int i;
- for (i = 0; i < NUM_OF_PROD_REVS; i++)
- if (prod_rev_map[i].mpl_product_key == key)
- return (short)i;
- return -EINVAL;
-}
-
-int inv_get_silicon_rev_mpu6500(struct inv_mpu_state *st)
-{
- struct inv_chip_info_s *chip_info = &st->chip_info;
- int result;
- u8 whoami, sw_rev;
-
- result = inv_i2c_read(st, REG_WHOAMI, 1, &whoami);
- if (result)
- return result;
- if (whoami != MPU6500_ID && whoami != MPU9250_ID &&
- whoami != MPU9350_ID && whoami != MPU6515_ID)
- return -EINVAL;
-
- /*memory read need more time after power up */
- msleep(POWER_UP_TIME);
- result = mpu_memory_read(st, st->i2c_addr,
- MPU6500_MEM_REV_ADDR, 1, &sw_rev);
- sw_rev &= INV_MPU_REV_MASK;
- if (result)
- return result;
- if (sw_rev != 0)
- return -EINVAL;
- /* these values are place holders and not real values */
- chip_info->product_id = MPU6500_PRODUCT_REVISION;
- chip_info->product_revision = MPU6500_PRODUCT_REVISION;
- chip_info->silicon_revision = MPU6500_PRODUCT_REVISION;
- chip_info->software_revision = sw_rev;
- chip_info->gyro_sens_trim = DEFAULT_GYRO_TRIM;
- chip_info->accel_sens_trim = DEFAULT_ACCEL_TRIM;
- chip_info->multi = 1;
-
- return 0;
-}
-
-int inv_get_silicon_rev_mpu6050(struct inv_mpu_state *st)
-{
- int result;
- struct inv_reg_map_s *reg;
- u8 prod_ver = 0x00, prod_rev = 0x00;
- struct prod_rev_map_t *p_rev;
- u8 bank =
- (BIT_PRFTCH_EN | BIT_CFG_USER_BANK | MPU_MEM_OTP_BANK_0);
- u16 mem_addr = ((bank << 8) | MEM_ADDR_PROD_REV);
- u16 key;
- u8 regs[5];
- u16 sw_rev;
- short index;
- struct inv_chip_info_s *chip_info = &st->chip_info;
- reg = &st->reg;
-
- result = inv_i2c_read(st, REG_PRODUCT_ID, 1, &prod_ver);
- if (result)
- return result;
- prod_ver &= 0xf;
- /*memory read need more time after power up */
- msleep(POWER_UP_TIME);
- result = mpu_memory_read(st, st->i2c_addr, mem_addr, 1, &prod_rev);
- if (result)
- return result;
- prod_rev >>= 2;
- /* clean the prefetch and cfg user bank bits */
- result = inv_i2c_single_write(st, reg->bank_sel, 0);
- if (result)
- return result;
- /* get the software-product version, read from XA_OFFS_L */
- result = inv_i2c_read(st, REG_XA_OFFS_L_TC,
- SOFT_PROD_VER_BYTES, regs);
- if (result)
- return result;
-
- sw_rev = (regs[4] & 0x01) << 2 | /* 0x0b, bit 0 */
- (regs[2] & 0x01) << 1 | /* 0x09, bit 0 */
- (regs[0] & 0x01); /* 0x07, bit 0 */
- /* if 0, use the product key to determine the type of part */
- if (sw_rev == 0) {
- key = MPL_PROD_KEY(prod_ver, prod_rev);
- if (key == 0)
- return -EINVAL;
- index = index_of_key(key);
- if (index < 0 || index >= NUM_OF_PROD_REVS)
- return -EINVAL;
- /* check MPL is compiled for this device */
- if (prod_rev_map[index].silicon_rev != MPU_SILICON_REV_B1)
- return -EINVAL;
- p_rev = (struct prod_rev_map_t *)&prod_rev_map[index];
- /* if valid, use the software product key */
- } else if (sw_rev < ARRAY_SIZE(sw_rev_map)) {
- p_rev = (struct prod_rev_map_t *)&sw_rev_map[sw_rev];
- } else {
- return -EINVAL;
- }
- chip_info->product_id = prod_ver;
- chip_info->product_revision = prod_rev;
- chip_info->silicon_revision = p_rev->silicon_rev;
- chip_info->software_revision = sw_rev;
- chip_info->gyro_sens_trim = p_rev->gyro_trim;
- chip_info->accel_sens_trim = p_rev->accel_trim;
- if (chip_info->accel_sens_trim == 0)
- chip_info->accel_sens_trim = DEFAULT_ACCEL_TRIM;
- chip_info->multi = DEFAULT_ACCEL_TRIM / chip_info->accel_sens_trim;
- if (chip_info->multi != 1)
- pr_info("multi is %d\n", chip_info->multi);
- return result;
-}
-
-/**
- * read_accel_hw_self_test_prod_shift()- read the accelerometer hardware
- * self-test bias shift calculated
- * during final production test and
- * stored in chip non-volatile memory.
- * @st: main data structure.
- * @st_prod: A pointer to an array of 3 elements to hold the values
- * for production hardware self-test bias shifts returned to the
- * user.
- * @accel_sens: accel sensitivity.
- */
-static int read_accel_hw_self_test_prod_shift(struct inv_mpu_state *st,
- int *st_prod, int *accel_sens)
-{
- u8 regs[4];
- u8 shift_code[3];
- int result, i;
-
- for (i = 0; i < 3; i++)
- st_prod[i] = 0;
-
- result = inv_i2c_read(st, REG_ST_GCT_X, ARRAY_SIZE(regs), regs);
- if (result)
- return result;
- if ((0 == regs[0]) && (0 == regs[1]) &&
- (0 == regs[2]) && (0 == regs[3]))
- return -EINVAL;
- shift_code[X] = ((regs[0] & 0xE0) >> 3) | ((regs[3] & 0x30) >> 4);
- shift_code[Y] = ((regs[1] & 0xE0) >> 3) | ((regs[3] & 0x0C) >> 2);
- shift_code[Z] = ((regs[2] & 0xE0) >> 3) | (regs[3] & 0x03);
- for (i = 0; i < 3; i++)
- if (shift_code[i] != 0)
- st_prod[i] = accel_sens[i] *
- accel_st_tb[shift_code[i] - 1];
-
- return 0;
-}
-
-/**
-* inv_check_accel_self_test()- check accel self test. this function returns
-* zero as success. A non-zero return value
-* indicates failure in self test.
-* @*st: main data structure.
-* @*reg_avg: average value of normal test.
-* @*st_avg: average value of self test
-*/
-static int inv_check_accel_self_test(struct inv_mpu_state *st,
- int *reg_avg, int *st_avg){
- int gravity, j, ret_val;
- int tmp;
- int st_shift_prod[THREE_AXIS], st_shift_cust[THREE_AXIS];
- int st_shift_ratio[THREE_AXIS];
- int accel_sens[THREE_AXIS];
-
- if (st->chip_info.software_revision < DEF_OLDEST_SUPP_SW_REV &&
- st->chip_info.product_revision < DEF_OLDEST_SUPP_PROD_REV)
- return 0;
- ret_val = 0;
- tmp = DEF_ST_SCALE * DEF_ST_PRECISION / DEF_ST_ACCEL_FS_MG;
- for (j = 0; j < 3; j++)
- accel_sens[j] = tmp;
-
- if (MPL_PROD_KEY(st->chip_info.product_id,
- st->chip_info.product_revision) ==
- MPU_PRODUCT_KEY_B1_E1_5) {
- /* half sensitivity Z accelerometer parts */
- accel_sens[Z] /= 2;
- } else {
- /* half sensitivity X, Y, Z accelerometer parts */
- accel_sens[X] /= st->chip_info.multi;
- accel_sens[Y] /= st->chip_info.multi;
- accel_sens[Z] /= st->chip_info.multi;
- }
- gravity = accel_sens[Z];
- ret_val = read_accel_hw_self_test_prod_shift(st, st_shift_prod,
- accel_sens);
- if (ret_val)
- return ret_val;
-
- for (j = 0; j < 3; j++) {
- st_shift_cust[j] = abs(reg_avg[j] - st_avg[j]);
- if (st_shift_prod[j]) {
- tmp = st_shift_prod[j] / DEF_ST_PRECISION;
- st_shift_ratio[j] = abs(st_shift_cust[j] / tmp
- - DEF_ST_PRECISION);
- if (st_shift_ratio[j] > DEF_ACCEL_ST_SHIFT_DELTA)
- ret_val = 1;
- } else {
- if (st_shift_cust[j] <
- DEF_ACCEL_ST_SHIFT_MIN * gravity)
- ret_val = 1;
- if (st_shift_cust[j] >
- DEF_ACCEL_ST_SHIFT_MAX * gravity)
- ret_val = 1;
- }
- }
-
- return ret_val;
-}
-
-/**
-* inv_check_3500_gyro_self_test() check gyro self test. this function returns
-* zero as success. A non-zero return value
-* indicates failure in self test.
-* @*st: main data structure.
-* @*reg_avg: average value of normal test.
-* @*st_avg: average value of self test
-*/
-
-static int inv_check_3500_gyro_self_test(struct inv_mpu_state *st,
- int *reg_avg, int *st_avg){
- int result;
- int gst[3], ret_val;
- int gst_otp[3], i;
- u8 st_code[THREE_AXIS];
- ret_val = 0;
-
- for (i = 0; i < 3; i++)
- gst[i] = st_avg[i] - reg_avg[i];
- result = inv_i2c_read(st, REG_3500_OTP, THREE_AXIS, st_code);
- if (result)
- return result;
- gst_otp[0] = 0;
- gst_otp[1] = 0;
- gst_otp[2] = 0;
- for (i = 0; i < 3; i++) {
- if (st_code[i] != 0)
- gst_otp[i] = gyro_3500_st_tb[st_code[i] - 1];
- }
- /* check self test value passing criterion. Using the DEF_ST_TOR
- * for certain degree of tolerance */
- for (i = 0; i < 3; i++) {
- if (gst_otp[i] == 0) {
- if (abs(gst[i]) * DEF_ST_TOR < DEF_ST_OTP0_THRESH *
- DEF_ST_PRECISION *
- DEF_GYRO_SCALE)
- ret_val |= (1 << i);
- } else {
- if (abs(gst[i]/gst_otp[i] - DEF_ST_PRECISION) >
- DEF_GYRO_CT_SHIFT_DELTA)
- ret_val |= (1 << i);
- }
- }
- /* check for absolute value passing criterion. Using DEF_ST_TOR
- * for certain degree of tolerance */
- for (i = 0; i < 3; i++) {
- if (abs(reg_avg[i]) > DEF_ST_TOR * DEF_ST_ABS_THRESH *
- DEF_ST_PRECISION * DEF_GYRO_SCALE)
- ret_val |= (1 << i);
- }
-
- return ret_val;
-}
-
-/**
-* inv_check_6050_gyro_self_test() - check 6050 gyro self test. this function
-* returns zero as success. A non-zero return
-* value indicates failure in self test.
-* @*st: main data structure.
-* @*reg_avg: average value of normal test.
-* @*st_avg: average value of self test
-*/
-static int inv_check_6050_gyro_self_test(struct inv_mpu_state *st,
- int *reg_avg, int *st_avg){
- int result;
- int ret_val;
- int st_shift_prod[3], st_shift_cust[3], st_shift_ratio[3], i;
- u8 regs[3];
-
- if (st->chip_info.software_revision < DEF_OLDEST_SUPP_SW_REV &&
- st->chip_info.product_revision < DEF_OLDEST_SUPP_PROD_REV)
- return 0;
-
- ret_val = 0;
- result = inv_i2c_read(st, REG_ST_GCT_X, 3, regs);
- if (result)
- return result;
- regs[X] &= 0x1f;
- regs[Y] &= 0x1f;
- regs[Z] &= 0x1f;
- for (i = 0; i < 3; i++) {
- if (regs[i] != 0)
- st_shift_prod[i] = gyro_6050_st_tb[regs[i] - 1];
- else
- st_shift_prod[i] = 0;
- }
- st_shift_prod[1] = -st_shift_prod[1];
-
- for (i = 0; i < 3; i++) {
- st_shift_cust[i] = st_avg[i] - reg_avg[i];
- if (st_shift_prod[i]) {
- st_shift_ratio[i] = abs(st_shift_cust[i] /
- st_shift_prod[i] - DEF_ST_PRECISION);
- if (st_shift_ratio[i] > DEF_GYRO_CT_SHIFT_DELTA)
- ret_val = 1;
- } else {
- if (st_shift_cust[i] < DEF_ST_PRECISION *
- DEF_GYRO_CT_SHIFT_MIN * DEF_SELFTEST_GYRO_SENS)
- ret_val = 1;
- if (st_shift_cust[i] > DEF_ST_PRECISION *
- DEF_GYRO_CT_SHIFT_MAX * DEF_SELFTEST_GYRO_SENS)
- ret_val = 1;
- }
- }
- /* check for absolute value passing criterion. Using DEF_ST_TOR
- * for certain degree of tolerance */
- for (i = 0; i < 3; i++)
- if (abs(reg_avg[i]) > DEF_ST_TOR * DEF_ST_ABS_THRESH *
- DEF_ST_PRECISION * DEF_GYRO_SCALE)
- ret_val = 1;
-
- return ret_val;
-}
-
-/**
-* inv_check_6500_gyro_self_test() - check 6500 gyro self test. this function
-* returns zero as success. A non-zero return
-* value indicates failure in self test.
-* @*st: main data structure.
-* @*reg_avg: average value of normal test.
-* @*st_avg: average value of self test
-*/
-static int inv_check_6500_gyro_self_test(struct inv_mpu_state *st,
- int *reg_avg, int *st_avg) {
- u8 regs[3];
- int ret_val, result;
- int otp_value_zero = 0;
- int st_shift_prod[3], st_shift_cust[3], i;
-
- ret_val = 0;
- result = inv_i2c_read(st, REG_6500_XG_ST_DATA, 3, regs);
- if (result)
- return result;
- pr_debug("%s self_test gyro shift_code - %02x %02x %02x\n",
- st->hw->name, regs[0], regs[1], regs[2]);
-
- for (i = 0; i < 3; i++) {
- if (regs[i] != 0) {
- st_shift_prod[i] = mpu_6500_st_tb[regs[i] - 1];
- } else {
- st_shift_prod[i] = 0;
- otp_value_zero = 1;
- }
- }
- pr_debug("%s self_test gyro st_shift_prod - %+d %+d %+d\n",
- st->hw->name, st_shift_prod[0], st_shift_prod[1],
- st_shift_prod[2]);
-
- for (i = 0; i < 3; i++) {
- st_shift_cust[i] = st_avg[i] - reg_avg[i];
- if (!otp_value_zero) {
- /* Self Test Pass/Fail Criteria A */
- if (st_shift_cust[i] < DEF_6500_GYRO_CT_SHIFT_DELTA
- * st_shift_prod[i])
- ret_val = 1;
- } else {
- /* Self Test Pass/Fail Criteria B */
- if (st_shift_cust[i] < DEF_GYRO_ST_AL *
- DEF_SELFTEST_GYRO_SENS *
- DEF_ST_PRECISION)
- ret_val = 1;
- }
- }
- pr_debug("%s self_test gyro st_shift_cust - %+d %+d %+d\n",
- st->hw->name, st_shift_cust[0], st_shift_cust[1],
- st_shift_cust[2]);
-
- if (ret_val == 0) {
- /* Self Test Pass/Fail Criteria C */
- for (i = 0; i < 3; i++)
- if (abs(reg_avg[i]) > DEF_GYRO_OFFSET_MAX *
- DEF_SELFTEST_GYRO_SENS *
- DEF_ST_PRECISION)
- ret_val = 1;
- }
-
- return ret_val;
-}
-
-/**
-* inv_check_6500_accel_self_test() - check 6500 accel self test. this function
-* returns zero as success. A non-zero return
-* value indicates failure in self test.
-* @*st: main data structure.
-* @*reg_avg: average value of normal test.
-* @*st_avg: average value of self test
-*/
-static int inv_check_6500_accel_self_test(struct inv_mpu_state *st,
- int *reg_avg, int *st_avg) {
- int ret_val, result;
- int st_shift_prod[3], st_shift_cust[3], st_shift_ratio[3], i;
- u8 regs[3];
- int otp_value_zero = 0;
-
-#define ACCEL_ST_AL_MIN ((DEF_ACCEL_ST_AL_MIN * DEF_ST_SCALE \
- / DEF_ST_6500_ACCEL_FS_MG) * DEF_ST_PRECISION)
-#define ACCEL_ST_AL_MAX ((DEF_ACCEL_ST_AL_MAX * DEF_ST_SCALE \
- / DEF_ST_6500_ACCEL_FS_MG) * DEF_ST_PRECISION)
-
- ret_val = 0;
- result = inv_i2c_read(st, REG_6500_XA_ST_DATA, 3, regs);
- if (result)
- return result;
- pr_debug("%s self_test accel shift_code - %02x %02x %02x\n",
- st->hw->name, regs[0], regs[1], regs[2]);
-
- for (i = 0; i < 3; i++) {
- if (regs[i] != 0) {
- st_shift_prod[i] = mpu_6500_st_tb[regs[i] - 1];
- } else {
- st_shift_prod[i] = 0;
- otp_value_zero = 1;
- }
- }
- pr_debug("%s self_test accel st_shift_prod - %+d %+d %+d\n",
- st->hw->name, st_shift_prod[0], st_shift_prod[1],
- st_shift_prod[2]);
-
- if (!otp_value_zero) {
- /* Self Test Pass/Fail Criteria A */
- for (i = 0; i < 3; i++) {
- st_shift_cust[i] = st_avg[i] - reg_avg[i];
- st_shift_ratio[i] = abs(st_shift_cust[i] /
- st_shift_prod[i] - DEF_ST_PRECISION);
- if (st_shift_ratio[i] > DEF_6500_ACCEL_ST_SHIFT_DELTA)
- ret_val = 1;
- }
- } else {
- /* Self Test Pass/Fail Criteria B */
- for (i = 0; i < 3; i++) {
- st_shift_cust[i] = abs(st_avg[i] - reg_avg[i]);
- if (st_shift_cust[i] < ACCEL_ST_AL_MIN ||
- st_shift_cust[i] > ACCEL_ST_AL_MAX)
- ret_val = 1;
- }
- }
- pr_debug("%s self_test accel st_shift_cust - %+d %+d %+d\n",
- st->hw->name, st_shift_cust[0], st_shift_cust[1],
- st_shift_cust[2]);
-
- return ret_val;
-}
-
-/*
- * inv_do_test() - do the actual test of self testing
- */
-static int inv_do_test(struct inv_mpu_state *st, int self_test_flag,
- int *gyro_result, int *accel_result)
-{
- struct inv_reg_map_s *reg;
- int result, i, j, packet_size;
- u8 data[BYTES_PER_SENSOR * 2], d;
- bool has_accel;
- int fifo_count, packet_count, ind, s;
-
- reg = &st->reg;
- has_accel = (st->chip_type != INV_ITG3500);
- if (has_accel)
- packet_size = BYTES_PER_SENSOR * 2;
- else
- packet_size = BYTES_PER_SENSOR;
-
- result = inv_i2c_single_write(st, reg->int_enable, 0);
- if (result)
- return result;
- /* disable the sensor output to FIFO */
- result = inv_i2c_single_write(st, reg->fifo_en, 0);
- if (result)
- return result;
- /* disable fifo reading */
- result = inv_i2c_single_write(st, reg->user_ctrl, 0);
- if (result)
- return result;
- /* clear FIFO */
- result = inv_i2c_single_write(st, reg->user_ctrl, BIT_FIFO_RST);
- if (result)
- return result;
- /* setup parameters */
- result = inv_i2c_single_write(st, reg->lpf, INV_FILTER_98HZ);
- if (result)
- return result;
-
- if (INV_MPU6500 == st->chip_type) {
- /* config accel LPF register for MPU6500 */
- result = inv_i2c_single_write(st, REG_6500_ACCEL_CONFIG2,
- DEF_ST_MPU6500_ACCEL_LPF |
- BIT_FIFO_SIZE_1K);
- if (result)
- return result;
- }
-
- result = inv_i2c_single_write(st, reg->sample_rate_div,
- DEF_SELFTEST_SAMPLE_RATE);
- if (result)
- return result;
- /* wait for the sampling rate change to stabilize */
- mdelay(INV_MPU_SAMPLE_RATE_CHANGE_STABLE);
- result = inv_i2c_single_write(st, reg->gyro_config,
- self_test_flag | DEF_SELFTEST_GYRO_FS);
- if (result)
- return result;
- if (has_accel) {
- if (INV_MPU6500 == st->chip_type)
- d = DEF_SELFTEST_6500_ACCEL_FS;
- else
- d = DEF_SELFTEST_ACCEL_FS;
- d |= self_test_flag;
- result = inv_i2c_single_write(st, reg->accel_config, d);
- if (result)
- return result;
- }
- /* wait for the output to get stable */
- if (self_test_flag) {
- if (INV_MPU6500 == st->chip_type)
- msleep(DEF_ST_6500_STABLE_TIME);
- else
- msleep(DEF_ST_STABLE_TIME);
- }
-
- /* enable FIFO reading */
- result = inv_i2c_single_write(st, reg->user_ctrl, BIT_FIFO_EN);
- if (result)
- return result;
- /* enable sensor output to FIFO */
- if (has_accel)
- d = BITS_GYRO_OUT | BIT_ACCEL_OUT;
- else
- d = BITS_GYRO_OUT;
- for (i = 0; i < THREE_AXIS; i++) {
- gyro_result[i] = 0;
- accel_result[i] = 0;
- }
- s = 0;
- while (s < st->self_test.samples) {
- result = inv_i2c_single_write(st, reg->fifo_en, d);
- if (result)
- return result;
- mdelay(DEF_GYRO_WAIT_TIME);
- result = inv_i2c_single_write(st, reg->fifo_en, 0);
- if (result)
- return result;
-
- result = inv_i2c_read(st, reg->fifo_count_h,
- FIFO_COUNT_BYTE, data);
- if (result)
- return result;
- fifo_count = be16_to_cpup((__be16 *)(&data[0]));
- pr_debug("%s self_test fifo_count - %d\n",
- st->hw->name, fifo_count);
- packet_count = fifo_count / packet_size;
- i = 0;
- while ((i < packet_count) && (s < st->self_test.samples)) {
- short vals[3];
- result = inv_i2c_read(st, reg->fifo_r_w,
- packet_size, data);
- if (result)
- return result;
- ind = 0;
- if (has_accel) {
- for (j = 0; j < THREE_AXIS; j++) {
- vals[j] = (short)be16_to_cpup(
- (__be16 *)(&data[ind + 2 * j]));
- accel_result[j] += vals[j];
- }
- ind += BYTES_PER_SENSOR;
- pr_debug(
- "%s self_test accel data - %d %+d %+d %+d",
- st->hw->name, s, vals[0], vals[1], vals[2]);
- }
-
- for (j = 0; j < THREE_AXIS; j++) {
- vals[j] = (short)be16_to_cpup(
- (__be16 *)(&data[ind + 2 * j]));
- gyro_result[j] += vals[j];
- }
- pr_debug("%s self_test gyro data - %d %+d %+d %+d",
- st->hw->name, s, vals[0], vals[1], vals[2]);
-
- s++;
- i++;
- }
- }
-
- if (has_accel) {
- for (j = 0; j < THREE_AXIS; j++) {
- accel_result[j] = accel_result[j] / s;
- accel_result[j] *= DEF_ST_PRECISION;
- }
- }
- for (j = 0; j < THREE_AXIS; j++) {
- gyro_result[j] = gyro_result[j] / s;
- gyro_result[j] *= DEF_ST_PRECISION;
- }
-
- return 0;
-}
-
-/*
- * inv_recover_setting() recover the old settings after everything is done
- */
-static void inv_recover_setting(struct inv_mpu_state *st)
-{
- struct inv_reg_map_s *reg;
- int data;
-
- reg = &st->reg;
- inv_i2c_single_write(st, reg->gyro_config,
- st->chip_config.fsr << GYRO_CONFIG_FSR_SHIFT);
- inv_i2c_single_write(st, reg->lpf, st->chip_config.lpf);
- data = ONE_K_HZ/st->chip_config.fifo_rate - 1;
- inv_i2c_single_write(st, reg->sample_rate_div, data);
- /* wait for the sampling rate change to stabilize */
- mdelay(INV_MPU_SAMPLE_RATE_CHANGE_STABLE);
- if (INV_ITG3500 != st->chip_type) {
- inv_i2c_single_write(st, reg->accel_config,
- (st->chip_config.accel_fs <<
- ACCEL_CONFIG_FSR_SHIFT));
- }
- inv_reset_offset_reg(st, false);
- st->switch_gyro_engine(st, false);
- st->switch_accel_engine(st, false);
- st->set_power_state(st, false);
-}
-
-
-static int inv_power_up_self_test(struct inv_mpu_state *st)
-{
- int result;
-
- result = st->set_power_state(st, true);
- if (result)
- return result;
- result = st->switch_accel_engine(st, true);
- if (result)
- return result;
- result = st->switch_gyro_engine(st, true);
- if (result)
- return result;
-
- return 0;
-}
-
-/*
- * inv_hw_self_test() - main function to do hardware self test
- */
-int inv_hw_self_test(struct inv_mpu_state *st)
-{
- int result;
- int gyro_bias_st[THREE_AXIS], gyro_bias_regular[THREE_AXIS];
- int accel_bias_st[THREE_AXIS], accel_bias_regular[THREE_AXIS];
- int test_times, i;
- char compass_result, accel_result, gyro_result;
-
- result = inv_power_up_self_test(st);
- if (result)
- return result;
- result = inv_reset_offset_reg(st, true);
- if (result)
- return result;
- compass_result = 0;
- accel_result = 0;
- gyro_result = 0;
- test_times = DEF_ST_TRY_TIMES;
- while (test_times > 0) {
- result = inv_do_test(st, 0, gyro_bias_regular,
- accel_bias_regular);
- if (result == -EAGAIN)
- test_times--;
- else
- test_times = 0;
- }
- if (result)
- goto test_fail;
- pr_debug("%s self_test accel bias_regular - %+d %+d %+d\n",
- st->hw->name, accel_bias_regular[0],
- accel_bias_regular[1], accel_bias_regular[2]);
- pr_debug("%s self_test gyro bias_regular - %+d %+d %+d\n",
- st->hw->name, gyro_bias_regular[0], gyro_bias_regular[1],
- gyro_bias_regular[2]);
-
- for (i = 0; i < 3; i++) {
- st->gyro_bias[i] = gyro_bias_regular[i];
- st->accel_bias[i] = accel_bias_regular[i];
- }
-
- test_times = DEF_ST_TRY_TIMES;
- while (test_times > 0) {
- result = inv_do_test(st, BITS_SELF_TEST_EN, gyro_bias_st,
- accel_bias_st);
- if (result == -EAGAIN)
- test_times--;
- else
- break;
- }
- if (result)
- goto test_fail;
- pr_debug("%s self_test accel bias_st - %+d %+d %+d\n",
- st->hw->name, accel_bias_st[0], accel_bias_st[1],
- accel_bias_st[2]);
- pr_debug("%s self_test gyro bias_st - %+d %+d %+d\n",
- st->hw->name, gyro_bias_st[0], gyro_bias_st[1],
- gyro_bias_st[2]);
-
- if (st->chip_type == INV_ITG3500) {
- gyro_result = !inv_check_3500_gyro_self_test(st,
- gyro_bias_regular, gyro_bias_st);
- } else {
- if (st->chip_config.has_compass)
- compass_result = !st->slave_compass->self_test(st);
-
- if (INV_MPU6050 == st->chip_type) {
- accel_result = !inv_check_accel_self_test(st,
- accel_bias_regular, accel_bias_st);
- gyro_result = !inv_check_6050_gyro_self_test(st,
- gyro_bias_regular, gyro_bias_st);
- } else if (INV_MPU6500 == st->chip_type) {
- accel_result = !inv_check_6500_accel_self_test(st,
- accel_bias_regular, accel_bias_st);
- gyro_result = !inv_check_6500_gyro_self_test(st,
- gyro_bias_regular, gyro_bias_st);
- }
- }
-
-test_fail:
- inv_recover_setting(st);
-
- return (compass_result << DEF_ST_COMPASS_RESULT_SHIFT) |
- (accel_result << DEF_ST_ACCEL_RESULT_SHIFT) | gyro_result;
-}
-
-static int inv_load_firmware(struct inv_mpu_state *st,
- u8 *data, int size)
-{
- int bank, write_size;
- int result;
- u16 memaddr;
-
- /* first bank start at MPU_DMP_LOAD_START */
- write_size = MPU_MEM_BANK_SIZE - MPU_DMP_LOAD_START;
- memaddr = MPU_DMP_LOAD_START;
- result = mem_w(memaddr, write_size, data);
- if (result)
- return result;
- size -= write_size;
- data += write_size;
-
- /* Write and verify memory */
- for (bank = 1; size > 0; bank++, size -= write_size,
- data += write_size) {
- if (size > MPU_MEM_BANK_SIZE)
- write_size = MPU_MEM_BANK_SIZE;
- else
- write_size = size;
-
- memaddr = ((bank << 8) | 0x00);
-
- result = mem_w(memaddr, write_size, data);
- if (result)
- return result;
- }
- return 0;
-}
-
-static int inv_verify_firmware(struct inv_mpu_state *st,
- u8 *data, int size)
-{
- int bank, write_size;
- int result;
- u16 memaddr;
- u8 firmware[MPU_MEM_BANK_SIZE];
-
- /* Write and verify memory */
- write_size = MPU_MEM_BANK_SIZE - MPU_DMP_LOAD_START;
- size -= write_size;
- data += write_size;
- for (bank = 1; size > 0; bank++,
- size -= write_size,
- data += write_size) {
- if (size > MPU_MEM_BANK_SIZE)
- write_size = MPU_MEM_BANK_SIZE;
- else
- write_size = size;
-
- memaddr = ((bank << 8) | 0x00);
- result = mpu_memory_read(st,
- st->i2c_addr, memaddr, write_size, firmware);
- if (result)
- return result;
- if (0 != memcmp(firmware, data, write_size))
- return -EINVAL;
- }
- return 0;
-}
-
-static int inv_set_step_buffer_time(struct inv_mpu_state *st)
-{
- /* Pedometer executes at 50Hz so 1.5 seconds is 20ms * 75 */
- return inv_write_2bytes(st, KEY_D_PEDSTD_SB_TIME, 75);
-}
-
-static int inv_set_step_threshold(struct inv_mpu_state *st)
-{
- return inv_write_2bytes(st, KEY_D_PEDSTD_SB, st->ped.step_thresh);
-}
-
-int inv_enable_pedometer_interrupt(struct inv_mpu_state *st, bool en)
-{
- u8 reg[3];
-
- if (en) {
- reg[0] = 0xf4;
- reg[1] = 0x44;
- reg[2] = 0xf1;
-
- } else {
- reg[0] = 0xf1;
- reg[1] = 0xf1;
- reg[2] = 0xf1;
- }
-
- return mem_w_key(KEY_CFG_PED_INT, ARRAY_SIZE(reg), reg);
-}
-
-int inv_read_pedometer_counter(struct inv_mpu_state *st)
-{
- int result;
- u8 d[4];
- u32 last_step_counter, curr_counter;
-
- result = mpu_memory_read(st, st->i2c_addr,
- inv_dmp_get_address(KEY_D_STPDET_TIMESTAMP), 4, d);
- if (result)
- return result;
- last_step_counter = (u32)be32_to_cpup((__be32 *)(d));
-
- result = mpu_memory_read(st, st->i2c_addr,
- inv_dmp_get_address(KEY_DMP_RUN_CNTR), 4, d);
- if (result)
- return result;
- curr_counter = (u32)be32_to_cpup((__be32 *)(d));
- if (0 != last_step_counter)
- st->ped.last_step_time = get_time_ns() -
- ((u64)(curr_counter - last_step_counter)) *
- DMP_INTERVAL_INIT;
-
- return 0;
-}
-
-int inv_enable_pedometer(struct inv_mpu_state *st, bool en)
-{
- u8 d[1];
-
- if (en) {
- inv_set_step_buffer_time(st);
- inv_set_step_threshold(st);
- d[0] = 0xf1;
- } else {
- d[0] = 0xff;
- }
- return mem_w_key(KEY_CFG_PED_ENABLE, ARRAY_SIZE(d), d);
-}
-
-int inv_get_pedometer_steps(struct inv_mpu_state *st, u32 *steps)
-{
- u8 d[4];
- int result;
-
- result = mpu_memory_read(st, st->i2c_addr,
- inv_dmp_get_address(KEY_D_PEDSTD_STEPCTR), 4, d);
- *steps = (u32)be32_to_cpup((__be32 *)(d));
-
- return result;
-}
-
-int inv_get_pedometer_time(struct inv_mpu_state *st, u32 *time)
-{
- u8 d[4];
- int result;
-
- result = mpu_memory_read(st, st->i2c_addr,
- inv_dmp_get_address(KEY_D_PEDSTD_TIMECTR), 4, d);
- *time = (u32)be32_to_cpup((__be32 *)(d));
-
- return result;
-}
-
-int inv_set_display_orient_interrupt_dmp(struct inv_mpu_state *st, bool on)
-{
- int r;
- u8 rn[] = {0xf4, 0x41};
- u8 rf[] = {0xd8, 0xd8};
-
- if (on)
- r = mem_w_key(KEY_CFG_DISPLAY_ORIENT_INT, ARRAY_SIZE(rn), rn);
- else
- r = mem_w_key(KEY_CFG_DISPLAY_ORIENT_INT, ARRAY_SIZE(rf), rf);
-
- return r;
-}
-
-static int inv_set_tap_interrupt_dmp(struct inv_mpu_state *st, u8 on)
-{
- int result;
- u16 d;
-
- if (on)
- d = 192;
- else
- d = 128;
-
- result = inv_write_2bytes(st, KEY_DMP_TAP_GATE, d);
-
- return result;
-}
-
-/*
- * inv_set_tap_threshold_dmp():
- * Sets the tap threshold in the dmp
- * Simultaneously sets secondary tap threshold to help correct the tap
- * direction for soft taps.
- */
-int inv_set_tap_threshold_dmp(struct inv_mpu_state *st, u16 threshold)
-{
- int result;
- int sampleDivider;
- int scaledThreshold;
- u32 dmpThreshold;
- u8 sample_div;
- const u32 accel_sens = (0x20000000 / 0x00010000);
-
- if (threshold > (1 << 15))
- return -EINVAL;
- sample_div = st->sample_divider;
-
- sampleDivider = (1 + sample_div);
- /* Scale factor corresponds linearly using
- * 0 : 0
- * 25 : 0.0250 g/ms
- * 50 : 0.0500 g/ms
- * 100: 1.0000 g/ms
- * 200: 2.0000 g/ms
- * 400: 4.0000 g/ms
- * 800: 8.0000 g/ms
- */
- /*multiply by 1000 to avoid floating point 1000/1000*/
- scaledThreshold = threshold;
- /* Convert to per sample */
- scaledThreshold *= sampleDivider;
-
- /* Scale to DMP 16 bit value */
- if (accel_sens != 0)
- dmpThreshold = (u32)(scaledThreshold * accel_sens);
- else
- return -EINVAL;
- dmpThreshold = dmpThreshold / DMP_PRECISION;
- result = inv_write_2bytes(st, KEY_DMP_TAP_THR_Z, dmpThreshold);
- if (result)
- return result;
- result = inv_write_2bytes(st, KEY_DMP_TAP_PREV_JERK_Z,
- dmpThreshold * 3 / 4);
-
- return result;
-}
-
-
-/*
- * inv_set_min_taps_dmp():
- * Indicates the minimum number of consecutive taps required
- * before the DMP will generate an interrupt.
- */
-int inv_set_min_taps_dmp(struct inv_mpu_state *st, u16 min_taps)
-{
- u8 result;
-
- /* check if any spurious bit other the ones expected are set */
- if ((min_taps > DMP_MAX_MIN_TAPS) || (min_taps < 1))
- return -EINVAL;
-
- /* DMP tap count is zero-based. So single-tap is 0.
- Furthermore, DMP code checks for tap_count > min_taps.
- So we have to do minus 2 here.
- For example, if the user expects any single tap will generate an
- interrupt, (s)he will call inv_set_min_taps_dmp(1).
- When DMP gets a single tap, tap_count = 0. To get
- tap_count > min_taps, we have to decrement min_taps by 2 to -1. */
- result = inv_write_2bytes(st, KEY_DMP_TAP_MIN_TAPS, (u16)(min_taps-2));
-
- return result;
-}
-
-/*
- * inv_set_tap_time_dmp():
- * Determines how long after a tap the DMP requires before
- * another tap can be registered.
- */
-int inv_set_tap_time_dmp(struct inv_mpu_state *st, u16 time)
-{
- int result;
- u16 dmpTime;
- u8 sampleDivider;
-
- sampleDivider = st->sample_divider;
- sampleDivider++;
-
- /* 60 ms minimum time added */
- dmpTime = ((time) / sampleDivider);
- result = inv_write_2bytes(st, KEY_DMP_TAPW_MIN, dmpTime);
-
- return result;
-}
-
-/*
- * inv_set_multiple_tap_time_dmp():
- * Determines how close together consecutive taps must occur
- * to be considered double/triple taps.
- */
-static int inv_set_multiple_tap_time_dmp(struct inv_mpu_state *st, u32 time)
-{
- int result;
- u16 dmpTime;
- u8 sampleDivider;
-
- sampleDivider = st->sample_divider;
- sampleDivider++;
-
- /* 60 ms minimum time added */
- dmpTime = ((time) / sampleDivider);
- result = inv_write_2bytes(st, KEY_DMP_TAP_NEXT_TAP_THRES, dmpTime);
-
- return result;
-}
-
-int inv_q30_mult(int a, int b)
-{
- u64 temp;
- int result;
-
- temp = (u64)a * b;
- result = (int)(temp >> DMP_MULTI_SHIFT);
-
- return result;
-}
-
-static u16 inv_row_2_scale(const s8 *row)
-{
- u16 b;
-
- if (row[0] > 0)
- b = 0;
- else if (row[0] < 0)
- b = 4;
- else if (row[1] > 0)
- b = 1;
- else if (row[1] < 0)
- b = 5;
- else if (row[2] > 0)
- b = 2;
- else if (row[2] < 0)
- b = 6;
- else
- b = 7;
-
- return b;
-}
-
-/** Converts an orientation matrix made up of 0,+1,and -1 to a scalar
-* representation.
-* @param[in] mtx Orientation matrix to convert to a scalar.
-* @return Description of orientation matrix. The lowest 2 bits (0 and 1)
-* represent the column the one is on for the
-* first row, with the bit number 2 being the sign. The next 2 bits
-* (3 and 4) represent
-* the column the one is on for the second row with bit number 5 being
-* the sign.
-* The next 2 bits (6 and 7) represent the column the one is on for the
-* third row with
-* bit number 8 being the sign. In binary the identity matrix would therefor
-* be: 010_001_000 or 0x88 in hex.
-*/
-static u16 inv_orientation_matrix_to_scaler(const signed char *mtx)
-{
-
- u16 scalar;
- scalar = inv_row_2_scale(mtx);
- scalar |= inv_row_2_scale(mtx + 3) << 3;
- scalar |= inv_row_2_scale(mtx + 6) << 6;
-
- return scalar;
-}
-
-static int inv_gyro_dmp_cal(struct inv_mpu_state *st)
-{
- int inv_gyro_orient;
- u8 regs[3];
- int result;
-
- u8 tmpD = DINA4C;
- u8 tmpE = DINACD;
- u8 tmpF = DINA6C;
-
- inv_gyro_orient =
- inv_orientation_matrix_to_scaler(st->plat_data.orientation);
-
- if ((inv_gyro_orient & 3) == 0)
- regs[0] = tmpD;
- else if ((inv_gyro_orient & 3) == 1)
- regs[0] = tmpE;
- else if ((inv_gyro_orient & 3) == 2)
- regs[0] = tmpF;
- if ((inv_gyro_orient & 0x18) == 0)
- regs[1] = tmpD;
- else if ((inv_gyro_orient & 0x18) == 0x8)
- regs[1] = tmpE;
- else if ((inv_gyro_orient & 0x18) == 0x10)
- regs[1] = tmpF;
- if ((inv_gyro_orient & 0xc0) == 0)
- regs[2] = tmpD;
- else if ((inv_gyro_orient & 0xc0) == 0x40)
- regs[2] = tmpE;
- else if ((inv_gyro_orient & 0xc0) == 0x80)
- regs[2] = tmpF;
-
- result = mem_w_key(KEY_FCFG_1, ARRAY_SIZE(regs), regs);
- if (result)
- return result;
-
- if (inv_gyro_orient & 4)
- regs[0] = DINA36 | 1;
- else
- regs[0] = DINA36;
- if (inv_gyro_orient & 0x20)
- regs[1] = DINA56 | 1;
- else
- regs[1] = DINA56;
- if (inv_gyro_orient & 0x100)
- regs[2] = DINA76 | 1;
- else
- regs[2] = DINA76;
- result = mem_w_key(KEY_FCFG_3, ARRAY_SIZE(regs), regs);
-
- return result;
-}
-
-static int inv_accel_dmp_cal(struct inv_mpu_state *st)
-{
- int inv_accel_orient;
- int result;
- u8 regs[3];
- const u8 tmp[3] = { DINA0C, DINAC9, DINA2C };
- inv_accel_orient =
- inv_orientation_matrix_to_scaler(st->plat_data.orientation);
-
- regs[0] = tmp[inv_accel_orient & 3];
- regs[1] = tmp[(inv_accel_orient >> 3) & 3];
- regs[2] = tmp[(inv_accel_orient >> 6) & 3];
- result = mem_w_key(KEY_FCFG_2, ARRAY_SIZE(regs), regs);
- if (result)
- return result;
-
- regs[0] = DINA26;
- regs[1] = DINA46;
- regs[2] = DINA66;
- if (inv_accel_orient & 4)
- regs[0] |= 1;
- if (inv_accel_orient & 0x20)
- regs[1] |= 1;
- if (inv_accel_orient & 0x100)
- regs[2] |= 1;
- result = mem_w_key(KEY_FCFG_7, ARRAY_SIZE(regs), regs);
-
- return result;
-}
-
-int inv_set_accel_bias_dmp(struct inv_mpu_state *st)
-{
- int inv_accel_orient, result, i, accel_bias_body[3], out[3];
- int tmp[] = {1, 1, 1};
- int mask[] = {4, 0x20, 0x100};
- int accel_sf = 0x20000000;/* 536870912 */
- u8 *regs;
-
- inv_accel_orient =
- inv_orientation_matrix_to_scaler(st->plat_data.orientation);
-
- for (i = 0; i < 3; i++)
- if (inv_accel_orient & mask[i])
- tmp[i] = -1;
-
- for (i = 0; i < 3; i++)
- accel_bias_body[i] =
- st->input_accel_dmp_bias[(inv_accel_orient >>
- (i * 3)) & 3] * tmp[i];
- for (i = 0; i < 3; i++)
- accel_bias_body[i] = inv_q30_mult(accel_sf,
- accel_bias_body[i]);
- for (i = 0; i < 3; i++)
- out[i] = cpu_to_be32p(&accel_bias_body[i]);
- regs = (u8 *)out;
- result = mem_w_key(KEY_D_ACCEL_BIAS, sizeof(out), regs);
-
- return result;
-}
-
-/*
- * inv_set_gyro_sf_dmp():
- * The gyro threshold, in dps, above which taps will be rejected.
- */
-static int inv_set_gyro_sf_dmp(struct inv_mpu_state *st)
-{
- int result;
- u8 sampleDivider;
- u32 gyro_sf;
- const u32 gyro_sens = 0x03e80000;
-
- sampleDivider = st->sample_divider;
- gyro_sf = inv_q30_mult(gyro_sens,
- (int)(DMP_TAP_SCALE * (sampleDivider + 1)));
- result = write_be32_key_to_mem(st, gyro_sf, KEY_D_0_104);
-
- return result;
-}
-
-/*
- * inv_set_shake_reject_thresh_dmp():
- * The gyro threshold, in dps, above which taps will be rejected.
- */
-static int inv_set_shake_reject_thresh_dmp(struct inv_mpu_state *st,
- int thresh)
-{
- int result;
- u8 sampleDivider;
- int thresh_scaled;
- u32 gyro_sf;
- const u32 gyro_sens = 0x03e80000;
-
- sampleDivider = st->sample_divider;
- gyro_sf = inv_q30_mult(gyro_sens, (int)(DMP_TAP_SCALE *
- (sampleDivider + 1)));
- /* We're in units of DPS, convert it back to chip units*/
- /*split the operation to aviod overflow of integer*/
- thresh_scaled = gyro_sens / (1L << 16);
- thresh_scaled = thresh_scaled / thresh;
- thresh_scaled = gyro_sf / thresh_scaled;
- result = write_be32_key_to_mem(st, thresh_scaled,
- KEY_DMP_TAP_SHAKE_REJECT);
-
- return result;
-}
-
-/*
- * inv_set_shake_reject_time_dmp():
- * How long a gyro axis must remain above its threshold
- * before taps are rejected.
- */
-static int inv_set_shake_reject_time_dmp(struct inv_mpu_state *st,
- u32 time)
-{
- int result;
- u16 dmpTime;
- u8 sampleDivider;
-
- sampleDivider = st->sample_divider;
- sampleDivider++;
-
- /* 60 ms minimum time added */
- dmpTime = ((time) / sampleDivider);
- result = inv_write_2bytes(st, KEY_DMP_TAP_SHAKE_COUNT_MAX, dmpTime);
-
- return result;
-}
-
-/*
- * inv_set_shake_reject_timeout_dmp():
- * How long the gyros must remain below their threshold,
- * after taps have been rejected, before taps can be detected again.
- */
-static int inv_set_shake_reject_timeout_dmp(struct inv_mpu_state *st,
- u32 time)
-{
- int result;
- u16 dmpTime;
- u8 sampleDivider;
-
- sampleDivider = st->sample_divider;
- sampleDivider++;
-
- /* 60 ms minimum time added */
- dmpTime = ((time) / sampleDivider);
- result = inv_write_2bytes(st, KEY_DMP_TAP_SHAKE_TIMEOUT_MAX, dmpTime);
-
- return result;
-}
-
-int inv_set_interrupt_on_gesture_event(struct inv_mpu_state *st, bool on)
-{
- u8 r;
- const u8 rn[] = {0xA3};
- const u8 rf[] = {0xFE};
-
- if (on)
- r = mem_w_key(KEY_CFG_FIFO_INT, ARRAY_SIZE(rn), rn);
- else
- r = mem_w_key(KEY_CFG_FIFO_INT, ARRAY_SIZE(rf), rf);
-
- return r;
-}
-
-/*
- * inv_enable_tap_dmp() - calling this function will enable/disable tap
- * function.
- */
-int inv_enable_tap_dmp(struct inv_mpu_state *st, bool on)
-{
- int result;
-
- result = inv_set_tap_interrupt_dmp(st, on);
- if (result)
- return result;
- result = inv_set_tap_threshold_dmp(st, st->tap.thresh);
- if (result)
- return result;
-
- result = inv_set_min_taps_dmp(st, st->tap.min_count);
- if (result)
- return result;
-
- result = inv_set_tap_time_dmp(st, st->tap.time);
- if (result)
- return result;
-
- result = inv_set_multiple_tap_time_dmp(st, DMP_MULTI_TAP_TIME);
- if (result)
- return result;
-
- result = inv_set_gyro_sf_dmp(st);
- if (result)
- return result;
-
- result = inv_set_shake_reject_thresh_dmp(st, DMP_SHAKE_REJECT_THRESH);
- if (result)
- return result;
-
- result = inv_set_shake_reject_time_dmp(st, DMP_SHAKE_REJECT_TIME);
- if (result)
- return result;
-
- result = inv_set_shake_reject_timeout_dmp(st,
- DMP_SHAKE_REJECT_TIMEOUT);
- return result;
-}
-
-static int inv_dry_run_dmp(struct inv_mpu_state *st)
-{
- int result;
- struct inv_reg_map_s *reg;
-
- reg = &st->reg;
- result = st->switch_gyro_engine(st, true);
- if (result)
- return result;
- result = inv_i2c_single_write(st, reg->user_ctrl, BIT_DMP_EN);
- if (result)
- return result;
- msleep(400);
- result = inv_i2c_single_write(st, reg->user_ctrl, 0);
- if (result)
- return result;
- result = st->switch_gyro_engine(st, false);
- if (result)
- return result;
-
- return 0;
-}
-
-static void inv_test_reset(struct inv_mpu_state *st)
-{
- int result, ii;
- u8 d[0x80];
-
- if (INV_MPU6500 != st->chip_type)
- return;
-
- for (ii = 3; ii < 0x80; ii++) {
- /* don't read fifo r/w register */
- if (ii != st->reg.fifo_r_w)
- inv_i2c_read(st, ii, 1, &d[ii]);
- }
- result = inv_i2c_single_write(st, st->reg.pwr_mgmt_1, BIT_H_RESET);
- if (result)
- return;
- msleep(POWER_UP_TIME);
-
- for (ii = 3; ii < 0x80; ii++) {
- /* don't write certain registers */
- if ((ii != st->reg.fifo_r_w) &&
- (ii != st->reg.mem_r_w) &&
- (ii != st->reg.mem_start_addr) &&
- (ii != st->reg.fifo_count_h) &&
- ii != (st->reg.fifo_count_h + 1))
- result = inv_i2c_single_write(st, ii, d[ii]);
- }
-}
-
-/*
- * inv_dmp_firmware_write() - calling this function will load the firmware.
- * This is the write function of file "dmp_firmware".
- */
-ssize_t inv_dmp_firmware_write(struct file *fp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t pos, size_t size)
-{
- u8 *firmware;
- int result;
- struct inv_reg_map_s *reg;
- struct iio_dev *indio_dev;
- struct inv_mpu_state *st;
-
- indio_dev = dev_get_drvdata(container_of(kobj, struct device, kobj));
- st = iio_priv(indio_dev);
-
- if (st->chip_config.firmware_loaded)
- return -EINVAL;
- if (st->chip_config.enable)
- return -EBUSY;
-
- reg = &st->reg;
- if (DMP_IMAGE_SIZE != size) {
- pr_err("wrong DMP image size - expected %d, actual %d\n",
- DMP_IMAGE_SIZE, size);
- return -EINVAL;
- }
-
- firmware = kmalloc(size, GFP_KERNEL);
- if (!firmware)
- return -ENOMEM;
-
- mutex_lock(&indio_dev->mlock);
-
- memcpy(firmware, buf, size);
- result = crc32(CRC_FIRMWARE_SEED, firmware, size);
- if (DMP_IMAGE_CRC_VALUE != result) {
- pr_err("firmware CRC error - 0x%08x vs 0x%08x\n",
- result, DMP_IMAGE_CRC_VALUE);
- result = -EINVAL;
- goto firmware_write_fail;
- }
-
- result = st->set_power_state(st, true);
- if (result)
- goto firmware_write_fail;
- inv_test_reset(st);
-
- result = inv_load_firmware(st, firmware, size);
- if (result)
- goto firmware_write_fail;
-
- result = inv_verify_firmware(st, firmware, size);
- if (result)
- goto firmware_write_fail;
-
- result = inv_i2c_single_write(st, reg->prgm_strt_addrh,
- st->chip_config.prog_start_addr >> 8);
- if (result)
- goto firmware_write_fail;
- result = inv_i2c_single_write(st, reg->prgm_strt_addrh + 1,
- st->chip_config.prog_start_addr & 0xff);
- if (result)
- goto firmware_write_fail;
-
- result = inv_gyro_dmp_cal(st);
- if (result)
- goto firmware_write_fail;
- result = inv_accel_dmp_cal(st);
- if (result)
- goto firmware_write_fail;
- result = inv_dry_run_dmp(st);
- if (result)
- goto firmware_write_fail;
-
- st->chip_config.firmware_loaded = 1;
-
-firmware_write_fail:
- result |= st->set_power_state(st, false);
- mutex_unlock(&indio_dev->mlock);
- kfree(firmware);
- if (result)
- return result;
-
- return size;
-}
-
-ssize_t inv_dmp_firmware_read(struct file *filp,
- struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count)
-{
- int bank, write_size, size, data, result;
- u16 memaddr;
- struct iio_dev *indio_dev;
- struct inv_mpu_state *st;
-
- size = count;
- indio_dev = dev_get_drvdata(container_of(kobj, struct device, kobj));
- st = iio_priv(indio_dev);
-
- data = 0;
- mutex_lock(&indio_dev->mlock);
- if (!st->chip_config.enable) {
- result = st->set_power_state(st, true);
- if (result) {
- mutex_unlock(&indio_dev->mlock);
- return result;
- }
- }
- for (bank = 0; size > 0; bank++, size -= write_size,
- data += write_size) {
- if (size > MPU_MEM_BANK_SIZE)
- write_size = MPU_MEM_BANK_SIZE;
- else
- write_size = size;
-
- memaddr = (bank << 8);
- result = mpu_memory_read(st,
- st->i2c_addr, memaddr, write_size, &buf[data]);
- if (result) {
- mutex_unlock(&indio_dev->mlock);
- return result;
- }
- }
- if (!st->chip_config.enable)
- result = st->set_power_state(st, false);
- mutex_unlock(&indio_dev->mlock);
- if (result)
- return result;
-
- return count;
-}
-
-ssize_t inv_six_q_write(struct file *fp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t pos, size_t size)
-{
- u8 q[QUATERNION_BYTES];
- struct inv_reg_map_s *reg;
- struct iio_dev *indio_dev;
- struct inv_mpu_state *st;
- int result;
-
- indio_dev = dev_get_drvdata(container_of(kobj, struct device, kobj));
- st = iio_priv(indio_dev);
-
- mutex_lock(&indio_dev->mlock);
-
- if (!st->chip_config.firmware_loaded) {
- mutex_unlock(&indio_dev->mlock);
- return -EINVAL;
- }
- if (st->chip_config.enable) {
- mutex_unlock(&indio_dev->mlock);
- return -EBUSY;
- }
- reg = &st->reg;
- if (QUATERNION_BYTES != size) {
- pr_err("wrong quaternion size=%d, should=%d\n", size,
- QUATERNION_BYTES);
- mutex_unlock(&indio_dev->mlock);
- return -EINVAL;
- }
-
- memcpy(q, buf, size);
- result = st->set_power_state(st, true);
- if (result)
- goto firmware_write_fail;
- result = mem_w_key(KEY_DMP_Q0, QUATERNION_BYTES, q);
-
-firmware_write_fail:
- result |= st->set_power_state(st, false);
- mutex_unlock(&indio_dev->mlock);
- if (result)
- return result;
-
- return size;
-}
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_ring.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_ring.c
deleted file mode 100644
index 9c3d0912df4..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_ring.c
+++ /dev/null
@@ -1,1899 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-
-#include "iio.h"
-#include "kfifo_buf.h"
-#include "trigger_consumer.h"
-#include "sysfs.h"
-
-#include "inv_mpu_iio.h"
-
-static u8 fifo_data[HARDWARE_FIFO_SIZE + HEADERED_Q_BYTES];
-static int inv_process_batchmode(struct inv_mpu_state *st);
-
-static int inv_push_marker_to_buffer(struct inv_mpu_state *st, u16 hdr)
-{
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- u8 buf[IIO_BUFFER_BYTES];
-
- memcpy(buf, &hdr, sizeof(hdr));
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_push_to_buffers(indio_dev, buf);
-#else
- iio_push_to_buffer(indio_dev->buffer, buf, 0);
-#endif
- return 0;
-}
-
-static int inv_push_8bytes_buffer(struct inv_mpu_state *st, u16 hdr,
- u64 t, s16 *d)
-{
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- u8 buf[IIO_BUFFER_BYTES];
- int i;
-
- memcpy(buf, &hdr, sizeof(hdr));
- for (i = 0; i < 3; i++)
- memcpy(&buf[2 + i * 2], &d[i], sizeof(d[i]));
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_push_to_buffers(indio_dev, buf);
-#else
- iio_push_to_buffer(indio_dev->buffer, buf, 0);
-#endif
- memcpy(buf, &t, sizeof(t));
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_push_to_buffers(indio_dev, buf);
-#else
- iio_push_to_buffer(indio_dev->buffer, buf, 0);
-#endif
- return 0;
-}
-
-static int inv_push_16bytes_buffer(struct inv_mpu_state *st, u16 hdr, u64 t,
- int *q)
-{
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- u8 buf[IIO_BUFFER_BYTES];
- int i;
-
- memcpy(buf, &hdr, sizeof(hdr));
- memcpy(buf + 4, &q[0], sizeof(q[0]));
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_push_to_buffers(indio_dev, buf);
-#else
- iio_push_to_buffer(indio_dev->buffer, buf, 0);
-#endif
- for (i = 0; i < 2; i++)
- memcpy(buf + 4 * i, &q[i + 1], sizeof(q[i]));
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_push_to_buffers(indio_dev, buf);
-#else
- iio_push_to_buffer(indio_dev->buffer, buf, 0);
-#endif
- memcpy(buf, &t, sizeof(t));
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_push_to_buffers(indio_dev, buf);
-#else
- iio_push_to_buffer(indio_dev->buffer, buf, 0);
-#endif
-
- return 0;
-}
-
-static int inv_send_pressure_data(struct inv_mpu_state *st)
-{
- short sen[3];
- struct inv_chip_config_s *conf;
- struct inv_mpu_slave *slave;
- u64 curr_ts;
- int result;
-
- conf = &st->chip_config;
- slave = st->slave_pressure;
- if (!st->sensor[SENSOR_PRESSURE].on)
- return 0;
- if (conf->dmp_on && conf->dmp_event_int_on)
- return 0;
- if (!conf->normal_pressure_measure) {
- conf->normal_pressure_measure = 1;
- return 0;
- }
- curr_ts = get_time_ns();
- if (curr_ts - slave->prev_ts > slave->min_read_time) {
- result = slave->read_data(st, sen);
- if (!result)
- inv_push_8bytes_buffer(st, PRESSURE_HDR,
- st->last_ts, sen);
- slave->prev_ts = curr_ts;
- }
-
- return 0;
-}
-
-static int inv_send_compass_data(struct inv_mpu_state *st)
-{
- short sen[3];
- struct inv_chip_config_s *conf;
- struct inv_mpu_slave *slave;
- u64 curr_ts;
- int result;
-
- conf = &st->chip_config;
- slave = st->slave_compass;
- if (!st->sensor[SENSOR_COMPASS].on)
- return 0;
- if (conf->dmp_on && conf->dmp_event_int_on)
- return 0;
- if (!conf->normal_compass_measure) {
- conf->normal_compass_measure = 1;
- return 0;
- }
- curr_ts = get_time_ns();
- if (curr_ts - slave->prev_ts > slave->min_read_time) {
- result = slave->read_data(st, sen);
- if (result)
- inv_push_marker_to_buffer(st, COMPASS_HDR_2);
- else
- inv_push_8bytes_buffer(st, COMPASS_HDR,
- st->last_ts, sen);
- slave->prev_ts = curr_ts;
- }
-
- return 0;
-}
-
-static int inv_batchmode_calc(struct inv_mpu_state *st)
-{
- int b, timeout;
- int rate_dur;
-
- rate_dur = MSEC_PER_SEC / st->batch.min_rate;
- if (st->batch.timeout < rate_dur)
- st->batch.timeout = rate_dur;
- b = st->batch.timeout * st->bytes_per_sec;
- if ((b > (FIFO_SIZE * ONE_K_HZ)) && (!st->batch.overflow_on))
- timeout = FIFO_SIZE * ONE_K_HZ / st->bytes_per_sec;
- else
- timeout = st->batch.timeout;
-
- st->batch.counter = timeout / 5;
- if (timeout)
- st->batch.on = true;
-
- return 0;
-}
-
-int inv_batchmode_setup(struct inv_mpu_state *st)
-{
- int r;
-
- r = inv_write_2bytes(st, KEY_BM_NUMWORD_TOFILL, 0);
- if (r)
- return r;
- r = write_be32_key_to_mem(st, 0, KEY_BM_BATCH_CNTR);
- if (r)
- return r;
-
- if (st->chip_config.dmp_on && (st->batch.timeout > 0) &&
- (st->chip_config.dmp_event_int_on == 0)) {
- r = inv_batchmode_calc(st);
- if (r)
- return r;
- }
-
- if (st->batch.on) {
- r = write_be32_key_to_mem(st, st->batch.counter,
- KEY_BM_BATCH_THLD);
- if (r)
- return r;
- }
- r = inv_write_2bytes(st, KEY_BM_ENABLE, st->batch.on);
-
- return r;
-}
-
-/**
- * reset_fifo_mpu3050() - Reset FIFO related registers
- * @indio_dev: Device driver instance.
- */
-static int reset_fifo_mpu3050(struct iio_dev *indio_dev)
-{
- struct inv_reg_map_s *reg;
- int result;
- u8 val, user_ctrl;
- struct inv_mpu_state *st = iio_priv(indio_dev);
- reg = &st->reg;
-
- /* disable interrupt */
- result = inv_i2c_single_write(st, reg->int_enable,
- st->plat_data.int_config);
- if (result)
- return result;
- /* disable the sensor output to FIFO */
- result = inv_i2c_single_write(st, reg->fifo_en, 0);
- if (result)
- goto reset_fifo_fail;
- result = inv_i2c_read(st, reg->user_ctrl, 1, &user_ctrl);
- if (result)
- goto reset_fifo_fail;
- /* disable fifo reading */
- user_ctrl &= ~BIT_FIFO_EN;
- st->chip_config.has_footer = 0;
- /* reset fifo */
- val = (BIT_3050_FIFO_RST | user_ctrl);
- result = inv_i2c_single_write(st, reg->user_ctrl, val);
- if (result)
- goto reset_fifo_fail;
- if (st->chip_config.dmp_on) {
- /* enable interrupt when DMP is done */
- result = inv_i2c_single_write(st, reg->int_enable,
- st->plat_data.int_config | BIT_DMP_INT_EN);
- if (result)
- return result;
-
- result = inv_i2c_single_write(st, reg->user_ctrl,
- BIT_FIFO_EN|user_ctrl);
- if (result)
- return result;
- } else {
- /* enable interrupt */
- if (st->sensor[SENSOR_ACCEL].on ||
- st->sensor[SENSOR_GYRO].on) {
- result = inv_i2c_single_write(st, reg->int_enable,
- st->plat_data.int_config | BIT_DATA_RDY_EN);
- if (result)
- return result;
- }
- /* enable FIFO reading and I2C master interface*/
- result = inv_i2c_single_write(st, reg->user_ctrl,
- BIT_FIFO_EN | user_ctrl);
- if (result)
- return result;
- /* enable sensor output to FIFO and FIFO footer*/
- val = 1;
- if (st->sensor[SENSOR_ACCEL].on)
- val |= BITS_3050_ACCEL_OUT;
- if (st->sensor[SENSOR_GYRO].on)
- val |= BITS_GYRO_OUT;
- result = inv_i2c_single_write(st, reg->fifo_en, val);
- if (result)
- return result;
- }
-
- return 0;
-reset_fifo_fail:
- if (st->chip_config.dmp_on)
- val = BIT_DMP_INT_EN;
- else
- val = BIT_DATA_RDY_EN;
- inv_i2c_single_write(st, reg->int_enable,
- st->plat_data.int_config | val);
- pr_err("reset fifo failed\n");
-
- return result;
-}
-
-/*
- * inv_set_lpf() - set low pass filer based on fifo rate.
- */
-static int inv_set_lpf(struct inv_mpu_state *st, int rate)
-{
- const short hz[] = {188, 98, 42, 20, 10, 5};
- const int d[] = {INV_FILTER_188HZ, INV_FILTER_98HZ,
- INV_FILTER_42HZ, INV_FILTER_20HZ,
- INV_FILTER_10HZ, INV_FILTER_5HZ};
- int i, h, data, result;
- struct inv_reg_map_s *reg;
-
- reg = &st->reg;
- h = (rate >> 1);
- i = 0;
- while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1))
- i++;
- data = d[i];
- if (INV_MPU3050 == st->chip_type) {
- if (st->slave_accel != NULL) {
- result = st->slave_accel->set_lpf(st, rate);
- if (result)
- return result;
- }
- result = inv_i2c_single_write(st, reg->lpf, data |
- (st->chip_config.fsr << GYRO_CONFIG_FSR_SHIFT));
- } else {
- result = inv_i2c_single_write(st, reg->lpf, data);
- }
- if (result)
- return result;
- st->chip_config.lpf = data;
-
- return 0;
-}
-
-/*
- * set_fifo_rate_reg() - Set fifo rate in hardware register
- */
-static int set_fifo_rate_reg(struct inv_mpu_state *st)
-{
- u8 data;
- u16 fifo_rate;
- int result;
- struct inv_reg_map_s *reg;
-
- reg = &st->reg;
- fifo_rate = st->chip_config.fifo_rate;
- data = ONE_K_HZ / fifo_rate - 1;
- result = inv_i2c_single_write(st, reg->sample_rate_div, data);
- if (result)
- return result;
- result = inv_set_lpf(st, fifo_rate);
-
- return result;
-}
-
-/*
- * inv_lpa_mode() - store current low power mode settings
- */
-static int inv_lpa_mode(struct inv_mpu_state *st, int lpa_mode)
-{
- unsigned long result;
- u8 d;
- struct inv_reg_map_s *reg;
-
- reg = &st->reg;
- result = inv_i2c_read(st, reg->pwr_mgmt_1, 1, &d);
- if (result)
- return result;
- if (lpa_mode)
- d |= BIT_CYCLE;
- else
- d &= ~BIT_CYCLE;
-
- result = inv_i2c_single_write(st, reg->pwr_mgmt_1, d);
- if (result)
- return result;
- if (INV_MPU6500 == st->chip_type) {
- d = BIT_FIFO_SIZE_1K;
- if (lpa_mode)
- d |= BIT_ACCEL_FCHOCIE_B;
- result = inv_i2c_single_write(st, REG_6500_ACCEL_CONFIG2, d);
- if (result)
- return result;
- }
-
- return 0;
-}
-
-static int inv_saturate_secondary_counter(struct inv_mpu_state *st)
-{
- int result;
- struct inv_reg_map_s *reg;
-
-#define COUNT_SATURATE_TIME_MS 32
- reg = &st->reg;
- /* set sampling to 1KHz */
- result = inv_i2c_single_write(st, reg->sample_rate_div, 0);
- if (result)
- return result;
- result = inv_i2c_single_write(st, REG_I2C_MST_DELAY_CTRL,
- BIT_SLV0_DLY_EN);
- if (result)
- return result;
- result = inv_i2c_single_write(st, REG_I2C_SLV4_CTRL, 0);
- if (result)
- return result;
- result = inv_i2c_single_write(st, reg->user_ctrl, BIT_I2C_MST_EN);
- if (result)
- return result;
- msleep(COUNT_SATURATE_TIME_MS);
-
- return 0;
-}
-static int inv_set_master_delay(struct inv_mpu_state *st)
-{
- int d, result, rate;
- u8 delay;
-
- if ((!st->sensor[SENSOR_COMPASS].on) &&
- (!st->sensor[SENSOR_PRESSURE].on))
- return 0;
-
- delay = 0;
- d = 0;
- if (st->sensor[SENSOR_COMPASS].on) {
- switch (st->plat_data.sec_slave_id) {
- case COMPASS_ID_AK8975:
- case COMPASS_ID_AK8972:
- case COMPASS_ID_AK8963:
- case COMPASS_ID_AK09911:
- delay = (BIT_SLV0_DLY_EN | BIT_SLV1_DLY_EN);
- break;
- case COMPASS_ID_MLX90399:
- delay = (BIT_SLV0_DLY_EN |
- BIT_SLV1_DLY_EN |
- BIT_SLV2_DLY_EN |
- BIT_SLV3_DLY_EN);
- break;
- default:
- return -EINVAL;
- }
- d = max(d, st->slave_compass->rate_scale);
- }
- if (st->sensor[SENSOR_PRESSURE].on) {
- /* read fake data when compass is disabled for DMP read */
- if ((!st->sensor[SENSOR_COMPASS].on) && st->chip_config.dmp_on)
- delay |= BIT_SLV0_DLY_EN;
- switch (st->plat_data.aux_slave_id) {
- case PRESSURE_ID_BMP280:
- delay |= (BIT_SLV2_DLY_EN | BIT_SLV3_DLY_EN);
- break;
- default:
- return -EINVAL;
- }
- d = max(d, st->slave_pressure->rate_scale);
- }
-
- d = d * st->chip_config.fifo_rate / ONE_K_HZ;
- if (st->chip_config.dmp_on) {
- rate = 0;
- if (st->sensor[SENSOR_PRESSURE].on)
- rate = max(rate, st->sensor[SENSOR_PRESSURE].rate);
- if (st->sensor[SENSOR_COMPASS].on)
- rate = max(rate, st->sensor[SENSOR_COMPASS].rate);
- if (rate == 0)
- return -EINVAL;
- d = max(d, st->chip_config.fifo_rate / rate);
- }
-
- if (d > 0)
- d -= 1;
- if (d > 0x1F)
- d = 0x1F;
-
- /* I2C_MST_DLY is set to slow down secondary I2C */
- if (0 == d)
- delay = 0;
- if (delay) {
- result = inv_saturate_secondary_counter(st);
- if (result)
- return result;
- }
- result = inv_i2c_single_write(st, REG_I2C_MST_DELAY_CTRL, delay);
- if (result)
- return result;
-
- return inv_i2c_single_write(st, REG_I2C_SLV4_CTRL, d);
-}
-
-/*
- * reset_fifo_itg() - Reset FIFO related registers.
- */
-static int reset_fifo_itg(struct iio_dev *indio_dev)
-{
- struct inv_reg_map_s *reg;
- int result, i;
- u8 val, int_word;
- struct inv_mpu_state *st = iio_priv(indio_dev);
-
- reg = &st->reg;
- if (st->chip_config.lpa_mode) {
- result = inv_lpa_mode(st, 0);
- if (result) {
- pr_err("reset lpa mode failed\n");
- return result;
- }
- }
- /* disable interrupt */
- result = inv_i2c_single_write(st, reg->int_enable, 0);
- if (result) {
- pr_err("int_enable write failed\n");
- return result;
- }
- /* disable the sensor output to FIFO */
- result = inv_i2c_single_write(st, reg->fifo_en, 0);
- if (result)
- goto reset_fifo_fail;
- /* disable fifo reading */
- result = inv_i2c_single_write(st, reg->user_ctrl, 0);
- if (result)
- goto reset_fifo_fail;
- int_word = 0;
-
- /* MPU6500's BIT_6500_WOM_EN is the same as BIT_MOT_EN */
- if (st->mot_int.mot_on)
- int_word |= BIT_MOT_EN;
-
- if (st->chip_config.dmp_on) {
- val = (BIT_FIFO_RST | BIT_DMP_RST);
- result = inv_i2c_single_write(st, reg->user_ctrl, val);
- if (result)
- goto reset_fifo_fail;
- if (st->chip_config.dmp_int_on) {
- int_word |= BIT_DMP_INT_EN;
- result = inv_i2c_single_write(st, reg->int_enable,
- int_word);
- if (result)
- return result;
- }
- val = (BIT_DMP_EN | BIT_FIFO_EN);
- if ((st->sensor[SENSOR_COMPASS].on ||
- st->sensor[SENSOR_PRESSURE].on) &&
- (!st->chip_config.dmp_event_int_on))
- val |= BIT_I2C_MST_EN;
- result = inv_i2c_single_write(st, reg->user_ctrl, val);
- if (result)
- goto reset_fifo_fail;
- } else {
- /* reset FIFO and possibly reset I2C*/
- val = BIT_FIFO_RST;
- result = inv_i2c_single_write(st, reg->user_ctrl, val);
- if (result)
- goto reset_fifo_fail;
- /* enable interrupt */
- if (st->sensor[SENSOR_ACCEL].on ||
- st->sensor[SENSOR_GYRO].on ||
- st->sensor[SENSOR_COMPASS].on ||
- st->sensor[SENSOR_PRESSURE].on)
- int_word |= BIT_DATA_RDY_EN;
-
- result = inv_i2c_single_write(st, reg->int_enable, int_word);
- if (result)
- return result;
- /* enable FIFO reading and I2C master interface*/
- val = BIT_FIFO_EN;
- if (st->sensor[SENSOR_COMPASS].on ||
- st->sensor[SENSOR_PRESSURE].on)
- val |= BIT_I2C_MST_EN;
- result = inv_i2c_single_write(st, reg->user_ctrl, val);
- if (result)
- goto reset_fifo_fail;
- /* enable sensor output to FIFO */
- val = 0;
- if (st->sensor[SENSOR_GYRO].on)
- val |= BITS_GYRO_OUT;
- if (st->sensor[SENSOR_ACCEL].on)
- val |= BIT_ACCEL_OUT;
- result = inv_i2c_single_write(st, reg->fifo_en, val);
- if (result)
- goto reset_fifo_fail;
- }
- st->last_ts = get_time_ns();
- st->prev_ts = st->last_ts;
- st->last_run_time = st->last_ts;
- if (st->sensor[SENSOR_COMPASS].on)
- st->slave_compass->prev_ts = st->last_ts;
- if (st->sensor[SENSOR_PRESSURE].on)
- st->slave_pressure->prev_ts = st->last_ts;
-
- st->dmp_interval = DMP_INTERVAL_INIT;
- st->ts_counter = 0;
- st->diff_accumulater = 0;
- st->dmp_interval_accum = 0;
- st->step_detector_base_ts = st->last_ts;
- st->chip_config.normal_compass_measure = 0;
- st->chip_config.normal_pressure_measure = 0;
- st->left_over_size = 0;
- for (i = 0; i < SENSOR_NUM_MAX; i++)
- st->sensor[i].ts = st->last_ts;
-
- result = inv_lpa_mode(st, st->chip_config.lpa_mode);
- if (result)
- goto reset_fifo_fail;
-
- return 0;
-
-reset_fifo_fail:
- if (st->chip_config.dmp_on)
- val = BIT_DMP_INT_EN;
- else
- val = BIT_DATA_RDY_EN;
- inv_i2c_single_write(st, reg->int_enable, val);
- pr_err("reset fifo failed\n");
-
- return result;
-}
-
-/**
- * inv_clear_kfifo() - clear time stamp fifo
- * @st: Device driver instance.
- */
-static void inv_clear_kfifo(struct inv_mpu_state *st)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&st->time_stamp_lock, flags);
- kfifo_reset(&st->timestamps);
- spin_unlock_irqrestore(&st->time_stamp_lock, flags);
-}
-
-/*
- * inv_reset_fifo() - Reset FIFO related registers.
- */
-int inv_reset_fifo(struct iio_dev *indio_dev)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
-
- inv_clear_kfifo(st);
- if (INV_MPU3050 == st->chip_type)
- return reset_fifo_mpu3050(indio_dev);
- else
- return reset_fifo_itg(indio_dev);
-}
-
-static int inv_send_gyro_data(struct inv_mpu_state *st, bool on)
-{
- u8 rn[] = {0xa3, 0xa3};
- u8 rf[] = {0xf4, 0x12};
- int result;
- u8 *r;
-
- if (on)
- r = rn;
- else
- r = rf;
- result = mem_w_key(KEY_CFG_OUT_GYRO, ARRAY_SIZE(rf), r);
-
- return result;
-}
-
-static int inv_send_accel_data(struct inv_mpu_state *st, bool on)
-{
- u8 rn[] = {0xa3, 0xa3};
- u8 rf[] = {0xf4, 0x12};
- int result;
- u8 *r;
-
- if (on)
- r = rn;
- else
- r = rf;
- result = mem_w_key(KEY_CFG_OUT_ACCL, ARRAY_SIZE(rf), r);
-
- return result;
-}
-
-static int inv_send_three_q_data(struct inv_mpu_state *st, bool on)
-{
- u8 rn[] = {0xa3, 0xa3};
- u8 rf[] = {0xf4, 0x13};
- int result;
- u8 *r;
-
- if (on)
- r = rn;
- else
- r = rf;
- result = mem_w_key(KEY_CFG_OUT_3QUAT, ARRAY_SIZE(rf), r);
-
- return result;
-}
-
-static int inv_send_six_q_data(struct inv_mpu_state *st, bool on)
-{
- u8 rn[] = {0xa3, 0xa3};
- u8 rf[] = {0xf4, 0x13};
- int result;
- u8 *r;
-
- if (on)
- r = rn;
- else
- r = rf;
- result = mem_w_key(KEY_CFG_OUT_6QUAT, ARRAY_SIZE(rf), r);
-
- return result;
-}
-
-static int inv_send_ped_q_data(struct inv_mpu_state *st, bool on)
-{
- u8 rn[] = {0xa3, 0xa3};
- u8 rf[] = {0xf4, 0x12};
- u8 *r;
- int result;
-
- if (on)
- r = rn;
- else
- r = rf;
- result = mem_w_key(KEY_CFG_OUT_PQUAT, ARRAY_SIZE(rn), r);
-
- return result;
-}
-
-static int inv_add_step_indicator(struct inv_mpu_state *st, bool on)
-{
- u8 rn[] = {0xf3, 0xf3};
- u8 rf[] = {0xf4, 0x03};
- int result;
- u8 *r;
-
- if (on)
- r = rn;
- else
- r = rf;
- result = mem_w_key(KEY_CFG_PEDSTEP_DET, ARRAY_SIZE(rn), r);
-
- return result;
-}
-
-static int inv_send_compass_dmp_data(struct inv_mpu_state *st, bool on)
-{
- u8 rn[] = {0xa3, 0xa3};
- u8 rf[] = {0xf4, 0x12};
- u8 *r;
- int result;
-
- if (on)
- r = rn;
- else
- r = rf;
- result = mem_w_key(KEY_CFG_OUT_CPASS, ARRAY_SIZE(rf), r);
-
- return result;
-}
-
-static int inv_send_pressure_dmp_data(struct inv_mpu_state *st, bool on)
-{
- u8 rn[] = {0xa3, 0xa3};
- u8 rf[] = {0xf4, 0x12};
- u8 *r;
- int result;
-
- if (on)
- r = rn;
- else
- r = rf;
- result = mem_w_key(KEY_CFG_OUT_PRESS, ARRAY_SIZE(rf), r);
-
- return result;
-}
-
-static int inv_send_step_detector(struct inv_mpu_state *st, bool on)
-{
- u8 rn[] = {0xa3, 0xa3};
- u8 rf[] = {0xf4, 0x0e};
- u8 *r;
- int result;
-
- if (on)
- r = rn;
- else
- r = rf;
- result = mem_w_key(KEY_CFG_OUT_STEPDET, ARRAY_SIZE(rf), r);
-
- return result;
-}
-
-static int inv_set_rate(struct inv_mpu_state *st, int k, int k_ct, int rate)
-{
- int v, result;
-
- v = MPU_DEFAULT_DMP_FREQ / rate - 1;
- result = inv_write_2bytes(st, k, v);
- if (result)
- return result;
- result = inv_write_2bytes(st, k_ct, 0);
-
- return result;
-}
-
-static int inv_set_gyro_rate(struct inv_mpu_state *st)
-{
- int result;
-
- result = inv_set_rate(st, KEY_CFG_GYRO_ODR, KEY_ODR_CNTR_GYRO,
- st->sensor[SENSOR_GYRO].rate);
-
- return result;
-}
-
-static int inv_set_accel_rate(struct inv_mpu_state *st)
-{
- int result;
-
- result = inv_set_rate(st, KEY_CFG_ACCL_ODR, KEY_ODR_CNTR_ACCL,
- st->sensor[SENSOR_ACCEL].rate);
-
- return result;
-}
-
-static int inv_set_compass_rate(struct inv_mpu_state *st)
-{
- int result;
-
- result = inv_set_rate(st, KEY_CFG_CPASS_ODR, KEY_ODR_CNTR_CPASS,
- st->sensor[SENSOR_COMPASS].rate);
-
- return result;
-}
-
-static int inv_set_pressure_rate(struct inv_mpu_state *st)
-{
- int result;
-
- result = inv_set_rate(st, KEY_CFG_PRESS_ODR, KEY_ODR_CNTR_PRESS,
- st->sensor[SENSOR_PRESSURE].rate);
-
- return result;
-}
-
-static int inv_set_step_detector(struct inv_mpu_state *st)
-{
- return 0;
-}
-
-
-static int inv_set_lpq_rate(struct inv_mpu_state *st)
-{
- int result;
-
- result = inv_set_rate(st, KEY_CFG_3QUAT_ODR, KEY_ODR_CNTR_3QUAT,
- st->sensor[SENSOR_LPQ].rate);
-
- return result;
-}
-
-static int inv_set_sixq_rate(struct inv_mpu_state *st)
-{
- int result;
-
- result = inv_set_rate(st, KEY_CFG_6QUAT_ODR, KEY_ODR_CNTR_6QUAT,
- st->sensor[SENSOR_SIXQ].rate);
-
- return result;
-}
-
-static int inv_set_pedq_rate(struct inv_mpu_state *st)
-{
- int result;
-
- result = inv_set_rate(st, KEY_CFG_PQUAT6_ODR, KEY_ODR_CNTR_PQUAT,
- st->sensor[SENSOR_PEDQ].rate);
-
- return result;
-}
-
-
-static int inv_set_dmp_sysfs(struct inv_mpu_state *st)
-{
- int result, i, s;
- u8 d[] = {0, 0, 0, 0};
-
- result = inv_set_interrupt_on_gesture_event(st,
- st->chip_config.dmp_event_int_on);
- if (result)
- return result;
-
- if (st->chip_config.dmp_event_int_on) {
- for (i = 0; i < SENSOR_NUM_MAX; i++) {
- result = st->sensor[i].send_data(st, false);
- if (result)
- return result;
- }
- } else {
- s = 0;
- st->batch.min_rate = MAX_DMP_OUTPUT_RATE;
- for (i = 0; i < SENSOR_NUM_MAX; i++) {
- result = st->sensor[i].send_data(st, st->sensor[i].on);
- if (result)
- return result;
- if (st->sensor[i].on) {
- if (0 == st->sensor[i].rate)
- return -EINVAL;
- if (st->sensor[i].rate < st->batch.min_rate)
- st->batch.min_rate = st->sensor[i].rate;
- s += st->sensor[i].rate *
- st->sensor[i].sample_size;
-
- result = st->sensor[i].set_rate(st);
- if (result)
- return result;
- st->sensor[i].counter = MPU_DEFAULT_DMP_FREQ /
- st->sensor[i].rate;
- }
- }
- st->bytes_per_sec = s;
- if (st->sensor[SENSOR_STEP].on)
- result = inv_add_step_indicator(st, true);
- else
- result = inv_add_step_indicator(st,
- st->chip_config.step_indicator_on);
- if (result)
- return result;
- }
- result = inv_batchmode_setup(st);
- if (result)
- return result;
-
- st->dmp_counter = 0;
- result = mem_w_key(KEY_DMP_RUN_CNTR, ARRAY_SIZE(d), d);
- if (result)
- return result;
- result = mem_w_key(KEY_D_STPDET_TIMESTAMP, ARRAY_SIZE(d), d);
-
- return result;
-}
-
-static void inv_get_data_count(struct inv_mpu_state *st)
-{
- struct inv_chip_config_s *c;
- int b, i;
-
- c = &st->chip_config;
- b = 0;
- if (st->chip_config.dmp_on) {
- for (i = 0; i < SENSOR_NUM_MAX; i++) {
- if (st->sensor[i].on)
- b += st->sensor[i].sample_size;
- }
- } else {
- if (st->sensor[SENSOR_ACCEL].on)
- b += BYTES_PER_SENSOR;
- if (st->sensor[SENSOR_GYRO].on)
- b += BYTES_PER_SENSOR;
- }
- c->bytes_per_datum = b;
-
- return;
-}
-/*
- * set_inv_enable() - main enable/disable function.
- */
-int set_inv_enable(struct iio_dev *indio_dev, bool enable)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct inv_reg_map_s *reg;
- u8 data[2];
- int result;
-
- reg = &st->reg;
- if (enable) {
- if (st->chip_config.dmp_on &&
- (!st->chip_config.firmware_loaded))
- return -EINVAL;
- st->batch.on = false;
-
- inv_get_data_count(st);
- result = inv_set_master_delay(st);
- if (result)
- return result;
-
- result = set_fifo_rate_reg(st);
- if (result)
- return result;
- if (st->chip_config.dmp_on) {
- result = inv_set_dmp_sysfs(st);
- if (result)
- return result;
- }
-
- if (st->chip_config.gyro_enable) {
- result = st->switch_gyro_engine(st, true);
- if (result)
- return result;
- }
- if (st->chip_config.accel_enable) {
- result = st->switch_accel_engine(st, true);
- if (result)
- return result;
- }
- if (st->sensor[SENSOR_COMPASS].on) {
- result = st->slave_compass->resume(st);
- if (result)
- return result;
- }
- if (st->sensor[SENSOR_PRESSURE].on) {
- result = st->slave_pressure->resume(st);
- if (result)
- return result;
- }
- result = inv_reset_fifo(indio_dev);
- if (result)
- return result;
- } else {
- if ((INV_MPU3050 != st->chip_type)
- && st->chip_config.lpa_mode) {
- /* if the chip is in low power mode,
- register write/read could fail */
- result = inv_lpa_mode(st, 0);
- if (result)
- return result;
- }
- result = inv_i2c_single_write(st, reg->fifo_en, 0);
- if (result)
- return result;
- if (st->chip_config.dmp_on) {
- result = inv_read_time_and_ticks(st, false);
- if (result)
- return result;
- result = inv_i2c_read(st, reg->fifo_count_h,
- FIFO_COUNT_BYTE, data);
- if (result)
- return result;
- st->fifo_count = be16_to_cpup((__be16 *)(data));
- if (st->fifo_count) {
- result = inv_process_batchmode(st);
- if (result)
- return result;
- }
- }
- inv_push_marker_to_buffer(st, END_MARKER);
- /* disable fifo reading */
- if (INV_MPU3050 != st->chip_type) {
- result = inv_i2c_single_write(st, reg->int_enable, 0);
- if (result)
- return result;
- result = inv_i2c_single_write(st, reg->user_ctrl, 0);
- } else {
- result = inv_i2c_single_write(st, reg->int_enable,
- st->plat_data.int_config);
- }
- if (result)
- return result;
- /* turn off the gyro/accel engine during disable phase */
- result = st->switch_gyro_engine(st, false);
- if (result)
- return result;
- result = st->switch_accel_engine(st, false);
- if (result)
- return result;
- if (st->sensor[SENSOR_COMPASS].on) {
- result = st->slave_compass->suspend(st);
- if (result)
- return result;
- }
- if (st->sensor[SENSOR_PRESSURE].on) {
- result = st->slave_pressure->suspend(st);
- if (result)
- return result;
- }
- }
- st->chip_config.enable = enable;
-
- return 0;
-}
-
-/*
- * inv_irq_handler() - Cache a timestamp at each data ready interrupt.
- */
-static irqreturn_t inv_irq_handler(int irq, void *dev_id)
-{
- struct inv_mpu_state *st = (struct inv_mpu_state *)dev_id;
- u64 ts;
-
- if (!st->chip_config.dmp_on) {
- ts = get_time_ns();
- kfifo_in_spinlocked(&st->timestamps, &ts, 1,
- &st->time_stamp_lock);
- }
-
- return IRQ_WAKE_THREAD;
-}
-
-static void inv_report_data_3050(struct iio_dev *indio_dev, s64 t,
- int has_footer, u8 *data)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
- int ind, i;
- short s[THREE_AXIS];
-
- ind = 0;
- if (has_footer)
- ind += 2;
-
- if (st->sensor[SENSOR_GYRO].on) {
- for (i = 0; i < 3; i++)
- s[i] = be16_to_cpup((__be16 *)(&data[ind + i * 2]));
-
- inv_push_8bytes_buffer(st, GYRO_HDR, t, s);
- ind += BYTES_PER_SENSOR;
- }
- if (st->sensor[SENSOR_ACCEL].on) {
- st->slave_accel->combine_data(&data[ind], s);
- inv_push_8bytes_buffer(st, ACCEL_HDR, t, s);
- }
-}
-
-/*
- * inv_read_fifo_mpu3050() - Transfer data from FIFO to ring buffer for
- * mpu3050.
- */
-irqreturn_t inv_read_fifo_mpu3050(int irq, void *dev_id)
-{
-
- struct inv_mpu_state *st = (struct inv_mpu_state *)dev_id;
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- int bytes_per_datum;
- u8 data[64];
- int result;
- short fifo_count, byte_read;
- s64 timestamp;
- struct inv_reg_map_s *reg;
-
- reg = &st->reg;
- mutex_lock(&st->suspend_resume_lock);
- mutex_lock(&indio_dev->mlock);
- if (st->chip_config.dmp_on)
- bytes_per_datum = HEADERED_NORMAL_BYTES;
- else
- bytes_per_datum = (st->sensor[SENSOR_ACCEL].on +
- st->sensor[SENSOR_GYRO].on) * BYTES_PER_SENSOR;
- if (st->chip_config.has_footer)
- byte_read = bytes_per_datum + MPU3050_FOOTER_SIZE;
- else
- byte_read = bytes_per_datum;
-
- fifo_count = 0;
- if (byte_read != 0) {
- result = inv_i2c_read(st, reg->fifo_count_h,
- FIFO_COUNT_BYTE, data);
- if (result)
- goto end_session;
- fifo_count = be16_to_cpup((__be16 *)(&data[0]));
- if (fifo_count < byte_read)
- goto end_session;
- if (fifo_count & 1)
- goto flush_fifo;
- if (fifo_count > FIFO_THRESHOLD)
- goto flush_fifo;
- /* Timestamp mismatch. */
- if (kfifo_len(&st->timestamps) <
- fifo_count / byte_read)
- goto flush_fifo;
- if (kfifo_len(&st->timestamps) >
- fifo_count / byte_read + TIME_STAMP_TOR) {
- if (st->chip_config.dmp_on) {
- result = kfifo_out(&st->timestamps,
- &timestamp, 1);
- if (result != 1)
- goto flush_fifo;
- } else {
- goto flush_fifo;
- }
- }
- }
- while ((bytes_per_datum != 0) && (fifo_count >= byte_read)) {
- result = inv_i2c_read(st, reg->fifo_r_w, byte_read, data);
- if (result)
- goto flush_fifo;
-
- result = kfifo_out(&st->timestamps, &timestamp, 1);
- if (result != 1)
- goto flush_fifo;
- inv_report_data_3050(indio_dev, timestamp,
- st->chip_config.has_footer, data);
- fifo_count -= byte_read;
- if (st->chip_config.has_footer == 0) {
- st->chip_config.has_footer = 1;
- byte_read = bytes_per_datum + MPU3050_FOOTER_SIZE;
- }
- }
-
-end_session:
- mutex_unlock(&indio_dev->mlock);
- mutex_unlock(&st->suspend_resume_lock);
-
- return IRQ_HANDLED;
-
-flush_fifo:
- /* Flush HW and SW FIFOs. */
- inv_reset_fifo(indio_dev);
- inv_clear_kfifo(st);
- mutex_unlock(&indio_dev->mlock);
- mutex_unlock(&st->suspend_resume_lock);
-
- return IRQ_HANDLED;
-}
-
-static int inv_report_gyro_accel(struct iio_dev *indio_dev,
- u8 *data, s64 t)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
- short s[THREE_AXIS];
- int ind;
- int i;
-
- ind = 0;
- if (st->sensor[SENSOR_ACCEL].on) {
- for (i = 0; i < 3; i++)
- s[i] = be16_to_cpup((__be16 *)(&data[ind + i * 2]));
- inv_push_8bytes_buffer(st, ACCEL_HDR, t, s);
- ind += BYTES_PER_SENSOR;
- }
-
- if (st->sensor[SENSOR_GYRO].on) {
- for (i = 0; i < 3; i++)
- s[i] = be16_to_cpup((__be16 *)(&data[ind + i * 2]));
- inv_push_8bytes_buffer(st, GYRO_HDR, t, s);
- ind += BYTES_PER_SENSOR;
- }
-
- return 0;
-}
-
-static void inv_process_motion(struct inv_mpu_state *st)
-{
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- int result;
- u8 data[1];
-
- /* motion interrupt */
- result = inv_i2c_read(st, REG_INT_STATUS, 1, data);
- if (result)
- return;
-
- if (data[0] & BIT_MOT_INT)
- sysfs_notify(&indio_dev->dev.kobj, NULL, "event_accel_motion");
-}
-
-static int inv_get_timestamp(struct inv_mpu_state *st, int count)
-{
- u32 *dur;
- u32 thresh;
- s32 diff, result, counter;
- u64 ts;
-
- /* goal of algorithm is to estimate the true frequency of the chip */
- if (st->chip_config.dmp_on && st->chip_config.dmp_event_int_on)
- return 0;
- dur = &st->irq_dur_ns;
- counter = 1;
- thresh = min((u32)((*dur) >> 2), (u32)(10 * NSEC_PER_MSEC));
- while (kfifo_len(&st->timestamps) >= count) {
- result = kfifo_out(&st->timestamps, &ts, 1);
- if (result != 1)
- return -EINVAL;
- /* first time since reset fifo, just take it */
- if (!st->ts_counter) {
- st->last_ts = ts;
- st->prev_ts = ts;
- st->ts_counter++;
- return 0;
- }
- diff = (s32)(ts - st->prev_ts);
- st->prev_ts = ts;
- if (abs(diff - (*dur)) < thresh) {
- st->diff_accumulater >>= 1;
- if (*dur > diff)
- st->diff_accumulater -= (((*dur) - diff) >> 7);
- else
- st->diff_accumulater += ((diff - (*dur)) >> 7);
- *dur += st->diff_accumulater;
- }
- }
- ts = *dur;
- ts *= counter;
- st->last_ts += ts;
-
- return 0;
-}
-
-static int inv_process_dmp_interrupt(struct inv_mpu_state *st)
-{
- int r;
- u8 d[1];
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
-
-#define DMP_INT_SMD 0x04
-#define DMP_INT_PED 0x08
-
- if ((!st->chip_config.smd_enable) &&
- (!st->ped.int_on) &&
- (!st->tap.on))
- return 0;
-
- r = inv_i2c_read(st, REG_DMP_INT_STATUS, 1, d);
- if (r)
- return r;
- if (d[0] & DMP_INT_SMD) {
- sysfs_notify(&indio_dev->dev.kobj, NULL, "event_smd");
- st->chip_config.smd_enable = false;
- st->chip_config.smd_triggered = true;
- }
- if (d[0] & DMP_INT_PED)
- sysfs_notify(&indio_dev->dev.kobj, NULL, "event_pedometer");
-
- return 0;
-}
-
-static int inv_get_shift2(int count)
-{
- int i;
-
- if (1 == count)
- return 13;
- if (count > 2000)
- return 2;
- i = 13;
- while (count > 0) {
- count >>= 1;
- i--;
- }
-
- return i;
-}
-
-static void inv_adjust_sensor_ts(struct inv_mpu_state *st, int sensor_ind)
-{
- s64 diff;
- int i, rate_adj, s3, delta, total_count;
-
- if (!st->chip_config.adjust_time)
- return;
-#define MAX_DIFF 0x7fffffff
- total_count = st->dmp_ticks;
- if (0 == total_count)
- total_count = 1;
-
- diff = (st->last_ts - st->prev_ts) - (u64)(st->dmp_interval) *
- total_count;
- if (diff > MAX_DIFF)
- diff = MAX_DIFF;
- if (diff < -MAX_DIFF)
- diff = -MAX_DIFF;
- s3 = 4;
- rate_adj = (int)diff;
- rate_adj /= total_count;
- delta = min(abs(rate_adj) >> inv_get_shift2(total_count),
- DMP_INTERVAL_MIN_ADJ);
- if (rate_adj < 0)
- delta = -delta;
- st->dmp_interval_accum >>= 1;
- st->dmp_interval_accum += delta;
- st->dmp_interval += st->dmp_interval_accum;
- for (i = 0; i < SENSOR_NUM_MAX; i++)
- if (st->sensor[i].on)
- st->sensor[i].dur = st->dmp_interval *
- st->sensor[i].counter;
-
- st->prev_ts = st->last_ts;
-}
-
-static void inv_reset_ts(struct inv_mpu_state *st, u64 curr_ts)
-{
- u32 dur, i;
-
- dur = USEC_PER_SEC / st->bytes_per_sec;
- dur *= 1024;
- curr_ts -= ((u64)dur * NSEC_PER_USEC);
- for (i = 0; i < SENSOR_NUM_MAX; i++)
- st->sensor[i].ts = curr_ts;
-}
-
-static void inv_push_step_indicator(struct inv_mpu_state *st, int sensor_ind,
- int steps)
-{
- int dur, i;
- s16 sen[3];
- u64 base;
-#define STEP_INDICATOR_HEADER 0x0001
-
- dur = st->sensor[sensor_ind].dur / steps;
- base = st->sensor[sensor_ind].ts;
-
- for (i = 1; i < steps; i++)
- inv_push_8bytes_buffer(st, STEP_INDICATOR_HEADER,
- base + i * dur, sen);
-}
-
-static int inv_parse_header(u16 hdr)
-{
- switch (hdr) {
- case ACCEL_HDR:
- return SENSOR_ACCEL;
- case GYRO_HDR:
- return SENSOR_GYRO;
- case PEDQUAT_HDR:
- return SENSOR_PEDQ;
- case LPQUAT_HDR:
- return SENSOR_LPQ;
- case SIXQUAT_HDR:
- return SENSOR_SIXQ;
- case COMPASS_HDR:
- case COMPASS_HDR_2:
- return SENSOR_COMPASS;
- case PRESSURE_HDR:
- return SENSOR_PRESSURE;
- case STEP_DETECTOR_HDR:
- return SENSOR_STEP;
- default:
- return SENSOR_INVALID;
- }
-}
-#define FEATURE_IKR_PANIC 1
-
-static int inv_process_batchmode(struct inv_mpu_state *st)
-{
- int i, target_bytes, tmp, res, counter;
- int sensor_ind, q[3];
- u8 *dptr, *d;
- u16 hdr, steps;
- s16 sen[3];
- u64 t;
- bool done_flag;
-
-#if FEATURE_IKR_PANIC
- if (1024 <= st->fifo_count) {
- if (1024 < st->fifo_count) {
- pr_err("fifo_count over spec\n");
- return 0;
- }
- inv_reset_ts(st, st->last_ts);
- st->left_over_size = 0;
- }
-#else
- if (1024 == st->fifo_count) {
- inv_reset_ts(st, st->last_ts);
- st->left_over_size = 0;
- }
-#endif
-
- d = fifo_data;
- if (st->left_over_size > 0) {
-#if FEATURE_IKR_PANIC
- if (st->left_over_size > HEADERED_Q_BYTES) {
- pr_err("left_over_size overflow 1\n");
- st->left_over_size = HEADERED_Q_BYTES;
- }
-#endif
- dptr = d + st->left_over_size;
- memcpy(d, st->left_over, st->left_over_size);
- } else {
- dptr = d;
- }
- target_bytes = st->fifo_count;
- while (target_bytes > 0) {
- if (target_bytes < MAX_READ_SIZE)
- tmp = target_bytes;
- else
- tmp = MAX_READ_SIZE;
- res = inv_i2c_read(st, st->reg.fifo_r_w, tmp, dptr);
- if (res < 0)
- return res;
- dptr += tmp;
- target_bytes -= tmp;
- }
- dptr = d;
- done_flag = false;
- target_bytes = st->fifo_count + st->left_over_size;
- counter = 0;
- while ((dptr - d <= target_bytes - HEADERED_NORMAL_BYTES) &&
- (!done_flag)) {
- hdr = (u16)be16_to_cpup((__be16 *)(dptr));
- steps = (hdr & STEP_INDICATOR_MASK);
- hdr &= (~STEP_INDICATOR_MASK);
- sensor_ind = inv_parse_header(hdr);
- /* error packet */
- if ((sensor_ind == SENSOR_INVALID) ||
- (!st->sensor[sensor_ind].on)) {
- dptr += HEADERED_NORMAL_BYTES;
- continue;
- }
- /* incomplete packet */
- if (target_bytes - (dptr - d) <
- st->sensor[sensor_ind].sample_size) {
- done_flag = true;
- continue;
- }
- if (sensor_ind == SENSOR_STEP) {
- tmp = (int)be32_to_cpup((__be32 *)(dptr + 4));
- t = st->step_detector_base_ts +
- (u64)tmp * 5 * NSEC_PER_MSEC;
- inv_push_8bytes_buffer(st, hdr, t, sen);
- dptr += HEADERED_NORMAL_BYTES;
- continue;
- }
- if (steps > 1)
- inv_push_step_indicator(st, sensor_ind, steps);
- st->sensor[sensor_ind].ts += (u64)st->sensor[sensor_ind].dur;
- t = st->sensor[sensor_ind].ts;
- if (sensor_ind == SENSOR_COMPASS) {
- if (!st->chip_config.normal_compass_measure) {
- st->chip_config.normal_compass_measure = 1;
- } else if (COMPASS_HDR == hdr) {
- for (i = 0; i < 6; i++)
- st->fifo_data[i] = dptr[i + 2];
- res = st->slave_compass->read_data(st, sen);
- if (!res)
- inv_push_8bytes_buffer(st, hdr |
- (!!steps), t, sen);
- } else if (COMPASS_HDR_2 == hdr) {
- inv_push_marker_to_buffer(st, hdr);
- }
- dptr += HEADERED_NORMAL_BYTES;
- continue;
- }
- if (sensor_ind == SENSOR_PRESSURE) {
- if (!st->chip_config.normal_pressure_measure) {
- st->chip_config.normal_pressure_measure = 1;
- } else {
- for (i = 0; i < 6; i++)
- st->fifo_data[i] = dptr[i + 2];
- res = st->slave_pressure->read_data(st, sen);
- if (!res)
- inv_push_8bytes_buffer(st, hdr |
- (!!steps), t, sen);
- }
- dptr += HEADERED_NORMAL_BYTES;
- continue;
- }
- if (st->sensor[sensor_ind].sample_size == HEADERED_Q_BYTES) {
- for (i = 0; i < 3; i++)
- q[i] = (int)be32_to_cpup((__be32 *)(dptr + 4
- + i * 4));
- inv_push_16bytes_buffer(st, hdr | (!!steps), t, q);
- } else {
- for (i = 0; i < 3; i++)
- sen[i] = (short)be16_to_cpup((__be16 *)(dptr +
- 2 + i * 2));
- inv_push_8bytes_buffer(st, hdr | (!!steps), t, sen);
- }
- dptr += st->sensor[sensor_ind].sample_size;
- }
- inv_adjust_sensor_ts(st, sensor_ind);
- st->left_over_size = target_bytes - (dptr - d);
-
- if (st->left_over_size) {
-#if FEATURE_IKR_PANIC
- if (st->left_over_size > HEADERED_Q_BYTES) {
- pr_err("left_over_size overflow 2\n");
- st->left_over_size = HEADERED_Q_BYTES;
- }
-#endif
- memcpy(st->left_over, dptr, st->left_over_size);
- }
-
- return 0;
-}
-
-int inv_read_time_and_ticks(struct inv_mpu_state *st, bool resume)
-{
- int result;
- u32 counter;
- u8 data[4];
-
-#define MIN_TICK_READING_TIME NSEC_PER_SEC
- st->last_ts = get_time_ns();
- if ((st->last_ts - st->prev_ts < MIN_TICK_READING_TIME) &&
- (!resume)) {
- st->chip_config.adjust_time = false;
- return 0;
- }
- result = mpu_memory_read(st, st->i2c_addr,
- inv_dmp_get_address(KEY_DMP_RUN_CNTR), 4, data);
- if (result)
- return result;
-
- counter = be32_to_cpup((__be32 *)(data));
- if (resume) {
- st->dmp_counter = counter;
- st->prev_ts = st->last_ts;
-
- return 0;
- }
- if (counter > st->dmp_counter)
- st->dmp_ticks = counter - st->dmp_counter;
- else
- st->dmp_ticks = 0xffffffff - st->dmp_counter + counter + 1;
- st->dmp_counter = counter;
- st->chip_config.adjust_time = true;
-
- return 0;
-}
-
-/*
- * inv_read_fifo() - Transfer data from FIFO to ring buffer.
- */
-irqreturn_t inv_read_fifo(int irq, void *dev_id)
-{
-
- struct inv_mpu_state *st = (struct inv_mpu_state *)dev_id;
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- int result, bpm;
- u8 data[MAX_HW_FIFO_BYTES];
- u16 fifo_count;
- struct inv_reg_map_s *reg;
- u64 pts1;
-
-#define DMP_MIN_RUN_TIME (37 * NSEC_PER_MSEC)
- if (st->suspend_state)
- return IRQ_HANDLED;
- mutex_lock(&indio_dev->mlock);
- if (st->chip_config.dmp_on) {
- pts1 = get_time_ns();
- result = inv_process_dmp_interrupt(st);
- if (result || st->chip_config.dmp_event_int_on)
- goto end_session;
- if (!st->chip_config.smd_triggered) {
- if (pts1 - st->last_run_time < DMP_MIN_RUN_TIME)
- goto end_session;
- else
- st->last_run_time = pts1;
- } else {
- st->chip_config.smd_triggered = false;
- }
- }
-
- if (!(iio_buffer_enabled(indio_dev)) || (!st->chip_config.enable))
- goto end_session;
-
- reg = &st->reg;
- if (!(st->sensor[SENSOR_ACCEL].on |
- st->sensor[SENSOR_GYRO].on |
- st->sensor[SENSOR_COMPASS].on |
- st->sensor[SENSOR_PRESSURE].on |
- st->chip_config.dmp_on |
- st->mot_int.mot_on))
- goto end_session;
- if (st->chip_config.lpa_mode) {
- result = inv_i2c_read(st, reg->raw_accel,
- BYTES_PER_SENSOR, data);
- if (result)
- goto end_session;
- inv_report_gyro_accel(indio_dev, data, get_time_ns());
- if (st->mot_int.mot_on)
- inv_process_motion(st);
-
- goto end_session;
- }
-
- if (st->chip_config.dmp_on) {
- result = inv_read_time_and_ticks(st, false);
- if (result)
- goto end_session;
- }
- bpm = st->chip_config.bytes_per_datum;
- fifo_count = 0;
- if (bpm) {
- result = inv_i2c_read(st, reg->fifo_count_h, FIFO_COUNT_BYTE,
- data);
- if (result)
- goto end_session;
- fifo_count = be16_to_cpup((__be16 *)(data));
- /* fifo count can't be odd number */
- if (fifo_count & 1)
- goto flush_fifo;
- if (fifo_count == 0)
- goto end_session;
- st->fifo_count = fifo_count;
- }
-
- if (st->chip_config.dmp_on) {
- result = inv_process_batchmode(st);
- } else {
- if (fifo_count > FIFO_THRESHOLD)
- goto flush_fifo;
- if (bpm) {
- while (fifo_count >= bpm) {
- result = inv_i2c_read(st, reg->fifo_r_w, bpm,
- data);
- if (result)
- goto flush_fifo;
- result = inv_get_timestamp(st,
- fifo_count / bpm);
- if (result)
- goto flush_fifo;
- inv_report_gyro_accel(indio_dev, data,
- st->last_ts);
- fifo_count -= bpm;
- }
- } else {
- result = inv_get_timestamp(st, 1);
- if (result)
- goto flush_fifo;
- }
- inv_send_compass_data(st);
- inv_send_pressure_data(st);
- }
-end_session:
- mutex_unlock(&indio_dev->mlock);
-
- return IRQ_HANDLED;
-flush_fifo:
- /* Flush HW and SW FIFOs. */
- inv_reset_fifo(indio_dev);
- inv_clear_kfifo(st);
- mutex_unlock(&indio_dev->mlock);
-
- return IRQ_HANDLED;
-}
-
-void inv_mpu_unconfigure_ring(struct iio_dev *indio_dev)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
- free_irq(st->client->irq, st);
- iio_kfifo_free(indio_dev->buffer);
-};
-
-static int inv_predisable(struct iio_dev *indio_dev)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
- int result;
-
- if (st->chip_config.enable) {
- result = set_inv_enable(indio_dev, false);
- if (result)
- return result;
- result = st->set_power_state(st, false);
- if (result)
- return result;
- }
-
- return 0;
-}
-
-static int inv_check_conflict_sysfs(struct iio_dev *indio_dev)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
-
- if (st->chip_config.lpa_mode) {
- /* dmp cannot run with low power mode on */
- st->chip_config.dmp_on = 0;
- st->chip_config.gyro_enable = false;
- st->sensor[SENSOR_GYRO].on = false;
- st->sensor[SENSOR_COMPASS].on = false;
- }
- if (st->sensor[SENSOR_GYRO].on &&
- (!st->chip_config.gyro_enable)) {
- st->chip_config.gyro_enable = true;
- }
- if (st->sensor[SENSOR_ACCEL].on &&
- (!st->chip_config.accel_enable)) {
- st->chip_config.accel_enable = true;
- }
-
- return 0;
-}
-
-static int inv_preenable(struct iio_dev *indio_dev)
-{
- int result;
-
- result = inv_check_conflict_sysfs(indio_dev);
- if (result)
- return result;
- result = iio_sw_buffer_preenable(indio_dev);
-
- return result;
-}
-
-void inv_init_sensor_struct(struct inv_mpu_state *st)
-{
- int i;
-
- for (i = 0; i < SENSOR_NUM_MAX; i++) {
- if (i < SENSOR_SIXQ)
- st->sensor[i].sample_size =
- HEADERED_NORMAL_BYTES;
- else
- st->sensor[i].sample_size = HEADERED_Q_BYTES;
- if (i == SENSOR_STEP) {
- st->sensor[i].rate = 1;
- st->sensor[i].dur = NSEC_PER_SEC;
- } else {
- st->sensor[i].rate = INIT_DMP_OUTPUT_RATE;
- st->sensor[i].dur = NSEC_PER_SEC /
- INIT_DMP_OUTPUT_RATE;
- }
- }
-
- st->sensor[SENSOR_ACCEL].send_data = inv_send_accel_data;
- st->sensor[SENSOR_GYRO].send_data = inv_send_gyro_data;
- st->sensor[SENSOR_COMPASS].send_data = inv_send_compass_dmp_data;
- st->sensor[SENSOR_PRESSURE].send_data = inv_send_pressure_dmp_data;
- st->sensor[SENSOR_STEP].send_data = inv_send_step_detector;
- st->sensor[SENSOR_PEDQ].send_data = inv_send_ped_q_data;
- st->sensor[SENSOR_SIXQ].send_data = inv_send_six_q_data;
- st->sensor[SENSOR_LPQ].send_data = inv_send_three_q_data;
-
- st->sensor[SENSOR_ACCEL].set_rate = inv_set_accel_rate;
- st->sensor[SENSOR_GYRO].set_rate = inv_set_gyro_rate;
- st->sensor[SENSOR_COMPASS].set_rate = inv_set_compass_rate;
- st->sensor[SENSOR_PRESSURE].set_rate = inv_set_pressure_rate;
- st->sensor[SENSOR_STEP].set_rate = inv_set_step_detector;
- st->sensor[SENSOR_PEDQ].set_rate = inv_set_pedq_rate;
- st->sensor[SENSOR_SIXQ].set_rate = inv_set_sixq_rate;
- st->sensor[SENSOR_LPQ].set_rate = inv_set_lpq_rate;
-}
-
-int inv_flush_batch_data(struct iio_dev *indio_dev, bool *has_data)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct inv_reg_map_s *reg;
- u8 data[FIFO_COUNT_BYTE];
- int result;
-
- reg = &st->reg;
- if (!(iio_buffer_enabled(indio_dev)) || (!st->chip_config.enable))
- return -EINVAL;
-
- if (st->batch.on) {
- result = inv_read_time_and_ticks(st, false);
- if (result)
- return result;
- result = inv_i2c_read(st, reg->fifo_count_h,
- FIFO_COUNT_BYTE, data);
- if (result)
- return result;
- st->fifo_count = be16_to_cpup((__be16 *)(data));
- if (st->fifo_count) {
- result = inv_process_batchmode(st);
- if (result)
- return result;
- *has_data = !!st->fifo_count;
- inv_push_marker_to_buffer(st, END_MARKER);
- result = write_be32_key_to_mem(st, 0,
- KEY_BM_BATCH_CNTR);
- return result;
- }
- }
- inv_push_marker_to_buffer(st, EMPTY_MARKER);
-
- return 0;
-}
-
-static const struct iio_buffer_setup_ops inv_mpu_ring_setup_ops = {
- .preenable = &inv_preenable,
- .predisable = &inv_predisable,
-};
-
-int inv_mpu_configure_ring(struct iio_dev *indio_dev)
-{
- int ret;
- struct inv_mpu_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring;
-
- ring = iio_kfifo_allocate(indio_dev);
- if (!ring)
- return -ENOMEM;
- indio_dev->buffer = ring;
- /* setup ring buffer */
- ring->scan_timestamp = true;
- indio_dev->setup_ops = &inv_mpu_ring_setup_ops;
- /*scan count double count timestamp. should subtract 1. but
- number of channels still includes timestamp*/
- if (INV_MPU3050 == st->chip_type)
- ret = request_threaded_irq(st->client->irq, inv_irq_handler,
- inv_read_fifo_mpu3050,
- IRQF_TRIGGER_RISING | IRQF_SHARED, "inv_irq", st);
- else
- ret = request_threaded_irq(st->client->irq, inv_irq_handler,
- inv_read_fifo,
- IRQF_TRIGGER_RISING | IRQF_SHARED, "inv_irq", st);
- if (ret)
- goto error_iio_sw_rb_free;
-
- indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-
- return 0;
-error_iio_sw_rb_free:
- iio_kfifo_free(indio_dev->buffer);
-
- return ret;
-}
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_trigger.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_trigger.c
deleted file mode 100755
index ad67c089cc3..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_mpu_trigger.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "iio.h"
-#include "sysfs.h"
-#include "trigger.h"
-
-#include "inv_mpu_iio.h"
-
-/*
- * inv_mpu_data_rdy_trigger_set_state() set data ready interrupt state
- */
-static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
- bool state)
-{
- return 0;
-}
-
-static const struct iio_trigger_ops inv_mpu_trigger_ops = {
- .owner = THIS_MODULE,
- .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state,
-};
-
-int inv_mpu_probe_trigger(struct iio_dev *indio_dev)
-{
- int ret;
- struct inv_mpu_state *st = iio_priv(indio_dev);
-
-#ifdef CONFIG_INV_KERNEL_3_10
- st->trig = iio_trigger_alloc("%s-dev%d",
-#else
- st->trig = iio_allocate_trigger("%s-dev%d",
-#endif
- indio_dev->name,
- indio_dev->id);
- if (st->trig == NULL)
- return -ENOMEM;
- st->trig->dev.parent = &st->client->dev;
-#ifndef CONFIG_INV_KERNEL_3_10
- st->trig->private_data = indio_dev;
-#endif
- st->trig->ops = &inv_mpu_trigger_ops;
- ret = iio_trigger_register(st->trig);
-
- if (ret) {
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_trigger_free(st->trig);
-#else
- iio_free_trigger(st->trig);
-#endif
- return -EPERM;
- }
- indio_dev->trig = st->trig;
-
- return 0;
-}
-
-void inv_mpu_remove_trigger(struct iio_dev *indio_dev)
-{
- struct inv_mpu_state *st = iio_priv(indio_dev);
-
- iio_trigger_unregister(st->trig);
-#ifdef CONFIG_INV_KERNEL_3_10
- iio_trigger_free(st->trig);
-#else
- iio_free_trigger(st->trig);
-#endif
-}
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_slave_bma250.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_slave_bma250.c
deleted file mode 100644
index 99ae702e67a..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_slave_bma250.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "inv_mpu_iio.h"
-#define BMA250_CHIP_ID 3
-#define BMA250_RANGE_SET 0
-#define BMA250_BW_SET 4
-
-/* range and bandwidth */
-#define BMA250_RANGE_2G 3
-#define BMA250_RANGE_4G 5
-#define BMA250_RANGE_8G 8
-#define BMA250_RANGE_16G 12
-#define BMA250_RANGE_MAX 4
-#define BMA250_RANGE_MASK 0xF0
-
-#define BMA250_BW_7_81HZ 0x08
-#define BMA250_BW_15_63HZ 0x09
-#define BMA250_BW_31_25HZ 0x0A
-#define BMA250_BW_62_50HZ 0x0B
-#define BMA250_BW_125HZ 0x0C
-#define BMA250_BW_250HZ 0x0D
-#define BMA250_BW_500HZ 0x0E
-#define BMA250_BW_1000HZ 0x0F
-#define BMA250_MAX_BW_SIZE 8
-#define BMA250_BW_REG_MASK 0xE0
-
-/* register definitions */
-#define BMA250_X_AXIS_LSB_REG 0x02
-#define BMA250_RANGE_SEL_REG 0x0F
-#define BMA250_BW_SEL_REG 0x10
-#define BMA250_MODE_CTRL_REG 0x11
-
-/* mode settings */
-#define BMA250_MODE_NORMAL 0
-#define BMA250_MODE_LOWPOWER 1
-#define BMA250_MODE_SUSPEND 2
-#define BMA250_MODE_MAX 3
-#define BMA250_MODE_MASK 0x3F
-#define BMA250_BIT_SUSPEND 0x80
-#define BMA250_BIT_LP 0x40
-
-struct bma_property {
- int range;
- int bandwidth;
- int mode;
-};
-
-static struct bma_property bma_static_property = {
- .range = BMA250_RANGE_SET,
- .bandwidth = BMA250_BW_SET,
- .mode = BMA250_MODE_SUSPEND
-};
-
-static int bma250_set_bandwidth(struct inv_mpu_state *st, u8 bw)
-{
- int res;
- u8 data;
- int bandwidth;
- switch (bw) {
- case 0:
- bandwidth = BMA250_BW_7_81HZ;
- break;
- case 1:
- bandwidth = BMA250_BW_15_63HZ;
- break;
- case 2:
- bandwidth = BMA250_BW_31_25HZ;
- break;
- case 3:
- bandwidth = BMA250_BW_62_50HZ;
- break;
- case 4:
- bandwidth = BMA250_BW_125HZ;
- break;
- case 5:
- bandwidth = BMA250_BW_250HZ;
- break;
- case 6:
- bandwidth = BMA250_BW_500HZ;
- break;
- case 7:
- bandwidth = BMA250_BW_1000HZ;
- break;
- default:
- return -EINVAL;
- }
- res = inv_secondary_read(BMA250_BW_SEL_REG, 1, &data);
- if (res)
- return res;
- data &= BMA250_BW_REG_MASK;
- data |= bandwidth;
- res = inv_secondary_write(BMA250_BW_SEL_REG, data);
- return res;
-}
-
-static int bma250_set_range(struct inv_mpu_state *st, u8 range)
-{
- int res;
- u8 orig, data;
- switch (range) {
- case 0:
- data = BMA250_RANGE_2G;
- break;
- case 1:
- data = BMA250_RANGE_4G;
- break;
- case 2:
- data = BMA250_RANGE_8G;
- break;
- case 3:
- data = BMA250_RANGE_16G;
- break;
- default:
- return -EINVAL;
- }
- res = inv_secondary_read(BMA250_RANGE_SEL_REG, 1, &orig);
- if (res)
- return res;
- orig &= BMA250_RANGE_MASK;
- data |= orig;
- res = inv_secondary_write(BMA250_RANGE_SEL_REG, data);
- if (res)
- return res;
- bma_static_property.range = range;
-
- return 0;
-}
-
-static int setup_slave_bma250(struct inv_mpu_state *st)
-{
- int result;
- u8 data[2];
- result = set_3050_bypass(st, true);
- if (result)
- return result;
- /*read secondary i2c ID register */
- result = inv_secondary_read(0, 1, data);
- if (result)
- return result;
- if (BMA250_CHIP_ID != data[0])
- return -EINVAL;
- result = set_3050_bypass(st, false);
- if (result)
- return result;
- /*AUX(accel), slave address is set inside set_3050_bypass*/
- /* bma250 x axis LSB register address is 2 */
- result = inv_i2c_single_write(st, REG_3050_AUX_BST_ADDR,
- BMA250_X_AXIS_LSB_REG);
-
- return result;
-}
-
-static int bma250_set_mode(struct inv_mpu_state *st, u8 mode)
-{
- int res;
- u8 data;
-
- res = inv_secondary_read(BMA250_MODE_CTRL_REG, 1, &data);
- if (res)
- return res;
- data &= BMA250_MODE_MASK;
- switch (mode) {
- case BMA250_MODE_NORMAL:
- break;
- case BMA250_MODE_LOWPOWER:
- data |= BMA250_BIT_LP;
- break;
- case BMA250_MODE_SUSPEND:
- data |= BMA250_BIT_SUSPEND;
- break;
- default:
- return -EINVAL;
- }
- res = inv_secondary_write(BMA250_MODE_CTRL_REG, data);
- if (res)
- return res;
- bma_static_property.mode = mode;
-
- return 0;
-}
-
-static int suspend_slave_bma250(struct inv_mpu_state *st)
-{
- int result;
- if (bma_static_property.mode == BMA250_MODE_SUSPEND)
- return 0;
- /*set to bypass mode */
- result = set_3050_bypass(st, true);
- if (result)
- return result;
- bma250_set_mode(st, BMA250_MODE_SUSPEND);
- /* no need to recover to non-bypass mode because we need it now */
-
- return 0;
-}
-
-static int resume_slave_bma250(struct inv_mpu_state *st)
-{
- int result;
- if (bma_static_property.mode == BMA250_MODE_NORMAL)
- return 0;
- /*set to bypass mode */
- result = set_3050_bypass(st, true);
- if (result)
- return result;
- result = bma250_set_mode(st, BMA250_MODE_NORMAL);
- /* recover bypass mode */
- result |= set_3050_bypass(st, false);
-
- return result ? (-EINVAL) : 0;
-}
-
-static int combine_data_slave_bma250(u8 *in, short *out)
-{
- out[0] = le16_to_cpup((__le16 *)(&in[0]));
- out[1] = le16_to_cpup((__le16 *)(&in[2]));
- out[2] = le16_to_cpup((__le16 *)(&in[4]));
-
- return 0;
-}
-
-static int get_mode_slave_bma250(void)
-{
- switch (bma_static_property.mode) {
- case BMA250_MODE_SUSPEND:
- return INV_MODE_SUSPEND;
- case BMA250_MODE_NORMAL:
- return INV_MODE_NORMAL;
- default:
- return -EINVAL;
- }
-}
-
-/**
- * set_lpf_bma250() - set lpf value
- */
-
-static int set_lpf_bma250(struct inv_mpu_state *st, int rate)
-{
- const short hz[] = {1000, 500, 250, 125, 62, 31, 15, 7};
- const int d[] = {7, 6, 5, 4, 3, 2, 1, 0};
- int i, h, data, result;
- h = (rate >> 1);
- i = 0;
- while ((h < hz[i]) && (i < ARRAY_SIZE(hz) - 1))
- i++;
- data = d[i];
-
- result = set_3050_bypass(st, true);
- if (result)
- return result;
- result = bma250_set_bandwidth(st, (u8) data);
- result |= set_3050_bypass(st, false);
-
- return result ? (-EINVAL) : 0;
-}
-/**
- * set_fs_bma250() - set range value
- */
-
-static int set_fs_bma250(struct inv_mpu_state *st, int fs)
-{
- int result;
- result = set_3050_bypass(st, true);
- if (result)
- return result;
- result = bma250_set_range(st, (u8) fs);
- result |= set_3050_bypass(st, false);
-
- return result ? (-EINVAL) : 0;
-}
-
-static struct inv_mpu_slave slave_bma250 = {
- .suspend = suspend_slave_bma250,
- .resume = resume_slave_bma250,
- .setup = setup_slave_bma250,
- .combine_data = combine_data_slave_bma250,
- .get_mode = get_mode_slave_bma250,
- .set_lpf = set_lpf_bma250,
- .set_fs = set_fs_bma250
-};
-
-int inv_register_mpu3050_slave(struct inv_mpu_state *st)
-{
- st->slave_accel = &slave_bma250;
-
- return 0;
-}
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_slave_compass.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_slave_compass.c
deleted file mode 100755
index 68b76d3a8e0..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_slave_compass.c
+++ /dev/null
@@ -1,854 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-
-#include "inv_mpu_iio.h"
-/* AKM definitions */
-#define REG_AKM_ID 0x00
-#define REG_AKM_INFO 0x01
-#define REG_AKM_STATUS 0x02
-#define REG_AKM_MEASURE_DATA 0x03
-#define REG_AKM_MODE 0x0A
-#define REG_AKM_ST_CTRL 0x0C
-#define REG_AKM_SENSITIVITY 0x10
-#define REG_AKM8963_CNTL1 0x0A
-
-/* AK09911 register definition */
-#define REG_AK09911_DMP_READ 0x3
-#define REG_AK09911_STATUS1 0x10
-#define REG_AK09911_CNTL2 0x31
-#define REG_AK09911_SENSITIVITY 0x60
-
-#define DATA_AKM_ID 0x48
-#define DATA_AKM_MODE_PD 0x00
-#define DATA_AKM_MODE_SM 0x01
-#define DATA_AKM_MODE_ST 0x08
-#define DATA_AKM_MODE_FR 0x0F
-#define DATA_AK09911_MODE_FR 0x1F
-#define DATA_AKM_SELF_TEST 0x40
-#define DATA_AKM_DRDY 0x01
-#define DATA_AKM8963_BIT 0x10
-#define DATA_AKM_STAT_MASK 0x0C
-
-#define DATA_AKM8975_SCALE (9830 * (1L << 15))
-#define DATA_AKM8972_SCALE (19661 * (1L << 15))
-#define DATA_AKM8963_SCALE0 (19661 * (1L << 15))
-#define DATA_AKM8963_SCALE1 (4915 * (1L << 15))
-#define DATA_AK09911_SCALE (19661 * (1L << 15))
-#define DATA_MLX_SCALE (4915 * (1L << 15))
-#define DATA_MLX_SCALE_EMPIRICAL (26214 * (1L << 15))
-
-#define DATA_AKM8963_SCALE_SHIFT 4
-#define DATA_AKM_99_BYTES_DMP 10
-#define DATA_AKM_89_BYTES_DMP 9
-#define DATA_AKM_MIN_READ_TIME (9 * NSEC_PER_MSEC)
-
-#define DEF_ST_COMPASS_WAIT_MIN (10 * 1000)
-#define DEF_ST_COMPASS_WAIT_MAX (15 * 1000)
-#define DEF_ST_COMPASS_TRY_TIMES 10
-#define DEF_ST_COMPASS_8963_SHIFT 2
-#define X 0
-#define Y 1
-#define Z 2
-
-/* milliseconds between each access */
-#define AKM_RATE_SCALE 10
-#define MLX_RATE_SCALE 50
-
-/* MLX90399 compass definition */
-#define DATA_MLX_CMD_READ_MEASURE 0x4F
-#define DATA_MLX_CMD_SINGLE_MEASURE 0x3F
-#define DATA_MLX_READ_DATA_BYTES 9
-#define DATA_MLX_STATUS_DATA 3
-#define DATA_MLX_MIN_READ_TIME (95 * NSEC_PER_MSEC)
-
-static const short AKM8975_ST_Lower[3] = {-100, -100, -1000};
-static const short AKM8975_ST_Upper[3] = {100, 100, -300};
-
-static const short AKM8972_ST_Lower[3] = {-50, -50, -500};
-static const short AKM8972_ST_Upper[3] = {50, 50, -100};
-
-static const short AKM8963_ST_Lower[3] = {-200, -200, -3200};
-static const short AKM8963_ST_Upper[3] = {200, 200, -800};
-
-/*
- * inv_setup_compass_akm() - Configure akm series compass.
- */
-static int inv_setup_compass_akm(struct inv_mpu_state *st)
-{
- int result;
- u8 data[4];
- u8 sens, mode, cmd;
-
- /* set to bypass mode */
- result = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config | BIT_BYPASS_EN);
- if (result)
- return result;
- /* read secondary i2c ID register */
- result = inv_secondary_read(REG_AKM_ID, 1, data);
- if (result)
- return result;
- if (data[0] != DATA_AKM_ID)
- return -ENXIO;
- /* set AKM to Fuse ROM access mode */
- if (COMPASS_ID_AK09911 == st->plat_data.sec_slave_id) {
- mode = REG_AK09911_CNTL2;
- sens = REG_AK09911_SENSITIVITY;
- cmd = DATA_AK09911_MODE_FR;
- } else {
- mode = REG_AKM_MODE;
- sens = REG_AKM_SENSITIVITY;
- cmd = DATA_AKM_MODE_FR;
- }
-
- result = inv_secondary_write(mode, cmd);
- if (result)
- return result;
- result = inv_secondary_read(sens, THREE_AXIS,
- st->chip_info.compass_sens);
- if (result)
- return result;
- /* revert to power down mode */
- result = inv_secondary_write(mode, DATA_AKM_MODE_PD);
- if (result)
- return result;
- pr_debug("%s senx=%d, seny=%d, senz=%d\n",
- st->hw->name,
- st->chip_info.compass_sens[0],
- st->chip_info.compass_sens[1],
- st->chip_info.compass_sens[2]);
- /* restore to non-bypass mode */
- result = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config);
- if (result)
- return result;
-
- /* setup master mode and master clock and ES bit */
- result = inv_i2c_single_write(st, REG_I2C_MST_CTRL, BIT_WAIT_FOR_ES);
- if (result)
- return result;
- /* slave 1 is used for AKM mode change only */
- result = inv_i2c_single_write(st, REG_I2C_SLV1_ADDR,
- st->plat_data.secondary_i2c_addr);
- if (result)
- return result;
- /* AKM mode register address */
- result = inv_i2c_single_write(st, REG_I2C_SLV1_REG, mode);
- if (result)
- return result;
- /* output data for slave 1 is fixed, single measure mode */
- st->slave_compass->scale = 1;
- if (COMPASS_ID_AK8975 == st->plat_data.sec_slave_id) {
- st->slave_compass->st_upper = AKM8975_ST_Upper;
- st->slave_compass->st_lower = AKM8975_ST_Lower;
- data[0] = DATA_AKM_MODE_SM;
- } else if (COMPASS_ID_AK8972 == st->plat_data.sec_slave_id) {
- st->slave_compass->st_upper = AKM8972_ST_Upper;
- st->slave_compass->st_lower = AKM8972_ST_Lower;
- data[0] = DATA_AKM_MODE_SM;
- } else if (COMPASS_ID_AK8963 == st->plat_data.sec_slave_id) {
- st->slave_compass->st_upper = AKM8963_ST_Upper;
- st->slave_compass->st_lower = AKM8963_ST_Lower;
- data[0] = DATA_AKM_MODE_SM |
- (st->slave_compass->scale << DATA_AKM8963_SCALE_SHIFT);
- } else if (COMPASS_ID_AK09911 == st->plat_data.sec_slave_id) {
- st->slave_compass->st_upper = AKM8963_ST_Upper;
- st->slave_compass->st_lower = AKM8963_ST_Lower;
- data[0] = DATA_AKM_MODE_SM;
- } else {
- return -EINVAL;
- }
-
- result = inv_i2c_single_write(st, INV_MPU_REG_I2C_SLV1_DO, data[0]);
-
- return result;
-}
-
-static int inv_akm_read_data(struct inv_mpu_state *st, short *o)
-{
- int result, shift;
- int i;
- u8 d[DATA_AKM_99_BYTES_DMP - 1];
- u8 *sens;
-
- sens = st->chip_info.compass_sens;
- result = 0;
- if (st->chip_config.dmp_on) {
- for (i = 0; i < 6; i++)
- d[1 + i] = st->fifo_data[i];
- } else {
- result = inv_i2c_read(st, REG_EXT_SENS_DATA_00,
- DATA_AKM_99_BYTES_DMP - 1, d);
- if ((DATA_AKM_DRDY != d[0]) || (d[7] & 0x8) || result)
- result = -EINVAL;
- }
- if (COMPASS_ID_AK09911 == st->plat_data.sec_slave_id)
- shift = 7;
- else
- shift = 8;
- for (i = 0; i < 3; i++) {
- o[i] = (short)((d[i * 2 + 1] << 8) | d[i * 2 + 2]);
- o[i] = (short)(((int)o[i] * (sens[i] + 128)) >> shift);
- }
-
- return result;
-}
-
-static int inv_mlx_read_data(struct inv_mpu_state *st, short *o)
-{
- int result;
- int i, z;
- u8 d[DATA_MLX_READ_DATA_BYTES];
-
- result = inv_i2c_read(st, REG_EXT_SENS_DATA_00,
- DATA_MLX_READ_DATA_BYTES, d);
- if ((!(d[0] & ~DATA_MLX_STATUS_DATA)) && (!result)) {
- for (i = 0; i < 3; i++)
- o[i] = (short)((d[i * 2 + 3] << 8) + d[i * 2 + 4]);
- } else {
- for (i = 0; i < 3; i++)
- o[i] = 0;
- }
- z = o[2];
- /* axis sensitivity conversion. Z axis has different sensitiviy from
- x and y */
- z *= 26;
- z /= 15;
- o[2] = z;
-
- return 0;
-}
-
-static int inv_check_akm_self_test(struct inv_mpu_state *st)
-{
- int result;
- u8 data[6], mode;
- u8 counter, cntl;
- short x, y, z;
- u8 *sens;
- sens = st->chip_info.compass_sens;
-
- /* set to bypass mode */
- result = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config | BIT_BYPASS_EN);
- if (result) {
- result = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config);
- return result;
- }
- if (COMPASS_ID_AK09911 == st->plat_data.sec_slave_id)
- mode = REG_AK09911_CNTL2;
- else
- mode = REG_AKM_MODE;
- /* set to power down mode */
- result = inv_secondary_write(mode, DATA_AKM_MODE_PD);
- if (result)
- goto AKM_fail;
-
- /* write 1 to ASTC register */
- result = inv_secondary_write(REG_AKM_ST_CTRL, DATA_AKM_SELF_TEST);
- if (result)
- goto AKM_fail;
- /* set self test mode */
- result = inv_secondary_write(mode, DATA_AKM_MODE_ST);
- if (result)
- goto AKM_fail;
- counter = DEF_ST_COMPASS_TRY_TIMES;
- while (counter > 0) {
- usleep_range(DEF_ST_COMPASS_WAIT_MIN, DEF_ST_COMPASS_WAIT_MAX);
- result = inv_secondary_read(REG_AKM_STATUS, 1, data);
- if (result)
- goto AKM_fail;
- if ((data[0] & DATA_AKM_DRDY) == 0)
- counter--;
- else
- counter = 0;
- }
- if ((data[0] & DATA_AKM_DRDY) == 0) {
- result = -EINVAL;
- goto AKM_fail;
- }
- result = inv_secondary_read(REG_AKM_MEASURE_DATA,
- BYTES_PER_SENSOR, data);
- if (result)
- goto AKM_fail;
-
- x = le16_to_cpup((__le16 *)(&data[0]));
- y = le16_to_cpup((__le16 *)(&data[2]));
- z = le16_to_cpup((__le16 *)(&data[4]));
- x = ((x * (sens[0] + 128)) >> 8);
- y = ((y * (sens[1] + 128)) >> 8);
- z = ((z * (sens[2] + 128)) >> 8);
- if (COMPASS_ID_AK8963 == st->plat_data.sec_slave_id) {
- result = inv_secondary_read(REG_AKM8963_CNTL1, 1, &cntl);
- if (result)
- goto AKM_fail;
- if (0 == (cntl & DATA_AKM8963_BIT)) {
- x <<= DEF_ST_COMPASS_8963_SHIFT;
- y <<= DEF_ST_COMPASS_8963_SHIFT;
- z <<= DEF_ST_COMPASS_8963_SHIFT;
- }
- }
- result = -EINVAL;
- if (x > st->slave_compass->st_upper[X] ||
- x < st->slave_compass->st_lower[X])
- goto AKM_fail;
- if (y > st->slave_compass->st_upper[Y] ||
- y < st->slave_compass->st_lower[Y])
- goto AKM_fail;
- if (z > st->slave_compass->st_upper[Z] ||
- z < st->slave_compass->st_lower[Z])
- goto AKM_fail;
- result = 0;
-AKM_fail:
- /*write 0 to ASTC register */
- result |= inv_secondary_write(REG_AKM_ST_CTRL, 0);
- /*set to power down mode */
- result |= inv_secondary_write(mode, DATA_AKM_MODE_PD);
- /*restore to non-bypass mode */
- result |= inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config);
- return result;
-}
-
-/*
- * inv_write_akm_scale() - Configure the akm scale range.
- */
-static int inv_write_akm_scale(struct inv_mpu_state *st, int data)
-{
- char d, en;
- int result;
-
- if (COMPASS_ID_AK8963 != st->plat_data.sec_slave_id)
- return 0;
- en = !!data;
- if (st->slave_compass->scale == en)
- return 0;
- d = (DATA_AKM_MODE_SM | (en << DATA_AKM8963_SCALE_SHIFT));
- result = inv_i2c_single_write(st, INV_MPU_REG_I2C_SLV1_DO, d);
- if (result)
- return result;
- st->slave_compass->scale = en;
-
- return 0;
-}
-
-/*
- * inv_read_akm_scale() - show AKM scale.
- */
-static int inv_read_akm_scale(struct inv_mpu_state *st, int *scale)
-{
- if (COMPASS_ID_AK8975 == st->plat_data.sec_slave_id)
- *scale = DATA_AKM8975_SCALE;
- else if (COMPASS_ID_AK8972 == st->plat_data.sec_slave_id)
- *scale = DATA_AKM8972_SCALE;
- else if (COMPASS_ID_AK8963 == st->plat_data.sec_slave_id)
- if (st->slave_compass->scale)
- *scale = DATA_AKM8963_SCALE1;
- else
- *scale = DATA_AKM8963_SCALE0;
- else if (COMPASS_ID_AK09911 == st->plat_data.sec_slave_id)
- *scale = DATA_AK09911_SCALE;
- else
- return -EINVAL;
-
- return IIO_VAL_INT;
-}
-
-static int inv_suspend_akm(struct inv_mpu_state *st)
-{
- int result;
-
- /* slave 0 is disabled */
- result = inv_i2c_single_write(st, REG_I2C_SLV0_CTRL, 0);
- if (result)
- return result;
- /* slave 1 is disabled */
- result = inv_i2c_single_write(st, REG_I2C_SLV1_CTRL, 0);
-
- return result;
-}
-
-static int inv_resume_akm(struct inv_mpu_state *st)
-{
- int result;
- u8 reg_addr, bytes;
-
- /* slave 0 is used to read data from compass */
- /*read mode */
- result = inv_i2c_single_write(st, REG_I2C_SLV0_ADDR,
- INV_MPU_BIT_I2C_READ |
- st->plat_data.secondary_i2c_addr);
- if (result)
- return result;
- /* AKM status register address is 1 */
- if (COMPASS_ID_AK09911 == st->plat_data.sec_slave_id) {
- if (st->chip_config.dmp_on) {
- reg_addr = REG_AK09911_DMP_READ;
- bytes = DATA_AKM_99_BYTES_DMP;
- } else {
- reg_addr = REG_AK09911_STATUS1;
- bytes = DATA_AKM_99_BYTES_DMP - 1;
- }
- } else {
- if (st->chip_config.dmp_on) {
- reg_addr = REG_AKM_INFO;
- bytes = DATA_AKM_89_BYTES_DMP;
- } else {
- reg_addr = REG_AKM_STATUS;
- bytes = DATA_AKM_89_BYTES_DMP - 1;
- }
- }
- result = inv_i2c_single_write(st, REG_I2C_SLV0_REG, reg_addr);
- if (result)
- return result;
-
- /* slave 0 is enabled, read 10 or 8 bytes from here, swap bytes */
- result = inv_i2c_single_write(st, REG_I2C_SLV0_CTRL,
- INV_MPU_BIT_GRP |
- INV_MPU_BIT_BYTE_SW |
- INV_MPU_BIT_SLV_EN |
- bytes);
- if (result)
- return result;
- /* slave 1 is enabled, write byte length is 1 */
- result = inv_i2c_single_write(st, REG_I2C_SLV1_CTRL,
- INV_MPU_BIT_SLV_EN | 1);
-
- return result;
-}
-
-/*
- * inv_write_mlx_scale() - Configure the mlx90399 scale range.
- */
-static int inv_write_mlx_scale(struct inv_mpu_state *st, int data)
-{
- st->slave_compass->scale = data;
- return 0;
-}
-
-/*
- * inv_read_mlx_scale() - show mlx90399 scale.
- */
-static int inv_read_mlx_scale(struct inv_mpu_state *st, int *scale)
-{
- *scale = st->slave_compass->scale;
- return IIO_VAL_INT;
-}
-
-static int inv_i2c_read_mlx(struct inv_mpu_state *st, u16 i2c_addr,
- u16 length, u8 *data)
-{
- struct i2c_msg msgs[1];
- int res;
-
- if (!data)
- return -EINVAL;
-
- msgs[0].addr = i2c_addr;
- msgs[0].flags = I2C_M_RD;
- msgs[0].buf = data;
- msgs[0].len = length;
-
- res = i2c_transfer(st->sl_handle, msgs, 1);
-
- if (res < 1) {
- if (res >= 0)
- res = -EIO;
- } else
- res = 0;
-
- return res;
-}
-
-static int inv_i2c_write_mlx(struct inv_mpu_state *st,
- u16 i2c_addr, u8 data)
-{
- u8 tmp[1];
- struct i2c_msg msg;
- int res;
-
- tmp[0] = data;
- msg.addr = i2c_addr;
- msg.flags = 0; /* write */
- msg.buf = tmp;
- msg.len = 1;
-
- res = i2c_transfer(st->sl_handle, &msg, 1);
- if (res < 1) {
- if (res == 0)
- res = -EIO;
- return res;
- } else
- return 0;
-}
-
-static int inv_i2c_read_reg_mlx(struct inv_mpu_state *st,
- u16 i2c_addr, u8 reg, u16 *val)
-{
- u8 tmp[10];
- struct i2c_msg msg;
- int res;
-
- tmp[0] = 0x50;
- tmp[1] = (reg << 2);
- msg.addr = i2c_addr;
- msg.flags = 0; /* write */
- msg.buf = tmp;
- msg.len = 2;
-
- res = i2c_transfer(st->sl_handle, &msg, 1);
- if (res < 1) {
- if (res == 0)
- res = -EIO;
- return res;
- }
- res = inv_i2c_read_mlx(st, i2c_addr, 10, tmp);
- if (res)
- return res;
- *val = ((tmp[1] << 8) | tmp[2]);
-
- return res;
-}
-
-static int inv_i2c_write_mlx_reg(struct inv_mpu_state *st,
- u16 i2c_addr, int reg, u16 d)
-{
- u8 tmp[10];
- struct i2c_msg msg;
- int res;
-
- /* write register command, writing volatile memory */
- tmp[0] = 0x60;
- tmp[1] = ((d >> 8) & 0xff);
- tmp[2] = (d & 0xff);
- tmp[3] = (reg << 2);
- msg.addr = i2c_addr;
- msg.flags = 0; /* write */
- msg.buf = tmp;
- msg.len = 4;
-
- res = i2c_transfer(st->sl_handle, &msg, 1);
- if (res < 1) {
- if (res == 0)
- res = -EIO;
- return res;
- }
- /* read status */
- res = inv_i2c_read_mlx(st, i2c_addr, 10, tmp);
-
- return res;
-}
-
-static int inv_write_mlx_cmd(struct inv_mpu_state *st, u8 cmd)
-{
- int result;
- u8 d[10];
- int addr;
-
- addr = st->plat_data.secondary_i2c_addr;
- result = inv_i2c_write_mlx(st, addr, cmd);
- if (result)
- return result;
- /* read back status byte */
- result = inv_i2c_read_mlx(st, addr, 10, d);
-
- return result;
-}
-
-static int inv_read_mlx_z_axis(struct inv_mpu_state *st, s16 *z)
-{
- int result;
- u8 d[10];
- int addr;
-
- addr = st->plat_data.secondary_i2c_addr;
-
- /* measure z axis */
- result = inv_write_mlx_cmd(st, 0x39);
- if (result)
- return result;
- msleep(100);
- /* read z axis */
- result = inv_i2c_write_mlx(st, addr, 0x49);
- if (result)
- return result;
- /* read back status byte */
- result = inv_i2c_read_mlx(st, addr, 10, d);
- if (result)
- return result;
- if ((d[0] & 0x3) == 1)
- *z = (short)((d[3] << 8) + d[4]);
- else
- return -EINVAL;
-
- return 0;
-}
-
-static int inv_write_mlx_reg(struct inv_mpu_state *st)
-{
- int result;
- int addr;
- u16 r_val;
-
- addr = st->plat_data.secondary_i2c_addr;
-
- /* write register 0.
- set GAIN_SEL as 7;
- set HALL_CONF as 0xC. */
- result = inv_i2c_write_mlx_reg(st, addr, 0, 0x7c);
- if (result)
- return result;
- /* write register 2.
- set resolution is zero for all axes;
- set DIGI filter as 6.
- set OSR as 0.
- set OSR2 as 0. */
- result = inv_i2c_write_mlx_reg(st, addr, 2, 0x18);
- if (result)
- return result;
- /* read register 1 */
- result = inv_i2c_read_reg_mlx(st, addr, 1, &r_val);
- if (result)
- return result;
- /* enable temp comp */
- r_val |= 0x400;
- result = inv_i2c_write_mlx_reg(st, addr, 1, r_val);
- /* the value should be kept in the volatile memory */
-
- return result;
-}
-
-static int inv_check_mlx_self_test(struct inv_mpu_state *st)
-{
- int result;
- int addr;
- s16 meas_ref, meas_coil;
- u16 diff, r_val;
-
- /* set to bypass mode */
- result = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config | BIT_BYPASS_EN);
- if (result) {
- result = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config);
- return result;
- }
-
- addr = st->plat_data.secondary_i2c_addr;
-
- /* fake read to flush the previous data */
- result = inv_read_mlx_z_axis(st, &meas_ref);
-
- result = inv_read_mlx_z_axis(st, &meas_ref);
- if (result)
- return result;
-
- /* read register 1 */
- result = inv_i2c_read_reg_mlx(st, addr, 0, &r_val);
- if (result)
- return result;
- /* enable self test */
- r_val |= 0x100;
- result = inv_i2c_write_mlx_reg(st, addr, 0, r_val);
- if (result)
- return result;
- msleep(200);
- result = inv_read_mlx_z_axis(st, &meas_coil);
- if (result)
- return result;
- result = inv_write_mlx_cmd(st, 0xD0);
- if (result)
- return result;
- result = inv_write_mlx_reg(st);
- if (result)
- return result;
- diff = abs(meas_ref - meas_coil);
- if (diff < 25 || diff > 300)
- result = 1;
-
- /*restore to non-bypass mode */
- result |= inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config);
-
- return result;
-}
-
-/*
- * inv_setup_compass_mlx() - Configure akm series compass.
- */
-static int inv_setup_compass_mlx(struct inv_mpu_state *st)
-{
- int result;
- int addr;
-
- addr = st->plat_data.secondary_i2c_addr;
- /* set to bypass mode */
- result = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config | BIT_BYPASS_EN);
- if (result)
- return result;
- result = inv_write_mlx_reg(st);
- if (result)
- return result;
-
- /*restore to non-bypass mode */
- result = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config);
- if (result)
- return result;
-
- /*setup master mode and master clock and ES bit*/
- result = inv_i2c_single_write(st, REG_I2C_MST_CTRL, BIT_WAIT_FOR_ES);
- if (result)
- return result;
-
- /* slave 0 used to write read measurement command, write mode */
- result = inv_i2c_single_write(st, REG_I2C_SLV0_ADDR, addr);
- if (result)
- return result;
- /* ignore the register address, send out data only */
- result = inv_i2c_single_write(st, INV_MPU_REG_I2C_SLV0_DO,
- DATA_MLX_CMD_READ_MEASURE);
- if (result)
- return result;
-
- /* slave 1 used to read status bytes and data of read measurement */
- result = inv_i2c_single_write(st, REG_I2C_SLV1_ADDR,
- INV_MPU_BIT_I2C_READ | addr);
- if (result)
- return result;
- /* slave 2 used to write single measurement command, write mode */
- result = inv_i2c_single_write(st, REG_I2C_SLV2_ADDR, addr);
- if (result)
- return result;
- /* ignore the register address, send out data only */
- result = inv_i2c_single_write(st, INV_MPU_REG_I2C_SLV2_DO,
- DATA_MLX_CMD_SINGLE_MEASURE);
- if (result)
- return result;
- /* slave 3 used to read status bytes and data of read measurement */
- result = inv_i2c_single_write(st, REG_I2C_SLV3_ADDR,
- INV_MPU_BIT_I2C_READ | addr);
-
- st->slave_compass->scale = DATA_MLX_SCALE;
-
- return result;
-}
-
-static int inv_suspend_mlx(struct inv_mpu_state *st)
-{
- int result;
-
- result = inv_i2c_single_write(st, REG_I2C_SLV0_CTRL, 0);
- if (result)
- return result;
- result = inv_i2c_single_write(st, REG_I2C_SLV1_CTRL, 0);
- if (result)
- return result;
- result = inv_i2c_single_write(st, REG_I2C_SLV2_CTRL, 0);
- if (result)
- return result;
- result = inv_i2c_single_write(st, REG_I2C_SLV3_CTRL, 0);
-
- return result;
-}
-
-static int inv_resume_mlx(struct inv_mpu_state *st)
-{
- int result;
-
- /* enable, ignore register, write 1 bytes */
- result = inv_i2c_single_write(st, REG_I2C_SLV0_CTRL,
- INV_MPU_BIT_SLV_EN |
- INV_MPU_BIT_REG_DIS |
- 1);
- if (result)
- return result;
-
- /* enable, ignore register, read 9 bytes */
- result = inv_i2c_single_write(st, REG_I2C_SLV1_CTRL,
- INV_MPU_BIT_SLV_EN |
- INV_MPU_BIT_REG_DIS |
- DATA_MLX_READ_DATA_BYTES);
- if (result)
- return result;
- /* enable, ignore register, write 1 bytes */
- result = inv_i2c_single_write(st, REG_I2C_SLV2_CTRL,
- INV_MPU_BIT_SLV_EN |
- INV_MPU_BIT_REG_DIS |
- 1);
- if (result)
- return result;
-
- /* enable, ignore register, read 1 bytes */
- result = inv_i2c_single_write(st, REG_I2C_SLV3_CTRL,
- INV_MPU_BIT_SLV_EN |
- INV_MPU_BIT_REG_DIS |
- 1);
-
- return result;
-}
-
-static struct inv_mpu_slave slave_akm = {
- .suspend = inv_suspend_akm,
- .resume = inv_resume_akm,
- .get_scale = inv_read_akm_scale,
- .set_scale = inv_write_akm_scale,
- .self_test = inv_check_akm_self_test,
- .setup = inv_setup_compass_akm,
- .read_data = inv_akm_read_data,
- .rate_scale = AKM_RATE_SCALE,
- .min_read_time = DATA_AKM_MIN_READ_TIME,
-};
-
-static struct inv_mpu_slave slave_mlx90399 = {
- .suspend = inv_suspend_mlx,
- .resume = inv_resume_mlx,
- .get_scale = inv_read_mlx_scale,
- .set_scale = inv_write_mlx_scale,
- .self_test = inv_check_mlx_self_test,
- .setup = inv_setup_compass_mlx,
- .read_data = inv_mlx_read_data,
- .rate_scale = MLX_RATE_SCALE,
- .min_read_time = DATA_MLX_MIN_READ_TIME,
-};
-
-int inv_mpu_setup_compass_slave(struct inv_mpu_state *st)
-{
- switch (st->plat_data.sec_slave_id) {
- case COMPASS_ID_AK8975:
- case COMPASS_ID_AK8972:
- case COMPASS_ID_AK8963:
- case COMPASS_ID_AK09911:
- st->slave_compass = &slave_akm;
- break;
- case COMPASS_ID_MLX90399:
- st->slave_compass = &slave_mlx90399;
- break;
- default:
- return -EINVAL;
- }
-
- return st->slave_compass->setup(st);
-}
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_slave_pressure.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_slave_pressure.c
deleted file mode 100755
index 24d80810449..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_slave_pressure.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-
-#include "inv_mpu_iio.h"
-
-/* Constants */
-#define SHIFT_RIGHT_4_POSITION 4
-#define SHIFT_LEFT_2_POSITION 2
-#define SHIFT_LEFT_4_POSITION 4
-#define SHIFT_LEFT_5_POSITION 5
-#define SHIFT_LEFT_8_POSITION 8
-#define SHIFT_LEFT_12_POSITION 12
-#define SHIFT_LEFT_16_POSITION 16
-
-/* Sensor Specific constants */
-#define BMP280_SLEEP_MODE 0x00
-#define BMP280_FORCED_MODE 0x01
-#define BMP280_NORMAL_MODE 0x03
-#define BMP280_SOFT_RESET 0xB6
-
-#define BMP280_DELAYTIME_MS_NONE 0
-#define BMP280_DELAYTIME_MS_5 5
-#define BMP280_DELAYTIME_MS_6 6
-#define BMP280_DELAYTIME_MS_8 8
-#define BMP280_DELAYTIME_MS_12 12
-#define BMP280_DELAYTIME_MS_22 22
-#define BMP280_DELAYTIME_MS_38 38
-
-#define BMP280_OVERSAMPLING_SKIPPED 0x00
-#define BMP280_OVERSAMPLING_1X 0x01
-#define BMP280_OVERSAMPLING_2X 0x02
-#define BMP280_OVERSAMPLING_4X 0x03
-#define BMP280_OVERSAMPLING_8X 0x04
-#define BMP280_OVERSAMPLING_16X 0x05
-
-#define BMP280_ULTRALOWPOWER_MODE 0x00
-#define BMP280_LOWPOWER_MODE 0x01
-#define BMP280_STANDARDRESOLUTION_MODE 0x02
-#define BMP280_HIGHRESOLUTION_MODE 0x03
-#define BMP280_ULTRAHIGHRESOLUTION_MODE 0x04
-
-#define BMP280_ULTRALOWPOWER_OSRS_P BMP280_OVERSAMPLING_1X
-#define BMP280_ULTRALOWPOWER_OSRS_T BMP280_OVERSAMPLING_1X
-
-#define BMP280_LOWPOWER_OSRS_P BMP280_OVERSAMPLING_2X
-#define BMP280_LOWPOWER_OSRS_T BMP280_OVERSAMPLING_1X
-
-#define BMP280_STANDARDRESOLUTION_OSRS_P BMP280_OVERSAMPLING_4X
-#define BMP280_STANDARDRESOLUTION_OSRS_T BMP280_OVERSAMPLING_1X
-
-#define BMP280_HIGHRESOLUTION_OSRS_P BMP280_OVERSAMPLING_8X
-#define BMP280_HIGHRESOLUTION_OSRS_T BMP280_OVERSAMPLING_1X
-
-#define BMP280_ULTRAHIGHRESOLUTION_OSRS_P BMP280_OVERSAMPLING_16X
-#define BMP280_ULTRAHIGHRESOLUTION_OSRS_T BMP280_OVERSAMPLING_2X
-
-#define BMP280_FILTERCOEFF_OFF 0x00
-#define BMP280_FILTERCOEFF_2 0x01
-#define BMP280_FILTERCOEFF_4 0x02
-#define BMP280_FILTERCOEFF_8 0x03
-#define BMP280_FILTERCOEFF_16 0x04
-
-/*calibration parameters */
-#define BMP280_DIG_T1_LSB_REG 0x88
-#define BMP280_DIG_T1_MSB_REG 0x89
-#define BMP280_DIG_T2_LSB_REG 0x8A
-#define BMP280_DIG_T2_MSB_REG 0x8B
-#define BMP280_DIG_T3_LSB_REG 0x8C
-#define BMP280_DIG_T3_MSB_REG 0x8D
-#define BMP280_DIG_P1_LSB_REG 0x8E
-#define BMP280_DIG_P1_MSB_REG 0x8F
-#define BMP280_DIG_P2_LSB_REG 0x90
-#define BMP280_DIG_P2_MSB_REG 0x91
-#define BMP280_DIG_P3_LSB_REG 0x92
-#define BMP280_DIG_P3_MSB_REG 0x93
-#define BMP280_DIG_P4_LSB_REG 0x94
-#define BMP280_DIG_P4_MSB_REG 0x95
-#define BMP280_DIG_P5_LSB_REG 0x96
-#define BMP280_DIG_P5_MSB_REG 0x97
-#define BMP280_DIG_P6_LSB_REG 0x98
-#define BMP280_DIG_P6_MSB_REG 0x99
-#define BMP280_DIG_P7_LSB_REG 0x9A
-#define BMP280_DIG_P7_MSB_REG 0x9B
-#define BMP280_DIG_P8_LSB_REG 0x9C
-#define BMP280_DIG_P8_MSB_REG 0x9D
-#define BMP280_DIG_P9_LSB_REG 0x9E
-#define BMP280_DIG_P9_MSB_REG 0x9F
-
-#define BMP280_CHIPID_REG 0xD0 /*Chip ID Register */
-#define BMP280_RESET_REG 0xE0 /*Softreset Register */
-#define BMP280_STATUS_REG 0xF3 /*Status Register */
-#define BMP280_CTRLMEAS_REG 0xF4 /*Ctrl Measure Register */
-#define BMP280_CONFIG_REG 0xF5 /*Configuration Register */
-#define BMP280_PRESSURE_MSB_REG 0xF7 /*Pressure MSB Register */
-#define BMP280_PRESSURE_LSB_REG 0xF8 /*Pressure LSB Register */
-#define BMP280_PRESSURE_XLSB_REG 0xF9 /*Pressure XLSB Register */
-#define BMP280_TEMPERATURE_MSB_REG 0xFA /*Temperature MSB Reg */
-#define BMP280_TEMPERATURE_LSB_REG 0xFB /*Temperature LSB Reg */
-#define BMP280_TEMPERATURE_XLSB_REG 0xFC /*Temperature XLSB Reg */
-
-/* Status Register */
-#define BMP280_STATUS_REG_MEASURING__POS 3
-#define BMP280_STATUS_REG_MEASURING__MSK 0x08
-#define BMP280_STATUS_REG_MEASURING__LEN 1
-#define BMP280_STATUS_REG_MEASURING__REG BMP280_STATUS_REG
-
-#define BMP280_STATUS_REG_IMUPDATE__POS 0
-#define BMP280_STATUS_REG_IMUPDATE__MSK 0x01
-#define BMP280_STATUS_REG_IMUPDATE__LEN 1
-#define BMP280_STATUS_REG_IMUPDATE__REG BMP280_STATUS_REG
-
-/* Control Measurement Register */
-#define BMP280_CTRLMEAS_REG_OSRST__POS 5
-#define BMP280_CTRLMEAS_REG_OSRST__MSK 0xE0
-#define BMP280_CTRLMEAS_REG_OSRST__LEN 3
-#define BMP280_CTRLMEAS_REG_OSRST__REG BMP280_CTRLMEAS_REG
-
-#define BMP280_CTRLMEAS_REG_OSRSP__POS 2
-#define BMP280_CTRLMEAS_REG_OSRSP__MSK 0x1C
-#define BMP280_CTRLMEAS_REG_OSRSP__LEN 3
-#define BMP280_CTRLMEAS_REG_OSRSP__REG BMP280_CTRLMEAS_REG
-
-#define BMP280_CTRLMEAS_REG_MODE__POS 0
-#define BMP280_CTRLMEAS_REG_MODE__MSK 0x03
-#define BMP280_CTRLMEAS_REG_MODE__LEN 2
-#define BMP280_CTRLMEAS_REG_MODE__REG BMP280_CTRLMEAS_REG
-
-/* Configuation Register */
-#define BMP280_CONFIG_REG_TSB__POS 5
-#define BMP280_CONFIG_REG_TSB__MSK 0xE0
-#define BMP280_CONFIG_REG_TSB__LEN 3
-#define BMP280_CONFIG_REG_TSB__REG BMP280_CONFIG_REG
-
-#define BMP280_CONFIG_REG_FILTER__POS 2
-#define BMP280_CONFIG_REG_FILTER__MSK 0x1C
-#define BMP280_CONFIG_REG_FILTER__LEN 3
-#define BMP280_CONFIG_REG_FILTER__REG BMP280_CONFIG_REG
-
-#define BMP280_CONFIG_REG_SPI3WEN__POS 0
-#define BMP280_CONFIG_REG_SPI3WEN__MSK 0x01
-#define BMP280_CONFIG_REG_SPI3WEN__LEN 1
-#define BMP280_CONFIG_REG_SPI3WEN__REG BMP280_CONFIG_REG
-
-/* Data Register */
-#define BMP280_PRESSURE_XLSB_REG_DATA__POS 4
-#define BMP280_PRESSURE_XLSB_REG_DATA__MSK 0xF0
-#define BMP280_PRESSURE_XLSB_REG_DATA__LEN 4
-#define BMP280_PRESSURE_XLSB_REG_DATA__REG BMP280_PRESSURE_XLSB_REG
-
-#define BMP280_TEMPERATURE_XLSB_REG_DATA__POS 4
-#define BMP280_TEMPERATURE_XLSB_REG_DATA__MSK 0xF0
-#define BMP280_TEMPERATURE_XLSB_REG_DATA__LEN 4
-#define BMP280_TEMPERATURE_XLSB_REG_DATA__REG BMP280_TEMPERATURE_XLSB_REG
-
-#define BMP280_RATE_SCALE 35
-#define DATA_BMP280_MIN_READ_TIME (32 * NSEC_PER_MSEC)
-#define BMP280_DATA_BYTES_9911 6
-#define FAKE_DATA_NUM_BYTES 10
-
-/** this structure holds all device specific calibration parameters */
-struct bmp280_calibration_param_t {
- u32 dig_T1;
- s32 dig_T2;
- s32 dig_T3;
- u32 dig_P1;
- s32 dig_P2;
- s32 dig_P3;
- s32 dig_P4;
- s32 dig_P5;
- s32 dig_P6;
- s32 dig_P7;
- s32 dig_P8;
- s32 dig_P9;
-
- s32 t_fine;
-};
-/** BMP280 image registers data structure */
-struct bmp280_t {
- struct bmp280_calibration_param_t cal_param;
-
- u8 chip_id;
- u8 dev_addr;
-
- u8 waittime;
-
- u8 osrs_t;
- u8 osrs_p;
-};
-static struct bmp280_t bmp280;
-
-static int bmp280_get_calib_param(struct inv_mpu_state *st)
-{
- u8 d[24];
- int r;
-
- r = inv_aux_read(BMP280_DIG_T1_LSB_REG, 24, d);
- if (r)
- return r;
-
- bmp280.cal_param.dig_T1 = (u16)((((u16)((u8)d[1])) <<
- SHIFT_LEFT_8_POSITION) | d[0]);
- bmp280.cal_param.dig_T2 = (s16)((((s16)((s8)d[3])) <<
- SHIFT_LEFT_8_POSITION) | d[2]);
- bmp280.cal_param.dig_T3 = (s16)((((s16)((s8)d[5])) <<
- SHIFT_LEFT_8_POSITION) | d[4]);
- bmp280.cal_param.dig_P1 = (u16)((((u16)((u8)d[7])) <<
- SHIFT_LEFT_8_POSITION) | d[6]);
- bmp280.cal_param.dig_P2 = (s16)((((s16)((s8)d[9])) <<
- SHIFT_LEFT_8_POSITION) | d[8]);
- bmp280.cal_param.dig_P3 = (s16)((((s16)((s8)d[11])) <<
- SHIFT_LEFT_8_POSITION) | d[10]);
- bmp280.cal_param.dig_P4 = (s16)((((s16)((s8)d[13])) <<
- SHIFT_LEFT_8_POSITION) | d[12]);
- bmp280.cal_param.dig_P5 = (s16)((((s16)((s8)d[15])) <<
- SHIFT_LEFT_8_POSITION) | d[14]);
- bmp280.cal_param.dig_P6 = (s16)((((s16)((s8)d[17])) <<
- SHIFT_LEFT_8_POSITION) | d[16]);
- bmp280.cal_param.dig_P7 = (s16)((((s16)((s8)d[19])) <<
- SHIFT_LEFT_8_POSITION) | d[18]);
- bmp280.cal_param.dig_P8 = (s16)((((s16)((s8)d[21])) <<
- SHIFT_LEFT_8_POSITION) | d[20]);
- bmp280.cal_param.dig_P9 = (s16)((((s16)((s8)d[23])) <<
- SHIFT_LEFT_8_POSITION) | d[22]);
-
- return 0;
-}
-
-static int inv_setup_bmp280(struct inv_mpu_state *st)
-{
- int r;
- u8 d[10];
-
- /* set to bypass mode */
- r = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config | BIT_BYPASS_EN);
- if (r)
- return r;
- /* issue soft reset */
- r = inv_aux_write(BMP280_RESET_REG, BMP280_SOFT_RESET);
- if (r)
- return r;
- msleep(100);
- r = inv_aux_read(BMP280_CHIPID_REG, 1, d);
- if (r)
- return r;
- /* set pressure as ultra high resolution */
- bmp280.osrs_t = BMP280_ULTRAHIGHRESOLUTION_OSRS_T;
- bmp280.osrs_p = BMP280_ULTRAHIGHRESOLUTION_OSRS_P;
-
- /* set IIR filter as 4 */
- r = inv_aux_write(BMP280_CONFIG_REG_FILTER__REG,
- BMP280_FILTERCOEFF_16 << SHIFT_LEFT_2_POSITION);
- if (r)
- return r;
- r = bmp280_get_calib_param(st);
- if (r)
- return r;
-
- /*restore to non-bypass mode */
- r = inv_i2c_single_write(st, REG_INT_PIN_CFG,
- st->plat_data.int_config);
- if (r)
- return r;
-
- /* setup master mode and master clock and ES bit */
- r = inv_i2c_single_write(st, REG_I2C_MST_CTRL, BIT_WAIT_FOR_ES);
- if (r)
- return r;
- /*slave 3 is used for pressure mode change only*/
- r = inv_i2c_single_write(st, REG_I2C_SLV3_ADDR,
- st->plat_data.aux_i2c_addr);
- if (r)
- return r;
- /* pressure sensor mode register address */
- r = inv_i2c_single_write(st, REG_I2C_SLV3_REG, BMP280_CTRLMEAS_REG);
- if (r)
- return r;
- d[0] = (bmp280.osrs_t << SHIFT_LEFT_5_POSITION) +
- (bmp280.osrs_p << SHIFT_LEFT_2_POSITION) +
- BMP280_FORCED_MODE;
- r = inv_i2c_single_write(st, INV_MPU_REG_I2C_SLV3_DO, d[0]);
-
- return r;
-}
-
-static int inv_check_bmp280_self_test(struct inv_mpu_state *st)
-{
- return 0;
-}
-static int inv_write_bmp280_scale(struct inv_mpu_state *st, int data)
-{
- return 0;
-}
-static int inv_read_bmp280_scale(struct inv_mpu_state *st, int *scale)
-{
- return 0;
-}
-
-static int inv_resume_bmp280(struct inv_mpu_state *st)
-{
- int r;
- u8 bytes, start;
-
- bytes = BMP280_DATA_BYTES_9911;
- start = BMP280_PRESSURE_MSB_REG;
- if (st->chip_config.dmp_on) {
- if (st->sensor[SENSOR_COMPASS].on) {
- if (COMPASS_ID_AK09911 != st->plat_data.sec_slave_id) {
- bytes++;
- start -= 1;
- }
- } else {
- /* if compass is disabled, read fake data for DMP */
- /*read mode */
- r = inv_i2c_single_write(st, REG_I2C_SLV0_ADDR,
- INV_MPU_BIT_I2C_READ |
- st->plat_data.aux_i2c_addr);
- if (r)
- return r;
- /* read calibration data as the fake data */
- r = inv_i2c_single_write(st, REG_I2C_SLV0_REG,
- BMP280_DIG_T1_LSB_REG);
- if (r)
- return r;
- /* slave 0 is enabled, read 10 bytes from here */
- r = inv_i2c_single_write(st, REG_I2C_SLV0_CTRL,
- INV_MPU_BIT_SLV_EN |
- FAKE_DATA_NUM_BYTES);
- }
- }
- /* slave 2 is used to read data from pressure sensor */
- /*read mode */
- r = inv_i2c_single_write(st, REG_I2C_SLV2_ADDR,
- INV_MPU_BIT_I2C_READ |
- st->plat_data.aux_i2c_addr);
- if (r)
- return r;
- /* start from pressure sensor */
- r = inv_i2c_single_write(st, REG_I2C_SLV2_REG, start);
- if (r)
- return r;
-
- /* slave 2 is enabled, read 6 or 7 bytes from here */
- r = inv_i2c_single_write(st, REG_I2C_SLV2_CTRL,
- INV_MPU_BIT_SLV_EN | bytes);
- if (r)
- return r;
- /* slave 3 is enabled, write byte length is 1 */
- r = inv_i2c_single_write(st, REG_I2C_SLV3_CTRL,
- INV_MPU_BIT_SLV_EN | 1);
-
- return r;
-}
-
-static int inv_suspend_bmp280(struct inv_mpu_state *st)
-{
- int r;
-
- if ((!st->sensor[SENSOR_COMPASS].on) && st->chip_config.dmp_on) {
- /* slave 0 is disabled */
- r = inv_i2c_single_write(st, REG_I2C_SLV0_CTRL, 0);
- if (r)
- return r;
- }
-
- /* slave 2 is disabled */
- r = inv_i2c_single_write(st, REG_I2C_SLV2_CTRL, 0);
- if (r)
- return r;
- /* slave 3 is disabled */
- r = inv_i2c_single_write(st, REG_I2C_SLV3_CTRL, 0);
-
- return r;
-}
-
-static s32 bmp280_compensate_T_int32(s32 adc_t)
-{
- s32 v_x1_u32r = 0;
- s32 v_x2_u32r = 0;
- s32 temperature = 0;
-
- v_x1_u32r = ((((adc_t >> 3) - ((s32)
- bmp280.cal_param.dig_T1 << 1))) *
- ((s32)bmp280.cal_param.dig_T2)) >> 11;
- v_x2_u32r = (((((adc_t >> 4) -
- ((s32)bmp280.cal_param.dig_T1)) * ((adc_t >> 4) -
- ((s32)bmp280.cal_param.dig_T1))) >> 12) *
- ((s32)bmp280.cal_param.dig_T3)) >> 14;
- bmp280.cal_param.t_fine = v_x1_u32r + v_x2_u32r;
- temperature = (bmp280.cal_param.t_fine * 5 + 128) >> 8;
-
- return temperature;
-}
-
-
-static u32 bmp280_compensate_P_int32(s32 adc_p)
-{
- s32 v_x1_u32r = 0;
- s32 v_x2_u32r = 0;
- u32 pressure = 0;
-
- v_x1_u32r = (((s32)bmp280.cal_param.t_fine) >> 1) -
- (s32)64000;
- v_x2_u32r = (((v_x1_u32r >> 2) * (v_x1_u32r >> 2)) >> 11) *
- ((s32)bmp280.cal_param.dig_P6);
- v_x2_u32r = v_x2_u32r + ((v_x1_u32r *
- ((s32)bmp280.cal_param.dig_P5)) << 1);
- v_x2_u32r = (v_x2_u32r >> 2) +
- (((s32)bmp280.cal_param.dig_P4) << 16);
- v_x1_u32r = (((bmp280.cal_param.dig_P3 * (((v_x1_u32r >> 2) *
- (v_x1_u32r >> 2)) >> 13)) >> 3) +
- ((((s32)bmp280.cal_param.dig_P2) *
- v_x1_u32r) >> 1)) >> 18;
- v_x1_u32r = ((((32768+v_x1_u32r)) *
- ((s32)bmp280.cal_param.dig_P1)) >> 15);
- /* Avoid exception caused by division by zero */
- if (v_x1_u32r == 0)
- return 0;
- pressure = (((u32)(((s32)1048576) - adc_p) -
- (v_x2_u32r >> 12))) * 3125;
- if (pressure < 0x80000000)
- pressure = (pressure << 1) / ((u32)v_x1_u32r);
- else
- pressure = (pressure / (u32)v_x1_u32r) * 2;
- v_x1_u32r = (((s32)bmp280.cal_param.dig_P9) *
- ((s32)(((pressure >> 3) * (pressure >> 3)) >> 13)))
- >> 12;
- v_x2_u32r = (((s32)(pressure >> 2)) *
- ((s32)bmp280.cal_param.dig_P8)) >> 13;
- pressure = (u32)((s32)pressure +
- ((v_x1_u32r + v_x2_u32r + bmp280.cal_param.dig_P7) >> 4));
-
- return pressure;
-}
-
-static int inv_bmp280_read_data(struct inv_mpu_state *st, short *o)
-{
- int r, i;
- u8 d[BMP280_DATA_BYTES_9911], reg_addr;
- s32 upressure, utemperature;
-
- if (st->chip_config.dmp_on) {
- for (i = 0; i < 6; i++)
- d[i] = st->fifo_data[i];
- } else {
- if (st->sensor[SENSOR_COMPASS].on) {
- if (COMPASS_ID_AK09911 == st->plat_data.sec_slave_id)
- reg_addr = REG_EXT_SENS_DATA_09;
- else
- reg_addr = REG_EXT_SENS_DATA_08;
- } else {
- reg_addr = REG_EXT_SENS_DATA_00;
- }
- r = inv_i2c_read(st, reg_addr, BMP280_DATA_BYTES_9911, d);
- if (r)
- return r;
- }
- /* pressure */
- upressure = (s32)((((s32)(d[0]))
- << SHIFT_LEFT_12_POSITION) | (((u32)(d[1]))
- << SHIFT_LEFT_4_POSITION) | ((u32)d[2] >>
- SHIFT_RIGHT_4_POSITION));
-
- /* Temperature */
- utemperature = (s32)(((
- (s32) (d[3])) << SHIFT_LEFT_12_POSITION) |
- (((u32)(d[4])) << SHIFT_LEFT_4_POSITION)
- | ((u32)d[5] >> SHIFT_RIGHT_4_POSITION));
-
- bmp280_compensate_T_int32(utemperature);
- r = bmp280_compensate_P_int32(upressure);
- o[0] = 0;
- o[1] = (r >> 16);
- o[2] = (r & 0xffff);
-
- return 0;
-}
-
-static struct inv_mpu_slave slave_bmp280 = {
- .suspend = inv_suspend_bmp280,
- .resume = inv_resume_bmp280,
- .get_scale = inv_read_bmp280_scale,
- .set_scale = inv_write_bmp280_scale,
- .self_test = inv_check_bmp280_self_test,
- .setup = inv_setup_bmp280,
- .read_data = inv_bmp280_read_data,
- .rate_scale = BMP280_RATE_SCALE,
- .min_read_time = DATA_BMP280_MIN_READ_TIME,
-};
-
-int inv_mpu_setup_pressure_slave(struct inv_mpu_state *st)
-{
- switch (st->plat_data.aux_slave_id) {
- case PRESSURE_ID_BMP280:
- st->slave_pressure = &slave_bmp280;
- break;
- default:
- return -EINVAL;
- }
-
- return st->slave_pressure->setup(st);
-}
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_test/Kconfig b/drivers/iio/imu-aosp/inv_mpu6515/inv_test/Kconfig
deleted file mode 100755
index 86c30bd8a63..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_test/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Kconfig for Invensense IIO testing hooks
-#
-
-config INV_TESTING
- boolean "Invensense IIO testing hooks"
- depends on INV_MPU_IIO || INV_AMI306_IIO || INV_YAS530 || INV_HUB_IIO
- default n
- help
- This flag enables display of additional testing information from the
- Invensense IIO drivers.
- It also enables the I2C counters facility to perform IO profiling.
- Some additional sysfs entries will appear when this flag is enabled.
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_test/Makefile b/drivers/iio/imu-aosp/inv_mpu6515/inv_test/Makefile
deleted file mode 100755
index 4f0edd3de90..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_test/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for Invensense IIO testing hooks.
-#
-
-obj-$(CONFIG_INV_TESTING) += inv_counters.o
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_test/inv_counters.c b/drivers/iio/imu-aosp/inv_mpu6515/inv_test/inv_counters.c
deleted file mode 100755
index 3b26ca97284..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_test/inv_counters.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * @file inv_counters.c
- * @brief Exports i2c read write counts through sysfs
- *
- * @version 0.1
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/miscdevice.h>
-#include <linux/err.h>
-#include <linux/sysfs.h>
-#include <linux/kdev_t.h>
-#include <linux/string.h>
-#include <linux/jiffies.h>
-#include <linux/spinlock.h>
-#include <linux/kernel_stat.h>
-
-#include "inv_counters.h"
-
-static int mpu_irq;
-static int accel_irq;
-static int compass_irq;
-
-struct inv_counters {
- uint32_t i2c_tempreads;
- uint32_t i2c_mpureads;
- uint32_t i2c_mpuwrites;
- uint32_t i2c_accelreads;
- uint32_t i2c_accelwrites;
- uint32_t i2c_compassreads;
- uint32_t i2c_compasswrites;
- uint32_t i2c_compassirq;
- uint32_t i2c_accelirq;
-};
-
-static struct inv_counters Counters;
-
-static ssize_t i2c_counters_show(struct class *cls,
- struct class_attribute *attr, char *buf)
-{
- return scnprintf(buf, PAGE_SIZE,
- "%ld.%03ld %u %u %u %u %u %u %u %u %u %u\n",
- jiffies / HZ, ((jiffies % HZ) * (1024 / HZ)),
- mpu_irq ? kstat_irqs(mpu_irq) : 0,
- Counters.i2c_tempreads,
- Counters.i2c_mpureads, Counters.i2c_mpuwrites,
- accel_irq ? kstat_irqs(accel_irq) : Counters.i2c_accelirq,
- Counters.i2c_accelreads, Counters.i2c_accelwrites,
- compass_irq ? kstat_irqs(compass_irq) : Counters.i2c_compassirq,
- Counters.i2c_compassreads, Counters.i2c_compasswrites);
-}
-
-void inv_iio_counters_set_i2cirq(enum irqtype type, int irq)
-{
- switch (type) {
- case IRQ_MPU:
- mpu_irq = irq;
- break;
- case IRQ_ACCEL:
- accel_irq = irq;
- break;
- case IRQ_COMPASS:
- compass_irq = irq;
- break;
- }
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_set_i2cirq);
-
-void inv_iio_counters_tempread(int count)
-{
- Counters.i2c_tempreads += count;
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_tempread);
-
-void inv_iio_counters_mpuread(int count)
-{
- Counters.i2c_mpureads += count;
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_mpuread);
-
-void inv_iio_counters_mpuwrite(int count)
-{
- Counters.i2c_mpuwrites += count;
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_mpuwrite);
-
-void inv_iio_counters_accelread(int count)
-{
- Counters.i2c_accelreads += count;
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_accelread);
-
-void inv_iio_counters_accelwrite(int count)
-{
- Counters.i2c_accelwrites += count;
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_accelwrite);
-
-void inv_iio_counters_compassread(int count)
-{
- Counters.i2c_compassreads += count;
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_compassread);
-
-void inv_iio_counters_compasswrite(int count)
-{
- Counters.i2c_compasswrites += count;
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_compasswrite);
-
-void inv_iio_counters_compassirq(void)
-{
- Counters.i2c_compassirq++;
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_compassirq);
-
-void inv_iio_counters_accelirq(void)
-{
- Counters.i2c_accelirq++;
-}
-EXPORT_SYMBOL_GPL(inv_iio_counters_accelirq);
-
-static struct class_attribute inv_class_attr[] = {
- __ATTR(i2c_counter, S_IRUGO, i2c_counters_show, NULL),
- __ATTR_NULL
-};
-
-static struct class inv_counters_class = {
- .name = "inv_counters",
- .owner = THIS_MODULE,
- .class_attrs = (struct class_attribute *) &inv_class_attr
-};
-
-static int __init inv_counters_init(void)
-{
- memset(&Counters, 0, sizeof(Counters));
-
- return class_register(&inv_counters_class);
-}
-
-static void __exit inv_counters_exit(void)
-{
- class_unregister(&inv_counters_class);
-}
-
-module_init(inv_counters_init);
-module_exit(inv_counters_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("GESL");
-MODULE_DESCRIPTION("inv_counters debug support");
-
diff --git a/drivers/iio/imu-aosp/inv_mpu6515/inv_test/inv_counters.h b/drivers/iio/imu-aosp/inv_mpu6515/inv_test/inv_counters.h
deleted file mode 100755
index d60dac9d97b..00000000000
--- a/drivers/iio/imu-aosp/inv_mpu6515/inv_test/inv_counters.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * @file inv_counters.h
- * @brief Debug file to keep track of various counters for the InvenSense
- * sensor drivers.
- *
- * @version 0.1
- */
-
-#ifndef _INV_COUNTERS_H_
-#define _INV_COUNTERS_H_
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/sysfs.h>
-#include <linux/string.h>
-#include <linux/jiffies.h>
-#include <linux/spinlock.h>
-
-#ifdef CONFIG_INV_TESTING
-
-enum irqtype {
- IRQ_MPU,
- IRQ_ACCEL,
- IRQ_COMPASS
-};
-
-#define INV_I2C_INC_MPUREAD(x) inv_iio_counters_mpuread(x)
-#define INV_I2C_INC_MPUWRITE(x) inv_iio_counters_mpuwrite(x)
-#define INV_I2C_INC_ACCELREAD(x) inv_iio_counters_accelread(x)
-#define INV_I2C_INC_ACCELWRITE(x) inv_iio_counters_accelwrite(x)
-#define INV_I2C_INC_COMPASSREAD(x) inv_iio_counters_compassread(x)
-#define INV_I2C_INC_COMPASSWRITE(x) inv_iio_counters_compasswrite(x)
-
-#define INV_I2C_INC_TEMPREAD(x) inv_iio_counters_tempread(x)
-
-#define INV_I2C_SETIRQ(type, irq) inv_iio_counters_set_i2cirq(type, irq)
-#define INV_I2C_INC_COMPASSIRQ() inv_iio_counters_compassirq()
-#define INV_I2C_INC_ACCELIRQ() inv_iio_counters_accelirq()
-
-void inv_iio_counters_mpuread(int count);
-void inv_iio_counters_mpuwrite(int count);
-void inv_iio_counters_accelread(int count);
-void inv_iio_counters_accelwrite(int count);
-void inv_iio_counters_compassread(int count);
-void inv_iio_counters_compasswrite(int count);
-
-void inv_iio_counters_tempread(int count);
-
-void inv_iio_counters_set_i2cirq(enum irqtype type, int irq);
-void inv_iio_counters_compassirq(void);
-void inv_iio_counters_accelirq(void);
-
-#else
-
-#define INV_I2C_INC_MPUREAD(x)
-#define INV_I2C_INC_MPUWRITE(x)
-#define INV_I2C_INC_ACCELREAD(x)
-#define INV_I2C_INC_ACCELWRITE(x)
-#define INV_I2C_INC_COMPASSREAD(x)
-#define INV_I2C_INC_COMPASSWRITE(x)
-
-#define INV_I2C_INC_TEMPREAD(x)
-
-#define INV_I2C_SETIRQ(type, irq)
-#define INV_I2C_INC_COMPASSIRQ()
-#define INV_I2C_INC_ACCELIRQ()
-
-#endif /* CONFIG_INV_TESTING */
-
-#endif /* _INV_COUNTERS_H_ */
-
diff --git a/drivers/iio/imu-aosp/Kconfig b/drivers/iio/imu/Kconfig
index c332d4918b1..124aa491101 100644
--- a/drivers/iio/imu-aosp/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -38,5 +38,4 @@ config IIO_ADIS_LIB_BUFFER
family.
source "drivers/iio/imu/inv_mpu6050/Kconfig"
-# source "drivers/iio/imu/inv_mpu6515/Kconfig"
-
+source "drivers/iio/imu/st_lsm6ds3/Kconfig"
diff --git a/drivers/iio/imu-aosp/Makefile b/drivers/iio/imu/Makefile
index 2fb21dd4a54..ebbe6001a32 100644
--- a/drivers/iio/imu-aosp/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -13,4 +13,4 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
obj-y += inv_mpu6050/
-obj-y += inv_mpu6515/
+obj-y += st_lsm6ds3/
diff --git a/drivers/iio/imu-aosp/adis.c b/drivers/iio/imu/adis.c
index 911255d41c1..911255d41c1 100644
--- a/drivers/iio/imu-aosp/adis.c
+++ b/drivers/iio/imu/adis.c
diff --git a/drivers/iio/imu-aosp/adis16400.h b/drivers/iio/imu/adis16400.h
index 2f8f9d63238..2f8f9d63238 100644
--- a/drivers/iio/imu-aosp/adis16400.h
+++ b/drivers/iio/imu/adis16400.h
diff --git a/drivers/iio/imu-aosp/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c
index 054c01d6e73..054c01d6e73 100644
--- a/drivers/iio/imu-aosp/adis16400_buffer.c
+++ b/drivers/iio/imu/adis16400_buffer.c
diff --git a/drivers/iio/imu-aosp/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index f60591f0b92..f60591f0b92 100644
--- a/drivers/iio/imu-aosp/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
diff --git a/drivers/iio/imu-aosp/adis16480.c b/drivers/iio/imu/adis16480.c
index b7db3837629..b7db3837629 100644
--- a/drivers/iio/imu-aosp/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
diff --git a/drivers/iio/imu-aosp/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
index 99d8e0b0dd3..99d8e0b0dd3 100644
--- a/drivers/iio/imu-aosp/adis_buffer.c
+++ b/drivers/iio/imu/adis_buffer.c
diff --git a/drivers/iio/imu-aosp/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
index e0017c22bb9..e0017c22bb9 100644
--- a/drivers/iio/imu-aosp/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
diff --git a/drivers/iio/imu-aosp/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
index 361b2328453..361b2328453 100644
--- a/drivers/iio/imu-aosp/inv_mpu6050/Kconfig
+++ b/drivers/iio/imu/inv_mpu6050/Kconfig
diff --git a/drivers/iio/imu-aosp/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile
index 3a677c778af..3a677c778af 100644
--- a/drivers/iio/imu-aosp/inv_mpu6050/Makefile
+++ b/drivers/iio/imu/inv_mpu6050/Makefile
diff --git a/drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index fe4c61e219f..fe4c61e219f 100644
--- a/drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
diff --git a/drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index f38395529a4..f38395529a4 100644
--- a/drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
diff --git a/drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 7da0832f187..7da0832f187 100644
--- a/drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
diff --git a/drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index 03b9372c121..03b9372c121 100644
--- a/drivers/iio/imu-aosp/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
diff --git a/drivers/iio/imu/st_lsm6ds3/Kconfig b/drivers/iio/imu/st_lsm6ds3/Kconfig
new file mode 100644
index 00000000000..cb350b25d12
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6ds3/Kconfig
@@ -0,0 +1,75 @@
+#
+# st-lsm6ds3 drivers for STMicroelectronics combo sensor
+#
+
+config ST_LSM6DS3_IIO
+ tristate "STMicroelectronics LSM6DS3 sensor"
+ depends on (I2C || SPI) && SYSFS
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ This driver supports the STMicroelectronics LSM6DS3 sensor.
+ It is a gyroscope/accelerometer combo device.
+ This driver can be built as a module. The module will be called
+ st-lsm6ds3.
+
+config ST_LSM6DS3_IIO_LIMIT_FIFO
+ int "Limit fifo read lenght (#n byte)"
+ depends on ST_LSM6DS3_IIO
+ range 0 8192
+ default 0
+ help
+ Limit atomic fifo read to #n byte. In some platform i2c/spi read
+ can be limited by software or hardware.
+
+ Set 0 to disable the limit.
+
+config ST_LSM6DS3_IIO_SENSORS_WAKEUP
+ bool "All sensors can wake-up system during suspend"
+ depends on ST_LSM6DS3_IIO
+ default n
+ help
+ If disabled only tilt and significant motion can wake-up system
+ during suspend.
+
+ If enabled all sensors can wake-up system during suspend.
+
+menuconfig ST_LSM6DS3_IIO_MASTER_SUPPORT
+ bool "I2C master controller"
+ depends on I2C && ST_LSM6DS3_IIO
+ default n
+ help
+ Added support for I2C master controller. Supported sensors up
+ to 4.
+
+if ST_LSM6DS3_IIO_MASTER_SUPPORT
+
+config ST_LSM6DS3_ENABLE_INTERNAL_PULLUP
+ bool "Enabled internals pull-up resistors"
+ default y
+
+choice
+ prompt "External sensor 0"
+ default ST_LSM6DS3_IIO_EXT0_LIS3MDL
+ help
+ Choose the external sensor 0 connected to LSM6DS3.
+
+config ST_LSM6DS3_IIO_EXT0_LIS3MDL
+ bool "LIS3MDL"
+config ST_LSM6DS3_IIO_EXT0_AKM09912
+ bool "AKM09912"
+endchoice
+
+choice
+ prompt "External sensor 1"
+ default ST_LSM6DS3_IIO_EXT1_DISABLED
+ help
+ Choose the external sensor 1 connected to LSM6DS3.
+
+config ST_LSM6DS3_IIO_EXT1_DISABLED
+ bool "Disabled"
+config ST_LSM6DS3_IIO_EXT1_LPS22HB
+ bool "LPS22HB"
+endchoice
+
+endif
diff --git a/drivers/iio/imu/st_lsm6ds3/Makefile b/drivers/iio/imu/st_lsm6ds3/Makefile
new file mode 100644
index 00000000000..36348a34e89
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6ds3/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for STMicroelectronics LSM6DS3 sensor.
+#
+
+obj-$(CONFIG_ST_LSM6DS3_IIO) += st_lsm6ds3.o
+st_lsm6ds3-objs := st_lsm6ds3_core.o
+
+obj-$(CONFIG_ST_LSM6DS3_IIO) += st_lsm6ds3_spi.o st_lsm6ds3_i2c.o
+st_lsm6ds3-$(CONFIG_IIO_BUFFER) += st_lsm6ds3_buffer.o
+st_lsm6ds3-$(CONFIG_IIO_TRIGGER) += st_lsm6ds3_trigger.o
+st_lsm6ds3-$(CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT) += st_lsm6ds3_i2c_master.o
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3.h b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3.h
new file mode 100644
index 00000000000..78fbf76f4c2
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3.h
@@ -0,0 +1,280 @@
+/*
+ * STMicroelectronics lsm6ds3 driver
+ *
+ * Copyright 2014 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ * v. 2.1.2
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_LSM6DS3_H
+#define ST_LSM6DS3_H
+
+#include <linux/types.h>
+#include <linux/iio/trigger.h>
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+#include <linux/i2c.h>
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+#define LSM6DS3_DEV_NAME "lsm6ds3"
+
+#define ST_INDIO_DEV_ACCEL 0
+#define ST_INDIO_DEV_GYRO 1
+#define ST_INDIO_DEV_SIGN_MOTION 2
+#define ST_INDIO_DEV_STEP_COUNTER 3
+#define ST_INDIO_DEV_STEP_DETECTOR 4
+#define ST_INDIO_DEV_TILT 5
+#define ST_INDIO_DEV_NUM 6
+
+#define ST_INDIO_DEV_EXT0 ST_INDIO_DEV_NUM
+#define ST_INDIO_DEV_EXT1 (ST_INDIO_DEV_NUM + 1)
+
+#define ST_LSM6DS3_ACCEL_DEPENDENCY ((1 << ST_INDIO_DEV_ACCEL) | \
+ (1 << ST_INDIO_DEV_STEP_COUNTER) | \
+ (1 << ST_INDIO_DEV_TILT) | \
+ (1 << ST_INDIO_DEV_SIGN_MOTION) | \
+ (1 << ST_INDIO_DEV_STEP_DETECTOR) | \
+ (1 << ST_INDIO_DEV_EXT0) | \
+ (1 << ST_INDIO_DEV_EXT1))
+
+#define ST_LSM6DS3_PEDOMETER_DEPENDENCY ((1 << ST_INDIO_DEV_STEP_COUNTER) | \
+ (1 << ST_INDIO_DEV_STEP_DETECTOR) | \
+ (1 << ST_INDIO_DEV_SIGN_MOTION))
+
+#define ST_LSM6DS3_EXTRA_DEPENDENCY ((1 << ST_INDIO_DEV_STEP_COUNTER) | \
+ (1 << ST_INDIO_DEV_TILT) | \
+ (1 << ST_INDIO_DEV_SIGN_MOTION) | \
+ (1 << ST_INDIO_DEV_STEP_DETECTOR) | \
+ (1 << ST_INDIO_DEV_EXT0) | \
+ (1 << ST_INDIO_DEV_EXT1))
+
+#define ST_LSM6DS3_USE_BUFFER ((1 << ST_INDIO_DEV_ACCEL) | \
+ (1 << ST_INDIO_DEV_GYRO) | \
+ (1 << ST_INDIO_DEV_STEP_COUNTER))
+
+#define ST_LSM6DS3_EXT_SENSORS ((1 << ST_INDIO_DEV_EXT0) | \
+ (1 << ST_INDIO_DEV_EXT1))
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP
+#define ST_LSM6DS3_WAKE_UP_SENSORS ((1 << ST_INDIO_DEV_SIGN_MOTION) | \
+ (1 << ST_INDIO_DEV_TILT))
+#else /* CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP */
+#define ST_LSM6DS3_WAKE_UP_SENSORS ((1 << ST_INDIO_DEV_SIGN_MOTION) | \
+ (1 << ST_INDIO_DEV_TILT) | \
+ (1 << ST_INDIO_DEV_ACCEL) | \
+ (1 << ST_INDIO_DEV_GYRO) | \
+ (1 << ST_INDIO_DEV_STEP_COUNTER) | \
+ (1 << ST_INDIO_DEV_STEP_DETECTOR) | \
+ (1 << ST_INDIO_DEV_EXT0) | \
+ (1 << ST_INDIO_DEV_EXT1))
+#endif /* CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP */
+
+#define ST_LSM6DS3_TX_MAX_LENGTH 12
+#define ST_LSM6DS3_RX_MAX_LENGTH 8193
+
+#define ST_LSM6DS3_BYTE_FOR_CHANNEL 2
+#define ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE 6
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+#define ST_LSM6DS3_NUM_CLIENTS 2
+#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+#define ST_LSM6DS3_NUM_CLIENTS 0
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+#define ST_LSM6DS3_LSM_CHANNELS(device_type, modif, index, mod, \
+ endian, sbits, rbits, addr, s) \
+{ \
+ .type = device_type, \
+ .modified = modif, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .scan_index = index, \
+ .channel2 = mod, \
+ .address = addr, \
+ .scan_type = { \
+ .sign = s, \
+ .realbits = rbits, \
+ .shift = sbits - rbits, \
+ .storagebits = sbits, \
+ .endianness = endian, \
+ }, \
+}
+
+#define ST_LSM6DS3_FIFO_LENGHT() \
+ IIO_DEVICE_ATTR(hw_fifo_lenght, S_IRUGO, \
+ st_lsm6ds3_sysfs_get_hw_fifo_lenght, NULL, 0);
+
+#define ST_LSM6DS3_FIFO_FLUSH() \
+ IIO_DEVICE_ATTR(flush, S_IWUSR, NULL, st_lsm6ds3_sysfs_flush_fifo, 0);
+
+enum fifo_mode {
+ BYPASS = 0,
+ CONTINUOS,
+};
+
+struct st_lsm6ds3_transfer_buffer {
+ struct mutex buf_lock;
+ u8 rx_buf[ST_LSM6DS3_RX_MAX_LENGTH];
+ u8 tx_buf[ST_LSM6DS3_TX_MAX_LENGTH] ____cacheline_aligned;
+};
+
+struct lsm6ds3_data {
+ const char *name;
+
+ bool reset_steps;
+ bool sign_motion_event_ready;
+
+ u8 *fifo_data;
+ u8 sensors_enabled;
+ u8 gyro_selftest_status;
+ u8 accel_selftest_status;
+ u8 accel_samples_in_pattern;
+ u8 gyro_samples_in_pattern;
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ u8 ext0_samples_in_pattern;
+ u8 ext1_samples_in_pattern;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+ u8 accel_samples_to_discard;
+ u8 gyro_samples_to_discard;
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ u8 ext_samples_to_discard[ST_LSM6DS3_NUM_CLIENTS];
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ u16 fifo_threshold;
+
+ int irq;
+
+ s64 timestamp;
+ int64_t accel_deltatime;
+ int64_t accel_timestamp;
+ int64_t gyro_deltatime;
+ int64_t gyro_timestamp;
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ int64_t ext0_deltatime;
+ int64_t ext0_timestamp;
+ int64_t ext1_deltatime;
+ int64_t ext1_timestamp;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ struct work_struct data_work;
+
+ struct device *dev;
+ struct iio_dev *indio_dev[ST_INDIO_DEV_NUM + ST_LSM6DS3_NUM_CLIENTS];
+ struct iio_trigger *trig[ST_INDIO_DEV_NUM + ST_LSM6DS3_NUM_CLIENTS];
+ struct mutex bank_registers_lock;
+ struct mutex fifo_lock;
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ struct i2c_client *master_client[ST_LSM6DS3_NUM_CLIENTS];
+ struct mutex passthrough_lock;
+ bool ext0_available;
+ bool ext1_available;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ const struct st_lsm6ds3_transfer_function *tf;
+ struct st_lsm6ds3_transfer_buffer tb;
+};
+
+struct st_lsm6ds3_transfer_function {
+ int (*write) (struct lsm6ds3_data *cdata,
+ u8 reg_addr, int len, u8 *data, bool b_lock);
+ int (*read) (struct lsm6ds3_data *cdata,
+ u8 reg_addr, int len, u8 *data, bool b_lock);
+};
+
+struct lsm6ds3_sensor_data {
+ struct lsm6ds3_data *cdata;
+
+ unsigned int c_odr;
+ unsigned int c_gain[3];
+
+ u8 num_data_channels;
+ u8 sindex;
+ u8 *buffer_data;
+};
+
+int st_lsm6ds3_write_data_with_mask(struct lsm6ds3_data *cdata,
+ u8 reg_addr, u8 mask, u8 data, bool b_lock);
+
+int st_lsm6ds3_common_probe(struct lsm6ds3_data *cdata, int irq);
+void st_lsm6ds3_common_remove(struct lsm6ds3_data *cdata, int irq);
+
+int st_lsm6ds3_set_enable(struct lsm6ds3_sensor_data *sdata, bool enable);
+int st_lsm6ds3_set_axis_enable(struct lsm6ds3_sensor_data *sdata, u8 value);
+int st_lsm6ds3_set_drdy_irq(struct lsm6ds3_sensor_data *sdata, bool state);
+int st_lsm6ds3_set_fifo_mode(struct lsm6ds3_data *cdata, enum fifo_mode fm);
+int st_lsm6ds3_reconfigure_fifo(struct lsm6ds3_data *cdata,
+ bool disable_irq_and_flush);
+
+ssize_t st_lsm6ds3_sysfs_get_hw_fifo_lenght(struct device *dev,
+ struct device_attribute *attr, char *buf);
+ssize_t st_lsm6ds3_sysfs_flush_fifo(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size);
+
+#ifdef CONFIG_IIO_BUFFER
+int st_lsm6ds3_allocate_rings(struct lsm6ds3_data *cdata);
+void st_lsm6ds3_deallocate_rings(struct lsm6ds3_data *cdata);
+int st_lsm6ds3_trig_set_state(struct iio_trigger *trig, bool state);
+void st_lsm6ds3_read_fifo(struct lsm6ds3_data *cdata, bool check_fifo_len);
+int st_lsm6ds3_set_fifo_decimators_and_threshold(struct lsm6ds3_data *cdata);
+#define ST_LSM6DS3_TRIGGER_SET_STATE (&st_lsm6ds3_trig_set_state)
+#else /* CONFIG_IIO_BUFFER */
+static inline int st_lsm6ds3_allocate_rings(struct lsm6ds3_data *cdata)
+{
+ return 0;
+}
+static inline void st_lsm6ds3_deallocate_rings(struct lsm6ds3_data *cdata)
+{
+}
+#define ST_LSM6DS3_TRIGGER_SET_STATE NULL
+#endif /* CONFIG_IIO_BUFFER */
+
+#ifdef CONFIG_IIO_TRIGGER
+void st_lsm6ds3_flush_works(void);
+int st_lsm6ds3_allocate_triggers(struct lsm6ds3_data *cdata,
+ const struct iio_trigger_ops *trigger_ops);
+
+void st_lsm6ds3_deallocate_triggers(struct lsm6ds3_data *cdata);
+
+#else /* CONFIG_IIO_TRIGGER */
+static inline int st_lsm6ds3_allocate_triggers(struct lsm6ds3_data *cdata,
+ const struct iio_trigger_ops *trigger_ops, int irq)
+{
+ return 0;
+}
+static inline void st_lsm6ds3_deallocate_triggers(struct lsm6ds3_data *cdata,
+ int irq)
+{
+ return;
+}
+static inline void st_lsm6ds3_flush_works()
+{
+ return;
+}
+#endif /* CONFIG_IIO_TRIGGER */
+
+#ifdef CONFIG_PM
+int st_lsm6ds3_common_suspend(struct lsm6ds3_data *cdata);
+int st_lsm6ds3_common_resume(struct lsm6ds3_data *cdata);
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+int st_lsm6ds3_i2c_master_probe(struct lsm6ds3_data *cdata);
+int st_lsm6ds3_i2c_master_exit(struct lsm6ds3_data *cdata);
+int st_lsm6ds3_enable_passthrough(struct lsm6ds3_data *cdata, bool enable);
+int st_lsm6ds3_enable_accel_dependency(struct lsm6ds3_sensor_data *sdata,
+ bool enable);
+#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+static inline int st_lsm6ds3_i2c_master_probe(struct lsm6ds3_data *cdata)
+{
+ return 0;
+}
+static inline int st_lsm6ds3_i2c_master_exit(struct lsm6ds3_data *cdata)
+{
+ return 0;
+}
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+#endif /* ST_LSM6DS3_H */
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_buffer.c b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_buffer.c
new file mode 100644
index 00000000000..8a7cc5176c2
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_buffer.c
@@ -0,0 +1,448 @@
+/*
+ * STMicroelectronics lsm6ds3 buffer driver
+ *
+ * Copyright 2014 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include "st_lsm6ds3.h"
+
+#define ST_LSM6DS3_ENABLE_AXIS 0x07
+#define ST_LSM6DS3_FIFO_DIFF_L 0x3a
+#define ST_LSM6DS3_FIFO_DIFF_MASK 0x0fff
+#define ST_LSM6DS3_FIFO_DATA_OUT_L 0x3e
+#define ST_LSM6DS3_FIFO_DATA_OVR_2REGS 0x4000
+
+static void st_lsm6ds3_push_data_with_timestamp(struct lsm6ds3_data *cdata,
+ u8 index, u8 *data, int64_t timestamp)
+{
+ int i, n = 0;
+ struct iio_chan_spec const *chs = cdata->indio_dev[index]->channels;
+ uint16_t bfch, bfchs_out = 0, bfchs_in = 0;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(cdata->indio_dev[index]);
+
+ for (i = 0; i < sdata->num_data_channels; i++) {
+ bfch = chs[i].scan_type.storagebits >> 3;
+
+ if (test_bit(i, cdata->indio_dev[index]->active_scan_mask)) {
+ memcpy(&sdata->buffer_data[bfchs_out],
+ &data[bfchs_in], bfch);
+ n++;
+ bfchs_out += bfch;
+ }
+
+ bfchs_in += bfch;
+ }
+
+ if (cdata->indio_dev[index]->scan_timestamp)
+ *(s64 *)((u8 *)sdata->buffer_data +
+ ALIGN(bfchs_out, sizeof(s64))) = timestamp;
+
+ iio_push_to_buffers(cdata->indio_dev[index], sdata->buffer_data);
+}
+
+static void st_lsm6ds3_parse_fifo_data(struct lsm6ds3_data *cdata, u16 read_len)
+{
+ u16 fifo_offset = 0;
+ u8 gyro_sip, accel_sip;
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ u8 ext0_sip, ext1_sip;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ while (fifo_offset < read_len) {
+ gyro_sip = cdata->gyro_samples_in_pattern;
+ accel_sip = cdata->accel_samples_in_pattern;
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ ext0_sip = cdata->ext0_samples_in_pattern;
+ ext1_sip = cdata->ext1_samples_in_pattern;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ do {
+ if (gyro_sip > 0) {
+ if (cdata->gyro_samples_to_discard > 0)
+ cdata->gyro_samples_to_discard--;
+ else {
+ st_lsm6ds3_push_data_with_timestamp(
+ cdata, ST_INDIO_DEV_GYRO,
+ &cdata->fifo_data[fifo_offset],
+ cdata->gyro_timestamp);
+ }
+
+ cdata->gyro_timestamp += cdata->gyro_deltatime;
+ fifo_offset += ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE;
+ gyro_sip--;
+ }
+
+ if (accel_sip > 0) {
+ if (cdata->accel_samples_to_discard > 0)
+ cdata->accel_samples_to_discard--;
+ else {
+ st_lsm6ds3_push_data_with_timestamp(
+ cdata, ST_INDIO_DEV_ACCEL,
+ &cdata->fifo_data[fifo_offset],
+ cdata->accel_timestamp);
+ }
+
+ cdata->accel_timestamp +=
+ cdata->accel_deltatime;
+ fifo_offset += ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE;
+ accel_sip--;
+ }
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ if (ext0_sip > 0) {
+ if (cdata->ext_samples_to_discard[0] > 0)
+ cdata->ext_samples_to_discard[0]--;
+ else {
+ st_lsm6ds3_push_data_with_timestamp(
+ cdata, ST_INDIO_DEV_EXT0,
+ &cdata->fifo_data[fifo_offset],
+ cdata->ext0_timestamp);
+ }
+
+ cdata->ext0_timestamp += cdata->ext0_deltatime;
+ fifo_offset += ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE;
+ ext0_sip--;
+ }
+
+ if (ext1_sip > 0) {
+ if (cdata->ext_samples_to_discard[1] > 0)
+ cdata->ext_samples_to_discard[1]--;
+ else {
+ st_lsm6ds3_push_data_with_timestamp(
+ cdata, ST_INDIO_DEV_EXT1,
+ &cdata->fifo_data[fifo_offset],
+ cdata->ext1_timestamp);
+ }
+
+ cdata->ext1_timestamp += cdata->ext1_deltatime;
+ fifo_offset += ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE;
+ ext1_sip--;
+ }
+
+ } while ((accel_sip > 0) || (gyro_sip > 0) ||
+ (ext0_sip > 0) || (ext1_sip > 0));
+#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+ } while ((accel_sip > 0) || (gyro_sip > 0));
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+ }
+
+ return;
+}
+
+void st_lsm6ds3_read_fifo(struct lsm6ds3_data *cdata, bool check_fifo_len)
+{
+ int err;
+#if (CONFIG_ST_LSM6DS3_IIO_LIMIT_FIFO > 0)
+ u16 data_remaining, data_to_read;
+#endif /* CONFIG_ST_LSM6DS3_IIO_LIMIT_FIFO */
+ u16 read_len = cdata->fifo_threshold, byte_in_pattern;
+
+ if (!cdata->fifo_data)
+ return;
+
+ if (check_fifo_len) {
+ err = cdata->tf->read(cdata, ST_LSM6DS3_FIFO_DIFF_L,
+ 2, (u8 *)&read_len, true);
+ if (err < 0)
+ return;
+
+ if (read_len & ST_LSM6DS3_FIFO_DATA_OVR_2REGS) {
+ dev_err(cdata->dev,
+ "data fifo overrun, failed to read it.\n");
+ return;
+ }
+
+ read_len &= ST_LSM6DS3_FIFO_DIFF_MASK;
+ read_len *= ST_LSM6DS3_BYTE_FOR_CHANNEL;
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ byte_in_pattern = (cdata->accel_samples_in_pattern +
+ cdata->gyro_samples_in_pattern +
+ cdata->ext0_samples_in_pattern +
+ cdata->ext1_samples_in_pattern) *
+ ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE;
+#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+ byte_in_pattern = (cdata->accel_samples_in_pattern +
+ cdata->gyro_samples_in_pattern) *
+ ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ read_len = (read_len / byte_in_pattern) * byte_in_pattern;
+
+ if (read_len > cdata->fifo_threshold)
+ read_len = cdata->fifo_threshold;
+ }
+
+ if (read_len == 0)
+ return;
+
+#if (CONFIG_ST_LSM6DS3_IIO_LIMIT_FIFO == 0)
+ err = cdata->tf->read(cdata, ST_LSM6DS3_FIFO_DATA_OUT_L,
+ read_len, cdata->fifo_data, true);
+ if (err < 0)
+ return;
+#else /* CONFIG_ST_LSM6DS3_IIO_LIMIT_FIFO */
+ data_remaining = read_len;
+
+ do {
+ if (data_remaining > CONFIG_ST_LSM6DS3_IIO_LIMIT_FIFO)
+ data_to_read = CONFIG_ST_LSM6DS3_IIO_LIMIT_FIFO;
+ else
+ data_to_read = data_remaining;
+
+ err = cdata->tf->read(cdata, ST_LSM6DS3_FIFO_DATA_OUT_L,
+ data_to_read, &cdata->fifo_data[read_len - data_remaining], true);
+ if (err < 0)
+ return;
+
+ data_remaining -= data_to_read;
+ } while (data_remaining > 0);
+#endif /* CONFIG_ST_LSM6DS3_IIO_LIMIT_FIFO */
+
+ st_lsm6ds3_parse_fifo_data(cdata, read_len);
+}
+
+static irqreturn_t st_lsm6ds3_step_counter_trigger_handler(int irq, void *p)
+{
+ int err;
+ struct timespec ts;
+ int64_t timestamp = 0;
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ if (!sdata->cdata->reset_steps) {
+ err = sdata->cdata->tf->read(sdata->cdata,
+ (u8)indio_dev->channels[0].address,
+ ST_LSM6DS3_BYTE_FOR_CHANNEL,
+ sdata->buffer_data, true);
+ if (err < 0)
+ goto st_lsm6ds3_step_counter_done;
+
+ timestamp = sdata->cdata->timestamp;
+ } else {
+ memset(sdata->buffer_data, 0, ST_LSM6DS3_BYTE_FOR_CHANNEL);
+ get_monotonic_boottime(&ts);
+ timestamp = timespec_to_ns(&ts);
+ sdata->cdata->reset_steps = false;
+ }
+
+ if (indio_dev->scan_timestamp)
+ *(s64 *)((u8 *)sdata->buffer_data +
+ ALIGN(ST_LSM6DS3_BYTE_FOR_CHANNEL,
+ sizeof(s64))) = timestamp;
+
+ iio_push_to_buffers(indio_dev, sdata->buffer_data);
+
+st_lsm6ds3_step_counter_done:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static inline irqreturn_t st_lsm6ds3_handler_empty(int irq, void *p)
+{
+ return IRQ_HANDLED;
+}
+
+int st_lsm6ds3_trig_set_state(struct iio_trigger *trig, bool state)
+{
+ int err;
+ struct lsm6ds3_sensor_data *sdata;
+
+ sdata = iio_priv(iio_trigger_get_drvdata(trig));
+
+ err = st_lsm6ds3_set_drdy_irq(sdata, state);
+
+ return err < 0 ? err : 0;
+}
+
+static int st_lsm6ds3_buffer_preenable(struct iio_dev *indio_dev)
+{
+ int err;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ err = st_lsm6ds3_set_enable(sdata, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_reconfigure_fifo(sdata->cdata, true);
+ if (err < 0)
+ return err;
+
+ return iio_sw_buffer_preenable(indio_dev);
+}
+
+static int st_lsm6ds3_buffer_postenable(struct iio_dev *indio_dev)
+{
+ int err;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ if ((1 << sdata->sindex) & ST_LSM6DS3_USE_BUFFER) {
+ sdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+ if (sdata->buffer_data == NULL)
+ return -ENOMEM;
+ }
+
+ if ((sdata->sindex == ST_INDIO_DEV_ACCEL) ||
+ (sdata->sindex == ST_INDIO_DEV_GYRO)) {
+ err = st_lsm6ds3_set_axis_enable(sdata,
+ (u8)indio_dev->active_scan_mask[0]);
+ if (err < 0)
+ goto free_buffer_data;
+ }
+
+ err = iio_triggered_buffer_postenable(indio_dev);
+ if (err < 0)
+ goto free_buffer_data;
+
+ if (sdata->sindex == ST_INDIO_DEV_STEP_COUNTER) {
+ iio_trigger_poll_chained(
+ sdata->cdata->trig[ST_INDIO_DEV_STEP_COUNTER], 0);
+ }
+
+ if (sdata->sindex == ST_INDIO_DEV_SIGN_MOTION)
+ sdata->cdata->sign_motion_event_ready = true;
+
+ return 0;
+
+free_buffer_data:
+ if ((1 << sdata->sindex) & ST_LSM6DS3_USE_BUFFER)
+ kfree(sdata->buffer_data);
+
+ return err;
+}
+
+static int st_lsm6ds3_buffer_predisable(struct iio_dev *indio_dev)
+{
+ int err;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ err = iio_triggered_buffer_predisable(indio_dev);
+ if (err < 0)
+ return err;
+
+ if ((sdata->sindex == ST_INDIO_DEV_ACCEL) ||
+ (sdata->sindex == ST_INDIO_DEV_GYRO)) {
+ err = st_lsm6ds3_set_axis_enable(sdata, ST_LSM6DS3_ENABLE_AXIS);
+ if (err < 0)
+ return err;
+ }
+
+ if (sdata->sindex == ST_INDIO_DEV_SIGN_MOTION)
+ sdata->cdata->sign_motion_event_ready = false;
+
+ err = st_lsm6ds3_set_enable(sdata, false);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_reconfigure_fifo(sdata->cdata, true);
+ if (err < 0)
+ return err;
+
+ if ((1 << sdata->sindex) & ST_LSM6DS3_USE_BUFFER)
+ kfree(sdata->buffer_data);
+
+ return 0;
+}
+
+static const struct iio_buffer_setup_ops st_lsm6ds3_buffer_setup_ops = {
+ .preenable = &st_lsm6ds3_buffer_preenable,
+ .postenable = &st_lsm6ds3_buffer_postenable,
+ .predisable = &st_lsm6ds3_buffer_predisable,
+};
+
+int st_lsm6ds3_allocate_rings(struct lsm6ds3_data *cdata)
+{
+ int err;
+
+ err = iio_triggered_buffer_setup(cdata->indio_dev[ST_INDIO_DEV_ACCEL],
+ &st_lsm6ds3_handler_empty, NULL,
+ &st_lsm6ds3_buffer_setup_ops);
+ if (err < 0)
+ return err;
+
+ err = iio_triggered_buffer_setup(cdata->indio_dev[ST_INDIO_DEV_GYRO],
+ &st_lsm6ds3_handler_empty, NULL,
+ &st_lsm6ds3_buffer_setup_ops);
+ if (err < 0)
+ goto buffer_cleanup_accel;
+
+ err = iio_triggered_buffer_setup(
+ cdata->indio_dev[ST_INDIO_DEV_SIGN_MOTION],
+ &st_lsm6ds3_handler_empty, NULL,
+ &st_lsm6ds3_buffer_setup_ops);
+ if (err < 0)
+ goto buffer_cleanup_gyro;
+
+ err = iio_triggered_buffer_setup(
+ cdata->indio_dev[ST_INDIO_DEV_STEP_COUNTER],
+ NULL,
+ &st_lsm6ds3_step_counter_trigger_handler,
+ &st_lsm6ds3_buffer_setup_ops);
+ if (err < 0)
+ goto buffer_cleanup_sign_motion;
+
+ err = iio_triggered_buffer_setup(
+ cdata->indio_dev[ST_INDIO_DEV_STEP_DETECTOR],
+ &st_lsm6ds3_handler_empty, NULL,
+ &st_lsm6ds3_buffer_setup_ops);
+ if (err < 0)
+ goto buffer_cleanup_step_counter;
+
+ err = iio_triggered_buffer_setup(
+ cdata->indio_dev[ST_INDIO_DEV_TILT],
+ &st_lsm6ds3_handler_empty, NULL,
+ &st_lsm6ds3_buffer_setup_ops);
+ if (err < 0)
+ goto buffer_cleanup_step_detector;
+
+ return 0;
+
+buffer_cleanup_step_detector:
+ iio_triggered_buffer_cleanup(
+ cdata->indio_dev[ST_INDIO_DEV_STEP_DETECTOR]);
+buffer_cleanup_step_counter:
+ iio_triggered_buffer_cleanup(
+ cdata->indio_dev[ST_INDIO_DEV_STEP_COUNTER]);
+buffer_cleanup_sign_motion:
+ iio_triggered_buffer_cleanup(
+ cdata->indio_dev[ST_INDIO_DEV_SIGN_MOTION]);
+buffer_cleanup_gyro:
+ iio_triggered_buffer_cleanup(cdata->indio_dev[ST_INDIO_DEV_GYRO]);
+buffer_cleanup_accel:
+ iio_triggered_buffer_cleanup(cdata->indio_dev[ST_INDIO_DEV_ACCEL]);
+ return err;
+}
+
+void st_lsm6ds3_deallocate_rings(struct lsm6ds3_data *cdata)
+{
+ iio_triggered_buffer_cleanup(cdata->indio_dev[ST_INDIO_DEV_TILT]);
+ iio_triggered_buffer_cleanup(
+ cdata->indio_dev[ST_INDIO_DEV_STEP_DETECTOR]);
+ iio_triggered_buffer_cleanup(
+ cdata->indio_dev[ST_INDIO_DEV_STEP_COUNTER]);
+ iio_triggered_buffer_cleanup(
+ cdata->indio_dev[ST_INDIO_DEV_SIGN_MOTION]);
+ iio_triggered_buffer_cleanup(cdata->indio_dev[ST_INDIO_DEV_ACCEL]);
+ iio_triggered_buffer_cleanup(cdata->indio_dev[ST_INDIO_DEV_GYRO]);
+}
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics lsm6ds3 buffer driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_core.c b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_core.c
new file mode 100644
index 00000000000..72881512c1b
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_core.c
@@ -0,0 +1,2137 @@
+/*
+ * STMicroelectronics lsm6ds3 core driver
+ *
+ * Copyright 2014 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/irq.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
+#include <asm/unaligned.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include "st_lsm6ds3.h"
+
+#define MS_TO_NS(msec) ((msec) * 1000 * 1000)
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#define MIN_BNZ(a, b) (((a) < (b)) ? ((a == 0) ? \
+ (b) : (a)) : ((b == 0) ? \
+ (a) : (b)))
+
+/* COMMON VALUES FOR ACCEL-GYRO SENSORS */
+#define ST_LSM6DS3_WAI_ADDRESS 0x0f
+#define ST_LSM6DS3_WAI_EXP 0x69
+#define ST_LSM6DS3_AXIS_EN_MASK 0x38
+#define ST_LSM6DS3_INT1_ADDR 0x0d
+#define ST_LSM6DS3_INT2_ADDR 0x0e
+#define ST_LSM6DS3_MD1_ADDR 0x5e
+#define ST_LSM6DS3_ODR_LIST_NUM 5
+#define ST_LSM6DS3_ODR_POWER_OFF_VAL 0x00
+#define ST_LSM6DS3_ODR_26HZ_VAL 0x02
+#define ST_LSM6DS3_ODR_52HZ_VAL 0x03
+#define ST_LSM6DS3_ODR_104HZ_VAL 0x04
+#define ST_LSM6DS3_ODR_208HZ_VAL 0x05
+#define ST_LSM6DS3_ODR_416HZ_VAL 0x06
+#define ST_LSM6DS3_FS_LIST_NUM 4
+#define ST_LSM6DS3_BDU_ADDR 0x12
+#define ST_LSM6DS3_BDU_MASK 0x40
+#define ST_LSM6DS3_EN_BIT 0x01
+#define ST_LSM6DS3_DIS_BIT 0x00
+#define ST_LSM6DS3_FUNC_EN_ADDR 0x19
+#define ST_LSM6DS3_FUNC_EN_MASK 0x04
+#define ST_LSM6DS3_FUNC_CFG_ACCESS_ADDR 0x01
+#define ST_LSM6DS3_FUNC_CFG_ACCESS_MASK 0x01
+#define ST_LSM6DS3_FUNC_CFG_ACCESS_MASK2 0x04
+#define ST_LSM6DS3_FUNC_CFG_REG2_MASK 0x80
+#define ST_LSM6DS3_FUNC_CFG_START1_ADDR 0x62
+#define ST_LSM6DS3_FUNC_CFG_START2_ADDR 0x63
+#define ST_LSM6DS3_PASS_THROUGH_MODE_ADDR 0x1a
+#define ST_LSM6DS3_PASS_THROUGH_MODE_MASK 0x04
+#define ST_LSM6DS3_INTER_PULLUP_ADDR 0x1a
+#define ST_LSM6DS3_INTER_PULLUP_MASK 0x08
+#define ST_LSM6DS3_SENSORHUB_ADDR 0x1a
+#define ST_LSM6DS3_SENSORHUB_MASK 0x01
+#define ST_LSM6DS3_STARTCONFIG_ADDR 0x1a
+#define ST_LSM6DS3_STARTCONFIG_MASK 0x10
+#define ST_LSM6DS3_SELFTEST_ADDR 0x14
+#define ST_LSM6DS3_SELFTEST_ACCEL_MASK 0x03
+#define ST_LSM6DS3_SELFTEST_GYRO_MASK 0x0c
+#define ST_LSM6DS3_SELF_TEST_DISABLED_VAL 0x00
+#define ST_LSM6DS3_SELF_TEST_POS_SIGN_VAL 0x01
+#define ST_LSM6DS3_SELF_TEST_NEG_ACCEL_SIGN_VAL 0x02
+#define ST_LSM6DS3_SELF_TEST_NEG_GYRO_SIGN_VAL 0x03
+#define ST_LSM6DS3_LIR_ADDR 0x58
+#define ST_LSM6DS3_LIR_MASK 0x01
+#define ST_LSM6DS3_TIMER_EN_ADDR 0x58
+#define ST_LSM6DS3_TIMER_EN_MASK 0x80
+#define ST_LSM6DS3_PEDOMETER_EN_ADDR 0x58
+#define ST_LSM6DS3_PEDOMETER_EN_MASK 0x40
+#define ST_LSM6DS3_INT2_ON_INT1_ADDR 0x13
+#define ST_LSM6DS3_INT2_ON_INT1_MASK 0x20
+#define ST_LSM6DS3_MIN_DURATION_MS 1638
+#define ST_LSM6DS3_ROUNDING_ADDR 0x16
+#define ST_LSM6DS3_ROUNDING_MASK 0x04
+#define ST_LSM6DS3_FIFO_MODE_ADDR 0x0a
+#define ST_LSM6DS3_FIFO_MODE_MASK 0x07
+#define ST_LSM6DS3_FIFO_MODE_BYPASS 0x00
+#define ST_LSM6DS3_FIFO_MODE_CONTINUOS 0x06
+#define ST_LSM6DS3_FIFO_THRESHOLD_IRQ_MASK 0x08
+#define ST_LSM6DS3_FIFO_ODR_ADDR 0x0a
+#define ST_LSM6DS3_FIFO_ODR_MASK 0x78
+#define ST_LSM6DS3_FIFO_ODR_MAX 0x08
+#define ST_LSM6DS3_FIFO_ODR_OFF 0x00
+#define ST_LSM6DS3_FIFO_DECIMATOR_ADDR 0x08
+#define ST_LSM6DS3_FIFO_ACCEL_DECIMATOR_MASK 0x07
+#define ST_LSM6DS3_FIFO_GYRO_DECIMATOR_MASK 0x38
+#define ST_LSM6DS3_FIFO_DECIMATOR2_ADDR 0x09
+#define ST_LSM6DS3_FIFO_DS3_DECIMATOR_MASK 0x07
+#define ST_LSM6DS3_FIFO_DS4_DECIMATOR_MASK 0x38
+#define ST_LSM6DS3_FIFO_THR_L_ADDR 0x06
+#define ST_LSM6DS3_FIFO_THR_H_ADDR 0x07
+#define ST_LSM6DS3_FIFO_THR_H_MASK 0x0f
+#define ST_LSM6DS3_FIFO_THR_IRQ_MASK 0x08
+#define ST_LSM6DS3_RESET_ADDR 0x12
+#define ST_LSM6DS3_RESET_MASK 0x01
+#define ST_LSM6DS3_MAX_FIFO_SIZE 8192
+#define ST_LSM6DS3_MAX_FIFO_LENGHT (ST_LSM6DS3_MAX_FIFO_SIZE / \
+ ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE)
+
+/* CUSTOM VALUES FOR ACCEL SENSOR */
+#define ST_LSM6DS3_ACCEL_ODR_ADDR 0x10
+#define ST_LSM6DS3_ACCEL_ODR_MASK 0xf0
+#define ST_LSM6DS3_ACCEL_FS_ADDR 0x10
+#define ST_LSM6DS3_ACCEL_FS_MASK 0x0c
+#define ST_LSM6DS3_ACCEL_FS_2G_VAL 0x00
+#define ST_LSM6DS3_ACCEL_FS_4G_VAL 0x02
+#define ST_LSM6DS3_ACCEL_FS_8G_VAL 0x03
+#define ST_LSM6DS3_ACCEL_FS_16G_VAL 0x01
+#define ST_LSM6DS3_ACCEL_FS_2G_GAIN IIO_G_TO_M_S_2(61)
+#define ST_LSM6DS3_ACCEL_FS_4G_GAIN IIO_G_TO_M_S_2(122)
+#define ST_LSM6DS3_ACCEL_FS_8G_GAIN IIO_G_TO_M_S_2(244)
+#define ST_LSM6DS3_ACCEL_FS_16G_GAIN IIO_G_TO_M_S_2(488)
+#define ST_LSM6DS3_ACCEL_OUT_X_L_ADDR 0x28
+#define ST_LSM6DS3_ACCEL_OUT_Y_L_ADDR 0x2a
+#define ST_LSM6DS3_ACCEL_OUT_Z_L_ADDR 0x2c
+#define ST_LSM6DS3_ACCEL_AXIS_EN_ADDR 0x18
+#define ST_LSM6DS3_ACCEL_STD 3
+
+/* CUSTOM VALUES FOR GYRO SENSOR */
+#define ST_LSM6DS3_GYRO_ODR_ADDR 0x11
+#define ST_LSM6DS3_GYRO_ODR_MASK 0xf0
+#define ST_LSM6DS3_GYRO_FS_ADDR 0x11
+#define ST_LSM6DS3_GYRO_FS_MASK 0x0c
+#define ST_LSM6DS3_GYRO_FS_245_VAL 0x00
+#define ST_LSM6DS3_GYRO_FS_500_VAL 0x01
+#define ST_LSM6DS3_GYRO_FS_1000_VAL 0x02
+#define ST_LSM6DS3_GYRO_FS_2000_VAL 0x03
+#define ST_LSM6DS3_GYRO_FS_245_GAIN IIO_DEGREE_TO_RAD(4375)
+#define ST_LSM6DS3_GYRO_FS_500_GAIN IIO_DEGREE_TO_RAD(8750)
+#define ST_LSM6DS3_GYRO_FS_1000_GAIN IIO_DEGREE_TO_RAD(17500)
+#define ST_LSM6DS3_GYRO_FS_2000_GAIN IIO_DEGREE_TO_RAD(70000)
+#define ST_LSM6DS3_GYRO_OUT_X_L_ADDR 0x22
+#define ST_LSM6DS3_GYRO_OUT_Y_L_ADDR 0x24
+#define ST_LSM6DS3_GYRO_OUT_Z_L_ADDR 0x26
+#define ST_LSM6DS3_GYRO_AXIS_EN_ADDR 0x19
+#define ST_LSM6DS3_GYRO_STD 6
+
+/* CUSTOM VALUES FOR SIGNIFICANT MOTION SENSOR */
+#define ST_LSM6DS3_SIGN_MOTION_EN_ADDR 0x19
+#define ST_LSM6DS3_SIGN_MOTION_EN_MASK 0x01
+
+/* CUSTOM VALUES FOR STEP DETECTOR SENSOR */
+#define ST_LSM6DS3_STEP_DETECTOR_DRDY_IRQ_MASK 0x80
+
+/* CUSTOM VALUES FOR STEP COUNTER SENSOR */
+#define ST_LSM6DS3_STEP_COUNTER_DRDY_IRQ_MASK 0x80
+#define ST_LSM6DS3_STEP_COUNTER_OUT_L_ADDR 0x4b
+#define ST_LSM6DS3_STEP_COUNTER_RES_ADDR 0x19
+#define ST_LSM6DS3_STEP_COUNTER_RES_MASK 0x06
+#define ST_LSM6DS3_STEP_COUNTER_RES_ALL_EN 0x03
+#define ST_LSM6DS3_STEP_COUNTER_RES_FUNC_EN 0x02
+#define ST_LSM6DS3_STEP_COUNTER_DURATION_ADDR 0x15
+
+/* CUSTOM VALUES FOR TILT SENSOR */
+#define ST_LSM6DS3_TILT_EN_ADDR 0x58
+#define ST_LSM6DS3_TILT_EN_MASK 0x20
+#define ST_LSM6DS3_TILT_DRDY_IRQ_MASK 0x02
+
+#define ST_LSM6DS3_ACCEL_SUFFIX_NAME "accel"
+#define ST_LSM6DS3_GYRO_SUFFIX_NAME "gyro"
+#define ST_LSM6DS3_STEP_COUNTER_SUFFIX_NAME "step_c"
+#define ST_LSM6DS3_STEP_DETECTOR_SUFFIX_NAME "step_d"
+#define ST_LSM6DS3_SIGN_MOTION_SUFFIX_NAME "sign_motion"
+#define ST_LSM6DS3_TILT_SUFFIX_NAME "tilt"
+
+#define ST_LSM6DS3_DEV_ATTR_SAMP_FREQ() \
+ IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, \
+ st_lsm6ds3_sysfs_get_sampling_frequency, \
+ st_lsm6ds3_sysfs_set_sampling_frequency)
+
+#define ST_LSM6DS3_DEV_ATTR_SAMP_FREQ_AVAIL() \
+ IIO_DEV_ATTR_SAMP_FREQ_AVAIL( \
+ st_lsm6ds3_sysfs_sampling_frequency_avail)
+
+#define ST_LSM6DS3_DEV_ATTR_SCALE_AVAIL(name) \
+ IIO_DEVICE_ATTR(name, S_IRUGO, \
+ st_lsm6ds3_sysfs_scale_avail, NULL , 0);
+
+static struct st_lsm6ds3_selftest_table {
+ char *string_mode;
+ u8 accel_value;
+ u8 gyro_value;
+ u8 accel_mask;
+ u8 gyro_mask;
+} st_lsm6ds3_selftest_table[] = {
+ [0] = {
+ .string_mode = "disabled",
+ .accel_value = ST_LSM6DS3_SELF_TEST_DISABLED_VAL,
+ .gyro_value = ST_LSM6DS3_SELF_TEST_DISABLED_VAL,
+ },
+ [1] = {
+ .string_mode = "positive-sign",
+ .accel_value = ST_LSM6DS3_SELF_TEST_POS_SIGN_VAL,
+ .gyro_value = ST_LSM6DS3_SELF_TEST_POS_SIGN_VAL
+ },
+ [2] = {
+ .string_mode = "negative-sign",
+ .accel_value = ST_LSM6DS3_SELF_TEST_NEG_ACCEL_SIGN_VAL,
+ .gyro_value = ST_LSM6DS3_SELF_TEST_NEG_GYRO_SIGN_VAL
+ },
+};
+
+struct st_lsm6ds3_odr_reg {
+ unsigned int hz;
+ u8 value;
+};
+
+static struct st_lsm6ds3_odr_table {
+ u8 addr[2];
+ u8 mask[2];
+ struct st_lsm6ds3_odr_reg odr_avl[ST_LSM6DS3_ODR_LIST_NUM];
+} st_lsm6ds3_odr_table = {
+ .addr[ST_INDIO_DEV_ACCEL] = ST_LSM6DS3_ACCEL_ODR_ADDR,
+ .mask[ST_INDIO_DEV_ACCEL] = ST_LSM6DS3_ACCEL_ODR_MASK,
+ .addr[ST_INDIO_DEV_GYRO] = ST_LSM6DS3_GYRO_ODR_ADDR,
+ .mask[ST_INDIO_DEV_GYRO] = ST_LSM6DS3_GYRO_ODR_MASK,
+ .odr_avl[0] = { .hz = 26, .value = ST_LSM6DS3_ODR_26HZ_VAL },
+ .odr_avl[1] = { .hz = 52, .value = ST_LSM6DS3_ODR_52HZ_VAL },
+ .odr_avl[2] = { .hz = 104, .value = ST_LSM6DS3_ODR_104HZ_VAL },
+ .odr_avl[3] = { .hz = 208, .value = ST_LSM6DS3_ODR_208HZ_VAL },
+ .odr_avl[4] = { .hz = 416, .value = ST_LSM6DS3_ODR_416HZ_VAL },
+};
+
+struct st_lsm6ds3_fs_reg {
+ unsigned int gain;
+ u8 value;
+};
+
+static struct st_lsm6ds3_fs_table {
+ u8 addr;
+ u8 mask;
+ struct st_lsm6ds3_fs_reg fs_avl[ST_LSM6DS3_FS_LIST_NUM];
+} st_lsm6ds3_fs_table[ST_INDIO_DEV_NUM] = {
+ [ST_INDIO_DEV_ACCEL] = {
+ .addr = ST_LSM6DS3_ACCEL_FS_ADDR,
+ .mask = ST_LSM6DS3_ACCEL_FS_MASK,
+ .fs_avl[0] = { .gain = ST_LSM6DS3_ACCEL_FS_2G_GAIN,
+ .value = ST_LSM6DS3_ACCEL_FS_2G_VAL },
+ .fs_avl[1] = { .gain = ST_LSM6DS3_ACCEL_FS_4G_GAIN,
+ .value = ST_LSM6DS3_ACCEL_FS_4G_VAL },
+ .fs_avl[2] = { .gain = ST_LSM6DS3_ACCEL_FS_8G_GAIN,
+ .value = ST_LSM6DS3_ACCEL_FS_8G_VAL },
+ .fs_avl[3] = { .gain = ST_LSM6DS3_ACCEL_FS_16G_GAIN,
+ .value = ST_LSM6DS3_ACCEL_FS_16G_VAL },
+ },
+ [ST_INDIO_DEV_GYRO] = {
+ .addr = ST_LSM6DS3_GYRO_FS_ADDR,
+ .mask = ST_LSM6DS3_GYRO_FS_MASK,
+ .fs_avl[0] = { .gain = ST_LSM6DS3_GYRO_FS_245_GAIN,
+ .value = ST_LSM6DS3_GYRO_FS_245_VAL },
+ .fs_avl[1] = { .gain = ST_LSM6DS3_GYRO_FS_500_GAIN,
+ .value = ST_LSM6DS3_GYRO_FS_500_VAL },
+ .fs_avl[2] = { .gain = ST_LSM6DS3_GYRO_FS_1000_GAIN,
+ .value = ST_LSM6DS3_GYRO_FS_1000_VAL },
+ .fs_avl[3] = { .gain = ST_LSM6DS3_GYRO_FS_2000_GAIN,
+ .value = ST_LSM6DS3_GYRO_FS_2000_VAL },
+ }
+};
+
+static const struct iio_chan_spec st_lsm6ds3_accel_ch[] = {
+ ST_LSM6DS3_LSM_CHANNELS(IIO_ACCEL, 1, 0, IIO_MOD_X, IIO_LE,
+ 16, 16, ST_LSM6DS3_ACCEL_OUT_X_L_ADDR, 's'),
+ ST_LSM6DS3_LSM_CHANNELS(IIO_ACCEL, 1, 1, IIO_MOD_Y, IIO_LE,
+ 16, 16, ST_LSM6DS3_ACCEL_OUT_Y_L_ADDR, 's'),
+ ST_LSM6DS3_LSM_CHANNELS(IIO_ACCEL, 1, 2, IIO_MOD_Z, IIO_LE,
+ 16, 16, ST_LSM6DS3_ACCEL_OUT_Z_L_ADDR, 's'),
+ IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
+static const struct iio_chan_spec st_lsm6ds3_gyro_ch[] = {
+ ST_LSM6DS3_LSM_CHANNELS(IIO_ANGL_VEL, 1, 0, IIO_MOD_X, IIO_LE,
+ 16, 16, ST_LSM6DS3_GYRO_OUT_X_L_ADDR, 's'),
+ ST_LSM6DS3_LSM_CHANNELS(IIO_ANGL_VEL, 1, 1, IIO_MOD_Y, IIO_LE,
+ 16, 16, ST_LSM6DS3_GYRO_OUT_Y_L_ADDR, 's'),
+ ST_LSM6DS3_LSM_CHANNELS(IIO_ANGL_VEL, 1, 2, IIO_MOD_Z, IIO_LE,
+ 16, 16, ST_LSM6DS3_GYRO_OUT_Z_L_ADDR, 's'),
+ IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
+static const struct iio_chan_spec st_lsm6ds3_sign_motion_ch[] = {
+ {
+ .type = IIO_SIGN_MOTION,
+ .channel = 0,
+ .modified = 0,
+ .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1)
+};
+
+static const struct iio_chan_spec st_lsm6ds3_step_c_ch[] = {
+ {
+ .type = IIO_STEP_COUNTER,
+ .modified = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .address = ST_LSM6DS3_STEP_COUNTER_OUT_L_ADDR,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1)
+};
+
+static const struct iio_chan_spec st_lsm6ds3_step_d_ch[] = {
+ {
+ .type = IIO_STEP_DETECTOR,
+ .channel = 0,
+ .modified = 0,
+ .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1)
+};
+
+static const struct iio_chan_spec st_lsm6ds3_tilt_ch[] = {
+ {
+ .type = IIO_TILT,
+ .channel = 0,
+ .modified = 0,
+ .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1)
+};
+
+int st_lsm6ds3_write_data_with_mask(struct lsm6ds3_data *cdata,
+ u8 reg_addr, u8 mask, u8 data, bool b_lock)
+{
+ int err;
+ u8 new_data = 0x00, old_data = 0x00;
+
+ err = cdata->tf->read(cdata, reg_addr, 1, &old_data, b_lock);
+ if (err < 0)
+ return err;
+
+ new_data = ((old_data & (~mask)) | ((data << __ffs(mask)) & mask));
+
+ if (new_data == old_data)
+ return 1;
+
+ return cdata->tf->write(cdata, reg_addr, 1, &new_data, b_lock);
+}
+EXPORT_SYMBOL(st_lsm6ds3_write_data_with_mask);
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+static int st_lsm6ds3_enable_sensor_hub(struct lsm6ds3_data *cdata, bool enable)
+{
+ int err;
+
+ if (enable) {
+ if (cdata->sensors_enabled & ST_LSM6DS3_EXT_SENSORS) {
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_STARTCONFIG_ADDR,
+ ST_LSM6DS3_STARTCONFIG_MASK,
+ ST_LSM6DS3_DIS_BIT, true);
+ if (err < 0)
+ return err;
+ }
+
+ if (cdata->sensors_enabled & ST_LSM6DS3_EXTRA_DEPENDENCY) {
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_FUNC_EN_ADDR,
+ ST_LSM6DS3_FUNC_EN_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+ }
+
+ if (cdata->sensors_enabled & ST_LSM6DS3_EXT_SENSORS) {
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_SENSORHUB_ADDR,
+ ST_LSM6DS3_SENSORHUB_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+ }
+ } else {
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_STARTCONFIG_ADDR,
+ ST_LSM6DS3_STARTCONFIG_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+
+ usleep_range(1500, 4000);
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_SENSORHUB_ADDR,
+ ST_LSM6DS3_SENSORHUB_MASK,
+ ST_LSM6DS3_DIS_BIT, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_FUNC_EN_ADDR,
+ ST_LSM6DS3_FUNC_EN_MASK,
+ ST_LSM6DS3_DIS_BIT, true);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+int st_lsm6ds3_enable_passthrough(struct lsm6ds3_data *cdata, bool enable)
+{
+ int err;
+ u8 reg_value;
+
+ if (enable)
+ reg_value = ST_LSM6DS3_EN_BIT;
+ else
+ reg_value = ST_LSM6DS3_DIS_BIT;
+
+ if (enable) {
+ err = st_lsm6ds3_enable_sensor_hub(cdata, false);
+ if (err < 0)
+ return err;
+
+#ifdef CONFIG_ST_LSM6DS3_ENABLE_INTERNAL_PULLUP
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_INTER_PULLUP_ADDR,
+ ST_LSM6DS3_INTER_PULLUP_MASK,
+ ST_LSM6DS3_DIS_BIT, true);
+ if (err < 0)
+ return err;
+#endif /* CONFIG_ST_LSM6DS3_ENABLE_INTERNAL_PULLUP */
+ }
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_PASS_THROUGH_MODE_ADDR,
+ ST_LSM6DS3_PASS_THROUGH_MODE_MASK,
+ reg_value, enable);
+ if (err < 0)
+ return err;
+
+ if (!enable) {
+#ifdef CONFIG_ST_LSM6DS3_ENABLE_INTERNAL_PULLUP
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_INTER_PULLUP_ADDR,
+ ST_LSM6DS3_INTER_PULLUP_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+#endif /* CONFIG_ST_LSM6DS3_ENABLE_INTERNAL_PULLUP */
+
+ err = st_lsm6ds3_enable_sensor_hub(cdata, true);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(st_lsm6ds3_enable_passthrough);
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+static int st_lsm6ds3_set_fifo_enable(struct lsm6ds3_data *cdata, bool status)
+{
+ int err;
+ u8 reg_value;
+ struct timespec ts;
+
+ if (status)
+ reg_value = ST_LSM6DS3_FIFO_ODR_MAX;
+ else
+ reg_value = ST_LSM6DS3_FIFO_ODR_OFF;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_FIFO_ODR_ADDR,
+ ST_LSM6DS3_FIFO_ODR_MASK,
+ reg_value, true);
+ if (err < 0)
+ return err;
+
+ get_monotonic_boottime(&ts);
+ cdata->gyro_timestamp = timespec_to_ns(&ts);
+ cdata->accel_timestamp = cdata->gyro_timestamp;
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ cdata->ext0_timestamp = cdata->gyro_timestamp;
+ cdata->ext1_timestamp = cdata->gyro_timestamp;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ return 0;
+}
+
+int st_lsm6ds3_set_fifo_mode(struct lsm6ds3_data *cdata, enum fifo_mode fm)
+{
+ int err;
+ u8 reg_value;
+ bool enable_fifo;
+
+ switch (fm) {
+ case BYPASS:
+ reg_value = ST_LSM6DS3_FIFO_MODE_BYPASS;
+ enable_fifo = false;
+ break;
+ case CONTINUOS:
+ reg_value = ST_LSM6DS3_FIFO_MODE_CONTINUOS;
+ enable_fifo = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = st_lsm6ds3_set_fifo_enable(cdata, enable_fifo);
+ if (err < 0)
+ return err;
+
+ return st_lsm6ds3_write_data_with_mask(cdata, ST_LSM6DS3_FIFO_MODE_ADDR,
+ ST_LSM6DS3_FIFO_MODE_MASK, reg_value, true);
+}
+EXPORT_SYMBOL(st_lsm6ds3_set_fifo_mode);
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+static int st_lsm6ds3_force_accel_odr(struct lsm6ds3_sensor_data *sdata,
+ unsigned int odr)
+{
+ int i;
+
+ for (i = 0; i < ST_LSM6DS3_ODR_LIST_NUM; i++) {
+ if (st_lsm6ds3_odr_table.odr_avl[i].hz == odr)
+ break;
+ }
+ if (i == ST_LSM6DS3_ODR_LIST_NUM)
+ return -EINVAL;
+
+ return st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ st_lsm6ds3_odr_table.addr[sdata->sindex],
+ st_lsm6ds3_odr_table.mask[sdata->sindex],
+ st_lsm6ds3_odr_table.odr_avl[i].value, true);
+}
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+int st_lsm6ds3_set_fifo_decimators_and_threshold(struct lsm6ds3_data *cdata)
+{
+ int err;
+ struct iio_dev *indio_dev;
+ u16 min_num_pattern, max_num_pattern;
+ unsigned int min_odr = 416, max_odr = 0;
+ u8 accel_decimator = 0, gyro_decimator = 0;
+ u16 num_pattern_accel = 0, num_pattern_gyro = 0;
+ struct lsm6ds3_sensor_data *sdata_accel, *sdata_gyro;
+ u16 fifo_len, fifo_threshold, fifo_len_accel = 0, fifo_len_gyro = 0;
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ int i;
+ bool force_accel_odr = false;
+ u8 ext0_decimator = 0, ext1_decimator = 0;
+ u16 num_pattern_ext1 = 0, fifo_len_ext1 = 0;
+ u16 num_pattern_ext0 = 0, fifo_len_ext0 = 0;
+ struct lsm6ds3_sensor_data *sdata_ext0 = NULL, *sdata_ext1 = NULL;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ indio_dev = cdata->indio_dev[ST_INDIO_DEV_ACCEL];
+ sdata_accel = iio_priv(indio_dev);
+ if ((1 << sdata_accel->sindex) & cdata->sensors_enabled) {
+ if (min_odr > sdata_accel->c_odr)
+ min_odr = sdata_accel->c_odr;
+
+ if (max_odr < sdata_accel->c_odr)
+ max_odr = sdata_accel->c_odr;
+
+ fifo_len_accel = (indio_dev->buffer->length / 2);
+ }
+
+ indio_dev = cdata->indio_dev[ST_INDIO_DEV_GYRO];
+ sdata_gyro = iio_priv(indio_dev);
+ if ((1 << sdata_gyro->sindex) & cdata->sensors_enabled) {
+ if (min_odr > sdata_gyro->c_odr)
+ min_odr = sdata_gyro->c_odr;
+
+ if (max_odr < sdata_gyro->c_odr)
+ max_odr = sdata_gyro->c_odr;
+
+ fifo_len_gyro = (indio_dev->buffer->length / 2);
+ }
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ if (cdata->ext0_available) {
+ indio_dev = cdata->indio_dev[ST_INDIO_DEV_EXT0];
+ sdata_ext0 = iio_priv(indio_dev);
+ if ((1 << sdata_ext0->sindex) & cdata->sensors_enabled) {
+ if (min_odr > sdata_ext0->c_odr)
+ min_odr = sdata_ext0->c_odr;
+
+ if (max_odr < sdata_ext0->c_odr) {
+ force_accel_odr = true;
+ max_odr = sdata_ext0->c_odr;
+ }
+
+ fifo_len_ext0 = (indio_dev->buffer->length / 2);
+ }
+ }
+
+ if (cdata->ext1_available) {
+ indio_dev = cdata->indio_dev[ST_INDIO_DEV_EXT1];
+ sdata_ext1 = iio_priv(indio_dev);
+ if ((1 << sdata_ext1->sindex) & cdata->sensors_enabled) {
+ if (min_odr > sdata_ext1->c_odr)
+ min_odr = sdata_ext1->c_odr;
+
+ if (max_odr < sdata_ext1->c_odr) {
+ force_accel_odr = true;
+ max_odr = sdata_ext1->c_odr;
+ }
+
+ fifo_len_ext1 = (indio_dev->buffer->length / 2);
+ }
+ }
+
+ if (force_accel_odr) {
+ err = st_lsm6ds3_force_accel_odr(sdata_accel, max_odr);
+ if (err < 0)
+ return err;
+ } else {
+ for (i = 0; i < ST_LSM6DS3_ODR_LIST_NUM; i++) {
+ if (st_lsm6ds3_odr_table.odr_avl[i].hz ==
+ sdata_accel->c_odr)
+ break;
+ }
+ if (i == ST_LSM6DS3_ODR_LIST_NUM)
+ return -EINVAL;
+
+ if (cdata->sensors_enabled & (1 << sdata_accel->sindex)) {
+ cdata->accel_samples_to_discard = ST_LSM6DS3_ACCEL_STD;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ st_lsm6ds3_odr_table.addr[sdata_accel->sindex],
+ st_lsm6ds3_odr_table.mask[sdata_accel->sindex],
+ st_lsm6ds3_odr_table.odr_avl[i].value, true);
+ if (err < 0)
+ return err;
+ }
+ }
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ if ((1 << sdata_accel->sindex) & cdata->sensors_enabled) {
+ cdata->accel_samples_in_pattern =
+ (sdata_accel->c_odr / min_odr);
+ num_pattern_accel = MAX(fifo_len_accel /
+ cdata->accel_samples_in_pattern, 1);
+ cdata->accel_deltatime = (1000000000ULL / sdata_accel->c_odr);
+ accel_decimator = max_odr / sdata_accel->c_odr;
+ } else
+ cdata->accel_samples_in_pattern = 0;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_FIFO_DECIMATOR_ADDR,
+ ST_LSM6DS3_FIFO_ACCEL_DECIMATOR_MASK,
+ accel_decimator, true);
+ if (err < 0)
+ return err;
+
+ if ((1 << sdata_gyro->sindex) & cdata->sensors_enabled) {
+ cdata->gyro_samples_in_pattern = (sdata_gyro->c_odr / min_odr);
+ num_pattern_gyro = MAX(fifo_len_gyro /
+ cdata->gyro_samples_in_pattern, 1);
+ cdata->gyro_deltatime = (1000000000ULL / sdata_gyro->c_odr);
+ gyro_decimator = max_odr / sdata_gyro->c_odr;
+ } else
+ cdata->gyro_samples_in_pattern = 0;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_FIFO_DECIMATOR_ADDR,
+ ST_LSM6DS3_FIFO_GYRO_DECIMATOR_MASK,
+ gyro_decimator, true);
+ if (err < 0)
+ return err;
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ if (cdata->ext0_available) {
+ if ((1 << sdata_ext0->sindex) & cdata->sensors_enabled) {
+ cdata->ext0_samples_in_pattern =
+ (sdata_ext0->c_odr / min_odr);
+ num_pattern_ext0 = MAX(fifo_len_ext0 /
+ cdata->ext0_samples_in_pattern, 1);
+ cdata->ext0_deltatime =
+ (1000000000ULL / sdata_ext0->c_odr);
+ ext0_decimator = max_odr / sdata_ext0->c_odr;
+ } else
+ cdata->ext0_samples_in_pattern = 0;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_FIFO_DECIMATOR2_ADDR,
+ ST_LSM6DS3_FIFO_DS3_DECIMATOR_MASK,
+ ext0_decimator, true);
+ if (err < 0)
+ return err;
+ }
+
+ if (cdata->ext1_available) {
+ if ((1 << sdata_ext1->sindex) & cdata->sensors_enabled) {
+ cdata->ext1_samples_in_pattern =
+ (sdata_ext1->c_odr / min_odr);
+ num_pattern_ext1 = MAX(fifo_len_ext1 /
+ cdata->ext1_samples_in_pattern, 1);
+ cdata->ext1_deltatime =
+ (1000000000ULL / sdata_ext1->c_odr);
+ ext1_decimator = max_odr / sdata_ext1->c_odr;
+ } else
+ cdata->ext1_samples_in_pattern = 0;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_FIFO_DECIMATOR2_ADDR,
+ ST_LSM6DS3_FIFO_DS4_DECIMATOR_MASK,
+ ext1_decimator, true);
+ if (err < 0)
+ return err;
+ }
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ min_num_pattern = MIN_BNZ(MIN_BNZ(MIN_BNZ(num_pattern_gyro,
+ num_pattern_accel), num_pattern_ext0), num_pattern_ext1);
+#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+ min_num_pattern = MIN_BNZ(num_pattern_gyro, num_pattern_accel);
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ if ((cdata->accel_samples_in_pattern +
+ cdata->gyro_samples_in_pattern +
+ cdata->ext0_samples_in_pattern +
+ cdata->ext1_samples_in_pattern) > 0) {
+ max_num_pattern = ST_LSM6DS3_MAX_FIFO_SIZE /
+ ((cdata->accel_samples_in_pattern +
+ cdata->gyro_samples_in_pattern +
+ cdata->ext0_samples_in_pattern +
+ cdata->ext1_samples_in_pattern) *
+ ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE);
+
+ if (min_num_pattern > max_num_pattern)
+ min_num_pattern = max_num_pattern;
+ }
+
+ fifo_len = (cdata->accel_samples_in_pattern +
+ cdata->gyro_samples_in_pattern +
+ cdata->ext0_samples_in_pattern +
+ cdata->ext1_samples_in_pattern) *
+ min_num_pattern * ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE;
+#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+ if ((cdata->accel_samples_in_pattern +
+ cdata->gyro_samples_in_pattern) > 0) {
+ max_num_pattern = ST_LSM6DS3_MAX_FIFO_SIZE /
+ ((cdata->accel_samples_in_pattern +
+ cdata->gyro_samples_in_pattern) *
+ ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE);
+
+ if (min_num_pattern > max_num_pattern)
+ min_num_pattern = max_num_pattern;
+ }
+
+ fifo_len = (cdata->accel_samples_in_pattern +
+ cdata->gyro_samples_in_pattern) *
+ min_num_pattern * ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ if (fifo_len > 0) {
+ fifo_threshold = fifo_len / 2;
+
+ err = cdata->tf->write(cdata, ST_LSM6DS3_FIFO_THR_L_ADDR,
+ 1, (u8 *)&fifo_threshold, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_FIFO_THR_H_ADDR,
+ ST_LSM6DS3_FIFO_THR_H_MASK,
+ *(((u8 *)&fifo_threshold) + 1), true);
+ if (err < 0)
+ return err;
+
+ cdata->fifo_threshold = fifo_len;
+ }
+ kfree(cdata->fifo_data);
+ cdata->fifo_data = 0;
+
+ if (fifo_len > 0) {
+ cdata->fifo_data = kmalloc(cdata->fifo_threshold, GFP_KERNEL);
+ if (!cdata->fifo_data)
+ return -ENOMEM;
+ }
+
+ return fifo_len;
+}
+EXPORT_SYMBOL(st_lsm6ds3_set_fifo_decimators_and_threshold);
+
+int st_lsm6ds3_reconfigure_fifo(struct lsm6ds3_data *cdata,
+ bool disable_irq_and_flush)
+{
+ int err, fifo_len;
+
+ if (disable_irq_and_flush) {
+ disable_irq(cdata->irq);
+ st_lsm6ds3_flush_works();
+ }
+
+ mutex_lock(&cdata->fifo_lock);
+
+ st_lsm6ds3_read_fifo(cdata, true);
+
+ err = st_lsm6ds3_set_fifo_mode(cdata, BYPASS);
+ if (err < 0)
+ goto reconfigure_fifo_irq_restore;
+
+ fifo_len = st_lsm6ds3_set_fifo_decimators_and_threshold(cdata);
+ if (fifo_len < 0) {
+ err = fifo_len;
+ goto reconfigure_fifo_irq_restore;
+ }
+
+ if (fifo_len > 0) {
+ err = st_lsm6ds3_set_fifo_mode(cdata, CONTINUOS);
+ if (err < 0)
+ goto reconfigure_fifo_irq_restore;
+ }
+
+reconfigure_fifo_irq_restore:
+ mutex_unlock(&cdata->fifo_lock);
+
+ if (disable_irq_and_flush)
+ enable_irq(cdata->irq);
+
+ return err;
+}
+EXPORT_SYMBOL(st_lsm6ds3_reconfigure_fifo);
+
+int st_lsm6ds3_set_drdy_irq(struct lsm6ds3_sensor_data *sdata, bool state)
+{
+ u8 reg_addr, mask, value;
+
+ if (state)
+ value = ST_LSM6DS3_EN_BIT;
+ else
+ value = ST_LSM6DS3_DIS_BIT;
+
+ switch (sdata->sindex) {
+ case ST_INDIO_DEV_ACCEL:
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ if ((sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_GYRO)) ||
+ (sdata->cdata->sensors_enabled &
+ ST_LSM6DS3_EXT_SENSORS))
+ return 0;
+#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+ if (sdata->cdata->sensors_enabled & (1 << ST_INDIO_DEV_GYRO))
+ return 0;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ reg_addr = ST_LSM6DS3_INT1_ADDR;
+ mask = ST_LSM6DS3_FIFO_THR_IRQ_MASK;
+ break;
+ case ST_INDIO_DEV_GYRO:
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ if ((sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_ACCEL)) ||
+ (sdata->cdata->sensors_enabled &
+ ST_LSM6DS3_EXT_SENSORS))
+ return 0;
+#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+ if (sdata->cdata->sensors_enabled & (1 << ST_INDIO_DEV_ACCEL))
+ return 0;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ reg_addr = ST_LSM6DS3_INT1_ADDR;
+ mask = ST_LSM6DS3_FIFO_THR_IRQ_MASK;
+ break;
+ case ST_INDIO_DEV_SIGN_MOTION:
+ if (sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_STEP_DETECTOR))
+ return 0;
+
+ reg_addr = ST_LSM6DS3_INT1_ADDR;
+ mask = ST_LSM6DS3_STEP_DETECTOR_DRDY_IRQ_MASK;
+ break;
+ case ST_INDIO_DEV_STEP_COUNTER:
+ reg_addr = ST_LSM6DS3_INT2_ADDR;
+ mask = ST_LSM6DS3_STEP_COUNTER_DRDY_IRQ_MASK;
+ break;
+ case ST_INDIO_DEV_STEP_DETECTOR:
+ if (sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_SIGN_MOTION))
+ return 0;
+
+ reg_addr = ST_LSM6DS3_INT1_ADDR;
+ mask = ST_LSM6DS3_STEP_DETECTOR_DRDY_IRQ_MASK;
+ break;
+ case ST_INDIO_DEV_TILT:
+ reg_addr = ST_LSM6DS3_MD1_ADDR;
+ mask = ST_LSM6DS3_TILT_DRDY_IRQ_MASK;
+ break;
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ case ST_INDIO_DEV_EXT0:
+ if ((sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_ACCEL)) ||
+ (sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_GYRO)) ||
+ (sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_EXT1)))
+ return 0;
+
+ reg_addr = ST_LSM6DS3_INT1_ADDR;
+ mask = ST_LSM6DS3_FIFO_THR_IRQ_MASK;
+ break;
+ case ST_INDIO_DEV_EXT1:
+ if ((sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_ACCEL)) ||
+ (sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_GYRO)) ||
+ (sdata->cdata->sensors_enabled &
+ (1 << ST_INDIO_DEV_EXT0)))
+ return 0;
+
+ reg_addr = ST_LSM6DS3_INT1_ADDR;
+ mask = ST_LSM6DS3_FIFO_THR_IRQ_MASK;
+ break;
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+ default:
+ return -EINVAL;
+ }
+
+ return st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ reg_addr, mask, value, true);
+}
+EXPORT_SYMBOL(st_lsm6ds3_set_drdy_irq);
+
+int st_lsm6ds3_set_axis_enable(struct lsm6ds3_sensor_data *sdata, u8 value)
+{
+ u8 reg_addr;
+
+ switch (sdata->sindex) {
+ case ST_INDIO_DEV_ACCEL:
+ reg_addr = ST_LSM6DS3_ACCEL_AXIS_EN_ADDR;
+ break;
+ case ST_INDIO_DEV_GYRO:
+ reg_addr = ST_LSM6DS3_GYRO_AXIS_EN_ADDR;
+ break;
+ default:
+ return 0;
+ }
+
+ return st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ reg_addr, ST_LSM6DS3_AXIS_EN_MASK, value, true);
+}
+EXPORT_SYMBOL(st_lsm6ds3_set_axis_enable);
+
+int st_lsm6ds3_enable_accel_dependency(struct lsm6ds3_sensor_data *sdata,
+ bool enable)
+{
+ int err;
+
+ if (!((sdata->cdata->sensors_enabled &
+ ST_LSM6DS3_ACCEL_DEPENDENCY) & ~(1 << sdata->sindex))) {
+ if (enable) {
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ st_lsm6ds3_odr_table.addr[ST_INDIO_DEV_ACCEL],
+ st_lsm6ds3_odr_table.mask[ST_INDIO_DEV_ACCEL],
+ st_lsm6ds3_odr_table.odr_avl[0].value, true);
+ if (err < 0)
+ return err;
+ } else {
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ st_lsm6ds3_odr_table.addr[ST_INDIO_DEV_ACCEL],
+ st_lsm6ds3_odr_table.mask[ST_INDIO_DEV_ACCEL],
+ ST_LSM6DS3_ODR_POWER_OFF_VAL, true);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(st_lsm6ds3_enable_accel_dependency);
+
+static int st_lsm6ds3_set_extra_dependency(struct lsm6ds3_sensor_data *sdata,
+ bool enable)
+{
+ int err;
+
+ if (!((sdata->cdata->sensors_enabled &
+ ST_LSM6DS3_EXTRA_DEPENDENCY) & ~(1 << sdata->sindex))) {
+ if (enable) {
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_FUNC_EN_ADDR,
+ ST_LSM6DS3_FUNC_EN_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+ } else {
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_FUNC_EN_ADDR,
+ ST_LSM6DS3_FUNC_EN_MASK,
+ ST_LSM6DS3_DIS_BIT, true);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return st_lsm6ds3_enable_accel_dependency(sdata, enable);
+}
+
+static int st_lsm6ds3_enable_pedometer(struct lsm6ds3_sensor_data *sdata,
+ bool enable)
+{
+ u8 value = ST_LSM6DS3_DIS_BIT;
+
+ if ((sdata->cdata->sensors_enabled & ~(1 << sdata->sindex)) &
+ ST_LSM6DS3_PEDOMETER_DEPENDENCY)
+ return 0;
+
+ if (enable)
+ value = ST_LSM6DS3_EN_BIT;
+
+ return st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_PEDOMETER_EN_ADDR,
+ ST_LSM6DS3_PEDOMETER_EN_MASK,
+ value, true);
+
+}
+
+static int st_lsm6ds3_enable_sensors(struct lsm6ds3_sensor_data *sdata)
+{
+ int err, i;
+
+ switch (sdata->sindex) {
+ case ST_INDIO_DEV_ACCEL:
+ case ST_INDIO_DEV_GYRO:
+ for (i = 0; i < ST_LSM6DS3_ODR_LIST_NUM; i++) {
+ if (st_lsm6ds3_odr_table.odr_avl[i].hz == sdata->c_odr)
+ break;
+ }
+ if (i == ST_LSM6DS3_ODR_LIST_NUM)
+ return -EINVAL;
+
+ if (sdata->sindex == ST_INDIO_DEV_ACCEL) {
+ sdata->cdata->accel_samples_to_discard =
+ ST_LSM6DS3_ACCEL_STD;
+ }
+
+ sdata->cdata->gyro_samples_to_discard = ST_LSM6DS3_GYRO_STD;
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ st_lsm6ds3_odr_table.addr[sdata->sindex],
+ st_lsm6ds3_odr_table.mask[sdata->sindex],
+ st_lsm6ds3_odr_table.odr_avl[i].value, true);
+ if (err < 0)
+ return err;
+
+ sdata->c_odr = st_lsm6ds3_odr_table.odr_avl[i].hz;
+
+ break;
+ case ST_INDIO_DEV_SIGN_MOTION:
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_SIGN_MOTION_EN_ADDR,
+ ST_LSM6DS3_SIGN_MOTION_EN_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+
+ if ((sdata->cdata->sensors_enabled & ~(1 << sdata->sindex)) &
+ ST_LSM6DS3_PEDOMETER_DEPENDENCY) {
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_PEDOMETER_EN_ADDR,
+ ST_LSM6DS3_PEDOMETER_EN_MASK,
+ ST_LSM6DS3_DIS_BIT, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_PEDOMETER_EN_ADDR,
+ ST_LSM6DS3_PEDOMETER_EN_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+ } else {
+ err = st_lsm6ds3_enable_pedometer(sdata, true);
+ if (err < 0)
+ return err;
+ }
+
+ break;
+ case ST_INDIO_DEV_STEP_COUNTER:
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_TIMER_EN_ADDR,
+ ST_LSM6DS3_TIMER_EN_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+
+ case ST_INDIO_DEV_STEP_DETECTOR:
+ err = st_lsm6ds3_enable_pedometer(sdata, true);
+ if (err < 0)
+ return err;
+
+ break;
+ case ST_INDIO_DEV_TILT:
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_TILT_EN_ADDR,
+ ST_LSM6DS3_TILT_EN_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = st_lsm6ds3_set_extra_dependency(sdata, true);
+ if (err < 0)
+ return err;
+
+ sdata->cdata->sensors_enabled |= (1 << sdata->sindex);
+
+ return 0;
+}
+
+static int st_lsm6ds3_disable_sensors(struct lsm6ds3_sensor_data *sdata)
+{
+ int err;
+
+ switch (sdata->sindex) {
+ case ST_INDIO_DEV_ACCEL:
+ if (sdata->cdata->sensors_enabled &
+ ST_LSM6DS3_EXTRA_DEPENDENCY) {
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ st_lsm6ds3_odr_table.addr[sdata->sindex],
+ st_lsm6ds3_odr_table.mask[sdata->sindex],
+ st_lsm6ds3_odr_table.odr_avl[0].value, true);
+ } else {
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ st_lsm6ds3_odr_table.addr[sdata->sindex],
+ st_lsm6ds3_odr_table.mask[sdata->sindex],
+ ST_LSM6DS3_ODR_POWER_OFF_VAL, true);
+ }
+ if (err < 0)
+ return err;
+
+ break;
+ case ST_INDIO_DEV_GYRO:
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ st_lsm6ds3_odr_table.addr[sdata->sindex],
+ st_lsm6ds3_odr_table.mask[sdata->sindex],
+ ST_LSM6DS3_ODR_POWER_OFF_VAL, true);
+ if (err < 0)
+ return err;
+
+ break;
+ case ST_INDIO_DEV_SIGN_MOTION:
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_SIGN_MOTION_EN_ADDR,
+ ST_LSM6DS3_SIGN_MOTION_EN_MASK,
+ ST_LSM6DS3_DIS_BIT, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_enable_pedometer(sdata, false);
+ if (err < 0)
+ return err;
+
+ break;
+ case ST_INDIO_DEV_STEP_COUNTER:
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_TIMER_EN_ADDR,
+ ST_LSM6DS3_TIMER_EN_MASK,
+ ST_LSM6DS3_DIS_BIT, true);
+ if (err < 0)
+ return err;
+
+ case ST_INDIO_DEV_STEP_DETECTOR:
+ err = st_lsm6ds3_enable_pedometer(sdata, false);
+ if (err < 0)
+ return err;
+
+ break;
+ case ST_INDIO_DEV_TILT:
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_TILT_EN_ADDR,
+ ST_LSM6DS3_TILT_EN_MASK,
+ ST_LSM6DS3_DIS_BIT, true);
+ if (err < 0)
+ return err;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = st_lsm6ds3_set_extra_dependency(sdata, false);
+ if (err < 0)
+ return err;
+
+ sdata->cdata->sensors_enabled &= ~(1 << sdata->sindex);
+
+ return 0;
+}
+
+int st_lsm6ds3_set_enable(struct lsm6ds3_sensor_data *sdata, bool enable)
+{
+ if (enable)
+ return st_lsm6ds3_enable_sensors(sdata);
+ else
+ return st_lsm6ds3_disable_sensors(sdata);
+}
+EXPORT_SYMBOL(st_lsm6ds3_set_enable);
+
+static int st_lsm6ds3_set_odr(struct lsm6ds3_sensor_data *sdata,
+ unsigned int odr)
+{
+ int err, i;
+
+ for (i = 0; i < ST_LSM6DS3_ODR_LIST_NUM; i++) {
+ if (st_lsm6ds3_odr_table.odr_avl[i].hz == odr)
+ break;
+ }
+ if (i == ST_LSM6DS3_ODR_LIST_NUM)
+ return -EINVAL;
+
+ if (sdata->cdata->sensors_enabled & (1 << sdata->sindex)) {
+ disable_irq(sdata->cdata->irq);
+ st_lsm6ds3_flush_works();
+
+ if (sdata->sindex == ST_INDIO_DEV_ACCEL)
+ sdata->cdata->accel_samples_to_discard =
+ ST_LSM6DS3_ACCEL_STD;
+
+ sdata->cdata->gyro_samples_to_discard = ST_LSM6DS3_GYRO_STD;
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ st_lsm6ds3_odr_table.addr[sdata->sindex],
+ st_lsm6ds3_odr_table.mask[sdata->sindex],
+ st_lsm6ds3_odr_table.odr_avl[i].value, true);
+ if (err < 0) {
+ enable_irq(sdata->cdata->irq);
+ return err;
+ }
+
+ sdata->c_odr = st_lsm6ds3_odr_table.odr_avl[i].hz;
+
+ st_lsm6ds3_reconfigure_fifo(sdata->cdata, false);
+ enable_irq(sdata->cdata->irq);
+ } else
+ sdata->c_odr = st_lsm6ds3_odr_table.odr_avl[i].hz;
+
+ return 0;
+}
+
+static int st_lsm6ds3_set_fs(struct lsm6ds3_sensor_data *sdata,
+ unsigned int gain)
+{
+ int err, i;
+
+ for (i = 0; i < ST_LSM6DS3_FS_LIST_NUM; i++) {
+ if (st_lsm6ds3_fs_table[sdata->sindex].fs_avl[i].gain == gain)
+ break;
+ }
+ if (i == ST_LSM6DS3_FS_LIST_NUM)
+ return -EINVAL;
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ st_lsm6ds3_fs_table[sdata->sindex].addr,
+ st_lsm6ds3_fs_table[sdata->sindex].mask,
+ st_lsm6ds3_fs_table[sdata->sindex].fs_avl[i].value, true);
+ if (err < 0)
+ return err;
+
+ sdata->c_gain[0] = gain;
+
+ return 0;
+}
+
+static int st_lsm6ds3_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *ch, int *val,
+ int *val2, long mask)
+{
+ int err;
+ u8 outdata[ST_LSM6DS3_BYTE_FOR_CHANNEL];
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&indio_dev->mlock);
+
+ if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+ mutex_unlock(&indio_dev->mlock);
+ return -EBUSY;
+ }
+
+ err = st_lsm6ds3_set_enable(sdata, true);
+ if (err < 0) {
+ mutex_unlock(&indio_dev->mlock);
+ return -EBUSY;
+ }
+
+ if (sdata->sindex == ST_INDIO_DEV_ACCEL)
+ msleep(40);
+
+ if (sdata->sindex == ST_INDIO_DEV_GYRO)
+ msleep(120);
+
+ err = sdata->cdata->tf->read(sdata->cdata, ch->address,
+ ST_LSM6DS3_BYTE_FOR_CHANNEL, outdata, true);
+ if (err < 0) {
+ mutex_unlock(&indio_dev->mlock);
+ return err;
+ }
+
+ *val = (s16)get_unaligned_le16(outdata);
+ *val = *val >> ch->scan_type.shift;
+
+ err = st_lsm6ds3_set_enable(sdata, false);
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = sdata->c_gain[0];
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int st_lsm6ds3_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+ int err;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ mutex_lock(&indio_dev->mlock);
+
+ if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+ mutex_unlock(&indio_dev->mlock);
+ return -EBUSY;
+ }
+
+ err = st_lsm6ds3_set_fs(sdata, val2);
+ mutex_unlock(&indio_dev->mlock);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static int st_lsm6ds3_reset_steps(struct lsm6ds3_data *cdata)
+{
+ int err;
+ u8 reg_value = 0x00;
+
+ err = cdata->tf->read(cdata,
+ ST_LSM6DS3_STEP_COUNTER_RES_ADDR, 1, &reg_value, true);
+ if (err < 0)
+ return err;
+
+ if (reg_value & ST_LSM6DS3_FUNC_EN_MASK)
+ reg_value = ST_LSM6DS3_STEP_COUNTER_RES_FUNC_EN;
+ else
+ reg_value = ST_LSM6DS3_DIS_BIT;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_STEP_COUNTER_RES_ADDR,
+ ST_LSM6DS3_STEP_COUNTER_RES_MASK,
+ ST_LSM6DS3_STEP_COUNTER_RES_ALL_EN, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_STEP_COUNTER_RES_ADDR,
+ ST_LSM6DS3_STEP_COUNTER_RES_MASK,
+ reg_value, true);
+ if (err < 0)
+ return err;
+
+ cdata->reset_steps = true;
+
+ return 0;
+}
+
+static int st_lsm6ds3_init_sensor(struct lsm6ds3_data *cdata)
+{
+ int err, i;
+ u8 default_reg_value = 0;
+ struct lsm6ds3_sensor_data *sdata;
+
+ mutex_init(&cdata->tb.buf_lock);
+
+ cdata->sensors_enabled = 0;
+ cdata->reset_steps = false;
+ cdata->sign_motion_event_ready = false;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata, ST_LSM6DS3_RESET_ADDR,
+ ST_LSM6DS3_RESET_MASK, ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < ST_INDIO_DEV_NUM; i++) {
+ sdata = iio_priv(cdata->indio_dev[i]);
+
+ err = st_lsm6ds3_set_enable(sdata, false);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_set_drdy_irq(sdata, false);
+ if (err < 0)
+ return err;
+
+ switch (sdata->sindex) {
+ case ST_INDIO_DEV_ACCEL:
+ case ST_INDIO_DEV_GYRO:
+ sdata->num_data_channels =
+ ARRAY_SIZE(st_lsm6ds3_accel_ch) - 1;
+
+ err = st_lsm6ds3_set_fs(sdata, sdata->c_gain[0]);
+ if (err < 0)
+ return err;
+
+ break;
+ case ST_INDIO_DEV_STEP_COUNTER:
+ sdata->num_data_channels =
+ ARRAY_SIZE(st_lsm6ds3_step_c_ch) - 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ cdata->gyro_selftest_status = 0;
+ cdata->accel_selftest_status = 0;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata, ST_LSM6DS3_LIR_ADDR,
+ ST_LSM6DS3_LIR_MASK, ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata, ST_LSM6DS3_BDU_ADDR,
+ ST_LSM6DS3_BDU_MASK, ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_set_fifo_enable(sdata->cdata, false);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_ROUNDING_ADDR,
+ ST_LSM6DS3_ROUNDING_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_write_data_with_mask(cdata,
+ ST_LSM6DS3_INT2_ON_INT1_ADDR,
+ ST_LSM6DS3_INT2_ON_INT1_MASK,
+ ST_LSM6DS3_EN_BIT, true);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_reset_steps(sdata->cdata);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&cdata->bank_registers_lock);
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_FUNC_CFG_ACCESS_ADDR,
+ ST_LSM6DS3_FUNC_CFG_REG2_MASK,
+ ST_LSM6DS3_EN_BIT, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ err = sdata->cdata->tf->write(sdata->cdata,
+ ST_LSM6DS3_STEP_COUNTER_DURATION_ADDR,
+ 1, &default_reg_value, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_FUNC_CFG_ACCESS_ADDR,
+ ST_LSM6DS3_FUNC_CFG_REG2_MASK,
+ ST_LSM6DS3_DIS_BIT, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ mutex_unlock(&cdata->bank_registers_lock);
+
+ sdata->c_odr = 0;
+
+ return 0;
+
+st_lsm6ds3_init_sensor_mutex_unlock:
+ mutex_unlock(&cdata->bank_registers_lock);
+ return err;
+}
+
+static int st_lsm6ds3_set_selftest(struct lsm6ds3_sensor_data *sdata, int index)
+{
+ int err;
+ u8 mode, mask;
+
+ switch (sdata->sindex) {
+ case ST_INDIO_DEV_ACCEL:
+ mask = ST_LSM6DS3_SELFTEST_ACCEL_MASK;
+ mode = st_lsm6ds3_selftest_table[index].accel_value;
+ break;
+ case ST_INDIO_DEV_GYRO:
+ mask = ST_LSM6DS3_SELFTEST_GYRO_MASK;
+ mode = st_lsm6ds3_selftest_table[index].gyro_value;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_SELFTEST_ADDR, mask, mode, true);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static ssize_t st_lsm6ds3_sysfs_set_max_delivery_rate(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ u8 duration;
+ int err, err2;
+ unsigned int max_delivery_rate;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ err = kstrtouint(buf, 10, &max_delivery_rate);
+ if (err < 0)
+ return -EINVAL;
+
+ if (max_delivery_rate == sdata->c_odr)
+ return size;
+
+ duration = max_delivery_rate / ST_LSM6DS3_MIN_DURATION_MS;
+
+ mutex_lock(&sdata->cdata->bank_registers_lock);
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_FUNC_CFG_ACCESS_ADDR,
+ ST_LSM6DS3_FUNC_CFG_REG2_MASK,
+ ST_LSM6DS3_EN_BIT, false);
+ if (err < 0)
+ goto st_lsm6ds3_sysfs_set_max_delivery_rate_mutex_unlock;
+
+ err = sdata->cdata->tf->write(sdata->cdata,
+ ST_LSM6DS3_STEP_COUNTER_DURATION_ADDR,
+ 1, &duration, false);
+ if (err < 0)
+ goto st_lsm6ds3_sysfs_set_max_delivery_rate_restore_bank;
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_FUNC_CFG_ACCESS_ADDR,
+ ST_LSM6DS3_FUNC_CFG_REG2_MASK,
+ ST_LSM6DS3_DIS_BIT, false);
+ if (err < 0)
+ goto st_lsm6ds3_sysfs_set_max_delivery_rate_restore_bank;
+
+ mutex_unlock(&sdata->cdata->bank_registers_lock);
+
+ sdata->c_odr = max_delivery_rate;
+
+ return size;
+
+st_lsm6ds3_sysfs_set_max_delivery_rate_restore_bank:
+ do {
+ err2 = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_FUNC_CFG_ACCESS_ADDR,
+ ST_LSM6DS3_FUNC_CFG_REG2_MASK,
+ ST_LSM6DS3_DIS_BIT, false);
+
+ msleep(500);
+ } while (err2 < 0);
+
+st_lsm6ds3_sysfs_set_max_delivery_rate_mutex_unlock:
+ mutex_unlock(&sdata->cdata->bank_registers_lock);
+ return err;
+}
+
+static ssize_t st_lsm6ds3_sysfs_get_max_delivery_rate(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct lsm6ds3_sensor_data *sdata = iio_priv(dev_get_drvdata(dev));
+
+ return sprintf(buf, "%d\n", sdata->c_odr);
+}
+
+static ssize_t st_lsm6ds3_sysfs_reset_counter(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int err;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(dev_get_drvdata(dev));
+
+ err = st_lsm6ds3_reset_steps(sdata->cdata);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+
+static ssize_t st_lsm6ds3_sysfs_get_sampling_frequency(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct lsm6ds3_sensor_data *sdata = iio_priv(dev_get_drvdata(dev));
+
+ return sprintf(buf, "%d\n", sdata->c_odr);
+}
+
+static ssize_t st_lsm6ds3_sysfs_set_sampling_frequency(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int err;
+ unsigned int odr;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ err = kstrtoint(buf, 10, &odr);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&indio_dev->mlock);
+
+ if (sdata->c_odr != odr)
+ err = st_lsm6ds3_set_odr(sdata, odr);
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return err < 0 ? err : size;
+}
+
+static ssize_t st_lsm6ds3_sysfs_sampling_frequency_avail(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int i, len = 0;
+
+ for (i = 0; i < ST_LSM6DS3_ODR_LIST_NUM; i++) {
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
+ st_lsm6ds3_odr_table.odr_avl[i].hz);
+ }
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static ssize_t st_lsm6ds3_sysfs_scale_avail(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int i, len = 0;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(dev_get_drvdata(dev));
+
+ for (i = 0; i < ST_LSM6DS3_FS_LIST_NUM; i++) {
+ len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
+ st_lsm6ds3_fs_table[sdata->sindex].fs_avl[i].gain);
+ }
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static ssize_t st_lsm6ds3_sysfs_get_selftest_available(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s, %s, %s\n",
+ st_lsm6ds3_selftest_table[0].string_mode,
+ st_lsm6ds3_selftest_table[1].string_mode,
+ st_lsm6ds3_selftest_table[2].string_mode);
+}
+
+static ssize_t st_lsm6ds3_sysfs_get_selftest_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 index;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(dev_get_drvdata(dev));
+
+ switch (sdata->sindex) {
+ case ST_INDIO_DEV_ACCEL:
+ index = sdata->cdata->accel_selftest_status;
+ break;
+ case ST_INDIO_DEV_GYRO:
+ index = sdata->cdata->gyro_selftest_status;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return sprintf(buf, "%s\n",
+ st_lsm6ds3_selftest_table[index].string_mode);
+}
+
+static ssize_t st_lsm6ds3_sysfs_set_selftest_status(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int err, i;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ for (i = 0; i < ARRAY_SIZE(st_lsm6ds3_selftest_table); i++) {
+ if (strncmp(buf, st_lsm6ds3_selftest_table[i].string_mode,
+ size - 2) == 0)
+ break;
+ }
+ if (i == ARRAY_SIZE(st_lsm6ds3_selftest_table))
+ return -EINVAL;
+
+ err = st_lsm6ds3_set_selftest(sdata, i);
+ if (err < 0)
+ return err;
+
+ switch (sdata->sindex) {
+ case ST_INDIO_DEV_ACCEL:
+ sdata->cdata->accel_selftest_status = i;
+ break;
+ case ST_INDIO_DEV_GYRO:
+ sdata->cdata->gyro_selftest_status = i;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return size;
+}
+
+ssize_t st_lsm6ds3_sysfs_get_hw_fifo_lenght(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", ST_LSM6DS3_MAX_FIFO_LENGHT);
+}
+
+ssize_t st_lsm6ds3_sysfs_flush_fifo(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ disable_irq(sdata->cdata->irq);
+ st_lsm6ds3_flush_works();
+
+ mutex_lock(&sdata->cdata->fifo_lock);
+
+ st_lsm6ds3_read_fifo(sdata->cdata, true);
+
+ mutex_unlock(&sdata->cdata->fifo_lock);
+
+ enable_irq(sdata->cdata->irq);
+
+ return size;
+}
+
+static ST_LSM6DS3_DEV_ATTR_SAMP_FREQ();
+static ST_LSM6DS3_DEV_ATTR_SAMP_FREQ_AVAIL();
+static ST_LSM6DS3_DEV_ATTR_SCALE_AVAIL(in_accel_scale_available);
+static ST_LSM6DS3_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
+static ST_LSM6DS3_FIFO_LENGHT();
+static ST_LSM6DS3_FIFO_FLUSH();
+
+static IIO_DEVICE_ATTR(reset_counter, S_IWUSR,
+ NULL, st_lsm6ds3_sysfs_reset_counter, 0);
+
+static IIO_DEVICE_ATTR(max_delivery_rate, S_IWUSR | S_IRUGO,
+ st_lsm6ds3_sysfs_get_max_delivery_rate,
+ st_lsm6ds3_sysfs_set_max_delivery_rate, 0);
+
+static IIO_DEVICE_ATTR(self_test_available, S_IRUGO,
+ st_lsm6ds3_sysfs_get_selftest_available,
+ NULL, 0);
+
+static IIO_DEVICE_ATTR(self_test, S_IWUSR | S_IRUGO,
+ st_lsm6ds3_sysfs_get_selftest_status,
+ st_lsm6ds3_sysfs_set_selftest_status, 0);
+
+static struct attribute *st_lsm6ds3_accel_attributes[] = {
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_in_accel_scale_available.dev_attr.attr,
+ &iio_dev_attr_sampling_frequency.dev_attr.attr,
+ &iio_dev_attr_self_test_available.dev_attr.attr,
+ &iio_dev_attr_self_test.dev_attr.attr,
+ &iio_dev_attr_hw_fifo_lenght.dev_attr.attr,
+ &iio_dev_attr_flush.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group st_lsm6ds3_accel_attribute_group = {
+ .attrs = st_lsm6ds3_accel_attributes,
+};
+
+static const struct iio_info st_lsm6ds3_accel_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6ds3_accel_attribute_group,
+ .read_raw = &st_lsm6ds3_read_raw,
+ .write_raw = &st_lsm6ds3_write_raw,
+};
+
+static struct attribute *st_lsm6ds3_gyro_attributes[] = {
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
+ &iio_dev_attr_sampling_frequency.dev_attr.attr,
+ &iio_dev_attr_self_test_available.dev_attr.attr,
+ &iio_dev_attr_self_test.dev_attr.attr,
+ &iio_dev_attr_hw_fifo_lenght.dev_attr.attr,
+ &iio_dev_attr_flush.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group st_lsm6ds3_gyro_attribute_group = {
+ .attrs = st_lsm6ds3_gyro_attributes,
+};
+
+static const struct iio_info st_lsm6ds3_gyro_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6ds3_gyro_attribute_group,
+ .read_raw = &st_lsm6ds3_read_raw,
+ .write_raw = &st_lsm6ds3_write_raw,
+};
+
+static struct attribute *st_lsm6ds3_sign_motion_attributes[] = {
+ NULL,
+};
+
+static const struct attribute_group st_lsm6ds3_sign_motion_attribute_group = {
+ .attrs = st_lsm6ds3_sign_motion_attributes,
+};
+
+static const struct iio_info st_lsm6ds3_sign_motion_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6ds3_sign_motion_attribute_group,
+};
+
+static struct attribute *st_lsm6ds3_step_c_attributes[] = {
+ &iio_dev_attr_reset_counter.dev_attr.attr,
+ &iio_dev_attr_max_delivery_rate.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group st_lsm6ds3_step_c_attribute_group = {
+ .attrs = st_lsm6ds3_step_c_attributes,
+};
+
+static const struct iio_info st_lsm6ds3_step_c_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6ds3_step_c_attribute_group,
+ .read_raw = &st_lsm6ds3_read_raw,
+};
+
+static struct attribute *st_lsm6ds3_step_d_attributes[] = {
+ NULL,
+};
+
+static const struct attribute_group st_lsm6ds3_step_d_attribute_group = {
+ .attrs = st_lsm6ds3_step_d_attributes,
+};
+
+static const struct iio_info st_lsm6ds3_step_d_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6ds3_step_d_attribute_group,
+};
+
+static struct attribute *st_lsm6ds3_tilt_attributes[] = {
+ NULL,
+};
+
+static const struct attribute_group st_lsm6ds3_tilt_attribute_group = {
+ .attrs = st_lsm6ds3_tilt_attributes,
+};
+
+static const struct iio_info st_lsm6ds3_tilt_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6ds3_tilt_attribute_group,
+};
+
+#ifdef CONFIG_IIO_TRIGGER
+static const struct iio_trigger_ops st_lsm6ds3_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = ST_LSM6DS3_TRIGGER_SET_STATE,
+};
+#define ST_LSM6DS3_TRIGGER_OPS (&st_lsm6ds3_trigger_ops)
+#else
+#define ST_LSM6DS3_TRIGGER_OPS NULL
+#endif
+
+int st_lsm6ds3_common_probe(struct lsm6ds3_data *cdata, int irq)
+{
+ u8 wai = 0x00;
+ int i, n, err;
+ struct lsm6ds3_sensor_data *sdata;
+
+ mutex_init(&cdata->bank_registers_lock);
+ mutex_init(&cdata->fifo_lock);
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT
+ mutex_init(&cdata->passthrough_lock);
+#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */
+
+ cdata->fifo_data = 0;
+
+ err = cdata->tf->read(cdata, ST_LSM6DS3_WAI_ADDRESS, 1, &wai, true);
+ if (err < 0) {
+ dev_err(cdata->dev, "failed to read Who-Am-I register.\n");
+ return err;
+ }
+ if (wai != ST_LSM6DS3_WAI_EXP) {
+ dev_err(cdata->dev, "Who-Am-I value not valid.\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < ST_INDIO_DEV_NUM; i++) {
+ cdata->indio_dev[i] = iio_device_alloc(sizeof(*sdata));
+ if (cdata->indio_dev[i] == NULL) {
+ err = -ENOMEM;
+ goto iio_device_free;
+ }
+ sdata = iio_priv(cdata->indio_dev[i]);
+ sdata->cdata = cdata;
+ sdata->sindex = i;
+
+ if ((i == ST_INDIO_DEV_ACCEL) || (i == ST_INDIO_DEV_GYRO)) {
+ sdata->c_odr = st_lsm6ds3_odr_table.odr_avl[0].hz;
+ sdata->c_gain[0] =
+ st_lsm6ds3_fs_table[i].fs_avl[0].gain;
+ }
+ cdata->indio_dev[i]->modes = INDIO_DIRECT_MODE;
+ }
+
+ if (irq > 0) {
+ cdata->irq = irq;
+ dev_info(cdata->dev, "driver use DRDY int pin 1\n");
+ }
+
+ cdata->indio_dev[ST_INDIO_DEV_ACCEL]->name =
+ kasprintf(GFP_KERNEL, "%s_%s", cdata->name,
+ ST_LSM6DS3_ACCEL_SUFFIX_NAME);
+ cdata->indio_dev[ST_INDIO_DEV_ACCEL]->info = &st_lsm6ds3_accel_info;
+ cdata->indio_dev[ST_INDIO_DEV_ACCEL]->channels = st_lsm6ds3_accel_ch;
+ cdata->indio_dev[ST_INDIO_DEV_ACCEL]->num_channels =
+ ARRAY_SIZE(st_lsm6ds3_accel_ch);
+
+ cdata->indio_dev[ST_INDIO_DEV_GYRO]->name =
+ kasprintf(GFP_KERNEL, "%s_%s", cdata->name,
+ ST_LSM6DS3_GYRO_SUFFIX_NAME);
+ cdata->indio_dev[ST_INDIO_DEV_GYRO]->info = &st_lsm6ds3_gyro_info;
+ cdata->indio_dev[ST_INDIO_DEV_GYRO]->channels = st_lsm6ds3_gyro_ch;
+ cdata->indio_dev[ST_INDIO_DEV_GYRO]->num_channels =
+ ARRAY_SIZE(st_lsm6ds3_gyro_ch);
+
+ cdata->indio_dev[ST_INDIO_DEV_SIGN_MOTION]->name =
+ kasprintf(GFP_KERNEL, "%s_%s", cdata->name,
+ ST_LSM6DS3_SIGN_MOTION_SUFFIX_NAME);
+ cdata->indio_dev[ST_INDIO_DEV_SIGN_MOTION]->info =
+ &st_lsm6ds3_sign_motion_info;
+ cdata->indio_dev[ST_INDIO_DEV_SIGN_MOTION]->channels =
+ st_lsm6ds3_sign_motion_ch;
+ cdata->indio_dev[ST_INDIO_DEV_SIGN_MOTION]->num_channels =
+ ARRAY_SIZE(st_lsm6ds3_sign_motion_ch);
+
+ cdata->indio_dev[ST_INDIO_DEV_STEP_COUNTER]->name =
+ kasprintf(GFP_KERNEL, "%s_%s", cdata->name,
+ ST_LSM6DS3_STEP_COUNTER_SUFFIX_NAME);
+ cdata->indio_dev[ST_INDIO_DEV_STEP_COUNTER]->info =
+ &st_lsm6ds3_step_c_info;
+ cdata->indio_dev[ST_INDIO_DEV_STEP_COUNTER]->channels =
+ st_lsm6ds3_step_c_ch;
+ cdata->indio_dev[ST_INDIO_DEV_STEP_COUNTER]->num_channels =
+ ARRAY_SIZE(st_lsm6ds3_step_c_ch);
+
+ cdata->indio_dev[ST_INDIO_DEV_STEP_DETECTOR]->name =
+ kasprintf(GFP_KERNEL, "%s_%s", cdata->name,
+ ST_LSM6DS3_STEP_DETECTOR_SUFFIX_NAME);
+ cdata->indio_dev[ST_INDIO_DEV_STEP_DETECTOR]->info =
+ &st_lsm6ds3_step_d_info;
+ cdata->indio_dev[ST_INDIO_DEV_STEP_DETECTOR]->channels =
+ st_lsm6ds3_step_d_ch;
+ cdata->indio_dev[ST_INDIO_DEV_STEP_DETECTOR]->num_channels =
+ ARRAY_SIZE(st_lsm6ds3_step_d_ch);
+
+ cdata->indio_dev[ST_INDIO_DEV_TILT]->name =
+ kasprintf(GFP_KERNEL, "%s_%s", cdata->name,
+ ST_LSM6DS3_TILT_SUFFIX_NAME);
+ cdata->indio_dev[ST_INDIO_DEV_TILT]->info = &st_lsm6ds3_tilt_info;
+ cdata->indio_dev[ST_INDIO_DEV_TILT]->channels = st_lsm6ds3_tilt_ch;
+ cdata->indio_dev[ST_INDIO_DEV_TILT]->num_channels =
+ ARRAY_SIZE(st_lsm6ds3_tilt_ch);
+
+ err = st_lsm6ds3_init_sensor(cdata);
+ if (err < 0)
+ goto iio_device_free;
+
+ err = st_lsm6ds3_allocate_rings(cdata);
+ if (err < 0)
+ goto iio_device_free;
+
+ if (irq > 0) {
+ err = st_lsm6ds3_allocate_triggers(cdata,
+ ST_LSM6DS3_TRIGGER_OPS);
+ if (err < 0)
+ goto deallocate_ring;
+ }
+
+ for (n = 0; n < ST_INDIO_DEV_NUM; n++) {
+ err = iio_device_register(cdata->indio_dev[n]);
+ if (err)
+ goto iio_device_unregister_and_trigger_deallocate;
+ }
+
+ err = st_lsm6ds3_i2c_master_probe(cdata);
+ if (err < 0)
+ goto iio_device_unregister_and_trigger_deallocate;
+
+ device_init_wakeup(cdata->dev, true);
+
+ return 0;
+
+iio_device_unregister_and_trigger_deallocate:
+ for (n--; n >= 0; n--)
+ iio_device_unregister(cdata->indio_dev[n]);
+
+ if (irq > 0)
+ st_lsm6ds3_deallocate_triggers(cdata);
+deallocate_ring:
+ st_lsm6ds3_deallocate_rings(cdata);
+iio_device_free:
+ for (i--; i >= 0; i--)
+ iio_device_free(cdata->indio_dev[i]);
+
+ return err;
+}
+EXPORT_SYMBOL(st_lsm6ds3_common_probe);
+
+void st_lsm6ds3_common_remove(struct lsm6ds3_data *cdata, int irq)
+{
+ int i;
+
+ for (i = 0; i < ST_INDIO_DEV_NUM; i++)
+ iio_device_unregister(cdata->indio_dev[i]);
+
+ if (irq > 0)
+ st_lsm6ds3_deallocate_triggers(cdata);
+
+ st_lsm6ds3_deallocate_rings(cdata);
+
+ for (i = 0; i < ST_INDIO_DEV_NUM; i++)
+ iio_device_free(cdata->indio_dev[i]);
+
+ st_lsm6ds3_i2c_master_exit(cdata);
+}
+EXPORT_SYMBOL(st_lsm6ds3_common_remove);
+
+#ifdef CONFIG_PM
+int st_lsm6ds3_common_suspend(struct lsm6ds3_data *cdata)
+{
+#ifndef CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP
+ int err, i;
+ u8 tmp_sensors_enabled;
+ struct lsm6ds3_sensor_data *sdata;
+
+ tmp_sensors_enabled = cdata->sensors_enabled;
+
+ for (i = 0; i < ST_INDIO_DEV_NUM; i++) {
+ if ((i == ST_INDIO_DEV_SIGN_MOTION) || (i == ST_INDIO_DEV_TILT))
+ continue;
+
+ sdata = iio_priv(cdata->indio_dev[i]);
+
+ err = st_lsm6ds3_set_enable(sdata, false);
+ if (err < 0)
+ return err;
+ }
+ cdata->sensors_enabled = tmp_sensors_enabled;
+#endif /* CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP */
+
+ if (cdata->sensors_enabled & ST_LSM6DS3_WAKE_UP_SENSORS) {
+ if (device_may_wakeup(cdata->dev))
+ enable_irq_wake(cdata->irq);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(st_lsm6ds3_common_suspend);
+
+int st_lsm6ds3_common_resume(struct lsm6ds3_data *cdata)
+{
+#ifndef CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP
+ int err, i;
+ struct lsm6ds3_sensor_data *sdata;
+
+ for (i = 0; i < ST_INDIO_DEV_NUM; i++) {
+ if ((i == ST_INDIO_DEV_SIGN_MOTION) || (i == ST_INDIO_DEV_TILT))
+ continue;
+
+ sdata = iio_priv(cdata->indio_dev[i]);
+
+ if ((1 << sdata->sindex) & cdata->sensors_enabled) {
+ err = st_lsm6ds3_set_enable(sdata, true);
+ if (err < 0)
+ return err;
+ }
+ }
+#endif /* CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP */
+
+ if (cdata->sensors_enabled & ST_LSM6DS3_WAKE_UP_SENSORS) {
+ if (device_may_wakeup(cdata->dev))
+ disable_irq_wake(cdata->irq);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(st_lsm6ds3_common_resume);
+#endif /* CONFIG_PM */
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics lsm6ds3 core driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_i2c.c b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_i2c.c
new file mode 100644
index 00000000000..436f09e0060
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_i2c.c
@@ -0,0 +1,159 @@
+/*
+ * STMicroelectronics lsm6ds3 i2c driver
+ *
+ * Copyright 2014 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+
+#include "st_lsm6ds3.h"
+
+static int st_lsm6ds3_i2c_read(struct lsm6ds3_data *cdata,
+ u8 reg_addr, int len, u8 *data, bool b_lock)
+{
+ int err = 0;
+ struct i2c_msg msg[2];
+ struct i2c_client *client = to_i2c_client(cdata->dev);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags;
+ msg[0].len = 1;
+ msg[0].buf = &reg_addr;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags | I2C_M_RD;
+ msg[1].len = len;
+ msg[1].buf = data;
+
+ if (b_lock) {
+ mutex_lock(&cdata->bank_registers_lock);
+ err = i2c_transfer(client->adapter, msg, 2);
+ mutex_unlock(&cdata->bank_registers_lock);
+ } else
+ err = i2c_transfer(client->adapter, msg, 2);
+
+ return err;
+}
+
+static int st_lsm6ds3_i2c_write(struct lsm6ds3_data *cdata,
+ u8 reg_addr, int len, u8 *data, bool b_lock)
+{
+ int err = 0;
+ u8 send[len + 1];
+ struct i2c_msg msg;
+ struct i2c_client *client = to_i2c_client(cdata->dev);
+
+ send[0] = reg_addr;
+ memcpy(&send[1], data, len * sizeof(u8));
+ len++;
+
+ msg.addr = client->addr;
+ msg.flags = client->flags;
+ msg.len = len;
+ msg.buf = send;
+
+ if (b_lock) {
+ mutex_lock(&cdata->bank_registers_lock);
+ err = i2c_transfer(client->adapter, &msg, 1);
+ mutex_unlock(&cdata->bank_registers_lock);
+ } else
+ err = i2c_transfer(client->adapter, &msg, 1);
+
+ return err;
+}
+
+static const struct st_lsm6ds3_transfer_function st_lsm6ds3_tf_i2c = {
+ .write = st_lsm6ds3_i2c_write,
+ .read = st_lsm6ds3_i2c_read,
+};
+
+static int st_lsm6ds3_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err;
+ struct lsm6ds3_data *cdata;
+
+ cdata = kmalloc(sizeof(*cdata), GFP_KERNEL);
+ if (!cdata)
+ return -ENOMEM;
+
+ cdata->dev = &client->dev;
+ cdata->name = client->name;
+ i2c_set_clientdata(client, cdata);
+
+ cdata->tf = &st_lsm6ds3_tf_i2c;
+
+ err = st_lsm6ds3_common_probe(cdata, client->irq);
+ if (err < 0)
+ goto free_data;
+
+ return 0;
+
+free_data:
+ kfree(cdata);
+ return err;
+}
+
+static int st_lsm6ds3_i2c_remove(struct i2c_client *client)
+{
+ struct lsm6ds3_data *cdata = i2c_get_clientdata(client);
+
+ st_lsm6ds3_common_remove(cdata, client->irq);
+ kfree(cdata);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int st_lsm6ds3_suspend(struct device *dev)
+{
+ struct lsm6ds3_data *cdata = i2c_get_clientdata(to_i2c_client(dev));
+
+ return st_lsm6ds3_common_suspend(cdata);
+}
+
+static int st_lsm6ds3_resume(struct device *dev)
+{
+ struct lsm6ds3_data *cdata = i2c_get_clientdata(to_i2c_client(dev));
+
+ return st_lsm6ds3_common_resume(cdata);
+}
+
+static const struct dev_pm_ops st_lsm6ds3_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(st_lsm6ds3_suspend, st_lsm6ds3_resume)
+};
+
+#define ST_LSM6DS3_PM_OPS (&st_lsm6ds3_pm_ops)
+#else /* CONFIG_PM */
+#define ST_LSM6DS3_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id st_lsm6ds3_id_table[] = {
+ { LSM6DS3_DEV_NAME },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, st_lsm6ds3_id_table);
+
+static struct i2c_driver st_lsm6ds3_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "st-lsm6ds3-i2c",
+ .pm = ST_LSM6DS3_PM_OPS,
+ },
+ .probe = st_lsm6ds3_i2c_probe,
+ .remove = st_lsm6ds3_i2c_remove,
+ .id_table = st_lsm6ds3_id_table,
+};
+module_i2c_driver(st_lsm6ds3_driver);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics lsm6ds3 i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_i2c_master.c b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_i2c_master.c
new file mode 100644
index 00000000000..49e0a08c8b5
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_i2c_master.c
@@ -0,0 +1,1387 @@
+/*
+ * STMicroelectronics lsm6ds3 i2c master driver
+ *
+ * Copyright 2014 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <asm/unaligned.h>
+
+#include "st_lsm6ds3.h"
+
+#define ST_LSM6DS3_EXT0_INDEX 0
+#define ST_LSM6DS3_EXT1_INDEX 1
+
+#define ST_LSM6DS3_I2C_MASTER_ODR_LIST_NUM 4
+#define ST_LSM6DS3_EN_BIT 0x01
+#define ST_LSM6DS3_DIS_BIT 0x00
+#define ST_LSM6DS3_HUB_REG1_ADDR 0x2e
+#define ST_LSM6DS3_FUNC_CFG_ACCESS_ADDR 0x01
+#define ST_LSM6DS3_FUNC_CFG_REG2_MASK 0x80
+#define ST_LSM6DS3_SLV0_ADDR_ADDR 0x02
+#define ST_LSM6DS3_SLV0_SUBADDR_ADDR 0x03
+#define ST_LSM6DS3_SLV0_CONFIG_ADDR 0x04
+#define ST_LSM6DS3_SLV0_CONFIG_MASK 0x07
+#define ST_LSM6DS3_SLV1_ADDR_ADDR 0x05
+#define ST_LSM6DS3_SLV1_SUBADDR_ADDR 0x06
+#define ST_LSM6DS3_SLV1_CONFIG_ADDR 0x07
+#define ST_LSM6DS3_SLV1_CONFIG_MASK 0x07
+#define ST_LSM6DS3_SLV2_ADDR_ADDR 0x08
+#define ST_LSM6DS3_SLV2_SUBADDR_ADDR 0x09
+#define ST_LSM6DS3_SLV2_CONFIG_ADDR 0x0a
+#define ST_LSM6DS3_SLV2_CONFIG_MASK 0x07
+#define ST_LSM6DS3_SLV_AUX_ADDR 0x04
+#define ST_LSM6DS3_SLV_AUX_MASK 0x30
+#define ST_LSM6DS3_SLV_AUX_1 0x00
+#define ST_LSM6DS3_SLV_AUX_2 0x01
+#define ST_LSM6DS3_SLV_AUX_3 0x02
+
+/* External sensors configuration */
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT0_LIS3MDL
+static int lis3mdl_initialization(struct lsm6ds3_sensor_data *sdata,
+ int ext_num);
+
+#define ST_LSM6DS3_EXT0_ADDR 0x1e
+#define ST_LSM6DS3_EXT0_WAI_ADDR 0x0f
+#define ST_LSM6DS3_EXT0_WAI_VALUE 0x3d
+#define ST_LSM6DS3_EXT0_RESET_ADDR 0x21
+#define ST_LSM6DS3_EXT0_RESET_MASK 0x04
+#define ST_LSM6DS3_EXT0_FULLSCALE_ADDR 0x21
+#define ST_LSM6DS3_EXT0_FULLSCALE_MASK 0x60
+#define ST_LSM6DS3_EXT0_FULLSCALE_VALUE 0x02
+#define ST_LSM6DS3_EXT0_ODR_ADDR 0x20
+#define ST_LSM6DS3_EXT0_ODR_MASK 0x1c
+#define ST_LSM6DS3_EXT0_ODR0_HZ 10
+#define ST_LSM6DS3_EXT0_ODR0_VALUE 0x04
+#define ST_LSM6DS3_EXT0_ODR1_HZ 20
+#define ST_LSM6DS3_EXT0_ODR1_VALUE 0x05
+#define ST_LSM6DS3_EXT0_ODR2_HZ 40
+#define ST_LSM6DS3_EXT0_ODR2_VALUE 0x06
+#define ST_LSM6DS3_EXT0_ODR3_HZ 80
+#define ST_LSM6DS3_EXT0_ODR3_VALUE 0x07
+#define ST_LSM6DS3_EXT0_PW_ADDR 0x22
+#define ST_LSM6DS3_EXT0_PW_MASK 0x03
+#define ST_LSM6DS3_EXT0_PW_OFF 0x02
+#define ST_LSM6DS3_EXT0_PW_ON 0x00
+#define ST_LSM6DS3_EXT0_GAIN_VALUE 438
+#define ST_LSM6DS3_EXT0_OUT_X_L_ADDR 0x28
+#define ST_LSM6DS3_EXT0_OUT_Y_L_ADDR 0x2a
+#define ST_LSM6DS3_EXT0_OUT_Z_L_ADDR 0x2c
+#define ST_LSM6DS3_EXT0_READ_DATA_LEN 6
+#define ST_LSM6DS3_EXT0_BDU_ADDR 0x24
+#define ST_LSM6DS3_EXT0_BDU_MASK 0x40
+#define ST_LSM6DS3_EXT0_STD 3
+#define ST_LSM6DS3_EXT0_BOOT_FUNCTION (&lis3mdl_initialization)
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT0_LIS3MDL */
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912
+static int akm09912_initialization(struct lsm6ds3_sensor_data *sdata,
+ int ext_num);
+
+#define ST_LSM6DS3_EXT0_ADDR 0x0c
+#define ST_LSM6DS3_EXT0_WAI_ADDR 0x01
+#define ST_LSM6DS3_EXT0_WAI_VALUE 0x04
+#define ST_LSM6DS3_EXT0_RESET_ADDR 0x32
+#define ST_LSM6DS3_EXT0_RESET_MASK 0x01
+#define ST_LSM6DS3_EXT0_FULLSCALE_ADDR 0x00
+#define ST_LSM6DS3_EXT0_FULLSCALE_MASK 0x00
+#define ST_LSM6DS3_EXT0_FULLSCALE_VALUE 0x00
+#define ST_LSM6DS3_EXT0_ODR_ADDR 0x31
+#define ST_LSM6DS3_EXT0_ODR_MASK 0x1f
+#define ST_LSM6DS3_EXT0_ODR0_HZ 10
+#define ST_LSM6DS3_EXT0_ODR0_VALUE 0x02
+#define ST_LSM6DS3_EXT0_ODR1_HZ 20
+#define ST_LSM6DS3_EXT0_ODR1_VALUE 0x04
+#define ST_LSM6DS3_EXT0_ODR2_HZ 50
+#define ST_LSM6DS3_EXT0_ODR2_VALUE 0x06
+#define ST_LSM6DS3_EXT0_ODR3_HZ 100
+#define ST_LSM6DS3_EXT0_ODR3_VALUE 0x08
+#define ST_LSM6DS3_EXT0_PW_ADDR ST_LSM6DS3_EXT0_ODR_ADDR
+#define ST_LSM6DS3_EXT0_PW_MASK ST_LSM6DS3_EXT0_ODR_MASK
+#define ST_LSM6DS3_EXT0_PW_OFF 0x00
+#define ST_LSM6DS3_EXT0_PW_ON ST_LSM6DS3_EXT0_ODR0_VALUE
+#define ST_LSM6DS3_EXT0_GAIN_VALUE 1500
+#define ST_LSM6DS3_EXT0_OUT_X_L_ADDR 0x11
+#define ST_LSM6DS3_EXT0_OUT_Y_L_ADDR 0x13
+#define ST_LSM6DS3_EXT0_OUT_Z_L_ADDR 0x15
+#define ST_LSM6DS3_EXT0_READ_DATA_LEN 6
+#define ST_LSM6DS3_EXT0_SENSITIVITY_ADDR 0x60
+#define ST_LSM6DS3_EXT0_SENSITIVITY_LEN 3
+#define ST_LSM6DS3_EXT0_STD 3
+#define ST_LSM6DS3_EXT0_BOOT_FUNCTION (&akm09912_initialization)
+#define ST_LSM6DS3_EXT0_DATA_STATUS 0x18
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912 */
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT1_LPS22HB
+static int lps22hb_initialization(struct lsm6ds3_sensor_data *sdata,
+ int ext_num);
+
+#define ST_LSM6DS3_EXT1_ADDR 0x5d
+#define ST_LSM6DS3_EXT1_WAI_ADDR 0x0f
+#define ST_LSM6DS3_EXT1_WAI_VALUE 0xb1
+#define ST_LSM6DS3_EXT1_RESET_ADDR 0x11
+#define ST_LSM6DS3_EXT1_RESET_MASK 0x80
+#define ST_LSM6DS3_EXT1_FULLSCALE_ADDR 0x00
+#define ST_LSM6DS3_EXT1_FULLSCALE_MASK 0x00
+#define ST_LSM6DS3_EXT1_FULLSCALE_VALUE 0x00
+#define ST_LSM6DS3_EXT1_ODR_ADDR 0x10
+#define ST_LSM6DS3_EXT1_ODR_MASK 0x70
+#define ST_LSM6DS3_EXT1_ODR0_HZ 1
+#define ST_LSM6DS3_EXT1_ODR0_VALUE 0x01
+#define ST_LSM6DS3_EXT1_ODR1_HZ 10
+#define ST_LSM6DS3_EXT1_ODR1_VALUE 0x02
+#define ST_LSM6DS3_EXT1_ODR2_HZ 25
+#define ST_LSM6DS3_EXT1_ODR2_VALUE 0x03
+#define ST_LSM6DS3_EXT1_ODR3_HZ 50
+#define ST_LSM6DS3_EXT1_ODR3_VALUE 0x04
+#define ST_LSM6DS3_EXT1_PW_ADDR ST_LSM6DS3_EXT1_ODR_ADDR
+#define ST_LSM6DS3_EXT1_PW_MASK ST_LSM6DS3_EXT1_ODR_MASK
+#define ST_LSM6DS3_EXT1_PW_OFF 0x00
+#define ST_LSM6DS3_EXT1_PW_ON ST_LSM6DS3_EXT1_ODR0_VALUE
+#define ST_LSM6DS3_EXT1_GAIN_VALUE 244
+#define ST_LSM6DS3_EXT1_OUT_P_L_ADDR 0x28
+#define ST_LSM6DS3_EXT1_OUT_T_L_ADDR 0x2b
+#define ST_LSM6DS3_EXT1_READ_DATA_LEN 5
+#define ST_LSM6DS3_EXT1_BDU_ADDR 0x10
+#define ST_LSM6DS3_EXT1_BDU_MASK 0x02
+#define ST_LSM6DS3_EXT1_STD 1
+#define ST_LSM6DS3_EXT1_BOOT_FUNCTION (&lps22hb_initialization)
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_LPS22HB */
+
+/* SENSORS SUFFIX NAMES */
+#define ST_LSM6DS3_EXT0_SUFFIX_NAME "magn"
+#define ST_LSM6DS3_EXT1_SUFFIX_NAME "press"
+
+struct st_lsm6ds3_i2c_master_odr_reg {
+ unsigned int hz;
+ u8 value;
+};
+
+struct st_lsm6ds3_i2c_master_odr_table {
+ u8 addr;
+ u8 mask;
+ struct st_lsm6ds3_i2c_master_odr_reg odr_avl[ST_LSM6DS3_I2C_MASTER_ODR_LIST_NUM];
+};
+
+static int st_lsm6ds3_i2c_master_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *ch, int *val, int *val2, long mask);
+
+static const struct iio_chan_spec st_lsm6ds3_ext0_ch[] = {
+ ST_LSM6DS3_LSM_CHANNELS(IIO_MAGN, 1, 0, IIO_MOD_X, IIO_LE,
+ 16, 16, ST_LSM6DS3_EXT0_OUT_X_L_ADDR, 's'),
+ ST_LSM6DS3_LSM_CHANNELS(IIO_MAGN, 1, 1, IIO_MOD_Y, IIO_LE,
+ 16, 16, ST_LSM6DS3_EXT0_OUT_Y_L_ADDR, 's'),
+ ST_LSM6DS3_LSM_CHANNELS(IIO_MAGN, 1, 2, IIO_MOD_Z, IIO_LE,
+ 16, 16, ST_LSM6DS3_EXT0_OUT_Z_L_ADDR, 's'),
+ IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+static const struct iio_chan_spec st_lsm6ds3_ext1_ch[] = {
+ ST_LSM6DS3_LSM_CHANNELS(IIO_PRESSURE, 0, 0, IIO_NO_MOD, IIO_LE,
+ 24, 24, ST_LSM6DS3_EXT1_OUT_P_L_ADDR, 'u'),
+ ST_LSM6DS3_LSM_CHANNELS(IIO_TEMP, 0, 1, IIO_NO_MOD, IIO_LE,
+ 16, 16, ST_LSM6DS3_EXT1_OUT_T_L_ADDR, 's'),
+ IIO_CHAN_SOFT_TIMESTAMP(2)
+};
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+
+static int st_lsm6ds3_i2c_master_set_odr(struct lsm6ds3_sensor_data *sdata,
+ unsigned int odr);
+
+static ssize_t st_lsm6ds3_i2c_master_sysfs_sampling_frequency_avail(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE,
+ "%d %d %d %d %d\n", 26, 52, 104, 208, 416);
+}
+
+static ssize_t st_lsm6ds3_i2c_master_sysfs_get_sampling_frequency(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct lsm6ds3_sensor_data *sdata = iio_priv(dev_get_drvdata(dev));
+
+ return sprintf(buf, "%d\n", sdata->c_odr);
+}
+
+static ssize_t st_lsm6ds3_i2c_master_sysfs_set_sampling_frequency(
+ struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int err, err2 = -EINVAL;
+ unsigned int odr;
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ err = kstrtoint(buf, 10, &odr);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&indio_dev->mlock);
+
+ switch (odr) {
+ case 26:
+ case 52:
+ case 104:
+ case 208:
+ case 416:
+ if (sdata->c_odr != odr) {
+
+ mutex_lock(&sdata->cdata->passthrough_lock);
+
+ disable_irq(sdata->cdata->irq);
+ st_lsm6ds3_flush_works();
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata, true);
+ if (err < 0) {
+ enable_irq(sdata->cdata->irq);
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+ mutex_unlock(&indio_dev->mlock);
+ return err;
+ }
+
+ err2 = st_lsm6ds3_i2c_master_set_odr(sdata, odr);
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata,
+ false);
+ if (err < 0) {
+ enable_irq(sdata->cdata->irq);
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+ mutex_unlock(&indio_dev->mlock);
+ return err;
+ }
+
+ enable_irq(sdata->cdata->irq);
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+ }
+ break;
+ default:
+ err2 = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return err2 < 0 ? err2 : size;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+ st_lsm6ds3_i2c_master_sysfs_get_sampling_frequency,
+ st_lsm6ds3_i2c_master_sysfs_set_sampling_frequency);
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(
+ st_lsm6ds3_i2c_master_sysfs_sampling_frequency_avail);
+static ST_LSM6DS3_FIFO_LENGHT();
+static ST_LSM6DS3_FIFO_FLUSH();
+
+static struct attribute *st_lsm6ds3_ext0_attributes[] = {
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_sampling_frequency.dev_attr.attr,
+ &iio_dev_attr_hw_fifo_lenght.dev_attr.attr,
+ &iio_dev_attr_flush.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group st_lsm6ds3_ext0_attribute_group = {
+ .attrs = st_lsm6ds3_ext0_attributes,
+};
+
+static const struct iio_info st_lsm6ds3_ext0_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6ds3_ext0_attribute_group,
+ .read_raw = &st_lsm6ds3_i2c_master_read_raw,
+};
+
+static struct attribute *st_lsm6ds3_ext1_attributes[] = {
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_sampling_frequency.dev_attr.attr,
+ &iio_dev_attr_hw_fifo_lenght.dev_attr.attr,
+ &iio_dev_attr_flush.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group st_lsm6ds3_ext1_attribute_group = {
+ .attrs = st_lsm6ds3_ext1_attributes,
+};
+
+static const struct iio_info st_lsm6ds3_ext1_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6ds3_ext1_attribute_group,
+ .read_raw = &st_lsm6ds3_i2c_master_read_raw,
+};
+
+struct st_lsm6ds3_iio_info_data {
+ char suffix_name[20];
+ struct iio_info *info;
+ struct iio_chan_spec *channels;
+ int num_channels;
+};
+
+struct st_lsm6ds3_reg {
+ u8 addr;
+ u8 mask;
+ u8 def_value;
+};
+
+struct st_lsm6ds3_power_reg {
+ u8 addr;
+ u8 mask;
+ u8 off_value;
+ u8 on_value;
+ bool isodr;
+};
+
+struct st_lsm6ds3_custom_function {
+ int (*boot_initialization) (struct lsm6ds3_sensor_data *sdata,
+ int ext_num);
+};
+
+static struct st_lsm6ds3_exs_list {
+ struct st_lsm6ds3_reg wai;
+ struct st_lsm6ds3_reg reset;
+ struct st_lsm6ds3_reg fullscale;
+ struct st_lsm6ds3_i2c_master_odr_table odr;
+ struct st_lsm6ds3_power_reg power;
+ u8 fullscale_value;
+ u8 samples_to_discard;
+ u8 read_data_len;
+ u8 num_data_channels;
+ bool available;
+ unsigned int gain;
+ struct i2c_board_info board_info;
+ struct st_lsm6ds3_iio_info_data data;
+ struct st_lsm6ds3_custom_function cf;
+} st_lsm6ds3_exs_list[] = {
+ {
+ .wai = {
+ .addr = ST_LSM6DS3_EXT0_WAI_ADDR,
+ .def_value = ST_LSM6DS3_EXT0_WAI_VALUE,
+ },
+ .reset = {
+ .addr = ST_LSM6DS3_EXT0_RESET_ADDR,
+ .mask = ST_LSM6DS3_EXT0_RESET_MASK,
+ },
+ .fullscale = {
+ .addr = ST_LSM6DS3_EXT0_FULLSCALE_ADDR,
+ .mask = ST_LSM6DS3_EXT0_FULLSCALE_MASK,
+ .def_value = ST_LSM6DS3_EXT0_FULLSCALE_VALUE,
+ },
+ .odr = {
+ .addr = ST_LSM6DS3_EXT0_ODR_ADDR,
+ .mask = ST_LSM6DS3_EXT0_ODR_MASK,
+ .odr_avl = {
+ {
+ .hz = ST_LSM6DS3_EXT0_ODR0_HZ,
+ .value = ST_LSM6DS3_EXT0_ODR0_VALUE,
+ },
+ {
+ .hz = ST_LSM6DS3_EXT0_ODR1_HZ,
+ .value = ST_LSM6DS3_EXT0_ODR1_VALUE,
+ },
+ {
+ .hz = ST_LSM6DS3_EXT0_ODR2_HZ,
+ .value = ST_LSM6DS3_EXT0_ODR2_VALUE,
+ },
+ {
+ .hz = ST_LSM6DS3_EXT0_ODR3_HZ,
+ .value = ST_LSM6DS3_EXT0_ODR3_VALUE,
+ },
+ },
+ },
+ .power = {
+ .addr = ST_LSM6DS3_EXT0_PW_ADDR,
+ .mask = ST_LSM6DS3_EXT0_PW_MASK,
+ .off_value = ST_LSM6DS3_EXT0_PW_OFF,
+ .on_value = ST_LSM6DS3_EXT0_PW_ON,
+ },
+ .samples_to_discard = ST_LSM6DS3_EXT0_STD,
+ .read_data_len = ST_LSM6DS3_EXT0_READ_DATA_LEN,
+ .num_data_channels = ARRAY_SIZE(st_lsm6ds3_ext0_ch) - 1,
+ .available = false,
+ .gain = ST_LSM6DS3_EXT0_GAIN_VALUE,
+ .board_info = { .addr = ST_LSM6DS3_EXT0_ADDR, },
+ .data = {
+ .suffix_name = ST_LSM6DS3_EXT0_SUFFIX_NAME,
+ .info = (struct iio_info *)&st_lsm6ds3_ext0_info,
+ .channels = (struct iio_chan_spec *)&st_lsm6ds3_ext0_ch,
+ .num_channels = ARRAY_SIZE(st_lsm6ds3_ext0_ch),
+ },
+ .cf.boot_initialization = ST_LSM6DS3_EXT0_BOOT_FUNCTION,
+ },
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+ {
+ .wai = {
+ .addr = ST_LSM6DS3_EXT1_WAI_ADDR,
+ .def_value = ST_LSM6DS3_EXT1_WAI_VALUE,
+ },
+ .reset = {
+ .addr = ST_LSM6DS3_EXT1_RESET_ADDR,
+ .mask = ST_LSM6DS3_EXT1_RESET_MASK,
+ },
+ .fullscale = {
+ .addr = ST_LSM6DS3_EXT1_FULLSCALE_ADDR,
+ .mask = ST_LSM6DS3_EXT1_FULLSCALE_MASK,
+ .def_value = ST_LSM6DS3_EXT1_FULLSCALE_VALUE,
+ },
+ .odr = {
+ .addr = ST_LSM6DS3_EXT1_ODR_ADDR,
+ .mask = ST_LSM6DS3_EXT1_ODR_MASK,
+ .odr_avl = {
+ {
+ .hz = ST_LSM6DS3_EXT1_ODR0_HZ,
+ .value = ST_LSM6DS3_EXT1_ODR0_VALUE,
+ },
+ {
+ .hz = ST_LSM6DS3_EXT1_ODR1_HZ,
+ .value = ST_LSM6DS3_EXT1_ODR1_VALUE,
+ },
+ {
+ .hz = ST_LSM6DS3_EXT1_ODR2_HZ,
+ .value = ST_LSM6DS3_EXT1_ODR2_VALUE,
+ },
+ {
+ .hz = ST_LSM6DS3_EXT1_ODR3_HZ,
+ .value = ST_LSM6DS3_EXT1_ODR3_VALUE,
+ },
+ },
+ },
+ .power = {
+ .addr = ST_LSM6DS3_EXT1_PW_ADDR,
+ .mask = ST_LSM6DS3_EXT1_PW_MASK,
+ .off_value = ST_LSM6DS3_EXT1_PW_OFF,
+ .on_value = ST_LSM6DS3_EXT1_PW_ON,
+ },
+ .samples_to_discard = ST_LSM6DS3_EXT1_STD,
+ .read_data_len = ST_LSM6DS3_EXT1_READ_DATA_LEN,
+ .num_data_channels = ARRAY_SIZE(st_lsm6ds3_ext1_ch) - 1,
+ .available = false,
+ .gain = ST_LSM6DS3_EXT1_GAIN_VALUE,
+ .board_info = { .addr = ST_LSM6DS3_EXT1_ADDR, },
+ .data = {
+ .suffix_name = ST_LSM6DS3_EXT1_SUFFIX_NAME,
+ .info = (struct iio_info *)&st_lsm6ds3_ext1_info,
+ .channels = (struct iio_chan_spec *)&st_lsm6ds3_ext1_ch,
+ .num_channels = ARRAY_SIZE(st_lsm6ds3_ext1_ch),
+ },
+ .cf.boot_initialization = ST_LSM6DS3_EXT1_BOOT_FUNCTION,
+ },
+#else /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+ {
+ },
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+};
+
+static int st_lsm6ds3_i2c_master_read(struct i2c_client *client,
+ u8 reg_addr, int len, u8 *data)
+{
+ struct i2c_msg msg[2];
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags;
+ msg[0].len = 1;
+ msg[0].buf = &reg_addr;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags | I2C_M_RD;
+ msg[1].len = len;
+ msg[1].buf = data;
+
+ return i2c_transfer(client->adapter, msg, 2);
+}
+
+static int st_lsm6ds3_i2c_master_write(struct i2c_client *client,
+ u8 reg_addr, int len, u8 *data)
+{
+ u8 send[len + 1];
+ struct i2c_msg msg;
+
+ send[0] = reg_addr;
+ memcpy(&send[1], data, len * sizeof(u8));
+ len++;
+
+ msg.addr = client->addr;
+ msg.flags = client->flags;
+ msg.len = len;
+ msg.buf = send;
+
+ return i2c_transfer(client->adapter, &msg, 1);
+}
+
+static int st_lsm6ds3_i2c_master_write_data_with_mask(struct i2c_client *client,
+ u8 reg_addr, u8 mask, u8 data)
+{
+ int err;
+ u8 new_data = 0x00, old_data = 0x00;
+
+ err = st_lsm6ds3_i2c_master_read(client, reg_addr, 1, &old_data);
+ if (err < 0)
+ return err;
+
+ new_data = ((old_data & (~mask)) | ((data << __ffs(mask)) & mask));
+
+ if (new_data == old_data)
+ return 1;
+
+ return st_lsm6ds3_i2c_master_write(client, reg_addr, 1, &new_data);
+}
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT0_LIS3MDL
+static int lis3mdl_initialization(struct lsm6ds3_sensor_data *sdata,
+ int ext_num)
+{
+
+ return st_lsm6ds3_i2c_master_write_data_with_mask(
+ sdata->cdata->master_client[ext_num],
+ ST_LSM6DS3_EXT0_BDU_ADDR,
+ ST_LSM6DS3_EXT0_BDU_MASK, ST_LSM6DS3_EN_BIT);
+}
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT0_LIS3MDL */
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912
+static int akm09912_initialization(struct lsm6ds3_sensor_data *sdata,
+ int ext_num)
+{
+ int err;
+ u8 data[ST_LSM6DS3_EXT0_SENSITIVITY_LEN];
+
+ err = st_lsm6ds3_i2c_master_read(sdata->cdata->master_client[ext_num],
+ ST_LSM6DS3_EXT0_SENSITIVITY_ADDR,
+ ST_LSM6DS3_EXT0_SENSITIVITY_LEN,
+ data);
+ if (err < 0)
+ return err;
+
+ sdata->c_gain[0] *= ((((data[0] - 128) * 1000) >> 8) + 1000);
+ sdata->c_gain[1] *= ((((data[1] - 128) * 1000) >> 8) + 1000);
+ sdata->c_gain[2] *= ((((data[2] - 128) * 1000) >> 8) + 1000);
+
+ return 0;
+}
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912 */
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT1_LPS22HB
+static int lps22hb_initialization(struct lsm6ds3_sensor_data *sdata,
+ int ext_num)
+{
+
+ return st_lsm6ds3_i2c_master_write_data_with_mask(
+ sdata->cdata->master_client[ext_num],
+ ST_LSM6DS3_EXT1_BDU_ADDR,
+ ST_LSM6DS3_EXT1_BDU_MASK, ST_LSM6DS3_EN_BIT);
+}
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_LPS22HB */
+
+static int st_lsm6ds3_i2c_master_set_odr(struct lsm6ds3_sensor_data *sdata,
+ unsigned int odr)
+{
+ int err, i, ext_num = sdata->sindex - ST_INDIO_DEV_EXT0;
+
+ for (i = 0; i < ST_LSM6DS3_I2C_MASTER_ODR_LIST_NUM; i++) {
+ if (st_lsm6ds3_exs_list[ext_num].odr.odr_avl[i].hz >= odr)
+ break;
+ }
+ if (i == ST_LSM6DS3_I2C_MASTER_ODR_LIST_NUM)
+ i--;
+
+ if (sdata->cdata->sensors_enabled & (1 << sdata->sindex)) {
+ err = st_lsm6ds3_i2c_master_write_data_with_mask(
+ sdata->cdata->master_client[ext_num],
+ st_lsm6ds3_exs_list[ext_num].odr.addr,
+ st_lsm6ds3_exs_list[ext_num].odr.mask,
+ st_lsm6ds3_exs_list[ext_num].odr.odr_avl[i].value);
+ if (err < 0)
+ return err;
+
+ sdata->cdata->ext_samples_to_discard[ext_num] =
+ st_lsm6ds3_exs_list[ext_num].samples_to_discard;
+
+ sdata->c_odr = odr;
+
+ if (st_lsm6ds3_exs_list[ext_num].power.isodr)
+ st_lsm6ds3_exs_list[ext_num].power.on_value =
+ st_lsm6ds3_exs_list[ext_num].odr.odr_avl[i].value;
+
+ st_lsm6ds3_reconfigure_fifo(sdata->cdata, false);
+ } else {
+ sdata->c_odr = odr;
+
+ if (st_lsm6ds3_exs_list[ext_num].power.isodr)
+ st_lsm6ds3_exs_list[ext_num].power.on_value =
+ st_lsm6ds3_exs_list[ext_num].odr.odr_avl[i].value;
+ }
+
+ return 0;
+}
+
+static int st_lsm6ds3_i2c_master_set_enable(struct lsm6ds3_sensor_data *sdata,
+ bool enable)
+{
+ u8 reg_value;
+ int err, ext_num = sdata->sindex - ST_INDIO_DEV_EXT0;
+
+ if (enable)
+ reg_value = st_lsm6ds3_exs_list[ext_num].power.on_value;
+ else
+ reg_value = st_lsm6ds3_exs_list[ext_num].power.off_value;
+
+ err = st_lsm6ds3_i2c_master_write_data_with_mask(
+ sdata->cdata->master_client[ext_num],
+ st_lsm6ds3_exs_list[ext_num].power.addr,
+ st_lsm6ds3_exs_list[ext_num].power.mask,
+ reg_value);
+ if (err < 0)
+ return err;
+
+ sdata->cdata->ext_samples_to_discard[ext_num] =
+ st_lsm6ds3_exs_list[ext_num].samples_to_discard;
+
+ if (enable)
+ sdata->cdata->sensors_enabled |= (1 << sdata->sindex);
+ else
+ sdata->cdata->sensors_enabled &= ~(1 << sdata->sindex);
+
+ return 0;
+}
+
+static int st_lsm6ds3_i2c_master_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+{
+ int err;
+ u8 outdata[(ch->scan_type.storagebits >> 3) + 1];
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&indio_dev->mlock);
+
+ if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+ mutex_unlock(&indio_dev->mlock);
+ return -EBUSY;
+ }
+
+ mutex_lock(&sdata->cdata->passthrough_lock);
+
+ err = st_lsm6ds3_enable_accel_dependency(sdata, true);
+ if (err < 0)
+ return err;
+
+ disable_irq(sdata->cdata->irq);
+ st_lsm6ds3_flush_works();
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata, true);
+ if (err < 0)
+ goto read_raw_reset_passthrough;
+
+ err = st_lsm6ds3_i2c_master_set_enable(sdata, true);
+ if (err < 0)
+ goto read_raw_reset_passthrough;
+
+ memset(outdata, 0, (ch->scan_type.storagebits >> 3) + 1);
+
+ msleep(200);
+
+ err = st_lsm6ds3_i2c_master_read(
+ sdata->cdata->master_client[sdata->sindex -
+ ST_INDIO_DEV_EXT0], ch->address,
+ ch->scan_type.storagebits >> 3, outdata);
+ if (err < 0)
+ goto read_raw_reset_passthrough;
+
+ err = st_lsm6ds3_i2c_master_set_enable(sdata, false);
+ if (err < 0)
+ goto read_raw_reset_passthrough;
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata, false);
+ if (err < 0)
+ goto read_raw_reset_passthrough;
+
+ enable_irq(sdata->cdata->irq);
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+
+ err = st_lsm6ds3_enable_accel_dependency(sdata, false);
+ if (err < 0)
+ return err;
+
+ if ((ch->scan_type.storagebits >> 3) > 2)
+ *val = (s32)get_unaligned_le32(outdata);
+ else
+ *val = (s16)get_unaligned_le16(outdata);
+
+ *val = *val >> ch->scan_type.shift;
+
+ mutex_unlock(&indio_dev->mlock);
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = sdata->c_gain[ch->scan_index];
+
+ if (ch->type == IIO_TEMP) {
+ *val = 1;
+ *val2 = 0;
+ return IIO_VAL_INT;
+ }
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912
+ if (sdata->sindex == ST_INDIO_DEV_EXT0)
+ return IIO_VAL_INT_PLUS_NANO;
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912 */
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+
+read_raw_reset_passthrough:
+ st_lsm6ds3_enable_passthrough(sdata->cdata, false);
+ enable_irq(sdata->cdata->irq);
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+ st_lsm6ds3_enable_accel_dependency(sdata, false);
+ return err;
+}
+
+static int st_lsm6ds3_i2c_master_buffer_preenable(struct iio_dev *indio_dev)
+{
+ int err;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ mutex_lock(&sdata->cdata->passthrough_lock);
+
+ err = st_lsm6ds3_enable_accel_dependency(sdata, true);
+ if (err < 0)
+ return err;
+
+ disable_irq(sdata->cdata->irq);
+ st_lsm6ds3_flush_works();
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata, true);
+ if (err < 0)
+ goto preenable_reset_passthrough;
+
+ err = st_lsm6ds3_i2c_master_set_enable(sdata, true);
+ if (err < 0)
+ goto preenable_reset_passthrough;
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata, false);
+ if (err < 0)
+ goto preenable_reset_passthrough;
+
+ enable_irq(sdata->cdata->irq);
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+
+ err = st_lsm6ds3_reconfigure_fifo(sdata->cdata, true);
+ if (err < 0)
+ return err;
+
+ return iio_sw_buffer_preenable(indio_dev);
+
+preenable_reset_passthrough:
+ st_lsm6ds3_enable_passthrough(sdata->cdata, false);
+ enable_irq(sdata->cdata->irq);
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+
+ return err;
+}
+
+static int st_lsm6ds3_i2c_master_buffer_postenable(struct iio_dev *indio_dev)
+{
+ int err;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ sdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+ if (sdata->buffer_data == NULL)
+ return -ENOMEM;
+
+ err = iio_triggered_buffer_postenable(indio_dev);
+ if (err < 0)
+ goto free_buffer_data;
+
+ return 0;
+
+free_buffer_data:
+ kfree(sdata->buffer_data);
+
+ return err;
+}
+
+static int st_lsm6ds3_i2c_master_buffer_predisable(struct iio_dev *indio_dev)
+{
+ int err;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(indio_dev);
+
+ err = iio_triggered_buffer_predisable(indio_dev);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&sdata->cdata->passthrough_lock);
+
+ disable_irq(sdata->cdata->irq);
+ st_lsm6ds3_flush_works();
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata, true);
+ if (err < 0)
+ goto predisable_reset_passthrough;
+
+ err = st_lsm6ds3_i2c_master_set_enable(sdata, false);
+ if (err < 0)
+ goto predisable_reset_passthrough;
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata, false);
+ if (err < 0)
+ goto predisable_reset_passthrough;
+
+ enable_irq(sdata->cdata->irq);
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+
+ err = st_lsm6ds3_enable_accel_dependency(sdata, false);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6ds3_reconfigure_fifo(sdata->cdata, true);
+ if (err < 0)
+ return err;
+
+ kfree(sdata->buffer_data);
+
+ return 0;
+
+predisable_reset_passthrough:
+ st_lsm6ds3_enable_passthrough(sdata->cdata, false);
+ enable_irq(sdata->cdata->irq);
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+
+ return err;
+}
+
+static const struct iio_trigger_ops st_lsm6ds3_i2c_master_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &st_lsm6ds3_trig_set_state,
+};
+
+int st_lsm6ds3_i2c_master_allocate_trigger(struct lsm6ds3_data *cdata,
+ int dev_index)
+{
+ int err;
+
+ cdata->trig[dev_index] = iio_trigger_alloc("%s-trigger",
+ cdata->indio_dev[dev_index]->name);
+ if (!cdata->trig[dev_index]) {
+ dev_err(cdata->dev, "failed to allocate iio trigger.\n");
+ return -ENOMEM;
+ }
+
+ iio_trigger_set_drvdata(cdata->trig[dev_index],
+ cdata->indio_dev[dev_index]);
+ cdata->trig[dev_index]->ops = &st_lsm6ds3_i2c_master_trigger_ops;
+ cdata->trig[dev_index]->dev.parent = cdata->dev;
+
+ err = iio_trigger_register(cdata->trig[dev_index]);
+ if (err < 0) {
+ dev_err(cdata->dev, "failed to register iio trigger.\n");
+ goto deallocate_trigger;
+ }
+
+ cdata->indio_dev[dev_index]->trig = cdata->trig[dev_index];
+
+ return 0;
+
+deallocate_trigger:
+ iio_trigger_free(cdata->trig[dev_index]);
+ return err;
+}
+
+static void st_lsm6ds3_i2c_master_deallocate_trigger(struct lsm6ds3_data *cdata,
+ int dev_index)
+{
+ iio_trigger_unregister(cdata->trig[dev_index]);
+}
+
+static const struct iio_buffer_setup_ops st_lsm6ds3_i2c_master_buffer_setup_ops = {
+ .preenable = &st_lsm6ds3_i2c_master_buffer_preenable,
+ .postenable = &st_lsm6ds3_i2c_master_buffer_postenable,
+ .predisable = &st_lsm6ds3_i2c_master_buffer_predisable,
+};
+
+static inline irqreturn_t st_lsm6ds3_i2c_master_handler_empty(int irq, void *p)
+{
+ return IRQ_HANDLED;
+}
+
+static int st_lsm6ds3_i2c_master_allocate_buffer(struct lsm6ds3_data *cdata,
+ int dev_index)
+{
+ return iio_triggered_buffer_setup(cdata->indio_dev[dev_index],
+ &st_lsm6ds3_i2c_master_handler_empty, NULL,
+ &st_lsm6ds3_i2c_master_buffer_setup_ops);
+}
+
+static void st_lsm6ds3_i2c_master_deallocate_buffer(struct lsm6ds3_data *cdata,
+ int dev_index)
+{
+ iio_triggered_buffer_cleanup(cdata->indio_dev[dev_index]);
+}
+
+static int st_lsm6ds3_i2c_master_send_sensor_hub_parameters(
+ struct lsm6ds3_sensor_data *sdata, int ext_num)
+{
+ int err;
+ u8 i2c_address_reg, data_start_address_reg, slave_num;
+ u8 i2c_address, data_start_address, config_reg_addr, config_reg_mask;
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912
+ u8 i2c_address_reg_akm, data_start_address_reg_akm, temp_reg;
+ u8 config_reg_addr_akm, config_reg_mask_akm;
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912 */
+
+ switch (ext_num) {
+ case ST_LSM6DS3_EXT0_INDEX:
+ i2c_address_reg = ST_LSM6DS3_SLV0_ADDR_ADDR;
+ data_start_address_reg = ST_LSM6DS3_SLV0_SUBADDR_ADDR;
+ config_reg_addr = ST_LSM6DS3_SLV0_CONFIG_ADDR;
+ config_reg_mask = ST_LSM6DS3_SLV0_CONFIG_MASK;
+ break;
+ case ST_LSM6DS3_EXT1_INDEX:
+ i2c_address_reg = ST_LSM6DS3_SLV1_ADDR_ADDR;
+ data_start_address_reg = ST_LSM6DS3_SLV1_SUBADDR_ADDR;
+ config_reg_addr = ST_LSM6DS3_SLV1_CONFIG_ADDR;
+ config_reg_mask = ST_LSM6DS3_SLV1_CONFIG_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ i2c_address = (st_lsm6ds3_exs_list[ext_num].board_info.addr << 1) |
+ ST_LSM6DS3_EN_BIT;
+
+ data_start_address =
+ st_lsm6ds3_exs_list[ext_num].data.channels[0].address;
+
+ mutex_lock(&sdata->cdata->bank_registers_lock);
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_FUNC_CFG_ACCESS_ADDR,
+ ST_LSM6DS3_FUNC_CFG_REG2_MASK,
+ ST_LSM6DS3_EN_BIT, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ err = sdata->cdata->tf->write(sdata->cdata, i2c_address_reg,
+ 1, &i2c_address, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ err = sdata->cdata->tf->write(sdata->cdata,
+ data_start_address_reg,
+ 1, &data_start_address, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ config_reg_addr, config_reg_mask,
+ st_lsm6ds3_exs_list[ext_num].read_data_len,
+ false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ if (ext_num == ST_LSM6DS3_EXT0_INDEX) {
+ if (sdata->cdata->ext1_available) {
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912
+ slave_num = ST_LSM6DS3_SLV_AUX_3;
+ i2c_address_reg_akm = ST_LSM6DS3_SLV2_ADDR_ADDR;
+ data_start_address_reg_akm = ST_LSM6DS3_SLV2_SUBADDR_ADDR;
+ config_reg_addr_akm = ST_LSM6DS3_SLV2_CONFIG_ADDR;
+ config_reg_mask_akm = ST_LSM6DS3_SLV2_CONFIG_MASK;
+#else /* CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912 */
+ slave_num = ST_LSM6DS3_SLV_AUX_2;
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912 */
+ } else {
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912
+ slave_num = ST_LSM6DS3_SLV_AUX_2;
+ i2c_address_reg_akm = ST_LSM6DS3_SLV1_ADDR_ADDR;
+ data_start_address_reg_akm = ST_LSM6DS3_SLV1_SUBADDR_ADDR;
+ config_reg_addr_akm = ST_LSM6DS3_SLV1_CONFIG_ADDR;
+ config_reg_mask_akm = ST_LSM6DS3_SLV1_CONFIG_MASK;
+#else /* CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912 */
+ slave_num = ST_LSM6DS3_SLV_AUX_1;
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912 */
+ }
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_SLV_AUX_ADDR,
+ ST_LSM6DS3_SLV_AUX_MASK,
+ slave_num, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+#ifdef CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912
+ temp_reg = (ST_LSM6DS3_EXT0_ADDR << 1) | ST_LSM6DS3_EN_BIT;
+
+ err = sdata->cdata->tf->write(sdata->cdata, i2c_address_reg_akm,
+ 1, &temp_reg, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ temp_reg = ST_LSM6DS3_EXT0_DATA_STATUS;
+
+ err = sdata->cdata->tf->write(sdata->cdata,
+ data_start_address_reg_akm,
+ 1, &temp_reg, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ config_reg_addr_akm, config_reg_mask_akm,
+ 1, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT0_AKM09912 */
+ }
+
+ err = st_lsm6ds3_write_data_with_mask(sdata->cdata,
+ ST_LSM6DS3_FUNC_CFG_ACCESS_ADDR,
+ ST_LSM6DS3_FUNC_CFG_REG2_MASK,
+ ST_LSM6DS3_DIS_BIT, false);
+ if (err < 0)
+ goto st_lsm6ds3_init_sensor_mutex_unlock;
+
+ mutex_unlock(&sdata->cdata->bank_registers_lock);
+
+ return 0;
+
+st_lsm6ds3_init_sensor_mutex_unlock:
+ mutex_unlock(&sdata->cdata->bank_registers_lock);
+ return err;
+}
+
+static int st_lsm6ds3_i2c_master_init_sensor(struct lsm6ds3_sensor_data *sdata,
+ int ext_num, int dev_index)
+{
+ int err;
+
+ mutex_lock(&sdata->cdata->passthrough_lock);
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata, true);
+ if (err < 0)
+ goto unlock_passthrough;
+
+ sdata->c_gain[0] = st_lsm6ds3_exs_list[ext_num].gain;
+ sdata->c_gain[1] = st_lsm6ds3_exs_list[ext_num].gain;
+ sdata->c_gain[2] = st_lsm6ds3_exs_list[ext_num].gain;
+
+ if ((st_lsm6ds3_exs_list[ext_num].power.addr ==
+ st_lsm6ds3_exs_list[ext_num].odr.addr) &&
+ (st_lsm6ds3_exs_list[ext_num].power.mask ==
+ st_lsm6ds3_exs_list[ext_num].odr.mask))
+ st_lsm6ds3_exs_list[ext_num].power.isodr = true;
+ else
+ st_lsm6ds3_exs_list[ext_num].power.isodr = false;
+
+ err = st_lsm6ds3_i2c_master_write_data_with_mask(
+ sdata->cdata->master_client[ext_num],
+ st_lsm6ds3_exs_list[ext_num].reset.addr,
+ st_lsm6ds3_exs_list[ext_num].reset.mask,
+ ST_LSM6DS3_EN_BIT);
+ if (err < 0)
+ goto unlock_passthrough;
+
+ usleep_range(3000, 8000);
+
+ if (st_lsm6ds3_exs_list[ext_num].fullscale.addr > 0) {
+ err = st_lsm6ds3_i2c_master_write_data_with_mask(
+ sdata->cdata->master_client[ext_num],
+ st_lsm6ds3_exs_list[ext_num].fullscale.addr,
+ st_lsm6ds3_exs_list[ext_num].fullscale.mask,
+ st_lsm6ds3_exs_list[ext_num].fullscale.def_value);
+ if (err < 0)
+ goto unlock_passthrough;
+ }
+
+ if (st_lsm6ds3_exs_list[ext_num].cf.boot_initialization != NULL) {
+ err = st_lsm6ds3_exs_list[ext_num].cf.boot_initialization(sdata, ext_num);
+ if (err < 0)
+ goto unlock_passthrough;
+ }
+
+ err = st_lsm6ds3_i2c_master_set_enable(sdata, false);
+ if (err < 0)
+ goto unlock_passthrough;
+
+ err = st_lsm6ds3_i2c_master_set_odr(sdata, 26);
+ if (err < 0)
+ goto unlock_passthrough;
+
+ err = st_lsm6ds3_i2c_master_send_sensor_hub_parameters(sdata, ext_num);
+ if (err < 0)
+ goto unlock_passthrough;
+
+ err = st_lsm6ds3_enable_passthrough(sdata->cdata, false);
+ if (err < 0)
+ goto unlock_passthrough;
+
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+
+ return 0;
+
+unlock_passthrough:
+ mutex_unlock(&sdata->cdata->passthrough_lock);
+ return err;
+}
+
+static int st_lsm6ds3_i2c_master_allocate_device(struct lsm6ds3_data *cdata,
+ int ext_num)
+{
+ int err, dev_index;
+ struct lsm6ds3_sensor_data *sdata_ext;
+
+ switch (ext_num) {
+ case ST_LSM6DS3_EXT0_INDEX:
+ dev_index = ST_INDIO_DEV_EXT0;
+ break;
+ case ST_LSM6DS3_EXT1_INDEX:
+ dev_index = ST_INDIO_DEV_EXT1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cdata->indio_dev[dev_index] = iio_device_alloc(sizeof(*sdata_ext));
+ if (!cdata->indio_dev[dev_index])
+ return -ENOMEM;
+
+ sdata_ext = iio_priv(cdata->indio_dev[dev_index]);
+ sdata_ext->cdata = cdata;
+ sdata_ext->sindex = dev_index;
+
+ sdata_ext->num_data_channels =
+ st_lsm6ds3_exs_list[ext_num].num_data_channels;
+
+ cdata->indio_dev[dev_index]->name = kasprintf(GFP_KERNEL,
+ "%s_%s", cdata->name,
+ st_lsm6ds3_exs_list[ext_num].data.suffix_name);
+
+ cdata->indio_dev[dev_index]->info =
+ st_lsm6ds3_exs_list[ext_num].data.info;
+ cdata->indio_dev[dev_index]->channels =
+ st_lsm6ds3_exs_list[ext_num].data.channels;
+ cdata->indio_dev[dev_index]->num_channels =
+ st_lsm6ds3_exs_list[ext_num].data.num_channels;
+
+ cdata->indio_dev[dev_index]->modes = INDIO_DIRECT_MODE;
+
+ err = st_lsm6ds3_i2c_master_init_sensor(sdata_ext, ext_num, dev_index);
+ if (err < 0)
+ goto iio_device_free;
+
+ err = st_lsm6ds3_i2c_master_allocate_buffer(cdata, dev_index);
+ if (err < 0)
+ goto iio_device_free;
+
+ err = st_lsm6ds3_i2c_master_allocate_trigger(cdata, dev_index);
+ if (err < 0)
+ goto iio_deallocate_buffer;
+
+ err = iio_device_register(cdata->indio_dev[dev_index]);
+ if (err < 0)
+ goto iio_deallocate_trigger;
+
+ return 0;
+
+iio_deallocate_trigger:
+ st_lsm6ds3_i2c_master_deallocate_trigger(cdata, dev_index);
+iio_deallocate_buffer:
+ st_lsm6ds3_i2c_master_deallocate_buffer(cdata, dev_index);
+iio_device_free:
+ iio_device_free(cdata->indio_dev[dev_index]);
+
+ return err;
+}
+
+static void st_lsm6ds3_i2c_master_deallocate_device(struct lsm6ds3_data *cdata,
+ int ext_num)
+{
+ int dev_index;
+
+ switch (ext_num) {
+ case ST_LSM6DS3_EXT0_INDEX:
+ dev_index = ST_INDIO_DEV_EXT0;
+ break;
+ case ST_LSM6DS3_EXT1_INDEX:
+ dev_index = ST_INDIO_DEV_EXT1;
+ break;
+ default:
+ return;
+ }
+
+ iio_device_unregister(cdata->indio_dev[dev_index]);
+ st_lsm6ds3_i2c_master_deallocate_trigger(cdata, dev_index);
+ st_lsm6ds3_i2c_master_deallocate_buffer(cdata, dev_index);
+ iio_device_free(cdata->indio_dev[dev_index]);
+}
+
+int st_lsm6ds3_i2c_master_probe(struct lsm6ds3_data *cdata)
+{
+ u8 wai;
+ int err;
+ struct i2c_client *client = to_i2c_client(cdata->dev);
+
+ cdata->ext0_available = false;
+ cdata->ext1_available = false;
+
+ cdata->ext0_samples_in_pattern = 0;
+ cdata->ext1_samples_in_pattern = 0;
+
+ sprintf(st_lsm6ds3_exs_list[ST_LSM6DS3_EXT0_INDEX].board_info.type,
+ "%s_ext%d", client->name, ST_LSM6DS3_EXT0_INDEX);
+
+ cdata->master_client[ST_LSM6DS3_EXT0_INDEX] =
+ i2c_new_device(client->adapter,
+ &st_lsm6ds3_exs_list[ST_LSM6DS3_EXT0_INDEX].board_info);
+ if (!cdata->master_client[ST_LSM6DS3_EXT0_INDEX])
+ return -ENOMEM;
+
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+ sprintf(st_lsm6ds3_exs_list[ST_LSM6DS3_EXT1_INDEX].board_info.type,
+ "%s_ext%d", client->name, ST_LSM6DS3_EXT1_INDEX);
+
+ cdata->master_client[ST_LSM6DS3_EXT1_INDEX] =
+ i2c_new_device(client->adapter,
+ &st_lsm6ds3_exs_list[ST_LSM6DS3_EXT1_INDEX].board_info);
+ if (!cdata->master_client[ST_LSM6DS3_EXT1_INDEX]) {
+ err = -ENOMEM;
+ goto unregister_ext0_i2c_client;
+ }
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+
+ mutex_lock(&cdata->passthrough_lock);
+
+ err = st_lsm6ds3_enable_passthrough(cdata, true);
+ if (err < 0)
+ goto master_probe_passthrough_lock;
+
+ err = st_lsm6ds3_i2c_master_read(
+ cdata->master_client[ST_LSM6DS3_EXT0_INDEX],
+ st_lsm6ds3_exs_list[ST_LSM6DS3_EXT0_INDEX].wai.addr, 1, &wai);
+ if (err < 0) {
+ dev_err(cdata->dev, "external sensor 0 not available\n");
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT0_INDEX]);
+ } else {
+ if (wai != st_lsm6ds3_exs_list[ST_LSM6DS3_EXT0_INDEX].wai.def_value) {
+ dev_err(cdata->dev, "wai value of external sensor 0 mismatch\n");
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT0_INDEX]);
+ } else
+ cdata->ext0_available = true;
+ }
+
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+ err = st_lsm6ds3_i2c_master_read(
+ cdata->master_client[ST_LSM6DS3_EXT1_INDEX],
+ st_lsm6ds3_exs_list[ST_LSM6DS3_EXT1_INDEX].wai.addr, 1, &wai);
+ if (err < 0) {
+ dev_err(cdata->dev, "external sensor 1 not available\n");
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT1_INDEX]);
+ } else {
+ if (wai != st_lsm6ds3_exs_list[ST_LSM6DS3_EXT1_INDEX].wai.def_value) {
+ dev_err(cdata->dev, "wai value of external sensor 1 mismatch\n");
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT1_INDEX]);
+ } else
+ cdata->ext1_available = true;
+ }
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+
+ err = st_lsm6ds3_enable_passthrough(cdata, false);
+ if (err < 0) {
+ if (cdata->ext0_available)
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT0_INDEX]);
+
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+ if (cdata->ext1_available)
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT1_INDEX]);
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+
+ mutex_unlock(&cdata->passthrough_lock);
+
+ return err;
+ }
+
+ mutex_unlock(&cdata->passthrough_lock);
+
+ if (cdata->ext0_available) {
+ err = st_lsm6ds3_i2c_master_allocate_device(cdata, ST_LSM6DS3_EXT0_INDEX);
+ if (err < 0)
+ goto unregister_with_check_i2c_clients;
+
+ }
+
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+ if (cdata->ext1_available) {
+ err = st_lsm6ds3_i2c_master_allocate_device(cdata, ST_LSM6DS3_EXT1_INDEX);
+ if (err < 0)
+ goto deallocate_ext0_device;
+
+ }
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+
+ return 0;
+
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+deallocate_ext0_device:
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+ st_lsm6ds3_i2c_master_deallocate_device(cdata, ST_LSM6DS3_EXT0_INDEX);
+unregister_with_check_i2c_clients:
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+ if (cdata->ext1_available)
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT1_INDEX]);
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+ if (cdata->ext0_available)
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT0_INDEX]);
+
+ return err;
+
+master_probe_passthrough_lock:
+ mutex_unlock(&cdata->passthrough_lock);
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT1_INDEX]);
+unregister_ext0_i2c_client:
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT0_INDEX]);
+
+ return err;
+}
+EXPORT_SYMBOL(st_lsm6ds3_i2c_master_probe);
+
+int st_lsm6ds3_i2c_master_exit(struct lsm6ds3_data *cdata)
+{
+ if (cdata->ext0_available) {
+ st_lsm6ds3_i2c_master_deallocate_device(cdata, ST_LSM6DS3_EXT0_INDEX);
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT0_INDEX]);
+ }
+#ifndef CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED
+ if (cdata->ext1_available) {
+ st_lsm6ds3_i2c_master_deallocate_device(cdata, ST_LSM6DS3_EXT1_INDEX);
+ i2c_unregister_device(cdata->master_client[ST_LSM6DS3_EXT1_INDEX]);
+ }
+#endif /* CONFIG_ST_LSM6DS3_IIO_EXT1_DISABLED */
+
+ return 0;
+}
+EXPORT_SYMBOL(st_lsm6ds3_i2c_master_exit);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics lsm6ds3 i2c master driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_spi.c b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_spi.c
new file mode 100644
index 00000000000..7212ae225f8
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_spi.c
@@ -0,0 +1,180 @@
+/*
+ * STMicroelectronics lsm6ds3 spi driver
+ *
+ * Copyright 2014 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/iio/iio.h>
+
+#include "st_lsm6ds3.h"
+
+#define ST_SENSORS_SPI_READ 0x80
+
+static int st_lsm6ds3_spi_read(struct lsm6ds3_data *cdata,
+ u8 reg_addr, int len, u8 *data, bool b_lock)
+{
+ int err;
+
+ struct spi_transfer xfers[] = {
+ {
+ .tx_buf = cdata->tb.tx_buf,
+ .bits_per_word = 8,
+ .len = 1,
+ },
+ {
+ .rx_buf = cdata->tb.rx_buf,
+ .bits_per_word = 8,
+ .len = len,
+ }
+ };
+
+ if (b_lock)
+ mutex_lock(&cdata->bank_registers_lock);
+
+ mutex_lock(&cdata->tb.buf_lock);
+ cdata->tb.tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ;
+
+ err = spi_sync_transfer(to_spi_device(cdata->dev),
+ xfers, ARRAY_SIZE(xfers));
+ if (err)
+ goto acc_spi_read_error;
+
+ memcpy(data, cdata->tb.rx_buf, len*sizeof(u8));
+ mutex_unlock(&cdata->tb.buf_lock);
+ if (b_lock)
+ mutex_unlock(&cdata->bank_registers_lock);
+
+ return len;
+
+acc_spi_read_error:
+ mutex_unlock(&cdata->tb.buf_lock);
+ if (b_lock)
+ mutex_unlock(&cdata->bank_registers_lock);
+
+ return err;
+}
+
+static int st_lsm6ds3_spi_write(struct lsm6ds3_data *cdata,
+ u8 reg_addr, int len, u8 *data, bool b_lock)
+{
+ int err;
+
+ struct spi_transfer xfers = {
+ .tx_buf = cdata->tb.tx_buf,
+ .bits_per_word = 8,
+ .len = len + 1,
+ };
+
+ if (len >= ST_LSM6DS3_RX_MAX_LENGTH)
+ return -ENOMEM;
+
+ if (b_lock)
+ mutex_lock(&cdata->bank_registers_lock);
+
+ mutex_lock(&cdata->tb.buf_lock);
+ cdata->tb.tx_buf[0] = reg_addr;
+
+ memcpy(&cdata->tb.tx_buf[1], data, len);
+
+ err = spi_sync_transfer(to_spi_device(cdata->dev), &xfers, 1);
+ mutex_unlock(&cdata->tb.buf_lock);
+ if (b_lock)
+ mutex_unlock(&cdata->bank_registers_lock);
+
+ return err;
+}
+
+static const struct st_lsm6ds3_transfer_function st_lsm6ds3_tf_spi = {
+ .write = st_lsm6ds3_spi_write,
+ .read = st_lsm6ds3_spi_read,
+};
+
+static int st_lsm6ds3_spi_probe(struct spi_device *spi)
+{
+ int err;
+ struct lsm6ds3_data *cdata;
+
+ cdata = kmalloc(sizeof(*cdata), GFP_KERNEL);
+ if (!cdata)
+ return -ENOMEM;
+
+ cdata->dev = &spi->dev;
+ cdata->name = spi->modalias;
+ spi_set_drvdata(spi, cdata);
+
+ cdata->tf = &st_lsm6ds3_tf_spi;
+
+ err = st_lsm6ds3_common_probe(cdata, spi->irq);
+ if (err < 0)
+ goto free_data;
+
+ return 0;
+
+free_data:
+ kfree(cdata);
+ return err;
+}
+
+static int st_lsm6ds3_spi_remove(struct spi_device *spi)
+{
+ struct lsm6ds3_data *cdata = spi_get_drvdata(spi);
+
+ st_lsm6ds3_common_remove(cdata, spi->irq);
+ kfree(cdata);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int st_lsm6ds3_suspend(struct device *dev)
+{
+ struct lsm6ds3_data *cdata = spi_get_drvdata(to_spi_device(dev));
+
+ return st_lsm6ds3_common_suspend(cdata);
+}
+
+static int st_lsm6ds3_resume(struct device *dev)
+{
+ struct lsm6ds3_data *cdata = spi_get_drvdata(to_spi_device(dev));
+
+ return st_lsm6ds3_common_resume(cdata);
+}
+
+static const struct dev_pm_ops st_lsm6ds3_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(st_lsm6ds3_suspend, st_lsm6ds3_resume)
+};
+
+#define ST_LSM6DS3_PM_OPS (&st_lsm6ds3_pm_ops)
+#else /* CONFIG_PM */
+#define ST_LSM6DS3_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static const struct spi_device_id st_lsm6ds3_id_table[] = {
+ { LSM6DS3_DEV_NAME },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, st_lsm6ds3_id_table);
+
+static struct spi_driver st_lsm6ds3_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "st-lsm6ds3-spi",
+ .pm = ST_LSM6DS3_PM_OPS,
+ },
+ .probe = st_lsm6ds3_spi_probe,
+ .remove = st_lsm6ds3_spi_remove,
+ .id_table = st_lsm6ds3_id_table,
+};
+module_spi_driver(st_lsm6ds3_driver);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics lsm6ds3 spi driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_trigger.c b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_trigger.c
new file mode 100644
index 00000000000..fb739c883d4
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_trigger.c
@@ -0,0 +1,175 @@
+/*
+ * STMicroelectronics lsm6ds3 trigger driver
+ *
+ * Copyright 2014 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/interrupt.h>
+#include <linux/iio/events.h>
+
+#include "st_lsm6ds3.h"
+
+#define ST_LSM6DS3_SRC_FUNC_ADDR 0x53
+#define ST_LSM6DS3_FIFO_DATA_AVL_ADDR 0x3b
+
+#define ST_LSM6DS3_SRC_STEP_DETECTOR_DATA_AVL 0x10
+#define ST_LSM6DS3_SRC_TILT_DATA_AVL 0x20
+#define ST_LSM6DS3_SRC_STEP_COUNTER_DATA_AVL 0x80
+#define ST_LSM6DS3_FIFO_DATA_AVL 0x80
+#define ST_LSM6DS3_FIFO_DATA_OVR 0x40
+
+static struct workqueue_struct *st_lsm6ds3_wq;
+
+void st_lsm6ds3_flush_works()
+{
+ flush_workqueue(st_lsm6ds3_wq);
+}
+
+irqreturn_t st_lsm6ds3_save_timestamp(int irq, void *private)
+{
+ struct timespec ts;
+ struct lsm6ds3_data *cdata = private;
+
+ get_monotonic_boottime(&ts);
+ cdata->timestamp = timespec_to_ns(&ts);
+ queue_work(st_lsm6ds3_wq, &cdata->data_work);
+
+ disable_irq_nosync(irq);
+
+ return IRQ_HANDLED;
+}
+
+static void st_lsm6ds3_irq_management(struct work_struct *data_work)
+{
+ struct lsm6ds3_data *cdata;
+ u8 src_value = 0x00, src_fifo = 0x00;
+
+ cdata = container_of((struct work_struct *)data_work,
+ struct lsm6ds3_data, data_work);
+
+ cdata->tf->read(cdata, ST_LSM6DS3_SRC_FUNC_ADDR, 1, &src_value, true);
+ cdata->tf->read(cdata, ST_LSM6DS3_FIFO_DATA_AVL_ADDR, 1,
+ &src_fifo, true);
+
+ if (src_fifo & ST_LSM6DS3_FIFO_DATA_AVL) {
+ if (src_fifo & ST_LSM6DS3_FIFO_DATA_OVR) {
+ st_lsm6ds3_set_fifo_mode(cdata, BYPASS);
+ st_lsm6ds3_set_fifo_mode(cdata, CONTINUOS);
+ dev_err(cdata->dev,
+ "data fifo overrun, reduce fifo size.\n");
+ } else
+ st_lsm6ds3_read_fifo(cdata, false);
+ }
+
+ if (src_value & ST_LSM6DS3_SRC_STEP_DETECTOR_DATA_AVL) {
+ iio_push_event(cdata->indio_dev[ST_INDIO_DEV_STEP_DETECTOR],
+ IIO_UNMOD_EVENT_CODE(IIO_STEP_DETECTOR,
+ 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER),
+ cdata->timestamp);
+
+ if (cdata->sign_motion_event_ready) {
+ iio_push_event(cdata->indio_dev[
+ ST_INDIO_DEV_SIGN_MOTION],
+ IIO_UNMOD_EVENT_CODE(IIO_SIGN_MOTION,
+ 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER),
+ cdata->timestamp);
+
+ cdata->sign_motion_event_ready = false;
+ }
+ }
+
+ if (src_value & ST_LSM6DS3_SRC_STEP_COUNTER_DATA_AVL) {
+ iio_trigger_poll_chained(
+ cdata->trig[ST_INDIO_DEV_STEP_COUNTER], 0);
+ }
+
+ if (src_value & ST_LSM6DS3_SRC_TILT_DATA_AVL) {
+ iio_push_event(cdata->indio_dev[ST_INDIO_DEV_TILT],
+ IIO_UNMOD_EVENT_CODE(IIO_TILT,
+ 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER),
+ cdata->timestamp);
+ }
+
+ enable_irq(cdata->irq);
+ return;
+}
+
+int st_lsm6ds3_allocate_triggers(struct lsm6ds3_data *cdata,
+ const struct iio_trigger_ops *trigger_ops)
+{
+ int err, i, n;
+
+ if (!st_lsm6ds3_wq)
+ st_lsm6ds3_wq = create_workqueue(cdata->name);
+
+ if (!st_lsm6ds3_wq)
+ return -EINVAL;
+
+ INIT_WORK(&cdata->data_work, st_lsm6ds3_irq_management);
+
+ for (i = 0; i < ST_INDIO_DEV_NUM; i++) {
+ cdata->trig[i] = iio_trigger_alloc("%s-trigger",
+ cdata->indio_dev[i]->name);
+ if (!cdata->trig[i]) {
+ dev_err(cdata->dev,
+ "failed to allocate iio trigger.\n");
+ err = -ENOMEM;
+ goto deallocate_trigger;
+ }
+ iio_trigger_set_drvdata(cdata->trig[i], cdata->indio_dev[i]);
+ cdata->trig[i]->ops = trigger_ops;
+ cdata->trig[i]->dev.parent = cdata->dev;
+ }
+
+ err = request_threaded_irq(cdata->irq, st_lsm6ds3_save_timestamp, NULL,
+ IRQF_TRIGGER_HIGH, cdata->name, cdata);
+ if (err)
+ goto deallocate_trigger;
+
+ for (n = 0; n < ST_INDIO_DEV_NUM; n++) {
+ err = iio_trigger_register(cdata->trig[n]);
+ if (err < 0) {
+ dev_err(cdata->dev,
+ "failed to register iio trigger.\n");
+ goto free_irq;
+ }
+ cdata->indio_dev[n]->trig = cdata->trig[n];
+ }
+
+ return 0;
+
+free_irq:
+ free_irq(cdata->irq, cdata);
+ for (n--; n >= 0; n--)
+ iio_trigger_unregister(cdata->trig[n]);
+deallocate_trigger:
+ for (i--; i >= 0; i--)
+ iio_trigger_free(cdata->trig[i]);
+
+ return err;
+}
+EXPORT_SYMBOL(st_lsm6ds3_allocate_triggers);
+
+void st_lsm6ds3_deallocate_triggers(struct lsm6ds3_data *cdata)
+{
+ int i;
+
+ free_irq(cdata->irq, cdata);
+
+ for (i = 0; i < ST_INDIO_DEV_NUM; i++)
+ iio_trigger_unregister(cdata->trig[i]);
+}
+EXPORT_SYMBOL(st_lsm6ds3_deallocate_triggers);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics lsm6ds3 trigger driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index e145931ef1b..a667c418018 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -66,6 +66,15 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_ALTVOLTAGE] = "altvoltage",
[IIO_CCT] = "cct",
[IIO_PRESSURE] = "pressure",
+ [IIO_HEARTRATE] = "heartrate",
+ [IIO_PEDOMETER] = "pedometer",
+ [IIO_PASSIVE] = "passive",
+ [IIO_GESTURE] = "gesture",
+ [IIO_FUSION] = "fusion",
+ [IIO_SIGN_MOTION] = "sign_motion",
+ [IIO_STEP_COUNTER] = "step_counter",
+ [IIO_TILT] = "tilt",
+ [IIO_STEP_DETECTOR] = "step_detector",
};
static const char * const iio_modifier_names[] = {
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index f9ea48f27d0..7f328e37fba 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -11,5 +11,3 @@ st_magn-$(CONFIG_IIO_BUFFER) += st_magn_buffer.o
obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o
obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o
-
-obj-y += inv_compass/
diff --git a/drivers/iio/magnetometer/inv_compass/Kconfig b/drivers/iio/magnetometer/inv_compass/Kconfig
deleted file mode 100755
index aa0ffde1869..00000000000
--- a/drivers/iio/magnetometer/inv_compass/Kconfig
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Kconfig for Invensense IIO compass drivers of 3rd party compass devices.
-#
-
-# Yamaha YAS530/YAS532/YAS533
-config INV_YAS53X_IIO
- tristate "Invensense IIO driver for Yamaha YAS530/YAS532/YAS533 compass"
- depends on I2C && SYSFS && IIO && IIO_KFIFO_BUF
- default n
- help
- This driver supports the Yamaha YAS530/YAS532/YAS533. It is the Invensense
- implementation of YAS53x series compass devices.
- This driver can be built as a module. The module will be called
- inv_yas53x_iio.
-
-# Aichi AMI306
-config INV_AMI306_IIO
- tristate "Invensense IIO driver for Aichi AMI306 compass"
- depends on I2C && SYSFS && IIO && IIO_KFIFO_BUF
- default n
- help
- This driver supports the Aichi AMI306 compass. It is the Invensense
- IIO implementation for the AMI306 compass device.
- This driver can be built as a module. The module will be called
- inv-ami306-iio.
-
-# Asahi Kasei AK8975/AK8972/AK8963
-config INV_AK89XX_IIO
- tristate "Invensense IIO driver for Asahi Kasei AK8975/AK8972/AK8963 compass"
- depends on I2C && SYSFS && IIO && IIO_KFIFO_BUF
- default n
- help
- This driver supports the Asahi Kasei AK8975/AK8972/AK8963 compasses. It is the Invensense
- IIO implementation of AK89xx series compass devices.
- This driver can be built as a module. The module will be called
- inv-ak89xx-iio.
-
-# Asahi Kasei AK09911
-config INV_AK09911_IIO
- tristate "Invensense IIO driver for Asahi Kasei AK09911 compass"
- depends on I2C && SYSFS && IIO && IIO_KFIFO_BUF
- default n
- help
- This driver supports the Asahi Kasei AK09911 compasses. It is the Invensense
- IIO implementation of AK09911 compass devices.
- This driver can be built as a module. The module will be called
- inv-ak09911-iio.
diff --git a/drivers/iio/magnetometer/inv_compass/Makefile b/drivers/iio/magnetometer/inv_compass/Makefile
deleted file mode 100755
index 568e5e2bf71..00000000000
--- a/drivers/iio/magnetometer/inv_compass/Makefile
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Makefile for Invensense IIO compass drivers of 3rd party compass devices.
-#
-
-# Yamaha YAS530/YAS532/YAS533
-obj-$(CONFIG_INV_YAS53X_IIO) += inv_yas53x.o
-
-inv_yas53x-objs := inv_yas53x_core.o
-inv_yas53x-objs += inv_yas53x_ring.o
-inv_yas53x-objs += inv_yas53x_trigger.o
-
-CFLAGS_inv_yas53x_core.o += -Idrivers/staging/iio
-CFLAGS_inv_yas53x_ring.o += -Idrivers/staging/iio
-CFLAGS_inv_yas53x_trigger.o += -Idrivers/staging/iio
-
-# Aichi AMI306
-obj-$(CONFIG_INV_AMI306_IIO) += inv-ami306-iio.o
-
-inv-ami306-iio-objs := inv_ami306_core.o
-inv-ami306-iio-objs += inv_ami306_ring.o
-inv-ami306-iio-objs += inv_ami306_trigger.o
-
-CFLAGS_inv_ami306_core.o += -Idrivers/staging/iio
-CFLAGS_inv_ami306_ring.o += -Idrivers/staging/iio
-CFLAGS_inv_ami306_trigger.o += -Idrivers/staging/iio
-
-# Asahi Kasei AK8975/AK8972/AK8963
-obj-$(CONFIG_INV_AK89XX_IIO) += inv-ak89xx-iio.o
-
-inv-ak89xx-iio-objs := inv_ak89xx_core.o
-inv-ak89xx-iio-objs += inv_ak89xx_ring.o
-inv-ak89xx-iio-objs += inv_ak89xx_trigger.o
-
-CFLAGS_inv_ak89xx_core.o += -Idrivers/staging/iio
-CFLAGS_inv_ak89xx_ring.o += -Idrivers/staging/iio
-CFLAGS_inv_ak89xx_trigger.o += -Idrivers/staging/iio
-
-# Asahi Kasei AK09911
-obj-$(CONFIG_INV_AK09911_IIO) += inv-ak09911-iio.o
-
-inv-ak09911-iio-objs := inv_ak09911_core.o
-inv-ak09911-iio-objs += inv_ak09911_ring.o
-inv-ak09911-iio-objs += inv_ak09911_trigger.o
-
-CFLAGS_inv_ak09911_core.o += -Idrivers/staging/iio
-CFLAGS_inv_ak09911_ring.o += -Idrivers/staging/iio
-CFLAGS_inv_ak09911_trigger.o += -Idrivers/staging/iio
-
diff --git a/drivers/iio/magnetometer/inv_compass/README b/drivers/iio/magnetometer/inv_compass/README
deleted file mode 100755
index 54f2bb8ded2..00000000000
--- a/drivers/iio/magnetometer/inv_compass/README
+++ /dev/null
@@ -1,176 +0,0 @@
-Kernel driver
-Author: Invensense <http://invensense.com>
-
-Table of Contents:
-==================
-- Description
-- Integrating the Driver in the Linux Kernel
-- Board and Platform Data
- > Platform Data
-- Board File Modifications for compass
- > AMI306
- > YAS530/532/533
-- IIO Subsystem
- > Communicating with the Driver in Userspace
-- Streaming Data to an Userspace Application
-- Test Applications
- > Running Test Applications with AMI306 or YAS53x
-
-Description
-===========
-This document describes how to install the Invensense device driver for AMI306
-and YAS53x series compass chip into a Linux kernel. The Invensense driver
-currently supports the following sensors:
-- AMI306
-- YAS530
-- YAS532
-- YAS533
-
-Please refer to the appropriate product specification
-document for further information regarding the slave address.
-
-The following files are included in this package:
-- Kconfig
-- Makefile
-- inv_ami306_core.c
-- inv_ami306_ring.c
-- inv_ami306_trigger.c
-- inv_ami306_iio.h
-- inv_yas53x_core.c
-- inv_yas53x_ring.c
-- inv_yas53x_trigger.c
-- inv_yas53x_iio.h
-
-Integrating the Driver in the Linux Kernel
-==========================================
-Please add the files as follows:
-- Add all above files to drivers/staging/iio/magnetometer/inv_compass
-(another directory is acceptable, but this is the recommended destination)
-
-In order to see the driver in menuconfig when building the kernel, please
-make modifications as shown below:
-
- modify "drivers/staging/iio/magnetometer/Kconfig" with:
- >> source "drivers/staging/iio/magnetometer/inv_compass/Kconfig"
-
- modify "drivers/staging/iio/magnetometer/Makefile" with:
- >> obj-y += inv_compass/
-
-
-Board and Platform Data
-=======================
-In order to recognize the Invensense device on the I2C bus, the board file must
-be modified.
-The i2c_board_info instance must be defined as shown below.
-
-Platform Data
--------------
-The platform data (orientation matrix and secondary bus configurations) must be
-modified as show below, according to your particular platform configuration.
-
-Board File Modifications for Secondary I2C Configuration
-========================================================
-For the Panda Board, the board file can be found at
-arch/arm/mach-omap2/board-omap4panda.c.
-Please modify the pertinent baord file in your system according to the examples
-shown below:
-
-AMI306
--------------------------------------------------
-static struct mpu_platform_data compass_data = {
- .orientation = { 0, 0, 1,
- 0, 1, 0,
- 1, 0, 0 },
-};
-
-static struct i2c_board_info __initdata chip_board_info[] = {
- {
- I2C_BOARD_INFO("ami306", 0x0E),
- .platform_data = &compass_data,
- },
-};
-
-YAS53x(Use YAS532 as an example)
--------------------------------------------------
-static struct mpu_platform_data compass_data = {
- .orientation = { 0, -1, 0,
- 1, 0, 0,
- 0, 0, 1 },
-};
-
-static struct i2c_board_info __initdata compass_board_info[] = {
- {
- I2C_BOARD_INFO("yas532", 0x2E),
- .platform_data = &compass_data,
- },
-};
-
-IIO subsystem
-=============
-A successful installation will create the following two new directories under
-/sys/bus/iio/devices:
- - iio:device0
- - trigger0
-
-Also, a new file, "iio:device0", will be created in the /dev/ diretory.
-(if you have more than one IIO device, the file will be named "iio:deviceX",
-where X is a number)
-
-
-Communicating with the Driver in Userspace
-------------------------------------------
-The driver generates several files in sysfs upon installation.
-These files are used to communicate with the driver. The files can be found
-at /sys/bus/iio/devices/iio:device0 (or ../iio:deviceX as shown above).
-
-A brief description of the pertinent files for each Invensense device is shown
-below:
-
-AMI306
---------
-compass_matrix (read-only)
---show the orientation matrix obtained from the board file.
-
-sampling_frequency(read and write)
---show and change the sampling rate of the sensor.
-
-YAS53x
----------------------
-YAS53x has all the attributes AMI306 has. It has one more additional attribute:
-
-overunderflow(read-only)
---value 1 shows an overflow or underflow happens. Need to write into it to make
- it zero.
-
-Streaming Data to an Userspace Application
-==========================================
-When streaming data to an userspace application, we recommend that you access
-compass data via /dev/iio:device0.
-
-Please follow the steps below to read data at a constant rate from the driver:
-
-1. Write the desired output rate to sampling_frequency.
-2. Write 1 to enable to turn on the event.
-3. Read /dev/iio:device0 to get a string of gyro/accel/compass data.
-4. Parse this string to obtain each compass element.
-
-Test Applications
-=================
-A test application is located under software/simple_apps/mpu_iio.
-This application is stand-alone in that it cannot be run concurrently with other
-entities trying to access the device node(s) or sysfs entries; in particular,
-the
-
-Running Test Applications
----------------------------------------------------------
-To run test applications with AMI306 or YAS53x devices,
-please use the following commands:
-
-1. for ami306:
- mpu_iio -n ami306 -c 10 -l 3
-
-2. for yas532:
- mpu_iio -n yas532 -c 10 -l 3
-
-Please use mpu_iio.c and iio_utils.h as example code for your development
-purposes.
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ak09911_core.c b/drivers/iio/magnetometer/inv_compass/inv_ak09911_core.c
deleted file mode 100755
index a52fb403207..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ak09911_core.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
-* Copyright (C) 2013 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "inv_ak09911_iio.h"
-#include "sysfs.h"
-#include "inv_test/inv_counters.h"
-
-static s64 get_time_ns(void)
-{
- struct timespec ts;
- ktime_get_ts(&ts);
- return timespec_to_ns(&ts);
-}
-
-/**
- * inv_serial_read() - Read one or more bytes from the device registers.
- * @st: Device driver instance.
- * @reg: First device register to be read from.
- * @length: Number of bytes to read.
- * @data: Data read from device.
- * NOTE: The slave register will not increment when reading from the FIFO.
- */
-int inv_serial_read(struct inv_ak09911_state_s *st, u8 reg, u16 length, u8 *data)
-{
- int result;
- INV_I2C_INC_COMPASSWRITE(3);
- INV_I2C_INC_COMPASSREAD(length);
- result = i2c_smbus_read_i2c_block_data(st->i2c, reg, length, data);
- if (result != length) {
- if (result < 0)
- return result;
- else
- return -EINVAL;
- } else {
- return 0;
- }
-}
-
-/**
- * inv_serial_single_write() - Write a byte to a device register.
- * @st: Device driver instance.
- * @reg: Device register to be written to.
- * @data: Byte to write to device.
- */
-int inv_serial_single_write(struct inv_ak09911_state_s *st, u8 reg, u8 data)
-{
- u8 d[1];
- d[0] = data;
- INV_I2C_INC_COMPASSWRITE(3);
-
- return i2c_smbus_write_i2c_block_data(st->i2c, reg, 1, d);
-}
-
-static int ak09911_init(struct inv_ak09911_state_s *st)
-{
- int result = 0;
- unsigned char serial_data[3];
-
- result = inv_serial_single_write(st, AK09911_REG_CNTL,
- AK09911_CNTL_MODE_POWER_DOWN);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
- /* Wait at least 100us */
- udelay(100);
-
- result = inv_serial_single_write(st, AK09911_REG_CNTL,
- AK09911_CNTL_MODE_FUSE_ACCESS);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
-
- /* Wait at least 200us */
- udelay(200);
-
- result = inv_serial_read(st, AK09911_FUSE_ASAX, 3, serial_data);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
-
- st->asa[0] = serial_data[0];
- st->asa[1] = serial_data[1];
- st->asa[2] = serial_data[2];
-
- result = inv_serial_single_write(st, AK09911_REG_CNTL,
- AK09911_CNTL_MODE_POWER_DOWN);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
- udelay(100);
-
- return result;
-}
-
-int ak09911_read(struct inv_ak09911_state_s *st, short rawfixed[3])
-{
- unsigned char regs[8];
- unsigned char *stat = &regs[0];
- unsigned char *stat2 = &regs[8];
- int result = 0;
- int status = 0;
-
- result = inv_serial_read(st, AK09911_REG_ST1, 9, regs);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
-
- rawfixed[0] = (short)((regs[2]<<8) | regs[1]);
- rawfixed[1] = (short)((regs[4]<<8) | regs[3]);
- rawfixed[2] = (short)((regs[6]<<8) | regs[5]);
-
- /*
- * ST : data ready -
- * Measurement has been completed and data is ready to be read.
- */
- if (*stat & 0x01)
- status = 0;
- /*
- * ST2 : overflow -
- * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
- * This is likely to happen in presence of an external magnetic
- * disturbance; it indicates, the sensor data is incorrect and should
- * be ignored.
- * An error is returned.
- * HOFL bit clears when a new measurement starts.
- */
- if (*stat2 & 0x08)
- status = 0x08;
- /*
- * ST : overrun -
- * the previous sample was not fetched and lost.
- * Valid in continuous measurement mode only.
- * In single measurement mode this error should not occour and we
- * don't consider this condition an error.
- * DOR bit is self-clearing when ST2 or any meas. data register is
- * read.
- */
- if (*stat & 0x02) {
- /* status = INV_ERROR_COMPASS_DATA_UNDERFLOW; */
- status = 0;
- }
-
- /*
- * trigger next measurement if:
- * - stat is non zero;
- * - if stat is zero and stat2 is non zero.
- * Won't trigger if data is not ready and there was no error.
- */
- result = inv_serial_single_write(st, AK09911_REG_CNTL,
- AK09911_CNTL_MODE_SNG_MEASURE);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
-
- if (status)
- pr_err("%s, line=%d, status=%d\n", __func__, __LINE__, status);
-
- return status;
-}
-
-/**
- * ak09911_read_raw() - read raw method.
- */
-static int ak09911_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val,
- int *val2,
- long mask) {
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
- int scale = 0;
-
- switch (mask) {
- case 0:
- if (!(iio_buffer_enabled(indio_dev)))
- return -EINVAL;
- if (chan->type == IIO_MAGN) {
- *val = st->compass_data[chan->channel2 - IIO_MOD_X];
- return IIO_VAL_INT;
- }
-
- return -EINVAL;
- case IIO_CHAN_INFO_SCALE:
- scale = 19661;
- scale *= (1L << 15);
- *val = scale;
- return IIO_VAL_INT;
- return -EINVAL;
- default:
- return -EINVAL;
- }
-}
-
-static ssize_t ak09911_value_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
- short c[3];
-
- mutex_lock(&indio_dev->mlock);
- c[0] = st->compass_data[0];
- c[1] = st->compass_data[1];
- c[2] = st->compass_data[2];
- mutex_unlock(&indio_dev->mlock);
- return sprintf(buf, "%d, %d, %d\n", c[0], c[1], c[2]);
-}
-
-static ssize_t ak09911_rate_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
- /* transform delay in ms to rate */
- return sprintf(buf, "%d\n", (1000 / st->delay));
-}
-
-/**
- * ak09911_matrix_show() - show orientation matrix
- */
-static ssize_t ak09911_matrix_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- signed char *m;
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
- m = st->plat_data.orientation;
- return sprintf(buf,
- "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
- m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
-}
-
-void set_ak09911_enable(struct iio_dev *indio_dev, bool enable)
-{
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
- int result = 0;
-
- if (enable) {
- result = inv_serial_single_write(st, AK09911_REG_CNTL,
- AK09911_CNTL_MODE_SNG_MEASURE);
- if (result)
- pr_err("%s, line=%d\n", __func__, __LINE__);
- schedule_delayed_work(&st->work,
- msecs_to_jiffies(st->delay));
- } else {
- cancel_delayed_work_sync(&st->work);
- result = inv_serial_single_write(st, AK09911_REG_CNTL,
- AK09911_CNTL_MODE_POWER_DOWN);
- if (result)
- pr_err("%s, line=%d\n", __func__, __LINE__);
- mdelay(1); /* wait at least 100us */
- }
-}
-
-static ssize_t ak09911_rate_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned long data;
- int error;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
-
- error = kstrtoul(buf, 10, &data);
- if (error)
- return error;
- /* transform rate to delay in ms */
- data = 1000 / data;
- if (data > AK09911_MAX_DELAY)
- data = AK09911_MAX_DELAY;
- if (data < AK09911_MIN_DELAY)
- data = AK09911_MIN_DELAY;
- st->delay = (unsigned int) data;
- return count;
-}
-
-static void ak09911_work_func(struct work_struct *work)
-{
- struct inv_ak09911_state_s *st =
- container_of((struct delayed_work *)work,
- struct inv_ak09911_state_s, work);
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- unsigned long delay = msecs_to_jiffies(st->delay);
-
- mutex_lock(&indio_dev->mlock);
- if (!(iio_buffer_enabled(indio_dev)))
- goto error_ret;
-
- st->timestamp = get_time_ns();
- schedule_delayed_work(&st->work, delay);
- inv_read_ak09911_fifo(indio_dev);
- INV_I2C_INC_COMPASSIRQ();
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
-}
-
-static const struct iio_chan_spec compass_channels[] = {
- {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_AK09911_SCAN_MAGN_X,
- .scan_type = IIO_ST('s', 16, 16, 0)
- }, {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_AK09911_SCAN_MAGN_Y,
- .scan_type = IIO_ST('s', 16, 16, 0)
- }, {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_AK09911_SCAN_MAGN_Z,
- .scan_type = IIO_ST('s', 16, 16, 0)
- },
- IIO_CHAN_SOFT_TIMESTAMP(INV_AK09911_SCAN_TIMESTAMP)
-};
-
-static DEVICE_ATTR(value, S_IRUGO, ak09911_value_show, NULL);
-static DEVICE_ATTR(sampling_frequency, S_IRUGO | S_IWUSR, ak09911_rate_show,
- ak09911_rate_store);
-static DEVICE_ATTR(compass_matrix, S_IRUGO, ak09911_matrix_show, NULL);
-
-static struct attribute *inv_ak09911_attributes[] = {
- &dev_attr_value.attr,
- &dev_attr_sampling_frequency.attr,
- &dev_attr_compass_matrix.attr,
- NULL,
-};
-
-static const struct attribute_group inv_attribute_group = {
- .name = "ak09911",
- .attrs = inv_ak09911_attributes
-};
-
-static const struct iio_info ak09911_info = {
- .driver_module = THIS_MODULE,
- .read_raw = &ak09911_read_raw,
- .attrs = &inv_attribute_group,
-};
-
-/*constant IIO attribute */
-/**
- * inv_ak09911_probe() - probe function.
- */
-static int inv_ak09911_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct inv_ak09911_state_s *st;
- struct iio_dev *indio_dev;
- int result;
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- result = -ENODEV;
- goto out_no_free;
- }
- indio_dev = iio_allocate_device(sizeof(*st));
- if (indio_dev == NULL) {
- result = -ENOMEM;
- goto out_no_free;
- }
- st = iio_priv(indio_dev);
- st->i2c = client;
- st->sl_handle = client->adapter;
- st->plat_data =
- *(struct mpu_platform_data *)dev_get_platdata(&client->dev);
- st->i2c_addr = client->addr;
- st->delay = AK09911_DEFAULT_DELAY;
- st->compass_id = id->driver_data;
-
- i2c_set_clientdata(client, indio_dev);
- result = ak09911_init(st);
- if (result)
- goto out_free;
-
- indio_dev->dev.parent = &client->dev;
- indio_dev->name = id->name;
- indio_dev->channels = compass_channels;
- indio_dev->num_channels = ARRAY_SIZE(compass_channels);
- indio_dev->info = &ak09911_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->currentmode = INDIO_DIRECT_MODE;
-
- result = inv_ak09911_configure_ring(indio_dev);
- if (result)
- goto out_free;
- result = iio_buffer_register(indio_dev, indio_dev->channels,
- indio_dev->num_channels);
- if (result)
- goto out_unreg_ring;
- result = inv_ak09911_probe_trigger(indio_dev);
- if (result)
- goto out_remove_ring;
-
- result = iio_device_register(indio_dev);
- if (result)
- goto out_remove_trigger;
- INIT_DELAYED_WORK(&st->work, ak09911_work_func);
- pr_info("%s: Probe name %s\n", __func__, id->name);
- return 0;
-out_remove_trigger:
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
- inv_ak09911_remove_trigger(indio_dev);
-out_remove_ring:
- iio_buffer_unregister(indio_dev);
-out_unreg_ring:
- inv_ak09911_unconfigure_ring(indio_dev);
-out_free:
- iio_free_device(indio_dev);
-out_no_free:
- dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
- return -EIO;
-}
-
-/**
- * inv_ak09911_remove() - remove function.
- */
-static int inv_ak09911_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
- cancel_delayed_work_sync(&st->work);
- iio_device_unregister(indio_dev);
- inv_ak09911_remove_trigger(indio_dev);
- iio_buffer_unregister(indio_dev);
- inv_ak09911_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
-
- dev_info(&client->adapter->dev, "inv-ak09911-iio module removed.\n");
- return 0;
-}
-
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* device id table is used to identify what device can be
- * supported by this driver
- */
-static const struct i2c_device_id inv_ak09911_id[] = {
- {"akm9911", COMPASS_ID_AK09911},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, inv_ak09911_id);
-
-static struct i2c_driver inv_ak09911_driver = {
- .class = I2C_CLASS_HWMON,
- .probe = inv_ak09911_probe,
- .remove = inv_ak09911_remove,
- .id_table = inv_ak09911_id,
- .driver = {
- .owner = THIS_MODULE,
- .name = "inv-ak09911-iio",
- },
- .address_list = normal_i2c,
-};
-
-static int __init inv_ak09911_init(void)
-{
- int result = i2c_add_driver(&inv_ak09911_driver);
- if (result) {
- pr_err("%s failed\n", __func__);
- return result;
- }
- return 0;
-}
-
-static void __exit inv_ak09911_exit(void)
-{
- i2c_del_driver(&inv_ak09911_driver);
-}
-
-module_init(inv_ak09911_init);
-module_exit(inv_ak09911_exit);
-
-MODULE_AUTHOR("Invensense Corporation");
-MODULE_DESCRIPTION("Invensense device driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("inv-ak09911-iio");
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ak09911_iio.h b/drivers/iio/magnetometer/inv_compass/inv_ak09911_iio.h
deleted file mode 100755
index 3c96a43d1d6..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ak09911_iio.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-#ifndef _INV_AK09911_IIO_H_
-#define _INV_AK09911_IIO_H_
-
-#include <linux/i2c.h>
-#include <linux/kfifo.h>
-#include <linux/miscdevice.h>
-#include <linux/input.h>
-#include <linux/spinlock.h>
-#include <linux/mpu.h>
-
-#include "iio.h"
-#include "buffer.h"
-#include "trigger.h"
-
-/**
- * struct inv_ak09911_state_s - Driver state variables.
- * @plat_data: board file platform data.
- * @i2c: i2c client handle.
- * @trig: not used. for compatibility.
- * @work: work data structure.
- * @delay: delay between each scheduled work.
- * @compass_id: id of compass.
- * @compass_data: compass data.
- * @asa: fuse data to adjust final data.
- * @timestamp: timestamp of each data.
- * @i2c_addr: i2c address
- * @sl_handle: Handle to I2C port.
- */
-struct inv_ak09911_state_s {
- struct mpu_platform_data plat_data;
- struct i2c_client *i2c;
- struct iio_trigger *trig;
- struct delayed_work work;
- int delay; /* msec */
- unsigned char compass_id;
- short compass_data[3];
- u8 asa[3]; /* axis sensitivity adjustment */
- s64 timestamp;
- short i2c_addr;
- void *sl_handle;
-};
-
-/* scan element definition */
-enum inv_mpu_scan {
- INV_AK09911_SCAN_MAGN_X,
- INV_AK09911_SCAN_MAGN_Y,
- INV_AK09911_SCAN_MAGN_Z,
- INV_AK09911_SCAN_TIMESTAMP,
-};
-
-/*! \name ak09911 constant definition
- \anchor ak09911_Def
- Constant definitions of the ak09911.*/
-#define AK09911_MEASUREMENT_TIME_US 10000
-
-/*! \name ak09911 operation mode
- \anchor AK09911_Mode
- Defines an operation mode of the ak09911.*/
-/*! @{*/
-#define AK09911_CNTL_MODE_SNG_MEASURE 0x01
-#define AK09911_CNTL_MODE_SELF_TEST 0x08
-#define AK09911_CNTL_MODE_FUSE_ACCESS 0x1F
-#define AK09911_CNTL_MODE_POWER_DOWN 0x00
-/*! @}*/
-
-/*! \name ak09911 register address
-\anchor AK09911_REG
-Defines a register address of the ak09911.*/
-/*! @{*/
-#define AK09911_REG_WIA 0x00
-#define AK09911_REG_INFO 0x01
-#define AK09911_REG_ST1 0x10
-#define AK09911_REG_HXL 0x11
-#define AK09911_REG_ST2 0x18
-#define AK09911_REG_CNTL 0x31
-/*! @}*/
-
-/*! \name ak09911 fuse-rom address
-\anchor AK09911_FUSE
-Defines a read-only address of the fuse ROM of the ak09911.*/
-/*! @{*/
-#define AK09911_FUSE_ASAX 0x60
-/*! @}*/
-
-#define AK09911_MAX_DELAY (200)
-#define AK09911_MIN_DELAY (10)
-#define AK09911_DEFAULT_DELAY (100)
-
-#define INV_ERROR_COMPASS_DATA_OVERFLOW (-1)
-#define INV_ERROR_COMPASS_DATA_NOT_READY (-2)
-
-int inv_ak09911_configure_ring(struct iio_dev *indio_dev);
-void inv_ak09911_unconfigure_ring(struct iio_dev *indio_dev);
-int inv_ak09911_probe_trigger(struct iio_dev *indio_dev);
-void inv_ak09911_remove_trigger(struct iio_dev *indio_dev);
-void set_ak09911_enable(struct iio_dev *indio_dev, bool enable);
-int ak09911_read_raw_data(struct inv_ak09911_state_s *st,
- short dat[3]);
-void inv_read_ak09911_fifo(struct iio_dev *indio_dev);
-int ak09911_read(struct inv_ak09911_state_s *st, short rawfixed[3]);
-
-#endif
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ak09911_ring.c b/drivers/iio/magnetometer/inv_compass/inv_ak09911_ring.c
deleted file mode 100755
index ae3119bb5b0..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ak09911_ring.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
-* Copyright (C) 2013 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-
-#include "iio.h"
-#include "kfifo_buf.h"
-#include "trigger_consumer.h"
-#include "sysfs.h"
-
-#include "inv_ak09911_iio.h"
-
-static int put_scan_to_buf(struct iio_dev *indio_dev, unsigned char *d,
- short *s, int scan_index)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- int st;
- int i, d_ind;
-
- d_ind = 0;
- for (i = 0; i < 3; i++) {
- st = iio_scan_mask_query(indio_dev, ring, scan_index + i);
- if (st) {
- memcpy(&d[d_ind], &s[i], sizeof(s[i]));
- d_ind += sizeof(s[i]);
- }
- }
-
- return d_ind;
-}
-
-/**
- * inv_read_ak09911_fifo() - Transfer data from FIFO to ring buffer.
- */
-void inv_read_ak09911_fifo(struct iio_dev *indio_dev)
-{
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- int d_ind, i;
- s8 *tmp;
- s64 tmp_buf[2];
-
- if (!ak09911_read(st, st->compass_data)) {
- for (i = 0; i < 3; i++) {
- st->compass_data[i] = (short)(((int)st->compass_data[i]
- * (st->asa[i] + 128)) >> 7);
- }
- tmp = (u8 *)tmp_buf;
- d_ind = put_scan_to_buf(indio_dev, tmp, st->compass_data,
- INV_AK09911_SCAN_MAGN_X);
- if (ring->scan_timestamp)
- tmp_buf[(d_ind + 7)/8] = st->timestamp;
- ring->access->store_to(indio_dev->buffer, tmp, st->timestamp);
- }
-}
-
-void inv_ak09911_unconfigure_ring(struct iio_dev *indio_dev)
-{
- iio_kfifo_free(indio_dev->buffer);
-};
-
-static int inv_ak09911_postenable(struct iio_dev *indio_dev)
-{
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
-
- /* when all the outputs are disabled, even though buffer/enable is on,
- do nothing */
- if (!(iio_scan_mask_query(indio_dev, ring, INV_AK09911_SCAN_MAGN_X) ||
- iio_scan_mask_query(indio_dev, ring, INV_AK09911_SCAN_MAGN_Y) ||
- iio_scan_mask_query(indio_dev, ring, INV_AK09911_SCAN_MAGN_Z)))
- return 0;
-
- set_ak09911_enable(indio_dev, true);
- schedule_delayed_work(&st->work, msecs_to_jiffies(st->delay));
-
- return 0;
-}
-
-static int inv_ak09911_predisable(struct iio_dev *indio_dev)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
-
- cancel_delayed_work_sync(&st->work);
- clear_bit(INV_AK09911_SCAN_MAGN_X, ring->scan_mask);
- clear_bit(INV_AK09911_SCAN_MAGN_Y, ring->scan_mask);
- clear_bit(INV_AK09911_SCAN_MAGN_Z, ring->scan_mask);
- set_ak09911_enable(indio_dev, false);
-
- return 0;
-}
-
-static const struct iio_buffer_setup_ops inv_ak09911_ring_setup_ops = {
- .preenable = &iio_sw_buffer_preenable,
- .postenable = &inv_ak09911_postenable,
- .predisable = &inv_ak09911_predisable,
-};
-
-int inv_ak09911_configure_ring(struct iio_dev *indio_dev)
-{
- int ret = 0;
- struct iio_buffer *ring;
-
- ring = iio_kfifo_allocate(indio_dev);
- if (!ring) {
- ret = -ENOMEM;
- return ret;
- }
- indio_dev->buffer = ring;
- /* setup ring buffer */
- ring->scan_timestamp = true;
- indio_dev->setup_ops = &inv_ak09911_ring_setup_ops;
-
- indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
- return 0;
-}
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ak09911_trigger.c b/drivers/iio/magnetometer/inv_compass/inv_ak09911_trigger.c
deleted file mode 100755
index 7fc6096ecb0..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ak09911_trigger.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-* Copyright (C) 2013 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "iio.h"
-#include "sysfs.h"
-#include "trigger.h"
-#include "inv_ak09911_iio.h"
-
-static const struct iio_trigger_ops inv_ak09911_trigger_ops = {
- .owner = THIS_MODULE,
-};
-
-int inv_ak09911_probe_trigger(struct iio_dev *indio_dev)
-{
- int ret;
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
-
- st->trig = iio_allocate_trigger("%s-dev%d",
- indio_dev->name,
- indio_dev->id);
- if (st->trig == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- /* select default trigger */
- st->trig->dev.parent = &st->i2c->dev;
- st->trig->private_data = indio_dev;
- st->trig->ops = &inv_ak09911_trigger_ops;
- ret = iio_trigger_register(st->trig);
-
- /* select default trigger */
- indio_dev->trig = st->trig;
- if (ret)
- goto error_free_trig;
-
- return 0;
-
-error_free_trig:
- iio_free_trigger(st->trig);
-error_ret:
- return ret;
-}
-
-void inv_ak09911_remove_trigger(struct iio_dev *indio_dev)
-{
- struct inv_ak09911_state_s *st = iio_priv(indio_dev);
-
- iio_trigger_unregister(st->trig);
- iio_free_trigger(st->trig);
-}
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ak89xx_core.c b/drivers/iio/magnetometer/inv_compass/inv_ak89xx_core.c
deleted file mode 100755
index a781fd39822..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ak89xx_core.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
-* Copyright (C) 2013 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "inv_ak89xx_iio.h"
-#include "sysfs.h"
-#include "inv_test/inv_counters.h"
-
-static s64 get_time_ns(void)
-{
- struct timespec ts;
- ktime_get_ts(&ts);
- return timespec_to_ns(&ts);
-}
-
-/**
- * inv_serial_read() - Read one or more bytes from the device registers.
- * @st: Device driver instance.
- * @reg: First device register to be read from.
- * @length: Number of bytes to read.
- * @data: Data read from device.
- * NOTE: The slave register will not increment when reading from the FIFO.
- */
-int inv_serial_read(struct inv_ak89xx_state_s *st, u8 reg, u16 length, u8 *data)
-{
- int result;
- INV_I2C_INC_COMPASSWRITE(3);
- INV_I2C_INC_COMPASSREAD(length);
- result = i2c_smbus_read_i2c_block_data(st->i2c, reg, length, data);
- if (result != length) {
- if (result < 0)
- return result;
- else
- return -EINVAL;
- } else {
- return 0;
- }
-}
-
-/**
- * inv_serial_single_write() - Write a byte to a device register.
- * @st: Device driver instance.
- * @reg: Device register to be written to.
- * @data: Byte to write to device.
- */
-int inv_serial_single_write(struct inv_ak89xx_state_s *st, u8 reg, u8 data)
-{
- u8 d[1];
- d[0] = data;
- INV_I2C_INC_COMPASSWRITE(3);
-
- return i2c_smbus_write_i2c_block_data(st->i2c, reg, 1, d);
-}
-
-static int ak89xx_init(struct inv_ak89xx_state_s *st)
-{
- int result = 0;
- unsigned char serial_data[3];
-
- result = inv_serial_single_write(st, AK89XX_REG_CNTL,
- AK89XX_CNTL_MODE_POWER_DOWN);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
- /* Wait at least 100us */
- udelay(100);
-
- result = inv_serial_single_write(st, AK89XX_REG_CNTL,
- AK89XX_CNTL_MODE_FUSE_ACCESS);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
-
- /* Wait at least 200us */
- udelay(200);
-
- result = inv_serial_read(st, AK89XX_FUSE_ASAX, 3, serial_data);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
-
- st->asa[0] = serial_data[0];
- st->asa[1] = serial_data[1];
- st->asa[2] = serial_data[2];
-
- result = inv_serial_single_write(st, AK89XX_REG_CNTL,
- AK89XX_CNTL_MODE_POWER_DOWN);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
- udelay(100);
-
- return result;
-}
-
-int ak89xx_read(struct inv_ak89xx_state_s *st, short rawfixed[3])
-{
- unsigned char regs[8];
- unsigned char *stat = &regs[0];
- unsigned char *stat2 = &regs[7];
- int result = 0;
- int status = 0;
-
- result = inv_serial_read(st, AK89XX_REG_ST1, 8, regs);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
-
- rawfixed[0] = (short)((regs[2]<<8) | regs[1]);
- rawfixed[1] = (short)((regs[4]<<8) | regs[3]);
- rawfixed[2] = (short)((regs[6]<<8) | regs[5]);
-
- /*
- * ST : data ready -
- * Measurement has been completed and data is ready to be read.
- */
- if (*stat & 0x01)
- status = 0;
-
- /*
- * ST2 : data error -
- * occurs when data read is started outside of a readable period;
- * data read would not be correct.
- * Valid in continuous measurement mode only.
- * In single measurement mode this error should not occour but we
- * stil account for it and return an error, since the data would be
- * corrupted.
- * DERR bit is self-clearing when ST2 register is read.
- */
- if (*stat2 & 0x04)
- status = 0x04;
- /*
- * ST2 : overflow -
- * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
- * This is likely to happen in presence of an external magnetic
- * disturbance; it indicates, the sensor data is incorrect and should
- * be ignored.
- * An error is returned.
- * HOFL bit clears when a new measurement starts.
- */
- if (*stat2 & 0x08)
- status = 0x08;
- /*
- * ST : overrun -
- * the previous sample was not fetched and lost.
- * Valid in continuous measurement mode only.
- * In single measurement mode this error should not occour and we
- * don't consider this condition an error.
- * DOR bit is self-clearing when ST2 or any meas. data register is
- * read.
- */
- if (*stat & 0x02) {
- /* status = INV_ERROR_COMPASS_DATA_UNDERFLOW; */
- status = 0;
- }
-
- /*
- * trigger next measurement if:
- * - stat is non zero;
- * - if stat is zero and stat2 is non zero.
- * Won't trigger if data is not ready and there was no error.
- */
- if (1) {
- unsigned char scale = 0;
- if (st->compass_id == COMPASS_ID_AK8963)
- scale = st->compass_scale;
- result = inv_serial_single_write(st, AK89XX_REG_CNTL,
- (scale << 4) | AK89XX_CNTL_MODE_SNG_MEASURE);
- if (result) {
- pr_err("%s, line=%d\n", __func__, __LINE__);
- return result;
- }
- } else
- pr_err("%s, no next measure(0x%x,0x%x)\n", __func__,
- *stat, *stat2);
-
- if (status)
- pr_err("%s, line=%d, status=%d\n", __func__, __LINE__, status);
-
- return status;
-}
-
-/**
- * ak89xx_read_raw() - read raw method.
- */
-static int ak89xx_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val,
- int *val2,
- long mask) {
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- int scale = 0;
-
- switch (mask) {
- case 0:
- if (!(iio_buffer_enabled(indio_dev)))
- return -EINVAL;
- if (chan->type == IIO_MAGN) {
- *val = st->compass_data[chan->channel2 - IIO_MOD_X];
- return IIO_VAL_INT;
- }
-
- return -EINVAL;
- case IIO_CHAN_INFO_SCALE:
- if (chan->type == IIO_MAGN) {
- if (st->compass_id == COMPASS_ID_AK8975)
- scale = 9830;
- else if (st->compass_id == COMPASS_ID_AK8972)
- scale = 19661;
- else if (st->compass_id == COMPASS_ID_AK8963) {
- if (st->compass_scale)
- scale = 4915; /* 16 bit */
- else
- scale = 19661; /* 14 bit */
- }
- scale *= (1L << 15);
- *val = scale;
- return IIO_VAL_INT;
- }
- return -EINVAL;
- default:
- return -EINVAL;
- }
-}
-
-static ssize_t ak89xx_value_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- short c[3];
-
- mutex_lock(&indio_dev->mlock);
- c[0] = st->compass_data[0];
- c[1] = st->compass_data[1];
- c[2] = st->compass_data[2];
- mutex_unlock(&indio_dev->mlock);
- return sprintf(buf, "%d, %d, %d\n", c[0], c[1], c[2]);
-}
-
-static ssize_t ak89xx_scale_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- int scale = 0;
-
- if (st->compass_id == COMPASS_ID_AK8975)
- scale = 9830;
- else if (st->compass_id == COMPASS_ID_AK8972)
- scale = 19661;
- else if (st->compass_id == COMPASS_ID_AK8963) {
- if (st->compass_scale)
- scale = 4915; /* 16 bit */
- else
- scale = 19661; /* 14 bit */
- }
- scale *= (1L << 15);
- return sprintf(buf, "%d\n", scale);
-}
-
-static ssize_t ak89xx_rate_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- /* transform delay in ms to rate */
- return sprintf(buf, "%d\n", (1000 / st->delay));
-}
-
-/**
- * ak89xx_matrix_show() - show orientation matrix
- */
-static ssize_t ak89xx_matrix_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- signed char *m;
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- m = st->plat_data.orientation;
- return sprintf(buf,
- "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
- m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
-}
-
-void set_ak89xx_enable(struct iio_dev *indio_dev, bool enable)
-{
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- int result = 0;
- unsigned char scale = 0;
-
- if (st->compass_id == COMPASS_ID_AK8963)
- scale = st->compass_scale;
-
- if (enable) {
- result = inv_serial_single_write(st, AK89XX_REG_CNTL,
- (scale << 4) | AK89XX_CNTL_MODE_SNG_MEASURE);
- if (result)
- pr_err("%s, line=%d\n", __func__, __LINE__);
- schedule_delayed_work(&st->work,
- msecs_to_jiffies(st->delay));
- } else {
- cancel_delayed_work_sync(&st->work);
- result = inv_serial_single_write(st, AK89XX_REG_CNTL,
- (scale << 4) | AK89XX_CNTL_MODE_POWER_DOWN);
- if (result)
- pr_err("%s, line=%d\n", __func__, __LINE__);
- mdelay(1); /* wait at least 100us */
- }
-}
-
-static ssize_t ak89xx_scale_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- unsigned long data, result;
-
- result = kstrtoul(buf, 10, &data);
- if (result)
- return result;
- if (st->compass_id == COMPASS_ID_AK8963)
- st->compass_scale = !!data;
- return count;
-}
-
-static ssize_t ak89xx_rate_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned long data;
- int error;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
-
- error = kstrtoul(buf, 10, &data);
- if (error)
- return error;
- /* transform rate to delay in ms */
- data = 1000 / data;
- if (data > AK89XX_MAX_DELAY)
- data = AK89XX_MAX_DELAY;
- if (data < AK89XX_MIN_DELAY)
- data = AK89XX_MIN_DELAY;
- st->delay = (unsigned int) data;
- return count;
-}
-
-static void ak89xx_work_func(struct work_struct *work)
-{
- struct inv_ak89xx_state_s *st =
- container_of((struct delayed_work *)work,
- struct inv_ak89xx_state_s, work);
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- unsigned long delay = msecs_to_jiffies(st->delay);
-
- mutex_lock(&indio_dev->mlock);
- if (!(iio_buffer_enabled(indio_dev)))
- goto error_ret;
-
- st->timestamp = get_time_ns();
- schedule_delayed_work(&st->work, delay);
- inv_read_ak89xx_fifo(indio_dev);
- INV_I2C_INC_COMPASSIRQ();
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
-}
-
-static const struct iio_chan_spec compass_channels[] = {
- {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_AK89XX_SCAN_MAGN_X,
- .scan_type = IIO_ST('s', 16, 16, 0)
- }, {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_AK89XX_SCAN_MAGN_Y,
- .scan_type = IIO_ST('s', 16, 16, 0)
- }, {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_AK89XX_SCAN_MAGN_Z,
- .scan_type = IIO_ST('s', 16, 16, 0)
- },
- IIO_CHAN_SOFT_TIMESTAMP(INV_AK89XX_SCAN_TIMESTAMP)
-};
-
-static DEVICE_ATTR(value, S_IRUGO, ak89xx_value_show, NULL);
-static DEVICE_ATTR(scale, S_IRUGO | S_IWUSR, ak89xx_scale_show,
- ak89xx_scale_store);
-static DEVICE_ATTR(sampling_frequency, S_IRUGO | S_IWUSR, ak89xx_rate_show,
- ak89xx_rate_store);
-static DEVICE_ATTR(compass_matrix, S_IRUGO, ak89xx_matrix_show, NULL);
-
-static struct attribute *inv_ak89xx_attributes[] = {
- &dev_attr_value.attr,
- &dev_attr_scale.attr,
- &dev_attr_sampling_frequency.attr,
- &dev_attr_compass_matrix.attr,
- NULL,
-};
-
-static const struct attribute_group inv_attribute_group = {
- .name = "ak89xx",
- .attrs = inv_ak89xx_attributes
-};
-
-static const struct iio_info ak89xx_info = {
- .driver_module = THIS_MODULE,
- .read_raw = &ak89xx_read_raw,
- .attrs = &inv_attribute_group,
-};
-
-/*constant IIO attribute */
-/**
- * inv_ak89xx_probe() - probe function.
- */
-static int inv_ak89xx_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct inv_ak89xx_state_s *st;
- struct iio_dev *indio_dev;
- int result;
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- result = -ENODEV;
- goto out_no_free;
- }
- indio_dev = iio_allocate_device(sizeof(*st));
- if (indio_dev == NULL) {
- result = -ENOMEM;
- goto out_no_free;
- }
- st = iio_priv(indio_dev);
- st->i2c = client;
- st->sl_handle = client->adapter;
- st->plat_data =
- *(struct mpu_platform_data *)dev_get_platdata(&client->dev);
- st->i2c_addr = client->addr;
- st->delay = AK89XX_DEFAULT_DELAY;
- st->compass_id = id->driver_data;
- st->compass_scale = 0;
-
- i2c_set_clientdata(client, indio_dev);
- result = ak89xx_init(st);
- if (result)
- goto out_free;
-
- indio_dev->dev.parent = &client->dev;
- indio_dev->name = id->name;
- indio_dev->channels = compass_channels;
- indio_dev->num_channels = ARRAY_SIZE(compass_channels);
- indio_dev->info = &ak89xx_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->currentmode = INDIO_DIRECT_MODE;
-
- result = inv_ak89xx_configure_ring(indio_dev);
- if (result)
- goto out_free;
- result = iio_buffer_register(indio_dev, indio_dev->channels,
- indio_dev->num_channels);
- if (result)
- goto out_unreg_ring;
- result = inv_ak89xx_probe_trigger(indio_dev);
- if (result)
- goto out_remove_ring;
-
- result = iio_device_register(indio_dev);
- if (result)
- goto out_remove_trigger;
- INIT_DELAYED_WORK(&st->work, ak89xx_work_func);
- pr_info("%s: Probe name %s\n", __func__, id->name);
- return 0;
-out_remove_trigger:
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
- inv_ak89xx_remove_trigger(indio_dev);
-out_remove_ring:
- iio_buffer_unregister(indio_dev);
-out_unreg_ring:
- inv_ak89xx_unconfigure_ring(indio_dev);
-out_free:
- iio_free_device(indio_dev);
-out_no_free:
- dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
- return -EIO;
-}
-
-/**
- * inv_ak89xx_remove() - remove function.
- */
-static int inv_ak89xx_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- cancel_delayed_work_sync(&st->work);
- iio_device_unregister(indio_dev);
- inv_ak89xx_remove_trigger(indio_dev);
- iio_buffer_unregister(indio_dev);
- inv_ak89xx_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
-
- dev_info(&client->adapter->dev, "inv-ak89xx-iio module removed.\n");
- return 0;
-}
-
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* device id table is used to identify what device can be
- * supported by this driver
- */
-static const struct i2c_device_id inv_ak89xx_id[] = {
- {"akm8975", COMPASS_ID_AK8975},
- {"akm8972", COMPASS_ID_AK8972},
- {"akm8963", COMPASS_ID_AK8963},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, inv_ak89xx_id);
-
-static struct i2c_driver inv_ak89xx_driver = {
- .class = I2C_CLASS_HWMON,
- .probe = inv_ak89xx_probe,
- .remove = inv_ak89xx_remove,
- .id_table = inv_ak89xx_id,
- .driver = {
- .owner = THIS_MODULE,
- .name = "inv-ak89xx-iio",
- },
- .address_list = normal_i2c,
-};
-
-static int __init inv_ak89xx_init(void)
-{
- int result = i2c_add_driver(&inv_ak89xx_driver);
- if (result) {
- pr_err("%s failed\n", __func__);
- return result;
- }
- return 0;
-}
-
-static void __exit inv_ak89xx_exit(void)
-{
- i2c_del_driver(&inv_ak89xx_driver);
-}
-
-module_init(inv_ak89xx_init);
-module_exit(inv_ak89xx_exit);
-
-MODULE_AUTHOR("Invensense Corporation");
-MODULE_DESCRIPTION("Invensense device driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("inv-ak89xx-iio");
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ak89xx_iio.h b/drivers/iio/magnetometer/inv_compass/inv_ak89xx_iio.h
deleted file mode 100755
index 9a9f14a73ec..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ak89xx_iio.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-#ifndef _INV_AK89XX_IIO_H_
-#define _INV_AK89XX_IIO_H_
-
-#include <linux/i2c.h>
-#include <linux/kfifo.h>
-#include <linux/miscdevice.h>
-#include <linux/input.h>
-#include <linux/spinlock.h>
-#include <linux/mpu.h>
-
-#include "iio.h"
-#include "buffer.h"
-#include "trigger.h"
-
-/**
- * struct inv_ak89xx_state_s - Driver state variables.
- * @plat_data: board file platform data.
- * @i2c: i2c client handle.
- * @trig: not used. for compatibility.
- * @work: work data structure.
- * @delay: delay between each scheduled work.
- * @dev: Represents read-only node for accessing buffered data.
- * @inv_dev: Handle to input device.
- * @sl_handle: Handle to I2C port.
- */
-struct inv_ak89xx_state_s {
- struct mpu_platform_data plat_data;
- struct i2c_client *i2c;
- struct iio_trigger *trig;
- struct delayed_work work;
- int delay; /* msec */
- unsigned char compass_id;
- int compass_scale; /* for ak8963, 1:16-bit, 0:14-bit */
- short compass_data[3];
- u8 asa[3]; /* axis sensitivity adjustment */
- s64 timestamp;
- short i2c_addr;
- void *sl_handle;
- struct device *inv_dev;
- struct input_dev *idev;
-};
-
-/* scan element definition */
-enum inv_mpu_scan {
- INV_AK89XX_SCAN_MAGN_X,
- INV_AK89XX_SCAN_MAGN_Y,
- INV_AK89XX_SCAN_MAGN_Z,
- INV_AK89XX_SCAN_TIMESTAMP,
-};
-
-#define AK89XX_I2C_NAME "ak89xx"
-
-#define SENSOR_DATA_SIZE 8
-#define YPR_DATA_SIZE 12
-#define RWBUF_SIZE 16
-
-#define ACC_DATA_FLAG 0
-#define MAG_DATA_FLAG 1
-#define ORI_DATA_FLAG 2
-#define AKM_NUM_SENSORS 3
-
-#define ACC_DATA_READY (1 << (ACC_DATA_FLAG))
-#define MAG_DATA_READY (1 << (MAG_DATA_FLAG))
-#define ORI_DATA_READY (1 << (ORI_DATA_FLAG))
-
-#define AKM_MINOR_NUMBER 254
-
-/*! \name AK89XX constant definition
- \anchor AK89XX_Def
- Constant definitions of the AK89XX.*/
-#define AK89XX_MEASUREMENT_TIME_US 10000
-
-/*! \name AK89XX operation mode
- \anchor AK89XX_Mode
- Defines an operation mode of the AK89XX.*/
-/*! @{*/
-#define AK89XX_CNTL_MODE_SNG_MEASURE 0x01
-#define AK89XX_CNTL_MODE_SELF_TEST 0x08
-#define AK89XX_CNTL_MODE_FUSE_ACCESS 0x0F
-#define AK89XX_CNTL_MODE_POWER_DOWN 0x00
-/*! @}*/
-
-/*! \name AK89XX register address
-\anchor AK89XX_REG
-Defines a register address of the AK89XX.*/
-/*! @{*/
-#define AK89XX_REG_WIA 0x00
-#define AK89XX_REG_INFO 0x01
-#define AK89XX_REG_ST1 0x02
-#define AK89XX_REG_HXL 0x03
-#define AK89XX_REG_HXH 0x04
-#define AK89XX_REG_HYL 0x05
-#define AK89XX_REG_HYH 0x06
-#define AK89XX_REG_HZL 0x07
-#define AK89XX_REG_HZH 0x08
-#define AK89XX_REG_ST2 0x09
-#define AK89XX_REG_CNTL 0x0A
-#define AK89XX_REG_RSV 0x0B
-#define AK89XX_REG_ASTC 0x0C
-#define AK89XX_REG_TS1 0x0D
-#define AK89XX_REG_TS2 0x0E
-#define AK89XX_REG_I2CDIS 0x0F
-/*! @}*/
-
-/*! \name AK89XX fuse-rom address
-\anchor AK89XX_FUSE
-Defines a read-only address of the fuse ROM of the AK89XX.*/
-/*! @{*/
-#define AK89XX_FUSE_ASAX 0x10
-#define AK89XX_FUSE_ASAY 0x11
-#define AK89XX_FUSE_ASAZ 0x12
-/*! @}*/
-
-#define AK89XX_MAX_DELAY (200)
-#define AK89XX_MIN_DELAY (10)
-#define AK89XX_DEFAULT_DELAY (100)
-
-#define INV_ERROR_COMPASS_DATA_OVERFLOW (-1)
-#define INV_ERROR_COMPASS_DATA_NOT_READY (-2)
-
-int inv_ak89xx_configure_ring(struct iio_dev *indio_dev);
-void inv_ak89xx_unconfigure_ring(struct iio_dev *indio_dev);
-int inv_ak89xx_probe_trigger(struct iio_dev *indio_dev);
-void inv_ak89xx_remove_trigger(struct iio_dev *indio_dev);
-void set_ak89xx_enable(struct iio_dev *indio_dev, bool enable);
-int ak89xx_read_raw_data(struct inv_ak89xx_state_s *st,
- short dat[3]);
-void inv_read_ak89xx_fifo(struct iio_dev *indio_dev);
-int ak89xx_read(struct inv_ak89xx_state_s *st, short rawfixed[3]);
-
-#endif
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ak89xx_ring.c b/drivers/iio/magnetometer/inv_compass/inv_ak89xx_ring.c
deleted file mode 100755
index a8c1090bed5..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ak89xx_ring.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-* Copyright (C) 2013 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-
-#include "iio.h"
-#include "kfifo_buf.h"
-#include "trigger_consumer.h"
-#include "sysfs.h"
-
-#include "inv_ak89xx_iio.h"
-
-static int put_scan_to_buf(struct iio_dev *indio_dev, unsigned char *d,
- short *s, int scan_index)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- int st;
- int i, d_ind;
-
- d_ind = 0;
- for (i = 0; i < 3; i++) {
- st = iio_scan_mask_query(indio_dev, ring, scan_index + i);
- if (st) {
- memcpy(&d[d_ind], &s[i], sizeof(s[i]));
- d_ind += sizeof(s[i]);
- }
- }
-
- return d_ind;
-}
-
-/**
- * inv_read_ak89xx_fifo() - Transfer data from FIFO to ring buffer.
- */
-void inv_read_ak89xx_fifo(struct iio_dev *indio_dev)
-{
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- int d_ind;
- s8 *tmp;
- s64 tmp_buf[2];
-
- if (!ak89xx_read(st, st->compass_data)) {
- st->compass_data[0] = (short)(((int)st->compass_data[0] * (st->asa[0] + 128)) >> 8);
- st->compass_data[1] = (short)(((int)st->compass_data[1] * (st->asa[1] + 128)) >> 8);
- st->compass_data[2] = (short)(((int)st->compass_data[2] * (st->asa[2] + 128)) >> 8);
- tmp = (u8 *)tmp_buf;
- d_ind = put_scan_to_buf(indio_dev, tmp, st->compass_data,
- INV_AK89XX_SCAN_MAGN_X);
- if (ring->scan_timestamp)
- tmp_buf[(d_ind + 7)/8] = st->timestamp;
- ring->access->store_to(indio_dev->buffer, tmp, st->timestamp);
- }
-}
-
-void inv_ak89xx_unconfigure_ring(struct iio_dev *indio_dev)
-{
- iio_kfifo_free(indio_dev->buffer);
-};
-
-static int inv_ak89xx_postenable(struct iio_dev *indio_dev)
-{
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
-
- /* when all the outputs are disabled, even though buffer/enable is on,
- do nothing */
- if (!(iio_scan_mask_query(indio_dev, ring, INV_AK89XX_SCAN_MAGN_X) ||
- iio_scan_mask_query(indio_dev, ring, INV_AK89XX_SCAN_MAGN_Y) ||
- iio_scan_mask_query(indio_dev, ring, INV_AK89XX_SCAN_MAGN_Z)))
- return 0;
-
- set_ak89xx_enable(indio_dev, true);
- schedule_delayed_work(&st->work, msecs_to_jiffies(st->delay));
-
- return 0;
-}
-
-static int inv_ak89xx_predisable(struct iio_dev *indio_dev)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
-
- cancel_delayed_work_sync(&st->work);
- clear_bit(INV_AK89XX_SCAN_MAGN_X, ring->scan_mask);
- clear_bit(INV_AK89XX_SCAN_MAGN_Y, ring->scan_mask);
- clear_bit(INV_AK89XX_SCAN_MAGN_Z, ring->scan_mask);
- set_ak89xx_enable(indio_dev, false);
-
- return 0;
-}
-
-static const struct iio_buffer_setup_ops inv_ak89xx_ring_setup_ops = {
- .preenable = &iio_sw_buffer_preenable,
- .postenable = &inv_ak89xx_postenable,
- .predisable = &inv_ak89xx_predisable,
-};
-
-int inv_ak89xx_configure_ring(struct iio_dev *indio_dev)
-{
- int ret = 0;
- struct iio_buffer *ring;
-
- ring = iio_kfifo_allocate(indio_dev);
- if (!ring) {
- ret = -ENOMEM;
- return ret;
- }
- indio_dev->buffer = ring;
- /* setup ring buffer */
- ring->scan_timestamp = true;
- indio_dev->setup_ops = &inv_ak89xx_ring_setup_ops;
-
- indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
- return 0;
-}
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ak89xx_trigger.c b/drivers/iio/magnetometer/inv_compass/inv_ak89xx_trigger.c
deleted file mode 100755
index 04c77ab5c79..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ak89xx_trigger.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-* Copyright (C) 2013 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "iio.h"
-#include "sysfs.h"
-#include "trigger.h"
-#include "inv_ak89xx_iio.h"
-
-static const struct iio_trigger_ops inv_ak89xx_trigger_ops = {
- .owner = THIS_MODULE,
-};
-
-int inv_ak89xx_probe_trigger(struct iio_dev *indio_dev)
-{
- int ret;
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
-
- st->trig = iio_allocate_trigger("%s-dev%d",
- indio_dev->name,
- indio_dev->id);
- if (st->trig == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- /* select default trigger */
- st->trig->dev.parent = &st->i2c->dev;
- st->trig->private_data = indio_dev;
- st->trig->ops = &inv_ak89xx_trigger_ops;
- ret = iio_trigger_register(st->trig);
-
- /* select default trigger */
- indio_dev->trig = st->trig;
- if (ret)
- goto error_free_trig;
-
- return 0;
-
-error_free_trig:
- iio_free_trigger(st->trig);
-error_ret:
- return ret;
-}
-
-void inv_ak89xx_remove_trigger(struct iio_dev *indio_dev)
-{
- struct inv_ak89xx_state_s *st = iio_priv(indio_dev);
-
- iio_trigger_unregister(st->trig);
- iio_free_trigger(st->trig);
-}
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ami306_core.c b/drivers/iio/magnetometer/inv_compass/inv_ami306_core.c
deleted file mode 100755
index 612ba72b59e..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ami306_core.c
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-*/
-
-/**
- * @addtogroup DRIVERS
- * @brief Hardware drivers.
- *
- * @{
- * @file inv_ami306_core.c
- * @brief Invensense implementation for AMI306
- * @details This driver currently works for the AMI306
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "inv_ami306_iio.h"
-#include "sysfs.h"
-#include "inv_test/inv_counters.h"
-
-static unsigned char late_initialize = true;
-
-s32 i2c_write(const struct i2c_client *client,
- u8 command, u8 length, const u8 *values)
-{
- INV_I2C_INC_COMPASSWRITE(3);
- return i2c_smbus_write_i2c_block_data(client, command, length, values);
-}
-
-s32 i2c_read(const struct i2c_client *client,
- u8 command, u8 length, u8 *values)
-{
- INV_I2C_INC_COMPASSWRITE(3);
- INV_I2C_INC_COMPASSREAD(length);
- return i2c_smbus_read_i2c_block_data(client, command, length, values);
-}
-
-static int ami306_read_param(struct inv_ami306_state_s *st)
-{
- int result = 0;
- unsigned char regs[AMI_PARAM_LEN];
- struct ami_sensor_parametor *param = &st->param;
-
- result = i2c_read(st->i2c, REG_AMI_SENX,
- AMI_PARAM_LEN, regs);
- if (result < 0)
- return result;
-
- /* Little endian 16 bit registers */
- param->m_gain.x = le16_to_cpup((__le16 *)(&regs[0]));
- param->m_gain.y = le16_to_cpup((__le16 *)(&regs[2]));
- param->m_gain.z = le16_to_cpup((__le16 *)(&regs[4]));
-
- param->m_interference.xy = regs[7];
- param->m_interference.xz = regs[6];
- param->m_interference.yx = regs[9];
- param->m_interference.yz = regs[8];
- param->m_interference.zx = regs[11];
- param->m_interference.zy = regs[10];
-
- param->m_offset.x = AMI_STANDARD_OFFSET;
- param->m_offset.y = AMI_STANDARD_OFFSET;
- param->m_offset.z = AMI_STANDARD_OFFSET;
-
- param->m_gain_cor.x = AMI_GAIN_COR_DEFAULT;
- param->m_gain_cor.y = AMI_GAIN_COR_DEFAULT;
- param->m_gain_cor.z = AMI_GAIN_COR_DEFAULT;
-
- return 0;
-}
-
-static int ami306_write_offset(const struct i2c_client *client,
- unsigned char *fine)
-{
- int result = 0;
- unsigned char dat[3];
- dat[0] = (0x7f & fine[0]);
- dat[1] = 0;
- result = i2c_write(client, REG_AMI_OFFX, 2, dat);
- dat[0] = (0x7f & fine[1]);
- dat[1] = 0;
- result = i2c_write(client, REG_AMI_OFFY, 2, dat);
- dat[0] = (0x7f & fine[2]);
- dat[1] = 0;
- result = i2c_write(client, REG_AMI_OFFZ, 2, dat);
-
- return result;
-}
-
-static int ami306_wait_data_ready(struct inv_ami306_state_s *st,
- unsigned long usecs, unsigned long times)
-{
- int result = 0;
- unsigned char buf;
-
- for (; 0 < times; --times) {
- udelay(usecs);
- result = i2c_read(st->i2c, REG_AMI_STA1, 1, &buf);
- if (result < 0)
- return INV_ERROR_COMPASS_DATA_NOT_READY;
- if (buf & AMI_STA1_DRDY_BIT)
- return 0;
- else if (buf & AMI_STA1_DOR_BIT)
- return INV_ERROR_COMPASS_DATA_OVERFLOW;
- }
-
- return INV_ERROR_COMPASS_DATA_NOT_READY;
-}
-int ami306_read_raw_data(struct inv_ami306_state_s *st,
- short dat[3])
-{
- int result;
- unsigned char buf[6];
- result = i2c_read(st->i2c, REG_AMI_DATAX, sizeof(buf), buf);
- if (result < 0)
- return result;
- dat[0] = le16_to_cpup((__le16 *)(&buf[0]));
- dat[1] = le16_to_cpup((__le16 *)(&buf[2]));
- dat[2] = le16_to_cpup((__le16 *)(&buf[4]));
-
- return 0;
-}
-
-#define AMI_WAIT_DATAREADY_RETRY 3 /* retry times */
-#define AMI_DRDYWAIT 800 /* u(micro) sec */
-static int ami306_force_measurement(struct inv_ami306_state_s *st,
- short ver[3])
-{
- int result;
- int status;
- char buf;
- buf = AMI_CTRL3_FORCE_BIT;
- result = i2c_write(st->i2c, REG_AMI_CTRL3, 1, &buf);
- if (result < 0)
- return result;
-
- result = ami306_wait_data_ready(st,
- AMI_DRDYWAIT, AMI_WAIT_DATAREADY_RETRY);
- if (result && result != INV_ERROR_COMPASS_DATA_OVERFLOW)
- return result;
- /* READ DATA X,Y,Z */
- status = ami306_read_raw_data(st, ver);
- if (status)
- return status;
-
- return result;
-}
-
-static int ami306_initial_b0_adjust(struct inv_ami306_state_s *st)
-{
- int result;
- unsigned char fine[3] = { 0 };
- short data[3];
- int diff[3] = { 0x7fff, 0x7fff, 0x7fff };
- int fn = 0;
- int ax = 0;
- unsigned char buf[3];
-
- buf[0] = AMI_CTRL2_DREN;
- result = i2c_write(st->i2c, REG_AMI_CTRL2, 1, buf);
- if (result)
- return result;
-
- buf[0] = AMI_CTRL4_HS & 0xFF;
- buf[1] = (AMI_CTRL4_HS >> 8) & 0xFF;
- result = i2c_write(st->i2c, REG_AMI_CTRL4, 2, buf);
- if (result < 0)
- return result;
-
- for (fn = 0; fn < AMI_FINE_MAX; ++fn) { /* fine 0 -> 95 */
- fine[0] = fine[1] = fine[2] = fn;
- result = ami306_write_offset(st->i2c, fine);
- if (result)
- return result;
-
- result = ami306_force_measurement(st, data);
- if (result)
- return result;
-
- for (ax = 0; ax < 3; ax++) {
- /* search point most close to zero. */
- if (diff[ax] > abs(data[ax])) {
- st->fine[ax] = fn;
- diff[ax] = abs(data[ax]);
- }
- }
- }
- result = ami306_write_offset(st->i2c, st->fine);
- if (result)
- return result;
-
- /* Software Reset */
- buf[0] = AMI_CTRL3_SRST_BIT;
- result = i2c_write(st->i2c, REG_AMI_CTRL3, 1, buf);
- if (result < 0)
- return result;
- else
- return 0;
-}
-
-static int ami306_start_sensor(struct inv_ami306_state_s *st)
-{
- int result = 0;
- unsigned char buf[2];
-
- /* Step 1 */
- buf[0] = (AMI_CTRL1_PC1 | AMI_CTRL1_FS1_FORCE);
- result = i2c_write(st->i2c, REG_AMI_CTRL1, 1, buf);
- if (result < 0)
- return result;
- /* Step 2 */
- buf[0] = AMI_CTRL2_DREN;
- result = i2c_write(st->i2c, REG_AMI_CTRL2, 1, buf);
- if (result < 0)
- return result;
- /* Step 3 */
- buf[0] = (AMI_CTRL4_HS & 0xFF);
- buf[1] = (AMI_CTRL4_HS >> 8) & 0xFF;
-
- result = i2c_write(st->i2c, REG_AMI_CTRL4, 2, buf);
- if (result < 0)
- return result;
-
- /* Step 4 */
- result = ami306_write_offset(st->i2c, st->fine);
-
- return result;
-}
-
-int set_ami306_enable(struct iio_dev *indio_dev, int state)
-{
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
- int result;
- char buf;
-
- buf = (AMI_CTRL1_PC1 | AMI_CTRL1_FS1_FORCE);
- result = i2c_write(st->i2c, REG_AMI_CTRL1, 1, &buf);
- if (result < 0)
- return result;
-
- result = ami306_read_param(st);
- if (result)
- return result;
- if (late_initialize) {
- result = ami306_initial_b0_adjust(st);
- if (result)
- return result;
- late_initialize = false;
- }
- result = ami306_start_sensor(st);
- if (result)
- return result;
- buf = AMI_CTRL3_FORCE_BIT;
- st->timestamp = iio_get_time_ns();
- result = i2c_write(st->i2c, REG_AMI_CTRL3, 1, &buf);
- if (result)
- return result;
-
- return 0;
-}
-
-/**
- * ami306_read_raw() - read raw method.
- */
-static int ami306_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val,
- int *val2,
- long mask) {
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
-
- switch (mask) {
- case 0:
- if (!(iio_buffer_enabled(indio_dev)))
- return -EINVAL;
- if (chan->type == IIO_MAGN) {
- *val = st->compass_data[chan->channel2 - IIO_MOD_X];
- return IIO_VAL_INT;
- }
-
- return -EINVAL;
- case IIO_CHAN_INFO_SCALE:
- if (chan->type == IIO_MAGN) {
- *val = AMI_SCALE;
- return IIO_VAL_INT;
- }
- return -EINVAL;
- default:
- return -EINVAL;
- }
-}
-
-/**
- * inv_compass_matrix_show() - show orientation matrix
- */
-static ssize_t inv_compass_matrix_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- signed char *m;
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
- m = st->plat_data.orientation;
- return sprintf(buf,
- "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
- m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
-}
-
-static ssize_t ami306_rate_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned long data;
- int error;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
-
- error = kstrtoul(buf, 10, &data);
- if (error)
- return error;
- if (0 == data)
- return -EINVAL;
- /* transform rate to delay in ms */
- data = 1000 / data;
- if (data > AMI_MAX_DELAY)
- data = AMI_MAX_DELAY;
- if (data < AMI_MIN_DELAY)
- data = AMI_MIN_DELAY;
- st->delay = data;
- return count;
-}
-
-static ssize_t ami306_rate_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
- /* transform delay in ms to rate */
- return sprintf(buf, "%d\n", 1000 / st->delay);
-}
-
-
-static void ami306_work_func(struct work_struct *work)
-{
- struct inv_ami306_state_s *st =
- container_of((struct delayed_work *)work,
- struct inv_ami306_state_s, work);
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- unsigned long delay = msecs_to_jiffies(st->delay);
-
- mutex_lock(&indio_dev->mlock);
- if (!(iio_buffer_enabled(indio_dev)))
- goto error_ret;
-
- st->timestamp = iio_get_time_ns();
- schedule_delayed_work(&st->work, delay);
- inv_read_ami306_fifo(indio_dev);
- INV_I2C_INC_COMPASSIRQ();
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
-}
-
-static const struct iio_chan_spec compass_channels[] = {
- {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_AMI306_SCAN_MAGN_X,
- .scan_type = IIO_ST('s', 16, 16, 0)
- }, {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_AMI306_SCAN_MAGN_Y,
- .scan_type = IIO_ST('s', 16, 16, 0)
- }, {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_AMI306_SCAN_MAGN_Z,
- .scan_type = IIO_ST('s', 16, 16, 0)
- },
- IIO_CHAN_SOFT_TIMESTAMP(INV_AMI306_SCAN_TIMESTAMP)
-};
-
-static DEVICE_ATTR(compass_matrix, S_IRUGO, inv_compass_matrix_show, NULL);
-static DEVICE_ATTR(sampling_frequency, S_IRUGO | S_IWUSR, ami306_rate_show,
- ami306_rate_store);
-
-static struct attribute *inv_ami306_attributes[] = {
- &dev_attr_compass_matrix.attr,
- &dev_attr_sampling_frequency.attr,
- NULL,
-};
-static const struct attribute_group inv_attribute_group = {
- .name = "ami306",
- .attrs = inv_ami306_attributes
-};
-
-static const struct iio_info ami306_info = {
- .driver_module = THIS_MODULE,
- .read_raw = &ami306_read_raw,
- .attrs = &inv_attribute_group,
-};
-
-/*constant IIO attribute */
-/**
- * inv_ami306_probe() - probe function.
- */
-static int inv_ami306_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct inv_ami306_state_s *st;
- struct iio_dev *indio_dev;
- int result;
- char data;
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- result = -ENODEV;
- goto out_no_free;
- }
- indio_dev = iio_allocate_device(sizeof(*st));
- if (indio_dev == NULL) {
- result = -ENOMEM;
- goto out_no_free;
- }
- st = iio_priv(indio_dev);
- st->i2c = client;
- st->plat_data =
- *(struct mpu_platform_data *)dev_get_platdata(&client->dev);
- st->delay = 10;
-
- /* Make state variables available to all _show and _store functions. */
- i2c_set_clientdata(client, indio_dev);
- result = i2c_read(st->i2c, REG_AMI_WIA, 1, &data);
- if (result < 0)
- goto out_free;
- if (data != DATA_WIA)
- goto out_free;
-
- indio_dev->dev.parent = &client->dev;
- indio_dev->name = id->name;
- indio_dev->channels = compass_channels;
- indio_dev->num_channels = ARRAY_SIZE(compass_channels);
- indio_dev->info = &ami306_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->currentmode = INDIO_DIRECT_MODE;
-
- result = inv_ami306_configure_ring(indio_dev);
- if (result)
- goto out_free;
- result = iio_buffer_register(indio_dev, indio_dev->channels,
- indio_dev->num_channels);
- if (result)
- goto out_unreg_ring;
- result = inv_ami306_probe_trigger(indio_dev);
- if (result)
- goto out_remove_ring;
-
- result = iio_device_register(indio_dev);
- if (result)
- goto out_remove_trigger;
- INIT_DELAYED_WORK(&st->work, ami306_work_func);
- pr_info("%s: Probe name %s\n", __func__, id->name);
- return 0;
-out_remove_trigger:
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
- inv_ami306_remove_trigger(indio_dev);
-out_remove_ring:
- iio_buffer_unregister(indio_dev);
-out_unreg_ring:
- inv_ami306_unconfigure_ring(indio_dev);
-out_free:
- iio_free_device(indio_dev);
-out_no_free:
- dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
- return -EIO;
-}
-
-/**
- * inv_ami306_remove() - remove function.
- */
-static int inv_ami306_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
- cancel_delayed_work_sync(&st->work);
- iio_device_unregister(indio_dev);
- inv_ami306_remove_trigger(indio_dev);
- iio_buffer_unregister(indio_dev);
- inv_ami306_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
-
- dev_info(&client->adapter->dev, "inv-ami306-iio module removed.\n");
- return 0;
-}
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-/* device id table is used to identify what device can be
- * supported by this driver
- */
-static const struct i2c_device_id inv_ami306_id[] = {
- {"ami306", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, inv_ami306_id);
-
-static struct i2c_driver inv_ami306_driver = {
- .class = I2C_CLASS_HWMON,
- .probe = inv_ami306_probe,
- .remove = inv_ami306_remove,
- .id_table = inv_ami306_id,
- .driver = {
- .owner = THIS_MODULE,
- .name = "inv-ami306-iio",
- },
- .address_list = normal_i2c,
-};
-
-static int __init inv_ami306_init(void)
-{
- int result = i2c_add_driver(&inv_ami306_driver);
- if (result) {
- pr_err("%s failed\n", __func__);
- return result;
- }
- return 0;
-}
-
-static void __exit inv_ami306_exit(void)
-{
- i2c_del_driver(&inv_ami306_driver);
-}
-
-module_init(inv_ami306_init);
-module_exit(inv_ami306_exit);
-
-MODULE_AUTHOR("Invensense Corporation");
-MODULE_DESCRIPTION("Invensense device driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("inv-ami306-iio");
-/**
- * @}
- */
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ami306_iio.h b/drivers/iio/magnetometer/inv_compass/inv_ami306_iio.h
deleted file mode 100755
index fa4f4ee1e5d..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ami306_iio.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-*/
-
-/**
- * @addtogroup DRIVERS
- * @brief Hardware drivers.
- *
- * @{
- * @file inv_ami306_iio.h
- * @brief Struct definitions for the Invensense implementation
- * of ami306 driver.
- */
-
-#ifndef _INV_GYRO_H_
-#define _INV_GYRO_H_
-
-#include <linux/i2c.h>
-#include <linux/kfifo.h>
-#include <linux/miscdevice.h>
-#include <linux/input.h>
-#include <linux/spinlock.h>
-#include <linux/mpu.h>
-
-#include "iio.h"
-#include "buffer.h"
-#include "trigger.h"
-
-/** axis sensitivity(gain) calibration parameter information */
-struct ami_vector3d {
- signed short x; /**< X-axis */
- signed short y; /**< Y-axis */
- signed short z; /**< Z-axis */
-};
-
-/** axis interference information */
-struct ami_interference {
- /**< Y-axis magnetic field for X-axis correction value */
- signed short xy;
- /**< Z-axis magnetic field for X-axis correction value */
- signed short xz;
- /**< X-axis magnetic field for Y-axis correction value */
- signed short yx;
- /**< Z-axis magnetic field for Y-axis correction value */
- signed short yz;
- /**< X-axis magnetic field for Z-axis correction value */
- signed short zx;
- /**< Y-axis magnetic field for Z-axis correction value */
- signed short zy;
-};
-
-/** sensor calibration Parameter information */
-struct ami_sensor_parametor {
- /**< geomagnetic field sensor gain */
- struct ami_vector3d m_gain;
- /**< geomagnetic field sensor gain correction parameter */
- struct ami_vector3d m_gain_cor;
- /**< geomagnetic field sensor offset */
- struct ami_vector3d m_offset;
- /**< geomagnetic field sensor axis interference parameter */
- struct ami_interference m_interference;
-};
-
-/**
- * struct inv_ami306_state_s - Driver state variables.
- * @plat_data: board file platform data.
- * @i2c: i2c client handle.
- * @trig: not used. for compatibility.
- * @param: ami specific sensor data.
- * @work: work data structure.
- * @delay: delay between each scheduled work.
- * @fine: fine tunign parameters.
- * @compass_data: compass data store.
- * @timestamp: time stamp.
- */
-struct inv_ami306_state_s {
- struct mpu_platform_data plat_data;
- struct i2c_client *i2c;
- struct iio_trigger *trig;
- struct ami_sensor_parametor param;
- struct delayed_work work;
- int delay;
- s8 fine[3];
- short compass_data[3];
- s64 timestamp;
-};
-/* scan element definition */
-enum inv_mpu_scan {
- INV_AMI306_SCAN_MAGN_X,
- INV_AMI306_SCAN_MAGN_Y,
- INV_AMI306_SCAN_MAGN_Z,
- INV_AMI306_SCAN_TIMESTAMP,
-};
-
-#define REG_AMI_WIA 0x0f
-#define REG_AMI_DATAX 0x10
-#define REG_AMI_STA1 0x18
-#define REG_AMI_CTRL1 0x1b
-#define REG_AMI_CTRL2 0x1c
-#define REG_AMI_CTRL3 0x1d
-#define REG_AMI_B0X 0x20
-#define REG_AMI_B0Y 0x22
-#define REG_AMI_B0Z 0x24
-#define REG_AMI_CTRL5 0x40
-#define REG_AMI_CTRL4 0x5c
-#define REG_AMI_TEMP 0x60
-#define REG_AMI_SENX 0x96
-#define REG_AMI_OFFX 0x6c
-#define REG_AMI_OFFY 0x72
-#define REG_AMI_OFFZ 0x78
-
-
-#define DATA_WIA 0x46
-#define AMI_CTRL1_PC1 0x80
-#define AMI_CTRL1_FS1_FORCE 0x02
-#define AMI_CTRL1_ODR1 0x10
-#define AMI_CTRL2_DREN 0x08
-#define AMI_CTRL2_DRP 0x04
-#define AMI_CTRL3_FORCE_BIT 0x40
-#define AMI_CTRL3_B0_LO_BIT 0x10
-#define AMI_CTRL3_SRST_BIT 0x80
-#define AMI_CTRL4_HS 0xa07e
-#define AMI_CTRL4_AB 0x0001
-#define AMI_STA1_DRDY_BIT 0x40
-#define AMI_STA1_DOR_BIT 0x20
-
-#define AMI_PARAM_LEN 12
-#define AMI_STANDARD_OFFSET 0x800
-#define AMI_GAIN_COR_DEFAULT 1000
-#define AMI_FINE_MAX 96
-#define AMI_MAX_DELAY 1000
-#define AMI_MIN_DELAY 10
-#define AMI_SCALE (5461 * (1<<15))
-
-#define INV_ERROR_COMPASS_DATA_OVERFLOW (-1)
-#define INV_ERROR_COMPASS_DATA_NOT_READY (-2)
-
-
-int inv_ami306_configure_ring(struct iio_dev *indio_dev);
-void inv_ami306_unconfigure_ring(struct iio_dev *indio_dev);
-int inv_ami306_probe_trigger(struct iio_dev *indio_dev);
-void inv_ami306_remove_trigger(struct iio_dev *indio_dev);
-int set_ami306_enable(struct iio_dev *indio_dev, int state);
-int ami306_read_raw_data(struct inv_ami306_state_s *st,
- short dat[3]);
-int inv_read_ami306_fifo(struct iio_dev *indio_dev);
-
-#endif /* #ifndef _INV_GYRO_H_ */
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ami306_ring.c b/drivers/iio/magnetometer/inv_compass/inv_ami306_ring.c
deleted file mode 100755
index ed91cf49516..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ami306_ring.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-*/
-
-/**
- * @addtogroup DRIVERS
- * @brief Hardware drivers.
- *
- * @{
- * @file inv_ami306_ring.c
- * @brief Invensense implementation for AMI306
- * @details This driver currently works for the AMI306
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-
-#include "iio.h"
-#include "kfifo_buf.h"
-#include "trigger_consumer.h"
-#include "sysfs.h"
-
-#include "inv_ami306_iio.h"
-
-static int put_scan_to_buf(struct iio_dev *indio_dev, unsigned char *d,
- short *s, int scan_index) {
- struct iio_buffer *ring = indio_dev->buffer;
- int st;
- int i, d_ind;
- d_ind = 0;
- for (i = 0; i < 3; i++) {
- st = iio_scan_mask_query(indio_dev, ring, scan_index + i);
- if (st) {
- memcpy(&d[d_ind], &s[i], sizeof(s[i]));
- d_ind += sizeof(s[i]);
- }
- }
- return d_ind;
-}
-
-/**
- * inv_read_fifo() - Transfer data from FIFO to ring buffer.
- */
-int inv_read_ami306_fifo(struct iio_dev *indio_dev)
-{
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- int result, status, d_ind;
- char b;
- char *tmp;
- s64 tmp_buf[2];
-
- result = i2c_smbus_read_i2c_block_data(st->i2c, REG_AMI_STA1, 1, &b);
- if (result < 0)
- goto end_session;
- if (b & AMI_STA1_DRDY_BIT) {
- status = ami306_read_raw_data(st, st->compass_data);
- if (status) {
- pr_err("error reading raw\n");
- goto end_session;
- }
- tmp = (unsigned char *)tmp_buf;
- d_ind = put_scan_to_buf(indio_dev, tmp, st->compass_data,
- INV_AMI306_SCAN_MAGN_X);
- if (ring->scan_timestamp)
- tmp_buf[(d_ind + 7)/8] = st->timestamp;
- ring->access->store_to(indio_dev->buffer, tmp, st->timestamp);
- } else if (b & AMI_STA1_DOR_BIT)
- pr_err("not ready\n");
-end_session:
- b = AMI_CTRL3_FORCE_BIT;
- result = i2c_smbus_write_i2c_block_data(st->i2c, REG_AMI_CTRL3, 1, &b);
-
- return IRQ_HANDLED;
-}
-
-void inv_ami306_unconfigure_ring(struct iio_dev *indio_dev)
-{
- iio_kfifo_free(indio_dev->buffer);
-};
-static int inv_ami306_postenable(struct iio_dev *indio_dev)
-{
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- int result;
-
- /* when all the outputs are disabled, even though buffer/enable is on,
- do nothing */
- if (!(iio_scan_mask_query(indio_dev, ring, INV_AMI306_SCAN_MAGN_X) ||
- iio_scan_mask_query(indio_dev, ring, INV_AMI306_SCAN_MAGN_Y) ||
- iio_scan_mask_query(indio_dev, ring, INV_AMI306_SCAN_MAGN_Z)))
- return 0;
-
- result = set_ami306_enable(indio_dev, true);
- if (result)
- return result;
- schedule_delayed_work(&st->work, msecs_to_jiffies(st->delay));
-
- return 0;
-}
-
-static int inv_ami306_predisable(struct iio_dev *indio_dev)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
-
- cancel_delayed_work_sync(&st->work);
- clear_bit(INV_AMI306_SCAN_MAGN_X, ring->scan_mask);
- clear_bit(INV_AMI306_SCAN_MAGN_Y, ring->scan_mask);
- clear_bit(INV_AMI306_SCAN_MAGN_Z, ring->scan_mask);
-
- return 0;
-}
-
-static const struct iio_buffer_setup_ops inv_ami306_ring_setup_ops = {
- .preenable = &iio_sw_buffer_preenable,
- .postenable = &inv_ami306_postenable,
- .predisable = &inv_ami306_predisable,
-};
-
-int inv_ami306_configure_ring(struct iio_dev *indio_dev)
-{
- int ret = 0;
- struct iio_buffer *ring;
-
- ring = iio_kfifo_allocate(indio_dev);
- if (!ring) {
- ret = -ENOMEM;
- return ret;
- }
- indio_dev->buffer = ring;
- /* setup ring buffer */
- ring->scan_timestamp = true;
- indio_dev->setup_ops = &inv_ami306_ring_setup_ops;
-
- indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
- return 0;
-}
-/**
- * @}
- */
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_ami306_trigger.c b/drivers/iio/magnetometer/inv_compass/inv_ami306_trigger.c
deleted file mode 100755
index f7fe59ef5df..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_ami306_trigger.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-*/
-
-/**
- * @addtogroup DRIVERS
- * @brief Hardware drivers.
- *
- * @{
- * @file inv_ami306_trigger.c
- * @brief Invensense implementation for AMI306
- * @details This driver currently works for the AMI306
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "iio.h"
-#include "sysfs.h"
-#include "trigger.h"
-#include "inv_ami306_iio.h"
-
-static const struct iio_trigger_ops inv_ami306_trigger_ops = {
- .owner = THIS_MODULE,
-};
-
-int inv_ami306_probe_trigger(struct iio_dev *indio_dev)
-{
- int ret;
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
-
- st->trig = iio_allocate_trigger("%s-dev%d",
- indio_dev->name,
- indio_dev->id);
- if (st->trig == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- /* select default trigger */
- st->trig->dev.parent = &st->i2c->dev;
- st->trig->private_data = indio_dev;
- st->trig->ops = &inv_ami306_trigger_ops;
- ret = iio_trigger_register(st->trig);
-
- /* select default trigger */
- indio_dev->trig = st->trig;
- if (ret)
- goto error_free_trig;
-
- return 0;
-
-error_free_trig:
- iio_free_trigger(st->trig);
-error_ret:
- return ret;
-}
-
-void inv_ami306_remove_trigger(struct iio_dev *indio_dev)
-{
- struct inv_ami306_state_s *st = iio_priv(indio_dev);
-
- iio_trigger_unregister(st->trig);
- iio_free_trigger(st->trig);
-}
-/**
- * @}
- */
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_yas53x_core.c b/drivers/iio/magnetometer/inv_compass/inv_yas53x_core.c
deleted file mode 100755
index 6af420bb5cf..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_yas53x_core.c
+++ /dev/null
@@ -1,969 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-*/
-
-/**
- * @addtogroup DRIVERS
- * @brief Hardware drivers.
- *
- * @{
- * @file inv_yas53x_core.c
- * @brief Invensense implementation for yas530/yas532/yas533.
- * @details This driver currently works for yas530/yas532/yas533.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "inv_yas53x_iio.h"
-#include "sysfs.h"
-#include "inv_test/inv_counters.h"
-
-/* -------------------------------------------------------------------------- */
-static int Cx, Cy1, Cy2;
-static int /*a1, */ a2, a3, a4, a5, a6, a7, a8, a9;
-static int k;
-
-static u8 dx, dy1, dy2;
-static u8 d2, d3, d4, d5, d6, d7, d8, d9, d0;
-static u8 dck, ver;
-
-/**
- * inv_serial_read() - Read one or more bytes from the device registers.
- * @st: Device driver instance.
- * @reg: First device register to be read from.
- * @length: Number of bytes to read.
- * @data: Data read from device.
- * NOTE: The slave register will not increment when reading from the FIFO.
- */
-int inv_serial_read(struct inv_compass_state *st, u8 reg, u16 length, u8 *data)
-{
- int result;
- INV_I2C_INC_COMPASSWRITE(3);
- INV_I2C_INC_COMPASSREAD(length);
- result = i2c_smbus_read_i2c_block_data(st->client, reg, length, data);
- if (result != length) {
- if (result < 0)
- return result;
- else
- return -EINVAL;
- } else {
- return 0;
- }
-}
-
-/**
- * inv_serial_single_write() - Write a byte to a device register.
- * @st: Device driver instance.
- * @reg: Device register to be written to.
- * @data: Byte to write to device.
- */
-int inv_serial_single_write(struct inv_compass_state *st, u8 reg, u8 data)
-{
- u8 d[1];
- d[0] = data;
- INV_I2C_INC_COMPASSWRITE(3);
-
- return i2c_smbus_write_i2c_block_data(st->client, reg, 1, d);
-}
-
-static int set_hardware_offset(struct inv_compass_state *st,
- char offset_x, char offset_y1, char offset_y2)
-{
- char data;
- int result = 0;
-
- data = offset_x & 0x3f;
- result = inv_serial_single_write(st, YAS530_REGADDR_OFFSET_X, data);
- if (result)
- return result;
-
- data = offset_y1 & 0x3f;
- result = inv_serial_single_write(st, YAS530_REGADDR_OFFSET_Y1, data);
- if (result)
- return result;
-
- data = offset_y2 & 0x3f;
- result = inv_serial_single_write(st, YAS530_REGADDR_OFFSET_Y2, data);
- return result;
-}
-
-static int set_measure_command(struct inv_compass_state *st)
-{
- int result = 0;
- result = inv_serial_single_write(st,
- YAS530_REGADDR_MEASURE_COMMAND, 0x01);
- return result;
-}
-
-static int measure_normal(struct inv_compass_state *st,
- int *busy, unsigned short *t,
- unsigned short *x, unsigned short *y1,
- unsigned short *y2)
-{
- int result;
- ktime_t sleeptime;
- result = set_measure_command(st);
- sleeptime = ktime_set(0, 2 * NSEC_PER_MSEC);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_hrtimeout(&sleeptime, HRTIMER_MODE_REL);
-
- result = st->read_data(st, busy, t, x, y1, y2);
-
- return result;
-}
-
-static int measure_int(struct inv_compass_state *st,
- int *busy, unsigned short *t,
- unsigned short *x, unsigned short *y1,
- unsigned short *y2)
-{
- int result;
- if (st->first_read_after_reset) {
- st->first_read_after_reset = 0;
- result = 1;
- } else {
- result = st->read_data(st, busy, t, x, y1, y2);
- }
- result |= set_measure_command(st);
-
- return result;
-}
-
-static int yas530_read_data(struct inv_compass_state *st,
- int *busy, u16 *t, u16 *x, u16 *y1, u16 *y2)
-{
- u8 data[8];
- u16 b, to, xo, y1o, y2o;
- int result;
-
- result = inv_serial_read(st,
- YAS530_REGADDR_MEASURE_DATA, 8, data);
- if (result)
- return result;
-
- b = (data[0] >> 7) & 0x01;
- to = (s16)(((data[0] << 2) & 0x1fc) | ((data[1] >> 6) & 0x03));
- xo = (s16)(((data[2] << 5) & 0xfe0) | ((data[3] >> 3) & 0x1f));
- y1o = (s16)(((data[4] << 5) & 0xfe0) | ((data[5] >> 3) & 0x1f));
- y2o = (s16)(((data[6] << 5) & 0xfe0) | ((data[7] >> 3) & 0x1f));
-
- *busy = b;
- *t = to;
- *x = xo;
- *y1 = y1o;
- *y2 = y2o;
-
- return 0;
-}
-
-static int yas532_533_read_data(struct inv_compass_state *st,
- int *busy, u16 *t, u16 *x, u16 *y1, u16 *y2)
-{
- u8 data[8];
- u16 b, to, xo, y1o, y2o;
- int result;
-
- result = inv_serial_read(st,
- YAS530_REGADDR_MEASURE_DATA, 8, data);
- if (result)
- return result;
-
- b = (data[0] >> 7) & 0x01;
- to = (s16)((((s32)data[0] << 3) & 0x3f8) | ((data[1] >> 5) & 0x07));
- xo = (s16)((((s32)data[2] << 6) & 0x1fc0) | ((data[3] >> 2) & 0x3f));
- y1o = (s16)((((s32)data[4] << 6) & 0x1fc0) | ((data[5] >> 2) & 0x3f));
- y2o = (s16)((((s32)data[6] << 6) & 0x1fc0) | ((data[7] >> 2) & 0x3f));
-
- *busy = b;
- *t = to;
- *x = xo;
- *y1 = y1o;
- *y2 = y2o;
-
- return 0;
-}
-
-static int check_offset(struct inv_compass_state *st,
- char offset_x, char offset_y1, char offset_y2,
- int *flag_x, int *flag_y1, int *flag_y2)
-{
- int result;
- int busy;
- short t, x, y1, y2;
-
- result = set_hardware_offset(st, offset_x, offset_y1, offset_y2);
- if (result)
- return result;
- result = measure_normal(st, &busy, &t, &x, &y1, &y2);
- if (result)
- return result;
- *flag_x = 0;
- *flag_y1 = 0;
- *flag_y2 = 0;
-
- if (x > st->center)
- *flag_x = 1;
- if (y1 > st->center)
- *flag_y1 = 1;
- if (y2 > st->center)
- *flag_y2 = 1;
- if (x < st->center)
- *flag_x = -1;
- if (y1 < st->center)
- *flag_y1 = -1;
- if (y2 < st->center)
- *flag_y2 = -1;
-
- return result;
-}
-
-static int measure_and_set_offset(struct inv_compass_state *st,
- char *offset)
-{
- int i;
- int result = 0;
- char offset_x = 0, offset_y1 = 0, offset_y2 = 0;
- int flag_x = 0, flag_y1 = 0, flag_y2 = 0;
- static const int correct[5] = {16, 8, 4, 2, 1};
-
- for (i = 0; i < 5; i++) {
- result = check_offset(st,
- offset_x, offset_y1, offset_y2,
- &flag_x, &flag_y1, &flag_y2);
- if (result)
- return result;
- if (flag_x)
- offset_x += flag_x * correct[i];
- if (flag_y1)
- offset_y1 += flag_y1 * correct[i];
- if (flag_y2)
- offset_y2 += flag_y2 * correct[i];
- }
-
- result = set_hardware_offset(st, offset_x, offset_y1, offset_y2);
- if (result)
- return result;
- offset[0] = offset_x;
- offset[1] = offset_y1;
- offset[2] = offset_y2;
-
- return result;
-}
-
-static void coordinate_conversion(short x, short y1, short y2, short t,
- int *xo, int *yo, int *zo)
-{
- int sx, sy1, sy2, sy, sz;
- int hx, hy, hz;
-
- sx = x - (Cx * t) / 100;
- sy1 = y1 - (Cy1 * t) / 100;
- sy2 = y2 - (Cy2 * t) / 100;
-
- sy = sy1 - sy2;
- sz = -sy1 - sy2;
-
- hx = k * ((100 * sx + a2 * sy + a3 * sz) / 10);
- hy = k * ((a4 * sx + a5 * sy + a6 * sz) / 10);
- hz = k * ((a7 * sx + a8 * sy + a9 * sz) / 10);
-
- *xo = hx;
- *yo = hy;
- *zo = hz;
-}
-
-static int get_cal_data_yas532_533(struct inv_compass_state *st)
-{
- u8 data[YAS_YAS532_533_CAL_DATA_SIZE];
- int result;
-
- result = inv_serial_read(st, YAS530_REGADDR_CAL,
- YAS_YAS532_533_CAL_DATA_SIZE, data);
- if (result)
- return result;
- /* CAL data Second Read */
- result = inv_serial_read(st, YAS530_REGADDR_CAL,
- YAS_YAS532_533_CAL_DATA_SIZE, data);
- if (result)
- return result;
-
- dx = data[0];
- dy1 = data[1];
- dy2 = data[2];
- d2 = (data[3] >> 2) & 0x03f;
- d3 = (u8)(((data[3] << 2) & 0x0c) | ((data[4] >> 6) & 0x03));
- d4 = (u8)(data[4] & 0x3f);
- d5 = (data[5] >> 2) & 0x3f;
- d6 = (u8)(((data[5] << 4) & 0x30) | ((data[6] >> 4) & 0x0f));
- d7 = (u8)(((data[6] << 3) & 0x78) | ((data[7] >> 5) & 0x07));
- d8 = (u8)(((data[7] << 1) & 0x3e) | ((data[8] >> 7) & 0x01));
- d9 = (u8)(((data[8] << 1) & 0xfe) | ((data[9] >> 7) & 0x01));
- d0 = (u8)((data[9] >> 2) & 0x1f);
- dck = (u8)(((data[9] << 1) & 0x06) | ((data[10] >> 7) & 0x01));
- ver = (u8)((data[13]) & 0x01);
-
- Cx = dx * 10 - 1280;
- Cy1 = dy1 * 10 - 1280;
- Cy2 = dy2 * 10 - 1280;
- a2 = d2 - 32;
- a3 = d3 - 8;
- a4 = d4 - 32;
- a5 = d5 + 38;
- a6 = d6 - 32;
- a7 = d7 - 64;
- a8 = d8 - 32;
- a9 = d9;
- k = d0;
-
- return 0;
-}
-
-static int get_cal_data_yas530(struct inv_compass_state *st)
-{
- u8 data[YAS_YAS530_CAL_DATA_SIZE];
- int result;
- /* CAL data read */
- result = inv_serial_read(st, YAS530_REGADDR_CAL,
- YAS_YAS530_CAL_DATA_SIZE, data);
- if (result)
- return result;
- /* CAL data Second Read */
- result = inv_serial_read(st, YAS530_REGADDR_CAL,
- YAS_YAS530_CAL_DATA_SIZE, data);
- if (result)
- return result;
- /*Cal data */
- dx = data[0];
- dy1 = data[1];
- dy2 = data[2];
- d2 = (data[3] >> 2) & 0x03f;
- d3 = ((data[3] << 2) & 0x0c) | ((data[4] >> 6) & 0x03);
- d4 = data[4] & 0x3f;
- d5 = (data[5] >> 2) & 0x3f;
- d6 = ((data[5] << 4) & 0x30) | ((data[6] >> 4) & 0x0f);
- d7 = ((data[6] << 3) & 0x78) | ((data[7] >> 5) & 0x07);
- d8 = ((data[7] << 1) & 0x3e) | ((data[8] >> 7) & 0x01);
- d9 = ((data[8] << 1) & 0xfe) | ((data[9] >> 7) & 0x01);
- d0 = (data[9] >> 2) & 0x1f;
- dck = ((data[9] << 1) & 0x06) | ((data[10] >> 7) & 0x01);
- ver = (u8)((data[15]) & 0x03);
-
- /*Correction Data */
- Cx = (int)dx * 6 - 768;
- Cy1 = (int)dy1 * 6 - 768;
- Cy2 = (int)dy2 * 6 - 768;
- a2 = (int)d2 - 32;
- a3 = (int)d3 - 8;
- a4 = (int)d4 - 32;
- a5 = (int)d5 + 38;
- a6 = (int)d6 - 32;
- a7 = (int)d7 - 64;
- a8 = (int)d8 - 32;
- a9 = (int)d9;
- k = (int)d0 + 10;
-
- return 0;
-}
-
-
-static void thresh_filter_init(struct yas_thresh_filter *thresh_filter,
- int threshold)
-{
- thresh_filter->threshold = threshold;
- thresh_filter->last = 0;
-}
-
-static void
-adaptive_filter_init(struct yas_adaptive_filter *adap_filter, int len,
- int noise)
-{
- int i;
-
- adap_filter->num = 0;
- adap_filter->index = 0;
- adap_filter->filter_noise = noise;
- adap_filter->filter_len = len;
-
- for (i = 0; i < adap_filter->filter_len; ++i)
- adap_filter->sequence[i] = 0;
-}
-
-static void yas_init_adap_filter(struct inv_compass_state *st)
-{
- struct yas_filter *f;
- int i;
- int noise[] = {YAS_MAG_DEFAULT_FILTER_NOISE_X,
- YAS_MAG_DEFAULT_FILTER_NOISE_Y,
- YAS_MAG_DEFAULT_FILTER_NOISE_Z};
-
- f = &st->filter;
- f->filter_len = YAS_MAG_DEFAULT_FILTER_LEN;
- for (i = 0; i < 3; i++)
- f->filter_noise[i] = noise[i];
-
- for (i = 0; i < 3; i++) {
- adaptive_filter_init(&f->adap_filter[i], f->filter_len,
- f->filter_noise[i]);
- thresh_filter_init(&f->thresh_filter[i], f->filter_thresh);
- }
-}
-
-int yas53x_resume(struct inv_compass_state *st)
-{
- int result = 0;
-
- unsigned char dummyData = 0x00;
- unsigned char read_reg[1];
-
- /* =============================================== */
-
- /* Step 1 - Test register initialization */
- dummyData = 0x00;
- result = inv_serial_single_write(st,
- YAS530_REGADDR_TEST1, dummyData);
- if (result)
- return result;
- result =
- inv_serial_single_write(st,
- YAS530_REGADDR_TEST2, dummyData);
- if (result)
- return result;
- /* Device ID read */
- result = inv_serial_read(st,
- YAS530_REGADDR_DEVICE_ID, 1, read_reg);
-
- /*Step 2 Read the CAL register */
- st->get_cal_data(st);
-
- /*Obtain the [49:47] bits */
- dck &= 0x07;
-
- /*Step 3 : Storing the CONFIG with the CLK value */
- dummyData = 0x00 | (dck << 2);
- result = inv_serial_single_write(st,
- YAS530_REGADDR_CONFIG, dummyData);
- if (result)
- return result;
- /*Step 4 : Set Acquisition Interval Register */
- dummyData = 0x00;
- result = inv_serial_single_write(st,
- YAS530_REGADDR_MEASURE_INTERVAL,
- dummyData);
- if (result)
- return result;
-
- /*Step 5 : Reset Coil */
- dummyData = 0x00;
- result = inv_serial_single_write(st,
- YAS530_REGADDR_ACTUATE_INIT_COIL,
- dummyData);
- if (result)
- return result;
- /* Offset Measurement and Set */
- result = measure_and_set_offset(st, st->offset);
- if (result)
- return result;
- st->first_measure_after_reset = 1;
- st->first_read_after_reset = 1;
- st->reset_timer = 0;
-
- yas_init_adap_filter(st);
-
- return result;
-}
-
-static int inv_check_range(struct inv_compass_state *st, s16 x, s16 y1, s16 y2)
-{
- int result = 0;
-
- if (x == 0)
- result |= 0x01;
- if (x == st->overflow_bound)
- result |= 0x02;
- if (y1 == 0)
- result |= 0x04;
- if (y1 == st->overflow_bound)
- result |= 0x08;
- if (y2 == 0)
- result |= 0x10;
- if (y2 == st->overflow_bound)
- result |= 0x20;
-
- return result;
-}
-static int square(int data)
-{
- return data * data;
-}
-
-static int
-adaptive_filter_filter(struct yas_adaptive_filter *adap_filter, int in)
-{
- int avg, sum;
- int i;
-
- if (adap_filter->filter_len == 0)
- return in;
- if (adap_filter->num < adap_filter->filter_len) {
- adap_filter->sequence[adap_filter->index++] = in / 100;
- adap_filter->num++;
- return in;
- }
- if (adap_filter->filter_len <= adap_filter->index)
- adap_filter->index = 0;
- adap_filter->sequence[adap_filter->index++] = in / 100;
-
- avg = 0;
- for (i = 0; i < adap_filter->filter_len; i++)
- avg += adap_filter->sequence[i];
- avg /= adap_filter->filter_len;
-
- sum = 0;
- for (i = 0; i < adap_filter->filter_len; i++)
- sum += square(avg - adap_filter->sequence[i]);
- sum /= adap_filter->filter_len;
-
- if (sum <= adap_filter->filter_noise)
- return avg * 100;
-
- return ((in/100 - avg) * (sum - adap_filter->filter_noise) / sum + avg)
- * 100;
-}
-
-static int
-thresh_filter_filter(struct yas_thresh_filter *thresh_filter, int in)
-{
- if (in < thresh_filter->last - thresh_filter->threshold
- || thresh_filter->last
- + thresh_filter->threshold < in) {
- thresh_filter->last = in;
- return in;
- } else {
- return thresh_filter->last;
- }
-}
-
-static void
-filter_filter(struct yas_filter *d, int *orig, int *filtered)
-{
- int i;
-
- for (i = 0; i < 3; i++) {
- filtered[i] = adaptive_filter_filter(&d->adap_filter[i],
- orig[i]);
- filtered[i] = thresh_filter_filter(&d->thresh_filter[i],
- filtered[i]);
- }
-}
-
-int yas53x_read(struct inv_compass_state *st, short rawfixed[3],
- int *overunderflow)
-{
- int result = 0;
-
- int busy, i, ov;
- short t, x, y1, y2;
- s32 xyz[3], disturb[3];
-
- result = measure_int(st, &busy, &t, &x, &y1, &y2);
- if (result)
- return result;
- if (busy)
- return -1;
- coordinate_conversion(x, y1, y2, t, &xyz[0], &xyz[1], &xyz[2]);
- filter_filter(&st->filter, xyz, xyz);
- for (i = 0; i < 3; i++)
- rawfixed[i] = (short)(xyz[i] / 100);
-
- if (st->first_measure_after_reset) {
- for (i = 0; i < 3; i++)
- st->base_compass_data[i] = rawfixed[i];
- st->first_measure_after_reset = 0;
- }
- ov = 0;
- for (i = 0; i < 3; i++) {
- disturb[i] = abs(st->base_compass_data[i] - rawfixed[i]);
- if (disturb[i] > YAS_MAG_DISTURBURNCE_THRESHOLD)
- ov = 1;
- }
- if (ov)
- st->reset_timer += st->delay;
- else
- st->reset_timer = 0;
-
- if (st->reset_timer > YAS_RESET_COIL_TIME_THRESHOLD)
- *overunderflow = (1<<8);
- else
- *overunderflow = 0;
- *overunderflow |= inv_check_range(st, x, y1, y2);
-
- return 0;
-}
-
-/**
- * yas53x_read_raw() - read raw method.
- */
-static int yas53x_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val,
- int *val2,
- long mask) {
- struct inv_compass_state *st = iio_priv(indio_dev);
-
- switch (mask) {
- case 0:
- if (!(iio_buffer_enabled(indio_dev)))
- return -EINVAL;
- if (chan->type == IIO_MAGN) {
- *val = st->compass_data[chan->channel2 - IIO_MOD_X];
- return IIO_VAL_INT;
- }
-
- return -EINVAL;
- case IIO_CHAN_INFO_SCALE:
- if (chan->type == IIO_MAGN) {
- *val = YAS530_SCALE;
- return IIO_VAL_INT;
- }
- return -EINVAL;
- default:
- return -EINVAL;
- }
-}
-
-/**
- * inv_compass_matrix_show() - show orientation matrix
- */
-static ssize_t inv_compass_matrix_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- signed char *m;
- struct inv_compass_state *st = iio_priv(indio_dev);
- m = st->plat_data.orientation;
- return sprintf(buf,
- "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
- m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
-}
-
-static ssize_t yas53x_rate_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- u32 data;
- int error;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_compass_state *st = iio_priv(indio_dev);
-
- error = kstrtoint(buf, 10, &data);
- if (error)
- return error;
- if (0 == data)
- return -EINVAL;
- /* transform rate to delay in ms */
- data = MSEC_PER_SEC / data;
-
- if (data > YAS530_MAX_DELAY)
- data = YAS530_MAX_DELAY;
- if (data < YAS530_MIN_DELAY)
- data = YAS530_MIN_DELAY;
- st->delay = data;
-
- return count;
-}
-
-static ssize_t yas53x_rate_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_compass_state *st = iio_priv(indio_dev);
- /* transform delay in ms to rate */
- return sprintf(buf, "%d\n", (int)MSEC_PER_SEC / st->delay);
-}
-
-static ssize_t yas53x_overunderflow_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- u32 data;
- int error;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_compass_state *st = iio_priv(indio_dev);
-
- error = kstrtoint(buf, 10, &data);
- if (error)
- return error;
- if (data)
- return -EINVAL;
- st->overunderflow = data;
-
- return count;
-}
-
-static ssize_t yas53x_overunderflow_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct inv_compass_state *st = iio_priv(indio_dev);
-
- return sprintf(buf, "%d\n", st->overunderflow);
-}
-
-void set_yas53x_enable(struct iio_dev *indio_dev, bool enable)
-{
- struct inv_compass_state *st = iio_priv(indio_dev);
-
- yas_init_adap_filter(st);
- st->first_measure_after_reset = 1;
- st->first_read_after_reset = 1;
- schedule_delayed_work(&st->work, msecs_to_jiffies(st->delay));
-}
-
-static void yas53x_work_func(struct work_struct *work)
-{
- struct inv_compass_state *st =
- container_of((struct delayed_work *)work,
- struct inv_compass_state, work);
- struct iio_dev *indio_dev = iio_priv_to_dev(st);
- u32 delay = msecs_to_jiffies(st->delay);
-
- mutex_lock(&indio_dev->mlock);
- if (!(iio_buffer_enabled(indio_dev)))
- goto error_ret;
-
- schedule_delayed_work(&st->work, delay);
- inv_read_yas53x_fifo(indio_dev);
- INV_I2C_INC_COMPASSIRQ();
-
-error_ret:
- mutex_unlock(&indio_dev->mlock);
-}
-
-static const struct iio_chan_spec compass_channels[] = {
- {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_X,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_YAS53X_SCAN_MAGN_X,
- .scan_type = IIO_ST('s', 16, 16, 0)
- }, {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_Y,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_YAS53X_SCAN_MAGN_Y,
- .scan_type = IIO_ST('s', 16, 16, 0)
- }, {
- .type = IIO_MAGN,
- .modified = 1,
- .channel2 = IIO_MOD_Z,
- .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,
- .scan_index = INV_YAS53X_SCAN_MAGN_Z,
- .scan_type = IIO_ST('s', 16, 16, 0)
- },
- IIO_CHAN_SOFT_TIMESTAMP(INV_YAS53X_SCAN_TIMESTAMP)
-};
-
-static DEVICE_ATTR(compass_matrix, S_IRUGO, inv_compass_matrix_show, NULL);
-static DEVICE_ATTR(sampling_frequency, S_IRUGO | S_IWUSR, yas53x_rate_show,
- yas53x_rate_store);
-static DEVICE_ATTR(overunderflow, S_IRUGO | S_IWUSR,
- yas53x_overunderflow_show, yas53x_overunderflow_store);
-
-static struct attribute *inv_yas53x_attributes[] = {
- &dev_attr_compass_matrix.attr,
- &dev_attr_sampling_frequency.attr,
- &dev_attr_overunderflow.attr,
- NULL,
-};
-static const struct attribute_group inv_attribute_group = {
- .name = "yas53x",
- .attrs = inv_yas53x_attributes
-};
-
-static const struct iio_info yas53x_info = {
- .driver_module = THIS_MODULE,
- .read_raw = &yas53x_read_raw,
- .attrs = &inv_attribute_group,
-};
-
-/*constant IIO attribute */
-/**
- * inv_yas53x_probe() - probe function.
- */
-static int inv_yas53x_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct inv_compass_state *st;
- struct iio_dev *indio_dev;
- int result;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- result = -ENODEV;
- goto out_no_free;
- }
- indio_dev = iio_allocate_device(sizeof(*st));
- if (indio_dev == NULL) {
- result = -ENOMEM;
- goto out_no_free;
- }
- st = iio_priv(indio_dev);
- st->client = client;
- st->plat_data =
- *(struct mpu_platform_data *)dev_get_platdata(&client->dev);
- st->delay = 10;
-
- i2c_set_clientdata(client, indio_dev);
-
- if (!strcmp(id->name, "yas530")) {
- st->read_data = yas530_read_data;
- st->get_cal_data = get_cal_data_yas530;
- st->overflow_bound = YAS_YAS530_DATA_OVERFLOW;
- st->center = YAS_YAS530_DATA_CENTER;
- st->filter.filter_thresh = YAS530_MAG_DEFAULT_FILTER_THRESH;
- } else {
- st->read_data = yas532_533_read_data;
- st->get_cal_data = get_cal_data_yas532_533;
- st->overflow_bound = YAS_YAS532_533_DATA_OVERFLOW;
- st->center = YAS_YAS532_533_DATA_CENTER;
- st->filter.filter_thresh = YAS532_MAG_DEFAULT_FILTER_THRESH;
- }
- st->upper_bound = st->center + (st->center >> 1);
- st->lower_bound = (st->center >> 1);
-
- result = yas53x_resume(st);
- if (result)
- goto out_free;
-
- indio_dev->dev.parent = &client->dev;
- indio_dev->name = id->name;
- indio_dev->channels = compass_channels;
- indio_dev->num_channels = ARRAY_SIZE(compass_channels);
- indio_dev->info = &yas53x_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->currentmode = INDIO_DIRECT_MODE;
-
- result = inv_yas53x_configure_ring(indio_dev);
- if (result)
- goto out_free;
- result = iio_buffer_register(indio_dev, indio_dev->channels,
- indio_dev->num_channels);
- if (result)
- goto out_unreg_ring;
- result = inv_yas53x_probe_trigger(indio_dev);
- if (result)
- goto out_remove_ring;
-
- result = iio_device_register(indio_dev);
- if (result)
- goto out_remove_trigger;
- INIT_DELAYED_WORK(&st->work, yas53x_work_func);
- pr_info("%s: Probe name %s\n", __func__, id->name);
-
- return 0;
-out_remove_trigger:
- if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
- inv_yas53x_remove_trigger(indio_dev);
-out_remove_ring:
- iio_buffer_unregister(indio_dev);
-out_unreg_ring:
- inv_yas53x_unconfigure_ring(indio_dev);
-out_free:
- iio_free_device(indio_dev);
-out_no_free:
- dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
- return -EIO;
-}
-
-/**
- * inv_yas53x_remove() - remove function.
- */
-static int inv_yas53x_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct inv_compass_state *st = iio_priv(indio_dev);
- cancel_delayed_work_sync(&st->work);
- iio_device_unregister(indio_dev);
- inv_yas53x_remove_trigger(indio_dev);
- iio_buffer_unregister(indio_dev);
- inv_yas53x_unconfigure_ring(indio_dev);
- iio_free_device(indio_dev);
-
- dev_info(&client->adapter->dev, "inv_yas53x_iio module removed.\n");
- return 0;
-}
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-/* device id table is used to identify what device can be
- * supported by this driver
- */
-static const struct i2c_device_id inv_yas53x_id[] = {
- {"yas530", 0},
- {"yas532", 0},
- {"yas533", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, inv_yas53x_id);
-
-static struct i2c_driver inv_yas53x_driver = {
- .class = I2C_CLASS_HWMON,
- .probe = inv_yas53x_probe,
- .remove = inv_yas53x_remove,
- .id_table = inv_yas53x_id,
- .driver = {
- .owner = THIS_MODULE,
- .name = "inv_yas53x_iio",
- },
- .address_list = normal_i2c,
-};
-
-static int __init inv_yas53x_init(void)
-{
- int result = i2c_add_driver(&inv_yas53x_driver);
- if (result) {
- pr_err("%s failed\n", __func__);
- return result;
- }
- return 0;
-}
-
-static void __exit inv_yas53x_exit(void)
-{
- i2c_del_driver(&inv_yas53x_driver);
-}
-
-module_init(inv_yas53x_init);
-module_exit(inv_yas53x_exit);
-
-MODULE_AUTHOR("Invensense Corporation");
-MODULE_DESCRIPTION("Invensense device driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("inv_yas53x_iio");
-/**
- * @}
- */
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_yas53x_iio.h b/drivers/iio/magnetometer/inv_compass/inv_yas53x_iio.h
deleted file mode 100755
index 92bf0af7ec7..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_yas53x_iio.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-*/
-
-/**
- * @addtogroup DRIVERS
- * @brief Hardware drivers.
- *
- * @{
- * @file inv_yas53x_iio.h
- * @brief Struct definitions for the Invensense implementation
- * of yas53x driver.
- */
-
-#ifndef _INV_GYRO_H_
-#define _INV_GYRO_H_
-
-#include <linux/i2c.h>
-#include <linux/kfifo.h>
-#include <linux/miscdevice.h>
-#include <linux/input.h>
-#include <linux/spinlock.h>
-#include <linux/mpu.h>
-
-#include "iio.h"
-#include "buffer.h"
-#include "trigger.h"
-
-#define YAS_MAG_MAX_FILTER_LEN 30
-struct yas_adaptive_filter {
- int num;
- int index;
- int filter_len;
- int filter_noise;
- int sequence[YAS_MAG_MAX_FILTER_LEN];
-};
-
-struct yas_thresh_filter {
- int threshold;
- int last;
-};
-
-struct yas_filter {
- int filter_len;
- int filter_thresh;
- int filter_noise[3];
- struct yas_adaptive_filter adap_filter[3];
- struct yas_thresh_filter thresh_filter[3];
-};
-
-/**
- * struct inv_compass_state - Driver state variables.
- * @plat_data: mpu platform data from board file.
- * @client: i2c client handle.
- * @chan_info: channel information.
- * @trig: IIO trigger.
- * @work: work structure.
- * @delay: delay to schedule the next work.
- * @overflow_bound: bound to determine overflow.
- * @center: center of the measurement.
- * @compass_data[3]: compass data store.
- * @offset[3]: yas530 specific data.
- * @base_compass_data[3]: first measure data after reset.
- * @first_measure_after_reset:1: flag for first measurement after reset.
- * @first_read_after_reset:1: flag for first read after reset.
- * @reset_timer: timer to accumulate overflow conditions.
- * @overunderflow:1: overflow and underflow flag.
- * @filter: filter data structure.
- * @read_data: function pointer of reading data from device.
- * @get_cal_data: function pointer of reading cal data.
- */
-struct inv_compass_state {
- struct mpu_platform_data plat_data;
- struct i2c_client *client;
- struct iio_trigger *trig;
- struct delayed_work work;
- s16 delay;
- s16 overflow_bound;
- s16 upper_bound;
- s16 lower_bound;
- s16 center;
- s16 compass_data[3];
- s8 offset[3];
- s16 base_compass_data[3];
- u8 first_measure_after_reset:1;
- u8 first_read_after_reset:1;
- u8 overunderflow:1;
- s32 reset_timer;
- struct yas_filter filter;
- int (*read_data)(struct inv_compass_state *st,
- int *, u16 *, u16 *, u16 *, u16 *);
- int (*get_cal_data)(struct inv_compass_state *);
-};
-
-/* scan element definition */
-enum inv_mpu_scan {
- INV_YAS53X_SCAN_MAGN_X,
- INV_YAS53X_SCAN_MAGN_Y,
- INV_YAS53X_SCAN_MAGN_Z,
- INV_YAS53X_SCAN_TIMESTAMP,
-};
-
-#define YAS530_REGADDR_DEVICE_ID 0x80
-#define YAS530_REGADDR_ACTUATE_INIT_COIL 0x81
-#define YAS530_REGADDR_MEASURE_COMMAND 0x82
-#define YAS530_REGADDR_CONFIG 0x83
-#define YAS530_REGADDR_MEASURE_INTERVAL 0x84
-#define YAS530_REGADDR_OFFSET_X 0x85
-#define YAS530_REGADDR_OFFSET_Y1 0x86
-#define YAS530_REGADDR_OFFSET_Y2 0x87
-#define YAS530_REGADDR_TEST1 0x88
-#define YAS530_REGADDR_TEST2 0x89
-#define YAS530_REGADDR_CAL 0x90
-#define YAS530_REGADDR_MEASURE_DATA 0xb0
-
-#define YAS530_MAX_DELAY 200
-#define YAS530_MIN_DELAY 5
-#define YAS530_SCALE 107374182L
-
-#define YAS_YAS530_VERSION_A 0 /* YAS530 (MS-3E Aver) */
-#define YAS_YAS530_VERSION_B 1 /* YAS530B (MS-3E Bver) */
-#define YAS_YAS530_VERSION_A_COEF 380
-#define YAS_YAS530_VERSION_B_COEF 550
-#define YAS_YAS530_DATA_CENTER 2048
-#define YAS_YAS530_DATA_OVERFLOW 4095
-#define YAS_YAS530_CAL_DATA_SIZE 16
-
-/*filter related defines */
-#define YAS_MAG_DEFAULT_FILTER_NOISE_X 144 /* sd: 1200 nT */
-#define YAS_MAG_DEFAULT_FILTER_NOISE_Y 144 /* sd: 1200 nT */
-#define YAS_MAG_DEFAULT_FILTER_NOISE_Z 144 /* sd: 1200 nT */
-#define YAS_MAG_DEFAULT_FILTER_LEN 20
-
-#define YAS530_MAG_DEFAULT_FILTER_THRESH 100
-#define YAS532_MAG_DEFAULT_FILTER_THRESH 300
-
-#define YAS_YAS532_533_VERSION_AB 0 /* YAS532_533AB (MS-3R/3F ABver) */
-#define YAS_YAS532_533_VERSION_AC 1 /* YAS532_533AC (MS-3R/3F ACver) */
-#define YAS_YAS532_533_VERSION_AB_COEF 1800
-#define YAS_YAS532_533_VERSION_AC_COEF 900
-#define YAS_YAS532_533_DATA_CENTER 4096
-#define YAS_YAS532_533_DATA_OVERFLOW 8190
-#define YAS_YAS532_533_CAL_DATA_SIZE 14
-
-#define YAS_MAG_DISTURBURNCE_THRESHOLD 1600
-#define YAS_RESET_COIL_TIME_THRESHOLD 3000
-
-#define INV_ERROR_COMPASS_DATA_OVERFLOW (-1)
-#define INV_ERROR_COMPASS_DATA_NOT_READY (-2)
-
-int inv_yas53x_configure_ring(struct iio_dev *indio_dev);
-void inv_yas53x_unconfigure_ring(struct iio_dev *indio_dev);
-int inv_yas53x_probe_trigger(struct iio_dev *indio_dev);
-void inv_yas53x_remove_trigger(struct iio_dev *indio_dev);
-void set_yas53x_enable(struct iio_dev *indio_dev, bool enable);
-void inv_read_yas53x_fifo(struct iio_dev *indio_dev);
-int yas53x_read(struct inv_compass_state *st, short rawfixed[3],
- s32 *overunderflow);
-int yas53x_resume(struct inv_compass_state *st);
-
-#endif /* #ifndef _INV_GYRO_H_ */
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_yas53x_ring.c b/drivers/iio/magnetometer/inv_compass/inv_yas53x_ring.c
deleted file mode 100755
index efcf49c6839..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_yas53x_ring.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-*/
-
-/**
- * @addtogroup DRIVERS
- * @brief Hardware drivers.
- *
- * @{
- * @file inv_yas53x_ring.c
- * @brief Invensense implementation for yas530/yas532/yas533.
- * @details This driver currently works for the yas530/yas532/yas533.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-
-#include "iio.h"
-#include "kfifo_buf.h"
-#include "trigger_consumer.h"
-#include "sysfs.h"
-
-#include "inv_yas53x_iio.h"
-
-static s64 get_time_ns(void)
-{
- struct timespec ts;
- ktime_get_ts(&ts);
-
- return timespec_to_ns(&ts);
-}
-
-static int put_scan_to_buf(struct iio_dev *indio_dev, unsigned char *d,
- short *s, int scan_index)
-{
- struct iio_buffer *ring = indio_dev->buffer;
- int st;
- int i, d_ind;
-
- d_ind = 0;
- for (i = 0; i < 3; i++) {
- st = iio_scan_mask_query(indio_dev, ring, scan_index + i);
- if (st) {
- memcpy(&d[d_ind], &s[i], sizeof(s[i]));
- d_ind += sizeof(s[i]);
- }
- }
-
- return d_ind;
-}
-
-/**
- * inv_read_yas53x_fifo() - Transfer data from FIFO to ring buffer.
- */
-void inv_read_yas53x_fifo(struct iio_dev *indio_dev)
-{
- struct inv_compass_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- int d_ind;
- s32 overunderflow;
- s8 *tmp;
- s64 tmp_buf[2];
-
- if (!yas53x_read(st, st->compass_data, &overunderflow)) {
- tmp = (u8 *)tmp_buf;
- d_ind = put_scan_to_buf(indio_dev, tmp, st->compass_data,
- INV_YAS53X_SCAN_MAGN_X);
- if (ring->scan_timestamp)
- tmp_buf[(d_ind + 7) / 8] = get_time_ns();
- ring->access->store_to(indio_dev->buffer, tmp, 0);
-
- if (overunderflow) {
- yas53x_resume(st);
- if (!st->overunderflow)
- st->overunderflow = 1;
- }
- }
-}
-
-void inv_yas53x_unconfigure_ring(struct iio_dev *indio_dev)
-{
- iio_kfifo_free(indio_dev->buffer);
-};
-
-static int inv_yas53x_postenable(struct iio_dev *indio_dev)
-{
- struct inv_compass_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
-
- /* when all the outputs are disabled, even though buffer/enable is on,
- do nothing */
- if (!(iio_scan_mask_query(indio_dev, ring, INV_YAS53X_SCAN_MAGN_X) ||
- iio_scan_mask_query(indio_dev, ring, INV_YAS53X_SCAN_MAGN_Y) ||
- iio_scan_mask_query(indio_dev, ring, INV_YAS53X_SCAN_MAGN_Z)))
- return 0;
-
- set_yas53x_enable(indio_dev, true);
- schedule_delayed_work(&st->work,
- msecs_to_jiffies(st->delay));
-
- return 0;
-}
-
-static int inv_yas53x_predisable(struct iio_dev *indio_dev)
-{
- struct inv_compass_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
-
- cancel_delayed_work_sync(&st->work);
- clear_bit(INV_YAS53X_SCAN_MAGN_X, ring->scan_mask);
- clear_bit(INV_YAS53X_SCAN_MAGN_Y, ring->scan_mask);
- clear_bit(INV_YAS53X_SCAN_MAGN_Z, ring->scan_mask);
-
- return 0;
-}
-
-static const struct iio_buffer_setup_ops inv_yas53x_ring_setup_ops = {
- .preenable = &iio_sw_buffer_preenable,
- .postenable = &inv_yas53x_postenable,
- .predisable = &inv_yas53x_predisable,
-};
-
-int inv_yas53x_configure_ring(struct iio_dev *indio_dev)
-{
- int ret = 0;
- struct iio_buffer *ring;
-
- ring = iio_kfifo_allocate(indio_dev);
- if (!ring) {
- ret = -ENOMEM;
- return ret;
- }
- indio_dev->buffer = ring;
- /* setup ring buffer */
- ring->scan_timestamp = true;
- indio_dev->setup_ops = &inv_yas53x_ring_setup_ops;
-
- indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
- return 0;
-}
-/**
- * @}
- */
-
diff --git a/drivers/iio/magnetometer/inv_compass/inv_yas53x_trigger.c b/drivers/iio/magnetometer/inv_compass/inv_yas53x_trigger.c
deleted file mode 100755
index a20ce2baa7e..00000000000
--- a/drivers/iio/magnetometer/inv_compass/inv_yas53x_trigger.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-* Copyright (C) 2012 Invensense, Inc.
-*
-* This software is licensed under the terms of the GNU General Public
-* License version 2, as published by the Free Software Foundation, and
-* may be copied, distributed, and modified under those terms.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-*/
-
-/**
- * @addtogroup DRIVERS
- * @brief Hardware drivers.
- *
- * @{
- * @file inv_yas53x_trigger.c
- * @brief Invensense implementation for yas530/yas532/yas533
- * @details This driver currently works for the yas530/yas532/yas533
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/sysfs.h>
-#include <linux/jiffies.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-
-#include "iio.h"
-#include "sysfs.h"
-#include "trigger.h"
-
-#include "inv_yas53x_iio.h"
-
-static const struct iio_trigger_ops inv_yas53x_trigger_ops = {
- .owner = THIS_MODULE,
-};
-
-int inv_yas53x_probe_trigger(struct iio_dev *indio_dev)
-{
- int ret;
- struct inv_compass_state *st = iio_priv(indio_dev);
-
- st->trig = iio_allocate_trigger("%s-dev%d",
- indio_dev->name,
- indio_dev->id);
- if (st->trig == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- /* select default trigger */
- st->trig->dev.parent = &st->client->dev;
- st->trig->private_data = indio_dev;
- st->trig->ops = &inv_yas53x_trigger_ops;
- ret = iio_trigger_register(st->trig);
-
- /* select default trigger */
- indio_dev->trig = st->trig;
- if (ret)
- goto error_free_trig;
-
- return 0;
-
-error_free_trig:
- iio_free_trigger(st->trig);
-error_ret:
- return ret;
-}
-
-void inv_yas53x_remove_trigger(struct iio_dev *indio_dev)
-{
- struct inv_compass_state *st = iio_priv(indio_dev);
-
- iio_trigger_unregister(st->trig);
- iio_free_trigger(st->trig);
-}
-/**
- * @}
- */
-
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 3009a8909cc..9b19ae172c3 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1109,7 +1109,14 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
+static void serial_omap_wake_peer(struct uart_port *port)
+{
+ struct uart_omap_port *up = to_uart_omap_port(port);
+ struct omap_uart_port_info *pdata = up->dev->platform_data;
+ if (pdata->wake_peer)
+ pdata->wake_peer(port);
+}
static void serial_omap_release_port(struct uart_port *port)
{
dev_dbg(port->dev, "serial_omap_release_port+\n");
@@ -1341,6 +1348,7 @@ static struct uart_ops serial_omap_pops = {
.shutdown = serial_omap_shutdown,
.set_termios = serial_omap_set_termios,
.pm = serial_omap_pm,
+ .wake_peer = serial_omap_wake_peer,
.type = serial_omap_type,
.release_port = serial_omap_release_port,
.request_port = serial_omap_request_port,
@@ -1860,6 +1868,39 @@ static void __exit serial_omap_exit(void)
uart_unregister_driver(&serial_omap_reg);
}
+/* Used by ext client device connected to uart to control uart */
+int omap_serial_ext_uart_enable(u8 port_id)
+{
+ struct uart_omap_port *up;
+ int err = 0;
+
+ if (port_id > OMAP_MAX_HSUART_PORTS) {
+ pr_err("Invalid Port_id %d passed to %s\n", port_id, __func__);
+ err = -ENODEV;
+ } else {
+ up = ui[port_id];
+ pm_runtime_get_sync(up->dev);
+ }
+ return err;
+}
+
+int omap_serial_ext_uart_disable(u8 port_id)
+{
+ struct uart_omap_port *up;
+ int err = 0;
+
+ if (port_id > OMAP_MAX_HSUART_PORTS) {
+ pr_err("Invalid Port_id %d passed to %s\n", port_id, __func__);
+ err = -ENODEV;
+ } else {
+ up = ui[port_id];
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+ }
+ return err;
+}
+
+
module_init(serial_omap_init);
module_exit(serial_omap_exit);
diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h
index a0aff63cf74..75fdea40e92 100644
--- a/include/linux/iio/types.h
+++ b/include/linux/iio/types.h
@@ -34,6 +34,10 @@ enum iio_chan_type {
IIO_PASSIVE,
IIO_GESTURE,
IIO_FUSION,
+ IIO_SIGN_MOTION,
+ IIO_STEP_COUNTER,
+ IIO_TILT,
+ IIO_STEP_DETECTOR,
};
enum iio_modifier {
diff --git a/include/linux/platform_data/serial-omap.h b/include/linux/platform_data/serial-omap.h
index afba9011b52..9990f7cd03c 100644
--- a/include/linux/platform_data/serial-omap.h
+++ b/include/linux/platform_data/serial-omap.h
@@ -48,10 +48,14 @@ struct omap_uart_port_info {
int (*get_context_loss_count)(struct device *);
void (*enable_wakeup)(struct device *, bool);
+ void (*wake_peer)(struct uart_port *);
};
extern void omap_uart_remove_wakeup(struct device *dev);
extern void omap_uart_enable_wakeup(struct device *dev, bool enable);
extern int omap_pm_get_dev_context_loss_count(struct device *dev);
+extern int omap_serial_ext_uart_enable(u8 port_id);
+extern int omap_serial_ext_uart_disable(u8 port_id);
+
#endif /* __OMAP_SERIAL_H__ */