#define ACCEL_COVARIANCE (101 * 16 + 8)
#define ACCEL_ALPHA_VAR (91 * 16)
#define ACCEL_A_VAR (92 * 16)
+#define ACCEL_CAL_INIT (94 * 16 + 2)
#define CPASS_BIAS_X (126 * 16 + 4)
#define CPASS_BIAS_Y (126 * 16 + 8)
#define CPASS_COVARIANCE (115 * 16)
#define CPASS_COVARIANCE_CUR (118 * 16 + 8)
#define CPASS_REF_MAG_3D (122 * 16)
+#define CPASS_CAL_INIT (114 * 16)
+#define CPASS_EST_FIRST_BIAS (113 * 16)
+#define MAG_DISTURB_STATE (113 * 16 + 2)
+#define CPASS_VAR_COUNT (112 * 16 + 6)
+#define CPASS_COUNT_7 ( 87 * 16 + 2)
+#define CPASS_MAX_INNO (124 * 16)
+#define CPASS_BIAS_OFFSET (113 * 16 + 4)
+#define CPASS_CUR_BIAS_OFFSET (114 * 16 + 4)
+#define CPASS_PRE_SENSOR_DATA ( 87 * 16 + 4)
#define CPASS_TIME_BUFFER (112 * 16 + 14)
#define CPASS_RADIUS_3D_THRESH_ANOMALY (112 * 16 + 8)
#define CPASS_STATUS_CHK (25 * 16 + 12)
+#define MAGN_THR_9X (35 * 16 + 8)
+#define MAGN_LPF_THR_9X (32 * 16 + 12)
+#define QFB_THR_9X (70 * 16 + 12)
+
#define DMPRATE_CNTR (18 * 16 + 4)
#define PEDSTD_BP_B (49 * 16 + 12)
#define PEDSTD_DECI (58 * 16)
#define PEDSTD_SB2 (60 * 16 + 14)
#define STPDET_TIMESTAMP (18 * 16 + 8)
-#define PEDSTD_DRIVE_STATE (43 * 16 + 10)
+#define PEDSTD_DRIVE_STATE (18 * 16)
#define PED_RATE (58 * 16 + 4)
-#define SMD_TIMER_THLD (26 * 16)
+#define SMD_E1_THLD (75 * 16 + 8)
+#define SMD_CNTR_TH (74 * 16 + 8)
+#define SMD_CNTR_LO_TH (74 * 16 + 12)
+#define SMD_LOW_ENERGY_TIMER_TH (76 * 16 + 8)
+#define SMD_E1_COUNTER_TH (76 * 16 + 12)
// Wake on Motion
#define TILT_ENABLE (68 * 16 + 12)
#define BAC_STATE (147 * 16)
-#define ACC_SCALE (30 * 16)
+// Accel FSR
+#define ACC_SCALE (30 * 16 + 0)
+#define ACC_SCALE2 (79 * 16 + 4)
#define ACCEL_MASK 0x80
#define GYRO_MASK 0x40
#define QUAT6_MASK 0x08
#define QUAT9_MASK 0x04
#define PQUAT6_MASK 0x02
+#define FOOTER_MASK 0x01
#define PRESSURE_MASK 0x80
#define GYRO_CALIBR_MASK 0x40
#define CPASS_CALIBR_MASK 0x20
#define QUAT6_SET 0x0800
#define QUAT9_SET 0x0400
#define PQUAT6_SET 0x0200
+#define FOOTER_SET 0x0100
#define PRESSURE_SET 0x0080
#define GYRO_CALIBR_SET 0x0040
#define CPASS_CALIBR_SET 0x0020
#define NINE_AXIS_EN 0x40
#define HEADER_SZ 2
-#define ACCEL_DATA_SZ 12
+#define ACCEL_DATA_SZ 6
#define GYRO_DATA_SZ 6
#define CPASS_DATA_SZ 6
#define ALS_DATA_SZ 8
#define GYRO_CALIBR_DATA_SZ 12
#define CPASS_CALIBR_DATA_SZ 12
#define PED_STEPDET_TIMESTAMP_SZ 4
+#define FOOTER_SZ 2
#define HEADER2_SZ 2
#define ACCEL_ACCURACY_SZ 2
static int inv_set_accel_sf(struct inv_mpu_state *st)
{
int result;
- int scale[] = {33554432, 67108864, 134217728, 268435456};
result = inv_set_bank(st, BANK_SEL_2);
if (result)
if (result)
return result;
- result = write_be32_to_mem(st,
- scale[st->chip_config.accel_fs], ACC_SCALE);
+ result = inv_set_accel_fsr_V3(st);
+ if (result)
+ return result;
+ result = inv_set_accel_scale2_V3(st);
+ if (result)
+ return result;
return result;
}
return result;
st->ped.int_thresh = data;
- return 0;
- case ATTR_DMP_SMD_TIMER_THLD:
- if (data < 0)
- return -EINVAL;
- result = write_be32_to_mem(st, data, SMD_TIMER_THLD);
- if (result)
- return result;
- st->smd.timer_thresh = data;
return 0;
default:
return -EINVAL;
return sprintf(buf, "%d\n", st->ped.int_thresh);
case ATTR_DMP_SMD_ENABLE:
return sprintf(buf, "%d\n", st->smd.on);
- case ATTR_DMP_SMD_TIMER_THLD:
- return sprintf(buf, "%d\n", st->smd.timer_thresh);
case ATTR_DMP_LOW_POWER_GYRO_ON:
return sprintf(buf, "%d\n", st->chip_config.low_power_gyro_on);
case ATTR_DEBUG_DATA_COLLECTION_MODE:
static IIO_DEVICE_ATTR(event_smd_enable, S_IRUGO | S_IWUGO,
inv_attr_show, inv_basic_attr_store, ATTR_DMP_SMD_ENABLE);
-static IIO_DEVICE_ATTR(params_smd_timer_thresh, S_IRUGO | S_IWUGO,
- inv_attr_show, inv_misc_attr_store, ATTR_DMP_SMD_TIMER_THLD);
static IIO_DEVICE_ATTR(params_pedometer_int_on, S_IRUGO | S_IWUGO,
inv_attr_show, inv_misc_attr_store, ATTR_DMP_PED_INT_ON);
static const struct attribute *inv_smd_attributes[] = {
&dev_attr_poll_smd.attr,
&iio_dev_attr_event_smd_enable.dev_attr.attr,
- &iio_dev_attr_params_smd_timer_thresh.dev_attr.attr,
};
static const struct attribute *inv_pressure_attributes[] = {
int invensense_mpu_parse_dt(struct device *dev, struct mpu_platform_data *pdata)
{
int rc;
- pr_info("%s: 15066 47", __func__);
+ pr_info("%s: 15667 52", __func__);
pr_info("%s: Invensense MPU parse_dt started.\n", __func__);
rc = inv_parse_orientation_matrix(dev, pdata->orientation);
} else {
inv_switch_power_in_lp(st, true);
}
+ st->suspend_state = false;
mutex_unlock(&indio_dev->mlock);
+ inv_read_fifo(0, (void *)st);
/* add code according to different request End */
- mutex_unlock(&st->suspend_resume_lock);
return 0;
}
/* add code according to different request Start */
pr_debug("%s inv_mpu_suspend\n", st->hw->name);
+ mutex_lock(&indio_dev->mlock);
+ st->suspend_state = true;
if (st->chip_config.dmp_on) {
if (st->batch.on) {
/* in non DMP case, just turn off the power */
inv_set_power(st, false);
}
+ mutex_unlock(&indio_dev->mlock);
+
/* add code according to different request End */
- st->suspend_state = true;
- msleep(100);
- mutex_lock(&st->suspend_resume_lock);
- st->suspend_state = false;
return 0;
}
#include <linux/miscdevice.h>
#include <linux/spinlock.h>
#include <linux/mpu.h>
+#include <linux/interrupt.h>
#include "iio.h"
#include "buffer.h"
#define DMP_OFFSET 0x90
#define DMP_IMAGE_SIZE (7021 + DMP_OFFSET)
#define MIN_MST_ODR_CONFIG 4
+#define MAX_MST_NON_COMPASS_ODR_CONFIG 7
#define THREE_AXES 3
#define NINE_ELEM (THREE_AXES * THREE_AXES)
#define MPU_TEMP_SHIFT 16
ATTR_DMP_PED_INT_THRESH,
ATTR_DMP_PED_ON,
ATTR_DMP_SMD_ENABLE,
- ATTR_DMP_SMD_TIMER_THLD,
ATTR_DMP_PEDOMETER_STEPS,
ATTR_DMP_PEDOMETER_TIME,
ATTR_DMP_PEDOMETER_COUNTER,
int inv_set_dmp(struct inv_mpu_state *st);
int inv_set_secondary(struct inv_mpu_state *st);
+irqreturn_t inv_read_fifo(int irq, void *dev_id);
+int inv_set_accel_fsr_V3(struct inv_mpu_state *st);
+int inv_set_accel_scale2_V3(struct inv_mpu_state *st);
+
#define mem_w(a, b, c) \
mpu_memory_write(st, st->i2c_addr, a, b, c)
#define mem_r(a, b, c) \
#include "inv_test/inv_counters.h"
/* DMP defines */
-#define FIRMWARE_CRC 0xfef1270d
+#define FIRMWARE_CRC 0xda126847
#define FIRMWARE_CRC_1 0x24e5ed7e
int inv_get_pedometer_steps(struct inv_mpu_state *st, int *ped)
return 0;
}
+
+/*
+input param: fsr for accel parts
+1: 1g. 2: 2g. 4: 4g. 8: 8g. 16: 16g. 32: 32g.
+
+The goal is to set 1g data to 2^25, 2g data to 2^26, etc.
+
+For 2g parts, raw accel data is 1g = 2^14, 2g = 2^15.
+DMP takes raw accel data and shifts by 16 bits, so this scale means to shift by -5 bits.
+In Q-30 math, >> 5 equals multiply by 2^25 = 33554432.
+
+For 8g parts, raw accel data is 4g = 2^14, 8g = 2^15.
+DMP takes raw accel data and shifts by 16 bits, so this scale means to shift by -3 bits.
+In Q-30 math, >> 3 equals multiply by 2^27 = 134217728.
+*/
+int inv_set_accel_fsr_V3(struct inv_mpu_state *st)
+{
+ u32 scale;
+
+ switch (st->chip_config.accel_fs) {
+ case 0: //2g
+ scale = 33554432; // 2^25
+ break;
+ case 1: //4g
+ scale = 67108864; // 2^26
+ break;
+ case 2: //8g
+ scale = 134217728; // 2^27
+ break;
+ case 3: //16g
+ scale = 268435456; // 2^28
+ break;
+ default:
+ return -EINVAL;
+ }
+ return write_be32_to_mem(st, scale, ACC_SCALE);
+}
+
+int inv_set_accel_scale2_V3(struct inv_mpu_state *st)
+{
+ u32 scale;
+
+ switch (st->chip_config.accel_fs) {
+ case 0: //2g
+ scale = 524288; // 2^19
+ break;
+ case 1: //4g
+ scale = 262144; // 2^18
+ break;
+ case 2: //8g
+ scale = 131072; // 2^17
+ break;
+ case 3: //16g
+ scale = 65536; // 2^16
+ break;
+ default:
+ return -EINVAL;
+ }
+ return write_be32_to_mem(st, scale, ACC_SCALE2);
+}
+
static int inv_load_firmware(struct inv_mpu_state *st)
{
int bank, write_size;
pr_err("dmp loading eror:inv_write_gyro_sf\n");
return result;
}
+
+ result = inv_set_accel_fsr_V3(st);
+ if (result)
+ return result;
+ result = inv_set_accel_scale2_V3(st);
+ if (result)
+ return result;
+
if (st->chip_config.has_compass) {
result = inv_compass_dmp_cal(st);
if (result)
switch (ind) {
case SENSOR_ACCEL:
- inv_convert_and_push_16bytes(st, hdr, d, t, iden);
+ inv_convert_and_push_8bytes(st, hdr, d, t, iden);
break;
case SENSOR_GYRO:
inv_convert_and_push_8bytes(st, hdr, d, t, iden);
#define NON_DMP_MIN_RUN_TIME (10 * NSEC_PER_MSEC)
- if (st->suspend_state)
- return IRQ_HANDLED;
- mutex_lock(&st->suspend_resume_lock);
mutex_lock(&indio_dev->mlock);
+ if (st->suspend_state) {
+ mutex_unlock(&indio_dev->mlock);
+ return IRQ_HANDLED;
+ }
if (st->chip_config.dmp_on) {
st->last_run_time = get_time_ns();
end_read_fifo:
inv_switch_power_in_lp(st, false);
mutex_unlock(&indio_dev->mlock);
- mutex_unlock(&st->suspend_resume_lock);
return IRQ_HANDLED;
inv_reset_fifo(indio_dev, true);
inv_switch_power_in_lp(st, false);
mutex_unlock(&indio_dev->mlock);
- mutex_unlock(&st->suspend_resume_lock);
return IRQ_HANDLED;
struct recover_regs {
/* Bank#0 */
u8 fifo_cfg; /* REG_FIFO_CFG */
+ u8 fifo_size_0; /* REG_FIFO_SIZE_0 */
u8 user_ctrl; /* REG_USER_CTRL */
u8 lp_config; /* REG_LP_CONFIG */
u8 int_enable; /* REG_INT_ENABLE */
static void inv_show_saved_setting(struct inv_mpu_state *st)
{
pr_debug(" REG_FIFO_CFG : 0x%02X\n", saved_regs.fifo_cfg);
+ pr_debug(" REG_FIFO_SIZE_0 : 0x%02X\n", saved_regs.fifo_size_0);
pr_debug(" REG_USER_CTRL : 0x%02X\n", saved_regs.user_ctrl);
pr_debug(" REG_LP_CONFIG : 0x%02X\n", saved_regs.lp_config);
pr_debug(" REG_INT_ENABLE : 0x%02X\n", saved_regs.int_enable);
return result;
result = inv_plat_read(st, REG_FIFO_CFG, 1, &saved_regs.fifo_cfg);
+ if (result)
+ return result;
+ result = inv_plat_read(st, REG_FIFO_SIZE_0, 1, &saved_regs.fifo_size_0);
if (result)
return result;
result = inv_plat_read(st, REG_USER_CTRL, 1, &saved_regs.user_ctrl);
u8 reg_pwr_mgmt_2;
u8 reg_lp_config;
u8 reg_fifo_cfg;
+ u8 reg_fifo_size_0;
u8 reg_delay_enable;
u8 reg_delay_time;
u8 reg_gyro_smplrt;
},
};
+static int accel_gyro_rate[] = {5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 17, 18, 22, 25, 28, 32, 37, 45,
+ 51, 75, 102, 225};
+
static int inv_out_data_cntl(struct inv_mpu_state *st, u16 wd, bool en)
{
return inv_write_cntl(st, wd, en, DATA_OUT_CTL1);
static int inv_batchmode_calc(struct inv_mpu_state *st)
{
int b, timeout;
- int i, bps, max_rate, max_ind;
+ int i, bps, max_rate;
enum INV_ENGINE eng;
int ps, real_rate;
int en_num, en_sen, count;
max_rate = 0;
- max_ind = -1;
bps = 0;
ps = 0;
en_num = 0;
if (st->sensor[i].on) {
if (max_rate < st->sensor[i].rate) {
max_rate = st->sensor[i].rate;
- max_ind = i;
}
/* get actual rate */
real_rate = (MSEC_PER_SEC * NSEC_PER_MSEC) /
} else
timeout = st->batch.timeout;
- eng = st->sensor[max_ind].engine_base;
+ if (st->chip_config.gyro_enable)
+ eng = ENGINE_GYRO;
+ else if (st->chip_config.accel_enable)
+ eng = ENGINE_ACCEL;
+ else
+ eng = ENGINE_I2C;
} else {
if (st->chip_config.step_detector_on ||
st->chip_config.step_indicator_on) {
static int inv_turn_on_engine(struct inv_mpu_state *st)
{
- u8 w, v;
+ u8 w;
int r;
r = 0;
BIT_PWR_PRESSURE_STBY);
}
}
- inv_plat_read(st, REG_PWR_MGMT_2, 1, &v);
- if ((BIT_PWR_ALL_OFF == v) &&
- (BIT_PWR_ALL_OFF != w) &&
- (!st->chip_config.slave_enable)) {
- r = inv_plat_single_write(st, REG_PWR_MGMT_2,
- BIT_PWR_GYRO_STBY |
- BIT_PWR_PRESSURE_STBY);
- if (r)
- return r;
- }
- if (!st->chip_config.dmp_on) {
- r = inv_plat_single_write(st, REG_PWR_MGMT_2,
- BIT_PWR_PRESSURE_STBY);
- if (r)
- return r;
- }
+ r = inv_plat_single_write(st, REG_PWR_MGMT_2, w);
+ if (r)
+ return r;
+
if (st->chip_config.gyro_enable)
msleep(GYRO_ENGINE_UP_TIME);
static int inv_set_fifo_size(struct inv_mpu_state *st)
{
int result;
- u8 size, cfg, ind;
+ u8 cfg, ind;
result = 0;
if (st->chip_config.dmp_on) {
/* use one FIFO in DMP mode */
- cfg = BIT_MULTI_FIFO_CFG;
- size = BIT_GYRO_FIFO_SIZE_1024;
+ cfg = BIT_SINGLE_FIFO_CFG;
} else {
ind = 0;
if (st->sensor[SENSOR_GYRO].on)
ind++;
if (st->sensor[SENSOR_COMPASS].on)
ind++;
- if (ind > 1) {
+ if (ind > 1)
cfg = BIT_MULTI_FIFO_CFG;
- size = (BIT_GYRO_FIFO_SIZE_1024 |
- BIT_ACCEL_FIFO_SIZE_1024
- | BIT_FIFO_3_SIZE_64);
- } else {
+ else
cfg = BIT_SINGLE_FIFO_CFG;
- size = BIT_FIFO_SIZE_1024;
- }
- }
- if (cfg != local.reg_fifo_cfg) {
- result = inv_plat_single_write(st, REG_FIFO_CFG, cfg);
- if (result)
- return result;
- local.reg_fifo_cfg = cfg;
}
+ result = inv_plat_single_write(st, REG_FIFO_CFG, cfg);
+ if (result)
+ return result;
- return result;
+ return 0;
}
/*
}
if (mst_odr_config < MIN_MST_ODR_CONFIG)
mst_odr_config = MIN_MST_ODR_CONFIG;
+ if (compass_rate) {
+ if (mst_odr_config > MAX_MST_NON_COMPASS_ODR_CONFIG)
+ mst_odr_config = MAX_MST_NON_COMPASS_ODR_CONFIG;
+ }
base = BASE_SAMPLE_RATE / (1 << mst_odr_config);
- st->eng_info[ENGINE_I2C].running_rate = base;
- st->eng_info[ENGINE_I2C].divider = (1 << mst_odr_config);
+ if ((!st->chip_config.gyro_enable) &&
+ (!st->chip_config.accel_enable)) {
+ st->eng_info[ENGINE_I2C].running_rate = base;
+ st->eng_info[ENGINE_I2C].divider = (1 << mst_odr_config);
+ }
inv_calc_engine_dur(&st->eng_info[ENGINE_I2C]);
d = 0;
local.wom_on = st->chip_config.wom_on;
}
+ inv_write_2bytes(st, 0x8a, st->chip_config.gyro_enable |
+ (st->chip_config.accel_enable << 1) |
+ (st->chip_config.slave_enable << 3));
+
return 0;
}
return result;
}
+
+static int inv_get_accel_gyro_rate(int compass_rate)
+{
+ int i;
+
+ i = 0;
+ while ((i < ARRAY_SIZE(accel_gyro_rate)) &&
+ compass_rate > accel_gyro_rate[i])
+ i++;
+
+ return accel_gyro_rate[i];
+}
+
static int inv_determine_engine(struct inv_mpu_state *st)
{
int i;
bool a_en, g_en, c_en, p_en, data_on, ped_on;
int compass_rate, pressure_rate, nineq_rate, accel_rate, gyro_rate;
+ u32 base_time;
#define NINEQ_MIN_COMPASS_RATE 35
#define GEOMAG_MIN_COMPASS_RATE 70
accel_rate = st->sensor[SENSOR_ACCEL].rate;
}
}
- if (a_en) {
+ if (a_en | g_en) {
gyro_rate = max(gyro_rate, PEDOMETER_FREQ);
accel_rate = max(accel_rate, PEDOMETER_FREQ);
}
if (st->sensor[SENSOR_CALIB_GYRO].on)
gyro_rate = max(gyro_rate, st->sensor[SENSOR_CALIB_GYRO].rate);
+ if (g_en) {
+ if (a_en)
+ gyro_rate = max(gyro_rate, accel_rate);
+ if (c_en || p_en) {
+ if (gyro_rate < compass_rate)
+ gyro_rate =
+ inv_get_accel_gyro_rate(compass_rate);
+ }
+ accel_rate = gyro_rate;
+ compass_rate = gyro_rate;
+ } else if (a_en) {
+ if (c_en || p_en) {
+ if (accel_rate < compass_rate)
+ accel_rate =
+ inv_get_accel_gyro_rate(compass_rate);
+ }
+ compass_rate = accel_rate;
+ gyro_rate = accel_rate;
+ }
+
st->eng_info[ENGINE_GYRO].running_rate = gyro_rate;
st->eng_info[ENGINE_ACCEL].running_rate = accel_rate;
st->eng_info[ENGINE_PRESSURE].running_rate = MPU_DEFAULT_DMP_FREQ;
(BASE_SAMPLE_RATE / MPU_DEFAULT_DMP_FREQ) *
(MPU_DEFAULT_DMP_FREQ /
st->eng_info[ENGINE_ACCEL].running_rate);
+ st->eng_info[ENGINE_I2C].divider =
+ (BASE_SAMPLE_RATE / MPU_DEFAULT_DMP_FREQ) *
+ (MPU_DEFAULT_DMP_FREQ /
+ st->eng_info[ENGINE_ACCEL].running_rate);
+
+ base_time = NSEC_PER_SEC;
+
+ st->eng_info[ENGINE_GYRO].base_time = base_time;
+ st->eng_info[ENGINE_ACCEL].base_time = base_time;
+ st->eng_info[ENGINE_I2C].base_time = base_time;
inv_calc_engine_dur(&st->eng_info[ENGINE_GYRO]);
inv_calc_engine_dur(&st->eng_info[ENGINE_ACCEL]);
st->chip_config.slave_enable = 1;
else
st->chip_config.slave_enable = 0;
-
if (a_en) {
- st->gyro_cal_enable = 1;
st->accel_cal_enable = 1;
} else {
- st->gyro_cal_enable = 0;
st->accel_cal_enable = 0;
}
+ if (g_en) {
+ st->gyro_cal_enable = 1;
+ } else {
+ st->gyro_cal_enable = 0;
+ }
if (c_en)
st->compass_cal_enable = 1;
else