summaryrefslogtreecommitdiffstats
path: root/drivers/iio/imu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/imu')
-rw-r--r--drivers/iio/imu/adis16480.c28
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c3
-rw-r--r--drivers/iio/imu/st_lsm6dsx/Kconfig2
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h39
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c107
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c115
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c55
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c70
8 files changed, 180 insertions, 239 deletions
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index 7a33d6bd60e0..a27fe208f3ae 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -194,7 +194,7 @@ static int adis16480_show_serial_number(void *arg, u64 *val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(adis16480_serial_number_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16480_serial_number_fops,
adis16480_show_serial_number, NULL, "0x%.4llx\n");
static int adis16480_show_product_id(void *arg, u64 *val)
@@ -212,7 +212,7 @@ static int adis16480_show_product_id(void *arg, u64 *val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(adis16480_product_id_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16480_product_id_fops,
adis16480_show_product_id, NULL, "%llu\n");
static int adis16480_show_flash_count(void *arg, u64 *val)
@@ -230,24 +230,28 @@ static int adis16480_show_flash_count(void *arg, u64 *val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(adis16480_flash_count_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16480_flash_count_fops,
adis16480_show_flash_count, NULL, "%lld\n");
static int adis16480_debugfs_init(struct iio_dev *indio_dev)
{
struct adis16480 *adis16480 = iio_priv(indio_dev);
- debugfs_create_file("firmware_revision", 0400,
+ debugfs_create_file_unsafe("firmware_revision", 0400,
indio_dev->debugfs_dentry, adis16480,
&adis16480_firmware_revision_fops);
- debugfs_create_file("firmware_date", 0400, indio_dev->debugfs_dentry,
- adis16480, &adis16480_firmware_date_fops);
- debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
- adis16480, &adis16480_serial_number_fops);
- debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
- adis16480, &adis16480_product_id_fops);
- debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
- adis16480, &adis16480_flash_count_fops);
+ debugfs_create_file_unsafe("firmware_date", 0400,
+ indio_dev->debugfs_dentry, adis16480,
+ &adis16480_firmware_date_fops);
+ debugfs_create_file_unsafe("serial_number", 0400,
+ indio_dev->debugfs_dentry, adis16480,
+ &adis16480_serial_number_fops);
+ debugfs_create_file_unsafe("product_id", 0400,
+ indio_dev->debugfs_dentry, adis16480,
+ &adis16480_product_id_fops);
+ debugfs_create_file_unsafe("flash_count", 0400,
+ indio_dev->debugfs_dentry, adis16480,
+ &adis16480_flash_count_fops);
return 0;
}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
index dd6fc6d21f9d..d78a10403bac 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
@@ -196,8 +196,7 @@ void inv_mpu_acpi_delete_mux_client(struct i2c_client *client)
{
struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(&client->dev));
- if (st->mux_client)
- i2c_unregister_device(st->mux_client);
+ i2c_unregister_device(st->mux_client);
}
#else
diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig
index e57337159b57..14f2eb6e9fb7 100644
--- a/drivers/iio/imu/st_lsm6dsx/Kconfig
+++ b/drivers/iio/imu/st_lsm6dsx/Kconfig
@@ -16,7 +16,9 @@ config IIO_ST_LSM6DSX
config IIO_ST_LSM6DSX_I2C
tristate
depends on IIO_ST_LSM6DSX
+ select REGMAP_I2C
config IIO_ST_LSM6DSX_SPI
tristate
depends on IIO_ST_LSM6DSX
+ select REGMAP_SPI
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index 4fdb7fcc3ea8..8fdd723afa05 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -27,23 +27,12 @@ enum st_lsm6dsx_hw_id {
ST_LSM6DSX_MAX_ID,
};
+#define ST_LSM6DSX_BUFF_SIZE 256
#define ST_LSM6DSX_CHAN_SIZE 2
#define ST_LSM6DSX_SAMPLE_SIZE 6
-
-#if defined(CONFIG_SPI_MASTER)
-#define ST_LSM6DSX_RX_MAX_LENGTH 256
-#define ST_LSM6DSX_TX_MAX_LENGTH 8
-
-struct st_lsm6dsx_transfer_buffer {
- u8 rx_buf[ST_LSM6DSX_RX_MAX_LENGTH];
- u8 tx_buf[ST_LSM6DSX_TX_MAX_LENGTH] ____cacheline_aligned;
-};
-#endif /* CONFIG_SPI_MASTER */
-
-struct st_lsm6dsx_transfer_function {
- int (*read)(struct device *dev, u8 addr, int len, u8 *data);
- int (*write)(struct device *dev, u8 addr, int len, u8 *data);
-};
+#define ST_LSM6DSX_MAX_WORD_LEN ((32 / ST_LSM6DSX_SAMPLE_SIZE) * \
+ ST_LSM6DSX_SAMPLE_SIZE)
+#define ST_LSM6DSX_SHIFT_VAL(val, mask) (((val) << __ffs(mask)) & (mask))
struct st_lsm6dsx_reg {
u8 addr;
@@ -127,47 +116,43 @@ struct st_lsm6dsx_sensor {
/**
* struct st_lsm6dsx_hw - ST IMU MEMS hw instance
* @dev: Pointer to instance of struct device (I2C or SPI).
+ * @regmap: Register map of the device.
* @irq: Device interrupt line (I2C or SPI).
- * @lock: Mutex to protect read and write operations.
* @fifo_lock: Mutex to prevent concurrent access to the hw FIFO.
+ * @conf_lock: Mutex to prevent concurrent FIFO configuration update.
* @fifo_mode: FIFO operating mode supported by the device.
* @enable_mask: Enabled sensor bitmask.
* @sip: Total number of samples (acc/gyro) in a given pattern.
+ * @buff: Device read buffer.
* @iio_devs: Pointers to acc/gyro iio_dev instances.
* @settings: Pointer to the specific sensor settings in use.
- * @tf: Transfer function structure used by I/O operations.
- * @tb: Transfer buffers used by SPI I/O operations.
*/
struct st_lsm6dsx_hw {
struct device *dev;
+ struct regmap *regmap;
int irq;
- struct mutex lock;
struct mutex fifo_lock;
+ struct mutex conf_lock;
enum st_lsm6dsx_fifo_mode fifo_mode;
u8 enable_mask;
u8 sip;
+ u8 *buff;
+
struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX];
const struct st_lsm6dsx_settings *settings;
-
- const struct st_lsm6dsx_transfer_function *tf;
-#if defined(CONFIG_SPI_MASTER)
- struct st_lsm6dsx_transfer_buffer tb;
-#endif /* CONFIG_SPI_MASTER */
};
extern const struct dev_pm_ops st_lsm6dsx_pm_ops;
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
- const struct st_lsm6dsx_transfer_function *tf_ops);
+ struct regmap *regmap);
int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor);
int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor);
int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw);
-int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
- u8 val);
int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor,
u16 watermark);
int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw);
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index 755c472e8a05..1d6aa9b1a4cf 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;
}
/**
@@ -223,11 +247,11 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor;
s64 acc_ts, acc_delta_ts, gyro_ts, gyro_delta_ts;
u8 iio_buff[ALIGN(ST_LSM6DSX_SAMPLE_SIZE, sizeof(s64)) + sizeof(s64)];
- 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 +279,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, hw->buff, pattern_len);
if (err < 0)
return err;
@@ -281,7 +304,7 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
while (acc_sip > 0 || gyro_sip > 0) {
if (gyro_sip-- > 0) {
- memcpy(iio_buff, &buff[offset],
+ memcpy(iio_buff, &hw->buff[offset],
ST_LSM6DSX_SAMPLE_SIZE);
iio_push_to_buffers_with_timestamp(
hw->iio_devs[ST_LSM6DSX_ID_GYRO],
@@ -291,7 +314,7 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
}
if (acc_sip-- > 0) {
- memcpy(iio_buff, &buff[offset],
+ memcpy(iio_buff, &hw->buff[offset],
ST_LSM6DSX_SAMPLE_SIZE);
iio_push_to_buffers_with_timestamp(
hw->iio_devs[ST_LSM6DSX_ID_ACC],
@@ -325,38 +348,40 @@ static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
struct st_lsm6dsx_hw *hw = sensor->hw;
int err;
+ mutex_lock(&hw->conf_lock);
+
if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) {
err = st_lsm6dsx_flush_fifo(hw);
if (err < 0)
- return err;
+ goto out;
}
if (enable) {
err = st_lsm6dsx_sensor_enable(sensor);
if (err < 0)
- return err;
+ goto out;
} else {
err = st_lsm6dsx_sensor_disable(sensor);
if (err < 0)
- return err;
+ goto out;
}
err = st_lsm6dsx_set_fifo_odr(sensor, enable);
if (err < 0)
- return err;
+ goto out;
err = st_lsm6dsx_update_decimators(hw);
if (err < 0)
- return err;
+ goto out;
err = st_lsm6dsx_update_watermark(sensor, sensor->watermark);
if (err < 0)
- return err;
+ goto out;
if (hw->enable_mask) {
err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
if (err < 0)
- return err;
+ goto out;
/*
* store enable buffer timestamp as reference to compute
@@ -365,7 +390,10 @@ static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
sensor->ts = iio_get_time_ns(iio_dev);
}
- return 0;
+out:
+ mutex_unlock(&hw->conf_lock);
+
+ return err;
}
static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private)
@@ -444,17 +472,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;
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index 239c735242be..c2fa3239b9c6 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -37,6 +37,8 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/bitfield.h>
#include <linux/platform_data/st_sensors_pdata.h>
@@ -277,36 +279,9 @@ static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(3),
};
-int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
- u8 val)
-{
- u8 data;
- int err;
-
- mutex_lock(&hw->lock);
-
- err = hw->tf->read(hw->dev, addr, sizeof(data), &data);
- if (err < 0) {
- dev_err(hw->dev, "failed to read %02x register\n", addr);
- goto out;
- }
-
- data = (data & ~mask) | ((val << __ffs(mask)) & mask);
-
- err = hw->tf->write(hw->dev, addr, sizeof(data), &data);
- if (err < 0)
- dev_err(hw->dev, "failed to write %02x register\n", addr);
-
-out:
- mutex_unlock(&hw->lock);
-
- return err;
-}
-
static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id)
{
- int err, i, j;
- u8 data;
+ int err, i, j, data;
for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) {
@@ -322,8 +297,7 @@ static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id)
return -ENODEV;
}
- err = hw->tf->read(hw->dev, ST_LSM6DSX_REG_WHOAMI_ADDR, sizeof(data),
- &data);
+ err = regmap_read(hw->regmap, ST_LSM6DSX_REG_WHOAMI_ADDR, &data);
if (err < 0) {
dev_err(hw->dev, "failed to read whoami register\n");
return err;
@@ -342,22 +316,22 @@ static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id)
static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor,
u32 gain)
{
- enum st_lsm6dsx_sensor_id id = sensor->id;
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ const struct st_lsm6dsx_reg *reg;
int i, err;
u8 val;
for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++)
- if (st_lsm6dsx_fs_table[id].fs_avl[i].gain == gain)
+ if (st_lsm6dsx_fs_table[sensor->id].fs_avl[i].gain == gain)
break;
if (i == ST_LSM6DSX_FS_LIST_SIZE)
return -EINVAL;
- val = st_lsm6dsx_fs_table[id].fs_avl[i].val;
- err = st_lsm6dsx_write_with_mask(sensor->hw,
- st_lsm6dsx_fs_table[id].reg.addr,
- st_lsm6dsx_fs_table[id].reg.mask,
- val);
+ val = st_lsm6dsx_fs_table[sensor->id].fs_avl[i].val;
+ reg = &st_lsm6dsx_fs_table[sensor->id].reg;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(val, reg->mask));
if (err < 0)
return err;
@@ -385,7 +359,8 @@ static int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr,
static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
{
- enum st_lsm6dsx_sensor_id id = sensor->id;
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ const struct st_lsm6dsx_reg *reg;
int err;
u8 val;
@@ -393,10 +368,9 @@ static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
if (err < 0)
return err;
- return st_lsm6dsx_write_with_mask(sensor->hw,
- st_lsm6dsx_odr_table[id].reg.addr,
- st_lsm6dsx_odr_table[id].reg.mask,
- val);
+ reg = &st_lsm6dsx_odr_table[sensor->id].reg;
+ return regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(val, reg->mask));
}
int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor)
@@ -414,16 +388,17 @@ int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor)
int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor)
{
- enum st_lsm6dsx_sensor_id id = sensor->id;
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ const struct st_lsm6dsx_reg *reg;
int err;
- err = st_lsm6dsx_write_with_mask(sensor->hw,
- st_lsm6dsx_odr_table[id].reg.addr,
- st_lsm6dsx_odr_table[id].reg.mask, 0);
+ reg = &st_lsm6dsx_odr_table[sensor->id].reg;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(0, reg->mask));
if (err < 0)
return err;
- sensor->hw->enable_mask &= ~BIT(id);
+ sensor->hw->enable_mask &= ~BIT(sensor->id);
return 0;
}
@@ -431,6 +406,7 @@ int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor)
static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
u8 addr, int *val)
{
+ struct st_lsm6dsx_hw *hw = sensor->hw;
int err, delay;
__le16 data;
@@ -441,14 +417,13 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
delay = 1000000 / sensor->odr;
usleep_range(delay, 2 * delay);
- err = sensor->hw->tf->read(sensor->hw->dev, addr, sizeof(data),
- (u8 *)&data);
+ err = regmap_bulk_read(hw->regmap, addr, &data, sizeof(data));
if (err < 0)
return err;
st_lsm6dsx_sensor_disable(sensor);
- *val = (s16)data;
+ *val = (s16)le16_to_cpu(data);
return IIO_VAL_INT;
}
@@ -528,7 +503,12 @@ static int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val)
if (val < 1 || val > hw->settings->max_fifo_size)
return -EINVAL;
+ mutex_lock(&hw->conf_lock);
+
err = st_lsm6dsx_update_watermark(sensor, val);
+
+ mutex_unlock(&hw->conf_lock);
+
if (err < 0)
return err;
@@ -652,20 +632,20 @@ static int st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, u8 *drdy_reg)
static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
{
- u8 data, drdy_int_reg;
+ u8 drdy_int_reg;
int err;
- data = ST_LSM6DSX_REG_RESET_MASK;
- err = hw->tf->write(hw->dev, ST_LSM6DSX_REG_RESET_ADDR, sizeof(data),
- &data);
+ err = regmap_write(hw->regmap, ST_LSM6DSX_REG_RESET_ADDR,
+ ST_LSM6DSX_REG_RESET_MASK);
if (err < 0)
return err;
msleep(200);
/* enable Block Data Update */
- err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_BDU_ADDR,
- ST_LSM6DSX_REG_BDU_MASK, 1);
+ err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_BDU_ADDR,
+ ST_LSM6DSX_REG_BDU_MASK,
+ FIELD_PREP(ST_LSM6DSX_REG_BDU_MASK, 1));
if (err < 0)
return err;
@@ -674,8 +654,10 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
if (err < 0)
return err;
- return st_lsm6dsx_write_with_mask(hw, drdy_int_reg,
- ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK, 1);
+ return regmap_update_bits(hw->regmap, drdy_int_reg,
+ ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK,
+ FIELD_PREP(ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK,
+ 1));
}
static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
@@ -726,7 +708,7 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
}
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
- const struct st_lsm6dsx_transfer_function *tf_ops)
+ struct regmap *regmap)
{
struct st_lsm6dsx_hw *hw;
int i, err;
@@ -737,12 +719,16 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
dev_set_drvdata(dev, (void *)hw);
- mutex_init(&hw->lock);
mutex_init(&hw->fifo_lock);
+ mutex_init(&hw->conf_lock);
+
+ hw->buff = devm_kzalloc(dev, ST_LSM6DSX_BUFF_SIZE, GFP_KERNEL);
+ if (!hw->buff)
+ return -ENOMEM;
hw->dev = dev;
hw->irq = irq;
- hw->tf = tf_ops;
+ hw->regmap = regmap;
err = st_lsm6dsx_check_whoami(hw, hw_id);
if (err < 0)
@@ -778,6 +764,7 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
{
struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
struct st_lsm6dsx_sensor *sensor;
+ const struct st_lsm6dsx_reg *reg;
int i, err = 0;
for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
@@ -785,9 +772,9 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
if (!(hw->enable_mask & BIT(sensor->id)))
continue;
- err = st_lsm6dsx_write_with_mask(hw,
- st_lsm6dsx_odr_table[sensor->id].reg.addr,
- st_lsm6dsx_odr_table[sensor->id].reg.mask, 0);
+ reg = &st_lsm6dsx_odr_table[sensor->id].reg;
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ ST_LSM6DSX_SHIFT_VAL(0, reg->mask));
if (err < 0)
return err;
}
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
index 305fec712ab0..41525dd2aab7 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
@@ -14,55 +14,30 @@
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/regmap.h>
#include "st_lsm6dsx.h"
-static int st_lsm6dsx_i2c_read(struct device *dev, u8 addr, int len, u8 *data)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct i2c_msg msg[2];
-
- msg[0].addr = client->addr;
- msg[0].flags = client->flags;
- msg[0].len = 1;
- msg[0].buf = &addr;
-
- msg[1].addr = client->addr;
- msg[1].flags = client->flags | I2C_M_RD;
- msg[1].len = len;
- msg[1].buf = data;
-
- return i2c_transfer(client->adapter, msg, 2);
-}
-
-static int st_lsm6dsx_i2c_write(struct device *dev, u8 addr, int len, u8 *data)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct i2c_msg msg;
- u8 send[len + 1];
-
- send[0] = addr;
- memcpy(&send[1], data, len * sizeof(u8));
-
- msg.addr = client->addr;
- msg.flags = client->flags;
- msg.len = len + 1;
- msg.buf = send;
-
- return i2c_transfer(client->adapter, &msg, 1);
-}
-
-static const struct st_lsm6dsx_transfer_function st_lsm6dsx_transfer_fn = {
- .read = st_lsm6dsx_i2c_read,
- .write = st_lsm6dsx_i2c_write,
+static const struct regmap_config st_lsm6dsx_i2c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
};
static int st_lsm6dsx_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ int hw_id = id->driver_data;
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_i2c(client, &st_lsm6dsx_i2c_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "Failed to register i2c regmap %d\n",
+ (int)PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
return st_lsm6dsx_probe(&client->dev, client->irq,
- (int)id->driver_data, id->name,
- &st_lsm6dsx_transfer_fn);
+ hw_id, id->name, regmap);
}
static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
index 95472f153ad2..2c8135834479 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
@@ -14,72 +14,30 @@
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/regmap.h>
#include "st_lsm6dsx.h"
-#define SENSORS_SPI_READ BIT(7)
-
-static int st_lsm6dsx_spi_read(struct device *dev, u8 addr, int len,
- u8 *data)
-{
- struct spi_device *spi = to_spi_device(dev);
- struct st_lsm6dsx_hw *hw = spi_get_drvdata(spi);
- int err;
-
- struct spi_transfer xfers[] = {
- {
- .tx_buf = hw->tb.tx_buf,
- .bits_per_word = 8,
- .len = 1,
- },
- {
- .rx_buf = hw->tb.rx_buf,
- .bits_per_word = 8,
- .len = len,
- }
- };
-
- hw->tb.tx_buf[0] = addr | SENSORS_SPI_READ;
-
- err = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));
- if (err < 0)
- return err;
-
- memcpy(data, hw->tb.rx_buf, len * sizeof(u8));
-
- return len;
-}
-
-static int st_lsm6dsx_spi_write(struct device *dev, u8 addr, int len,
- u8 *data)
-{
- struct st_lsm6dsx_hw *hw;
- struct spi_device *spi;
-
- if (len >= ST_LSM6DSX_TX_MAX_LENGTH)
- return -ENOMEM;
-
- spi = to_spi_device(dev);
- hw = spi_get_drvdata(spi);
-
- hw->tb.tx_buf[0] = addr;
- memcpy(&hw->tb.tx_buf[1], data, len);
-
- return spi_write(spi, hw->tb.tx_buf, len + 1);
-}
-
-static const struct st_lsm6dsx_transfer_function st_lsm6dsx_transfer_fn = {
- .read = st_lsm6dsx_spi_read,
- .write = st_lsm6dsx_spi_write,
+static const struct regmap_config st_lsm6dsx_spi_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
};
static int st_lsm6dsx_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
+ int hw_id = id->driver_data;
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_spi(spi, &st_lsm6dsx_spi_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&spi->dev, "Failed to register spi regmap %d\n",
+ (int)PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
return st_lsm6dsx_probe(&spi->dev, spi->irq,
- (int)id->driver_data, id->name,
- &st_lsm6dsx_transfer_fn);
+ hw_id, id->name, regmap);
}
static const struct of_device_id st_lsm6dsx_spi_of_match[] = {