Loading drivers/iio/imu/inv_mpu/Kconfig +7 −0 Original line number Diff line number Diff line Loading @@ -60,4 +60,11 @@ config INV_MPU_IIO_SPI This driver can be built as a module. The module will be called inv-mpu-iio-spi. config ENABLE_IAM_ACC_GYRO_BUFFERING bool "Enable accel & gyro boot time sensor sample buffering" depends on INV_MPU_IIO help Say Y here if you want to buffer boot time sensor samples for IAM20680 accelerometer and gyroscope source "drivers/iio/imu/inv_mpu/inv_test/Kconfig" drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c +205 −3 Original line number Diff line number Diff line Loading @@ -311,6 +311,26 @@ static int _misc_attr_store(struct device *dev, return result; } #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING static inline int inv_check_acc_gyro_early_buff_enable_flag( struct iio_dev *indio_dev) { struct inv_mpu_state *st = iio_priv(indio_dev); if (st->acc_buffer_inv_samples == true || st->gyro_buffer_inv_samples == true) return 1; else return 0; } #else static inline int inv_check_acc_gyro_early_buff_enable_flag( struct iio_dev *indio_dev) { return 0; } #endif /* * inv_misc_attr_store() - calling this function */ Loading @@ -321,6 +341,9 @@ static ssize_t inv_misc_attr_store(struct device *dev, struct iio_dev *indio_dev = dev_get_drvdata(dev); int result; if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev)) return count; mutex_lock(&indio_dev->mlock); result = _misc_attr_store(dev, attr, buf, count); mutex_unlock(&indio_dev->mlock); Loading Loading @@ -351,6 +374,9 @@ static ssize_t inv_sensor_rate_store(struct device *dev, int data, rate, ind; int result; if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev)) return count; result = kstrtoint(buf, 10, &data); if (result) return -EINVAL; Loading Loading @@ -398,6 +424,9 @@ static ssize_t inv_sensor_on_store(struct device *dev, int data, on, ind; int result; if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev)) return count; result = kstrtoint(buf, 10, &data); if (result) return -EINVAL; Loading Loading @@ -493,7 +522,7 @@ static int _basic_attr_store(struct device *dev, p1[0] = ((power_on_data >> 16) & 0xff); p1[1] = ((power_on_data >> 24) & 0xff); if (st->bus_type == BUS_SPI) { if (st->bus_type == BUS_IIO_SPI) { struct spi_transfer power_on; struct spi_message msg; Loading @@ -508,7 +537,7 @@ static int _basic_attr_store(struct device *dev, spi_message_add_tail(&power_on, &msg); spi_sync(to_spi_device(st->dev), &msg); } else if (st->bus_type == BUS_I2C) { } else if (st->bus_type == BUS_IIO_I2C) { struct i2c_msg msgs[2]; p0[0] &= 0x7f; Loading Loading @@ -717,7 +746,7 @@ static ssize_t inv_temperature_show(struct device *dev, return res; mutex_unlock(&indio_dev->mlock); temp = (s32)be16_to_cpup((__be16 *)(data)) * 10000; temp = (s16)be16_to_cpup((__be16 *)(data)) * 10000; temp = temp / TEMP_SENSITIVITY + TEMP_OFFSET; return snprintf(buf, MAX_WR_SZ, "%d %lld\n", temp, get_time_ns()); Loading Loading @@ -771,6 +800,169 @@ static ssize_t inv_flush_batch_store(struct device *dev, return count; } #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING static int inv_gyro_read_bootsampl(struct inv_mpu_state *st, unsigned long enable_read) { int i = 0; if (enable_read) { st->gyro_buffer_inv_samples = false; for (i = 0; i < st->gyro_bufsample_cnt; i++) { dev_dbg(st->dev, "gyro_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n", i, st->inv_gyro_samplist[i]->xyz[0], st->inv_gyro_samplist[i]->xyz[1], st->inv_gyro_samplist[i]->xyz[2], st->inv_gyro_samplist[i]->tsec, st->inv_gyro_samplist[i]->tnsec); input_report_abs(st->gyrobuf_dev, ABS_X, st->inv_gyro_samplist[i]->xyz[0]); input_report_abs(st->gyrobuf_dev, ABS_Y, st->inv_gyro_samplist[i]->xyz[1]); input_report_abs(st->gyrobuf_dev, ABS_Z, st->inv_gyro_samplist[i]->xyz[2]); input_report_abs(st->gyrobuf_dev, ABS_RX, st->inv_gyro_samplist[i]->tsec); input_report_abs(st->gyrobuf_dev, ABS_RY, st->inv_gyro_samplist[i]->tnsec); input_sync(st->gyrobuf_dev); } } else { /* clean up */ if (st->gyro_bufsample_cnt != 0) { for (i = 0; i < INV_GYRO_MAXSAMPLE; i++) kmem_cache_free(st->inv_gyro_cachepool, st->inv_gyro_samplist[i]); kmem_cache_destroy(st->inv_gyro_cachepool); st->gyro_bufsample_cnt = 0; } } /*SYN_CONFIG indicates end of data*/ input_event(st->gyrobuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF); input_sync(st->gyrobuf_dev); dev_dbg(st->dev, "End of gyro samples bufsample_cnt=%d\n", st->gyro_bufsample_cnt); return 0; } static int inv_acc_read_bootsampl(struct inv_mpu_state *st, unsigned long enable_read) { int i = 0; if (enable_read) { st->acc_buffer_inv_samples = false; for (i = 0; i < st->acc_bufsample_cnt; i++) { dev_dbg(st->dev, "acc_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n", i, st->inv_acc_samplist[i]->xyz[0], st->inv_acc_samplist[i]->xyz[1], st->inv_acc_samplist[i]->xyz[2], st->inv_acc_samplist[i]->tsec, st->inv_acc_samplist[i]->tnsec); input_report_abs(st->accbuf_dev, ABS_X, st->inv_acc_samplist[i]->xyz[0]); input_report_abs(st->accbuf_dev, ABS_Y, st->inv_acc_samplist[i]->xyz[1]); input_report_abs(st->accbuf_dev, ABS_Z, st->inv_acc_samplist[i]->xyz[2]); input_report_abs(st->accbuf_dev, ABS_RX, st->inv_acc_samplist[i]->tsec); input_report_abs(st->accbuf_dev, ABS_RY, st->inv_acc_samplist[i]->tnsec); input_sync(st->accbuf_dev); } } else { /* clean up */ if (st->acc_bufsample_cnt != 0) { for (i = 0; i < INV_ACC_MAXSAMPLE; i++) kmem_cache_free(st->inv_acc_cachepool, st->inv_acc_samplist[i]); kmem_cache_destroy(st->inv_acc_cachepool); st->acc_bufsample_cnt = 0; } } /*SYN_CONFIG indicates end of data*/ input_event(st->accbuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF); input_sync(st->accbuf_dev); dev_dbg(st->dev, "End of acc samples bufsample_cnt=%d\n", st->acc_bufsample_cnt); return 0; } static ssize_t read_gyro_boot_sample_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct inv_mpu_state *st = iio_priv(indio_dev); return snprintf(buf, MAX_WR_SZ, "%d\n", st->read_gyro_boot_sample); } static ssize_t read_gyro_boot_sample_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err; unsigned long enable = 0; struct iio_dev *indio_dev = dev_get_drvdata(dev); struct inv_mpu_state *st = iio_priv(indio_dev); err = kstrtoul(buf, 10, &enable); if (err) return err; if (enable > 1) { dev_err(st->dev, "Invalid value of input, input=%ld\n", enable); return -EINVAL; } err = inv_gyro_read_bootsampl(st, enable); if (err) return err; st->read_gyro_boot_sample = enable; return count; } static ssize_t read_acc_boot_sample_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct inv_mpu_state *st = iio_priv(indio_dev); return snprintf(buf, MAX_WR_SZ, "%d\n", st->read_acc_boot_sample); } static ssize_t read_acc_boot_sample_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err; struct iio_dev *indio_dev = dev_get_drvdata(dev); struct inv_mpu_state *st = iio_priv(indio_dev); unsigned long enable = 0; err = kstrtoul(buf, 10, &enable); if (err) return err; if (enable > 1) { dev_err(st->dev, "Invalid value of input, input=%ld\n", enable); return -EINVAL; } err = inv_acc_read_bootsampl(st, enable); if (err) return err; st->read_acc_boot_sample = enable; return count; } #endif static const struct iio_chan_spec inv_mpu_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU_SCAN_TIMESTAMP), }; Loading @@ -780,6 +972,12 @@ static DEVICE_ATTR(debug_reg_dump, S_IRUGO | S_IWUSR, inv_reg_dump_show, NULL); static DEVICE_ATTR(out_temperature, S_IRUGO | S_IWUSR, inv_temperature_show, NULL); static DEVICE_ATTR(misc_self_test, S_IRUGO | S_IWUSR, inv_self_test, NULL); #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING static IIO_DEVICE_ATTR(read_acc_boot_sample, 0644, read_acc_boot_sample_show, read_acc_boot_sample_store, SENSOR_L_ACCEL); static IIO_DEVICE_ATTR(read_gyro_boot_sample, 0644, read_gyro_boot_sample_show, read_gyro_boot_sample_store, SENSOR_L_GYRO); #endif static IIO_DEVICE_ATTR(info_anglvel_matrix, S_IRUGO, inv_attr_show, NULL, ATTR_GYRO_MATRIX); Loading Loading @@ -913,6 +1111,10 @@ static const struct attribute *inv_raw_attributes[] = { &dev_attr_misc_self_test.attr, #ifndef SUPPORT_ONLY_BASIC_FEATURES &iio_dev_attr_in_power_on.dev_attr.attr, #endif #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING &iio_dev_attr_read_acc_boot_sample.dev_attr.attr, &iio_dev_attr_read_gyro_boot_sample.dev_attr.attr, #endif &iio_dev_attr_in_accel_enable.dev_attr.attr, &iio_dev_attr_in_accel_wake_enable.dev_attr.attr, Loading drivers/iio/imu/inv_mpu/iam20680/inv_mpu_setup_20680.c +3 −0 Original line number Diff line number Diff line Loading @@ -271,6 +271,9 @@ static int inv_set_batch(struct inv_mpu_state *st) u64 timeout; int required_fifo_size; #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING st->batch.timeout = 100; #endif if (st->batch.timeout) { required_fifo_size = st->batch.timeout * st->eng_info[ENGINE_GYRO].running_rate * st->batch.pk_size / 1000; Loading drivers/iio/imu/inv_mpu/inv_mpu_i2c.c +219 −2 Original line number Diff line number Diff line Loading @@ -278,6 +278,219 @@ static int inv_i2c_mem_read(struct inv_mpu_state *st, u8 mpu_addr, u16 mem_addr, return res; } #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING static void inv_enable_acc_gyro(struct inv_mpu_state *st) { struct iio_dev *indio_dev = iio_priv_to_dev(st); int accel_hz = 100; int gyro_hz = 100; /**Enable the ACCEL**/ st->sensor_l[SENSOR_L_ACCEL].on = 0; st->trigger_state = RATE_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); inv_switch_power_in_lp(st, true); st->chip_config.accel_fs = ACCEL_FSR_2G; inv_set_accel_sf(st); st->trigger_state = MISC_TRIGGER; set_inv_enable(indio_dev); st->sensor_l[SENSOR_L_ACCEL].rate = accel_hz; st->trigger_state = DATA_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); st->sensor_l[SENSOR_L_ACCEL].on = 1; st->trigger_state = RATE_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); /**Enable the GYRO**/ st->sensor_l[SENSOR_L_GYRO].on = 0; st->trigger_state = RATE_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); inv_switch_power_in_lp(st, true); st->chip_config.fsr = GYRO_FSR_250DPS; inv_set_gyro_sf(st); st->trigger_state = MISC_TRIGGER; set_inv_enable(indio_dev); st->sensor_l[SENSOR_L_GYRO].rate = gyro_hz; st->trigger_state = DATA_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); st->sensor_l[SENSOR_L_GYRO].on = 1; st->trigger_state = RATE_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); } static int inv_acc_gyro_early_buff_init(struct iio_dev *indio_dev) { int i = 0, err = 0; struct inv_mpu_state *st; st = iio_priv(indio_dev); st->acc_bufsample_cnt = 0; st->gyro_bufsample_cnt = 0; st->report_evt_cnt = 5; st->max_buffer_time = 40; st->inv_acc_cachepool = kmem_cache_create("acc_sensor_sample", sizeof(struct inv_acc_sample), 0, SLAB_HWCACHE_ALIGN, NULL); if (!st->inv_acc_cachepool) { pr_err("inv_acc_cachepool cache create failed\n"); err = -ENOMEM; goto clean_exit1; } for (i = 0; i < INV_ACC_MAXSAMPLE; i++) { st->inv_acc_samplist[i] = kmem_cache_alloc(st->inv_acc_cachepool, GFP_KERNEL); if (!st->inv_acc_samplist[i]) { err = -ENOMEM; goto clean_exit2; } } st->inv_gyro_cachepool = kmem_cache_create("gyro_sensor_sample" , sizeof(struct inv_gyro_sample), 0, SLAB_HWCACHE_ALIGN, NULL); if (!st->inv_gyro_cachepool) { pr_err("inv_gyro_cachepool cache create failed\n"); err = -ENOMEM; goto clean_exit3; } for (i = 0; i < INV_GYRO_MAXSAMPLE; i++) { st->inv_gyro_samplist[i] = kmem_cache_alloc(st->inv_gyro_cachepool, GFP_KERNEL); if (!st->inv_gyro_samplist[i]) { err = -ENOMEM; goto clean_exit4; } } st->accbuf_dev = input_allocate_device(); if (!st->accbuf_dev) { err = -ENOMEM; pr_err("input device allocation failed\n"); goto clean_exit5; } st->accbuf_dev->name = "inv_accbuf"; st->accbuf_dev->id.bustype = BUS_I2C; input_set_events_per_packet(st->accbuf_dev, st->report_evt_cnt * INV_ACC_MAXSAMPLE); set_bit(EV_ABS, st->accbuf_dev->evbit); input_set_abs_params(st->accbuf_dev, ABS_X, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->accbuf_dev, ABS_Y, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->accbuf_dev, ABS_Z, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->accbuf_dev, ABS_RX, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->accbuf_dev, ABS_RY, -G_MAX, G_MAX, 0, 0); err = input_register_device(st->accbuf_dev); if (err) { pr_err("unable to register input device %s\n", st->accbuf_dev->name); goto clean_exit5; } st->gyrobuf_dev = input_allocate_device(); if (!st->gyrobuf_dev) { err = -ENOMEM; pr_err("input device allocation failed\n"); goto clean_exit6; } st->gyrobuf_dev->name = "inv_gyrobuf"; st->gyrobuf_dev->id.bustype = BUS_I2C; input_set_events_per_packet(st->gyrobuf_dev, st->report_evt_cnt * INV_GYRO_MAXSAMPLE); set_bit(EV_ABS, st->gyrobuf_dev->evbit); input_set_abs_params(st->gyrobuf_dev, ABS_X, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->gyrobuf_dev, ABS_Y, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->gyrobuf_dev, ABS_Z, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->gyrobuf_dev, ABS_RX, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->gyrobuf_dev, ABS_RY, -G_MAX, G_MAX, 0, 0); err = input_register_device(st->gyrobuf_dev); if (err) { pr_err("unable to register input device %s\n", st->gyrobuf_dev->name); goto clean_exit6; } st->acc_buffer_inv_samples = true; st->gyro_buffer_inv_samples = true; inv_enable_acc_gyro(st); return 1; clean_exit6: input_free_device(st->gyrobuf_dev); input_unregister_device(st->accbuf_dev); clean_exit5: input_free_device(st->accbuf_dev); clean_exit4: for (i = 0; i < INV_GYRO_MAXSAMPLE; i++) kmem_cache_free(st->inv_gyro_cachepool, st->inv_gyro_samplist[i]); clean_exit3: kmem_cache_destroy(st->inv_gyro_cachepool); clean_exit2: for (i = 0; i < INV_ACC_MAXSAMPLE; i++) kmem_cache_free(st->inv_acc_cachepool, st->inv_acc_samplist[i]); clean_exit1: kmem_cache_destroy(st->inv_acc_cachepool); return 0; } static void inv_acc_gyro_input_cleanup( struct iio_dev *indio_dev) { int i = 0; struct inv_mpu_state *st; st = iio_priv(indio_dev); input_free_device(st->accbuf_dev); input_unregister_device(st->gyrobuf_dev); input_free_device(st->gyrobuf_dev); for (i = 0; i < INV_GYRO_MAXSAMPLE; i++) kmem_cache_free(st->inv_gyro_cachepool, st->inv_gyro_samplist[i]); kmem_cache_destroy(st->inv_gyro_cachepool); for (i = 0; i < INV_ACC_MAXSAMPLE; i++) kmem_cache_free(st->inv_acc_cachepool, st->inv_acc_samplist[i]); kmem_cache_destroy(st->inv_acc_cachepool); } #else static int inv_acc_gyro_early_buff_init(struct iio_dev *indio_dev) { return 1; } static void inv_acc_gyro_input_cleanup( struct iio_dev *indio_dev) { } #endif /* * inv_mpu_probe() - probe function. */ Loading Loading @@ -318,7 +531,7 @@ static int inv_mpu_probe(struct i2c_client *client, st->mem_write = inv_i2c_mem_write; st->mem_read = inv_i2c_mem_read; st->dev = &client->dev; st->bus_type = BUS_I2C; st->bus_type = BUS_IIO_I2C; #ifdef CONFIG_OF result = invensense_mpu_parse_dt(st->dev, &st->plat_data); if (result) Loading Loading @@ -420,6 +633,9 @@ static int inv_mpu_probe(struct i2c_client *client, #ifdef TIMER_BASED_BATCHING pr_info("Timer based batching\n"); #endif result = inv_acc_gyro_early_buff_init(indio_dev); if (!result) return -EIO; return 0; #ifdef KERNEL_VERSION_4_X Loading @@ -438,10 +654,10 @@ static int inv_mpu_probe(struct i2c_client *client, out_unreg_ring: inv_mpu_unconfigure_ring(indio_dev); out_free: dev_err(st->dev, "%s failed %d\n", __func__, result); iio_device_free(indio_dev); out_no_free: #endif dev_err(st->dev, "%s failed %d\n", __func__, result); return -EIO; } Loading Loading @@ -479,6 +695,7 @@ static int inv_mpu_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct inv_mpu_state *st = iio_priv(indio_dev); inv_acc_gyro_input_cleanup(indio_dev); #ifdef KERNEL_VERSION_4_X devm_iio_device_unregister(st->dev, indio_dev); #else Loading drivers/iio/imu/inv_mpu/inv_mpu_iio.h +51 −3 Original line number Diff line number Diff line Loading @@ -37,7 +37,9 @@ #include <linux/iio/sysfs.h> #include <linux/iio/iio.h> #include <linux/iio/kfifo_buf.h> #include <linux/input.h> #include <linux/ktime.h> #include <linux/slab.h> #ifdef CONFIG_INV_MPU_IIO_ICM20648 #include "icm20648/dmp3Default.h" #endif Loading Loading @@ -131,9 +133,37 @@ #define COVARIANCE_SIZE 14 #define ACCEL_COVARIANCE_SIZE (COVARIANCE_SIZE * sizeof(int)) #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING #define INV_ACC_MAXSAMPLE 4000 #define INV_GYRO_MAXSAMPLE 4000 #define G_MAX 23920640 struct inv_acc_sample { int xyz[3]; unsigned int tsec; unsigned long long tnsec; }; struct inv_gyro_sample { int xyz[3]; unsigned int tsec; unsigned long long tnsec; }; enum { ACCEL_FSR_2G = 0, ACCEL_FSR_4G = 1, ACCEL_FSR_8G = 2, ACCEL_FSR_16G = 3 }; enum { GYRO_FSR_250DPS = 0, GYRO_FSR_500DPS = 1, GYRO_FSR_1000DPS = 2, GYRO_FSR_2000DPS = 3 }; #endif enum inv_bus_type { BUS_I2C = 0, BUS_SPI, BUS_IIO_I2C = 0, BUS_IIO_SPI, }; struct inv_mpu_state; Loading Loading @@ -825,6 +855,24 @@ struct inv_mpu_state { u8 int_en_2; u8 gesture_int_count; u8 smplrt_div; #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING bool read_acc_boot_sample; bool read_gyro_boot_sample; int acc_bufsample_cnt; int gyro_bufsample_cnt; bool acc_buffer_inv_samples; bool gyro_buffer_inv_samples; struct kmem_cache *inv_acc_cachepool; struct kmem_cache *inv_gyro_cachepool; struct inv_acc_sample *inv_acc_samplist[INV_ACC_MAXSAMPLE]; struct inv_gyro_sample *inv_gyro_samplist[INV_GYRO_MAXSAMPLE]; ktime_t timestamp; int max_buffer_time; struct input_dev *accbuf_dev; struct input_dev *gyrobuf_dev; int report_evt_cnt; #endif }; /** Loading Loading
drivers/iio/imu/inv_mpu/Kconfig +7 −0 Original line number Diff line number Diff line Loading @@ -60,4 +60,11 @@ config INV_MPU_IIO_SPI This driver can be built as a module. The module will be called inv-mpu-iio-spi. config ENABLE_IAM_ACC_GYRO_BUFFERING bool "Enable accel & gyro boot time sensor sample buffering" depends on INV_MPU_IIO help Say Y here if you want to buffer boot time sensor samples for IAM20680 accelerometer and gyroscope source "drivers/iio/imu/inv_mpu/inv_test/Kconfig"
drivers/iio/imu/inv_mpu/iam20680/inv_mpu_core_20680.c +205 −3 Original line number Diff line number Diff line Loading @@ -311,6 +311,26 @@ static int _misc_attr_store(struct device *dev, return result; } #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING static inline int inv_check_acc_gyro_early_buff_enable_flag( struct iio_dev *indio_dev) { struct inv_mpu_state *st = iio_priv(indio_dev); if (st->acc_buffer_inv_samples == true || st->gyro_buffer_inv_samples == true) return 1; else return 0; } #else static inline int inv_check_acc_gyro_early_buff_enable_flag( struct iio_dev *indio_dev) { return 0; } #endif /* * inv_misc_attr_store() - calling this function */ Loading @@ -321,6 +341,9 @@ static ssize_t inv_misc_attr_store(struct device *dev, struct iio_dev *indio_dev = dev_get_drvdata(dev); int result; if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev)) return count; mutex_lock(&indio_dev->mlock); result = _misc_attr_store(dev, attr, buf, count); mutex_unlock(&indio_dev->mlock); Loading Loading @@ -351,6 +374,9 @@ static ssize_t inv_sensor_rate_store(struct device *dev, int data, rate, ind; int result; if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev)) return count; result = kstrtoint(buf, 10, &data); if (result) return -EINVAL; Loading Loading @@ -398,6 +424,9 @@ static ssize_t inv_sensor_on_store(struct device *dev, int data, on, ind; int result; if (inv_check_acc_gyro_early_buff_enable_flag(indio_dev)) return count; result = kstrtoint(buf, 10, &data); if (result) return -EINVAL; Loading Loading @@ -493,7 +522,7 @@ static int _basic_attr_store(struct device *dev, p1[0] = ((power_on_data >> 16) & 0xff); p1[1] = ((power_on_data >> 24) & 0xff); if (st->bus_type == BUS_SPI) { if (st->bus_type == BUS_IIO_SPI) { struct spi_transfer power_on; struct spi_message msg; Loading @@ -508,7 +537,7 @@ static int _basic_attr_store(struct device *dev, spi_message_add_tail(&power_on, &msg); spi_sync(to_spi_device(st->dev), &msg); } else if (st->bus_type == BUS_I2C) { } else if (st->bus_type == BUS_IIO_I2C) { struct i2c_msg msgs[2]; p0[0] &= 0x7f; Loading Loading @@ -717,7 +746,7 @@ static ssize_t inv_temperature_show(struct device *dev, return res; mutex_unlock(&indio_dev->mlock); temp = (s32)be16_to_cpup((__be16 *)(data)) * 10000; temp = (s16)be16_to_cpup((__be16 *)(data)) * 10000; temp = temp / TEMP_SENSITIVITY + TEMP_OFFSET; return snprintf(buf, MAX_WR_SZ, "%d %lld\n", temp, get_time_ns()); Loading Loading @@ -771,6 +800,169 @@ static ssize_t inv_flush_batch_store(struct device *dev, return count; } #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING static int inv_gyro_read_bootsampl(struct inv_mpu_state *st, unsigned long enable_read) { int i = 0; if (enable_read) { st->gyro_buffer_inv_samples = false; for (i = 0; i < st->gyro_bufsample_cnt; i++) { dev_dbg(st->dev, "gyro_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n", i, st->inv_gyro_samplist[i]->xyz[0], st->inv_gyro_samplist[i]->xyz[1], st->inv_gyro_samplist[i]->xyz[2], st->inv_gyro_samplist[i]->tsec, st->inv_gyro_samplist[i]->tnsec); input_report_abs(st->gyrobuf_dev, ABS_X, st->inv_gyro_samplist[i]->xyz[0]); input_report_abs(st->gyrobuf_dev, ABS_Y, st->inv_gyro_samplist[i]->xyz[1]); input_report_abs(st->gyrobuf_dev, ABS_Z, st->inv_gyro_samplist[i]->xyz[2]); input_report_abs(st->gyrobuf_dev, ABS_RX, st->inv_gyro_samplist[i]->tsec); input_report_abs(st->gyrobuf_dev, ABS_RY, st->inv_gyro_samplist[i]->tnsec); input_sync(st->gyrobuf_dev); } } else { /* clean up */ if (st->gyro_bufsample_cnt != 0) { for (i = 0; i < INV_GYRO_MAXSAMPLE; i++) kmem_cache_free(st->inv_gyro_cachepool, st->inv_gyro_samplist[i]); kmem_cache_destroy(st->inv_gyro_cachepool); st->gyro_bufsample_cnt = 0; } } /*SYN_CONFIG indicates end of data*/ input_event(st->gyrobuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF); input_sync(st->gyrobuf_dev); dev_dbg(st->dev, "End of gyro samples bufsample_cnt=%d\n", st->gyro_bufsample_cnt); return 0; } static int inv_acc_read_bootsampl(struct inv_mpu_state *st, unsigned long enable_read) { int i = 0; if (enable_read) { st->acc_buffer_inv_samples = false; for (i = 0; i < st->acc_bufsample_cnt; i++) { dev_dbg(st->dev, "acc_cnt=%d,x=%d,y=%d,z=%d,tsec=%d,nsec=%lld\n", i, st->inv_acc_samplist[i]->xyz[0], st->inv_acc_samplist[i]->xyz[1], st->inv_acc_samplist[i]->xyz[2], st->inv_acc_samplist[i]->tsec, st->inv_acc_samplist[i]->tnsec); input_report_abs(st->accbuf_dev, ABS_X, st->inv_acc_samplist[i]->xyz[0]); input_report_abs(st->accbuf_dev, ABS_Y, st->inv_acc_samplist[i]->xyz[1]); input_report_abs(st->accbuf_dev, ABS_Z, st->inv_acc_samplist[i]->xyz[2]); input_report_abs(st->accbuf_dev, ABS_RX, st->inv_acc_samplist[i]->tsec); input_report_abs(st->accbuf_dev, ABS_RY, st->inv_acc_samplist[i]->tnsec); input_sync(st->accbuf_dev); } } else { /* clean up */ if (st->acc_bufsample_cnt != 0) { for (i = 0; i < INV_ACC_MAXSAMPLE; i++) kmem_cache_free(st->inv_acc_cachepool, st->inv_acc_samplist[i]); kmem_cache_destroy(st->inv_acc_cachepool); st->acc_bufsample_cnt = 0; } } /*SYN_CONFIG indicates end of data*/ input_event(st->accbuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF); input_sync(st->accbuf_dev); dev_dbg(st->dev, "End of acc samples bufsample_cnt=%d\n", st->acc_bufsample_cnt); return 0; } static ssize_t read_gyro_boot_sample_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct inv_mpu_state *st = iio_priv(indio_dev); return snprintf(buf, MAX_WR_SZ, "%d\n", st->read_gyro_boot_sample); } static ssize_t read_gyro_boot_sample_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err; unsigned long enable = 0; struct iio_dev *indio_dev = dev_get_drvdata(dev); struct inv_mpu_state *st = iio_priv(indio_dev); err = kstrtoul(buf, 10, &enable); if (err) return err; if (enable > 1) { dev_err(st->dev, "Invalid value of input, input=%ld\n", enable); return -EINVAL; } err = inv_gyro_read_bootsampl(st, enable); if (err) return err; st->read_gyro_boot_sample = enable; return count; } static ssize_t read_acc_boot_sample_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct inv_mpu_state *st = iio_priv(indio_dev); return snprintf(buf, MAX_WR_SZ, "%d\n", st->read_acc_boot_sample); } static ssize_t read_acc_boot_sample_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err; struct iio_dev *indio_dev = dev_get_drvdata(dev); struct inv_mpu_state *st = iio_priv(indio_dev); unsigned long enable = 0; err = kstrtoul(buf, 10, &enable); if (err) return err; if (enable > 1) { dev_err(st->dev, "Invalid value of input, input=%ld\n", enable); return -EINVAL; } err = inv_acc_read_bootsampl(st, enable); if (err) return err; st->read_acc_boot_sample = enable; return count; } #endif static const struct iio_chan_spec inv_mpu_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU_SCAN_TIMESTAMP), }; Loading @@ -780,6 +972,12 @@ static DEVICE_ATTR(debug_reg_dump, S_IRUGO | S_IWUSR, inv_reg_dump_show, NULL); static DEVICE_ATTR(out_temperature, S_IRUGO | S_IWUSR, inv_temperature_show, NULL); static DEVICE_ATTR(misc_self_test, S_IRUGO | S_IWUSR, inv_self_test, NULL); #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING static IIO_DEVICE_ATTR(read_acc_boot_sample, 0644, read_acc_boot_sample_show, read_acc_boot_sample_store, SENSOR_L_ACCEL); static IIO_DEVICE_ATTR(read_gyro_boot_sample, 0644, read_gyro_boot_sample_show, read_gyro_boot_sample_store, SENSOR_L_GYRO); #endif static IIO_DEVICE_ATTR(info_anglvel_matrix, S_IRUGO, inv_attr_show, NULL, ATTR_GYRO_MATRIX); Loading Loading @@ -913,6 +1111,10 @@ static const struct attribute *inv_raw_attributes[] = { &dev_attr_misc_self_test.attr, #ifndef SUPPORT_ONLY_BASIC_FEATURES &iio_dev_attr_in_power_on.dev_attr.attr, #endif #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING &iio_dev_attr_read_acc_boot_sample.dev_attr.attr, &iio_dev_attr_read_gyro_boot_sample.dev_attr.attr, #endif &iio_dev_attr_in_accel_enable.dev_attr.attr, &iio_dev_attr_in_accel_wake_enable.dev_attr.attr, Loading
drivers/iio/imu/inv_mpu/iam20680/inv_mpu_setup_20680.c +3 −0 Original line number Diff line number Diff line Loading @@ -271,6 +271,9 @@ static int inv_set_batch(struct inv_mpu_state *st) u64 timeout; int required_fifo_size; #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING st->batch.timeout = 100; #endif if (st->batch.timeout) { required_fifo_size = st->batch.timeout * st->eng_info[ENGINE_GYRO].running_rate * st->batch.pk_size / 1000; Loading
drivers/iio/imu/inv_mpu/inv_mpu_i2c.c +219 −2 Original line number Diff line number Diff line Loading @@ -278,6 +278,219 @@ static int inv_i2c_mem_read(struct inv_mpu_state *st, u8 mpu_addr, u16 mem_addr, return res; } #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING static void inv_enable_acc_gyro(struct inv_mpu_state *st) { struct iio_dev *indio_dev = iio_priv_to_dev(st); int accel_hz = 100; int gyro_hz = 100; /**Enable the ACCEL**/ st->sensor_l[SENSOR_L_ACCEL].on = 0; st->trigger_state = RATE_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); inv_switch_power_in_lp(st, true); st->chip_config.accel_fs = ACCEL_FSR_2G; inv_set_accel_sf(st); st->trigger_state = MISC_TRIGGER; set_inv_enable(indio_dev); st->sensor_l[SENSOR_L_ACCEL].rate = accel_hz; st->trigger_state = DATA_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); st->sensor_l[SENSOR_L_ACCEL].on = 1; st->trigger_state = RATE_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); /**Enable the GYRO**/ st->sensor_l[SENSOR_L_GYRO].on = 0; st->trigger_state = RATE_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); inv_switch_power_in_lp(st, true); st->chip_config.fsr = GYRO_FSR_250DPS; inv_set_gyro_sf(st); st->trigger_state = MISC_TRIGGER; set_inv_enable(indio_dev); st->sensor_l[SENSOR_L_GYRO].rate = gyro_hz; st->trigger_state = DATA_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); st->sensor_l[SENSOR_L_GYRO].on = 1; st->trigger_state = RATE_TRIGGER; inv_check_sensor_on(st); set_inv_enable(indio_dev); } static int inv_acc_gyro_early_buff_init(struct iio_dev *indio_dev) { int i = 0, err = 0; struct inv_mpu_state *st; st = iio_priv(indio_dev); st->acc_bufsample_cnt = 0; st->gyro_bufsample_cnt = 0; st->report_evt_cnt = 5; st->max_buffer_time = 40; st->inv_acc_cachepool = kmem_cache_create("acc_sensor_sample", sizeof(struct inv_acc_sample), 0, SLAB_HWCACHE_ALIGN, NULL); if (!st->inv_acc_cachepool) { pr_err("inv_acc_cachepool cache create failed\n"); err = -ENOMEM; goto clean_exit1; } for (i = 0; i < INV_ACC_MAXSAMPLE; i++) { st->inv_acc_samplist[i] = kmem_cache_alloc(st->inv_acc_cachepool, GFP_KERNEL); if (!st->inv_acc_samplist[i]) { err = -ENOMEM; goto clean_exit2; } } st->inv_gyro_cachepool = kmem_cache_create("gyro_sensor_sample" , sizeof(struct inv_gyro_sample), 0, SLAB_HWCACHE_ALIGN, NULL); if (!st->inv_gyro_cachepool) { pr_err("inv_gyro_cachepool cache create failed\n"); err = -ENOMEM; goto clean_exit3; } for (i = 0; i < INV_GYRO_MAXSAMPLE; i++) { st->inv_gyro_samplist[i] = kmem_cache_alloc(st->inv_gyro_cachepool, GFP_KERNEL); if (!st->inv_gyro_samplist[i]) { err = -ENOMEM; goto clean_exit4; } } st->accbuf_dev = input_allocate_device(); if (!st->accbuf_dev) { err = -ENOMEM; pr_err("input device allocation failed\n"); goto clean_exit5; } st->accbuf_dev->name = "inv_accbuf"; st->accbuf_dev->id.bustype = BUS_I2C; input_set_events_per_packet(st->accbuf_dev, st->report_evt_cnt * INV_ACC_MAXSAMPLE); set_bit(EV_ABS, st->accbuf_dev->evbit); input_set_abs_params(st->accbuf_dev, ABS_X, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->accbuf_dev, ABS_Y, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->accbuf_dev, ABS_Z, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->accbuf_dev, ABS_RX, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->accbuf_dev, ABS_RY, -G_MAX, G_MAX, 0, 0); err = input_register_device(st->accbuf_dev); if (err) { pr_err("unable to register input device %s\n", st->accbuf_dev->name); goto clean_exit5; } st->gyrobuf_dev = input_allocate_device(); if (!st->gyrobuf_dev) { err = -ENOMEM; pr_err("input device allocation failed\n"); goto clean_exit6; } st->gyrobuf_dev->name = "inv_gyrobuf"; st->gyrobuf_dev->id.bustype = BUS_I2C; input_set_events_per_packet(st->gyrobuf_dev, st->report_evt_cnt * INV_GYRO_MAXSAMPLE); set_bit(EV_ABS, st->gyrobuf_dev->evbit); input_set_abs_params(st->gyrobuf_dev, ABS_X, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->gyrobuf_dev, ABS_Y, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->gyrobuf_dev, ABS_Z, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->gyrobuf_dev, ABS_RX, -G_MAX, G_MAX, 0, 0); input_set_abs_params(st->gyrobuf_dev, ABS_RY, -G_MAX, G_MAX, 0, 0); err = input_register_device(st->gyrobuf_dev); if (err) { pr_err("unable to register input device %s\n", st->gyrobuf_dev->name); goto clean_exit6; } st->acc_buffer_inv_samples = true; st->gyro_buffer_inv_samples = true; inv_enable_acc_gyro(st); return 1; clean_exit6: input_free_device(st->gyrobuf_dev); input_unregister_device(st->accbuf_dev); clean_exit5: input_free_device(st->accbuf_dev); clean_exit4: for (i = 0; i < INV_GYRO_MAXSAMPLE; i++) kmem_cache_free(st->inv_gyro_cachepool, st->inv_gyro_samplist[i]); clean_exit3: kmem_cache_destroy(st->inv_gyro_cachepool); clean_exit2: for (i = 0; i < INV_ACC_MAXSAMPLE; i++) kmem_cache_free(st->inv_acc_cachepool, st->inv_acc_samplist[i]); clean_exit1: kmem_cache_destroy(st->inv_acc_cachepool); return 0; } static void inv_acc_gyro_input_cleanup( struct iio_dev *indio_dev) { int i = 0; struct inv_mpu_state *st; st = iio_priv(indio_dev); input_free_device(st->accbuf_dev); input_unregister_device(st->gyrobuf_dev); input_free_device(st->gyrobuf_dev); for (i = 0; i < INV_GYRO_MAXSAMPLE; i++) kmem_cache_free(st->inv_gyro_cachepool, st->inv_gyro_samplist[i]); kmem_cache_destroy(st->inv_gyro_cachepool); for (i = 0; i < INV_ACC_MAXSAMPLE; i++) kmem_cache_free(st->inv_acc_cachepool, st->inv_acc_samplist[i]); kmem_cache_destroy(st->inv_acc_cachepool); } #else static int inv_acc_gyro_early_buff_init(struct iio_dev *indio_dev) { return 1; } static void inv_acc_gyro_input_cleanup( struct iio_dev *indio_dev) { } #endif /* * inv_mpu_probe() - probe function. */ Loading Loading @@ -318,7 +531,7 @@ static int inv_mpu_probe(struct i2c_client *client, st->mem_write = inv_i2c_mem_write; st->mem_read = inv_i2c_mem_read; st->dev = &client->dev; st->bus_type = BUS_I2C; st->bus_type = BUS_IIO_I2C; #ifdef CONFIG_OF result = invensense_mpu_parse_dt(st->dev, &st->plat_data); if (result) Loading Loading @@ -420,6 +633,9 @@ static int inv_mpu_probe(struct i2c_client *client, #ifdef TIMER_BASED_BATCHING pr_info("Timer based batching\n"); #endif result = inv_acc_gyro_early_buff_init(indio_dev); if (!result) return -EIO; return 0; #ifdef KERNEL_VERSION_4_X Loading @@ -438,10 +654,10 @@ static int inv_mpu_probe(struct i2c_client *client, out_unreg_ring: inv_mpu_unconfigure_ring(indio_dev); out_free: dev_err(st->dev, "%s failed %d\n", __func__, result); iio_device_free(indio_dev); out_no_free: #endif dev_err(st->dev, "%s failed %d\n", __func__, result); return -EIO; } Loading Loading @@ -479,6 +695,7 @@ static int inv_mpu_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct inv_mpu_state *st = iio_priv(indio_dev); inv_acc_gyro_input_cleanup(indio_dev); #ifdef KERNEL_VERSION_4_X devm_iio_device_unregister(st->dev, indio_dev); #else Loading
drivers/iio/imu/inv_mpu/inv_mpu_iio.h +51 −3 Original line number Diff line number Diff line Loading @@ -37,7 +37,9 @@ #include <linux/iio/sysfs.h> #include <linux/iio/iio.h> #include <linux/iio/kfifo_buf.h> #include <linux/input.h> #include <linux/ktime.h> #include <linux/slab.h> #ifdef CONFIG_INV_MPU_IIO_ICM20648 #include "icm20648/dmp3Default.h" #endif Loading Loading @@ -131,9 +133,37 @@ #define COVARIANCE_SIZE 14 #define ACCEL_COVARIANCE_SIZE (COVARIANCE_SIZE * sizeof(int)) #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING #define INV_ACC_MAXSAMPLE 4000 #define INV_GYRO_MAXSAMPLE 4000 #define G_MAX 23920640 struct inv_acc_sample { int xyz[3]; unsigned int tsec; unsigned long long tnsec; }; struct inv_gyro_sample { int xyz[3]; unsigned int tsec; unsigned long long tnsec; }; enum { ACCEL_FSR_2G = 0, ACCEL_FSR_4G = 1, ACCEL_FSR_8G = 2, ACCEL_FSR_16G = 3 }; enum { GYRO_FSR_250DPS = 0, GYRO_FSR_500DPS = 1, GYRO_FSR_1000DPS = 2, GYRO_FSR_2000DPS = 3 }; #endif enum inv_bus_type { BUS_I2C = 0, BUS_SPI, BUS_IIO_I2C = 0, BUS_IIO_SPI, }; struct inv_mpu_state; Loading Loading @@ -825,6 +855,24 @@ struct inv_mpu_state { u8 int_en_2; u8 gesture_int_count; u8 smplrt_div; #ifdef CONFIG_ENABLE_IAM_ACC_GYRO_BUFFERING bool read_acc_boot_sample; bool read_gyro_boot_sample; int acc_bufsample_cnt; int gyro_bufsample_cnt; bool acc_buffer_inv_samples; bool gyro_buffer_inv_samples; struct kmem_cache *inv_acc_cachepool; struct kmem_cache *inv_gyro_cachepool; struct inv_acc_sample *inv_acc_samplist[INV_ACC_MAXSAMPLE]; struct inv_gyro_sample *inv_gyro_samplist[INV_GYRO_MAXSAMPLE]; ktime_t timestamp; int max_buffer_time; struct input_dev *accbuf_dev; struct input_dev *gyrobuf_dev; int report_evt_cnt; #endif }; /** Loading