Loading drivers/input/sensors/smi130/Kconfig +8 −0 Original line number Diff line number Diff line Loading @@ -126,4 +126,12 @@ depends on SENSORS_SMI_ACC4XY help If you say yes here, you get support for Bosch Sensortec's sensor driver of SMI_ACC4XY with mag sensor support. config ENABLE_SMI_ACC_GYRO_BUFFERING bool "Enable accel & gyro boot time sensor sample buffering" depends on SMI130 help Say Y here if you want to buffer boot time sensor samples for ASM330 accelerometer and gyroscope endif drivers/input/sensors/smi130/smi130_acc.c +276 −0 Original line number Diff line number Diff line Loading @@ -1528,6 +1528,16 @@ struct bosch_sensor_data { }; }; #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING #define SMI_ACC_MAXSAMPLE 4000 #define G_MAX 23920640 struct smi_acc_sample { int xyz[3]; unsigned int tsec; unsigned long long tnsec; }; #endif struct smi130_accacc { s16 x; s16 y; Loading Loading @@ -1590,6 +1600,16 @@ struct smi130_acc_data { struct timer_list tap_timer; int tap_time_period; #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING bool read_acc_boot_sample; int acc_bufsample_cnt; bool acc_buffer_smi130_samples; struct kmem_cache *smi_acc_cachepool; struct smi_acc_sample *smi130_acc_samplist[SMI_ACC_MAXSAMPLE]; int max_buffer_time; struct input_dev *accbuf_dev; int report_evt_cnt; #endif }; #ifdef CONFIG_HAS_EARLYSUSPEND Loading Loading @@ -4044,6 +4064,23 @@ static int smi130_acc_read_temperature(struct i2c_client *client, return comres; } #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static inline int smi130_check_acc_early_buff_enable_flag( struct smi130_acc_data *client_data) { if (client_data->acc_buffer_smi130_samples == true) return 1; else return 0; } #else static inline int smi130_check_acc_early_buff_enable_flag( struct smi130_acc_data *client_data) { return 0; } #endif static ssize_t smi130_acc_enable_int_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) Loading Loading @@ -5365,6 +5402,10 @@ static ssize_t smi130_acc_range_store(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); error = smi130_check_acc_early_buff_enable_flag(smi130_acc); if (error) return count; error = kstrtoul(buf, 10, &data); if (error) return error; Loading Loading @@ -5397,6 +5438,10 @@ static ssize_t smi130_acc_bandwidth_store(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); error = smi130_check_acc_early_buff_enable_flag(smi130_acc); if (error) return count; error = kstrtoul(buf, 10, &data); if (error) return error; Loading Loading @@ -5436,6 +5481,10 @@ static ssize_t smi130_acc_mode_store(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); error = smi130_check_acc_early_buff_enable_flag(smi130_acc); if (error) return count; error = kstrtoul(buf, 10, &data); if (error) return error; Loading Loading @@ -6432,10 +6481,97 @@ static void smi130_acc_tap_timeout_handle(unsigned long data) } #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static int smi_acc_read_bootsampl(struct smi130_acc_data *client_data, unsigned long enable_read) { int i = 0; if (enable_read) { client_data->acc_buffer_smi130_samples = false; for (i = 0; i < client_data->acc_bufsample_cnt; i++) { if (client_data->debug_level & 0x08) PINFO("acc=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n", i, client_data->smi130_acc_samplist[i]->xyz[0], client_data->smi130_acc_samplist[i]->xyz[1], client_data->smi130_acc_samplist[i]->xyz[2], client_data->smi130_acc_samplist[i]->tsec, client_data->smi130_acc_samplist[i]->tnsec); input_report_abs(client_data->accbuf_dev, ABS_X, client_data->smi130_acc_samplist[i]->xyz[0]); input_report_abs(client_data->accbuf_dev, ABS_Y, client_data->smi130_acc_samplist[i]->xyz[1]); input_report_abs(client_data->accbuf_dev, ABS_Z, client_data->smi130_acc_samplist[i]->xyz[2]); input_report_abs(client_data->accbuf_dev, ABS_RX, client_data->smi130_acc_samplist[i]->tsec); input_report_abs(client_data->accbuf_dev, ABS_RY, client_data->smi130_acc_samplist[i]->tnsec); input_sync(client_data->accbuf_dev); } } else { /* clean up */ if (client_data->acc_bufsample_cnt != 0) { for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_acc_cachepool, client_data->smi130_acc_samplist[i]); kmem_cache_destroy(client_data->smi_acc_cachepool); client_data->acc_bufsample_cnt = 0; } } /*SYN_CONFIG indicates end of data*/ input_event(client_data->accbuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF); input_sync(client_data->accbuf_dev); if (client_data->debug_level & 0x08) PINFO("End of acc samples bufsample_cnt=%d\n", client_data->acc_bufsample_cnt); return 0; } static ssize_t read_acc_boot_sample_show(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); return snprintf(buf, 16, "%u\n", smi130_acc->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 i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); unsigned long enable = 0; err = kstrtoul(buf, 10, &enable); if (err) return err; if (enable > 1) { PERR("Invalid value of input, input=%ld\n", enable); return -EINVAL; } err = smi_acc_read_bootsampl(smi130_acc, enable); if (err) return err; smi130_acc->read_acc_boot_sample = enable; return count; } #endif static DEVICE_ATTR(range, S_IRUGO | S_IWUSR, smi130_acc_range_show, smi130_acc_range_store); static DEVICE_ATTR(bandwidth, S_IRUGO | S_IWUSR, smi130_acc_bandwidth_show, smi130_acc_bandwidth_store); #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static DEVICE_ATTR(read_acc_boot_sample, 0644, read_acc_boot_sample_show, read_acc_boot_sample_store); #endif static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR, smi130_acc_mode_show, smi130_acc_mode_store); static DEVICE_ATTR(value, S_IRUSR, Loading Loading @@ -6555,6 +6691,9 @@ static DEVICE_ATTR(en_double_tap, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH, static struct attribute *smi130_acc_attributes[] = { &dev_attr_range.attr, &dev_attr_bandwidth.attr, #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING &dev_attr_read_acc_boot_sample.attr, #endif &dev_attr_op_mode.attr, &dev_attr_value.attr, &dev_attr_value_cache.attr, Loading Loading @@ -6752,6 +6891,136 @@ static void smi130_acc_slope_interrupt_handle(struct smi130_acc_data *smi130_acc } } #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static void store_acc_boot_sample(struct smi130_acc_data *client_data, int x, int y, int z, struct timespec ts) { if (false == client_data->acc_buffer_smi130_samples) return; if (ts.tv_sec < client_data->max_buffer_time) { if (client_data->acc_bufsample_cnt < SMI_ACC_MAXSAMPLE) { client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->xyz[0] = x; client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->xyz[1] = y; client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->xyz[2] = z; client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->tsec = ts.tv_sec; client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->tnsec = ts.tv_nsec; client_data->acc_bufsample_cnt++; } } else { PINFO("End of ACC buffering %d\n", client_data->acc_bufsample_cnt); client_data->acc_buffer_smi130_samples = false; } } #else static void store_acc_boot_sample(struct smi130_acc_data *client_data, int x, int y, int z, struct timespec ts) { } #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static int smi130_acc_early_buff_init(struct i2c_client *client, struct smi130_acc_data *client_data) { int i = 0, err = 0; client_data->acc_bufsample_cnt = 0; client_data->report_evt_cnt = 5; client_data->max_buffer_time = 40; client_data->smi_acc_cachepool = kmem_cache_create("acc_sensor_sample", sizeof(struct smi_acc_sample), 0, SLAB_HWCACHE_ALIGN, NULL); if (!client_data->smi_acc_cachepool) { PERR("smi_acc_cachepool cache create failed\n"); err = -ENOMEM; goto clean_exit1; } for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) { client_data->smi130_acc_samplist[i] = kmem_cache_alloc(client_data->smi_acc_cachepool, GFP_KERNEL); if (!client_data->smi130_acc_samplist[i]) { err = -ENOMEM; goto clean_exit2; } } client_data->accbuf_dev = input_allocate_device(); if (!client_data->accbuf_dev) { err = -ENOMEM; PERR("input device allocation failed\n"); goto clean_exit3; } client_data->accbuf_dev->name = "smi130_accbuf"; client_data->accbuf_dev->id.bustype = BUS_I2C; input_set_events_per_packet(client_data->accbuf_dev, client_data->report_evt_cnt * SMI_ACC_MAXSAMPLE); set_bit(EV_ABS, client_data->accbuf_dev->evbit); input_set_abs_params(client_data->accbuf_dev, ABS_X, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->accbuf_dev, ABS_Y, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->accbuf_dev, ABS_Z, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->accbuf_dev, ABS_RX, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->accbuf_dev, ABS_RY, -G_MAX, G_MAX, 0, 0); err = input_register_device(client_data->accbuf_dev); if (err) { PERR("unable to register input device %s\n", client_data->accbuf_dev->name); goto clean_exit3; } client_data->acc_buffer_smi130_samples = true; smi130_acc_set_mode(client, SMI_ACC2X2_MODE_NORMAL, 1); smi130_acc_set_bandwidth(client, SMI_ACC2X2_BW_62_50HZ); smi130_acc_set_range(client, SMI_ACC2X2_RANGE_2G); return 1; clean_exit3: input_free_device(client_data->accbuf_dev); clean_exit2: for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_acc_cachepool, client_data->smi130_acc_samplist[i]); clean_exit1: kmem_cache_destroy(client_data->smi_acc_cachepool); return 0; } static void smi130_acc_input_cleanup(struct smi130_acc_data *client_data) { int i = 0; input_unregister_device(client_data->accbuf_dev); input_free_device(client_data->accbuf_dev); for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_acc_cachepool, client_data->smi130_acc_samplist[i]); kmem_cache_destroy(client_data->smi_acc_cachepool); } #else static int smi130_acc_early_buff_init(struct i2c_client *client, struct smi130_acc_data *client_data) { return 1; } static void smi130_acc_input_cleanup(struct smi130_acc_data *client_data) { } #endif static void smi130_acc_irq_work_func(struct work_struct *work) { Loading Loading @@ -6800,6 +7069,7 @@ static void smi130_acc_irq_work_func(struct work_struct *work) smi130_acc->value = acc; mutex_unlock(&smi130_acc->value_mutex); } store_acc_boot_sample(smi130_acc, acc.x, acc.y, acc.z, ts); #endif smi130_acc_get_interruptstatus1(smi130_acc->smi130_acc_client, &status); Loading Loading @@ -7268,6 +7538,11 @@ static int smi130_acc_probe(struct i2c_client *client, PDEBUG("data->IRQ = %d", data->IRQ); err = request_irq(data->IRQ, smi130_acc_irq_handler, IRQF_TRIGGER_RISING, "smi130_acc", data); err = smi130_acc_early_buff_init(client, data); if (!err) goto exit; PINFO("SMI130_ACC driver probe successfully"); return 0; Loading Loading @@ -7379,6 +7654,7 @@ static int smi130_acc_remove(struct i2c_client *client) if (NULL == data) return 0; smi130_acc_input_cleanup(data); smi130_acc_set_enable(&client->dev, 0); #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&data->early_suspend); Loading drivers/input/sensors/smi130/smi130_gyro_driver.c +306 −3 Original line number Diff line number Diff line Loading @@ -249,6 +249,16 @@ struct bosch_sensor_data { }; }; #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING #define SMI_GYRO_MAXSAMPLE 4000 #define G_MAX 23920640 struct smi_gyro_sample { int xyz[3]; unsigned int tsec; unsigned long long tnsec; }; #endif struct smi_gyro_client_data { struct smi130_gyro_t device; struct i2c_client *client; Loading Loading @@ -281,6 +291,16 @@ struct smi_gyro_client_data { uint8_t gpio_pin; int16_t IRQ; struct work_struct irq_work; #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING bool read_gyro_boot_sample; int gyro_bufsample_cnt; bool gyro_buffer_smi130_samples; struct kmem_cache *smi_gyro_cachepool; struct smi_gyro_sample *smi130_gyro_samplist[SMI_GYRO_MAXSAMPLE]; int max_buffer_time; struct input_dev *gyrobuf_dev; int report_evt_cnt; #endif }; static struct i2c_client *smi_gyro_client; Loading Loading @@ -831,6 +851,23 @@ static ssize_t smi_gyro_show_chip_id(struct device *dev, return snprintf(buf, 16, "%d\n", SENSOR_CHIP_ID_SMI_GYRO); } #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static inline int smi130_check_gyro_early_buff_enable_flag( struct smi_gyro_client_data *client_data) { if (client_data->gyro_buffer_smi130_samples == true) return 1; else return 0; } #else static inline int smi130_check_gyro_early_buff_enable_flag( struct smi_gyro_client_data *client_data) { return 0; } #endif static ssize_t smi_gyro_show_op_mode(struct device *dev, struct device_attribute *attr, char *buf) { Loading Loading @@ -858,6 +895,10 @@ static ssize_t smi_gyro_store_op_mode(struct device *dev, long op_mode; err = smi130_check_gyro_early_buff_enable_flag(client_data); if (err) return count; err = kstrtoul(buf, 10, &op_mode); if (err) return err; Loading Loading @@ -911,6 +952,13 @@ static ssize_t smi_gyro_store_range(struct device *dev, { int err; unsigned long range; struct input_dev *input = to_input_dev(dev); struct smi_gyro_client_data *client_data = input_get_drvdata(input); err = smi130_check_gyro_early_buff_enable_flag(client_data); if (err) return count; err = kstrtoul(buf, 10, &range); if (err) return err; Loading Loading @@ -952,6 +1000,11 @@ static ssize_t smi_gyro_store_bandwidth(struct device *dev, struct smi_gyro_client_data *client_data = input_get_drvdata(input); unsigned long bandwidth; u8 op_mode = 0xff; err = smi130_check_gyro_early_buff_enable_flag(client_data); if (err) return count; err = kstrtoul(buf, 10, &bandwidth); if (err) return err; Loading Loading @@ -1445,8 +1498,96 @@ static ssize_t smi130_gyro_driver_version_show(struct device *dev DRIVER_VERSION); return ret; } #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static int smi_gyro_read_bootsampl(struct smi_gyro_client_data *client_data, unsigned long enable_read) { int i = 0; if (enable_read) { client_data->gyro_buffer_smi130_samples = false; for (i = 0; i < client_data->gyro_bufsample_cnt; i++) { if (client_data->debug_level & 0x08) PINFO("gyro=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n", i, client_data->smi130_gyro_samplist[i]->xyz[0], client_data->smi130_gyro_samplist[i]->xyz[1], client_data->smi130_gyro_samplist[i]->xyz[2], client_data->smi130_gyro_samplist[i]->tsec, client_data->smi130_gyro_samplist[i]->tnsec); input_report_abs(client_data->gyrobuf_dev, ABS_X, client_data->smi130_gyro_samplist[i]->xyz[0]); input_report_abs(client_data->gyrobuf_dev, ABS_Y, client_data->smi130_gyro_samplist[i]->xyz[1]); input_report_abs(client_data->gyrobuf_dev, ABS_Z, client_data->smi130_gyro_samplist[i]->xyz[2]); input_report_abs(client_data->gyrobuf_dev, ABS_RX, client_data->smi130_gyro_samplist[i]->tsec); input_report_abs(client_data->gyrobuf_dev, ABS_RY, client_data->smi130_gyro_samplist[i]->tnsec); input_sync(client_data->gyrobuf_dev); } } else { /* clean up */ if (client_data->gyro_bufsample_cnt != 0) { for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_gyro_cachepool, client_data->smi130_gyro_samplist[i]); kmem_cache_destroy(client_data->smi_gyro_cachepool); client_data->gyro_bufsample_cnt = 0; } } /*SYN_CONFIG indicates end of data*/ input_event(client_data->gyrobuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF); input_sync(client_data->gyrobuf_dev); if (client_data->debug_level & 0x08) PINFO("End of gyro samples bufsample_cnt=%d\n", client_data->gyro_bufsample_cnt); return 0; } static ssize_t read_gyro_boot_sample_show(struct device *dev, struct device_attribute *attr, char *buf) { struct input_dev *input = to_input_dev(dev); struct smi_gyro_client_data *client_data = input_get_drvdata(input); return snprintf(buf, 16, "%u\n", client_data->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; struct input_dev *input = to_input_dev(dev); struct smi_gyro_client_data *client_data = input_get_drvdata(input); unsigned long enable = 0; err = kstrtoul(buf, 10, &enable); if (err) return err; if (enable > 1) { PERR("Invalid value of input, input=%ld\n", enable); return -EINVAL; } err = smi_gyro_read_bootsampl(client_data, enable); if (err) return err; client_data->read_gyro_boot_sample = enable; return count; } #endif static DEVICE_ATTR(chip_id, S_IRUSR, smi_gyro_show_chip_id, NULL); #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static DEVICE_ATTR(read_gyro_boot_sample, 0644, read_gyro_boot_sample_show, read_gyro_boot_sample_store); #endif static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR, smi_gyro_show_op_mode, smi_gyro_store_op_mode); static DEVICE_ATTR(value, S_IRUSR, Loading Loading @@ -1500,6 +1641,9 @@ static DEVICE_ATTR(fifo_tag, S_IRUGO | S_IWUSR, static struct attribute *smi_gyro_attributes[] = { &dev_attr_chip_id.attr, #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING &dev_attr_read_gyro_boot_sample.attr, #endif &dev_attr_op_mode.attr, &dev_attr_value.attr, &dev_attr_range.attr, Loading Loading @@ -1574,6 +1718,159 @@ static void smi_gyro_input_destroy(struct smi_gyro_client_data *client_data) input_unregister_device(dev); input_free_device(dev); } #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data, int x, int y, int z, struct timespec ts) { if (false == client_data->gyro_buffer_smi130_samples) return; if (ts.tv_sec < client_data->max_buffer_time) { if (client_data->gyro_bufsample_cnt < SMI_GYRO_MAXSAMPLE) { client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->xyz[0] = x; client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->xyz[1] = y; client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->xyz[2] = z; client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->tsec = ts.tv_sec; client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->tnsec = ts.tv_nsec; client_data->gyro_bufsample_cnt++; } } else { PINFO("End of GYRO buffering %d", client_data->gyro_bufsample_cnt); client_data->gyro_buffer_smi130_samples = false; } } #else static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data, int x, int y, int z, struct timespec ts) { } #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data) { int i = 0, err = 0; client_data->gyro_bufsample_cnt = 0; client_data->report_evt_cnt = 5; client_data->max_buffer_time = 40; client_data->smi_gyro_cachepool = kmem_cache_create("gyro_sensor_sample" , sizeof(struct smi_gyro_sample), 0, SLAB_HWCACHE_ALIGN, NULL); if (!client_data->smi_gyro_cachepool) { PERR("smi_gyro_cachepool cache create failed\n"); err = -ENOMEM; goto clean_exit1; } for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) { client_data->smi130_gyro_samplist[i] = kmem_cache_alloc(client_data->smi_gyro_cachepool, GFP_KERNEL); if (!client_data->smi130_gyro_samplist[i]) { err = -ENOMEM; goto clean_exit2; } } client_data->gyrobuf_dev = input_allocate_device(); if (!client_data->gyrobuf_dev) { err = -ENOMEM; PERR("input device allocation failed\n"); goto clean_exit3; } client_data->gyrobuf_dev->name = "smi130_gyrobuf"; client_data->gyrobuf_dev->id.bustype = BUS_I2C; input_set_events_per_packet(client_data->gyrobuf_dev, client_data->report_evt_cnt * SMI_GYRO_MAXSAMPLE); set_bit(EV_ABS, client_data->gyrobuf_dev->evbit); input_set_abs_params(client_data->gyrobuf_dev, ABS_X, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->gyrobuf_dev, ABS_Y, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->gyrobuf_dev, ABS_Z, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->gyrobuf_dev, ABS_RX, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->gyrobuf_dev, ABS_RY, -G_MAX, G_MAX, 0, 0); err = input_register_device(client_data->gyrobuf_dev); if (err) { PERR("unable to register input device %s\n", client_data->gyrobuf_dev->name); goto clean_exit3; } client_data->gyro_buffer_smi130_samples = true; smi130_gyro_set_mode(SMI130_GYRO_MODE_NORMAL); smi130_gyro_delay(5); smi130_gyro_set_bw(5); smi130_gyro_delay(5); smi130_gyro_set_range_reg(4); smi130_gyro_delay(5); smi130_gyro_set_mode(SMI130_GYRO_MODE_NORMAL); smi130_gyro_delay(5); smi130_gyro_set_range_reg(4); smi130_gyro_delay(5); smi130_gyro_set_data_en(SMI130_GYRO_ENABLE); return 1; clean_exit3: input_free_device(client_data->gyrobuf_dev); clean_exit2: for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_gyro_cachepool, client_data->smi130_gyro_samplist[i]); clean_exit1: kmem_cache_destroy(client_data->smi_gyro_cachepool); return 0; } static void smi130_gyro_input_cleanup(struct smi_gyro_client_data *client_data) { int i = 0; input_unregister_device(client_data->gyrobuf_dev); input_free_device(client_data->gyrobuf_dev); for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_gyro_cachepool, client_data->smi130_gyro_samplist[i]); kmem_cache_destroy(client_data->smi_gyro_cachepool); } static int smi130_enable_int1(void) { return smi130_gyro_set_data_en(SMI130_GYRO_DISABLE); } #else static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data) { return 1; } static void smi130_gyro_input_cleanup(struct smi_gyro_client_data *client_data) { } static int smi130_enable_int1(void) { return smi130_gyro_set_data_en(SMI130_GYRO_ENABLE); } #endif #if defined(SMI130_GYRO_ENABLE_INT1) || defined(SMI130_GYRO_ENABLE_INT2) static void smi130_gyro_irq_work_func(struct work_struct *work) Loading @@ -1598,7 +1895,8 @@ static void smi130_gyro_irq_work_func(struct work_struct *work) input_event(client_data->input, EV_MSC, MSC_SCAN, gyro_data.dataz); input_sync(client_data->input); store_gyro_boot_sample(client_data, gyro_data.datax, gyro_data.datay, gyro_data.dataz, ts); } static irqreturn_t smi_gyro_irq_handler(int irq, void *handle) Loading Loading @@ -1727,7 +2025,7 @@ static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id smi130_gyro_delay(5); err += smi130_gyro_set_int_data(SMI130_GYRO_INT1_DATA, SMI130_GYRO_ENABLE); smi130_gyro_delay(5); err += smi130_gyro_set_data_en(SMI130_GYRO_ENABLE); err += smi130_enable_int1(); smi130_gyro_delay(5); /*default odr is 100HZ*/ err += SMI_GYRO_CALL_API(set_bw)(7); Loading Loading @@ -1786,6 +2084,11 @@ static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id } INIT_WORK(&client_data->irq_work, smi130_gyro_irq_work_func); #endif err = smi130_gyro_early_buff_init(client_data); if (!err) return err; PINFO("sensor %s probed successfully", SENSOR_NAME); dev_dbg(&client->dev, Loading Loading @@ -1926,6 +2229,7 @@ static int smi_gyro_remove(struct i2c_client *client) #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&client_data->early_suspend_handler); #endif smi130_gyro_input_cleanup(client_data); mutex_lock(&client_data->mutex_op_mode); SMI_GYRO_CALL_API(get_mode)(&op_mode); if (SMI_GYRO_VAL_NAME(MODE_NORMAL) == op_mode) { Loading @@ -1942,7 +2246,6 @@ static int smi_gyro_remove(struct i2c_client *client) &smi_gyro_attribute_group); smi_gyro_input_destroy(client_data); kfree(client_data); smi_gyro_client = NULL; } Loading Loading
drivers/input/sensors/smi130/Kconfig +8 −0 Original line number Diff line number Diff line Loading @@ -126,4 +126,12 @@ depends on SENSORS_SMI_ACC4XY help If you say yes here, you get support for Bosch Sensortec's sensor driver of SMI_ACC4XY with mag sensor support. config ENABLE_SMI_ACC_GYRO_BUFFERING bool "Enable accel & gyro boot time sensor sample buffering" depends on SMI130 help Say Y here if you want to buffer boot time sensor samples for ASM330 accelerometer and gyroscope endif
drivers/input/sensors/smi130/smi130_acc.c +276 −0 Original line number Diff line number Diff line Loading @@ -1528,6 +1528,16 @@ struct bosch_sensor_data { }; }; #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING #define SMI_ACC_MAXSAMPLE 4000 #define G_MAX 23920640 struct smi_acc_sample { int xyz[3]; unsigned int tsec; unsigned long long tnsec; }; #endif struct smi130_accacc { s16 x; s16 y; Loading Loading @@ -1590,6 +1600,16 @@ struct smi130_acc_data { struct timer_list tap_timer; int tap_time_period; #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING bool read_acc_boot_sample; int acc_bufsample_cnt; bool acc_buffer_smi130_samples; struct kmem_cache *smi_acc_cachepool; struct smi_acc_sample *smi130_acc_samplist[SMI_ACC_MAXSAMPLE]; int max_buffer_time; struct input_dev *accbuf_dev; int report_evt_cnt; #endif }; #ifdef CONFIG_HAS_EARLYSUSPEND Loading Loading @@ -4044,6 +4064,23 @@ static int smi130_acc_read_temperature(struct i2c_client *client, return comres; } #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static inline int smi130_check_acc_early_buff_enable_flag( struct smi130_acc_data *client_data) { if (client_data->acc_buffer_smi130_samples == true) return 1; else return 0; } #else static inline int smi130_check_acc_early_buff_enable_flag( struct smi130_acc_data *client_data) { return 0; } #endif static ssize_t smi130_acc_enable_int_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) Loading Loading @@ -5365,6 +5402,10 @@ static ssize_t smi130_acc_range_store(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); error = smi130_check_acc_early_buff_enable_flag(smi130_acc); if (error) return count; error = kstrtoul(buf, 10, &data); if (error) return error; Loading Loading @@ -5397,6 +5438,10 @@ static ssize_t smi130_acc_bandwidth_store(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); error = smi130_check_acc_early_buff_enable_flag(smi130_acc); if (error) return count; error = kstrtoul(buf, 10, &data); if (error) return error; Loading Loading @@ -5436,6 +5481,10 @@ static ssize_t smi130_acc_mode_store(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); error = smi130_check_acc_early_buff_enable_flag(smi130_acc); if (error) return count; error = kstrtoul(buf, 10, &data); if (error) return error; Loading Loading @@ -6432,10 +6481,97 @@ static void smi130_acc_tap_timeout_handle(unsigned long data) } #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static int smi_acc_read_bootsampl(struct smi130_acc_data *client_data, unsigned long enable_read) { int i = 0; if (enable_read) { client_data->acc_buffer_smi130_samples = false; for (i = 0; i < client_data->acc_bufsample_cnt; i++) { if (client_data->debug_level & 0x08) PINFO("acc=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n", i, client_data->smi130_acc_samplist[i]->xyz[0], client_data->smi130_acc_samplist[i]->xyz[1], client_data->smi130_acc_samplist[i]->xyz[2], client_data->smi130_acc_samplist[i]->tsec, client_data->smi130_acc_samplist[i]->tnsec); input_report_abs(client_data->accbuf_dev, ABS_X, client_data->smi130_acc_samplist[i]->xyz[0]); input_report_abs(client_data->accbuf_dev, ABS_Y, client_data->smi130_acc_samplist[i]->xyz[1]); input_report_abs(client_data->accbuf_dev, ABS_Z, client_data->smi130_acc_samplist[i]->xyz[2]); input_report_abs(client_data->accbuf_dev, ABS_RX, client_data->smi130_acc_samplist[i]->tsec); input_report_abs(client_data->accbuf_dev, ABS_RY, client_data->smi130_acc_samplist[i]->tnsec); input_sync(client_data->accbuf_dev); } } else { /* clean up */ if (client_data->acc_bufsample_cnt != 0) { for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_acc_cachepool, client_data->smi130_acc_samplist[i]); kmem_cache_destroy(client_data->smi_acc_cachepool); client_data->acc_bufsample_cnt = 0; } } /*SYN_CONFIG indicates end of data*/ input_event(client_data->accbuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF); input_sync(client_data->accbuf_dev); if (client_data->debug_level & 0x08) PINFO("End of acc samples bufsample_cnt=%d\n", client_data->acc_bufsample_cnt); return 0; } static ssize_t read_acc_boot_sample_show(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); return snprintf(buf, 16, "%u\n", smi130_acc->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 i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); unsigned long enable = 0; err = kstrtoul(buf, 10, &enable); if (err) return err; if (enable > 1) { PERR("Invalid value of input, input=%ld\n", enable); return -EINVAL; } err = smi_acc_read_bootsampl(smi130_acc, enable); if (err) return err; smi130_acc->read_acc_boot_sample = enable; return count; } #endif static DEVICE_ATTR(range, S_IRUGO | S_IWUSR, smi130_acc_range_show, smi130_acc_range_store); static DEVICE_ATTR(bandwidth, S_IRUGO | S_IWUSR, smi130_acc_bandwidth_show, smi130_acc_bandwidth_store); #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static DEVICE_ATTR(read_acc_boot_sample, 0644, read_acc_boot_sample_show, read_acc_boot_sample_store); #endif static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR, smi130_acc_mode_show, smi130_acc_mode_store); static DEVICE_ATTR(value, S_IRUSR, Loading Loading @@ -6555,6 +6691,9 @@ static DEVICE_ATTR(en_double_tap, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH, static struct attribute *smi130_acc_attributes[] = { &dev_attr_range.attr, &dev_attr_bandwidth.attr, #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING &dev_attr_read_acc_boot_sample.attr, #endif &dev_attr_op_mode.attr, &dev_attr_value.attr, &dev_attr_value_cache.attr, Loading Loading @@ -6752,6 +6891,136 @@ static void smi130_acc_slope_interrupt_handle(struct smi130_acc_data *smi130_acc } } #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static void store_acc_boot_sample(struct smi130_acc_data *client_data, int x, int y, int z, struct timespec ts) { if (false == client_data->acc_buffer_smi130_samples) return; if (ts.tv_sec < client_data->max_buffer_time) { if (client_data->acc_bufsample_cnt < SMI_ACC_MAXSAMPLE) { client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->xyz[0] = x; client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->xyz[1] = y; client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->xyz[2] = z; client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->tsec = ts.tv_sec; client_data->smi130_acc_samplist[client_data-> acc_bufsample_cnt]->tnsec = ts.tv_nsec; client_data->acc_bufsample_cnt++; } } else { PINFO("End of ACC buffering %d\n", client_data->acc_bufsample_cnt); client_data->acc_buffer_smi130_samples = false; } } #else static void store_acc_boot_sample(struct smi130_acc_data *client_data, int x, int y, int z, struct timespec ts) { } #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static int smi130_acc_early_buff_init(struct i2c_client *client, struct smi130_acc_data *client_data) { int i = 0, err = 0; client_data->acc_bufsample_cnt = 0; client_data->report_evt_cnt = 5; client_data->max_buffer_time = 40; client_data->smi_acc_cachepool = kmem_cache_create("acc_sensor_sample", sizeof(struct smi_acc_sample), 0, SLAB_HWCACHE_ALIGN, NULL); if (!client_data->smi_acc_cachepool) { PERR("smi_acc_cachepool cache create failed\n"); err = -ENOMEM; goto clean_exit1; } for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) { client_data->smi130_acc_samplist[i] = kmem_cache_alloc(client_data->smi_acc_cachepool, GFP_KERNEL); if (!client_data->smi130_acc_samplist[i]) { err = -ENOMEM; goto clean_exit2; } } client_data->accbuf_dev = input_allocate_device(); if (!client_data->accbuf_dev) { err = -ENOMEM; PERR("input device allocation failed\n"); goto clean_exit3; } client_data->accbuf_dev->name = "smi130_accbuf"; client_data->accbuf_dev->id.bustype = BUS_I2C; input_set_events_per_packet(client_data->accbuf_dev, client_data->report_evt_cnt * SMI_ACC_MAXSAMPLE); set_bit(EV_ABS, client_data->accbuf_dev->evbit); input_set_abs_params(client_data->accbuf_dev, ABS_X, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->accbuf_dev, ABS_Y, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->accbuf_dev, ABS_Z, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->accbuf_dev, ABS_RX, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->accbuf_dev, ABS_RY, -G_MAX, G_MAX, 0, 0); err = input_register_device(client_data->accbuf_dev); if (err) { PERR("unable to register input device %s\n", client_data->accbuf_dev->name); goto clean_exit3; } client_data->acc_buffer_smi130_samples = true; smi130_acc_set_mode(client, SMI_ACC2X2_MODE_NORMAL, 1); smi130_acc_set_bandwidth(client, SMI_ACC2X2_BW_62_50HZ); smi130_acc_set_range(client, SMI_ACC2X2_RANGE_2G); return 1; clean_exit3: input_free_device(client_data->accbuf_dev); clean_exit2: for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_acc_cachepool, client_data->smi130_acc_samplist[i]); clean_exit1: kmem_cache_destroy(client_data->smi_acc_cachepool); return 0; } static void smi130_acc_input_cleanup(struct smi130_acc_data *client_data) { int i = 0; input_unregister_device(client_data->accbuf_dev); input_free_device(client_data->accbuf_dev); for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_acc_cachepool, client_data->smi130_acc_samplist[i]); kmem_cache_destroy(client_data->smi_acc_cachepool); } #else static int smi130_acc_early_buff_init(struct i2c_client *client, struct smi130_acc_data *client_data) { return 1; } static void smi130_acc_input_cleanup(struct smi130_acc_data *client_data) { } #endif static void smi130_acc_irq_work_func(struct work_struct *work) { Loading Loading @@ -6800,6 +7069,7 @@ static void smi130_acc_irq_work_func(struct work_struct *work) smi130_acc->value = acc; mutex_unlock(&smi130_acc->value_mutex); } store_acc_boot_sample(smi130_acc, acc.x, acc.y, acc.z, ts); #endif smi130_acc_get_interruptstatus1(smi130_acc->smi130_acc_client, &status); Loading Loading @@ -7268,6 +7538,11 @@ static int smi130_acc_probe(struct i2c_client *client, PDEBUG("data->IRQ = %d", data->IRQ); err = request_irq(data->IRQ, smi130_acc_irq_handler, IRQF_TRIGGER_RISING, "smi130_acc", data); err = smi130_acc_early_buff_init(client, data); if (!err) goto exit; PINFO("SMI130_ACC driver probe successfully"); return 0; Loading Loading @@ -7379,6 +7654,7 @@ static int smi130_acc_remove(struct i2c_client *client) if (NULL == data) return 0; smi130_acc_input_cleanup(data); smi130_acc_set_enable(&client->dev, 0); #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&data->early_suspend); Loading
drivers/input/sensors/smi130/smi130_gyro_driver.c +306 −3 Original line number Diff line number Diff line Loading @@ -249,6 +249,16 @@ struct bosch_sensor_data { }; }; #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING #define SMI_GYRO_MAXSAMPLE 4000 #define G_MAX 23920640 struct smi_gyro_sample { int xyz[3]; unsigned int tsec; unsigned long long tnsec; }; #endif struct smi_gyro_client_data { struct smi130_gyro_t device; struct i2c_client *client; Loading Loading @@ -281,6 +291,16 @@ struct smi_gyro_client_data { uint8_t gpio_pin; int16_t IRQ; struct work_struct irq_work; #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING bool read_gyro_boot_sample; int gyro_bufsample_cnt; bool gyro_buffer_smi130_samples; struct kmem_cache *smi_gyro_cachepool; struct smi_gyro_sample *smi130_gyro_samplist[SMI_GYRO_MAXSAMPLE]; int max_buffer_time; struct input_dev *gyrobuf_dev; int report_evt_cnt; #endif }; static struct i2c_client *smi_gyro_client; Loading Loading @@ -831,6 +851,23 @@ static ssize_t smi_gyro_show_chip_id(struct device *dev, return snprintf(buf, 16, "%d\n", SENSOR_CHIP_ID_SMI_GYRO); } #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static inline int smi130_check_gyro_early_buff_enable_flag( struct smi_gyro_client_data *client_data) { if (client_data->gyro_buffer_smi130_samples == true) return 1; else return 0; } #else static inline int smi130_check_gyro_early_buff_enable_flag( struct smi_gyro_client_data *client_data) { return 0; } #endif static ssize_t smi_gyro_show_op_mode(struct device *dev, struct device_attribute *attr, char *buf) { Loading Loading @@ -858,6 +895,10 @@ static ssize_t smi_gyro_store_op_mode(struct device *dev, long op_mode; err = smi130_check_gyro_early_buff_enable_flag(client_data); if (err) return count; err = kstrtoul(buf, 10, &op_mode); if (err) return err; Loading Loading @@ -911,6 +952,13 @@ static ssize_t smi_gyro_store_range(struct device *dev, { int err; unsigned long range; struct input_dev *input = to_input_dev(dev); struct smi_gyro_client_data *client_data = input_get_drvdata(input); err = smi130_check_gyro_early_buff_enable_flag(client_data); if (err) return count; err = kstrtoul(buf, 10, &range); if (err) return err; Loading Loading @@ -952,6 +1000,11 @@ static ssize_t smi_gyro_store_bandwidth(struct device *dev, struct smi_gyro_client_data *client_data = input_get_drvdata(input); unsigned long bandwidth; u8 op_mode = 0xff; err = smi130_check_gyro_early_buff_enable_flag(client_data); if (err) return count; err = kstrtoul(buf, 10, &bandwidth); if (err) return err; Loading Loading @@ -1445,8 +1498,96 @@ static ssize_t smi130_gyro_driver_version_show(struct device *dev DRIVER_VERSION); return ret; } #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static int smi_gyro_read_bootsampl(struct smi_gyro_client_data *client_data, unsigned long enable_read) { int i = 0; if (enable_read) { client_data->gyro_buffer_smi130_samples = false; for (i = 0; i < client_data->gyro_bufsample_cnt; i++) { if (client_data->debug_level & 0x08) PINFO("gyro=%d,x=%d,y=%d,z=%d,sec=%d,ns=%lld\n", i, client_data->smi130_gyro_samplist[i]->xyz[0], client_data->smi130_gyro_samplist[i]->xyz[1], client_data->smi130_gyro_samplist[i]->xyz[2], client_data->smi130_gyro_samplist[i]->tsec, client_data->smi130_gyro_samplist[i]->tnsec); input_report_abs(client_data->gyrobuf_dev, ABS_X, client_data->smi130_gyro_samplist[i]->xyz[0]); input_report_abs(client_data->gyrobuf_dev, ABS_Y, client_data->smi130_gyro_samplist[i]->xyz[1]); input_report_abs(client_data->gyrobuf_dev, ABS_Z, client_data->smi130_gyro_samplist[i]->xyz[2]); input_report_abs(client_data->gyrobuf_dev, ABS_RX, client_data->smi130_gyro_samplist[i]->tsec); input_report_abs(client_data->gyrobuf_dev, ABS_RY, client_data->smi130_gyro_samplist[i]->tnsec); input_sync(client_data->gyrobuf_dev); } } else { /* clean up */ if (client_data->gyro_bufsample_cnt != 0) { for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_gyro_cachepool, client_data->smi130_gyro_samplist[i]); kmem_cache_destroy(client_data->smi_gyro_cachepool); client_data->gyro_bufsample_cnt = 0; } } /*SYN_CONFIG indicates end of data*/ input_event(client_data->gyrobuf_dev, EV_SYN, SYN_CONFIG, 0xFFFFFFFF); input_sync(client_data->gyrobuf_dev); if (client_data->debug_level & 0x08) PINFO("End of gyro samples bufsample_cnt=%d\n", client_data->gyro_bufsample_cnt); return 0; } static ssize_t read_gyro_boot_sample_show(struct device *dev, struct device_attribute *attr, char *buf) { struct input_dev *input = to_input_dev(dev); struct smi_gyro_client_data *client_data = input_get_drvdata(input); return snprintf(buf, 16, "%u\n", client_data->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; struct input_dev *input = to_input_dev(dev); struct smi_gyro_client_data *client_data = input_get_drvdata(input); unsigned long enable = 0; err = kstrtoul(buf, 10, &enable); if (err) return err; if (enable > 1) { PERR("Invalid value of input, input=%ld\n", enable); return -EINVAL; } err = smi_gyro_read_bootsampl(client_data, enable); if (err) return err; client_data->read_gyro_boot_sample = enable; return count; } #endif static DEVICE_ATTR(chip_id, S_IRUSR, smi_gyro_show_chip_id, NULL); #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static DEVICE_ATTR(read_gyro_boot_sample, 0644, read_gyro_boot_sample_show, read_gyro_boot_sample_store); #endif static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR, smi_gyro_show_op_mode, smi_gyro_store_op_mode); static DEVICE_ATTR(value, S_IRUSR, Loading Loading @@ -1500,6 +1641,9 @@ static DEVICE_ATTR(fifo_tag, S_IRUGO | S_IWUSR, static struct attribute *smi_gyro_attributes[] = { &dev_attr_chip_id.attr, #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING &dev_attr_read_gyro_boot_sample.attr, #endif &dev_attr_op_mode.attr, &dev_attr_value.attr, &dev_attr_range.attr, Loading Loading @@ -1574,6 +1718,159 @@ static void smi_gyro_input_destroy(struct smi_gyro_client_data *client_data) input_unregister_device(dev); input_free_device(dev); } #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data, int x, int y, int z, struct timespec ts) { if (false == client_data->gyro_buffer_smi130_samples) return; if (ts.tv_sec < client_data->max_buffer_time) { if (client_data->gyro_bufsample_cnt < SMI_GYRO_MAXSAMPLE) { client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->xyz[0] = x; client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->xyz[1] = y; client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->xyz[2] = z; client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->tsec = ts.tv_sec; client_data->smi130_gyro_samplist[client_data-> gyro_bufsample_cnt]->tnsec = ts.tv_nsec; client_data->gyro_bufsample_cnt++; } } else { PINFO("End of GYRO buffering %d", client_data->gyro_bufsample_cnt); client_data->gyro_buffer_smi130_samples = false; } } #else static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data, int x, int y, int z, struct timespec ts) { } #endif #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data) { int i = 0, err = 0; client_data->gyro_bufsample_cnt = 0; client_data->report_evt_cnt = 5; client_data->max_buffer_time = 40; client_data->smi_gyro_cachepool = kmem_cache_create("gyro_sensor_sample" , sizeof(struct smi_gyro_sample), 0, SLAB_HWCACHE_ALIGN, NULL); if (!client_data->smi_gyro_cachepool) { PERR("smi_gyro_cachepool cache create failed\n"); err = -ENOMEM; goto clean_exit1; } for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) { client_data->smi130_gyro_samplist[i] = kmem_cache_alloc(client_data->smi_gyro_cachepool, GFP_KERNEL); if (!client_data->smi130_gyro_samplist[i]) { err = -ENOMEM; goto clean_exit2; } } client_data->gyrobuf_dev = input_allocate_device(); if (!client_data->gyrobuf_dev) { err = -ENOMEM; PERR("input device allocation failed\n"); goto clean_exit3; } client_data->gyrobuf_dev->name = "smi130_gyrobuf"; client_data->gyrobuf_dev->id.bustype = BUS_I2C; input_set_events_per_packet(client_data->gyrobuf_dev, client_data->report_evt_cnt * SMI_GYRO_MAXSAMPLE); set_bit(EV_ABS, client_data->gyrobuf_dev->evbit); input_set_abs_params(client_data->gyrobuf_dev, ABS_X, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->gyrobuf_dev, ABS_Y, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->gyrobuf_dev, ABS_Z, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->gyrobuf_dev, ABS_RX, -G_MAX, G_MAX, 0, 0); input_set_abs_params(client_data->gyrobuf_dev, ABS_RY, -G_MAX, G_MAX, 0, 0); err = input_register_device(client_data->gyrobuf_dev); if (err) { PERR("unable to register input device %s\n", client_data->gyrobuf_dev->name); goto clean_exit3; } client_data->gyro_buffer_smi130_samples = true; smi130_gyro_set_mode(SMI130_GYRO_MODE_NORMAL); smi130_gyro_delay(5); smi130_gyro_set_bw(5); smi130_gyro_delay(5); smi130_gyro_set_range_reg(4); smi130_gyro_delay(5); smi130_gyro_set_mode(SMI130_GYRO_MODE_NORMAL); smi130_gyro_delay(5); smi130_gyro_set_range_reg(4); smi130_gyro_delay(5); smi130_gyro_set_data_en(SMI130_GYRO_ENABLE); return 1; clean_exit3: input_free_device(client_data->gyrobuf_dev); clean_exit2: for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_gyro_cachepool, client_data->smi130_gyro_samplist[i]); clean_exit1: kmem_cache_destroy(client_data->smi_gyro_cachepool); return 0; } static void smi130_gyro_input_cleanup(struct smi_gyro_client_data *client_data) { int i = 0; input_unregister_device(client_data->gyrobuf_dev); input_free_device(client_data->gyrobuf_dev); for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) kmem_cache_free(client_data->smi_gyro_cachepool, client_data->smi130_gyro_samplist[i]); kmem_cache_destroy(client_data->smi_gyro_cachepool); } static int smi130_enable_int1(void) { return smi130_gyro_set_data_en(SMI130_GYRO_DISABLE); } #else static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data) { return 1; } static void smi130_gyro_input_cleanup(struct smi_gyro_client_data *client_data) { } static int smi130_enable_int1(void) { return smi130_gyro_set_data_en(SMI130_GYRO_ENABLE); } #endif #if defined(SMI130_GYRO_ENABLE_INT1) || defined(SMI130_GYRO_ENABLE_INT2) static void smi130_gyro_irq_work_func(struct work_struct *work) Loading @@ -1598,7 +1895,8 @@ static void smi130_gyro_irq_work_func(struct work_struct *work) input_event(client_data->input, EV_MSC, MSC_SCAN, gyro_data.dataz); input_sync(client_data->input); store_gyro_boot_sample(client_data, gyro_data.datax, gyro_data.datay, gyro_data.dataz, ts); } static irqreturn_t smi_gyro_irq_handler(int irq, void *handle) Loading Loading @@ -1727,7 +2025,7 @@ static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id smi130_gyro_delay(5); err += smi130_gyro_set_int_data(SMI130_GYRO_INT1_DATA, SMI130_GYRO_ENABLE); smi130_gyro_delay(5); err += smi130_gyro_set_data_en(SMI130_GYRO_ENABLE); err += smi130_enable_int1(); smi130_gyro_delay(5); /*default odr is 100HZ*/ err += SMI_GYRO_CALL_API(set_bw)(7); Loading Loading @@ -1786,6 +2084,11 @@ static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id } INIT_WORK(&client_data->irq_work, smi130_gyro_irq_work_func); #endif err = smi130_gyro_early_buff_init(client_data); if (!err) return err; PINFO("sensor %s probed successfully", SENSOR_NAME); dev_dbg(&client->dev, Loading Loading @@ -1926,6 +2229,7 @@ static int smi_gyro_remove(struct i2c_client *client) #ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&client_data->early_suspend_handler); #endif smi130_gyro_input_cleanup(client_data); mutex_lock(&client_data->mutex_op_mode); SMI_GYRO_CALL_API(get_mode)(&op_mode); if (SMI_GYRO_VAL_NAME(MODE_NORMAL) == op_mode) { Loading @@ -1942,7 +2246,6 @@ static int smi_gyro_remove(struct i2c_client *client) &smi_gyro_attribute_group); smi_gyro_input_destroy(client_data); kfree(client_data); smi_gyro_client = NULL; } Loading