diff options
Diffstat (limited to 'drivers/iio/accel')
-rw-r--r-- | drivers/iio/accel/Kconfig | 32 | ||||
-rw-r--r-- | drivers/iio/accel/Makefile | 5 | ||||
-rw-r--r-- | drivers/iio/accel/bma180.c | 676 | ||||
-rw-r--r-- | drivers/iio/accel/hid-sensor-accel-3d.c | 43 | ||||
-rw-r--r-- | drivers/iio/accel/kxsd9.c | 17 | ||||
-rw-r--r-- | drivers/iio/accel/st_accel.h | 11 | ||||
-rw-r--r-- | drivers/iio/accel/st_accel_core.c | 28 | ||||
-rw-r--r-- | drivers/iio/accel/st_accel_i2c.c | 17 | ||||
-rw-r--r-- | drivers/iio/accel/st_accel_spi.c | 17 |
9 files changed, 764 insertions, 82 deletions
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 719d83fe51dd..e23e50850655 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -1,8 +1,22 @@ # # Accelerometer drivers # +# When adding new entries keep the list in alphabetical order + menu "Accelerometers" +config BMA180 + tristate "Bosch BMA180 3-Axis Accelerometer Driver" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here if you want to build a driver for the Bosch BMA180 + triaxial acceleration sensor. + + To compile this driver as a module, choose M here: the + module will be called bma180. + config HID_SENSOR_ACCEL_3D depends on HID_SENSOR_HUB select IIO_BUFFER @@ -14,13 +28,6 @@ config HID_SENSOR_ACCEL_3D Say yes here to build support for the HID SENSOR accelerometers 3D. -config KXSD9 - tristate "Kionix KXSD9 Accelerometer Driver" - depends on SPI - help - Say yes here to build support for the Kionix KXSD9 accelerometer. - Currently this only supports the device via an SPI interface. - config IIO_ST_ACCEL_3AXIS tristate "STMicroelectronics accelerometers 3-Axis Driver" depends on (I2C || SPI_MASTER) && SYSFS @@ -33,8 +40,8 @@ config IIO_ST_ACCEL_3AXIS LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC, LIS331DLH, LSM303DL, LSM303DLM, LSM330. - This driver can also be built as a module. If so, will be created - these modules: + This driver can also be built as a module. If so, these modules + will be created: - st_accel (core functions for the driver [it is mandatory]); - st_accel_i2c (necessary for the I2C devices [optional*]); - st_accel_spi (necessary for the SPI devices [optional*]); @@ -51,4 +58,11 @@ config IIO_ST_ACCEL_SPI_3AXIS depends on IIO_ST_ACCEL_3AXIS depends on IIO_ST_SENSORS_SPI +config KXSD9 + tristate "Kionix KXSD9 Accelerometer Driver" + depends on SPI + help + Say yes here to build support for the Kionix KXSD9 accelerometer. + Currently this only supports the device via an SPI interface. + endmenu diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 87d8fa264894..c48d15f25616 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -2,7 +2,10 @@ # Makefile for industrial I/O accelerometer drivers # +# When adding new entries keep the list in alphabetical order +obj-$(CONFIG_BMA180) += bma180.o obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o +obj-$(CONFIG_KXSD9) += kxsd9.o obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o st_accel-y := st_accel_core.o @@ -10,5 +13,3 @@ st_accel-$(CONFIG_IIO_BUFFER) += st_accel_buffer.o obj-$(CONFIG_IIO_ST_ACCEL_I2C_3AXIS) += st_accel_i2c.o obj-$(CONFIG_IIO_ST_ACCEL_SPI_3AXIS) += st_accel_spi.o - -obj-$(CONFIG_KXSD9) += kxsd9.o diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c new file mode 100644 index 000000000000..12e32e6b4103 --- /dev/null +++ b/drivers/iio/accel/bma180.c @@ -0,0 +1,676 @@ +/* + * bma180.c - IIO driver for Bosch BMA180 triaxial acceleration sensor + * + * Copyright 2013 Oleksandr Kravchenko <x0199363@ti.com> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/bitops.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> + +#define BMA180_DRV_NAME "bma180" +#define BMA180_IRQ_NAME "bma180_event" + +/* Register set */ +#define BMA180_CHIP_ID 0x00 /* Need to distinguish BMA180 from other */ +#define BMA180_ACC_X_LSB 0x02 /* First of 6 registers of accel data */ +#define BMA180_CTRL_REG0 0x0d +#define BMA180_RESET 0x10 +#define BMA180_BW_TCS 0x20 +#define BMA180_CTRL_REG3 0x21 +#define BMA180_TCO_Z 0x30 +#define BMA180_OFFSET_LSB1 0x35 + +/* BMA180_CTRL_REG0 bits */ +#define BMA180_DIS_WAKE_UP BIT(0) /* Disable wake up mode */ +#define BMA180_SLEEP BIT(1) /* 1 - chip will sleep */ +#define BMA180_EE_W BIT(4) /* Unlock writing to addr from 0x20 */ +#define BMA180_RESET_INT BIT(6) /* Reset pending interrupts */ + +/* BMA180_CTRL_REG3 bits */ +#define BMA180_NEW_DATA_INT BIT(1) /* Intr every new accel data is ready */ + +/* BMA180_OFFSET_LSB1 skipping mode bit */ +#define BMA180_SMP_SKIP BIT(0) + +/* Bit masks for registers bit fields */ +#define BMA180_RANGE 0x0e /* Range of measured accel values*/ +#define BMA180_BW 0xf0 /* Accel bandwidth */ +#define BMA180_MODE_CONFIG 0x03 /* Config operation modes */ + +/* We have to write this value in reset register to do soft reset */ +#define BMA180_RESET_VAL 0xb6 + +#define BMA_180_ID_REG_VAL 0x03 + +/* Chip power modes */ +#define BMA180_LOW_NOISE 0x00 +#define BMA180_LOW_POWER 0x03 + +#define BMA180_LOW_NOISE_STR "low_noise" +#define BMA180_LOW_POWER_STR "low_power" + +/* Defaults values */ +#define BMA180_DEF_PMODE 0 +#define BMA180_DEF_BW 20 +#define BMA180_DEF_SCALE 250 + +/* Available values for sysfs */ +#define BMA180_FLP_FREQ_AVAILABLE \ + "10 20 40 75 150 300" +#define BMA180_SCALE_AVAILABLE \ + "0.000130 0.000190 0.000250 0.000380 0.000500 0.000990 0.001980" + +struct bma180_data { + struct i2c_client *client; + struct iio_trigger *trig; + struct mutex mutex; + int sleep_state; + int scale; + int bw; + int pmode; + char *buff; +}; + +enum bma180_axis { + AXIS_X, + AXIS_Y, + AXIS_Z, +}; + +static int bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ +static int scale_table[] = { 130, 190, 250, 380, 500, 990, 1980 }; + +static int bma180_get_acc_reg(struct bma180_data *data, enum bma180_axis axis) +{ + u8 reg = BMA180_ACC_X_LSB + axis * 2; + int ret; + + if (data->sleep_state) + return -EBUSY; + + ret = i2c_smbus_read_word_data(data->client, reg); + if (ret < 0) + dev_err(&data->client->dev, + "failed to read accel_%c registers\n", 'x' + axis); + + return ret; +} + +static int bma180_set_bits(struct bma180_data *data, u8 reg, u8 mask, u8 val) +{ + int ret = i2c_smbus_read_byte_data(data->client, reg); + u8 reg_val = (ret & ~mask) | (val << (ffs(mask) - 1)); + + if (ret < 0) + return ret; + + return i2c_smbus_write_byte_data(data->client, reg, reg_val); +} + +static int bma180_reset_intr(struct bma180_data *data) +{ + int ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_RESET_INT, 1); + + if (ret) + dev_err(&data->client->dev, "failed to reset interrupt\n"); + + return ret; +} + +static int bma180_set_new_data_intr_state(struct bma180_data *data, int state) +{ + u8 reg_val = state ? BMA180_NEW_DATA_INT : 0x00; + int ret = i2c_smbus_write_byte_data(data->client, BMA180_CTRL_REG3, + reg_val); + + if (ret) + goto err; + ret = bma180_reset_intr(data); + if (ret) + goto err; + + return 0; + +err: + dev_err(&data->client->dev, + "failed to set new data interrupt state %d\n", state); + return ret; +} + +static int bma180_set_sleep_state(struct bma180_data *data, int state) +{ + int ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_SLEEP, state); + + if (ret) { + dev_err(&data->client->dev, + "failed to set sleep state %d\n", state); + return ret; + } + data->sleep_state = state; + + return 0; +} + +static int bma180_set_ee_writing_state(struct bma180_data *data, int state) +{ + int ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_EE_W, state); + + if (ret) + dev_err(&data->client->dev, + "failed to set ee writing state %d\n", state); + + return ret; +} + +static int bma180_set_bw(struct bma180_data *data, int val) +{ + int ret, i; + + if (data->sleep_state) + return -EBUSY; + + for (i = 0; i < ARRAY_SIZE(bw_table); ++i) { + if (bw_table[i] == val) { + ret = bma180_set_bits(data, + BMA180_BW_TCS, BMA180_BW, i); + if (ret) { + dev_err(&data->client->dev, + "failed to set bandwidth\n"); + return ret; + } + data->bw = val; + return 0; + } + } + + return -EINVAL; +} + +static int bma180_set_scale(struct bma180_data *data, int val) +{ + int ret, i; + + if (data->sleep_state) + return -EBUSY; + + for (i = 0; i < ARRAY_SIZE(scale_table); ++i) + if (scale_table[i] == val) { + ret = bma180_set_bits(data, + BMA180_OFFSET_LSB1, BMA180_RANGE, i); + if (ret) { + dev_err(&data->client->dev, + "failed to set scale\n"); + return ret; + } + data->scale = val; + return 0; + } + + return -EINVAL; +} + +static int bma180_set_pmode(struct bma180_data *data, int mode) +{ + u8 reg_val = mode ? BMA180_LOW_POWER : BMA180_LOW_NOISE; + int ret = bma180_set_bits(data, BMA180_TCO_Z, BMA180_MODE_CONFIG, + reg_val); + + if (ret) { + dev_err(&data->client->dev, "failed to set power mode\n"); + return ret; + } + data->pmode = mode; + + return 0; +} + +static int bma180_soft_reset(struct bma180_data *data) +{ + int ret = i2c_smbus_write_byte_data(data->client, + BMA180_RESET, BMA180_RESET_VAL); + + if (ret) + dev_err(&data->client->dev, "failed to reset the chip\n"); + + return ret; +} + +static int bma180_chip_init(struct bma180_data *data) +{ + /* Try to read chip_id register. It must return 0x03. */ + int ret = i2c_smbus_read_byte_data(data->client, BMA180_CHIP_ID); + + if (ret < 0) + goto err; + if (ret != BMA_180_ID_REG_VAL) { + ret = -ENODEV; + goto err; + } + + ret = bma180_soft_reset(data); + if (ret) + goto err; + /* + * No serial transaction should occur within minimum 10 us + * after soft_reset command + */ + msleep(20); + + ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_DIS_WAKE_UP, 1); + if (ret) + goto err; + ret = bma180_set_ee_writing_state(data, 1); + if (ret) + goto err; + ret = bma180_set_new_data_intr_state(data, 0); + if (ret) + goto err; + ret = bma180_set_bits(data, BMA180_OFFSET_LSB1, BMA180_SMP_SKIP, 1); + if (ret) + goto err; + ret = bma180_set_pmode(data, BMA180_DEF_PMODE); + if (ret) + goto err; + ret = bma180_set_bw(data, BMA180_DEF_BW); + if (ret) + goto err; + ret = bma180_set_scale(data, BMA180_DEF_SCALE); + if (ret) + goto err; + + return 0; + +err: + dev_err(&data->client->dev, "failed to init the chip\n"); + return ret; +} + +static void bma180_chip_disable(struct bma180_data *data) +{ + if (bma180_set_new_data_intr_state(data, 0)) + goto err; + if (bma180_set_ee_writing_state(data, 0)) + goto err; + if (bma180_set_sleep_state(data, 1)) + goto err; + + return; + +err: + dev_err(&data->client->dev, "failed to disable the chip\n"); +} + +static IIO_CONST_ATTR(in_accel_filter_low_pass_3db_frequency_available, + BMA180_FLP_FREQ_AVAILABLE); +static IIO_CONST_ATTR(in_accel_scale_available, BMA180_SCALE_AVAILABLE); + +static struct attribute *bma180_attributes[] = { + &iio_const_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, + &iio_const_attr_in_accel_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group bma180_attrs_group = { + .attrs = bma180_attributes, +}; + +static int bma180_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, + long mask) +{ + struct bma180_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&data->mutex); + if (iio_buffer_enabled(indio_dev)) + ret = -EBUSY; + else + ret = bma180_get_acc_reg(data, chan->scan_index); + mutex_unlock(&data->mutex); + if (ret < 0) + return ret; + *val = (s16)ret >> chan->scan_type.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *val = data->bw; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = data->scale; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int bma180_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct bma180_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + if (val) + return -EINVAL; + mutex_lock(&data->mutex); + ret = bma180_set_scale(data, val2); + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + mutex_lock(&data->mutex); + ret = bma180_set_bw(data, val); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } +} + +static int bma180_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct bma180_data *data = iio_priv(indio_dev); + + if (data->buff) + devm_kfree(&indio_dev->dev, data->buff); + data->buff = devm_kzalloc(&indio_dev->dev, + indio_dev->scan_bytes, GFP_KERNEL); + if (!data->buff) + return -ENOMEM; + + return 0; +} + +static const struct iio_info bma180_info = { + .attrs = &bma180_attrs_group, + .read_raw = bma180_read_raw, + .write_raw = bma180_write_raw, + .update_scan_mode = bma180_update_scan_mode, + .driver_module = THIS_MODULE, +}; + +static const char * const bma180_power_modes[] = { + BMA180_LOW_NOISE_STR, + BMA180_LOW_POWER_STR, +}; + +static int bma180_get_power_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct bma180_data *data = iio_priv(indio_dev); + + return data->pmode; +} + +static int bma180_set_power_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) +{ + struct bma180_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = bma180_set_pmode(data, mode); + mutex_unlock(&data->mutex); + + return ret; +} + +static const struct iio_enum bma180_power_mode_enum = { + .items = bma180_power_modes, + .num_items = ARRAY_SIZE(bma180_power_modes), + .get = bma180_get_power_mode, + .set = bma180_set_power_mode, +}; + +static const struct iio_chan_spec_ext_info bma180_ext_info[] = { + IIO_ENUM("power_mode", true, &bma180_power_mode_enum), + IIO_ENUM_AVAILABLE("power_mode", &bma180_power_mode_enum), + { }, +}; + +#define BMA180_CHANNEL(_index) { \ + .type = IIO_ACCEL, \ + .indexed = 1, \ + .channel = (_index), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = (_index), \ + .scan_type = IIO_ST('s', 14, 16, 2), \ + .ext_info = bma180_ext_info, \ +} + +static const struct iio_chan_spec bma180_channels[] = { + BMA180_CHANNEL(AXIS_X), + BMA180_CHANNEL(AXIS_Y), + BMA180_CHANNEL(AXIS_Z), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static irqreturn_t bma180_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct bma180_data *data = iio_priv(indio_dev); + int bit, ret, i = 0; + + mutex_lock(&data->mutex); + if (indio_dev->scan_timestamp) { + ret = indio_dev->scan_bytes / sizeof(s64) - 1; + ((s64 *)data->buff)[ret] = iio_get_time_ns(); + } + + for_each_set_bit(bit, indio_dev->buffer->scan_mask, + indio_dev->masklength) { + ret = bma180_get_acc_reg(data, bit); + if (ret < 0) { + mutex_unlock(&data->mutex); + goto err; + } + ((s16 *)data->buff)[i++] = ret; + } + mutex_unlock(&data->mutex); + + iio_push_to_buffers(indio_dev, (u8 *)data->buff); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int bma180_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct bma180_data *data = iio_priv(indio_dev); + + return bma180_set_new_data_intr_state(data, state); +} + +static int bma180_trig_try_reen(struct iio_trigger *trig) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct bma180_data *data = iio_priv(indio_dev); + + return bma180_reset_intr(data); +} + +static const struct iio_trigger_ops bma180_trigger_ops = { + .set_trigger_state = bma180_data_rdy_trigger_set_state, + .try_reenable = bma180_trig_try_reen, + .owner = THIS_MODULE, +}; + +static int bma180_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct bma180_data *data; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + ret = bma180_chip_init(data); + if (ret < 0) + goto err_chip_disable; + + mutex_init(&data->mutex); + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = bma180_channels; + indio_dev->num_channels = ARRAY_SIZE(bma180_channels); + indio_dev->name = BMA180_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &bma180_info; + + trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id); + if (!trig) { + ret = -ENOMEM; + goto err_chip_disable; + } + + ret = devm_request_irq(&client->dev, client->irq, + iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_RISING, BMA180_IRQ_NAME, trig); + if (ret) { + dev_err(&client->dev, "unable to request IRQ\n"); + goto err_trigger_free; + } + + trig->dev.parent = &client->dev; + trig->ops = &bma180_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + data->trig = trig; + indio_dev->trig = trig; + + ret = iio_trigger_register(trig); + if (ret) + goto err_trigger_free; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + bma180_trigger_handler, NULL); + if (ret < 0) { + dev_err(&client->dev, "unable to setup iio triggered buffer\n"); + goto err_trigger_unregister; + } + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "unable to register iio device\n"); + goto err_buffer_cleanup; + } + + return 0; + +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); +err_trigger_unregister: + iio_trigger_unregister(trig); +err_trigger_free: + iio_trigger_free(trig); +err_chip_disable: + bma180_chip_disable(data); + + return ret; +} + +static int bma180_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct bma180_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + iio_trigger_unregister(data->trig); + iio_trigger_free(data->trig); + + mutex_lock(&data->mutex); + bma180_chip_disable(data); + mutex_unlock(&data->mutex); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int bma180_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct bma180_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = bma180_set_sleep_state(data, 1); + mutex_unlock(&data->mutex); + + return ret; +} + +static int bma180_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct bma180_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = bma180_set_sleep_state(data, 0); + mutex_unlock(&data->mutex); + + return ret; +} + +static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); +#define BMA180_PM_OPS (&bma180_pm_ops) +#else +#define BMA180_PM_OPS NULL +#endif + +static struct i2c_device_id bma180_id[] = { + { BMA180_DRV_NAME, 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, bma180_id); + +static struct i2c_driver bma180_driver = { + .driver = { + .name = BMA180_DRV_NAME, + .owner = THIS_MODULE, + .pm = BMA180_PM_OPS, + }, + .probe = bma180_probe, + .remove = bma180_remove, + .id_table = bma180_id, +}; + +module_i2c_driver(bma180_driver); + +MODULE_AUTHOR("Kravchenko Oleksandr <x0199363@ti.com>"); +MODULE_AUTHOR("Texas Instruments, Inc."); +MODULE_DESCRIPTION("Bosch BMA180 triaxial acceleration sensor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index bbcbd7101f33..46d22f3fb1a9 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -30,10 +30,6 @@ #include <linux/iio/triggered_buffer.h> #include "../common/hid-sensors/hid-sensor-trigger.h" -/*Format: HID-SENSOR-usage_id_in_hex*/ -/*Usage ID from spec for Accelerometer-3D: 0x200073*/ -#define DRIVER_NAME "HID-SENSOR-200073" - enum accel_3d_channel { CHANNEL_SCAN_INDEX_X, CHANNEL_SCAN_INDEX_Y, @@ -179,18 +175,10 @@ static int accel_3d_write_raw(struct iio_dev *indio_dev, return ret; } -static int accel_3d_write_raw_get_fmt(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask) -{ - return IIO_VAL_INT_PLUS_MICRO; -} - static const struct iio_info accel_3d_info = { .driver_module = THIS_MODULE, .read_raw = &accel_3d_read_raw, .write_raw = &accel_3d_write_raw, - .write_raw_get_fmt = &accel_3d_write_raw_get_fmt, }; /* Function to push data to buffer */ @@ -286,11 +274,11 @@ static int hid_accel_3d_probe(struct platform_device *pdev) struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; struct iio_chan_spec *channels; - indio_dev = iio_device_alloc(sizeof(struct accel_3d_state)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&pdev->dev, + sizeof(struct accel_3d_state)); + if (indio_dev == NULL) + return -ENOMEM; + platform_set_drvdata(pdev, indio_dev); accel_state = iio_priv(indio_dev); @@ -302,15 +290,14 @@ static int hid_accel_3d_probe(struct platform_device *pdev) &accel_state->common_attributes); if (ret) { dev_err(&pdev->dev, "failed to setup common attributes\n"); - goto error_free_dev; + return ret; } channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels), GFP_KERNEL); if (!channels) { - ret = -ENOMEM; dev_err(&pdev->dev, "failed to duplicate channels\n"); - goto error_free_dev; + return -ENOMEM; } ret = accel_3d_parse_report(pdev, hsdev, channels, @@ -367,9 +354,6 @@ error_unreg_buffer_funcs: iio_triggered_buffer_cleanup(indio_dev); error_free_dev_mem: kfree(indio_dev->channels); -error_free_dev: - iio_device_free(indio_dev); -error_ret: return ret; } @@ -384,14 +368,23 @@ static int hid_accel_3d_remove(struct platform_device *pdev) hid_sensor_remove_trigger(indio_dev); iio_triggered_buffer_cleanup(indio_dev); kfree(indio_dev->channels); - iio_device_free(indio_dev); return 0; } +static struct platform_device_id hid_accel_3d_ids[] = { + { + /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ + .name = "HID-SENSOR-200073", + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, hid_accel_3d_ids); + static struct platform_driver hid_accel_3d_platform_driver = { + .id_table = hid_accel_3d_ids, .driver = { - .name = DRIVER_NAME, + .name = KBUILD_MODNAME, .owner = THIS_MODULE, }, .probe = hid_accel_3d_probe, diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 7229645bf1d7..709c13259f14 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -224,11 +224,10 @@ static int kxsd9_probe(struct spi_device *spi) struct kxsd9_state *st; int ret; - indio_dev = iio_device_alloc(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + st = iio_priv(indio_dev); spi_set_drvdata(spi, indio_dev); @@ -247,20 +246,14 @@ static int kxsd9_probe(struct spi_device *spi) ret = iio_device_register(indio_dev); if (ret) - goto error_free_dev; + return ret; return 0; - -error_free_dev: - iio_device_free(indio_dev); -error_ret: - return ret; } static int kxsd9_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); - iio_device_free(spi_get_drvdata(spi)); return 0; } diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index 37949b94377d..c3877630b2e4 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -25,7 +25,16 @@ #define LSM303DLM_ACCEL_DEV_NAME "lsm303dlm_accel" #define LSM330_ACCEL_DEV_NAME "lsm330_accel" -int st_accel_common_probe(struct iio_dev *indio_dev); +/** +* struct st_sensors_platform_data - default accel platform data +* @drdy_int_pin: default accel DRDY is available on INT1 pin. +*/ +static const struct st_sensors_platform_data default_accel_pdata = { + .drdy_int_pin = 1, +}; + +int st_accel_common_probe(struct iio_dev *indio_dev, + struct st_sensors_platform_data *pdata); void st_accel_common_remove(struct iio_dev *indio_dev); #ifdef CONFIG_IIO_BUFFER diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 4aec121261d7..1458343f6f3f 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -65,7 +65,8 @@ #define ST_ACCEL_1_BDU_ADDR 0x23 #define ST_ACCEL_1_BDU_MASK 0x80 #define ST_ACCEL_1_DRDY_IRQ_ADDR 0x22 -#define ST_ACCEL_1_DRDY_IRQ_MASK 0x10 +#define ST_ACCEL_1_DRDY_IRQ_INT1_MASK 0x10 +#define ST_ACCEL_1_DRDY_IRQ_INT2_MASK 0x08 #define ST_ACCEL_1_MULTIREAD_BIT true /* CUSTOM VALUES FOR SENSOR 2 */ @@ -89,7 +90,8 @@ #define ST_ACCEL_2_BDU_ADDR 0x23 #define ST_ACCEL_2_BDU_MASK 0x80 #define ST_ACCEL_2_DRDY_IRQ_ADDR 0x22 -#define ST_ACCEL_2_DRDY_IRQ_MASK 0x02 +#define ST_ACCEL_2_DRDY_IRQ_INT1_MASK 0x02 +#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10 #define ST_ACCEL_2_MULTIREAD_BIT true /* CUSTOM VALUES FOR SENSOR 3 */ @@ -121,7 +123,8 @@ #define ST_ACCEL_3_BDU_ADDR 0x20 #define ST_ACCEL_3_BDU_MASK 0x08 #define ST_ACCEL_3_DRDY_IRQ_ADDR 0x23 -#define ST_ACCEL_3_DRDY_IRQ_MASK 0x80 +#define ST_ACCEL_3_DRDY_IRQ_INT1_MASK 0x80 +#define ST_ACCEL_3_DRDY_IRQ_INT2_MASK 0x00 #define ST_ACCEL_3_IG1_EN_ADDR 0x23 #define ST_ACCEL_3_IG1_EN_MASK 0x08 #define ST_ACCEL_3_MULTIREAD_BIT false @@ -224,7 +227,8 @@ static const struct st_sensors st_accel_sensors[] = { }, .drdy_irq = { .addr = ST_ACCEL_1_DRDY_IRQ_ADDR, - .mask = ST_ACCEL_1_DRDY_IRQ_MASK, + .mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK, + .mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK, }, .multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT, .bootime = 2, @@ -285,7 +289,8 @@ static const struct st_sensors st_accel_sensors[] = { }, .drdy_irq = { .addr = ST_ACCEL_2_DRDY_IRQ_ADDR, - .mask = ST_ACCEL_2_DRDY_IRQ_MASK, + .mask_int1 = ST_ACCEL_2_DRDY_IRQ_INT1_MASK, + .mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK, }, .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT, .bootime = 2, @@ -358,7 +363,8 @@ static const struct st_sensors st_accel_sensors[] = { }, .drdy_irq = { .addr = ST_ACCEL_3_DRDY_IRQ_ADDR, - .mask = ST_ACCEL_3_DRDY_IRQ_MASK, + .mask_int1 = ST_ACCEL_3_DRDY_IRQ_INT1_MASK, + .mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK, .ig1 = { .en_addr = ST_ACCEL_3_IG1_EN_ADDR, .en_mask = ST_ACCEL_3_IG1_EN_MASK, @@ -443,7 +449,8 @@ static const struct iio_trigger_ops st_accel_trigger_ops = { #define ST_ACCEL_TRIGGER_OPS NULL #endif -int st_accel_common_probe(struct iio_dev *indio_dev) +int st_accel_common_probe(struct iio_dev *indio_dev, + struct st_sensors_platform_data *plat_data) { int err; struct st_sensor_data *adata = iio_priv(indio_dev); @@ -465,7 +472,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev) &adata->sensor->fs.fs_avl[0]; adata->odr = adata->sensor->odr.odr_avl[0].hz; - err = st_sensors_init_sensor(indio_dev); + if (!plat_data) + plat_data = + (struct st_sensors_platform_data *)&default_accel_pdata; + + err = st_sensors_init_sensor(indio_dev, plat_data); if (err < 0) goto st_accel_common_probe_error; @@ -506,7 +517,6 @@ void st_accel_common_remove(struct iio_dev *indio_dev) st_sensors_deallocate_trigger(indio_dev); st_accel_deallocate_ring(indio_dev); } - iio_device_free(indio_dev); } EXPORT_SYMBOL(st_accel_common_remove); diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index ffc9d097e484..d7bedbdfc81d 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -25,27 +25,20 @@ static int st_accel_i2c_probe(struct i2c_client *client, struct st_sensor_data *adata; int err; - indio_dev = iio_device_alloc(sizeof(*adata)); - if (indio_dev == NULL) { - err = -ENOMEM; - goto iio_device_alloc_error; - } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata)); + if (!indio_dev) + return -ENOMEM; adata = iio_priv(indio_dev); adata->dev = &client->dev; st_sensors_i2c_configure(indio_dev, client, adata); - err = st_accel_common_probe(indio_dev); + err = st_accel_common_probe(indio_dev, client->dev.platform_data); if (err < 0) - goto st_accel_common_probe_error; + return err; return 0; - -st_accel_common_probe_error: - iio_device_free(indio_dev); -iio_device_alloc_error: - return err; } static int st_accel_i2c_remove(struct i2c_client *client) diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 22b35bfea7d2..195639646e34 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -24,27 +24,20 @@ static int st_accel_spi_probe(struct spi_device *spi) struct st_sensor_data *adata; int err; - indio_dev = iio_device_alloc(sizeof(*adata)); - if (indio_dev == NULL) { - err = -ENOMEM; - goto iio_device_alloc_error; - } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adata)); + if (!indio_dev) + return -ENOMEM; adata = iio_priv(indio_dev); adata->dev = &spi->dev; st_sensors_spi_configure(indio_dev, spi, adata); - err = st_accel_common_probe(indio_dev); + err = st_accel_common_probe(indio_dev, spi->dev.platform_data); if (err < 0) - goto st_accel_common_probe_error; + return err; return 0; - -st_accel_common_probe_error: - iio_device_free(indio_dev); -iio_device_alloc_error: - return err; } static int st_accel_spi_remove(struct spi_device *spi) |