diff options
author | Erik Lilliebjerg <elilliebjerg@nvidia.com> | 2013-07-08 05:55:56 -0700 |
---|---|---|
committer | Riham Haidar <rhaidar@nvidia.com> | 2013-10-07 16:39:23 -0700 |
commit | c69d9aae4115103aca523f0ddfcc1ddaf8c493fa (patch) | |
tree | 9b5a5c6bb9440552e3c695e858b0c72f55e6425e | |
parent | ae306268afc1c478740096f4d89875db90b03b6d (diff) |
input: misc: sensor drivers
- reduce suspend time for compass and pressure
- fix MPU possible interrupt storm
- fix MPU sample frequency overrun
- fix MPU 9250 support for sw_rev > 2 HW
- add BMP280 support to BMP180 pressure driver
- optimize MPU FIFO timestamp algorithm
- add compass self-test
- add data interface
Bug 1313284
Bug 1311053
Bug 1295128
Bug 1256470
Bug 1236893
Change-Id: I4ffa906c07ed1d07ad3b89aea9eb83fb153b765d
Signed-off-by: Erik Lilliebjerg <elilliebjerg@nvidia.com>
Reviewed-on: http://git-master/r/246132
(cherry picked from commit 8cdf5b9ccfb47477229bf2cbb37f5132e81ad39e)
Reviewed-on: http://git-master/r/248192
Reviewed-by: Riham Haidar <rhaidar@nvidia.com>
Tested-by: Riham Haidar <rhaidar@nvidia.com>
-rw-r--r-- | drivers/input/misc/compass/ak8975_input.c | 314 | ||||
-rw-r--r-- | drivers/input/misc/mpu/inv_gyro.c | 747 | ||||
-rw-r--r-- | drivers/input/misc/mpu/inv_gyro.h | 40 | ||||
-rw-r--r-- | drivers/input/misc/mpu/inv_gyro_misc.c | 2 | ||||
-rw-r--r-- | drivers/input/misc/pressure/bmp180.c | 426 | ||||
-rw-r--r-- | include/linux/mpu.h | 6 |
6 files changed, 888 insertions, 647 deletions
diff --git a/drivers/input/misc/compass/ak8975_input.c b/drivers/input/misc/compass/ak8975_input.c index b882f66514b0..665a4bee184c 100644 --- a/drivers/input/misc/compass/ak8975_input.c +++ b/drivers/input/misc/compass/ak8975_input.c @@ -22,14 +22,15 @@ #include <linux/mpu.h> +#define AKM_VERSION (23) #define AKM_NAME "akm89xx" #define AKM_HW_DELAY_POR_MS (50) #define AKM_HW_DELAY_TSM_MS (10) /* Time Single Measurement */ #define AKM_HW_DELAY_US (100) #define AKM_HW_DELAY_ROM_ACCESS_US (200) #define AKM_POLL_DELAY_MS_DFLT (200) -#define AKM_MPU_RETRY_COUNT (20) -#define AKM_MPU_RETRY_DELAY_MS (100) +#define AKM_MPU_RETRY_COUNT (50) +#define AKM_MPU_RETRY_DELAY_MS (20) #define AKM_ERR_CNT_MAX (20) #define AKM_INPUT_RESOLUTION (1) @@ -109,14 +110,18 @@ #define WR (0) #define RD (1) +#define AKM_DBG_SPEW_MSG (1 << 0) +#define AKM_DBG_SPEW_MAGNETIC_FIELD (1 << 1) +#define AKM_DBG_SPEW_MAGNETIC_FIELD_RAW (1 << 2) + enum AKM_DATA_INFO { - AKM_DATA_INFO_MAGNETIC_FIELD = 0, - AKM_DATA_INFO_MAGNETIC_FIELD_RAW, - AKM_DATA_INFO_CALIBRATION, - AKM_DATA_INFO_SELF_TEST, - AKM_DATA_INFO_SELF_TEST_RAW, + AKM_DATA_INFO_DATA = 0, + AKM_DATA_INFO_VER, AKM_DATA_INFO_RESET, - AKM_DATA_INFO_REGISTERS, + AKM_DATA_INFO_REGS, + AKM_DATA_INFO_DBG, + AKM_DATA_INFO_MAGNETIC_FIELD_SPEW, + AKM_DATA_INFO_MAGNETIC_FIELD_RAW_SPEW, AKM_DATA_INFO_LIMIT_MAX, }; @@ -151,6 +156,7 @@ struct akm_inf { unsigned int range_i; /* max_range index */ unsigned int resolution; /* report when new data outside this */ unsigned int data_info; /* data info to return */ + unsigned int dbg; /* device id */ unsigned int dev_id; /* device id */ bool use_mpu; /* if device behind MPU */ bool initd; /* set if initialized */ @@ -306,10 +312,10 @@ static int akm_pm(struct akm_inf *inf, bool enable) if (err > 0) err = 0; if (err) - dev_err(&inf->i2c->dev, "%s enable=%x ERR=%d\n", + dev_err(&inf->i2c->dev, "%s pwr=%x ERR=%d\n", __func__, enable, err); else - dev_dbg(&inf->i2c->dev, "%s enable=%x\n", + dev_dbg(&inf->i2c->dev, "%s pwr=%x\n", __func__, enable); return err; } @@ -370,7 +376,7 @@ static int akm_nvi_mpu_bypass_request(struct akm_inf *inf) if ((!err) || (err == -EPERM)) break; - mdelay(AKM_MPU_RETRY_DELAY_MS); + msleep(AKM_MPU_RETRY_DELAY_MS); } if (err == -EPERM) err = 0; @@ -551,6 +557,14 @@ static void akm_report(struct akm_inf *inf, u8 *data, s64 ts) { akm_calc(inf, data); mutex_lock(&inf->mutex_data); + if (inf->dbg & AKM_DBG_SPEW_MAGNETIC_FIELD_RAW) + dev_info(&inf->i2c->dev, "r %d %d %d %lld\n", + inf->xyz_raw[AXIS_X], inf->xyz_raw[AXIS_Y], + inf->xyz_raw[AXIS_Z], ts); + if (inf->dbg & AKM_DBG_SPEW_MAGNETIC_FIELD) + dev_info(&inf->i2c->dev, "%d %d %d %lld\n", + inf->xyz[AXIS_X], inf->xyz[AXIS_Y], + inf->xyz[AXIS_Z], ts); input_report_rel(inf->idev, REL_X, inf->xyz[AXIS_X]); input_report_rel(inf->idev, REL_Y, inf->xyz[AXIS_Y]); input_report_rel(inf->idev, REL_Z, inf->xyz[AXIS_Z]); @@ -756,26 +770,25 @@ static int akm_enable(struct akm_inf *inf, bool enable) { int err = 0; - akm_pm(inf, true); - if (!inf->initd) - err = akm_init_hw(inf); - if (!err) { - if (enable) { + if (enable) { + akm_pm(inf, true); + if (!inf->initd) + err = akm_init_hw(inf); + if (!err) { inf->data_out = AKM_CNTL1_MODE_SINGLE; err |= akm_delay(inf, inf->poll_delay_us); err |= akm_mode_wr(inf, true, inf->range_i, inf->data_out & AKM_CNTL1_MODE_MASK); if (!err) inf->enable = true; - } else { + } + } else if (inf->enable) { + err = akm_mode_wr(inf, false, inf->range_i, + AKM_CNTL1_MODE_POWERDOWN); + if (!err) { + akm_pm(inf, false); inf->enable = false; - err = akm_mode_wr(inf, false, inf->range_i, - AKM_CNTL1_MODE_POWERDOWN); - if (!err) - akm_pm(inf, false); } - } else { - akm_pm(inf, false); } return err; } @@ -798,7 +811,8 @@ static ssize_t akm_enable_store(struct device *dev, en = true; else en = false; - dev_dbg(&inf->i2c->dev, "%s: %x\n", __func__, en); + if (inf->dbg & AKM_DBG_SPEW_MSG) + dev_info(&inf->i2c->dev, "%s: %x\n", __func__, en); err = akm_enable(inf, en); if (err) { dev_err(&inf->i2c->dev, "%s: %x ERR=%d\n", __func__, en, err); @@ -835,12 +849,14 @@ static ssize_t akm_delay_store(struct device *dev, if (err) return -EINVAL; - dev_dbg(&inf->i2c->dev, "%s: %u\n", __func__, delay_us); if (delay_us < (AKM_INPUT_DELAY_MS_MIN * 1000)) delay_us = (AKM_INPUT_DELAY_MS_MIN * 1000); if ((inf->enable) && (delay_us != inf->poll_delay_us)) err = akm_delay(inf, delay_us); if (!err) { + if (inf->dbg & AKM_DBG_SPEW_MSG) + dev_info(&inf->i2c->dev, "%s: %u\n", + __func__, delay_us); inf->poll_delay_us = delay_us; } else { dev_err(&inf->i2c->dev, "%s: %u ERR=%d\n", @@ -968,6 +984,27 @@ static ssize_t akm_data_store(struct device *dev, dev_dbg(&inf->i2c->dev, "%s %u\n", __func__, data_info); inf->data_info = data_info; + switch (data_info) { + case AKM_DATA_INFO_DATA: + inf->dbg = 0; + break; + + case AKM_DATA_INFO_DBG: + inf->dbg ^= AKM_DBG_SPEW_MSG; + break; + + case AKM_DATA_INFO_MAGNETIC_FIELD_SPEW: + inf->dbg ^= AKM_DBG_SPEW_MAGNETIC_FIELD; + break; + + case AKM_DATA_INFO_MAGNETIC_FIELD_RAW_SPEW: + inf->dbg ^= AKM_DBG_SPEW_MAGNETIC_FIELD_RAW; + break; + + default: + break; + } + return count; } @@ -976,112 +1013,33 @@ static ssize_t akm_data_show(struct device *dev, char *buf) { struct akm_inf *inf; + ssize_t t; u8 data[16]; - s16 x = 0; - s16 y = 0; - s16 z = 0; enum AKM_DATA_INFO data_info; bool enable; - char const *info_str; + unsigned int i; int err = 0; inf = dev_get_drvdata(dev); data_info = inf->data_info; - inf->data_info = AKM_DATA_INFO_MAGNETIC_FIELD; + inf->data_info = AKM_DATA_INFO_DATA; enable = inf->enable; switch (data_info) { - case AKM_DATA_INFO_MAGNETIC_FIELD: - if (inf->enable) { - mutex_lock(&inf->mutex_data); - x = inf->xyz[AXIS_X]; - y = inf->xyz[AXIS_Y]; - z = inf->xyz[AXIS_Z]; - mutex_unlock(&inf->mutex_data); - info_str = "magnetic_field"; - } else { - info_str = "ERR: DISABLED"; - } - break; - - case AKM_DATA_INFO_MAGNETIC_FIELD_RAW: - if (inf->enable) { - mutex_lock(&inf->mutex_data); - x = inf->xyz_raw[AXIS_X]; - y = inf->xyz_raw[AXIS_Y]; - z = inf->xyz_raw[AXIS_Z]; - mutex_unlock(&inf->mutex_data); - info_str = "raw_data"; - } else { - info_str = "ERR: DISABLED"; - } - break; - - case AKM_DATA_INFO_CALIBRATION: - err = 0; - if (!inf->initd) - err = akm_enable(inf, enable); - if (err) { - info_str = "calibration ERR"; - } else { - x = (s16)inf->asa.asa[AXIS_X]; - y = (s16)inf->asa.asa[AXIS_Y]; - z = (s16)inf->asa.asa[AXIS_Z]; - info_str = "calibration"; - } - break; - - case AKM_DATA_INFO_SELF_TEST: - akm_enable(inf, false); - akm_pm(inf, true); - if (!inf->initd) { - err = akm_init_hw(inf); - } else { - err = akm_nvi_mpu_bypass_request(inf); - if (!err) { - err = akm_self_test(inf); - akm_nvi_mpu_bypass_release(inf); - } - } - if (err < 0) { - info_str = "self_test ERR"; - } else { - mutex_lock(&inf->mutex_data); - x = inf->xyz[AXIS_X]; - y = inf->xyz[AXIS_Y]; - z = inf->xyz[AXIS_Z]; - mutex_unlock(&inf->mutex_data); - if (err > 0) - info_str = "self_test FAIL"; - else - info_str = "self_test PASS"; - } - akm_enable(inf, enable); - break; - - case AKM_DATA_INFO_SELF_TEST_RAW: - akm_enable(inf, false); - akm_pm(inf, true); - if (!inf->initd) { - err = akm_init_hw(inf); - } else { - err = akm_nvi_mpu_bypass_request(inf); - if (!err) { - err = akm_self_test(inf); - akm_nvi_mpu_bypass_release(inf); - } - } - if (err < 0) { - info_str = "self_test ERR"; - } else { - mutex_lock(&inf->mutex_data); - x = inf->xyz_raw[AXIS_X]; - y = inf->xyz_raw[AXIS_Y]; - z = inf->xyz_raw[AXIS_Z]; - mutex_unlock(&inf->mutex_data); - info_str = "self_test raw"; - } - akm_enable(inf, enable); - break; + case AKM_DATA_INFO_DATA: + mutex_lock(&inf->mutex_data); + t = sprintf(buf, "magnetic_field: %hd, %hd, %hd ", + inf->xyz[AXIS_X], + inf->xyz[AXIS_Y], + inf->xyz[AXIS_Z]); + t += sprintf(buf + t, "raw: %hd, %hd, %hd\n", + inf->xyz_raw[AXIS_X], + inf->xyz_raw[AXIS_Y], + inf->xyz_raw[AXIS_Z]); + mutex_unlock(&inf->mutex_data); + return t; + + case AKM_DATA_INFO_VER: + return sprintf(buf, "version=%u\n", AKM_VERSION); case AKM_DATA_INFO_RESET: akm_pm(inf, true); @@ -1089,31 +1047,50 @@ static ssize_t akm_data_show(struct device *dev, inf->data_out & AKM_CNTL1_MODE_MASK); akm_enable(inf, enable); if (err) - return sprintf(buf, "reset ERR\n"); + return sprintf(buf, "reset ERR %d\n", err); else return sprintf(buf, "reset done\n"); - case AKM_DATA_INFO_REGISTERS: + case AKM_DATA_INFO_REGS: + if (!inf->initd) + t = sprintf(buf, "calibration: NEED ENABLE\n"); + else + t = sprintf(buf, "calibration: x=%#2x y=%#2x z=%#2x\n", + inf->asa.asa[AXIS_X], + inf->asa.asa[AXIS_Y], + inf->asa.asa[AXIS_Z]); err = akm_nvi_mpu_bypass_request(inf); if (!err) { err = akm_i2c_rd(inf, AKM_REG_WIA, AKM_REG_ASAX, data); akm_nvi_mpu_bypass_release(inf); } - if (err) - return sprintf(buf, "register read ERR\n"); + if (err) { + t += sprintf(buf + t, "registers: ERR %d\n", err); + } else { + t += sprintf(buf + t, "registers:\n"); + for (i = 0; i < AKM_REG_ASAX; i++) + t += sprintf(buf + t, "%#2x=%#2x\n", + AKM_REG_WIA + i, data[i]); + } + return t; + + case AKM_DATA_INFO_DBG: + return sprintf(buf, "debug spew=%x\n", + inf->dbg & AKM_DBG_SPEW_MSG); - return sprintf(buf, "%x %x %x %x %x %x %x %x %x %x\n", - data[0], data[1], data[2], - le16_to_cpup((__le16 *)(&data[3])), - le16_to_cpup((__le16 *)(&data[5])), - le16_to_cpup((__le16 *)(&data[7])), - data[9], data[10], data[11], data[12]); + case AKM_DATA_INFO_MAGNETIC_FIELD_SPEW: + return sprintf(buf, "xyz_ts spew=%x\n", + !!(inf->dbg & AKM_DBG_SPEW_MAGNETIC_FIELD)); + + case AKM_DATA_INFO_MAGNETIC_FIELD_RAW_SPEW: + return sprintf(buf, "xyz_raw_ts spew=%x\n", + !!(inf->dbg & AKM_DBG_SPEW_MAGNETIC_FIELD_RAW)); default: - return -EINVAL; + break; } - return sprintf(buf, "%s: %hd, %hd, %hd\n", info_str, x, y, z); + return -EINVAL; } static ssize_t akm_mpu_fifo_enable_store(struct device *dev, @@ -1167,6 +1144,54 @@ static ssize_t akm_microamp_show(struct device *dev, return sprintf(buf, "%u\n", AKM_INPUT_POWER_UA); } +static ssize_t akm_self_test_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct akm_inf *inf; + ssize_t t; + bool enable; + int err; + + inf = dev_get_drvdata(dev); + enable = inf->enable; + akm_enable(inf, false); + akm_pm(inf, true); + if (!inf->initd) { + err = akm_init_hw(inf); + } else { + err = akm_nvi_mpu_bypass_request(inf); + if (!err) { + err = akm_self_test(inf); + akm_nvi_mpu_bypass_release(inf); + } + } + if (err < 0) { + t = sprintf(buf, "ERR: %d\n", err); + } else { + t = sprintf(buf, "%d xyz: %hd %hd %hd raw: %hd %hd %hd ", + err, + inf->xyz[AXIS_X], + inf->xyz[AXIS_Y], + inf->xyz[AXIS_Z], + inf->xyz_raw[AXIS_X], + inf->xyz_raw[AXIS_Y], + inf->xyz_raw[AXIS_Z]); + if (err > 0) { + if (err & (1 << AXIS_X)) + t += sprintf(buf + t, "X "); + if (err & (1 << AXIS_Y)) + t += sprintf(buf + t, "Y "); + if (err & (1 << AXIS_Z)) + t += sprintf(buf + t, "Z "); + t += sprintf(buf + t, "FAILED\n"); + } else { + t += sprintf(buf + t, "PASS\n"); + } + } + akm_enable(inf, enable); + return t; +} + static ssize_t akm_orientation_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1196,6 +1221,8 @@ static DEVICE_ATTR(divisor, S_IRUGO, akm_divisor_show, NULL); static DEVICE_ATTR(microamp, S_IRUGO, akm_microamp_show, NULL); +static DEVICE_ATTR(self_test, S_IRUGO, + akm_self_test_show, NULL); static DEVICE_ATTR(orientation, S_IRUGO, akm_orientation_show, NULL); @@ -1207,6 +1234,7 @@ static struct attribute *akm_attrs[] = { &dev_attr_divisor.attr, &dev_attr_microamp.attr, &dev_attr_data.attr, + &dev_attr_self_test.attr, &dev_attr_orientation.attr, &dev_attr_mpu_fifo_en.attr, NULL @@ -1460,23 +1488,6 @@ akm_probe_again: return err; } -static int akm_suspend(struct device *dev) -{ - struct akm_inf *inf; - int err; - - inf = dev_get_drvdata(dev); - err = akm_enable(inf, false); - if (err) - dev_err(dev, "%s ERR\n", __func__); - dev_info(dev, "%s done\n", __func__); - return 0; -} - -static const struct dev_pm_ops akm_pm_ops = { - .suspend = akm_suspend, -}; - static const struct i2c_device_id akm_i2c_device_id[] = { {AKM_NAME, 0}, {"ak8963", 0}, @@ -1505,7 +1516,6 @@ static struct i2c_driver akm_driver = { .name = AKM_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(akm_of_match), - .pm = &akm_pm_ops, }, .id_table = akm_i2c_device_id, .shutdown = akm_shutdown, diff --git a/drivers/input/misc/mpu/inv_gyro.c b/drivers/input/misc/mpu/inv_gyro.c index 5e1c52dfb0a5..f09044e25ef2 100644 --- a/drivers/input/misc/mpu/inv_gyro.c +++ b/drivers/input/misc/mpu/inv_gyro.c @@ -23,7 +23,6 @@ * @details This driver currently works for the ITG3500, MPU6050, MPU9150 * MPU3050 */ -#define DEBUG_FIFO_DATA_SPEW (0) #include <linux/module.h> #include <linux/init.h> @@ -46,6 +45,8 @@ #include "inv_gyro.h" +#define NVI_VERSION (23) + /* regulator names in order of powering on */ static char *nvi_vregs[] = { "vdd", @@ -146,12 +147,6 @@ int inv_i2c_read_base(struct inv_gyro_state_s *st, unsigned short i2c_addr, struct i2c_msg msgs[2]; int res; - if (st->shutdown) - return 0; - - if (!data) - return -EINVAL; - msgs[0].addr = i2c_addr; msgs[0].flags = 0; /* write */ msgs[0].buf = ® @@ -164,7 +159,7 @@ int inv_i2c_read_base(struct inv_gyro_state_s *st, unsigned short i2c_addr, res = i2c_transfer(st->sl_handle, msgs, 2); pr_debug("%s RD%02X%02X%02X res=%d\n", - st->hw_s->name, i2c_addr, reg, length, res); + st->hw_s->name, i2c_addr, reg, length, res); if (res < 2) { if (res >= 0) res = -EIO; @@ -188,9 +183,6 @@ int inv_i2c_single_write_base(struct inv_gyro_state_s *st, struct i2c_msg msg; int res; - if (st->shutdown) - return 0; - tmp[0] = reg; tmp[1] = data; @@ -200,7 +192,7 @@ int inv_i2c_single_write_base(struct inv_gyro_state_s *st, msg.len = 2; res = i2c_transfer(st->sl_handle, &msg, 1); - pr_debug("%s WS%02X%02X%02X res=%d\n", + pr_debug("%s WR%02X%02X%02X res=%d\n", st->hw_s->name, i2c_addr, reg, data, res); if (res < 1) { if (res == 0) @@ -501,7 +493,9 @@ static int nvi_int_enable_wr(struct inv_gyro_state_s *inf, bool enable) err = inv_i2c_single_write(inf, inf->reg->int_enable, val); if (!err) { inf->hw.int_enable = val; - dev_dbg(&inf->i2c->dev, "%s: %x\n", __func__, val); + if (inf->dbg & NVI_DBG_SPEW_MSG) + dev_info(&inf->i2c->dev, "%s: %x\n", + __func__, val); } } return err; @@ -1130,12 +1124,13 @@ static int nvi_global_delay(struct inv_gyro_state_s *inf) /* set the limits */ if (delay_us < inf->chip_config.min_delay_us) delay_us = inf->chip_config.min_delay_us; - if (delay_us > MAX_FIFO_RATE) - delay_us = MAX_FIFO_RATE; + if (delay_us > NVI_DELAY_US_MAX) + delay_us = NVI_DELAY_US_MAX; /* program if new value */ if (delay_us != inf->sample_delay_us) { - if (inf->aux.dbg) - pr_info("%s %lu\n", __func__, delay_us); + if (inf->dbg) + dev_info(&inf->i2c->dev, "%s %lu\n", + __func__, delay_us); delay_us_old = inf->sample_delay_us; inf->sample_delay_us = delay_us; delay_us <<= 1; @@ -1190,10 +1185,10 @@ static void nvi_aux_dbg(struct inv_gyro_state_s *inf, char *tag, int val) u8 data[4]; int i; - if (!inf->aux.dbg) + if (!(inf->dbg & NVI_DBG_SPEW_AUX)) return; - pr_info("%s %s %d\n", __func__, tag, val); + dev_info(&inf->i2c->dev, "%s %s %d\n", __func__, tag, val); for (i = 0; i < AUX_PORT_MAX; i++) { inv_i2c_read(inf, (REG_I2C_SLV0_ADDR + (i * 3)), 3, data); inv_i2c_read(inf, (REG_I2C_SLV0_DO + i), 1, &data[3]); @@ -1657,7 +1652,7 @@ int nvi_mpu_dev_valid(struct nvi_mpu_port *nmp, u8 *data) inf = inf_local; if (inf != NULL) { - if (inf->aux.dbg) + if (inf->dbg & NVI_DBG_SPEW_AUX) pr_info("%s\n", __func__); } else { pr_debug("%s ERR -EAGAIN\n", __func__); @@ -1690,7 +1685,7 @@ int nvi_mpu_port_alloc(struct nvi_mpu_port *nmp) inf = inf_local; if (inf != NULL) { - if (inf->aux.dbg) + if (inf->dbg & NVI_DBG_SPEW_AUX) pr_info("%s\n", __func__); } else { pr_debug("%s ERR -EAGAIN\n", __func__); @@ -1722,7 +1717,7 @@ int nvi_mpu_port_free(int port) inf = inf_local; if (inf != NULL) { - if (inf->aux.dbg) + if (inf->dbg & NVI_DBG_SPEW_AUX) pr_info("%s port %d\n", __func__, port); } else { pr_debug("%s port %d ERR -EAGAIN\n", __func__, port); @@ -1748,7 +1743,7 @@ int nvi_mpu_enable(int port, bool enable, bool fifo_enable) inf = inf_local; if (inf != NULL) { - if (inf->aux.dbg) + if (inf->dbg & NVI_DBG_SPEW_AUX) pr_info("%s port %d: %x\n", __func__, port, enable); } else { pr_debug("%s port %d: %x ERR -EAGAIN\n", @@ -1775,7 +1770,7 @@ int nvi_mpu_delay_ms(int port, u8 delay_ms) inf = inf_local; if (inf != NULL) { - if (inf->aux.dbg) + if (inf->dbg & NVI_DBG_SPEW_AUX) pr_info("%s port %d: %u\n", __func__, port, delay_ms); } else { pr_debug("%s port %d: %u ERR -EAGAIN\n", @@ -1805,7 +1800,7 @@ int nvi_mpu_delay_us(int port, unsigned long delay_us) inf = inf_local; if (inf != NULL) { - if (inf->aux.dbg) + if (inf->dbg & NVI_DBG_SPEW_AUX) pr_info("%s port %d: %lu\n", __func__, port, delay_us); } else { pr_debug("%s port %d: %lu ERR -EAGAIN\n", @@ -1858,7 +1853,7 @@ int nvi_mpu_bypass_request(bool enable) inf = inf_local; if (inf != NULL) { - if (inf->aux.dbg) + if (inf->dbg & NVI_DBG_SPEW_AUX) pr_info("%s\n", __func__); } else { pr_debug("%s ERR -EAGAIN\n", __func__); @@ -1883,7 +1878,7 @@ int nvi_mpu_bypass_release(void) inf = inf_local; if (inf != NULL) { - if (inf->aux.dbg) + if (inf->dbg & NVI_DBG_SPEW_AUX) pr_info("%s\n", __func__); } else { pr_debug("%s\n", __func__); @@ -2020,17 +2015,17 @@ static ssize_t nvi_gyro_enable_store(struct device *dev, return count; } -ssize_t nvi_gyro_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t nvi_gyro_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct inv_gyro_state_s *inf = dev_get_drvdata(dev); return sprintf(buf, "%u\n", inf->chip_config.gyro_enable); } -ssize_t nvi_gyro_fifo_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t nvi_gyro_fifo_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct inv_gyro_state_s *inf; unsigned char fifo_enable; @@ -2060,8 +2055,9 @@ ssize_t nvi_gyro_fifo_enable_store(struct device *dev, return count; } -ssize_t nvi_gyro_fifo_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t nvi_gyro_fifo_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct inv_gyro_state_s *inf = dev_get_drvdata(dev); @@ -2185,7 +2181,7 @@ static ssize_t nvi_gyro_max_range_store(struct device *dev, return count; } -ssize_t nvi_gyro_max_range_show(struct device *dev, +static ssize_t nvi_gyro_max_range_show(struct device *dev, struct device_attribute *attr, char *buf) { struct inv_gyro_state_s *inf = dev_get_drvdata(dev); @@ -2321,8 +2317,8 @@ static ssize_t nvi_accl_delay_store(struct device *dev, return count; } -ssize_t nvi_accl_delay_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t nvi_accl_delay_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct inv_gyro_state_s *inf; @@ -2411,8 +2407,8 @@ static ssize_t nvi_accl_max_range_store(struct device *dev, return count; } -ssize_t nvi_accl_max_range_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t nvi_accl_max_range_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct inv_gyro_state_s *inf = dev_get_drvdata(dev); unsigned int range; @@ -2437,6 +2433,8 @@ static ssize_t nvi_lpa_delay_enable_store(struct device *dev, if (err) return err; + if (lpa_delay_us > NVI_DELAY_US_MAX) + lpa_delay_us = NVI_DELAY_US_MAX; dev_dbg(&inf->i2c->dev, "%s: %lu\n", __func__, lpa_delay_us); mutex_lock(&inf->mutex); inf->chip_config.lpa_delay_us = lpa_delay_us; @@ -2857,17 +2855,17 @@ static ssize_t nvi_temp_enable_store(struct device *dev, return count; } -ssize_t nvi_temp_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t nvi_temp_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct inv_gyro_state_s *inf = dev_get_drvdata(dev); return sprintf(buf, "%u\n", inf->chip_config.temp_enable); } -ssize_t nvi_temp_fifo_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t nvi_temp_fifo_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct inv_gyro_state_s *inf; unsigned char fifo_enable; @@ -2902,8 +2900,9 @@ ssize_t nvi_temp_fifo_enable_store(struct device *dev, return count; } -ssize_t nvi_temp_fifo_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t nvi_temp_fifo_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct inv_gyro_state_s *inf = dev_get_drvdata(dev); @@ -3129,216 +3128,117 @@ static ssize_t inv_power_state_show(struct device *dev, return sprintf(buf, "1\n"); } -#if DEBUG_SYSFS_INTERFACE -static ssize_t nvi_dbg_i2c_addr_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct inv_gyro_state_s *inf; - u16 dbg_i2c_addr; - int err; - - inf = dev_get_drvdata(dev); - err = kstrtou16(buf, 16, &dbg_i2c_addr); - if (err) - return -EINVAL; - - inf->dbg_i2c_addr = dbg_i2c_addr; - return count; -} - -static ssize_t nvi_dbg_i2c_addr_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct inv_gyro_state_s *inf; - ssize_t ret = 0; - u16 dbg_i2c_addr; - - inf = dev_get_drvdata(dev); - if (inf->dbg_i2c_addr) - dbg_i2c_addr = inf->dbg_i2c_addr; - else - dbg_i2c_addr = inf->i2c->addr; - ret += sprintf(buf + ret, "%#2x\n", dbg_i2c_addr); - return ret; -} - -static ssize_t nvi_dbg_reg_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static u16 nvi_report_accl(struct inv_gyro_state_s *inf, u8 *data, s64 ts) { - struct inv_gyro_state_s *inf; - u8 dbg_reg; - int err; - - inf = dev_get_drvdata(dev); - err = kstrtou8(buf, 16, &dbg_reg); - if (err) - return -EINVAL; - - inf->dbg_reg = dbg_reg; - return count; -} - -static ssize_t nvi_dbg_reg_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct inv_gyro_state_s *inf; - ssize_t ret = 0; - - inf = dev_get_drvdata(dev); - ret += sprintf(buf + ret, "%#2x\n", inf->dbg_reg); - return ret; -} - -static ssize_t nvi_dbg_dat_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct inv_gyro_state_s *inf; - u16 dbg_i2c_addr; - u8 dbg_dat; - int err; - - inf = dev_get_drvdata(dev); - err = kstrtou8(buf, 16, &dbg_dat); - if (err) - return -EINVAL; - - if (inf->dbg_i2c_addr) - dbg_i2c_addr = inf->dbg_i2c_addr; - else - dbg_i2c_addr = inf->i2c->addr; - err = inv_i2c_single_write_base(inf, dbg_i2c_addr, - inf->dbg_reg, dbg_dat); - pr_info("%s dev=%x reg=%x data=%x err=%d\n", - __func__, dbg_i2c_addr, inf->dbg_reg, dbg_dat, err); - return count; -} - -static ssize_t nvi_dbg_dat_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct inv_gyro_state_s *inf; - ssize_t ret = 0; - u16 dbg_i2c_addr; - u8 dbg_dat = 0; - int err; - - inf = dev_get_drvdata(dev); - if (inf->dbg_i2c_addr) - dbg_i2c_addr = inf->dbg_i2c_addr; - else - dbg_i2c_addr = inf->i2c->addr; - err = inv_i2c_read_base(inf, dbg_i2c_addr, inf->dbg_reg, 1, &dbg_dat); - ret += sprintf(buf + ret, "%s dev=%x reg=%x data=%x err=%d\n", - __func__, dbg_i2c_addr, inf->dbg_reg, dbg_dat, err); - return ret; -} - -static ssize_t nvi_dbg_aux_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct inv_gyro_state_s *inf; - unsigned int enable; - int err; - - inf = dev_get_drvdata(dev); - err = kstrtouint(buf, 10, &enable); - if (err) - return err; - - inf->aux.dbg = true; - nvi_aux_dbg(inf, "SNAPSHOT", 0); - if (enable) - inf->aux.dbg = true; - else - inf->aux.dbg = false; - return count; -} - -static ssize_t nvi_dbg_aux_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct inv_gyro_state_s *inf = dev_get_drvdata(dev); - - return sprintf(buf, "%x\n", inf->aux.dbg); -} -#endif /* DEBUG_SYSFS_INTERFACE */ - - -static u16 nvi_report_accl(struct inv_gyro_state_s *inf, u8 *data) -{ - u16 val[3]; - u16 buf_index; + s16 val[3]; + s16 raw[3]; + u16 buf_i; + unsigned int i; if (inf->chip_type == INV_MPU3050) { - if (inf->mpu_slave != NULL) - inf->mpu_slave->combine_data(data, val); + if (inf->mpu_slave != NULL) { + inf->mpu_slave->combine_data(data, raw); + for (i = 0; i < 3; i++) + val[i] = raw[i]; + } else { + return 0; + } } else { - val[0] = ((data[0] << 8) | data[1]) * inf->chip_info.multi; - val[1] = ((data[2] << 8) | data[3]) * inf->chip_info.multi; - val[2] = ((data[4] << 8) | data[5]) * inf->chip_info.multi; + raw[AXIS_X] = be16_to_cpup((__be16 *)&data[0]); + raw[AXIS_Y] = be16_to_cpup((__be16 *)&data[2]); + raw[AXIS_Z] = be16_to_cpup((__be16 *)&data[4]); + val[AXIS_X] = raw[AXIS_X] * inf->chip_info.multi; + val[AXIS_Y] = raw[AXIS_Y] * inf->chip_info.multi; + val[AXIS_Z] = raw[AXIS_Z] * inf->chip_info.multi; } - buf_index = 0; + + buf_i = 0; if (!(inf->hw.pwr_mgmt_2 & BIT_STBY_XA)) { - input_report_rel(inf->idev, REL_RX, val[0]); - buf_index += 2; + input_report_rel(inf->idev, REL_RX, val[AXIS_X]); + buf_i += 2; + } else { + raw[AXIS_X] = 0; + val[AXIS_X] = 0; } if (!(inf->hw.pwr_mgmt_2 & BIT_STBY_YA)) { - input_report_rel(inf->idev, REL_RY, val[1]); - buf_index += 2; + input_report_rel(inf->idev, REL_RY, val[AXIS_Y]); + buf_i += 2; + } else { + raw[AXIS_Y] = 0; + val[AXIS_Y] = 0; } if (!(inf->hw.pwr_mgmt_2 & BIT_STBY_ZA)) { - input_report_rel(inf->idev, REL_RZ, val[2]); - buf_index += 2; + input_report_rel(inf->idev, REL_RZ, val[AXIS_Z]); + buf_i += 2; + } else { + raw[AXIS_Z] = 0; + val[AXIS_Z] = 0; } - return buf_index; + for (i = 0; i < 3; i++) { + inf->accl_raw[i] = raw[i]; + inf->accl[i] = val[i]; + } + if (inf->dbg & NVI_DBG_SPEW_ACCL_RAW) + dev_info(&inf->i2c->dev, "ACCL_RAW %d %d %d %lld\n", + raw[AXIS_X], raw[AXIS_Y], raw[AXIS_Z], ts); + if (inf->dbg & NVI_DBG_SPEW_ACCL) + dev_info(&inf->i2c->dev, "ACCL %d %d %d %lld\n", + val[AXIS_X], val[AXIS_Y], val[AXIS_Z], ts); + return buf_i; } static void nvi_report_temp(struct inv_gyro_state_s *inf, u8 *data, s64 ts) { mutex_lock(&inf->mutex_temp); - inf->temp_val = (data[0] << 8) | data[1]; + inf->temp_val = be16_to_cpup((__be16 *)data); inf->temp_ts = ts; + if (inf->dbg & NVI_DBG_SPEW_TEMP) + dev_info(&inf->i2c->dev, "TEMP %d %lld\n", inf->temp_val, ts); mutex_unlock(&inf->mutex_temp); } static u16 nvi_report_gyro(struct inv_gyro_state_s *inf, u8 *data, u8 mask, s64 ts) { - u16 val; - u16 buf_index; + s16 val[3]; + u16 buf_i; bool report; + unsigned int i; if (ts < inf->gyro_start_ts) report = false; else report = true; - buf_index = 0; + for (i = 0; i < 3; i++) + val[i] = 0; + buf_i = 0; if (mask & 4) { if (report && (!(inf->hw.pwr_mgmt_2 & BIT_STBY_XG))) { - val = (data[buf_index] << 8) | data[buf_index + 1]; - input_report_rel(inf->idev, REL_X, val); + val[AXIS_X] = be16_to_cpup((__be16 *)&data[buf_i]); + input_report_rel(inf->idev, REL_X, val[AXIS_X]); } - buf_index += 2; + buf_i += 2; } if (mask & 2) { if (report && (!(inf->hw.pwr_mgmt_2 & BIT_STBY_YG))) { - val = (data[buf_index] << 8) | data[buf_index + 1]; - input_report_rel(inf->idev, REL_Y, val); + val[AXIS_Y] = be16_to_cpup((__be16 *)&data[buf_i]); + input_report_rel(inf->idev, REL_Y, val[AXIS_Y]); } - buf_index += 2; + buf_i += 2; } if (mask & 1) { if (report && (!(inf->hw.pwr_mgmt_2 & BIT_STBY_ZG))) { - val = (data[buf_index] << 8) | data[buf_index + 1]; - input_report_rel(inf->idev, REL_Z, val); + val[AXIS_Z] = be16_to_cpup((__be16 *)&data[buf_i]); + input_report_rel(inf->idev, REL_Z, val[AXIS_Z]); } - buf_index += 2; + buf_i += 2; } - return buf_index; + for (i = 0; i < 3; i++) + inf->gyro[i] = val[i]; + if (inf->dbg & NVI_DBG_SPEW_GYRO) + dev_info(&inf->i2c->dev, "GYRO %d %d %d %lld\n", + val[AXIS_X], val[AXIS_Y], val[AXIS_Z], ts); + return buf_i; } static void nvi_sync(struct inv_gyro_state_s *inf, s64 ts) @@ -3349,28 +3249,22 @@ static void nvi_sync(struct inv_gyro_state_s *inf, s64 ts) input_sync(inf->idev); } -static int nvi_accl_read(struct inv_gyro_state_s *inf) +static int nvi_accl_read(struct inv_gyro_state_s *inf, s64 ts) { u8 data[6]; int err; err = inv_i2c_read(inf, inf->reg->raw_accl, 6, data); if (!err) - err = nvi_report_accl(inf, data); + err = nvi_report_accl(inf, data, ts); return err; } static u16 nvi_fifo_read_accl(struct inv_gyro_state_s *inf, - u16 buf_index) + u16 buf_index, s64 ts) { if (inf->hw.fifo_en & inf->reg->accl_fifo_en) { - nvi_report_accl(inf, &inf->buf[buf_index]); -#if DEBUG_FIFO_DATA_SPEW - pr_info("%s %x %x %x\n", __func__, - (inf->buf[buf_index+0] << 8) | inf->buf[buf_index+1], - (inf->buf[buf_index+2] << 8) | inf->buf[buf_index+3], - (inf->buf[buf_index+4] << 8) | inf->buf[buf_index+5]); -#endif /* DEBUG_FIFO_DATA_SPEW */ + nvi_report_accl(inf, &inf->buf[buf_index], ts); buf_index += 6; } return buf_index; @@ -3383,22 +3277,12 @@ static u16 nvi_fifo_read_gyro(struct inv_gyro_state_s *inf, if (inf->hw.fifo_en & BIT_TEMP_FIFO_EN) { nvi_report_temp(inf, &inf->buf[buf_index], ts); -#if DEBUG_FIFO_DATA_SPEW - pr_info("%s %x\n", __func__, - (inf->buf[buf_index+0] << 8) | inf->buf[buf_index+1]); -#endif /* DEBUG_FIFO_DATA_SPEW */ buf_index += 2; } mask = inf->hw.fifo_en; mask &= (BIT_GYRO_XOUT | BIT_GYRO_YOUT | BIT_GYRO_ZOUT); mask >>= 4; if (mask) { -#if DEBUG_FIFO_DATA_SPEW - pr_info("%s %x %x %x\n", __func__, - (inf->buf[buf_index+0] << 8) | inf->buf[buf_index+1], - (inf->buf[buf_index+2] << 8) | inf->buf[buf_index+3], - (inf->buf[buf_index+4] << 8) | inf->buf[buf_index+5]); -#endif /* DEBUG_FIFO_DATA_SPEW */ buf_index += nvi_report_gyro(inf, &inf->buf[buf_index], mask, ts); } @@ -3420,7 +3304,7 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id) s64 delay; bool sync; unsigned int ts_len; - unsigned int sample_count; + unsigned int samples; unsigned int copied; unsigned int len; int i; @@ -3440,7 +3324,7 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id) pr_info("%s motion detect off\n", __func__); } ts = nvi_ts_ns(); - err = nvi_accl_read(inf); + err = nvi_accl_read(inf, ts); if (err < 0) goto nvi_irq_thread_exit; @@ -3458,7 +3342,7 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id) ts = nvi_ts_ns(); if (inf->chip_config.accl_enable && (!(inf->hw.fifo_en & inf->reg->accl_fifo_en))) { - err = nvi_accl_read(inf); + err = nvi_accl_read(inf, ts); if (err > 0) sync = true; } @@ -3504,7 +3388,7 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id) if (!fifo_sample_size) goto nvi_irq_thread_exit; - /* must get IRQ timestamps first for timestamp best-fit algorithm */ + /* must get IRQ timestamp len first for timestamp best-fit algorithm */ ts_len = kfifo_len(&inf->trigger.timestamps); err = inv_i2c_read(inf, inf->reg->fifo_count_h, 2, inf->buf); if (err) @@ -3527,7 +3411,7 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id) /* FIFO HW BUG WAR: * The MPU3050 will fire an IRQ on incomplete sampling of data * to the FIFO causing misalignment of data. The WAR is to - * simply wait for the next IRQ when this misalignment problem + * simply wait for the next IRQ. This misalignment problem * usually works itself out with the next data sample. * The safety net is a FIFO reset, should the problem not work * itself out by the time the FIFO threshold is reached. @@ -3543,34 +3427,20 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id) ts = inf->fifo_ts; delay = inf->sample_delay_us * 1000; - sample_count = (fifo_count / fifo_sample_size); - /* Ideally sample_count >= ts_len. If not, pull excess timestamps */ - if (sample_count < ts_len) { - len = ts_len - sample_count; - for (i = 0; i < len; i++) { - err = kfifo_to_user(&inf->trigger.timestamps, - &ts_irq, sizeof(ts_irq), &copied); - if (err) - goto nvi_irq_thread_exit_reset; - - ts_len--; - } - ts = ts_irq + delay; - dev_dbg(&inf->i2c->dev, "%s SYNC FIFO to TS %lld\n", - __func__, ts); - } -#if DEBUG_FIFO_DATA_SPEW - pr_info("fifo_count=%u sample_size=%u fifo_align=%u sample_count=%u\n", - fifo_count, fifo_sample_size, fifo_align, sample_count); -#endif /* DEBUG_FIFO_DATA_SPEW */ + samples = (fifo_count / fifo_sample_size); + if (inf->dbg & NVI_DBG_SPEW_FIFO) + dev_info(&inf->i2c->dev, + "fifo_count=%u sample_size=%u offset=%u samples=%u\n", + fifo_count, fifo_sample_size, fifo_align, samples); fifo_rd_n = 0; buf_index = 0; - while (sample_count) { + while (samples) { if (buf_index >= fifo_rd_n) { - fifo_rd_n = (ARRAY_SIZE(inf->buf) - fifo_align) / - fifo_sample_size; - if (sample_count < fifo_rd_n) - fifo_rd_n = sample_count; + fifo_rd_n = sizeof(inf->buf); + fifo_rd_n -= fifo_align; + fifo_rd_n /= fifo_sample_size; + if (samples < fifo_rd_n) + fifo_rd_n = samples; fifo_rd_n *= fifo_sample_size; fifo_rd_n += fifo_align; if (inf->chip_type == INV_MPU3050) @@ -3588,6 +3458,7 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id) } } } + if (ts_len) { len = ts_len; for (i = 0; i < len; i++) { @@ -3611,24 +3482,29 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id) break; } } + if ((inf->dbg & NVI_DBG_SPEW_FIFO) && (ts != ts_irq)) + dev_info(&inf->i2c->dev, + "%s TS=%lld != IRQ=%lld s=%u i=%u\n", + __func__, ts, ts_irq, samples, ts_len); + } else { + if (inf->dbg & NVI_DBG_SPEW_FIFO) + dev_info(&inf->i2c->dev, + "%s NO IRQ_TS TS=%lld s=%u\n", + __func__, ts, samples); } - if (ts != ts_irq) - dev_dbg(&inf->i2c->dev, "%s NOSYNC TS=%lld IRQ=%lld\n", - __func__, ts, ts_irq); if (inf->chip_type == INV_MPU3050) { buf_index = nvi_fifo_read_gyro(inf, buf_index, ts); - buf_index = nvi_fifo_read_accl(inf, buf_index); + buf_index = nvi_fifo_read_accl(inf, buf_index, ts); buf_index += 2; /* FIFO_FOOTER */ } else { - buf_index = nvi_fifo_read_accl(inf, buf_index); + buf_index = nvi_fifo_read_accl(inf, buf_index, ts); buf_index = nvi_fifo_read_gyro(inf, buf_index, ts); } nvi_sync(inf, ts); for (i = 0; i < AUX_PORT_SPECIAL; i++) { ap = &inf->aux.port[i]; - if ((inf->hw.i2c_slv_ctrl[i] & BIT_SLV_EN) && - (inf->hw.i2c_slv_addr[i] & BIT_I2C_READ) && - ap->fifo_en) { + if (ap->fifo_en && + (inf->hw.i2c_slv_ctrl[i] & BIT_SLV_EN)) { len = ap->nmp.ctrl & BITS_I2C_SLV_CTRL_LEN; if (ap->nmp.handler != NULL) ap->nmp.handler(&inf->buf[buf_index], @@ -3638,15 +3514,33 @@ static irqreturn_t nvi_irq_thread(int irq, void *dev_id) } } ts += delay; - sample_count--; + samples--; + } + if (ts_len) { + if (inf->dbg & NVI_DBG_SPEW_FIFO) + dev_info(&inf->i2c->dev, "%s SYNC TO IRQ_TS %lld\n", + __func__, ts); + for (i = 0; i < ts_len; i++) { + err = kfifo_to_user(&inf->trigger.timestamps, + &ts, sizeof(ts), &copied); + if (err) + goto nvi_irq_thread_exit_reset; + } } + inf->fifo_ts = ts; + return IRQ_HANDLED; + nvi_irq_thread_exit: + /* Ensure HW touched to clear IRQ */ + inv_i2c_read(inf, inf->reg->int_status, 1, inf->buf); return IRQ_HANDLED; nvi_irq_thread_exit_reset: - dev_dbg(&inf->i2c->dev, "%s fifo_count=%u fifo_sample_size=%u\n", - __func__, fifo_count, fifo_sample_size); + if (inf->dbg & NVI_DBG_SPEW_FIFO) + dev_info(&inf->i2c->dev, + "%s fifo_count=%u fifo_sample_size=%u\n", + __func__, fifo_count, fifo_sample_size); nvi_reset(inf, true, false); return IRQ_HANDLED; } @@ -3666,36 +3560,263 @@ static irqreturn_t nvi_irq_handler(int irq, void *dev_id) return IRQ_WAKE_THREAD; } -#ifdef CONFIG_PM -static int nvi_suspend(struct device *dev) +static ssize_t nvi_data_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct inv_gyro_state_s *inf; + unsigned int data_info; int err; inf = dev_get_drvdata(dev); - inf->suspend = true; - err = nvi_pm(inf, NVI_PM_OFF_FORCE); + err = kstrtouint(buf, 10, &data_info); if (err) - dev_err(dev, "%s ERR\n", __func__); - dev_info(dev, "%s done\n", __func__); - return 0; + return -EINVAL; + + if (data_info >= NVI_DATA_INFO_LIMIT_MAX) + return -EINVAL; + + dev_dbg(&inf->i2c->dev, "%s %u\n", __func__, data_info); + inf->data_info = data_info; + switch (data_info) { + case NVI_DATA_INFO_DATA: + inf->dbg = 0; + break; + + case NVI_DATA_INFO_DBG: + inf->dbg ^= NVI_DBG_SPEW_MSG; + break; + + case NVI_DATA_INFO_AUX_SPEW: + inf->dbg ^= NVI_DBG_SPEW_AUX; + nvi_aux_dbg(inf, "SNAPSHOT", 0); + break; + + case NVI_DATA_INFO_GYRO_SPEW: + inf->dbg ^= NVI_DBG_SPEW_GYRO; + break; + + case NVI_DATA_INFO_TEMP_SPEW: + inf->dbg ^= NVI_DBG_SPEW_TEMP; + break; + + case NVI_DATA_INFO_ACCL_SPEW: + inf->dbg ^= NVI_DBG_SPEW_ACCL; + break; + + case NVI_DATA_INFO_ACCL_RAW_SPEW: + inf->dbg ^= NVI_DBG_SPEW_ACCL_RAW; + break; + + case NVI_DATA_INFO_FIFO_SPEW: + inf->dbg ^= NVI_DBG_SPEW_FIFO; + break; + + default: + break; + } + + return count; } -static int nvi_resume(struct device *dev) +static ssize_t nvi_data_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct inv_gyro_state_s *inf; + ssize_t t = 0; + enum NVI_DATA_INFO data_info; + char data; + unsigned int i; + int err; inf = dev_get_drvdata(dev); - inf->suspend = false; - dev_info(dev, "%s done\n", __func__); - return 0; + data_info = inf->data_info; + inf->data_info = NVI_DATA_INFO_DATA; + switch (data_info) { + case NVI_DATA_INFO_DATA: + t = sprintf(buf, "ACCL_RAW %hd %hd %hd\n", + inf->accl_raw[AXIS_X], + inf->accl_raw[AXIS_Y], + inf->accl_raw[AXIS_Z]); + t += sprintf(buf + t, "ACCL %hd %hd %hd\n", + inf->accl[AXIS_X], + inf->accl[AXIS_Y], + inf->accl[AXIS_Z]); + t += sprintf(buf + t, "GYRO %hd %hd %hd\n", + inf->gyro[AXIS_X], + inf->gyro[AXIS_Y], + inf->gyro[AXIS_Z]); + mutex_lock(&inf->mutex_temp); + t += sprintf(buf + t, "TEMP %hd %lld\n", + inf->temp_val, + inf->temp_ts); + mutex_unlock(&inf->mutex_temp); + return t; + + case NVI_DATA_INFO_VER: + return sprintf(buf, "version=%u\n", NVI_VERSION); + + case NVI_DATA_INFO_RESET: + err = nvi_pm(inf, NVI_PM_OFF_FORCE); + err |= nvi_pm(inf, NVI_PM_AUTO); + if (err) + return sprintf(buf, "reset ERR\n"); + else + return sprintf(buf, "reset done\n"); + + case NVI_DATA_INFO_REGS: + for (i = 0; i < inf->hw_s->num_reg; i++) { + if (i == inf->reg->fifo_r_w) + data = 0; + else + inv_i2c_read(inf, i, 1, &data); + t += sprintf(buf + t, "%#2x=%#2x\n", i, data); + } + return t; + + case NVI_DATA_INFO_DBG: + return sprintf(buf, "DBG spew=%x\n", + !!(inf->dbg & NVI_DBG_SPEW_MSG)); + + case NVI_DATA_INFO_AUX_SPEW: + return sprintf(buf, "AUX spew=%x\n", + !!(inf->dbg & NVI_DBG_SPEW_AUX)); + + case NVI_DATA_INFO_GYRO_SPEW: + return sprintf(buf, "GYRO spew=%x\n", + !!(inf->dbg & NVI_DBG_SPEW_GYRO)); + + case NVI_DATA_INFO_TEMP_SPEW: + return sprintf(buf, "TEMP spew=%x\n", + !!(inf->dbg & NVI_DBG_SPEW_TEMP)); + + case NVI_DATA_INFO_ACCL_SPEW: + return sprintf(buf, "ACCL spew=%x\n", + !!(inf->dbg & NVI_DBG_SPEW_ACCL)); + + case NVI_DATA_INFO_ACCL_RAW_SPEW: + return sprintf(buf, "ACCL_RAW spew=%x\n", + !!(inf->dbg & NVI_DBG_SPEW_ACCL_RAW)); + + case NVI_DATA_INFO_FIFO_SPEW: + return sprintf(buf, "FIFO spew=%x\n", + !!(inf->dbg & NVI_DBG_SPEW_FIFO)); + + default: + break; + } + + return -EINVAL; } -static const struct dev_pm_ops nvi_pm_ops = { - .suspend = nvi_suspend, - .resume = nvi_resume, -}; -#endif /* CONFIG_PM */ +#if DEBUG_SYSFS_INTERFACE +static ssize_t nvi_dbg_i2c_addr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct inv_gyro_state_s *inf; + u16 dbg_i2c_addr; + int err; + + inf = dev_get_drvdata(dev); + err = kstrtou16(buf, 16, &dbg_i2c_addr); + if (err) + return -EINVAL; + + inf->dbg_i2c_addr = dbg_i2c_addr; + return count; +} + +static ssize_t nvi_dbg_i2c_addr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct inv_gyro_state_s *inf; + ssize_t ret = 0; + u16 dbg_i2c_addr; + + inf = dev_get_drvdata(dev); + if (inf->dbg_i2c_addr) + dbg_i2c_addr = inf->dbg_i2c_addr; + else + dbg_i2c_addr = inf->i2c->addr; + ret += sprintf(buf + ret, "%#2x\n", dbg_i2c_addr); + return ret; +} + +static ssize_t nvi_dbg_reg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct inv_gyro_state_s *inf; + u8 dbg_reg; + int err; + + inf = dev_get_drvdata(dev); + err = kstrtou8(buf, 16, &dbg_reg); + if (err) + return -EINVAL; + + inf->dbg_reg = dbg_reg; + return count; +} + +static ssize_t nvi_dbg_reg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct inv_gyro_state_s *inf; + ssize_t ret = 0; + + inf = dev_get_drvdata(dev); + ret += sprintf(buf + ret, "%#2x\n", inf->dbg_reg); + return ret; +} + +static ssize_t nvi_dbg_dat_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct inv_gyro_state_s *inf; + u16 dbg_i2c_addr; + u8 dbg_dat; + int err; + + inf = dev_get_drvdata(dev); + err = kstrtou8(buf, 16, &dbg_dat); + if (err) + return -EINVAL; + + if (inf->dbg_i2c_addr) + dbg_i2c_addr = inf->dbg_i2c_addr; + else + dbg_i2c_addr = inf->i2c->addr; + err = inv_i2c_single_write_base(inf, dbg_i2c_addr, + inf->dbg_reg, dbg_dat); + pr_info("%s dev=%x reg=%x data=%x err=%d\n", + __func__, dbg_i2c_addr, inf->dbg_reg, dbg_dat, err); + return count; +} + +static ssize_t nvi_dbg_dat_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct inv_gyro_state_s *inf; + ssize_t ret = 0; + u16 dbg_i2c_addr; + u8 dbg_dat = 0; + int err; + + inf = dev_get_drvdata(dev); + if (inf->dbg_i2c_addr) + dbg_i2c_addr = inf->dbg_i2c_addr; + else + dbg_i2c_addr = inf->i2c->addr; + err = inv_i2c_read_base(inf, dbg_i2c_addr, inf->dbg_reg, 1, &dbg_dat); + ret += sprintf(buf + ret, "%s dev=%x reg=%x data=%x err=%d\n", + __func__, dbg_i2c_addr, inf->dbg_reg, dbg_dat, err); + return ret; +} +#endif /* DEBUG_SYSFS_INTERFACE */ static DEVICE_ATTR(gyro_enable, S_IRUGO | S_IWUSR | S_IWGRP, nvi_gyro_enable_show, nvi_gyro_enable_store); @@ -3759,14 +3880,14 @@ static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP, nvi_enable_show, nvi_enable_store); static DEVICE_ATTR(self_test, S_IRUGO, inv_self_test_show, NULL); +static DEVICE_ATTR(data, S_IRUGO | S_IWUSR | S_IWGRP, + nvi_data_show, nvi_data_store); static DEVICE_ATTR(dbg_reg, S_IRUGO | S_IWUSR | S_IWGRP, nvi_dbg_reg_show, nvi_dbg_reg_store); static DEVICE_ATTR(dbg_dat, S_IRUGO | S_IWUSR | S_IWGRP, nvi_dbg_dat_show, nvi_dbg_dat_store); static DEVICE_ATTR(dbg_i2c_addr, S_IRUGO | S_IWUSR | S_IWGRP, nvi_dbg_i2c_addr_show, nvi_dbg_i2c_addr_store); -static DEVICE_ATTR(dbg_aux, S_IRUGO | S_IWUSR | S_IWGRP, - nvi_dbg_aux_show, nvi_dbg_aux_store); static DEVICE_ATTR(reg_dump, S_IRUGO, inv_reg_dump_show, NULL); static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR | S_IWGRP, @@ -3818,9 +3939,7 @@ static struct device_attribute *inv_mpu6050_attributes[] = { &dev_attr_bypass_timeout_ms, &dev_attr_min_delay_us, &dev_attr_fifo_threshold, -#if DEBUG_SYSFS_INTERFACE - &dev_attr_dbg_aux, -#endif /* DEBUG_SYSFS_INTERFACE */ + &dev_attr_data, NULL }; @@ -4131,12 +4250,46 @@ static int nvi_dev_init(struct inv_gyro_state_s *inf, return err; } +static int nvi_suspend(struct device *dev) +{ + struct inv_gyro_state_s *inf; + int err; + + inf = dev_get_drvdata(dev); + inf->suspend = true; + disable_irq(inf->i2c->irq); + err = nvi_pm(inf, NVI_PM_OFF_FORCE); + if (err) + dev_err(dev, "%s ERR\n", __func__); + if (inf->dbg & NVI_DBG_SPEW_MSG) + dev_info(dev, "%s done\n", __func__); + return 0; +} + +static int nvi_resume(struct device *dev) +{ + struct inv_gyro_state_s *inf; + + inf = dev_get_drvdata(dev); + inf->suspend = false; + enable_irq(inf->i2c->irq); + if (inf->dbg & NVI_DBG_SPEW_MSG) + dev_info(dev, "%s done\n", __func__); + return 0; +} + +static const struct dev_pm_ops nvi_pm_ops = { + .suspend = nvi_suspend, + .resume = nvi_resume, +}; + static void nvi_shutdown(struct i2c_client *client) { struct inv_gyro_state_s *inf; int i; inf = i2c_get_clientdata(client); + disable_irq(inf->i2c->irq); if (inf != NULL) { for (i = 0; i < AUX_PORT_SPECIAL; i++) { if (inf->aux.port[i].nmp.shutdown_bypass) { diff --git a/drivers/input/misc/mpu/inv_gyro.h b/drivers/input/misc/mpu/inv_gyro.h index d4b333d45764..17df1f406e37 100644 --- a/drivers/input/misc/mpu/inv_gyro.h +++ b/drivers/input/misc/mpu/inv_gyro.h @@ -63,6 +63,33 @@ #define NVI_PM_ON (6) #define NVI_PM_ON_FULL (7) +#define AXIS_X (0) +#define AXIS_Y (1) +#define AXIS_Z (2) + +#define NVI_DBG_SPEW_MSG (1 << 0) +#define NVI_DBG_SPEW_AUX (1 << 1) +#define NVI_DBG_SPEW_GYRO (1 << 2) +#define NVI_DBG_SPEW_TEMP (1 << 3) +#define NVI_DBG_SPEW_ACCL (1 << 4) +#define NVI_DBG_SPEW_ACCL_RAW (1 << 5) +#define NVI_DBG_SPEW_FIFO (1 << 6) + +enum NVI_DATA_INFO { + NVI_DATA_INFO_DATA = 0, + NVI_DATA_INFO_VER, + NVI_DATA_INFO_RESET, + NVI_DATA_INFO_REGS, + NVI_DATA_INFO_DBG, + NVI_DATA_INFO_AUX_SPEW, + NVI_DATA_INFO_GYRO_SPEW, + NVI_DATA_INFO_TEMP_SPEW, + NVI_DATA_INFO_ACCL_SPEW, + NVI_DATA_INFO_ACCL_RAW_SPEW, + NVI_DATA_INFO_FIFO_SPEW, + NVI_DATA_INFO_LIMIT_MAX, +}; + /** * struct inv_reg_map_s - Notable slave registers. * @who_am_i: Upper 6 bits of the device's slave address. @@ -314,7 +341,6 @@ struct aux_ports { bool reset_fifo; bool enable; bool en3050; - bool dbg; }; struct nvi_hw { @@ -397,7 +423,6 @@ struct inv_gyro_state_s { struct mpu_platform_data plat_data; struct inv_mpu_slave *mpu_slave; struct regulator_bulk_data vreg[2]; - bool fifo_reset_3050; unsigned char i2c_addr; unsigned char sample_divider; unsigned char fifo_divider; @@ -412,15 +437,21 @@ struct inv_gyro_state_s { u16 fifo_sample_size; bool shutdown; bool suspend; + bool fifo_reset_3050; unsigned int mot_cnt; - short temp_val; - s64 temp_ts; s64 fifo_ts; s64 gyro_start_ts; + unsigned int data_info; + unsigned int dbg; #if DEBUG_SYSFS_INTERFACE u16 dbg_i2c_addr; u8 dbg_reg; #endif /* DEBUG_SYSFS_INTERFACE */ + s64 temp_ts; + s16 temp_val; + s16 gyro[3]; + s16 accl[3]; + s16 accl_raw[3]; u8 buf[NVI_FIFO_SAMPLE_SIZE_MAX * 2]; /* (* 2)=FIFO OVERFLOW OFFSET */ }; @@ -566,7 +597,6 @@ struct inv_mpu_slave { #define MPU6500_ID (0x70) #define MPU6500_PRODUCT_REVISION (1) #define MPU6500_MEM_REV_ADDR (0x17) -#define MPU6500_REV (2) #define MPU9250_ID (0x71) #define BIT_PRFTCH_EN 0x40 diff --git a/drivers/input/misc/mpu/inv_gyro_misc.c b/drivers/input/misc/mpu/inv_gyro_misc.c index bd5c37a12256..39b51a5cf400 100644 --- a/drivers/input/misc/mpu/inv_gyro_misc.c +++ b/drivers/input/misc/mpu/inv_gyro_misc.c @@ -382,8 +382,6 @@ int inv_get_silicon_rev_mpu6500(struct inv_gyro_state_s *st) } if (result) return result; - if (sw_rev > MPU6500_REV) - return -EINVAL; /* these values are place holders and not real values */ chip_info->product_id = MPU6500_PRODUCT_REVISION; diff --git a/drivers/input/misc/pressure/bmp180.c b/drivers/input/misc/pressure/bmp180.c index 5c40f8d2575d..5f46ce4d518d 100644 --- a/drivers/input/misc/pressure/bmp180.c +++ b/drivers/input/misc/pressure/bmp180.c @@ -18,10 +18,10 @@ #include <linux/delay.h> #include <linux/workqueue.h> #include <linux/regulator/consumer.h> -#include <asm/div64.h> #include <linux/mpu.h> +#define BMP_VERSION (23) #define BMP180_RANGE_DFLT (0) /* until OSS is supported in the pressure calculation, this defaults to 5 */ #define BMP280_RANGE_DFLT (5) @@ -29,13 +29,12 @@ #define BMPX80_NAME "bmpX80" #define BMP180_NAME "bmp180" #define BMP280_NAME "bmp280" -#define BMP180_I2C_ADDR0 (0x76) -#define BMP180_I2C_ADDR1 (0x77) +#define BMP280_I2C_ADDR0 (0x76) +#define BMPX80_I2C_ADDR1 (0x77) #define BMPX80_HW_DELAY_POR_MS (10) -#define BMP180_POLL_DELAY_MS_DFLT (200) -#define BMP180_MPU_RETRY_COUNT (20) -#define BMP180_MPU_RETRY_DELAY_MS (100) -#define BMP180_ERR_CNT_MAX (20) +#define BMPX80_POLL_DELAY_MS_DFLT (200) +#define BMPX80_MPU_RETRY_COUNT (50) +#define BMPX80_MPU_RETRY_DELAY_MS (20) /* sampling delays */ #define BMP180_DELAY_MS_ULP (5) #define BMP180_DELAY_MS_ST (8) @@ -49,7 +48,7 @@ /* input poll values*/ #define BMP180_INPUT_RESOLUTION (1) #define BMP180_INPUT_DIVISOR (100) -#define BMP280_INPUT_DIVISOR (256) +#define BMP280_INPUT_DIVISOR (100) #define BMP180_INPUT_DELAY_MS_MIN (BMP180_DELAY_MS_UHIGH_RES) #define BMP180_INPUT_POWER_UA (12) #define BMP180_PRESSURE_MIN (30000) @@ -120,22 +119,30 @@ #define WR (0) #define RD (1) +#define BMP_DBG_SPEW_MSG (1 << 0) +#define BMP_DBG_SPEW_PRESSURE (1 << 1) +#define BMP_DBG_SPEW_TEMPERATURE (1 << 2) +#define BMP_DBG_SPEW_PRESSURE_RAW (1 << 3) +#define BMP_DBG_SPEW_TEMPERATURE_RAW (1 << 4) + enum BMP_DATA_INFO { - BMP_DATA_INFO_PRESSURE = 0, - BMP_DATA_INFO_TEMPERATURE, - BMP_DATA_INFO_PRESSURE_RAW, - BMP_DATA_INFO_TEMPERATURE_RAW, - BMP_DATA_INFO_TEMPERATURE_FINE, - BMP_DATA_INFO_CALIBRATION, + BMP_DATA_INFO_DATA = 0, + BMP_DATA_INFO_VER, BMP_DATA_INFO_RESET, - BMP_DATA_INFO_REGISTERS, + BMP_DATA_INFO_REGS, + BMP_DATA_INFO_DBG, + BMP_DATA_INFO_PRESSURE_SPEW, + BMP_DATA_INFO_TEMPERATURE_SPEW, + BMP_DATA_INFO_PRESSURE_RAW_SPEW, + BMP_DATA_INFO_TEMPERATURE_RAW_SPEW, BMP_DATA_INFO_LIMIT_MAX, }; - static u8 bmp_ids[] = { BMPX80_REG_ID_BMP180, BMPX80_REG_ID_BMP280, + 0x57, + 0x58, }; /* regulator names in order of powering on */ @@ -210,6 +217,7 @@ struct bmp_inf { unsigned int range_i; /* oversampling value */ unsigned int resolution; /* report when new data outside this */ unsigned int data_info; /* data info to return */ + unsigned int dbg; /* debug switches */ unsigned int dev_id; /* device ID */ bool use_mpu; /* if device behind MPU */ bool initd; /* set if initialized */ @@ -219,10 +227,10 @@ struct bmp_inf { bool port_en[2]; /* enable status of MPU write port */ int port_id[2]; /* MPU port ID */ u8 data_out; /* write value to mode register */ - long UT; /* uncompensated temperature */ - long UP; /* uncompensated pressure */ + s32 UT; /* uncompensated temperature */ + s32 UP; /* uncompensated pressure */ s32 t_fine; /* temperature used in pressure calc */ - long temperature; /* true temperature */ + s32 temperature; /* true temperature */ int pressure; /* true pressure hPa/100 Pa/1 mBar */ }; @@ -380,10 +388,10 @@ static int bmp_pm(struct bmp_inf *inf, bool enable) if (err > 0) err = 0; if (err) - dev_err(&inf->i2c->dev, "%s enable=%x ERR=%d\n", + dev_err(&inf->i2c->dev, "%s pwr=%x ERR=%d\n", __func__, enable, err); else - dev_dbg(&inf->i2c->dev, "%s enable=%x\n", + dev_dbg(&inf->i2c->dev, "%s pwr=%x\n", __func__, enable); return err; } @@ -428,7 +436,7 @@ static int bmp_pm_init(struct bmp_inf *inf) inf->port_id[WR] = -1; inf->port_id[RD] = -1; inf->resolution = 0; - inf->poll_delay_us = (BMP180_POLL_DELAY_MS_DFLT * 1000); + inf->poll_delay_us = (BMPX80_POLL_DELAY_MS_DFLT * 1000); bmp_vreg_init(inf); err = bmp_pm(inf, true); return err; @@ -440,12 +448,12 @@ static int bmp_nvi_mpu_bypass_request(struct bmp_inf *inf) int err = 0; if (inf->use_mpu) { - for (i = 0; i < BMP180_MPU_RETRY_COUNT; i++) { + for (i = 0; i < BMPX80_MPU_RETRY_COUNT; i++) { err = nvi_mpu_bypass_request(true); if ((!err) || (err == -EPERM)) break; - mdelay(BMP180_MPU_RETRY_DELAY_MS); + msleep(BMPX80_MPU_RETRY_DELAY_MS); } if (err == -EPERM) err = 0; @@ -555,7 +563,14 @@ static int bmp_mode_wr(struct bmp_inf *inf, bool reset, bool enable) u8 mode_new; int err = 0; - if (inf->dev_id == BMPX80_REG_ID_BMP280) { + if (inf->dev_id == BMPX80_REG_ID_BMP180) { + if (enable) { + mode_new = inf->range_i << BMP180_REG_CTRL_OSS; + mode_new |= BMP180_REG_CTRL_MODE_TEMP; + } else { + mode_new = 0; + } + } else { if (enable) { mode_new = inf->range_i + 1; mode_new = (mode_new << BMP280_REG_CTRL_OSRS_T) | @@ -564,13 +579,6 @@ static int bmp_mode_wr(struct bmp_inf *inf, bool reset, bool enable) } else { mode_new = BMP280_REG_CTRL_MODE_SLEEP; } - } else { - if (enable) { - mode_new = inf->range_i << BMP180_REG_CTRL_OSS; - mode_new |= BMP180_REG_CTRL_MODE_TEMP; - } else { - mode_new = 0; - } } if ((mode_new == inf->data_out) && (!reset)) return err; @@ -628,6 +636,9 @@ static int bmp_delay(struct bmp_inf *inf, if (delay_us < (inf->hal->bmp_delay_ms_tbl[inf->range_i] * 1000)) delay_us = (inf->hal->bmp_delay_ms_tbl[inf->range_i] * 1000); if (delay_us != inf->poll_delay_us) { + if (inf->dbg & BMP_DBG_SPEW_MSG) + dev_info(&inf->i2c->dev, "%s: %u\n", + __func__, delay_us); err = 0; if (inf->use_mpu) err = nvi_mpu_delay_us(inf->port_id[RD], @@ -652,6 +663,14 @@ static s64 bmp_timestamp_ns(void) static void bmp_report(struct bmp_inf *inf, s64 ts) { + if (inf->dbg & BMP_DBG_SPEW_PRESSURE_RAW) + dev_info(&inf->i2c->dev, "pr %d %lld\n", inf->UP, ts); + if (inf->dbg & BMP_DBG_SPEW_PRESSURE) + dev_info(&inf->i2c->dev, "p %d %lld\n", inf->pressure, ts); + if (inf->dbg & BMP_DBG_SPEW_TEMPERATURE_RAW) + dev_info(&inf->i2c->dev, "tr %d %lld\n", inf->UT, ts); + if (inf->dbg & BMP_DBG_SPEW_TEMPERATURE) + dev_info(&inf->i2c->dev, "t %d %lld\n", inf->temperature, ts); input_report_abs(inf->idev, ABS_PRESSURE, inf->pressure); input_sync(inf->idev); } @@ -689,7 +708,7 @@ static void bmp180_calc(struct bmp_inf *inf) static int bmp180_read_sts(struct bmp_inf *inf, u8 *data) { - long val; + s32 val; int limit_lo; int limit_hi; int pres; @@ -697,8 +716,7 @@ static int bmp180_read_sts(struct bmp_inf *inf, u8 *data) int err = 0; /* BMP180_REG_CTRL_SCO is 0 when data is ready */ - val = data[0] & (1 << BMP180_REG_CTRL_SCO); - if (!val) { + if (!(data[0] & (1 << BMP180_REG_CTRL_SCO))) { err = -1; if (data[0] == 0x0A) { /* temperature */ inf->UT = ((data[2] << 8) + data[3]); @@ -719,8 +737,8 @@ static int bmp180_read_sts(struct bmp_inf *inf, u8 *data) if (inf->resolution) { limit_lo = pres; limit_hi = pres; - limit_lo -= (inf->resolution / 2); - limit_hi += (inf->resolution / 2); + limit_lo -= (inf->resolution >> 1); + limit_hi += (inf->resolution >> 1); if (limit_lo < 0) limit_lo = 0; if ((pres < limit_lo) || (pres > limit_hi)) @@ -754,7 +772,7 @@ static int bmp180_read(struct bmp_inf *inf) err = bmp180_read_sts(inf, data); if (err > 0) { - timestamp2 = (timestamp2 - timestamp1) / 2; + timestamp2 = (timestamp2 - timestamp1) >> 1; timestamp1 += timestamp2; bmp_report(inf, timestamp1); bmp_i2c_wr(inf, BMPX80_REG_CTRL, inf->data_out); @@ -787,68 +805,96 @@ static void bmp280_calc_temp(struct bmp_inf *inf) s32 var1; s32 var2; - adc_T = (s32)inf->UT; - adc_T <<= inf->range_i; - adc_T >>= 4; - var1 = ((((adc_T >> 3) - ((s32)inf->rom.bmp280.dig_T1 << 1))) * - ((s32)inf->rom.bmp280.dig_T2)) >> 11; - var2 = (((((adc_T >> 4) - ((s32)inf->rom.bmp280.dig_T1)) * - ((adc_T >> 4) - ((s32)inf->rom.bmp280.dig_T1))) >> 12) * - ((s32)inf->rom.bmp280.dig_T3)) >> 14; + adc_T = inf->UT; + adc_T >>= (4 - inf->range_i); + var1 = adc_T >> 3; + var1 -= ((s32)inf->rom.bmp280.dig_T1 << 1); + var1 *= (s32)inf->rom.bmp280.dig_T2; + var1 >>= 11; + var2 = adc_T >> 4; + var2 -= (s32)inf->rom.bmp280.dig_T1; + var2 *= var2; + var2 >>= 12; + var2 *= (s32)inf->rom.bmp280.dig_T3; + var2 >>= 14; inf->t_fine = var1 + var2; inf->temperature = (inf->t_fine * 5 + 128) >> 8; } -static void bmp280_calc_pres(struct bmp_inf *inf) +static int bmp280_calc_pres(struct bmp_inf *inf) { s32 adc_P; - s64 var1; - s64 var2; - s64 p; - - adc_P = (s32)inf->UP; - adc_P <<= inf->range_i; - adc_P >>= 4; - var1 = ((s64)inf->t_fine) - 128000; - var2 = var1 * var1 * (s64)inf->rom.bmp280.dig_P6; - var2 += ((var1 * (s64)inf->rom.bmp280.dig_P5) << 17); - var2 += (((s64)inf->rom.bmp280.dig_P4) << 35); - var1 = ((var1 * var1 * (s64)inf->rom.bmp280.dig_P3) >> 8) + - ((var1 * (s64)inf->rom.bmp280.dig_P2) << 12); - var1 = (((((s64)1) << 47) + var1) * - ((s64)inf->rom.bmp280.dig_P1)) >> 33; - if (var1) { /* avoid division by zero */ - p = 1048576 - adc_P; - p = ((p << 31) - var2) * 3125; - p = do_div(p, var1); - var1 = (((s64)inf->rom.bmp280.dig_P9) * - (p >> 13) * (p >> 13)) >> 25; - var2 = (((s64)inf->rom.bmp280.dig_P8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + - (((s64)inf->rom.bmp280.dig_P7) << 4); - } else { - p = 0; - } + s32 var1; + s32 var2; + s32 var3; + u32 p; + + adc_P = inf->UP; + var1 = inf->t_fine >> 1; + var1 -= 64000; + var2 = var1 >> 2; + var2 *= var2; + var3 = var2; + var2 >>= 11; + var2 *= inf->rom.bmp280.dig_P6; + var2 += ((var1 * inf->rom.bmp280.dig_P5) << 1); + var2 >>= 2; + var2 += (inf->rom.bmp280.dig_P4 << 16); + var3 >>= 13; + var3 *= inf->rom.bmp280.dig_P3; + var3 >>= 3; + var1 *= inf->rom.bmp280.dig_P2; + var1 >>= 1; + var1 += var3; + var1 >>= 18; + var1 += 32768; + var1 *= inf->rom.bmp280.dig_P1; + var1 >>= 15; + if (!var1) + return -1; + + p = ((u32)(((s32)1048576) - adc_P) - (var2 >> 12)) * 3125; + if (p < 0x80000000) + p = (p << 1) / ((u32)var1); + else + p = (p / (u32)var1) << 1; + var3 = p >> 3; + var3 *= var3; + var3 >>= 13; + var1 = (s32)inf->rom.bmp280.dig_P9 * var3; + var1 >>= 12; + var2 = (s32)(p >> 2); + var2 *= (s32)inf->rom.bmp280.dig_P8; + var2 >>= 13; + var3 = var1 + var2 + inf->rom.bmp280.dig_P7; + var3 >>= 4; + p = (u32)((s32)p + var3); inf->pressure = (int)p; + return 1; } static int bmp280_read_sts(struct bmp_inf *inf, u8 *data) { u8 sts; - int val; + s32 val; + int err; sts = data[1] & BMP280_REG_CTRL_MODE_MASK; if ((sts == BMP280_REG_CTRL_MODE_FORCED1) || (sts == BMP280_REG_CTRL_MODE_FORCED2)) return 0; - val = (data[4] << 12) | (data[5] << 4) | (data[6] >> 4); + val = (data[4] << 16) | (data[5] << 8) | data[6]; + val = le32_to_cpup(&val); + val >>= 4; inf->UP = val; - val = (data[7] << 12) | (data[8] << 4) | (data[9] >> 4); + val = (data[7] << 16) | (data[8] << 8) | data[9]; + val = le32_to_cpup(&val); + val >>= 4; inf->UT = val; bmp280_calc_temp(inf); - bmp280_calc_pres(inf); - return 1; + err = bmp280_calc_pres(inf); + return err; } static int bmp280_read(struct bmp_inf *inf) @@ -864,7 +910,7 @@ static int bmp280_read(struct bmp_inf *inf) if (err) return err; - err = bmp180_read_sts(inf, data); + err = bmp280_read_sts(inf, data); if (err > 0) { timestamp2 = (timestamp2 - timestamp1) >> 1; timestamp1 += timestamp2; @@ -882,7 +928,7 @@ static void bmp280_mpu_handler(u8 *data, unsigned int len, s64 ts, void *p_val) inf = (struct bmp_inf *)p_val; if (inf->enable) { err = bmp280_read_sts(inf, data); - if (!err) + if (err > 0) bmp_report(inf, ts); } } @@ -919,7 +965,7 @@ static int bmp_init_hw(struct bmp_inf *inf) return err; p_rom16 = (u16 *)&inf->rom; - for (i = 0; i < (inf->hal->rom_size / 2); i++) { + for (i = 0; i < (inf->hal->rom_size >> 1); i++) { *p_rom16 = be16_to_cpup(p_rom16); p_rom16++; } @@ -931,25 +977,24 @@ static int bmp_enable(struct bmp_inf *inf, bool enable) { int err = 0; - bmp_pm(inf, true); - if (!inf->initd) - err = bmp_init_hw(inf); - if (!err) { - if (enable) { + if (enable) { + bmp_pm(inf, true); + if (!inf->initd) + err = bmp_init_hw(inf); + if (!err) { inf->report = true; err |= bmp_delay(inf, inf->poll_delay_us, inf->range_user); err |= bmp_mode_wr(inf, true, true); if (!err) inf->enable = true; - } else { + } + } else if (inf->enable) { + err = bmp_mode_wr(inf, false, false); + if (!err) { + bmp_pm(inf, false); inf->enable = false; - err = bmp_mode_wr(inf, false, false); - if (!err) - bmp_pm(inf, false); } - } else { - bmp_pm(inf, false); } return err; } @@ -1009,7 +1054,6 @@ static ssize_t bmp_delay_store(struct device *dev, if (err) return -EINVAL; - dev_dbg(&inf->i2c->dev, "%s: %u\n", __func__, delay_us); if (inf->dev_id == BMPX80_REG_ID_BMP180) /* since we rotate between acquiring data for pressure and * temperature on the BMP180 we need to go twice as fast. @@ -1132,6 +1176,35 @@ static ssize_t bmp_data_store(struct device *dev, dev_dbg(&inf->i2c->dev, "%s %u\n", __func__, data_info); inf->data_info = data_info; + switch (data_info) { + case BMP_DATA_INFO_DATA: + inf->dbg = 0; + break; + + case BMP_DATA_INFO_DBG: + inf->dbg ^= BMP_DBG_SPEW_MSG; + break; + + case BMP_DATA_INFO_PRESSURE_SPEW: + inf->dbg ^= BMP_DBG_SPEW_PRESSURE; + break; + + case BMP_DATA_INFO_TEMPERATURE_SPEW: + inf->dbg ^= BMP_DBG_SPEW_TEMPERATURE; + break; + + case BMP_DATA_INFO_PRESSURE_RAW_SPEW: + inf->dbg ^= BMP_DBG_SPEW_PRESSURE_RAW; + break; + + case BMP_DATA_INFO_TEMPERATURE_RAW_SPEW: + inf->dbg ^= BMP_DBG_SPEW_TEMPERATURE_RAW; + break; + + default: + break; + } + return count; } @@ -1140,99 +1213,97 @@ static ssize_t bmp_data_show(struct device *dev, char *buf) { struct bmp_inf *inf; + ssize_t t; u8 data[11]; - long val = 0; + u16 *cal; enum BMP_DATA_INFO data_info; bool enable; - char const *info_str; + unsigned int i; int err = 0; inf = dev_get_drvdata(dev); data_info = inf->data_info; - inf->data_info = BMP_DATA_INFO_PRESSURE; + inf->data_info = BMP_DATA_INFO_DATA; enable = inf->enable; - info_str = "ERR: DISABLED"; switch (data_info) { - case BMP_DATA_INFO_PRESSURE: - val = (long)inf->pressure; - if (inf->enable) - info_str = "pressure"; - break; - - case BMP_DATA_INFO_TEMPERATURE: - val = inf->temperature; - if (inf->enable) - info_str = "temperature"; - break; - - case BMP_DATA_INFO_PRESSURE_RAW: - val = inf->UP; - if (inf->enable) - info_str = "pressure_raw"; - break; - - case BMP_DATA_INFO_TEMPERATURE_RAW: - val = inf->UT; - if (inf->enable) - info_str = "temperature_raw"; - break; - - case BMP_DATA_INFO_TEMPERATURE_FINE: - val = (long)inf->t_fine; - if (inf->enable) - info_str = "temperature_fine"; - break; - - case BMP_DATA_INFO_CALIBRATION: - err = 0; - if (!inf->initd) - err = bmp_enable(inf, enable); - if (err) - return sprintf(buf, "calibration ERR\n"); - - return sprintf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x\n", - inf->rom.bmp280.dig_T1, - inf->rom.bmp280.dig_T2, - inf->rom.bmp280.dig_T3, - inf->rom.bmp280.dig_P1, - inf->rom.bmp280.dig_P2, - inf->rom.bmp280.dig_P3, - inf->rom.bmp280.dig_P4, - inf->rom.bmp280.dig_P5, - inf->rom.bmp280.dig_P6, - inf->rom.bmp280.dig_P7, - inf->rom.bmp280.dig_P8, - inf->rom.bmp280.dig_P9); + case BMP_DATA_INFO_DATA: + t = sprintf(buf, "pressure: %d raw: %d\n", + inf->pressure, inf->UP); + t += sprintf(buf + t, "temperature: %d raw: %d\n", + inf->temperature, inf->UT); + if (inf->dev_id != BMPX80_REG_ID_BMP180) + t += sprintf(buf + t, "temperature_fine: %d\n", + inf->t_fine); + return t; + + case BMP_DATA_INFO_VER: + return sprintf(buf, "version=%u\n", BMP_VERSION); case BMP_DATA_INFO_RESET: bmp_pm(inf, true); err = bmp_mode_wr(inf, true, enable); bmp_pm(inf, enable); if (err) - return sprintf(buf, "reset ERR\n"); + return sprintf(buf, "reset ERR %d\n", err); else return sprintf(buf, "reset done\n"); - case BMP_DATA_INFO_REGISTERS: + case BMP_DATA_INFO_REGS: + if (!inf->initd) { + t = sprintf(buf, "calibration: NEED ENABLE\n"); + } else { + t = sprintf(buf, "calibration:\n"); + cal = &inf->rom.bmp280.dig_T1; + for (i = 0; i < inf->hal->rom_size; i = i + 2) + t += sprintf(buf + t, "%#2x=%#2x\n", + inf->hal->rom_addr_start + i, + *cal++); + } err = bmp_nvi_mpu_bypass_request(inf); if (!err) { err = bmp_i2c_rd(inf, BMPX80_REG_ID, 1, data); - err |= bmp_i2c_rd(inf, BMP280_REG_STATUS, 10, &data[1]); + err |= bmp_i2c_rd(inf, BMP280_REG_STATUS, + 10, &data[1]); bmp_nvi_mpu_bypass_release(inf); } - if (err) - return sprintf(buf, "register read ERR\n"); + if (err) { + t += sprintf(buf + t, "registers: ERR %d\n", err); + } else { + t += sprintf(buf + t, "registers:\n"); + t += sprintf(buf + t, "%#2x=%#2x\n", + BMPX80_REG_ID, data[0]); + for (i = 0; i < 10; i++) + t += sprintf(buf + t, "%#2x=%#2x\n", + BMP280_REG_STATUS + i, + data[i + 1]); + } + return t; - return sprintf(buf, "%x %x %x %x %x %x %x %x %x %x %x\n", - data[0], data[1], data[2], data[3], data[4], - data[5], data[6], data[7], data[8], data[9], - data[10]); + case BMP_DATA_INFO_DBG: + return sprintf(buf, "debug spew=%x\n", + !!(inf->dbg & BMP_DBG_SPEW_MSG)); + + case BMP_DATA_INFO_PRESSURE_SPEW: + return sprintf(buf, "pressure spew=%x\n", + !!(inf->dbg & BMP_DBG_SPEW_PRESSURE)); + + case BMP_DATA_INFO_TEMPERATURE_SPEW: + return sprintf(buf, "temperature spew=%x\n", + !!(inf->dbg & BMP_DBG_SPEW_TEMPERATURE)); + + case BMP_DATA_INFO_PRESSURE_RAW_SPEW: + return sprintf(buf, "pressure_raw spew=%x\n", + !!(inf->dbg & BMP_DBG_SPEW_PRESSURE_RAW)); + + case BMP_DATA_INFO_TEMPERATURE_RAW_SPEW: + return sprintf(buf, "temperature_raw spew=%x\n", + !!(inf->dbg & BMP_DBG_SPEW_TEMPERATURE_RAW)); default: - return -EINVAL; + break; } - return sprintf(buf, "%s: %ld\n", info_str, val); + return -EINVAL; } static ssize_t bmp_mpu_fifo_enable_store(struct device *dev, @@ -1376,6 +1447,9 @@ static int bmp_id_compare(struct bmp_inf *inf, u8 val, if (inf->dev_id && (inf->dev_id != val)) dev_err(&inf->i2c->dev, "%s ERR: %x != %s\n", __func__, inf->dev_id, id->name); + if (val != BMPX80_REG_ID_BMP180) + /* BMP280 may have more ID's than 0x56 */ + val = BMPX80_REG_ID_BMP280; inf->dev_id = val; break; } @@ -1445,9 +1519,9 @@ static int bmp_id(struct bmp_inf *inf, const struct i2c_device_id *id) int err; config_boot = inf->pdata.config & NVI_CONFIG_BOOT_MASK; - if ((inf->i2c->addr != BMP180_I2C_ADDR0) || - (inf->i2c->addr != BMP180_I2C_ADDR1)) - inf->i2c->addr = BMP180_I2C_ADDR1; + if ((inf->i2c->addr != BMP280_I2C_ADDR0) || + (inf->i2c->addr != BMPX80_I2C_ADDR1)) + inf->i2c->addr = BMPX80_I2C_ADDR1; if (!strcmp(id->name, BMP180_NAME)) inf->dev_id = BMPX80_REG_ID_BMP180; else if (!strcmp(id->name, BMP280_NAME)) @@ -1482,14 +1556,14 @@ static int bmp_id(struct bmp_inf *inf, const struct i2c_device_id *id) nmp.delay_us = inf->poll_delay_us; nmp.shutdown_bypass = true; nmp.ext_driver = (void *)inf; - if (inf->dev_id == BMPX80_REG_ID_BMP280) { - nmp.reg = BMP280_REG_STATUS; - nmp.ctrl = 10; /* MPU FIFO can't handle odd size */ - nmp.handler = &bmp280_mpu_handler; - } else { + if (inf->dev_id == BMPX80_REG_ID_BMP180) { nmp.reg = BMPX80_REG_CTRL; nmp.ctrl = 6; /* MPU FIFO can't handle odd size */ nmp.handler = &bmp180_mpu_handler; + } else { + nmp.reg = BMP280_REG_STATUS; + nmp.ctrl = 10; /* MPU FIFO can't handle odd size */ + nmp.handler = &bmp280_mpu_handler; } err = nvi_mpu_port_alloc(&nmp); dev_dbg(&inf->i2c->dev, "%s MPU port/err=%d\n", @@ -1650,23 +1724,6 @@ bmp_probe_again: return err; } -static int bmp_suspend(struct device *dev) -{ - struct bmp_inf *inf; - int err; - - inf = dev_get_drvdata(dev); - err = bmp_enable(inf, false); - if (err) - dev_err(dev, "%s ERR\n", __func__); - dev_info(dev, "%s done\n", __func__); - return 0; -} - -static const struct dev_pm_ops bmp_pm_ops = { - .suspend = bmp_suspend, -}; - static const struct i2c_device_id bmp_i2c_device_id[] = { {BMPX80_NAME, 0}, {BMP180_NAME, 0}, @@ -1693,7 +1750,6 @@ static struct i2c_driver bmp_driver = { .name = BMPX80_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(bmp_of_match), - .pm = &bmp_pm_ops, }, .id_table = bmp_i2c_device_id, .shutdown = bmp_shutdown, diff --git a/include/linux/mpu.h b/include/linux/mpu.h index 0b15d7c02a72..c0202aeba32e 100644 --- a/include/linux/mpu.h +++ b/include/linux/mpu.h @@ -53,12 +53,6 @@ * Other devices can be accessed by setting this to * that device's I2C address. When used after enabling * bypass mode, devices behind the MPU can be accessed. -* aux_dbg = write 1 to spew auxiliary port register dumps after -* each external driver call. -* Write 0 to disable the spew. -* Writing anything takes a snapshot of the registers. -* Therefore, a write of 0 can take snapshots whenever -* without the external driver call spew. **********************************************************************/ #define DEBUG_SYSFS_INTERFACE 1 |