staging: iio: new invensence mpu6050/6500 driver

Change-Id: I0f804afa1f5ad0815fe0b8f3663423db1b1c0e43
Signed-off-by: Zhangbin Tong <zebulun.tong@rock-chips.com>
Signed-off-by: Zorro Liu <lyx@rock-chips.com>
This commit is contained in:
Zhangbin Tong
2016-05-18 10:18:04 +08:00
committed by Gerrit Code Review
parent 0739622b08
commit a3c1d3323d
19 changed files with 9419 additions and 305 deletions

View File

@@ -11,6 +11,7 @@ source "drivers/staging/iio/cdc/Kconfig"
source "drivers/staging/iio/frequency/Kconfig"
source "drivers/staging/iio/gyro/Kconfig"
source "drivers/staging/iio/impedance-analyzer/Kconfig"
source "drivers/staging/iio/imu/inv_mpu/Kconfig"
source "drivers/staging/iio/light/Kconfig"
source "drivers/staging/iio/magnetometer/Kconfig"
source "drivers/staging/iio/meter/Kconfig"

View File

@@ -16,6 +16,7 @@ obj-y += cdc/
obj-y += frequency/
obj-y += gyro/
obj-y += impedance-analyzer/
obj-y += imu/inv_mpu/
obj-y += light/
obj-y += magnetometer/
obj-y += meter/

View File

@@ -0,0 +1,31 @@
#
# 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 INV_TESTING
bool "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

View File

@@ -0,0 +1,49 @@
#
# 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
ifeq ($(CONFIG_INV_TESTING), y)
inv-mpu-iio-objs += inv_counters.o
endif
ifeq ($(VERSION),4)
ifeq ($(PATCHLEVEL),4)
CFLAGS_inv_mpu_core.o += -Idrivers/iio -DINV_KERNEL_3_10
CFLAGS_inv_mpu_i2c.o += -Idrivers/iio -DINV_KERNEL_3_10
CFLAGS_inv_mpu_ring.o += -Idrivers/iio -DINV_KERNEL_3_10
CFLAGS_inv_mpu_trigger.o += -Idrivers/iio -DINV_KERNEL_3_10
CFLAGS_inv_mpu_common.o += -Idrivers/iio -DINV_KERNEL_3_10
CFLAGS_inv_mpu_load_image.o += -Idrivers/iio -DINV_KERNEL_3_10
CFLAGS_inv_mpu_misc.o += -Idrivers/iio -DINV_KERNEL_3_10
CFLAGS_inv_mpu3050_iio.o += -Idrivers/iio -DINV_KERNEL_3_10
CFLAGS_dmpDefaultMPU6050.o += -Idrivers/iio -DINV_KERNEL_3_10
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
endif
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 ($(VERSION),4)
ifeq ($(PATCHLEVEL),4)
CFLAGS_inv_slave_bma250.o += -Idrivers/iio
else
CFLAGS_inv_slave_bma250.o += -Idrivers/staging/iio
endif
endif
endif

View File

@@ -0,0 +1,603 @@
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-9150
> MPU-9250
> MPU-3050 + BMA250 on the secondary I2C interface
- Board File Modifications for Invensense Devices
> MPU-3050
> ITG-3500
> MPU-6050
> 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
- 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
- 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-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,
.secondary_orientation = { -1, 0, 0,
0, -1, 0,
0, 0, 1 },
};
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-3050
--------
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_duration
--set motion duration. in ms. This means filtered out all the motino interrupts
during this period.
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.
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.

View File

