diff options
author | Lorenzo Bianconi <lorenzo.bianconi@redhat.com> | 2018-01-01 19:54:44 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-01-08 16:03:43 +0100 |
commit | 51a8b707627b437f17a153812f049daf3da6729d (patch) | |
tree | 937647f5a989dceb5e1493e656e8a2cf23928b16 /drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | |
parent | iio: imu: st_lsm6dsx: introduce conf_lock mutex (diff) | |
download | linux-dev-51a8b707627b437f17a153812f049daf3da6729d.tar.xz linux-dev-51a8b707627b437f17a153812f049daf3da6729d.zip |
iio: imu: st_lsm6dsx: add regmap API support
Introduce regmap API support to access to i2c/spi bus instead of
using a custom support. Set max bulk read to
(32 / SAMPLE_SIZE) * SAMPLE_SIZE since spi_write_then_read() used in
regmap_spi indicates that is the max buffer length to use in order to
avoid a kmalloc for each bus access.
Remove lock mutex since concurrency is already managed by regmap API
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c')
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 81 |
1 files changed, 54 insertions, 27 deletions
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index c899d658f6be..093f9750974a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -30,6 +30,8 @@ #include <linux/iio/kfifo_buf.h> #include <linux/iio/iio.h> #include <linux/iio/buffer.h> +#include <linux/regmap.h> +#include <linux/bitfield.h> #include <linux/platform_data/st_sensors_pdata.h> @@ -120,8 +122,10 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw) dec_reg = &hw->settings->decimator[sensor->id]; if (dec_reg->addr) { - err = st_lsm6dsx_write_with_mask(hw, dec_reg->addr, - dec_reg->mask, data); + int val = ST_LSM6DSX_SHIFT_VAL(data, dec_reg->mask); + + err = regmap_update_bits(hw->regmap, dec_reg->addr, + dec_reg->mask, val); if (err < 0) return err; } @@ -137,8 +141,10 @@ int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, { int err; - err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_FIFO_MODE_ADDR, - ST_LSM6DSX_FIFO_MODE_MASK, fifo_mode); + err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_FIFO_MODE_ADDR, + ST_LSM6DSX_FIFO_MODE_MASK, + FIELD_PREP(ST_LSM6DSX_FIFO_MODE_MASK, + fifo_mode)); if (err < 0) return err; @@ -154,8 +160,9 @@ static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_sensor *sensor, u8 data; data = hw->enable_mask ? ST_LSM6DSX_MAX_FIFO_ODR_VAL : 0; - return st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_FIFO_MODE_ADDR, - ST_LSM6DSX_FIFO_ODR_MASK, data); + return regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_FIFO_MODE_ADDR, + ST_LSM6DSX_FIFO_ODR_MASK, + FIELD_PREP(ST_LSM6DSX_FIFO_ODR_MASK, data)); } int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark) @@ -163,9 +170,8 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark) u16 fifo_watermark = ~0, cur_watermark, sip = 0, fifo_th_mask; struct st_lsm6dsx_hw *hw = sensor->hw; struct st_lsm6dsx_sensor *cur_sensor; + int i, err, data; __le16 wdata; - int i, err; - u8 data; for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { cur_sensor = iio_priv(hw->iio_devs[i]); @@ -187,24 +193,42 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark) fifo_watermark = (fifo_watermark / sip) * sip; fifo_watermark = fifo_watermark * hw->settings->fifo_ops.th_wl; - mutex_lock(&hw->lock); - - err = hw->tf->read(hw->dev, hw->settings->fifo_ops.fifo_th.addr + 1, - sizeof(data), &data); + err = regmap_read(hw->regmap, hw->settings->fifo_ops.fifo_th.addr + 1, + &data); if (err < 0) - goto out; + return err; fifo_th_mask = hw->settings->fifo_ops.fifo_th.mask; fifo_watermark = ((data << 8) & ~fifo_th_mask) | (fifo_watermark & fifo_th_mask); wdata = cpu_to_le16(fifo_watermark); - err = hw->tf->write(hw->dev, hw->settings->fifo_ops.fifo_th.addr, - sizeof(wdata), (u8 *)&wdata); -out: - mutex_unlock(&hw->lock); + return regmap_bulk_write(hw->regmap, + hw->settings->fifo_ops.fifo_th.addr, + &wdata, sizeof(wdata)); +} - return err < 0 ? err : 0; +/* + * Set max bulk read to ST_LSM6DSX_MAX_WORD_LEN in order to avoid + * a kmalloc for each bus access + */ +static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 *data, + unsigned int data_len) +{ + unsigned int word_len, read_len = 0; + int err; + + while (read_len < data_len) { + word_len = min_t(unsigned int, data_len - read_len, + ST_LSM6DSX_MAX_WORD_LEN); + err = regmap_bulk_read(hw->regmap, + ST_LSM6DSX_REG_FIFO_OUTL_ADDR, + data + read_len, word_len); + if (err < 0) + return err; + read_len += word_len; + } + return 0; } /** @@ -226,8 +250,9 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) u8 buff[pattern_len]; __le16 fifo_status; - err = hw->tf->read(hw->dev, hw->settings->fifo_ops.fifo_diff.addr, - sizeof(fifo_status), (u8 *)&fifo_status); + err = regmap_bulk_read(hw->regmap, + hw->settings->fifo_ops.fifo_diff.addr, + &fifo_status, sizeof(fifo_status)); if (err < 0) return err; @@ -255,8 +280,7 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) samples); for (read_len = 0; read_len < fifo_len; read_len += pattern_len) { - err = hw->tf->read(hw->dev, ST_LSM6DSX_REG_FIFO_OUTL_ADDR, - sizeof(buff), buff); + err = st_lsm6dsx_read_block(hw, buff, sizeof(buff)); if (err < 0) return err; @@ -449,17 +473,20 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) return -EINVAL; } - err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_HLACTIVE_ADDR, - ST_LSM6DSX_REG_HLACTIVE_MASK, - irq_active_low); + err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_HLACTIVE_ADDR, + ST_LSM6DSX_REG_HLACTIVE_MASK, + FIELD_PREP(ST_LSM6DSX_REG_HLACTIVE_MASK, + irq_active_low)); if (err < 0) return err; pdata = (struct st_sensors_platform_data *)hw->dev->platform_data; if ((np && of_property_read_bool(np, "drive-open-drain")) || (pdata && pdata->open_drain)) { - err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_PP_OD_ADDR, - ST_LSM6DSX_REG_PP_OD_MASK, 1); + err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_PP_OD_ADDR, + ST_LSM6DSX_REG_PP_OD_MASK, + FIELD_PREP(ST_LSM6DSX_REG_PP_OD_MASK, + 1)); if (err < 0) return err; |