123491b51SDenis Ciocca /* 223491b51SDenis Ciocca * STMicroelectronics sensors core library driver 323491b51SDenis Ciocca * 423491b51SDenis Ciocca * Copyright 2012-2013 STMicroelectronics Inc. 523491b51SDenis Ciocca * 623491b51SDenis Ciocca * Denis Ciocca <denis.ciocca@st.com> 723491b51SDenis Ciocca * 823491b51SDenis Ciocca * Licensed under the GPL-2. 923491b51SDenis Ciocca */ 1023491b51SDenis Ciocca 1123491b51SDenis Ciocca #include <linux/kernel.h> 1223491b51SDenis Ciocca #include <linux/module.h> 1323491b51SDenis Ciocca #include <linux/slab.h> 1423491b51SDenis Ciocca #include <linux/delay.h> 1523491b51SDenis Ciocca #include <linux/iio/iio.h> 1623491b51SDenis Ciocca #include <asm/unaligned.h> 1723491b51SDenis Ciocca 1823491b51SDenis Ciocca #include <linux/iio/common/st_sensors.h> 1923491b51SDenis Ciocca 2023491b51SDenis Ciocca 2123491b51SDenis Ciocca #define ST_SENSORS_WAI_ADDRESS 0x0f 2223491b51SDenis Ciocca 2323491b51SDenis Ciocca static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, 2423491b51SDenis Ciocca u8 reg_addr, u8 mask, u8 data) 2523491b51SDenis Ciocca { 2623491b51SDenis Ciocca int err; 2723491b51SDenis Ciocca u8 new_data; 2823491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 2923491b51SDenis Ciocca 3023491b51SDenis Ciocca err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data); 3123491b51SDenis Ciocca if (err < 0) 3223491b51SDenis Ciocca goto st_sensors_write_data_with_mask_error; 3323491b51SDenis Ciocca 3423491b51SDenis Ciocca new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask)); 3523491b51SDenis Ciocca err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data); 3623491b51SDenis Ciocca 3723491b51SDenis Ciocca st_sensors_write_data_with_mask_error: 3823491b51SDenis Ciocca return err; 3923491b51SDenis Ciocca } 4023491b51SDenis Ciocca 4123491b51SDenis Ciocca static int st_sensors_match_odr(struct st_sensors *sensor, 4223491b51SDenis Ciocca unsigned int odr, struct st_sensor_odr_avl *odr_out) 4323491b51SDenis Ciocca { 4423491b51SDenis Ciocca int i, ret = -EINVAL; 4523491b51SDenis Ciocca 4623491b51SDenis Ciocca for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) { 4723491b51SDenis Ciocca if (sensor->odr.odr_avl[i].hz == 0) 4823491b51SDenis Ciocca goto st_sensors_match_odr_error; 4923491b51SDenis Ciocca 5023491b51SDenis Ciocca if (sensor->odr.odr_avl[i].hz == odr) { 5123491b51SDenis Ciocca odr_out->hz = sensor->odr.odr_avl[i].hz; 5223491b51SDenis Ciocca odr_out->value = sensor->odr.odr_avl[i].value; 5323491b51SDenis Ciocca ret = 0; 5423491b51SDenis Ciocca break; 5523491b51SDenis Ciocca } 5623491b51SDenis Ciocca } 5723491b51SDenis Ciocca 5823491b51SDenis Ciocca st_sensors_match_odr_error: 5923491b51SDenis Ciocca return ret; 6023491b51SDenis Ciocca } 6123491b51SDenis Ciocca 6223491b51SDenis Ciocca int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr) 6323491b51SDenis Ciocca { 6423491b51SDenis Ciocca int err; 65852afe99SDenis CIOCCA struct st_sensor_odr_avl odr_out = {0, 0}; 6623491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 6723491b51SDenis Ciocca 6823491b51SDenis Ciocca err = st_sensors_match_odr(sdata->sensor, odr, &odr_out); 6923491b51SDenis Ciocca if (err < 0) 7023491b51SDenis Ciocca goto st_sensors_match_odr_error; 7123491b51SDenis Ciocca 7223491b51SDenis Ciocca if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) && 7323491b51SDenis Ciocca (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) { 7423491b51SDenis Ciocca if (sdata->enabled == true) { 7523491b51SDenis Ciocca err = st_sensors_write_data_with_mask(indio_dev, 7623491b51SDenis Ciocca sdata->sensor->odr.addr, 7723491b51SDenis Ciocca sdata->sensor->odr.mask, 7823491b51SDenis Ciocca odr_out.value); 7923491b51SDenis Ciocca } else { 8023491b51SDenis Ciocca err = 0; 8123491b51SDenis Ciocca } 8223491b51SDenis Ciocca } else { 8323491b51SDenis Ciocca err = st_sensors_write_data_with_mask(indio_dev, 8423491b51SDenis Ciocca sdata->sensor->odr.addr, sdata->sensor->odr.mask, 8523491b51SDenis Ciocca odr_out.value); 8623491b51SDenis Ciocca } 8723491b51SDenis Ciocca if (err >= 0) 8823491b51SDenis Ciocca sdata->odr = odr_out.hz; 8923491b51SDenis Ciocca 9023491b51SDenis Ciocca st_sensors_match_odr_error: 9123491b51SDenis Ciocca return err; 9223491b51SDenis Ciocca } 9323491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_set_odr); 9423491b51SDenis Ciocca 9523491b51SDenis Ciocca static int st_sensors_match_fs(struct st_sensors *sensor, 9623491b51SDenis Ciocca unsigned int fs, int *index_fs_avl) 9723491b51SDenis Ciocca { 9823491b51SDenis Ciocca int i, ret = -EINVAL; 9923491b51SDenis Ciocca 10023491b51SDenis Ciocca for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) { 10123491b51SDenis Ciocca if (sensor->fs.fs_avl[i].num == 0) 10223491b51SDenis Ciocca goto st_sensors_match_odr_error; 10323491b51SDenis Ciocca 10423491b51SDenis Ciocca if (sensor->fs.fs_avl[i].num == fs) { 10523491b51SDenis Ciocca *index_fs_avl = i; 10623491b51SDenis Ciocca ret = 0; 10723491b51SDenis Ciocca break; 10823491b51SDenis Ciocca } 10923491b51SDenis Ciocca } 11023491b51SDenis Ciocca 11123491b51SDenis Ciocca st_sensors_match_odr_error: 11223491b51SDenis Ciocca return ret; 11323491b51SDenis Ciocca } 11423491b51SDenis Ciocca 11523491b51SDenis Ciocca static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs) 11623491b51SDenis Ciocca { 117852afe99SDenis CIOCCA int err, i = 0; 11823491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 11923491b51SDenis Ciocca 12023491b51SDenis Ciocca err = st_sensors_match_fs(sdata->sensor, fs, &i); 12123491b51SDenis Ciocca if (err < 0) 12223491b51SDenis Ciocca goto st_accel_set_fullscale_error; 12323491b51SDenis Ciocca 12423491b51SDenis Ciocca err = st_sensors_write_data_with_mask(indio_dev, 12523491b51SDenis Ciocca sdata->sensor->fs.addr, 12623491b51SDenis Ciocca sdata->sensor->fs.mask, 12723491b51SDenis Ciocca sdata->sensor->fs.fs_avl[i].value); 12823491b51SDenis Ciocca if (err < 0) 12923491b51SDenis Ciocca goto st_accel_set_fullscale_error; 13023491b51SDenis Ciocca 13123491b51SDenis Ciocca sdata->current_fullscale = (struct st_sensor_fullscale_avl *) 13223491b51SDenis Ciocca &sdata->sensor->fs.fs_avl[i]; 13323491b51SDenis Ciocca return err; 13423491b51SDenis Ciocca 13523491b51SDenis Ciocca st_accel_set_fullscale_error: 13623491b51SDenis Ciocca dev_err(&indio_dev->dev, "failed to set new fullscale.\n"); 13723491b51SDenis Ciocca return err; 13823491b51SDenis Ciocca } 13923491b51SDenis Ciocca 14023491b51SDenis Ciocca int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable) 14123491b51SDenis Ciocca { 14223491b51SDenis Ciocca u8 tmp_value; 14323491b51SDenis Ciocca int err = -EINVAL; 144852afe99SDenis CIOCCA bool found = false; 145852afe99SDenis CIOCCA struct st_sensor_odr_avl odr_out = {0, 0}; 14623491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 14723491b51SDenis Ciocca 14823491b51SDenis Ciocca if (enable) { 14923491b51SDenis Ciocca tmp_value = sdata->sensor->pw.value_on; 15023491b51SDenis Ciocca if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) && 15123491b51SDenis Ciocca (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) { 15223491b51SDenis Ciocca err = st_sensors_match_odr(sdata->sensor, 15323491b51SDenis Ciocca sdata->odr, &odr_out); 15423491b51SDenis Ciocca if (err < 0) 15523491b51SDenis Ciocca goto set_enable_error; 15623491b51SDenis Ciocca tmp_value = odr_out.value; 15723491b51SDenis Ciocca found = true; 15823491b51SDenis Ciocca } 15923491b51SDenis Ciocca err = st_sensors_write_data_with_mask(indio_dev, 16023491b51SDenis Ciocca sdata->sensor->pw.addr, 16123491b51SDenis Ciocca sdata->sensor->pw.mask, tmp_value); 16223491b51SDenis Ciocca if (err < 0) 16323491b51SDenis Ciocca goto set_enable_error; 16423491b51SDenis Ciocca 16523491b51SDenis Ciocca sdata->enabled = true; 16623491b51SDenis Ciocca 16723491b51SDenis Ciocca if (found) 16823491b51SDenis Ciocca sdata->odr = odr_out.hz; 16923491b51SDenis Ciocca } else { 17023491b51SDenis Ciocca err = st_sensors_write_data_with_mask(indio_dev, 17123491b51SDenis Ciocca sdata->sensor->pw.addr, 17223491b51SDenis Ciocca sdata->sensor->pw.mask, 17323491b51SDenis Ciocca sdata->sensor->pw.value_off); 17423491b51SDenis Ciocca if (err < 0) 17523491b51SDenis Ciocca goto set_enable_error; 17623491b51SDenis Ciocca 17723491b51SDenis Ciocca sdata->enabled = false; 17823491b51SDenis Ciocca } 17923491b51SDenis Ciocca 18023491b51SDenis Ciocca set_enable_error: 18123491b51SDenis Ciocca return err; 18223491b51SDenis Ciocca } 18323491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_set_enable); 18423491b51SDenis Ciocca 18523491b51SDenis Ciocca int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable) 18623491b51SDenis Ciocca { 18723491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 18823491b51SDenis Ciocca 18923491b51SDenis Ciocca return st_sensors_write_data_with_mask(indio_dev, 19023491b51SDenis Ciocca sdata->sensor->enable_axis.addr, 19123491b51SDenis Ciocca sdata->sensor->enable_axis.mask, axis_enable); 19223491b51SDenis Ciocca } 19323491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_set_axis_enable); 19423491b51SDenis Ciocca 19523491b51SDenis Ciocca int st_sensors_init_sensor(struct iio_dev *indio_dev) 19623491b51SDenis Ciocca { 19723491b51SDenis Ciocca int err; 19823491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 19923491b51SDenis Ciocca 20023491b51SDenis Ciocca mutex_init(&sdata->tb.buf_lock); 20123491b51SDenis Ciocca 20223491b51SDenis Ciocca err = st_sensors_set_enable(indio_dev, false); 20323491b51SDenis Ciocca if (err < 0) 20423491b51SDenis Ciocca goto init_error; 20523491b51SDenis Ciocca 20623491b51SDenis Ciocca err = st_sensors_set_fullscale(indio_dev, 20723491b51SDenis Ciocca sdata->current_fullscale->num); 20823491b51SDenis Ciocca if (err < 0) 20923491b51SDenis Ciocca goto init_error; 21023491b51SDenis Ciocca 21123491b51SDenis Ciocca err = st_sensors_set_odr(indio_dev, sdata->odr); 21223491b51SDenis Ciocca if (err < 0) 21323491b51SDenis Ciocca goto init_error; 21423491b51SDenis Ciocca 21523491b51SDenis Ciocca /* set BDU */ 21623491b51SDenis Ciocca err = st_sensors_write_data_with_mask(indio_dev, 21723491b51SDenis Ciocca sdata->sensor->bdu.addr, sdata->sensor->bdu.mask, true); 21823491b51SDenis Ciocca if (err < 0) 21923491b51SDenis Ciocca goto init_error; 22023491b51SDenis Ciocca 22123491b51SDenis Ciocca err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); 22223491b51SDenis Ciocca 22323491b51SDenis Ciocca init_error: 22423491b51SDenis Ciocca return err; 22523491b51SDenis Ciocca } 22623491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_init_sensor); 22723491b51SDenis Ciocca 22823491b51SDenis Ciocca int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable) 22923491b51SDenis Ciocca { 23023491b51SDenis Ciocca int err; 23123491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 23223491b51SDenis Ciocca 23323491b51SDenis Ciocca /* Enable/Disable the interrupt generator 1. */ 23423491b51SDenis Ciocca if (sdata->sensor->drdy_irq.ig1.en_addr > 0) { 23523491b51SDenis Ciocca err = st_sensors_write_data_with_mask(indio_dev, 23623491b51SDenis Ciocca sdata->sensor->drdy_irq.ig1.en_addr, 23723491b51SDenis Ciocca sdata->sensor->drdy_irq.ig1.en_mask, (int)enable); 23823491b51SDenis Ciocca if (err < 0) 23923491b51SDenis Ciocca goto st_accel_set_dataready_irq_error; 24023491b51SDenis Ciocca } 24123491b51SDenis Ciocca 24223491b51SDenis Ciocca /* Enable/Disable the interrupt generator for data ready. */ 24323491b51SDenis Ciocca err = st_sensors_write_data_with_mask(indio_dev, 24423491b51SDenis Ciocca sdata->sensor->drdy_irq.addr, 24523491b51SDenis Ciocca sdata->sensor->drdy_irq.mask, (int)enable); 24623491b51SDenis Ciocca 24723491b51SDenis Ciocca st_accel_set_dataready_irq_error: 24823491b51SDenis Ciocca return err; 24923491b51SDenis Ciocca } 25023491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_set_dataready_irq); 25123491b51SDenis Ciocca 25223491b51SDenis Ciocca int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale) 25323491b51SDenis Ciocca { 25423491b51SDenis Ciocca int err = -EINVAL, i; 25523491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 25623491b51SDenis Ciocca 25723491b51SDenis Ciocca for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) { 25823491b51SDenis Ciocca if ((sdata->sensor->fs.fs_avl[i].gain == scale) && 25923491b51SDenis Ciocca (sdata->sensor->fs.fs_avl[i].gain != 0)) { 26023491b51SDenis Ciocca err = 0; 26123491b51SDenis Ciocca break; 26223491b51SDenis Ciocca } 26323491b51SDenis Ciocca } 26423491b51SDenis Ciocca if (err < 0) 26523491b51SDenis Ciocca goto st_sensors_match_scale_error; 26623491b51SDenis Ciocca 26723491b51SDenis Ciocca err = st_sensors_set_fullscale(indio_dev, 26823491b51SDenis Ciocca sdata->sensor->fs.fs_avl[i].num); 26923491b51SDenis Ciocca 27023491b51SDenis Ciocca st_sensors_match_scale_error: 27123491b51SDenis Ciocca return err; 27223491b51SDenis Ciocca } 27323491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain); 27423491b51SDenis Ciocca 27523491b51SDenis Ciocca static int st_sensors_read_axis_data(struct iio_dev *indio_dev, 27623491b51SDenis Ciocca u8 ch_addr, int *data) 27723491b51SDenis Ciocca { 27823491b51SDenis Ciocca int err; 27923491b51SDenis Ciocca u8 outdata[ST_SENSORS_BYTE_FOR_CHANNEL]; 28023491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 28123491b51SDenis Ciocca 28223491b51SDenis Ciocca err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, 28323491b51SDenis Ciocca ch_addr, ST_SENSORS_BYTE_FOR_CHANNEL, 28423491b51SDenis Ciocca outdata, sdata->multiread_bit); 28523491b51SDenis Ciocca if (err < 0) 28623491b51SDenis Ciocca goto read_error; 28723491b51SDenis Ciocca 28823491b51SDenis Ciocca *data = (s16)get_unaligned_le16(outdata); 28923491b51SDenis Ciocca 29023491b51SDenis Ciocca read_error: 29123491b51SDenis Ciocca return err; 29223491b51SDenis Ciocca } 29323491b51SDenis Ciocca 29423491b51SDenis Ciocca int st_sensors_read_info_raw(struct iio_dev *indio_dev, 29523491b51SDenis Ciocca struct iio_chan_spec const *ch, int *val) 29623491b51SDenis Ciocca { 29723491b51SDenis Ciocca int err; 29823491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 29923491b51SDenis Ciocca 30023491b51SDenis Ciocca mutex_lock(&indio_dev->mlock); 30123491b51SDenis Ciocca if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { 30223491b51SDenis Ciocca err = -EBUSY; 30323491b51SDenis Ciocca goto read_error; 30423491b51SDenis Ciocca } else { 30523491b51SDenis Ciocca err = st_sensors_set_enable(indio_dev, true); 30623491b51SDenis Ciocca if (err < 0) 30723491b51SDenis Ciocca goto read_error; 30823491b51SDenis Ciocca 30923491b51SDenis Ciocca msleep((sdata->sensor->bootime * 1000) / sdata->odr); 31023491b51SDenis Ciocca err = st_sensors_read_axis_data(indio_dev, ch->address, val); 31123491b51SDenis Ciocca if (err < 0) 31223491b51SDenis Ciocca goto read_error; 31323491b51SDenis Ciocca 31423491b51SDenis Ciocca *val = *val >> ch->scan_type.shift; 315d61a04dcSDenis CIOCCA 316d61a04dcSDenis CIOCCA err = st_sensors_set_enable(indio_dev, false); 31723491b51SDenis Ciocca } 31823491b51SDenis Ciocca mutex_unlock(&indio_dev->mlock); 31923491b51SDenis Ciocca 32023491b51SDenis Ciocca return err; 32123491b51SDenis Ciocca 32223491b51SDenis Ciocca read_error: 32323491b51SDenis Ciocca mutex_unlock(&indio_dev->mlock); 32423491b51SDenis Ciocca return err; 32523491b51SDenis Ciocca } 32623491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_read_info_raw); 32723491b51SDenis Ciocca 32823491b51SDenis Ciocca int st_sensors_check_device_support(struct iio_dev *indio_dev, 32923491b51SDenis Ciocca int num_sensors_list, const struct st_sensors *sensors) 33023491b51SDenis Ciocca { 33123491b51SDenis Ciocca u8 wai; 33223491b51SDenis Ciocca int i, n, err; 33323491b51SDenis Ciocca struct st_sensor_data *sdata = iio_priv(indio_dev); 33423491b51SDenis Ciocca 33523491b51SDenis Ciocca err = sdata->tf->read_byte(&sdata->tb, sdata->dev, 33623491b51SDenis Ciocca ST_SENSORS_DEFAULT_WAI_ADDRESS, &wai); 33723491b51SDenis Ciocca if (err < 0) { 33823491b51SDenis Ciocca dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n"); 33923491b51SDenis Ciocca goto read_wai_error; 34023491b51SDenis Ciocca } 34123491b51SDenis Ciocca 34223491b51SDenis Ciocca for (i = 0; i < num_sensors_list; i++) { 34323491b51SDenis Ciocca if (sensors[i].wai == wai) 34423491b51SDenis Ciocca break; 34523491b51SDenis Ciocca } 34623491b51SDenis Ciocca if (i == num_sensors_list) 34723491b51SDenis Ciocca goto device_not_supported; 34823491b51SDenis Ciocca 34923491b51SDenis Ciocca for (n = 0; n < ARRAY_SIZE(sensors[i].sensors_supported); n++) { 35023491b51SDenis Ciocca if (strcmp(indio_dev->name, 35123491b51SDenis Ciocca &sensors[i].sensors_supported[n][0]) == 0) 35223491b51SDenis Ciocca break; 35323491b51SDenis Ciocca } 35423491b51SDenis Ciocca if (n == ARRAY_SIZE(sensors[i].sensors_supported)) { 35523491b51SDenis Ciocca dev_err(&indio_dev->dev, "device name and WhoAmI mismatch.\n"); 35623491b51SDenis Ciocca goto sensor_name_mismatch; 35723491b51SDenis Ciocca } 35823491b51SDenis Ciocca 35923491b51SDenis Ciocca sdata->sensor = (struct st_sensors *)&sensors[i]; 36023491b51SDenis Ciocca 36123491b51SDenis Ciocca return i; 36223491b51SDenis Ciocca 36323491b51SDenis Ciocca device_not_supported: 36423491b51SDenis Ciocca dev_err(&indio_dev->dev, "device not supported: WhoAmI (0x%x).\n", wai); 36523491b51SDenis Ciocca sensor_name_mismatch: 36623491b51SDenis Ciocca err = -ENODEV; 36723491b51SDenis Ciocca read_wai_error: 36823491b51SDenis Ciocca return err; 36923491b51SDenis Ciocca } 37023491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_check_device_support); 37123491b51SDenis Ciocca 37223491b51SDenis Ciocca ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev, 37323491b51SDenis Ciocca struct device_attribute *attr, char *buf) 37423491b51SDenis Ciocca { 37523491b51SDenis Ciocca struct st_sensor_data *adata = iio_priv(dev_get_drvdata(dev)); 37623491b51SDenis Ciocca 37723491b51SDenis Ciocca return sprintf(buf, "%d\n", adata->odr); 37823491b51SDenis Ciocca } 37923491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_sysfs_get_sampling_frequency); 38023491b51SDenis Ciocca 38123491b51SDenis Ciocca ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev, 38223491b51SDenis Ciocca struct device_attribute *attr, const char *buf, size_t size) 38323491b51SDenis Ciocca { 38423491b51SDenis Ciocca int err; 38523491b51SDenis Ciocca unsigned int odr; 38623491b51SDenis Ciocca struct iio_dev *indio_dev = dev_get_drvdata(dev); 38723491b51SDenis Ciocca 38823491b51SDenis Ciocca err = kstrtoint(buf, 10, &odr); 38923491b51SDenis Ciocca if (err < 0) 39023491b51SDenis Ciocca goto conversion_error; 39123491b51SDenis Ciocca 39223491b51SDenis Ciocca mutex_lock(&indio_dev->mlock); 39323491b51SDenis Ciocca err = st_sensors_set_odr(indio_dev, odr); 39423491b51SDenis Ciocca mutex_unlock(&indio_dev->mlock); 39523491b51SDenis Ciocca 39623491b51SDenis Ciocca conversion_error: 39723491b51SDenis Ciocca return err < 0 ? err : size; 39823491b51SDenis Ciocca } 39923491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_sysfs_set_sampling_frequency); 40023491b51SDenis Ciocca 40123491b51SDenis Ciocca ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, 40223491b51SDenis Ciocca struct device_attribute *attr, char *buf) 40323491b51SDenis Ciocca { 4044d2e4fc2SDenis CIOCCA int i, len = 0; 40523491b51SDenis Ciocca struct iio_dev *indio_dev = dev_get_drvdata(dev); 4064d2e4fc2SDenis CIOCCA struct st_sensor_data *sdata = iio_priv(indio_dev); 40723491b51SDenis Ciocca 4084d2e4fc2SDenis CIOCCA mutex_lock(&indio_dev->mlock); 4094d2e4fc2SDenis CIOCCA for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) { 4104d2e4fc2SDenis CIOCCA if (sdata->sensor->odr.odr_avl[i].hz == 0) 4114d2e4fc2SDenis CIOCCA break; 4124d2e4fc2SDenis CIOCCA 4134d2e4fc2SDenis CIOCCA len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", 4144d2e4fc2SDenis CIOCCA sdata->sensor->odr.odr_avl[i].hz); 4154d2e4fc2SDenis CIOCCA } 4164d2e4fc2SDenis CIOCCA mutex_unlock(&indio_dev->mlock); 4174d2e4fc2SDenis CIOCCA buf[len - 1] = '\n'; 4184d2e4fc2SDenis CIOCCA 4194d2e4fc2SDenis CIOCCA return len; 42023491b51SDenis Ciocca } 42123491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_sysfs_sampling_frequency_avail); 42223491b51SDenis Ciocca 42323491b51SDenis Ciocca ssize_t st_sensors_sysfs_scale_avail(struct device *dev, 42423491b51SDenis Ciocca struct device_attribute *attr, char *buf) 42523491b51SDenis Ciocca { 4264d2e4fc2SDenis CIOCCA int i, len = 0; 42723491b51SDenis Ciocca struct iio_dev *indio_dev = dev_get_drvdata(dev); 4284d2e4fc2SDenis CIOCCA struct st_sensor_data *sdata = iio_priv(indio_dev); 42923491b51SDenis Ciocca 4304d2e4fc2SDenis CIOCCA mutex_lock(&indio_dev->mlock); 4314d2e4fc2SDenis CIOCCA for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) { 4324d2e4fc2SDenis CIOCCA if (sdata->sensor->fs.fs_avl[i].num == 0) 4334d2e4fc2SDenis CIOCCA break; 4344d2e4fc2SDenis CIOCCA 4354d2e4fc2SDenis CIOCCA len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", 4364d2e4fc2SDenis CIOCCA sdata->sensor->fs.fs_avl[i].gain); 4374d2e4fc2SDenis CIOCCA } 4384d2e4fc2SDenis CIOCCA mutex_unlock(&indio_dev->mlock); 4394d2e4fc2SDenis CIOCCA buf[len - 1] = '\n'; 4404d2e4fc2SDenis CIOCCA 4414d2e4fc2SDenis CIOCCA return len; 44223491b51SDenis Ciocca } 44323491b51SDenis Ciocca EXPORT_SYMBOL(st_sensors_sysfs_scale_avail); 44423491b51SDenis Ciocca 44523491b51SDenis Ciocca MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>"); 44623491b51SDenis Ciocca MODULE_DESCRIPTION("STMicroelectronics ST-sensors core"); 44723491b51SDenis Ciocca MODULE_LICENSE("GPL v2"); 448