@@ -0,0 +1,350 @@
/*
* 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_LP_QUAT (2500)
#define END_ORIENT_TEMP (2063)
#define CFG_27 (2530)
#define CFG_23 (2533)
#define CFG_PED_ENABLE (2620)
#define CFG_FIFO_ON_EVENT (2475)
#define CFG_PED_INT (2873)
#define END_PREDICTION_UPDATE (1958)
#define X_GRT_Y_TMP (1555)
#define CFG_DR_INT (1029)
#define CFG_AUTH (1035)
#define UPDATE_PROP_ROT (2032)
#define END_COMPARE_Y_X_TMP2 (1652)
#define SKIP_X_GRT_Y_TMP (1556)
#define SKIP_END_COMPARE (1632)
#define FCFG_3 (1087)
#define FCFG_2 (1066)
#define FCFG_1 (1062)
#define END_COMPARE_Y_X_TMP3 (1631)
#define FCFG_7 (1073)
#define FCFG_6 (1105)
#define FLAT_STATE_END (1910)
#define SWING_END_4 (1813)
#define SWING_END_2 (1762)
#define SWING_END_3 (1784)
#define SWING_END_1 (1747)
#define CFG_8 (2506)
#define CFG_15 (2515)
#define CFG_16 (2534)
#define CFG_EXT_GYRO_BIAS (1184)
#define END_COMPARE_Y_X_TMP (1604)
#define DO_NOT_UPDATE_PROP_ROT (2036)
#define CFG_7 (1403)
#define FLAT_STATE_END_TEMP (1880)
#define END_COMPARE_Y_X (1681)
#define SMD_TP2 (1366)
#define SKIP_SWING_END_1 (1748)
#define SKIP_SWING_END_3 (1785)
#define SKIP_SWING_END_2 (1763)
#define SMD_TP1 (1343)
#define TILTG75_START (1869)
#define CFG_6 (2541)
#define TILTL75_END (1866)
#define END_ORIENT (2081)
#define TILTL75_START (1840)
#define CFG_MOTION_BIAS (1405)
#define X_GRT_Y (1605)
#define TEMPLABEL (2105)
#define CFG_DISPLAY_ORIENT_INT (2050)
#define CFG_GYRO_RAW_DATA (2510)
#define X_GRT_Y_TMP2 (1576)
#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 (35 * 16 + 4)
#define CPASS_BIAS_Y (35 * 16 + 8)
#define CPASS_BIAS_Z (35 * 16 + 12)
#define CPASS_MTX_00 (36 * 16)
#define CPASS_MTX_01 (36 * 16 + 4)
#define CPASS_MTX_02 (36 * 16 + 8)
#define CPASS_MTX_10 (36 * 16 + 12)
#define CPASS_MTX_11 (37 * 16)
#define CPASS_MTX_12 (37 * 16 + 4)
#define CPASS_MTX_20 (37 * 16 + 8)
#define CPASS_MTX_21 (37 * 16 + 12)
#define CPASS_MTX_22 (43 * 16 + 12)
#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 (20 * 16)
#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_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_HP_A (768 + 0x78)
#define D_PEDSTD_HP_B (768 + 0x7C)
#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_INT_THRSH (768 + 0x68)
#define D_PEDSTD_CLIP (768 + 0x6C)
#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_TIMECTR (964)
#define D_PEDSTD_DECI (768 + 0xA0)
#define D_HOST_NO_MOT (976)
#define D_ACCEL_BIAS (660)
#define D_ORIENT_GAP (76)
#define D_TILT0_H (48)
#define D_TILT0_L (50)
#define D_TILT1_H (52)
#define D_TILT1_L (54)
#define D_TILT2_H (56)
#define D_TILT2_L (58)
#define D_TILT3_H (60)
#define D_TILT3_L (62)
/* Batch mode */
#define D_BM_BATCH_CNTR (27 * 16 + 4)
#define D_BM_BATCH_THLD (27 * 16 + 8)
#define D_BM_ENABLE (28 * 16 + 6)
#define D_BM_NUMWORD_TOFILL (28 * 16 + 4)
static const struct tKeyLabel dmpTConfig[] = {
{KEY_CFG_27, CFG_27},
{KEY_CFG_23, CFG_23},
{KEY_CFG_PED_ENABLE, CFG_PED_ENABLE},
{KEY_CFG_FIFO_ON_EVENT, CFG_FIFO_ON_EVENT},
{KEY_CFG_DR_INT, CFG_DR_INT},
{KEY_CFG_AUTH, CFG_AUTH},
{KEY_FCFG_1, FCFG_1},
{KEY_FCFG_3, FCFG_3},
{KEY_FCFG_2, FCFG_2},
{KEY_CFG_DISPLAY_ORIENT_INT, CFG_DISPLAY_ORIENT_INT},
{KEY_FCFG_7, FCFG_7},
{KEY_FCFG_6, FCFG_6},
{KEY_CFG_8, CFG_8},
{KEY_CFG_15, CFG_15},
{KEY_CFG_16, CFG_16},
{KEY_CFG_EXT_GYRO_BIAS, CFG_EXT_GYRO_BIAS},
{KEY_CFG_6, CFG_6},
{KEY_CFG_LP_QUAT, CFG_LP_QUAT},
{KEY_CFG_7, CFG_7},
{KEY_CFG_MOTION_BIAS, CFG_MOTION_BIAS},
{KEY_CFG_DISPLAY_ORIENT_INT, CFG_DISPLAY_ORIENT_INT},
{KEY_CFG_GYRO_RAW_DATA, CFG_GYRO_RAW_DATA},
{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_178, D_1_178},
{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_FLICK_MSG, FLICK_MSG},
{KEY_FLICK_COUNTER, FLICK_COUNTER},
{KEY_FLICK_LOWER, FLICK_LOWER},
{KEY_FLICK_UPPER, FLICK_UPPER},
{KEY_D_PEDSTD_BP_B, D_PEDSTD_BP_B},
{KEY_D_PEDSTD_HP_A, D_PEDSTD_HP_A},
{KEY_D_PEDSTD_HP_B, D_PEDSTD_HP_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_INT_THRSH, D_PEDSTD_INT_THRSH},
{KEY_D_PEDSTD_CLIP, D_PEDSTD_CLIP},
{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_TIMECTR, D_PEDSTD_TIMECTR},
{KEY_D_PEDSTD_DECI, D_PEDSTD_DECI},
{KEY_D_HOST_NO_MOT, D_HOST_NO_MOT},
{KEY_D_ACCEL_BIAS, D_ACCEL_BIAS},
{KEY_D_ORIENT_GAP, D_ORIENT_GAP},
{KEY_D_TILT0_H, D_TILT0_H},
{KEY_D_TILT0_L, D_TILT0_L},
{KEY_D_TILT1_H, D_TILT1_H},
{KEY_D_TILT1_L, D_TILT1_L},
{KEY_D_TILT2_H, D_TILT2_H},
{KEY_D_TILT2_L, D_TILT2_L},
{KEY_D_TILT3_H, D_TILT3_H},
{KEY_D_TILT3_L, D_TILT3_L},
{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}
};
#define NUM_LOCAL_KEYS (ARRAY_SIZE(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);
dump_stack();
}
return keys[key].addr;
}

View File

@@ -0,0 +1,569 @@
/*
* 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 dmpKey.h
* @brief dmp Key definition
* @details This file is part of invensense mpu driver code
*
*/
#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)
/* Gesture Keys */
#define KEY_DMP_TAPW_MIN (KEY_CPASS_MTX_22 + 1)
#define KEY_DMP_TAP_THR_X (KEY_DMP_TAPW_MIN + 1)
#define KEY_DMP_TAP_THR_Y (KEY_DMP_TAP_THR_X + 1)
#define KEY_DMP_TAP_THR_Z (KEY_DMP_TAP_THR_Y + 1)
#define KEY_DMP_SH_TH_Y (KEY_DMP_TAP_THR_Z + 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_X_GRT_Y_TMP (KEY_D_ACSZ + 1)
#define KEY_SKIP_X_GRT_Y_TMP (KEY_X_GRT_Y_TMP + 1)
#define KEY_SKIP_END_COMPARE (KEY_SKIP_X_GRT_Y_TMP + 1)
#define KEY_END_COMPARE_Y_X_TMP2 (KEY_SKIP_END_COMPARE + 1)
#define KEY_CFG_DISPLAY_ORIENT_INT (KEY_END_COMPARE_Y_X_TMP2 + 1)
#define KEY_NO_ORIENT_INTERRUPT (KEY_CFG_DISPLAY_ORIENT_INT + 1)
#define KEY_END_COMPARE_Y_X_TMP (KEY_NO_ORIENT_INTERRUPT + 1)
#define KEY_END_ORIENT_1 (KEY_END_COMPARE_Y_X_TMP + 1)
#define KEY_END_COMPARE_Y_X (KEY_END_ORIENT_1 + 1)
#define KEY_END_ORIENT (KEY_END_COMPARE_Y_X + 1)
#define KEY_X_GRT_Y (KEY_END_ORIENT + 1)
#define KEY_NOT_TIME_MINUS_1 (KEY_X_GRT_Y + 1)
#define KEY_END_COMPARE_Y_X_TMP3 (KEY_NOT_TIME_MINUS_1 + 1)
#define KEY_X_GRT_Y_TMP2 (KEY_END_COMPARE_Y_X_TMP3 + 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_WALKTIME (KEY_D_PEDSTD_STEPCTR + 1)
#define KEY_D_PEDSTD_DECI (KEY_D_PEDSTD_WALKTIME + 1)
#define KEY_CFG_PED_INT (KEY_D_PEDSTD_DECI + 1)
#define KEY_CFG_PED_ENABLE (KEY_CFG_PED_INT + 1)
/*Host Based No Motion*/
#define KEY_D_HOST_NO_MOT (KEY_CFG_PED_ENABLE + 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)
/* Stream keys */
#define KEY_STREAM_P_GYRO_Z (KEY_D_TILT3_L + 1)
#define KEY_STREAM_P_GYRO_Y (KEY_STREAM_P_GYRO_Z + 1)
#define KEY_STREAM_P_GYRO_X (KEY_STREAM_P_GYRO_Y + 1)
#define KEY_STREAM_P_TEMP (KEY_STREAM_P_GYRO_X + 1)
#define KEY_STREAM_P_AUX_Y (KEY_STREAM_P_TEMP + 1)
#define KEY_STREAM_P_AUX_X (KEY_STREAM_P_AUX_Y + 1)
#define KEY_STREAM_P_AUX_Z (KEY_STREAM_P_AUX_X + 1)
#define KEY_STREAM_P_ACCEL_Y (KEY_STREAM_P_AUX_Z + 1)
#define KEY_STREAM_P_ACCEL_X (KEY_STREAM_P_ACCEL_Y + 1)
#define KEY_STREAM_P_FOOTER (KEY_STREAM_P_ACCEL_X + 1)
#define KEY_STREAM_P_ACCEL_Z (KEY_STREAM_P_FOOTER + 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_PQUAT (KEY_CFG_OUT_6QUAT + 1)
#define KEY_CFG_FIFO_INT (KEY_CFG_OUT_PQUAT + 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_HW_ID (KEY_SO_DATA + 1)
#define NUM_KEYS (KEY_P_HW_ID + 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

