mirror of https://gitee.com/openkylin/linux.git
iio: imu: inv_mpu6050: replace timestamp fifo by generic timestamp
Using a fifo for storing timestamps is useless since the interrupt is in one-shot mode, preventing the hard irq handler to be called when the irq thread is running. Instead use the generic timestamp function iio_pollfunc_store_time. Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
c2c8406b31
commit
3ca4fb431b
|
@ -20,8 +20,6 @@
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/kfifo.h>
|
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
@ -1003,7 +1001,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
|
||||||
indio_dev->modes = INDIO_BUFFER_TRIGGERED;
|
indio_dev->modes = INDIO_BUFFER_TRIGGERED;
|
||||||
|
|
||||||
result = devm_iio_triggered_buffer_setup(dev, indio_dev,
|
result = devm_iio_triggered_buffer_setup(dev, indio_dev,
|
||||||
inv_mpu6050_irq_handler,
|
iio_pollfunc_store_time,
|
||||||
inv_mpu6050_read_fifo,
|
inv_mpu6050_read_fifo,
|
||||||
NULL);
|
NULL);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -1016,8 +1014,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_KFIFO(st->timestamps);
|
|
||||||
spin_lock_init(&st->time_stamp_lock);
|
|
||||||
result = devm_iio_device_register(dev, indio_dev);
|
result = devm_iio_device_register(dev, indio_dev);
|
||||||
if (result) {
|
if (result) {
|
||||||
dev_err(dev, "IIO register fail %d\n", result);
|
dev_err(dev, "IIO register fail %d\n", result);
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
*/
|
*/
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-mux.h>
|
#include <linux/i2c-mux.h>
|
||||||
#include <linux/kfifo.h>
|
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/iio/buffer.h>
|
#include <linux/iio/buffer.h>
|
||||||
|
@ -116,36 +114,30 @@ struct inv_mpu6050_hw {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct inv_mpu6050_state - Driver state variables.
|
* struct inv_mpu6050_state - Driver state variables.
|
||||||
* @TIMESTAMP_FIFO_SIZE: fifo size for timestamp.
|
|
||||||
* @lock: Chip access lock.
|
* @lock: Chip access lock.
|
||||||
* @trig: IIO trigger.
|
* @trig: IIO trigger.
|
||||||
* @chip_config: Cached attribute information.
|
* @chip_config: Cached attribute information.
|
||||||
* @reg: Map of important registers.
|
* @reg: Map of important registers.
|
||||||
* @hw: Other hardware-specific information.
|
* @hw: Other hardware-specific information.
|
||||||
* @chip_type: chip type.
|
* @chip_type: chip type.
|
||||||
* @time_stamp_lock: spin lock to time stamp.
|
|
||||||
* @plat_data: platform data (deprecated in favor of @orientation).
|
* @plat_data: platform data (deprecated in favor of @orientation).
|
||||||
* @orientation: sensor chip orientation relative to main hardware.
|
* @orientation: sensor chip orientation relative to main hardware.
|
||||||
* @timestamps: kfifo queue to store time stamp.
|
|
||||||
* @map regmap pointer.
|
* @map regmap pointer.
|
||||||
* @irq interrupt number.
|
* @irq interrupt number.
|
||||||
* @irq_mask the int_pin_cfg mask to configure interrupt type.
|
* @irq_mask the int_pin_cfg mask to configure interrupt type.
|
||||||
*/
|
*/
|
||||||
struct inv_mpu6050_state {
|
struct inv_mpu6050_state {
|
||||||
#define TIMESTAMP_FIFO_SIZE 16
|
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct iio_trigger *trig;
|
struct iio_trigger *trig;
|
||||||
struct inv_mpu6050_chip_config chip_config;
|
struct inv_mpu6050_chip_config chip_config;
|
||||||
const struct inv_mpu6050_reg_map *reg;
|
const struct inv_mpu6050_reg_map *reg;
|
||||||
const struct inv_mpu6050_hw *hw;
|
const struct inv_mpu6050_hw *hw;
|
||||||
enum inv_devices chip_type;
|
enum inv_devices chip_type;
|
||||||
spinlock_t time_stamp_lock;
|
|
||||||
struct i2c_mux_core *muxc;
|
struct i2c_mux_core *muxc;
|
||||||
struct i2c_client *mux_client;
|
struct i2c_client *mux_client;
|
||||||
unsigned int powerup_count;
|
unsigned int powerup_count;
|
||||||
struct inv_mpu6050_platform_data plat_data;
|
struct inv_mpu6050_platform_data plat_data;
|
||||||
struct iio_mount_matrix orientation;
|
struct iio_mount_matrix orientation;
|
||||||
DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
|
|
||||||
struct regmap *map;
|
struct regmap *map;
|
||||||
int irq;
|
int irq;
|
||||||
u8 irq_mask;
|
u8 irq_mask;
|
||||||
|
@ -234,7 +226,6 @@ struct inv_mpu6050_state {
|
||||||
|
|
||||||
/* init parameters */
|
/* init parameters */
|
||||||
#define INV_MPU6050_INIT_FIFO_RATE 50
|
#define INV_MPU6050_INIT_FIFO_RATE 50
|
||||||
#define INV_MPU6050_TIME_STAMP_TOR 5
|
|
||||||
#define INV_MPU6050_MAX_FIFO_RATE 1000
|
#define INV_MPU6050_MAX_FIFO_RATE 1000
|
||||||
#define INV_MPU6050_MIN_FIFO_RATE 4
|
#define INV_MPU6050_MIN_FIFO_RATE 4
|
||||||
#define INV_MPU6050_ONE_K_HZ 1000
|
#define INV_MPU6050_ONE_K_HZ 1000
|
||||||
|
@ -300,7 +291,6 @@ enum inv_mpu6050_clock_sel_e {
|
||||||
NUM_CLK
|
NUM_CLK
|
||||||
};
|
};
|
||||||
|
|
||||||
irqreturn_t inv_mpu6050_irq_handler(int irq, void *p);
|
|
||||||
irqreturn_t inv_mpu6050_read_fifo(int irq, void *p);
|
irqreturn_t inv_mpu6050_read_fifo(int irq, void *p);
|
||||||
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type);
|
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type);
|
||||||
int inv_reset_fifo(struct iio_dev *indio_dev);
|
int inv_reset_fifo(struct iio_dev *indio_dev);
|
||||||
|
|
|
@ -19,20 +19,9 @@
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/kfifo.h>
|
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include "inv_mpu_iio.h"
|
#include "inv_mpu_iio.h"
|
||||||
|
|
||||||
static void inv_clear_kfifo(struct inv_mpu6050_state *st)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/* take the spin lock sem to avoid interrupt kick in */
|
|
||||||
spin_lock_irqsave(&st->time_stamp_lock, flags);
|
|
||||||
kfifo_reset(&st->timestamps);
|
|
||||||
spin_unlock_irqrestore(&st->time_stamp_lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int inv_reset_fifo(struct iio_dev *indio_dev)
|
int inv_reset_fifo(struct iio_dev *indio_dev)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
@ -62,9 +51,6 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
|
||||||
if (result)
|
if (result)
|
||||||
goto reset_fifo_fail;
|
goto reset_fifo_fail;
|
||||||
|
|
||||||
/* clear timestamps fifo */
|
|
||||||
inv_clear_kfifo(st);
|
|
||||||
|
|
||||||
/* enable interrupt */
|
/* enable interrupt */
|
||||||
if (st->chip_config.accl_fifo_enable ||
|
if (st->chip_config.accl_fifo_enable ||
|
||||||
st->chip_config.gyro_fifo_enable) {
|
st->chip_config.gyro_fifo_enable) {
|
||||||
|
@ -98,23 +84,6 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt.
|
|
||||||
*/
|
|
||||||
irqreturn_t inv_mpu6050_irq_handler(int irq, void *p)
|
|
||||||
{
|
|
||||||
struct iio_poll_func *pf = p;
|
|
||||||
struct iio_dev *indio_dev = pf->indio_dev;
|
|
||||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
|
||||||
s64 timestamp;
|
|
||||||
|
|
||||||
timestamp = iio_get_time_ns(indio_dev);
|
|
||||||
kfifo_in_spinlocked(&st->timestamps, ×tamp, 1,
|
|
||||||
&st->time_stamp_lock);
|
|
||||||
|
|
||||||
return IRQ_WAKE_THREAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
|
* inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
|
||||||
*/
|
*/
|
||||||
|
@ -127,7 +96,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
|
||||||
int result;
|
int result;
|
||||||
u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
|
u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
|
||||||
u16 fifo_count;
|
u16 fifo_count;
|
||||||
s64 timestamp;
|
s64 timestamp = pf->timestamp;
|
||||||
int int_status;
|
int int_status;
|
||||||
|
|
||||||
mutex_lock(&st->lock);
|
mutex_lock(&st->lock);
|
||||||
|
@ -171,28 +140,17 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
|
||||||
goto flush_fifo;
|
goto flush_fifo;
|
||||||
if (fifo_count > INV_MPU6050_FIFO_THRESHOLD)
|
if (fifo_count > INV_MPU6050_FIFO_THRESHOLD)
|
||||||
goto flush_fifo;
|
goto flush_fifo;
|
||||||
/* Timestamp mismatch. */
|
|
||||||
if (kfifo_len(&st->timestamps) >
|
|
||||||
fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
|
|
||||||
goto flush_fifo;
|
|
||||||
do {
|
do {
|
||||||
result = regmap_bulk_read(st->map, st->reg->fifo_r_w,
|
result = regmap_bulk_read(st->map, st->reg->fifo_r_w,
|
||||||
data, bytes_per_datum);
|
data, bytes_per_datum);
|
||||||
if (result)
|
if (result)
|
||||||
goto flush_fifo;
|
goto flush_fifo;
|
||||||
|
|
||||||
result = kfifo_out(&st->timestamps, ×tamp, 1);
|
|
||||||
/* when there is no timestamp, put timestamp as 0 */
|
|
||||||
if (result == 0)
|
|
||||||
timestamp = 0;
|
|
||||||
|
|
||||||
/* skip first samples if needed */
|
/* skip first samples if needed */
|
||||||
if (st->skip_samples)
|
if (st->skip_samples)
|
||||||
st->skip_samples--;
|
st->skip_samples--;
|
||||||
else
|
else
|
||||||
iio_push_to_buffers_with_timestamp(indio_dev, data,
|
iio_push_to_buffers_with_timestamp(indio_dev, data,
|
||||||
timestamp);
|
timestamp);
|
||||||
|
|
||||||
fifo_count -= bytes_per_datum;
|
fifo_count -= bytes_per_datum;
|
||||||
} while (fifo_count >= bytes_per_datum);
|
} while (fifo_count >= bytes_per_datum);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue