summaryrefslogtreecommitdiffstats
path: root/drivers/iio/imu/st_lsm9ds0
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/imu/st_lsm9ds0')
-rw-r--r--drivers/iio/imu/st_lsm9ds0/Kconfig45
-rw-r--r--drivers/iio/imu/st_lsm9ds0/Makefile5
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0.h22
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c99
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c92
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c84
6 files changed, 347 insertions, 0 deletions
diff --git a/drivers/iio/imu/st_lsm9ds0/Kconfig b/drivers/iio/imu/st_lsm9ds0/Kconfig
new file mode 100644
index 0000000000..7aef714b6e
--- /dev/null
+++ b/drivers/iio/imu/st_lsm9ds0/Kconfig
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config IIO_ST_LSM9DS0
+ tristate "STMicroelectronics LSM9DS0 IMU driver"
+ depends on (I2C || SPI_MASTER) && SYSFS
+ depends on !SENSORS_LIS3_I2C
+ depends on !SENSORS_LIS3_SPI
+ select IIO_ST_ACCEL_3AXIS
+ select IIO_ST_MAGN_3AXIS
+
+ help
+ Say yes here to build support for STMicroelectronics LSM9DS0 IMU
+ sensor. Supported devices: accelerometer/magnetometer of lsm9ds0
+ and lsm303d.
+
+ To compile this driver as a module, choose M here: the module
+ will be called st_lsm9ds0.
+
+ Also need to enable at least one of I2C and SPI interface drivers
+
+config IIO_ST_LSM9DS0_I2C
+ tristate "STMicroelectronics LSM9DS0 IMU I2C interface"
+ depends on I2C && IIO_ST_LSM9DS0
+ default I2C && IIO_ST_LSM9DS0
+ select IIO_ST_ACCEL_I2C_3AXIS
+ select IIO_ST_MAGN_I2C_3AXIS
+ select REGMAP_I2C
+ help
+ Build support for STMicroelectronics LSM9DS0 IMU I2C interface.
+
+ To compile this driver as a module, choose M here. The module
+ will be called st_lsm9ds0_i2c.
+
+config IIO_ST_LSM9DS0_SPI
+ tristate "STMicroelectronics LSM9DS0 IMU SPI interface"
+ depends on SPI_MASTER && IIO_ST_LSM9DS0
+ default SPI_MASTER && IIO_ST_LSM9DS0
+ select IIO_ST_ACCEL_SPI_3AXIS
+ select IIO_ST_MAGN_SPI_3AXIS
+ select REGMAP_SPI
+ help
+ Build support for STMicroelectronics LSM9DS0 IMU I2C interface.
+
+ To compile this driver as a module, choose M here. The module
+ will be called st_lsm9ds0_spi.
diff --git a/drivers/iio/imu/st_lsm9ds0/Makefile b/drivers/iio/imu/st_lsm9ds0/Makefile
new file mode 100644
index 0000000000..488af523f6
--- /dev/null
+++ b/drivers/iio/imu/st_lsm9ds0/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_IIO_ST_LSM9DS0) += st_lsm9ds0.o
+st_lsm9ds0-y := st_lsm9ds0_core.o
+obj-$(CONFIG_IIO_ST_LSM9DS0_I2C) += st_lsm9ds0_i2c.o
+obj-$(CONFIG_IIO_ST_LSM9DS0_SPI) += st_lsm9ds0_spi.o
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0.h b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0.h
new file mode 100644
index 0000000000..76678cdefb
--- /dev/null
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+// STMicroelectronics LSM9DS0 IMU driver
+
+#ifndef ST_LSM9DS0_H
+#define ST_LSM9DS0_H
+
+struct iio_dev;
+struct regulator;
+
+struct st_lsm9ds0 {
+ struct device *dev;
+ const char *name;
+ int irq;
+ struct iio_dev *accel;
+ struct iio_dev *magn;
+ struct regulator *vdd;
+ struct regulator *vdd_io;
+};
+
+int st_lsm9ds0_probe(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap);
+
+#endif /* ST_LSM9DS0_H */
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c
new file mode 100644
index 0000000000..e887b45cdb
--- /dev/null
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STMicroelectronics LSM9DS0 IMU driver
+ *
+ * Copyright (C) 2021, Intel Corporation
+ *
+ * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include <linux/iio/iio.h>
+
+#include "st_lsm9ds0.h"
+
+static int st_lsm9ds0_probe_accel(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap)
+{
+ const struct st_sensor_settings *settings;
+ struct device *dev = lsm9ds0->dev;
+ struct st_sensor_data *data;
+
+ settings = st_accel_get_settings(lsm9ds0->name);
+ if (!settings) {
+ dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name);
+ return -ENODEV;
+ }
+
+ lsm9ds0->accel = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!lsm9ds0->accel)
+ return -ENOMEM;
+
+ lsm9ds0->accel->name = lsm9ds0->name;
+
+ data = iio_priv(lsm9ds0->accel);
+ data->sensor_settings = (struct st_sensor_settings *)settings;
+ data->irq = lsm9ds0->irq;
+ data->regmap = regmap;
+
+ return st_accel_common_probe(lsm9ds0->accel);
+}
+
+static int st_lsm9ds0_probe_magn(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap)
+{
+ const struct st_sensor_settings *settings;
+ struct device *dev = lsm9ds0->dev;
+ struct st_sensor_data *data;
+
+ settings = st_magn_get_settings(lsm9ds0->name);
+ if (!settings) {
+ dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name);
+ return -ENODEV;
+ }
+
+ lsm9ds0->magn = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!lsm9ds0->magn)
+ return -ENOMEM;
+
+ lsm9ds0->magn->name = lsm9ds0->name;
+
+ data = iio_priv(lsm9ds0->magn);
+ data->sensor_settings = (struct st_sensor_settings *)settings;
+ data->irq = lsm9ds0->irq;
+ data->regmap = regmap;
+
+ return st_magn_common_probe(lsm9ds0->magn);
+}
+
+int st_lsm9ds0_probe(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap)
+{
+ struct device *dev = lsm9ds0->dev;
+ static const char * const regulator_names[] = { "vdd", "vddio" };
+ int ret;
+
+ /* Regulators not mandatory, but if requested we should enable them. */
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),
+ regulator_names);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "unable to enable Vdd supply\n");
+
+ /* Setup accelerometer device */
+ ret = st_lsm9ds0_probe_accel(lsm9ds0, regmap);
+ if (ret)
+ return ret;
+
+ /* Setup magnetometer device */
+ return st_lsm9ds0_probe_magn(lsm9ds0, regmap);
+}
+EXPORT_SYMBOL_NS_GPL(st_lsm9ds0_probe, IIO_ST_SENSORS);
+
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
+MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU core driver");
+MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(IIO_ST_SENSORS);
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
new file mode 100644
index 0000000000..61d855083a
--- /dev/null
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STMicroelectronics LSM9DS0 IMU driver
+ *
+ * Copyright (C) 2021, Intel Corporation
+ *
+ * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+
+#include <linux/iio/common/st_sensors_i2c.h>
+
+#include "st_lsm9ds0.h"
+
+static const struct of_device_id st_lsm9ds0_of_match[] = {
+ {
+ .compatible = "st,lsm303d-imu",
+ .data = LSM303D_IMU_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm9ds0-imu",
+ .data = LSM9DS0_IMU_DEV_NAME,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match);
+
+static const struct i2c_device_id st_lsm9ds0_id_table[] = {
+ { LSM303D_IMU_DEV_NAME },
+ { LSM9DS0_IMU_DEV_NAME },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table);
+
+static const struct acpi_device_id st_lsm9ds0_acpi_match[] = {
+ {"ACCL0001", (kernel_ulong_t)LSM303D_IMU_DEV_NAME},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, st_lsm9ds0_acpi_match);
+
+static const struct regmap_config st_lsm9ds0_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .read_flag_mask = 0x80,
+};
+
+static int st_lsm9ds0_i2c_probe(struct i2c_client *client)
+{
+ const struct regmap_config *config = &st_lsm9ds0_regmap_config;
+ struct device *dev = &client->dev;
+ struct st_lsm9ds0 *lsm9ds0;
+ struct regmap *regmap;
+
+ st_sensors_dev_name_probe(dev, client->name, sizeof(client->name));
+
+ lsm9ds0 = devm_kzalloc(dev, sizeof(*lsm9ds0), GFP_KERNEL);
+ if (!lsm9ds0)
+ return -ENOMEM;
+
+ lsm9ds0->dev = dev;
+ lsm9ds0->name = client->name;
+ lsm9ds0->irq = client->irq;
+
+ regmap = devm_regmap_init_i2c(client, config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ i2c_set_clientdata(client, lsm9ds0);
+
+ return st_lsm9ds0_probe(lsm9ds0, regmap);
+}
+
+static struct i2c_driver st_lsm9ds0_driver = {
+ .driver = {
+ .name = "st-lsm9ds0-i2c",
+ .of_match_table = st_lsm9ds0_of_match,
+ .acpi_match_table = st_lsm9ds0_acpi_match,
+ },
+ .probe = st_lsm9ds0_i2c_probe,
+ .id_table = st_lsm9ds0_id_table,
+};
+module_i2c_driver(st_lsm9ds0_driver);
+
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
+MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU I2C driver");
+MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(IIO_ST_SENSORS);
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
new file mode 100644
index 0000000000..8cc041d56c
--- /dev/null
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STMicroelectronics LSM9DS0 IMU driver
+ *
+ * Copyright (C) 2021, Intel Corporation
+ *
+ * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include <linux/iio/common/st_sensors_spi.h>
+
+#include "st_lsm9ds0.h"
+
+static const struct of_device_id st_lsm9ds0_of_match[] = {
+ {
+ .compatible = "st,lsm303d-imu",
+ .data = LSM303D_IMU_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm9ds0-imu",
+ .data = LSM9DS0_IMU_DEV_NAME,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match);
+
+static const struct spi_device_id st_lsm9ds0_id_table[] = {
+ { LSM303D_IMU_DEV_NAME },
+ { LSM9DS0_IMU_DEV_NAME },
+ {}
+};
+MODULE_DEVICE_TABLE(spi, st_lsm9ds0_id_table);
+
+static const struct regmap_config st_lsm9ds0_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .read_flag_mask = 0xc0,
+};
+
+static int st_lsm9ds0_spi_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct st_lsm9ds0 *lsm9ds0;
+ struct regmap *regmap;
+
+ st_sensors_dev_name_probe(dev, spi->modalias, sizeof(spi->modalias));
+
+ lsm9ds0 = devm_kzalloc(dev, sizeof(*lsm9ds0), GFP_KERNEL);
+ if (!lsm9ds0)
+ return -ENOMEM;
+
+ lsm9ds0->dev = dev;
+ lsm9ds0->name = spi->modalias;
+ lsm9ds0->irq = spi->irq;
+
+ regmap = devm_regmap_init_spi(spi, &st_lsm9ds0_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ spi_set_drvdata(spi, lsm9ds0);
+
+ return st_lsm9ds0_probe(lsm9ds0, regmap);
+}
+
+static struct spi_driver st_lsm9ds0_driver = {
+ .driver = {
+ .name = "st-lsm9ds0-spi",
+ .of_match_table = st_lsm9ds0_of_match,
+ },
+ .probe = st_lsm9ds0_spi_probe,
+ .id_table = st_lsm9ds0_id_table,
+};
+module_spi_driver(st_lsm9ds0_driver);
+
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
+MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU SPI driver");
+MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(IIO_ST_SENSORS);