View File

@@ -0,0 +1,283 @@
/*
* 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 dmpmap.h
* @brief dmp map definition
* @details This file is part of invensense mpu driver code
*
*/
#ifndef DMPMAP_H
#define DMPMAP_H
#ifdef __cplusplus
extern "C"
{
#endif
#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_0H2 68
#define DMP_0L2 70
#define DMP_BERR2H 72
#define DMP_BERR2L 74
#define DMP_BERR2NH 76
#define DMP_SMCINC 78
#define DMP_ANGVBXH 80
#define DMP_ANGVBXL 82
#define DMP_ANGVBYH 84
#define DMP_ANGVBYL 86
#define DMP_ANGVBZH 88
#define DMP_ANGVBZL 90
#define DMP_BERR1H 92
#define DMP_BERR1L 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_TAP_THZ 476
#define DMP_TAPW_MIN 478
#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
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,154 @@
/*
* @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");

View File

@@ -0,0 +1,72 @@
/*
* @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_ */

View File

@@ -0,0 +1,287 @@
/*
* 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_mpu3050_iio.c
* @brief A sysfs device driver for Invensense devices
* @details This file is part of invensense mpu driver code
*/
#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_iio_s *st)
{
return 0;
}
int set_3050_bypass(struct inv_mpu_iio_s *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 | BIT_3050_AUX_IF_RST));
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_gyro = REG_3050_RAW_GYRO;
reg->raw_accl = 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_iio_s *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_accl_engine(struct inv_mpu_iio_s *st, bool en)
{
int result;
if (NULL == st->mpu_slave)
return -EPERM;
if (en)
result = st->mpu_slave->resume(st);
else
result = st->mpu_slave->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_iio_s *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;
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->chip_config.new_fifo_rate = INIT_FIFO_RATE;
st->irq_dur_ns = INIT_DUR_TIME;
if ((SECONDARY_SLAVE_TYPE_ACCEL == st->plat_data.sec_slave_type) &&
st->mpu_slave) {
result = st->mpu_slave->setup(st);
if (result)
return result;
result = st->mpu_slave->set_fs(st, INV_FS_02G);
if (result)
return result;
result = st->mpu_slave->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_iio_s *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->mpu_slave) {
result = st->mpu_slave->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->mpu_slave) {
result = st->mpu_slave->resume(st);
if (result)
return result;
}
}
st->chip_config.is_asleep = !power_on;
return 0;
}
/**
* @}
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,910 @@
/*
* 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_mpu_iio.h
* @brief Struct definitions for the Invensense mpu driver.
*/
#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>
#ifdef INV_KERNEL_3_10
#include <linux/mpu.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#else
#include <linux/mpu.h>
#include "iio.h"
#include "buffer.h"
#endif
#include "dmpKey.h"
/**
* 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.
* @accl_config: accel config register
* @fifo_count_h: Upper byte of FIFO count.
* @fifo_r_w: FIFO register.
* @raw_gyro Address of first gyro register.
* @raw_accl 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 accl_config;
u8 fifo_count_h;
u8 fifo_r_w;
u8 raw_gyro;
u8 raw_accl;
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_MPU6515,
INV_NUM_PARTS
};
/**
* struct test_setup_t - set up parameters for self test.
* @gyro_sens: sensitity for gyro.
* @sample_rate: sample rate, i.e, fifo rate.
* @lpf: low pass filter.
* @fsr: full scale range.
* @accl_fs: accel full scale range.
* @accl_sens: accel sensitivity
*/
struct test_setup_t {
int gyro_sens;
int sample_rate;
int lpf;
int fsr;
int accl_fs;
u32 accl_sens[3];
};
/**
* 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;
};
/**
* struct inv_chip_config_s - Cached chip configuration data.
* @fsr: Full scale range.
* @lpf: Digital low pass filter frequency.
* @accl_fs: accel full scale range.
* @self_test_run_once flag for self test run ever.
* @has_footer: MPU3050 specific work around.
* @has_compass: has compass or not.
* @enable: master enable to enable output
* @accl_enable: enable accel functionality
* @accl_fifo_enable: enable accel data output
* @gyro_enable: enable gyro functionality
* @gyro_fifo_enable: enable gyro data output
* @compass_enable: enable compass
* @compass_fifo_enable: enable compass data output
* @is_asleep: 1 if chip is powered down.
* @dmp_on: dmp is on/off.
* @dmp_int_on: dmp interrupt on/off.
* @dmp_event_int_on: dmp event interrupt on/off.
* @firmware_loaded: flag indicate firmware loaded or not.
* @lpa_mod: low power mode.
* @tap_on: tap on/off.
* @quaternion_on: send quaternion data on/off.
* @display_orient_on: display orientation on/off.
* @normal_compass_measure: discard first compass data after reset.
* @smd_enable: disable/enable SMD function.
* @lpa_freq: low power frequency
* @prog_start_addr: firmware program start address.
* @fifo_rate: current FIFO update rate.
* @new_fifo_rate: set FIFO update rate
* @dmp_output_rate: current dmp output rate.
*/
struct inv_chip_config_s {
u32 fsr:2;
u32 lpf:3;
u32 accl_fs:2;
u32 self_test_run_once:1;
u32 has_footer:1;
u32 has_compass:1;
u32 enable:1;
u32 accl_enable:1;
u32 accl_fifo_enable:1;
u32 gyro_enable:1;
u32 gyro_fifo_enable:1;
u32 compass_enable:1;
u32 compass_fifo_enable:1;
u32 is_asleep:1;
u32 dmp_on:1;
u32 dmp_int_on:1;
u32 dmp_event_int_on:1;
u32 firmware_loaded:1;
u32 lpa_mode:1;
u32 tap_on:1;
u32 quaternion_on:1;
u32 display_orient_on:1;
u32 normal_compass_measure:1;
u32 smd_enable:1;
u16 lpa_freq;
u16 prog_start_addr;
u16 fifo_rate;
u16 new_fifo_rate;
u16 dmp_output_rate;
};
/**
* 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.
* @accl_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 accl_sens_trim;
};
enum inv_channel_num {
INV_CHANNEL_NUM_GYRO = 4,
INV_CHANNEL_NUM_GYRO_ACCL = 7,
INV_CHANNEL_NUM_GYRO_ACCL_QUANTERNION = 11,
INV_CHANNEL_NUM_GYRO_ACCL_QUANTERNION_MAGN = 14,
};
/**
* struct inv_tap_s structure to store tap data.
* @min_count: minimum taps counted.
* @thresh: tap threshold.
* @time: tap time.
*/
struct inv_tap_s {
u16 min_count;
u16 thresh;
u16 time;
};
/**
* 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_s {
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_s significant motion detection structure.
* threshold: accel threshold for motion detection.
* delay: delay time to confirm 2nd motion.
* delay2: delay window parameter.
*/
struct inv_smd_s {
u32 threshold;
u32 delay;
u32 delay2;
};
struct inv_mpu_slave;
/**
* struct inv_mpu_iio_s - 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.
* @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.
* @client: i2c client handle.
* @plat_data: platform data.
* @mpu_slave: mpu slave handle.
* (*set_power_state)(struct inv_mpu_iio_s *, int on): function ptr
* (*switch_gyro_engine)(struct inv_mpu_iio_s *, int on): function ptr
* (*switch_accl_engine)(struct inv_mpu_iio_s *, int on): function ptr
* (*compass_en)(struct inv_mpu_iio_s *, struct iio_buffer *, bool);
* (*quaternion_en)(struct inv_mpu_iio_s *, struct iio_buffer *, bool)
* (*gyro_en)(struct inv_mpu_iio_s *, struct iio_buffer *, bool): func ptr.
* (*accl_en)(struct inv_mpu_iio_s *, struct iio_buffer *, bool): func ptr.
* (*init_config)(struct iio_dev *indio_dev): function ptr
* void (*setup_reg)(struct inv_reg_map_s *reg): function ptr
* @timestamps: kfifo queue to store time stamp.
* @compass_st_upper: compass self test upper limit.
* @compass_st_lower: compass self test lower limit.
* @irq: irq number store.
* @accel_bias: accel bias store.
* @gyro_bias: gyro bias store.
* @raw_gyro: raw gyro data.
* @raw_accel: raw accel data.
* @raw_compass: raw compass.
* @raw_quaternion raw quaternion data.
* @int input_accel_bias[3]: accel bias from sysfs.
* @compass_scale: compass scale.
* @i2c_addr: i2c address.
* @compass_divider: slow down compass rate.
* @compass_dmp_divider: slow down compass rate for dmp.
* @compass_counter: slow down compass rate.
* @sample_divider: sample divider for dmp.
* @fifo_divider: fifo divider for dmp.
* @display_orient_data:display orient data.
* @tap_data: tap data.
* @num_channels: number of channels for current chip.
* @sl_handle: Handle to I2C port.
* @irq_dur_ns: duration between each irq.
* @last_isr_time: last isr time.
* @mpu6500_last_motion_time: MPU6500 last real motion interrupt time.
* @name: name for distiguish MPU6050 and MPU6500 in MPU6XXX.
*/
struct inv_mpu_iio_s {
#define TIMESTAMP_FIFO_SIZE 16
struct inv_chip_config_s chip_config;
struct inv_chip_info_s chip_info;
struct iio_trigger *trig;
struct inv_tap_s tap;
struct inv_smd_s smd;
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 i2c_client *client;
struct mpu_platform_data plat_data;
struct inv_mpu_slave *mpu_slave;
struct accel_mot_int_s mot_int;
int (*set_power_state)(struct inv_mpu_iio_s *, bool on);
int (*switch_gyro_engine)(struct inv_mpu_iio_s *, bool on);
int (*switch_accl_engine)(struct inv_mpu_iio_s *, bool on);
int (*compass_en)(struct inv_mpu_iio_s *,
struct iio_buffer *ring, bool on);
int (*quaternion_en)(struct inv_mpu_iio_s *,
struct iio_buffer *ring, bool on);
int (*gyro_en)(struct inv_mpu_iio_s *,
struct iio_buffer *ring, bool on);
int (*accl_en)(struct inv_mpu_iio_s *,
struct iio_buffer *ring, 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);
const short *compass_st_upper;
const short *compass_st_lower;
short irq;
int accel_bias[3];
int gyro_bias[3];
short raw_gyro[3];
short raw_accel[3];
short raw_compass[3];
int raw_quaternion[4];
int input_accel_bias[3];
u8 compass_scale;
u8 i2c_addr;
u8 compass_divider;
u8 compass_counter;
u8 compass_dmp_divider;
u8 sample_divider;
u8 fifo_divider;
u8 display_orient_data;
u8 tap_data;
enum inv_channel_num num_channels;
void *sl_handle;
u32 irq_dur_ns;
u64 last_isr_time;
u64 mpu6500_last_motion_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.
* @suspend: suspend operation.
* @resume: resume operation.
* @setup: setup chip. initialization.
* @combine_data: combine raw data into meaningful data.
* @get_mode: get current chip mode.
* @set_lpf set low pass filter.
* @set_fs set full scale
*/
struct inv_mpu_slave {
int (*suspend)(struct inv_mpu_iio_s *);
int (*resume)(struct inv_mpu_iio_s *);
int (*setup)(struct inv_mpu_iio_s *);
int (*combine_data)(u8 *in, short *out);
int (*get_mode)(void);
int (*set_lpf)(struct inv_mpu_iio_s *, int rate);
int (*set_fs)(struct inv_mpu_iio_s *, int fs);
};
/* AKM definitions */
#define REG_AKM_ID 0x00
#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
#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_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 AKM8963_SCALE_SHIFT 4
#define NUM_BYTES_COMPASS_SLAVE 8
/*register and associated bit definition*/
#define REG_3050_FIFO_EN 0x12
#define BITS_3050_ACCL_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_AUX_IF_RST 0x08
#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_L_TC 0x7
#define REG_PRODUCT_ID 0xC
#define REG_ST_GCT_X 0xD
#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 BIT_I2C_READ 0x80
#define REG_I2C_SLV0_REG 0x26
#define REG_I2C_SLV0_CTRL 0x27
#define BIT_SLV_EN 0x80
#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_SLV4_CTRL 0x34
#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 SMD_INT_ON 0x04
#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_RAW_GYRO 0x43
#define REG_EXT_SENS_DATA_00 0x49
#define REG_ACCEL_INTEL_STATUS 0x61
#define REG_I2C_SLV1_DO 0x64
#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 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_ACCL_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_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
#define BYTES_FOR_DMP 16
#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 500
#define POWER_UP_TIME 100
#define SENSOR_UP_TIME 30
#define REG_UP_TIME 5
#define INV_MPU_SAMPLE_RATE_CHANGE_STABLE 50
#define MPU_MEM_BANK_SIZE 256
#define MPU6XXX_MAX_MOTION_THRESH (255*4)
#define MPU6XXX_MOTION_THRESH_SHIFT 5
#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_ACCL_FS_PARAM 3
#define MAX_LPA_FREQ_PARAM 3
#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 50
#define INIT_ST_THRESHOLD 14
#define ST_THRESHOLD_MULTIPLIER 10
#define ST_MAX_SAMPLES 500
#define ST_MAX_THRESHOLD 100
/*---- MPU6500 ----*/
#define MPU6500_ID 0x70 /* unique WHOAMI */
#define MPU6500_PRODUCT_REVISION 1
#define MPU6500_MEM_REV_ADDR 0x16
#define INV_MPU_REV_MASK 0xF
#define MPU6500_REV 2
/*---- MPU6515 ----*/
#define MPU6515_ID 0x74 /* unique WHOAMI */
/*---- MPU9250 ----*/
#define MPU9250_ID 0x71 /* unique WHOAMI */
#define THREE_AXIS 3
#define GYRO_CONFIG_FSR_SHIFT 3
#define ACCL_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
/* init parameters */
#define INIT_FIFO_RATE 50
#define INIT_DMP_OUTPUT_RATE 25
#define INIT_DUR_TIME ((1000 / INIT_FIFO_RATE) * 1000 * 1000)
#define INIT_TAP_THRESHOLD 100
#define INIT_TAP_TIME 100
#define INIT_TAP_MIN_COUNT 2
#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 DEFAULT_ACCL_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
/*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_ACCL_MASK 0x70
#define INV_GYRO_MASK 0xE
/* 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_ACCL_X,
INV_MPU_SCAN_ACCL_Y,
INV_MPU_SCAN_ACCL_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_SMD_ENABLE,
ATTR_DMP_SMD_THLD,
ATTR_DMP_SMD_DELAY_THLD,
ATTR_DMP_SMD_DELAY_THLD2,
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_OUTPUT_RATE,
ATTR_DMP_QUATERNION_ON,
/* *****above this line, it is all DMP related features */
/* *****below this line, it is all non-DMP related features */
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_ACCL_ENABLE,
ATTR_COMPASS_ENABLE,
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 but needs power on/off */
ATTR_GYRO_MATRIX,
ATTR_ACCL_MATRIX,
ATTR_COMPASS_MATRIX,
ATTR_SECONDARY_NAME,
#ifdef CONFIG_INV_TESTING
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
#endif
};
enum inv_accl_fs_e {
INV_FS_02G = 0,
INV_FS_04G,
INV_FS_08G,
INV_FS_16G,
NUM_ACCL_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);
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_iio_s *st);
int inv_get_silicon_rev_mpu6500(struct inv_mpu_iio_s *st);
int set_3050_bypass(struct inv_mpu_iio_s *st, bool enable);
int inv_register_mpu3050_slave(struct inv_mpu_iio_s *st);
void inv_setup_reg_mpu3050(struct inv_reg_map_s *reg);
int inv_switch_3050_gyro_engine(struct inv_mpu_iio_s *st, bool en);
int inv_switch_3050_accl_engine(struct inv_mpu_iio_s *st, bool en);
int set_power_mpu3050(struct inv_mpu_iio_s *st, bool power_on);
int inv_set_interrupt_on_gesture_event(struct inv_mpu_iio_s *st, bool on);
int inv_send_quaternion(struct inv_mpu_iio_s *st, bool on);
int inv_set_display_orient_interrupt_dmp(struct inv_mpu_iio_s *st, bool on);
int inv_set_fifo_rate(struct inv_mpu_iio_s *st, u16 fifo_rate);
u16 inv_dmp_get_address(u16 key);
int inv_q30_mult(int a, int b);
int inv_set_tap_threshold_dmp(struct inv_mpu_iio_s *st,
u32 axis, u16 threshold);
int inv_set_min_taps_dmp(struct inv_mpu_iio_s *st, u16 min_taps);
int inv_set_tap_time_dmp(struct inv_mpu_iio_s *st, u16 time);
int inv_enable_tap_dmp(struct inv_mpu_iio_s *st, bool on);
int inv_i2c_read_base(struct inv_mpu_iio_s *st, u16 i2c_addr,
u8 reg, u16 length, u8 *data);
int inv_i2c_single_write_base(struct inv_mpu_iio_s *st,
u16 i2c_addr, u8 reg, u8 data);
int inv_do_test(struct inv_mpu_iio_s *st, int self_test_flag,
int *gyro_result, int *accl_result);
int inv_hw_self_test(struct inv_mpu_iio_s *st);
void inv_recover_setting(struct inv_mpu_iio_s *st);
int inv_power_up_self_test(struct inv_mpu_iio_s *st);
s64 get_time_ns(void);
int write_be32_key_to_mem(struct inv_mpu_iio_s *st,
u32 data, int key);
int inv_set_accel_bias_dmp(struct inv_mpu_iio_s *st);
int inv_send_sensor_data(struct inv_mpu_iio_s *st, u16 elements);
int inv_send_interrupt_word(struct inv_mpu_iio_s *st, bool on);
int mpu_memory_write(struct inv_mpu_iio_s *st, u8 mpu_addr, u16 mem_addr,
u32 len, u8 const *data);
int mpu_memory_read(struct inv_mpu_iio_s *st, u8 mpu_addr, u16 mem_addr,
u32 len, u8 *data);
int mpu_memory_write_unaligned(struct inv_mpu_iio_s *st, u16 key, int len,
u8 const *d);
/* 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)
#endif /* #ifndef _INV_MPU_IIO_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,120 @@
/*
* 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_mpu_trigger.c
* @brief A sysfs device driver for Invensense devices
* @details This file is part of inv mpu iio driver code
*/
#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>
#ifdef INV_KERNEL_3_10
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#else
#include "iio.h"
#include "sysfs.h"
#include "trigger.h"
#endif
#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)
{
/*
--yd struct iio_dev *indio_dev = trig->private_data;
--yd dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, 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_iio_s *st = iio_priv(indio_dev);
#ifdef 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;
#ifdef INV_KERNEL_3_10
iio_trigger_set_drvdata(st->trig, indio_dev);
#else
st->trig->private_data = indio_dev;
#endif
st->trig->ops = &inv_mpu_trigger_ops;
ret = iio_trigger_register(st->trig);
if (ret) {
#ifdef 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_iio_s *st = iio_priv(indio_dev);
iio_trigger_unregister(st->trig);
#ifdef INV_KERNEL_3_10
iio_trigger_free(st->trig);
#else
iio_free_trigger(st->trig);
#endif
}
/**
* @}
*/

View File

@@ -0,0 +1,330 @@
/*
* 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_slave_bma250.c
* @brief A sysfs device driver for Invensense devices
* @details This file is part of invensense mpu driver code
*
*/
#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_iio_s *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_iio_s *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_iio_s *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_iio_s *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_iio_s *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_iio_s *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_iio_s *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_iio_s *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_iio_s *st)
{
st->mpu_slave = &slave_bma250;
return 0;
}
/**
* @}
*/

View File

@@ -1,8 +1,15 @@
/*
$License:
Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
$
*/
* 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 __MPU_H_
#define __MPU_H_
@@ -10,133 +17,25 @@
#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/ioctl.h>
#elif defined LINUX
#include <sys/ioctl.h>
#include <linux/types.h>
#else
#include "mltypes.h"
#endif
/* Number of axes on each sensor */
#define GYRO_NUM_AXES (3)
#define ACCEL_NUM_AXES (3)
#define COMPASS_NUM_AXES (3)
enum secondary_slave_type {
SECONDARY_SLAVE_TYPE_NONE,
SECONDARY_SLAVE_TYPE_ACCEL,
SECONDARY_SLAVE_TYPE_COMPASS,
SECONDARY_SLAVE_TYPE_PRESSURE,
SECONDARY_SLAVE_TYPE_ALS,
struct mpu_read_write {
/* Memory address or register address depending on ioctl */
__u16 address;
__u16 length;
__u8 *data;
};
enum mpuirq_data_type {
MPUIRQ_DATA_TYPE_MPU_IRQ,
MPUIRQ_DATA_TYPE_SLAVE_IRQ,
MPUIRQ_DATA_TYPE_PM_EVENT,
MPUIRQ_DATA_TYPE_NUM_TYPES,
};
/* User space PM event notification */
#define MPU_PM_EVENT_SUSPEND_PREPARE (3)
#define MPU_PM_EVENT_POST_SUSPEND (4)
struct mpuirq_data {
__u32 interruptcount;
__u64 irqtime;
__u32 data_type;
__s32 data;
};
enum ext_slave_config_key {
MPU_SLAVE_CONFIG_ODR_SUSPEND,
MPU_SLAVE_CONFIG_ODR_RESUME,
MPU_SLAVE_CONFIG_FSR_SUSPEND,
MPU_SLAVE_CONFIG_FSR_RESUME,
MPU_SLAVE_CONFIG_MOT_THS,
MPU_SLAVE_CONFIG_NMOT_THS,
MPU_SLAVE_CONFIG_MOT_DUR,
MPU_SLAVE_CONFIG_NMOT_DUR,
MPU_SLAVE_CONFIG_IRQ_SUSPEND,
MPU_SLAVE_CONFIG_IRQ_RESUME,
MPU_SLAVE_WRITE_REGISTERS,
MPU_SLAVE_READ_REGISTERS,
MPU_SLAVE_CONFIG_INTERNAL_REFERENCE,
/* AMI 306 specific config keys */
MPU_SLAVE_PARAM,
MPU_SLAVE_WINDOW,
MPU_SLAVE_READWINPARAMS,
MPU_SLAVE_SEARCHOFFSET,
/* AKM specific config keys */
MPU_SLAVE_READ_SCALE,
/* MPU3050 and MPU6050 Keys */
MPU_SLAVE_INT_CONFIG,
MPU_SLAVE_EXT_SYNC,
MPU_SLAVE_FULL_SCALE,
MPU_SLAVE_LPF,
MPU_SLAVE_CLK_SRC,
MPU_SLAVE_DIVIDER,
MPU_SLAVE_DMP_ENABLE,
MPU_SLAVE_FIFO_ENABLE,
MPU_SLAVE_DMP_CFG1,
MPU_SLAVE_DMP_CFG2,
MPU_SLAVE_TC,
MPU_SLAVE_GYRO,
MPU_SLAVE_ADDR,
MPU_SLAVE_PRODUCT_REVISION,
MPU_SLAVE_SILICON_REVISION,
MPU_SLAVE_PRODUCT_ID,
MPU_SLAVE_GYRO_SENS_TRIM,
MPU_SLAVE_ACCEL_SENS_TRIM,
MPU_SLAVE_RAM,
/* -------------------------- */
MPU_SLAVE_CONFIG_NUM_CONFIG_KEYS
};
/* For the MPU_SLAVE_CONFIG_IRQ_SUSPEND and MPU_SLAVE_CONFIG_IRQ_RESUME */
enum ext_slave_config_irq_type {
MPU_SLAVE_IRQ_TYPE_NONE,
MPU_SLAVE_IRQ_TYPE_MOTION,
MPU_SLAVE_IRQ_TYPE_DATA_READY,
};
/* Structure for the following IOCTS's
* MPU_CONFIG_GYRO
* MPU_CONFIG_ACCEL
* MPU_CONFIG_COMPASS
* MPU_CONFIG_PRESSURE
* MPU_GET_CONFIG_GYRO
* MPU_GET_CONFIG_ACCEL
* MPU_GET_CONFIG_COMPASS
* MPU_GET_CONFIG_PRESSURE
*
* @key one of enum ext_slave_config_key
* @len length of data pointed to by data
* @apply zero if communication with the chip is not necessary, false otherwise
* This flag can be used to select cached data or to refresh cashed data
* cache data to be pushed later or push immediately. If true and the
* slave is on the secondary bus the MPU will first enger bypass mode
* before calling the slaves .config or .get_config funcion
* @data pointer to the data to confgure or get
*/
struct ext_slave_config {
__u8 key;
__u16 len;
__u8 apply;
void *data;
};
enum ext_slave_type {
EXT_SLAVE_TYPE_GYROSCOPE,
EXT_SLAVE_TYPE_ACCEL,
EXT_SLAVE_TYPE_COMPASS,
EXT_SLAVE_TYPE_PRESSURE,
/*EXT_SLAVE_TYPE_TEMPERATURE */
EXT_SLAVE_NUM_TYPES
SECONDARY_SLAVE_TYPE_TYPES
};
enum ext_slave_id {
ID_INVALID = 0,
GYRO_ID_MPU3050,
GYRO_ID_MPU6050A2,
GYRO_ID_MPU6050B1,
GYRO_ID_MPU6050B1_NO_ACCEL,
GYRO_ID_ITG3500,
ACCEL_ID_LIS331,
ACCEL_ID_LSM303DLX,
@@ -151,9 +50,9 @@ enum ext_slave_id {
ACCEL_ID_MMA845X,
ACCEL_ID_MPU6050,
COMPASS_ID_AK8963,
COMPASS_ID_AK8975,
COMPASS_ID_AK8972,
COMPASS_ID_AK8963,
COMPASS_ID_AMI30X,
COMPASS_ID_AMI306,
COMPASS_ID_YAS529,
@@ -162,138 +61,36 @@ enum ext_slave_id {
COMPASS_ID_LSM303DLH,
COMPASS_ID_LSM303DLM,
COMPASS_ID_MMC314X,
COMPASS_ID_MMC328X,
COMPASS_ID_HSCDTD002B,
COMPASS_ID_HSCDTD004A,
COMPASS_ID_MLX90399,
COMPASS_ID_AK09911,
COMPASS_ID_AK09912,
COMPASS_ID_ST480M,
PRESSURE_ID_BMA085,
};
enum ext_slave_endian {
EXT_SLAVE_BIG_ENDIAN,
EXT_SLAVE_LITTLE_ENDIAN,
EXT_SLAVE_FS8_BIG_ENDIAN,
EXT_SLAVE_FS16_BIG_ENDIAN,
};
enum ext_slave_bus {
EXT_SLAVE_BUS_INVALID = -1,
EXT_SLAVE_BUS_PRIMARY = 0,
EXT_SLAVE_BUS_SECONDARY = 1
};
/**
* struct ext_slave_platform_data - Platform data for mpu3050 and mpu6050
* slave devices
*
* @type: the type of slave device based on the enum ext_slave_type
* definitions.
* @irq: the irq number attached to the slave if any.
* @adapt_num: the I2C adapter number.
* @bus: the bus the slave is attached to: enum ext_slave_bus
* @address: the I2C slave address of the slave device.
* @orientation: the mounting matrix of the device relative to MPU.
* @irq_data: private data for the slave irq handler
* @private_data: additional data, user customizable. Not touched by the MPU
* driver.
*
* The orientation matricies are 3x3 rotation matricies
* that are applied to the data to rotate from the mounting orientation to the
* platform orientation. The values must be one of 0, 1, or -1 and each row and
* column should have exactly 1 non-zero value.
*/
struct ext_slave_platform_data {
__u8 type;
__u32 irq;
__u32 adapt_num;
__u32 bus;
__u8 address;
__s8 orientation[9];
void *irq_data;
void *private_data;
};
struct fix_pnt_range {
__s32 mantissa;
__s32 fraction;
};
static inline long range_fixedpoint_to_long_mg(struct fix_pnt_range rng)
{
return (long)(rng.mantissa * 1000 + rng.fraction / 10);
}
struct ext_slave_read_trigger {
__u8 reg;
__u8 value;
};
/**
* struct ext_slave_descr - Description of the slave device for programming.
*
* @suspend: function pointer to put the device in suspended state
* @resume: function pointer to put the device in running state
* @read: function that reads the device data
* @init: function used to preallocate memory used by the driver
* @exit: function used to free memory allocated for the driver
* @config: function used to configure the device
* @get_config:function used to get the device's configuration
*
* @name: text name of the device
* @type: device type. enum ext_slave_type
* @id: enum ext_slave_id
* @read_reg: starting register address to retrieve data.
* @read_len: length in bytes of the sensor data. Typically 6.
* @endian: byte order of the data. enum ext_slave_endian
* @range: full scale range of the slave ouput: struct fix_pnt_range
* @trigger: If reading data first requires writing a register this is the
* data to write.
*
* Defines the functions and information about the slave the mpu3050 and
* mpu6050 needs to use the slave device.
*/
struct ext_slave_descr {
int (*init) (void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata);
int (*exit) (void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata);
int (*suspend) (void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata);
int (*resume) (void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata);
int (*read) (void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata,
__u8 *data);
int (*config) (void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata,
struct ext_slave_config *config);
int (*get_config) (void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata,
struct ext_slave_config *config);
char *name;
__u8 type;
__u8 id;
__u8 read_reg;
__u8 read_len;
__u8 endian;
struct fix_pnt_range range;
struct ext_slave_read_trigger *trigger;
PRESSURE_ID_BMP085,
PRESSURE_ID_BMP280,
ALS_ID_APDS_9900,
ALS_ID_APDS_9930,
};
#define INV_PROD_KEY(ver, rev) (ver * 100 + rev)
/**
* struct mpu_platform_data - Platform data for the mpu driver
* @int_config: Bits [7:3] of the int config register.
* @level_shifter: 0: VLogic, 1: VDD
* @orientation: Orientation matrix of the gyroscope
* @sec_slave_type: secondary slave device type, can be compass, accel, etc
* @sec_slave_id: id of the secondary slave device
* @secondary_i2c_address: secondary device's i2c address
* @secondary_orientation: secondary device's orientation matrix
* @aux_slave_type: auxiliary slave. Another slave device type
* @aux_slave_id: auxiliary slave ID.
* @aux_i2c_addr: auxiliary device I2C address.
* @read_only_slave_type: read only slave type.
* @read_only_slave_id: read only slave device ID.
* @read_only_i2c_addr: read only slave device address.
*
* Contains platform specific information on how to configure the MPU3050 to
* work on this platform. The orientation matricies are 3x3 rotation matricies
@@ -302,63 +99,25 @@ struct ext_slave_descr {
* column should have exactly 1 non-zero value.
*/
struct mpu_platform_data {
__u32 int_config;
__u32 level_shifter;
__s8 orientation[GYRO_NUM_AXES * GYRO_NUM_AXES];
__u8 int_config;
__u8 level_shifter;
__s8 orientation[9];
enum secondary_slave_type sec_slave_type;
enum ext_slave_id sec_slave_id;
__u16 secondary_i2c_addr;
__s8 secondary_orientation[9];
enum secondary_slave_type aux_slave_type;
enum ext_slave_id aux_slave_id;
__u16 aux_i2c_addr;
enum secondary_slave_type read_only_slave_type;
enum ext_slave_id read_only_slave_id;
__u16 read_only_i2c_addr;
#ifdef CONFIG_DTS_INV_MPU_IIO
int (*power_on)(struct mpu_platform_data *);
int (*power_off)(struct mpu_platform_data *);
struct regulator *vdd_ana;
struct regulator *vdd_i2c;
#endif
};
#if defined __KERNEL__ || defined LINUX
#define MPU_IOCTL (0x81) /* Magic number for MPU Iocts */
/* IOCTL commands for /dev/mpu */
/*--------------------------------------------------------------------------
* Deprecated, debugging only
*/
#define MPU_SET_MPU_PLATFORM_DATA \
_IOWR(MPU_IOCTL, 0x01, struct mpu_platform_data)
#define MPU_SET_EXT_SLAVE_PLATFORM_DATA \
_IOWR(MPU_IOCTL, 0x01, struct ext_slave_platform_data)
/*--------------------------------------------------------------------------*/
#define MPU_GET_EXT_SLAVE_PLATFORM_DATA \
_IOWR(MPU_IOCTL, 0x02, struct ext_slave_platform_data)
#define MPU_GET_MPU_PLATFORM_DATA \
_IOWR(MPU_IOCTL, 0x02, struct mpu_platform_data)
#define MPU_GET_EXT_SLAVE_DESCR \
_IOWR(MPU_IOCTL, 0x02, struct ext_slave_descr)
#define MPU_READ _IOWR(MPU_IOCTL, 0x10, struct mpu_read_write)
#define MPU_WRITE _IOW(MPU_IOCTL, 0x10, struct mpu_read_write)
#define MPU_READ_MEM _IOWR(MPU_IOCTL, 0x11, struct mpu_read_write)
#define MPU_WRITE_MEM _IOW(MPU_IOCTL, 0x11, struct mpu_read_write)
#define MPU_READ_FIFO _IOWR(MPU_IOCTL, 0x12, struct mpu_read_write)
#define MPU_WRITE_FIFO _IOW(MPU_IOCTL, 0x12, struct mpu_read_write)
#define MPU_READ_COMPASS _IOR(MPU_IOCTL, 0x12, __u8)
#define MPU_READ_ACCEL _IOR(MPU_IOCTL, 0x13, __u8)
#define MPU_READ_PRESSURE _IOR(MPU_IOCTL, 0x14, __u8)
#define MPU_CONFIG_GYRO _IOW(MPU_IOCTL, 0x20, struct ext_slave_config)
#define MPU_CONFIG_ACCEL _IOW(MPU_IOCTL, 0x21, struct ext_slave_config)
#define MPU_CONFIG_COMPASS _IOW(MPU_IOCTL, 0x22, struct ext_slave_config)
#define MPU_CONFIG_PRESSURE _IOW(MPU_IOCTL, 0x23, struct ext_slave_config)
#define MPU_GET_CONFIG_GYRO _IOWR(MPU_IOCTL, 0x20, struct ext_slave_config)
#define MPU_GET_CONFIG_ACCEL _IOWR(MPU_IOCTL, 0x21, struct ext_slave_config)
#define MPU_GET_CONFIG_COMPASS _IOWR(MPU_IOCTL, 0x22, struct ext_slave_config)
#define MPU_GET_CONFIG_PRESSURE _IOWR(MPU_IOCTL, 0x23, struct ext_slave_config)
#define MPU_SUSPEND _IOW(MPU_IOCTL, 0x30, __u32)
#define MPU_RESUME _IOW(MPU_IOCTL, 0x31, __u32)
/* Userspace PM Event response */
#define MPU_PM_EVENT_HANDLED _IO(MPU_IOCTL, 0x32)
#define MPU_GET_REQUESTED_SENSORS _IOR(MPU_IOCTL, 0x40, __u8)
#define MPU_SET_REQUESTED_SENSORS _IOW(MPU_IOCTL, 0x40, __u8)
#define MPU_GET_IGNORE_SYSTEM_SUSPEND _IOR(MPU_IOCTL, 0x41, __u8)
#define MPU_SET_IGNORE_SYSTEM_SUSPEND _IOW(MPU_IOCTL, 0x41, __u8)
#define MPU_GET_MLDL_STATUS _IOR(MPU_IOCTL, 0x42, __u8)
#define MPU_GET_I2C_SLAVES_ENABLED _IOR(MPU_IOCTL, 0x43, __u8)
#endif
#endif /* __MPU_H_ */
#endif /* __MPU_H_ */

View File

@@ -37,6 +37,7 @@ enum iio_chan_type {
IIO_VELOCITY,
IIO_CONCENTRATION,
IIO_RESISTANCE,
IIO_QUATERNION,
};
enum iio_modifier {
@@ -76,6 +77,7 @@ enum iio_modifier {
IIO_MOD_Q,
IIO_MOD_CO2,
IIO_MOD_VOC,
IIO_MOD_R,
};
enum iio_event_type {