diff options
Diffstat (limited to 'drivers/iio/accel/st_accel_core.c')
| -rw-r--r-- | drivers/iio/accel/st_accel_core.c | 243 |
1 files changed, 188 insertions, 55 deletions
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 28fceac9f2f6..a7961c610ed2 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -9,17 +9,13 @@ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mutex.h> +#include <linux/sysfs.h> #include <linux/slab.h> #include <linux/acpi.h> -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/i2c.h> -#include <linux/irq.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/trigger.h> -#include <linux/iio/buffer.h> #include <linux/iio/common/st_sensors.h> #include "st_accel.h" @@ -448,6 +444,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { [0] = LIS331DL_ACCEL_DEV_NAME, + [1] = LIS302DL_ACCEL_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_accel_8bit_channels, .odr = { @@ -520,6 +517,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { [0] = H3LIS331DL_ACCEL_DEV_NAME, + [1] = IIS328DQ_ACCEL_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_accel_12bit_channels, .odr = { @@ -928,10 +926,92 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .bootime = 2, }, { + .wai = 0x43, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LIS2DS12_ACCEL_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_accel_16bit_channels, + .odr = { + .addr = 0x20, + .mask = 0xf0, + .odr_avl = { + { .hz = 10, .value = 0x01, }, + { .hz = 50, .value = 0x02, }, + { .hz = 100, .value = 0x03, }, + { .hz = 200, .value = 0x04, }, + { .hz = 400, .value = 0x05, }, + { .hz = 800, .value = 0x06, }, + }, + }, + .pw = { + .addr = 0x20, + .mask = 0xf0, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .enable_axis = { + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, + }, + .fs = { + .addr = 0x20, + .mask = 0x0c, + .fs_avl = { + [0] = { + .num = ST_ACCEL_FS_AVL_2G, + .value = 0x00, + .gain = IIO_G_TO_M_S_2(61), + }, + [1] = { + .num = ST_ACCEL_FS_AVL_4G, + .value = 0x02, + .gain = IIO_G_TO_M_S_2(122), + }, + [2] = { + .num = ST_ACCEL_FS_AVL_8G, + .value = 0x03, + .gain = IIO_G_TO_M_S_2(244), + }, + [3] = { + .num = ST_ACCEL_FS_AVL_16G, + .value = 0x01, + .gain = IIO_G_TO_M_S_2(488), + }, + }, + }, + .bdu = { + .addr = 0x20, + .mask = 0x01, + }, + .drdy_irq = { + .int1 = { + .addr = 0x23, + .mask = 0x01, + }, + .int2 = { + .addr = 0x24, + .mask = 0x01, + }, + .addr_ihl = 0x22, + .mask_ihl = 0x02, + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = 0x01, + }, + }, + .sim = { + .addr = 0x21, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, + { .wai = 0x41, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { [0] = LIS2HH12_ACCEL_DEV_NAME, + [1] = LSM303C_ACCEL_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_accel_16bit_channels, .odr = { @@ -1008,6 +1088,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { [0] = LSM9DS0_IMU_DEV_NAME, + [1] = LSM303D_IMU_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_accel_16bit_channels, .odr = { @@ -1091,6 +1172,89 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .multi_read_bit = true, .bootime = 2, }, + { + /* + * Not an ST part. Register-compatible with the LIS2DH, even + * though the WAI value is different. + */ + .wai = 0x11, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = SC7A20_ACCEL_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_accel_12bit_channels, + .odr = { + .addr = 0x20, + .mask = 0xf0, + .odr_avl = { + { .hz = 1, .value = 0x01, }, + { .hz = 10, .value = 0x02, }, + { .hz = 25, .value = 0x03, }, + { .hz = 50, .value = 0x04, }, + { .hz = 100, .value = 0x05, }, + { .hz = 200, .value = 0x06, }, + { .hz = 400, .value = 0x07, }, + { .hz = 1600, .value = 0x08, }, + }, + }, + .pw = { + .addr = 0x20, + .mask = 0xf0, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .enable_axis = { + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, + }, + .fs = { + .addr = 0x23, + .mask = 0x30, + .fs_avl = { + [0] = { + .num = ST_ACCEL_FS_AVL_2G, + .value = 0x00, + .gain = IIO_G_TO_M_S_2(1000), + }, + [1] = { + .num = ST_ACCEL_FS_AVL_4G, + .value = 0x01, + .gain = IIO_G_TO_M_S_2(2000), + }, + [2] = { + .num = ST_ACCEL_FS_AVL_8G, + .value = 0x02, + .gain = IIO_G_TO_M_S_2(4000), + }, + [3] = { + .num = ST_ACCEL_FS_AVL_16G, + .value = 0x03, + .gain = IIO_G_TO_M_S_2(12000), + }, + }, + }, + .bdu = { + .addr = 0x23, + .mask = 0x80, + }, + .drdy_irq = { + .int1 = { + .addr = 0x22, + .mask = 0x10, + }, + .addr_ihl = 0x25, + .mask_ihl = 0x02, + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = 0x07, + }, + }, + .sim = { + .addr = 0x23, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, }; /* Default accel DRDY is available on INT1 pin */ @@ -1130,28 +1294,21 @@ read_error: static int st_accel_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { - int err; - switch (mask) { case IIO_CHAN_INFO_SCALE: { int gain; gain = val * 1000000 + val2; - err = st_sensors_set_fullscale_by_gain(indio_dev, gain); - break; + return st_sensors_set_fullscale_by_gain(indio_dev, gain); } case IIO_CHAN_INFO_SAMP_FREQ: if (val2) return -EINVAL; - mutex_lock(&indio_dev->mlock); - err = st_sensors_set_odr(indio_dev, val); - mutex_unlock(&indio_dev->mlock); - return err; + + return st_sensors_set_odr(indio_dev, val); default: return -EINVAL; } - - return err; } static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL(); @@ -1196,6 +1353,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) union acpi_object *ont; union acpi_object *elements; acpi_status status; + struct device *parent = indio_dev->dev.parent; int ret = -EINVAL; unsigned int val; int i, j; @@ -1214,17 +1372,16 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) }; - adev = ACPI_COMPANION(adata->dev); + adev = ACPI_COMPANION(parent); if (!adev) - return 0; + return -ENXIO; /* Read _ONT data, which should be a package of 6 integers. */ status = acpi_evaluate_object(adev->handle, "_ONT", NULL, &buffer); if (status == AE_NOT_FOUND) { - return 0; + return -ENXIO; } else if (ACPI_FAILURE(status)) { - dev_warn(&indio_dev->dev, "failed to execute _ONT: %d\n", - status); + dev_warn(parent, "failed to execute _ONT: %d\n", status); return status; } @@ -1300,12 +1457,12 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) } ret = 0; - dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n"); + dev_info(parent, "computed mount matrix from ACPI\n"); out: kfree(buffer.pointer); if (ret) - dev_dbg(&indio_dev->dev, + dev_dbg(parent, "failed to apply ACPI orientation data: %d\n", ret); return ret; @@ -1333,12 +1490,13 @@ const struct st_sensor_settings *st_accel_get_settings(const char *name) return &st_accel_sensors_settings[index]; } -EXPORT_SYMBOL(st_accel_get_settings); +EXPORT_SYMBOL_NS(st_accel_get_settings, "IIO_ST_SENSORS"); int st_accel_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *adata = iio_priv(indio_dev); - struct st_sensors_platform_data *pdata = dev_get_platdata(adata->dev); + struct device *parent = indio_dev->dev.parent; + struct st_sensors_platform_data *pdata = dev_get_platdata(parent); int err; indio_dev->modes = INDIO_DIRECT_MODE; @@ -1358,7 +1516,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) */ err = apply_acpi_orientation(indio_dev); if (err) { - err = iio_read_mount_matrix(adata->dev, &adata->mount_matrix); + err = iio_read_mount_matrix(parent, &adata->mount_matrix); if (err) return err; } @@ -1381,39 +1539,14 @@ int st_accel_common_probe(struct iio_dev *indio_dev) err = st_sensors_allocate_trigger(indio_dev, ST_ACCEL_TRIGGER_OPS); if (err < 0) - goto st_accel_probe_trigger_error; + return err; } - err = iio_device_register(indio_dev); - if (err) - goto st_accel_device_register_error; - - dev_info(&indio_dev->dev, "registered accelerometer %s\n", - indio_dev->name); - - return 0; - -st_accel_device_register_error: - if (adata->irq > 0) - st_sensors_deallocate_trigger(indio_dev); -st_accel_probe_trigger_error: - st_accel_deallocate_ring(indio_dev); - return err; -} -EXPORT_SYMBOL(st_accel_common_probe); - -void st_accel_common_remove(struct iio_dev *indio_dev) -{ - struct st_sensor_data *adata = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (adata->irq > 0) - st_sensors_deallocate_trigger(indio_dev); - - st_accel_deallocate_ring(indio_dev); + return devm_iio_device_register(parent, indio_dev); } -EXPORT_SYMBOL(st_accel_common_remove); +EXPORT_SYMBOL_NS(st_accel_common_probe, "IIO_ST_SENSORS"); MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>"); MODULE_DESCRIPTION("STMicroelectronics accelerometers driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS("IIO_ST_SENSORS"); |
