diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-11 09:58:02 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-11 09:58:02 -0800 |
commit | ad463ac42771a0bb8a706cf8a985788fe5f5c1c6 (patch) | |
tree | d8585ea49108c4d73af97b75b3ffdc0d094b68ee /drivers | |
parent | 5305d746054d1c73e7e9263b25189dedefb2dc01 (diff) | |
parent | 09a642b78523e9f4c5970c806ad218aa3de31551 (diff) |
Merge tag 'iio-for-3.9d' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
"4th set of IIO new drivers cleanups and fixes for the 3.9 cycle
+ a new spi helper function.
1) Introduce spi_sync_transfer and use it within IIO. Originally
it was envisioned that this nice little boilerplate replacement
would go through the spi tree, but Grant Likely stated he'd
prefer we take it through IIO as the example usecases were all
in IIO (and are also in this pull request). Note that given
their may have been some unresolved elements related to the
coccinelle element of the patch, that has been stripped out
and will doubtlessly follow at a later date (along with
lots of other patches for drivers elsewhere in the tree).
2) New Invensense MPU6050 driver. This is stripped down to pretty
much the basics from the original submission with the intent
to build up all the fancy bits in an incremental (and hence
reviewable fashion). It's been through a good few revisions
so nice to finally merge this.
3) Change to iio_channel_get api to simplify device tree based
mappings. The actual mappings are currently under review.
4) Build fixes for !CONFIG_IIO_TRIGGER in the st_sensors driver.
This one snuck past during review and testing but got picked
up by Randy Dunlap in a randconfig build.
5) Some max1363 cleanups and enhancements.
6) Some comment fixes to make them coherent and comprehensible.
7) Trivial build warning fix in mxs-lradc"
Diffstat (limited to 'drivers')
47 files changed, 1540 insertions, 244 deletions
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index eda2a1aa4adb..d0233cd18ffa 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -135,8 +135,7 @@ static int adc_jack_probe(struct platform_device *pdev) ; data->num_conditions = i; - data->chan = iio_channel_get(dev_name(&pdev->dev), - pdata->consumer_channel); + data->chan = iio_channel_get(&pdev->dev, pdata->consumer_channel); if (IS_ERR(data->chan)) { err = PTR_ERR(data->chan); goto out; diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 4a24c2ee81a9..c2229a521ab9 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -94,7 +94,6 @@ error_ret: static int kxsd9_read(struct iio_dev *indio_dev, u8 address) { - struct spi_message msg; int ret; struct kxsd9_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { @@ -112,10 +111,7 @@ static int kxsd9_read(struct iio_dev *indio_dev, u8 address) mutex_lock(&st->buf_lock); st->tx[0] = KXSD9_READ(address); - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) return ret; return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index a235de252a90..e0f5a3ceba5e 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -20,7 +20,7 @@ #include <linux/irq.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#include <linux/iio/trigger_consumer.h> +#include <linux/iio/trigger.h> #include <linux/iio/buffer.h> #include <linux/iio/common/st_sensors.h> @@ -419,10 +419,15 @@ static const struct iio_info accel_info = { .write_raw = &st_accel_write_raw, }; +#ifdef CONFIG_IIO_TRIGGER static const struct iio_trigger_ops st_accel_trigger_ops = { .owner = THIS_MODULE, .set_trigger_state = ST_ACCEL_TRIGGER_SET_STATE, }; +#define ST_ACCEL_TRIGGER_OPS (&st_accel_trigger_ops) +#else +#define ST_ACCEL_TRIGGER_OPS NULL +#endif int st_accel_common_probe(struct iio_dev *indio_dev) { @@ -455,7 +460,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) goto st_accel_common_probe_error; err = st_sensors_allocate_trigger(indio_dev, - &st_accel_trigger_ops); + ST_ACCEL_TRIGGER_OPS); if (err < 0) goto st_accel_probe_trigger_error; } diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index 90b8ddfb61ed..ffc9d097e484 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -13,7 +13,6 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/iio/iio.h> -#include <linux/iio/trigger.h> #include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors_i2c.h> diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index dbd45c08711f..22b35bfea7d2 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -13,7 +13,6 @@ #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/iio/iio.h> -#include <linux/iio/trigger.h> #include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors_spi.h> diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 08e4feb4f6ee..6c1cfb74bdfc 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -163,6 +163,8 @@ struct max1363_chip_info { * @mask_low: bitmask for enabled low thresholds * @thresh_high: high threshold values * @thresh_low: low threshold values + * @vref: Reference voltage regulator + * @vref_uv: Actual (external or internal) reference voltage */ struct max1363_state { struct i2c_client *client; @@ -182,6 +184,8 @@ struct max1363_state { /* 4x unipolar first then the fours bipolar ones */ s16 thresh_high[8]; s16 thresh_low[8]; + struct regulator *vref; + u32 vref_uv; }; #define MAX1363_MODE_SINGLE(_num, _mask) { \ @@ -393,6 +397,8 @@ static int max1363_read_raw(struct iio_dev *indio_dev, { struct max1363_state *st = iio_priv(indio_dev); int ret; + unsigned long scale_uv; + switch (m) { case IIO_CHAN_INFO_RAW: ret = max1363_read_single_chan(indio_dev, chan, val, m); @@ -400,16 +406,10 @@ static int max1363_read_raw(struct iio_dev *indio_dev, return ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - if ((1 << (st->chip_info->bits + 1)) > - st->chip_info->int_vref_mv) { - *val = 0; - *val2 = 500000; - return IIO_VAL_INT_PLUS_MICRO; - } else { - *val = (st->chip_info->int_vref_mv) - >> st->chip_info->bits; - return IIO_VAL_INT; - } + scale_uv = st->vref_uv >> st->chip_info->bits; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -1390,12 +1390,16 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = { static int max1363_initial_setup(struct max1363_state *st) { - st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD - | MAX1363_SETUP_POWER_UP_INT_REF - | MAX1363_SETUP_INT_CLOCK + st->setupbyte = MAX1363_SETUP_INT_CLOCK | MAX1363_SETUP_UNIPOLAR | MAX1363_SETUP_NORESET; + if (st->vref) + st->setupbyte |= MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF; + else + st->setupbyte |= MAX1363_SETUP_POWER_UP_INT_REF + | MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT; + /* Set scan mode writes the config anyway so wait until then */ st->setupbyte = MAX1363_SETUP_BYTE(st->setupbyte); st->current_mode = &max1363_mode_table[st->chip_info->default_mode]; @@ -1410,8 +1414,9 @@ static int max1363_alloc_scan_masks(struct iio_dev *indio_dev) unsigned long *masks; int i; - masks = kzalloc(BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*sizeof(long)* - (st->chip_info->num_modes + 1), GFP_KERNEL); + masks = devm_kzalloc(&indio_dev->dev, + BITS_TO_LONGS(MAX1363_MAX_CHANNELS) * sizeof(long) * + (st->chip_info->num_modes + 1), GFP_KERNEL); if (!masks) return -ENOMEM; @@ -1490,6 +1495,7 @@ static int max1363_probe(struct i2c_client *client, int ret; struct max1363_state *st; struct iio_dev *indio_dev; + struct regulator *vref; indio_dev = iio_device_alloc(sizeof(struct max1363_state)); if (indio_dev == NULL) { @@ -1504,7 +1510,7 @@ static int max1363_probe(struct i2c_client *client, st = iio_priv(indio_dev); - st->reg = regulator_get(&client->dev, "vcc"); + st->reg = devm_regulator_get(&client->dev, "vcc"); if (IS_ERR(st->reg)) { ret = PTR_ERR(st->reg); goto error_unregister_map; @@ -1512,7 +1518,7 @@ static int max1363_probe(struct i2c_client *client, ret = regulator_enable(st->reg); if (ret) - goto error_put_reg; + goto error_unregister_map; /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); @@ -1520,6 +1526,23 @@ static int max1363_probe(struct i2c_client *client, st->chip_info = &max1363_chip_info_tbl[id->driver_data]; st->client = client; + st->vref_uv = st->chip_info->int_vref_mv * 1000; + vref = devm_regulator_get(&client->dev, "vref"); + if (!IS_ERR(vref)) { + int vref_uv; + + ret = regulator_enable(vref); + if (ret) + goto error_disable_reg; + st->vref = vref; + vref_uv = regulator_get_voltage(vref); + if (vref_uv <= 0) { + ret = -EINVAL; + goto error_disable_reg; + } + st->vref_uv = vref_uv; + } + ret = max1363_alloc_scan_masks(indio_dev); if (ret) goto error_disable_reg; @@ -1533,15 +1556,15 @@ static int max1363_probe(struct i2c_client *client, indio_dev->modes = INDIO_DIRECT_MODE; ret = max1363_initial_setup(st); if (ret < 0) - goto error_free_available_scan_masks; + goto error_disable_reg; ret = iio_triggered_buffer_setup(indio_dev, NULL, &max1363_trigger_handler, &max1363_buffered_setup_ops); if (ret) - goto error_free_available_scan_masks; + goto error_disable_reg; if (client->irq) { - ret = request_threaded_irq(st->client->irq, + ret = devm_request_threaded_irq(&client->dev, st->client->irq, NULL, &max1363_event_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, @@ -1554,20 +1577,16 @@ static int max1363_probe(struct i2c_client *client, ret = iio_device_register(indio_dev); if (ret < 0) - goto error_free_irq; + goto error_uninit_buffer; return 0; -error_free_irq: - if (client->irq) - free_irq(st->client->irq, indio_dev); + error_uninit_buffer: iio_triggered_buffer_cleanup(indio_dev); -error_free_available_scan_masks: - kfree(indio_dev->available_scan_masks); error_disable_reg: + if (st->vref) + regulator_disable(st->vref); regulator_disable(st->reg); -error_put_reg: - regulator_put(st->reg); error_unregister_map: iio_map_array_unregister(indio_dev); error_free_device: @@ -1582,12 +1601,10 @@ static int max1363_remove(struct i2c_client *client) struct max1363_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - if (client->irq) - free_irq(st->client->irq, indio_dev); iio_triggered_buffer_cleanup(indio_dev); - kfree(indio_dev->available_scan_masks); + if (st->vref) + regulator_disable(st->vref); regulator_disable(st->reg); - regulator_put(st->reg); iio_map_array_unregister(indio_dev); iio_device_free(indio_dev); diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c index 54b46fd3aede..92771217f665 100644 --- a/drivers/iio/dac/ad5360.c +++ b/drivers/iio/dac/ad5360.c @@ -213,7 +213,6 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, unsigned int addr) { struct ad5360_state *st = iio_priv(indio_dev); - struct spi_message m; int ret; struct spi_transfer t[] = { { @@ -226,10 +225,6 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, }, }; - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - mutex_lock(&indio_dev->mlock); st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) | @@ -237,7 +232,7 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, AD5360_READBACK_TYPE(type) | AD5360_READBACK_ADDR(addr)); - ret = spi_sync(st->spi, &m); + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); if (ret >= 0) ret = be32_to_cpu(st->data[1].d32) & 0xffff; diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index 43be948db83e..6b86a638dad0 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -127,7 +127,6 @@ static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg, static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg) { struct ad5421_state *st = iio_priv(indio_dev); - struct spi_message m; int ret; struct spi_transfer t[] = { { @@ -140,15 +139,11 @@ static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg) }, }; - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - mutex_lock(&indio_dev->mlock); st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16)); - ret = spi_sync(st->spi, &m); + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); if (ret >= 0) ret = be32_to_cpu(st->data[1].d32) & 0xffff; diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index 0661829f2773..e5e59749f109 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -85,11 +85,7 @@ static int ad5504_spi_read(struct spi_device *spi, u8 addr) .rx_buf = &val, .len = 2, }; - struct spi_message m; - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - ret = spi_sync(spi, &m); + ret = spi_sync_transfer(spi, &t, 1); if (ret < 0) return ret; diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index ca9609d7a15c..5e554af21703 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -117,18 +117,13 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr) .len = 3, }, }; - struct spi_message m; int ret; - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) | AD5686_ADDR(addr)); st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP)); - ret = spi_sync(st->spi, &m); + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); if (ret < 0) return ret; diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index 0869bbd27d30..71faabc6b14e 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -153,7 +153,6 @@ static int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel, static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr) { struct ad5755_state *st = iio_priv(indio_dev); - struct spi_message m; int ret; struct spi_transfer t[] = { { @@ -167,16 +166,12 @@ static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr) }, }; - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - mutex_lock(&indio_dev->mlock); st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16)); st->data[1].d32 = cpu_to_be32(AD5755_NOOP); - ret = spi_sync(st->spi, &m); + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); if (ret >= 0) ret = be32_to_cpu(st->data[1].d32) & 0xffff; diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c index 7f9045e6daa4..5b7acd3a2c77 100644 --- a/drivers/iio/dac/ad5764.c +++ b/drivers/iio/dac/ad5764.c @@ -135,7 +135,6 @@ static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg, unsigned int *val) { struct ad5764_state *st = iio_priv(indio_dev); - struct spi_message m; int ret; struct spi_transfer t[] = { { @@ -148,15 +147,11 @@ static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg, }, }; - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - mutex_lock(&indio_dev->mlock); st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16)); - ret = spi_sync(st->spi, &m); + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); if (ret >= 0) *val = be32_to_cpu(st->data[1].d32) & 0xffff; diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index 6407b5407ddd..8dfd3da8a07b 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -125,7 +125,6 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) u8 d8[4]; } data[3]; int ret; - struct spi_message msg; struct spi_transfer xfers[] = { { .tx_buf = &data[0].d8[1], @@ -144,10 +143,7 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) AD5791_ADDR(addr)); data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP)); - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(spi, &msg); + ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); *val = be32_to_cpu(data[2].d32); diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 80307473e3a9..1ea132e239ea 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -287,7 +287,6 @@ struct ad9523_state { static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) { struct ad9523_state *st = iio_priv(indio_dev); - struct spi_message m; int ret; /* We encode the register size 1..3 bytes into the register address. @@ -305,15 +304,11 @@ static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) }, }; - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - st->data[0].d32 = cpu_to_be32(AD9523_READ | AD9523_CNT(AD9523_TRANSF_LEN(addr)) | AD9523_ADDR(addr)); - ret = spi_sync(st->spi, &m); + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); if (ret < 0) dev_err(&indio_dev->dev, "read failed (%d)", ret); else @@ -326,7 +321,6 @@ static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val) { struct ad9523_state *st = iio_priv(indio_dev); - struct spi_message m; int ret; struct spi_transfer t[] = { { @@ -338,16 +332,12 @@ static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val) }, }; - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - st->data[0].d32 = cpu_to_be32(AD9523_WRITE | AD9523_CNT(AD9523_TRANSF_LEN(addr)) | AD9523_ADDR(addr)); st->data[1].d32 = cpu_to_be32(val); - ret = spi_sync(st->spi, &m); + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); if (ret < 0) dev_err(&indio_dev->dev, "write failed (%d)", ret); diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c index d9d43831c380..5b79953f7011 100644 --- a/drivers/iio/gyro/adxrs450.c +++ b/drivers/iio/gyro/adxrs450.c @@ -213,7 +213,6 @@ error_ret: static int adxrs450_spi_initial(struct adxrs450_state *st, u32 *val, char chk) { - struct spi_message msg; int ret; u32 tx; struct spi_transfer xfers = { @@ -228,9 +227,7 @@ static int adxrs450_spi_initial(struct adxrs450_state *st, if (chk) tx |= (ADXRS450_CHK | ADXRS450_P); st->tx = cpu_to_be32(tx); - spi_message_init(&msg); - spi_message_add_tail(&xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, &xfers, 1); if (ret) { dev_err(&st->us->dev, "Problem while reading initializing data\n"); goto error_ret; diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 0a09998276c0..fa9b24219987 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -21,7 +21,7 @@ #include <linux/delay.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#include <linux/iio/trigger_consumer.h> +#include <linux/iio/trigger.h> #include <linux/iio/buffer.h> #include <linux/iio/common/st_sensors.h> @@ -287,10 +287,15 @@ static const struct iio_info gyro_info = { .write_raw = &st_gyro_write_raw, }; +#ifdef CONFIG_IIO_TRIGGER static const struct iio_trigger_ops st_gyro_trigger_ops = { .owner = THIS_MODULE, .set_trigger_state = ST_GYRO_TRIGGER_SET_STATE, }; +#define ST_GYRO_TRIGGER_OPS (&st_gyro_trigger_ops) +#else +#define ST_GYRO_TRIGGER_OPS NULL +#endif int st_gyro_common_probe(struct iio_dev *indio_dev) { @@ -323,7 +328,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) goto st_gyro_common_probe_error; err = st_sensors_allocate_trigger(indio_dev, - &st_gyro_trigger_ops); + ST_GYRO_TRIGGER_OPS); if (err < 0) goto st_gyro_probe_trigger_error; } diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index a44b5b4a2013..8a310500573d 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -13,7 +13,6 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/iio/iio.h> -#include <linux/iio/trigger.h> #include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors_i2c.h> diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index 8b4dcc5eab0c..f3540390eb22 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -13,7 +13,6 @@ #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/iio/iio.h> -#include <linux/iio/trigger.h> #include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors_spi.h> diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 47f66ed9c4ef..4f40a10cb74f 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -36,3 +36,5 @@ config IIO_ADIS_LIB_BUFFER help A set of buffer helper functions for the Analog Devices ADIS* device family. + +source "drivers/iio/imu/inv_mpu6050/Kconfig" diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 019b717c5ff1..f2f56ceaed26 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -11,3 +11,5 @@ adis_lib-y += adis.o adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o + +obj-y += inv_mpu6050/ diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig new file mode 100644 index 000000000000..b5cfa3a354cf --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -0,0 +1,13 @@ +# +# inv-mpu6050 drivers for Invensense MPU devices and combos +# + +config INV_MPU6050_IIO + tristate "Invensense MPU6050 devices" + depends on I2C && SYSFS + select IIO_TRIGGERED_BUFFER + help + This driver supports the Invensense MPU6050 devices. + It is a gyroscope/accelerometer combo device. + This driver can be built as a module. The module will be called + inv-mpu6050. diff --git a/drivers/iio/imu/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile new file mode 100644 index 000000000000..3a677c778afb --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for Invensense MPU6050 device. +# + +obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o +inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c new file mode 100644 index 000000000000..37ca05b47e4b --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -0,0 +1,795 @@ +/* +* Copyright (C) 2012 Invensense, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/sysfs.h> +#include <linux/jiffies.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/kfifo.h> +#include <linux/spinlock.h> +#include "inv_mpu_iio.h" + +/* + * this is the gyro scale translated from dynamic range plus/minus + * {250, 500, 1000, 2000} to rad/s + */ +static const int gyro_scale_6050[] = {133090, 266181, 532362, 1064724}; + +/* + * this is the accel scale translated from dynamic range plus/minus + * {2, 4, 8, 16} to m/s^2 + */ +static const int accel_scale[] = {598, 1196, 2392, 4785}; + +static const struct inv_mpu6050_reg_map reg_set_6050 = { + .sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV, + .lpf = INV_MPU6050_REG_CONFIG, + .user_ctrl = INV_MPU6050_REG_USER_CTRL, + .fifo_en = INV_MPU6050_REG_FIFO_EN, + .gyro_config = INV_MPU6050_REG_GYRO_CONFIG, + .accl_config = INV_MPU6050_REG_ACCEL_CONFIG, + .fifo_count_h = INV_MPU6050_REG_FIFO_COUNT_H, + .fifo_r_w = INV_MPU6050_REG_FIFO_R_W, + .raw_gyro = INV_MPU6050_REG_RAW_GYRO, + .raw_accl = INV_MPU6050_REG_RAW_ACCEL, + .temperature = INV_MPU6050_REG_TEMPERATURE, + .int_enable = INV_MPU6050_REG_INT_ENABLE, + .pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1, + .pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2, +}; + +static const struct inv_mpu6050_chip_config chip_config_6050 = { + .fsr = INV_MPU6050_FSR_2000DPS, + .lpf = INV_MPU6050_FILTER_20HZ, + .fifo_rate = INV_MPU6050_INIT_FIFO_RATE, + .gyro_fifo_enable = false, + .accl_fifo_enable = false, + .accl_fs = INV_MPU6050_FS_02G, +}; + +static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = { + { + .num_reg = 117, + .name = "MPU6050", + .reg = ®_set_6050, + .config = &chip_config_6050, + }, +}; + +int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d) +{ + return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d); +} + +int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) +{ + u8 d, mgmt_1; + int result; + + /* switch clock needs to be careful. Only when gyro is on, can + clock source be switched to gyro. Otherwise, it must be set to + internal clock */ + if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) { + result = i2c_smbus_read_i2c_block_data(st->client, + st->reg->pwr_mgmt_1, 1, &mgmt_1); + if (result != 1) + return result; + + mgmt_1 &= ~INV_MPU6050_BIT_CLK_MASK; + } + + if ((INV_MPU6050_BIT_PWR_GYRO_STBY == mask) && (!en)) { + /* turning off gyro requires switch to internal clock first. + Then turn off gyro engine */ + mgmt_1 |= INV_CLK_INTERNAL; + result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, mgmt_1); + if (result) + return result; + } + + result = i2c_smbus_read_i2c_block_data(st->client, + st->reg->pwr_mgmt_2, 1, &d); + if (result != 1) + return result; + if (en) + d &= ~mask; + else + d |= mask; + result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_2, d); + if (result) + return result; + + if (en) { + /* Wait for output stablize */ + msleep(INV_MPU6050_TEMP_UP_TIME); + if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) { + /* switch internal clock to PLL */ + mgmt_1 |= INV_CLK_PLL; + result = inv_mpu6050_write_reg(st, + st->reg->pwr_mgmt_1, mgmt_1); + if (result) + return result; + } + } + + return 0; +} + +int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on) +{ + int result; + + if (power_on) + result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, 0); + else + result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_SLEEP); + if (result) + return result; + + if (power_on) + msleep(INV_MPU6050_REG_UP_TIME); + + return 0; +} + +/** + * inv_mpu6050_init_config() - Initialize hardware, disable FIFO. + * + * Initial configuration: + * FSR: ± 2000DPS + * DLPF: 20Hz + * FIFO rate: 50Hz + * Clock source: Gyro PLL + */ +static int inv_mpu6050_init_config(struct iio_dev *indio_dev) +{ + int result; + u8 d; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + result = inv_mpu6050_set_power_itg(st, true); + if (result) + return result; + d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT); + result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d); + if (result) + return result; + + d = INV_MPU6050_FILTER_20HZ; + result = inv_mpu6050_write_reg(st, st->reg->lpf, d); + if (result) + return result; + + d = INV_MPU6050_ONE_K_HZ / INV_MPU6050_INIT_FIFO_RATE - 1; + result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d); + if (result) + return result; + + d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT); + result = inv_mpu6050_write_reg(st, st->reg->accl_config, d); + if (result) + return result; + + memcpy(&st->chip_config, hw_info[st->chip_type].config, + sizeof(struct inv_mpu6050_chip_config)); + result = inv_mpu6050_set_power_itg(st, false); + + return result; +} + +static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg, + int axis, int *val) +{ + int ind, result; + __be16 d; + + ind = (axis - IIO_MOD_X) * 2; + result = i2c_smbus_read_i2c_block_data(st->client, reg + ind, 2, + (u8 *)&d); + if (result != 2) + return -EINVAL; + *val = (short)be16_to_cpup(&d); + + return IIO_VAL_INT; +} + +static int inv_mpu6050_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) { + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + { + int ret, result; + + ret = IIO_VAL_INT; + result = 0; + mutex_lock(&indio_dev->mlock); + if (!st->chip_config.enable) { + result = inv_mpu6050_set_power_itg(st, true); + if (result) + goto error_read_raw; + } + /* when enable is on, power is already on */ + switch (chan->type) { + case IIO_ANGL_VEL: + if (!st->chip_config.gyro_fifo_enable || + !st->chip_config.enable) { + result = inv_mpu6050_switch_engine(st, true, + INV_MPU6050_BIT_PWR_GYRO_STBY); + if (result) + goto error_read_raw; + } + ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro, + chan->channel2, val); + if (!st->chip_config.gyro_fifo_enable || + !st->chip_config.enable) { + result = inv_mpu6050_switch_engine(st, false, + INV_MPU6050_BIT_PWR_GYRO_STBY); + if (result) + goto error_read_raw; + } + break; + case IIO_ACCEL: + if (!st->chip_config.accl_fifo_enable || + !st->chip_config.enable) { + result = inv_mpu6050_switch_engine(st, true, + INV_MPU6050_BIT_PWR_ACCL_STBY); + if (result) + goto error_read_raw; + } + ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl, + chan->channel2, val); + if (!st->chip_config.accl_fifo_enable || + !st->chip_config.enable) { + result = inv_mpu6050_switch_engine(st, false, + INV_MPU6050_BIT_PWR_ACCL_STBY); + if (result) + goto error_read_raw; + } + break; + case IIO_TEMP: + /* wait for stablization */ + msleep(INV_MPU6050_SENSOR_UP_TIME); + inv_mpu6050_sensor_show(st, st->reg->temperature, + IIO_MOD_X, val); + break; + default: + ret = -EINVAL; + break; + } +error_read_raw: + if (!st->chip_config.enable) + result |= inv_mpu6050_set_power_itg(st, false); + mutex_unlock(&indio_dev->mlock); + if (result) + return result; + + return ret; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + *val = 0; + *val2 = gyro_scale_6050[st->chip_config.fsr]; + + return IIO_VAL_INT_PLUS_NANO; + case IIO_ACCEL: + *val = 0; + *val2 = accel_scale[st->chip_config.accl_fs]; + + return IIO_VAL_INT_PLUS_MICRO; + case IIO_TEMP: + *val = 0; + *val2 = INV_MPU6050_TEMP_SCALE; + + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + *val = INV_MPU6050_TEMP_OFFSET; + + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int inv_mpu6050_write_fsr(struct inv_mpu6050_state *st, int fsr) +{ + int result; + u8 d; + + if (fsr < 0 || fsr > INV_MPU6050_MAX_GYRO_FS_PARAM) + return -EINVAL; + if (fsr == st->chip_config.fsr) + return 0; + + d = (fsr << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT); + result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d); + if (result) + return result; + st->chip_config.fsr = fsr; + + return 0; +} + +static int inv_mpu6050_write_accel_fs(struct inv_mpu6050_state *st, int fs) +{ + int result; + u8 d; + + if (fs < 0 || fs > INV_MPU6050_MAX_ACCL_FS_PARAM) + return -EINVAL; + if (fs == st->chip_config.accl_fs) + return 0; + + d = (fs << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT); + result = inv_mpu6050_write_reg(st, st->reg->accl_config, d); + if (result) + return result; + st->chip_config.accl_fs = fs; + + return 0; +} + +static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) { + struct inv_mpu6050_state *st = iio_priv(indio_dev); + int result; + + mutex_lock(&indio_dev->mlock); + /* we should only update scale when the chip is disabled, i.e., + not running */ + if (st->chip_config.enable) { + result = -EBUSY; + goto error_write_raw; + } + result = inv_mpu6050_set_power_itg(st, true); + if (result) + goto error_write_raw; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + result = inv_mpu6050_write_fsr(st, val); + break; + case IIO_ACCEL: + result = inv_mpu6050_write_accel_fs(st, val); + break; + default: + result = -EINVAL; + break; + } + break; + default: + result = -EINVAL; + break; + } + +error_write_raw: + result |= inv_mpu6050_set_power_itg(st, false); + mutex_unlock(&indio_dev->mlock); + + return result; +} + +/** + * inv_mpu6050_set_lpf() - set low pass filer based on fifo rate. + * + * Based on the Nyquist principle, the sampling rate must + * exceed twice of the bandwidth of the signal, or there + * would be alising. This function basically search for the + * correct low pass parameters based on the fifo rate, e.g, + * sampling frequency. + */ +static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate) +{ + const int hz[] = {188, 98, 42, 20, 10, 5}; + const int d[] = {INV_MPU6050_FILTER_188HZ, INV_MPU6050_FILTER_98HZ, + INV_MPU6050_FILTER_42HZ, INV_MPU6050_FILTER_20HZ, + INV_MPU6050_FILTER_10HZ, INV_MPU6050_FILTER_5HZ}; + int i, h, result; + u8 data; + + h = (rate >> 1); + i = 0; + while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1)) + i++; + data = d[i]; + result = inv_mpu6050_write_reg(st, st->reg->lpf, data); + if (result) + return result; + st->chip_config.lpf = data; + + return 0; +} + +/** + * inv_mpu6050_fifo_rate_store() - Set fifo rate. + */ +static ssize_t inv_mpu6050_fifo_rate_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + s32 fifo_rate; + u8 d; + int result; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + if (kstrtoint(buf, 10, &fifo_rate)) + return -EINVAL; + if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE || + fifo_rate > INV_MPU6050_MAX_FIFO_RATE) + return -EINVAL; + if (fifo_rate == st->chip_config.fifo_rate) + return count; + + mutex_lock(&indio_dev->mlock); + if (st->chip_config.enable) { + result = -EBUSY; + goto fifo_rate_fail; + } + result = inv_mpu6050_set_power_itg(st, true); + if (result) + goto fifo_rate_fail; + + d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1; + result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d); + if (result) + goto fifo_rate_fail; + st->chip_config.fifo_rate = fifo_rate; + + result = inv_mpu6050_set_lpf(st, fifo_rate); + if (result) + goto fifo_rate_fail; + +fifo_rate_fail: + result |= inv_mpu6050_set_power_itg(st, false); + mutex_unlock(&indio_dev->mlock); + if (result) + return result; + + return count; +} + +/** + * inv_fifo_rate_show() - Get the current sampling rate. + */ +static ssize_t inv_fifo_rate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev)); + + return sprintf(buf, "%d\n", st->chip_config.fifo_rate); +} + +/** + * inv_attr_show() - calling this function will show current + * parameters. + */ +static ssize_t inv_attr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev)); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + s8 *m; + + switch (this_attr->address) { + /* In MPU6050, the two matrix are the same because gyro and accel + are integrated in one chip */ + case ATTR_GYRO_MATRIX: + case ATTR_ACCL_MATRIX: + m = st->plat_data.orientation; + + return sprintf(buf, "%d, %d, %d; %d, %d, %d; %d, %d, %d\n", + m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]); + default: + return -EINVAL; + } +} + +/** + * inv_mpu6050_validate_trigger() - validate_trigger callback for invensense + * MPU6050 device. + * @indio_dev: The IIO device + * @trig: The new trigger + * + * Returns: 0 if the 'trig' matches the trigger registered by the MPU6050 + * device, -EINVAL otherwise. + */ +static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + if (st->trig != trig) + return -EINVAL; + + return 0; +} + +#define INV_MPU6050_CHAN(_type, _channel2, _index) \ + { \ + .type = _type, \ + .modified = 1, \ + .channel2 = _channel2, \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT \ + | IIO_CHAN_INFO_RAW_SEPARATE_BIT, \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .shift = 0 , \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec inv_mpu_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP), + /* + * Note that temperature should only be via polled reading only, + * not the final scan elements output. + */ + { + .type = IIO_TEMP, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT + | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT + | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + .scan_index = -1, + }, + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), + + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X), + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y), + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), +}; + +/* constant IIO attribute */ +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500"); +static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show, + inv_mpu6050_fifo_rate_store); +static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL, + ATTR_GYRO_MATRIX); +static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL, + ATTR_ACCL_MATRIX); + +static struct attribute *inv_attributes[] = { + &iio_dev_attr_in_gyro_matrix.dev_attr.attr, + &iio_dev_attr_in_accel_matrix.dev_attr.attr, + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group inv_attribute_group = { + .attrs = inv_attributes +}; + +static const struct iio_info mpu_info = { + .driver_module = THIS_MODULE, + .read_raw = &inv_mpu6050_read_raw, + .write_raw = &inv_mpu6050_write_raw, + .attrs = &inv_attribute_group, + .validate_trigger = inv_mpu6050_validate_trigger, +}; + +/** + * inv_check_and_setup_chip() - check and setup chip. + */ +static int inv_check_and_setup_chip(struct inv_mpu6050_state *st, + const struct i2c_device_id *id) +{ + int result; + + st->chip_type = INV_MPU6050; + st->hw = &hw_info[st->chip_type]; + st->reg = hw_info[st->chip_type].reg; + + /* reset to make sure previous state are not there */ + result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_H_RESET); + if (result) + return result; + msleep(INV_MPU6050_POWER_UP_TIME); + /* toggle power state. After reset, the sleep bit could be on + or off depending on the OTP settings. Toggling power would + make it in a definite state as well as making the hardware + state align with the software state */ + result = inv_mpu6050_set_power_itg(st, false); + if (result) + return result; + result = inv_mpu6050_set_power_itg(st, true); + if (result) + return result; + + result = inv_mpu6050_switch_engine(st, false, + INV_MPU6050_BIT_PWR_ACCL_STBY); + if (result) + return result; + result = inv_mpu6050_switch_engine(st, false, + INV_MPU6050_BIT_PWR_GYRO_STBY); + if (result) + return result; + + return 0; +} + +/** + * inv_mpu_probe() - probe function. + * @client: i2c client. + * @id: i2c device id. + * + * Returns 0 on success, a negative error code otherwise. + */ +static int inv_mpu_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct inv_mpu6050_state *st; + struct iio_dev *indio_dev; + int result; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK | + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + result = -ENOSYS; + goto out_no_free; + } + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + result = -ENOMEM; + goto out_no_free; + } + st = iio_priv(indio_dev); + st->client = client; + st->plat_data = *(struct inv_mpu6050_platform_data + *)dev_get_platdata(&client->dev); + /* power is turned on inside check chip type*/ + result = inv_check_and_setup_chip(st, id); + if (result) + goto out_free; + + result = inv_mpu6050_init_config(indio_dev); + if (result) { + dev_err(&client->dev, + "Could not initialize device.\n"); + goto out_free; + } + + i2c_set_clientdata(client, indio_dev); + indio_dev->dev.parent = &client->dev; + indio_dev->name = id->name; + indio_dev->channels = inv_mpu_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); + + indio_dev->info = &mpu_info; + indio_dev->modes = INDIO_BUFFER_TRIGGERED; + + result = iio_triggered_buffer_setup(indio_dev, + inv_mpu6050_irq_handler, + inv_mpu6050_read_fifo, + NULL); + if (result) { + dev_err(&st->client->dev, "configure buffer fail %d\n", + result); + goto out_free; + } + result = inv_mpu6050_probe_trigger(indio_dev); + if (result) { + dev_err(&st->client->dev, "trigger probe fail %d\n", result); + goto out_unreg_ring; + } + + INIT_KFIFO(st->timestamps); + spin_lock_init(&st->time_stamp_lock); + result = iio_device_register(indio_dev); + if (result) { + dev_err(&st->client->dev, "IIO register fail %d\n", result); + goto out_remove_trigger; + } + + return 0; + +out_remove_trigger: + inv_mpu6050_remove_trigger(st); +out_unreg_ring: + iio_triggered_buffer_cleanup(indio_dev); +out_free: + iio_device_free(indio_dev); +out_no_free: + + return result; +} + +static int inv_mpu_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + inv_mpu6050_remove_trigger(st); + iio_triggered_buffer_cleanup(indio_dev); + iio_device_free(indio_dev); + + return 0; +} +#ifdef CONFIG_PM_SLEEP + +static int inv_mpu_resume(struct device *dev) +{ + return inv_mpu6050_set_power_itg( + iio_priv(i2c_get_clientdata(to_i2c_client(dev))), true); +} + +static int inv_mpu_suspend(struct device *dev) +{ + return inv_mpu6050_set_power_itg( + iio_priv(i2c_get_clientdata(to_i2c_client(dev))), false); +} +static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume); + +#define INV_MPU6050_PMOPS (&inv_mpu_pmops) +#else +#define INV_MPU6050_PMOPS NULL +#endif /* CONFIG_PM_SLEEP */ + +/* + * device id table is used to identify what device can be + * supported by this driver + */ +static const struct i2c_device_id inv_mpu_id[] = { + {"mpu6050", INV_MPU6050}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, inv_mpu_id); + +static struct i2c_driver inv_mpu_driver = { + .probe = inv_mpu_probe, + .remove = inv_mpu_remove, + .id_table = inv_mpu_id, + .driver = { + .owner = THIS_MODULE, + .name = "inv-mpu6050", + .pm = INV_MPU6050_PMOPS, + }, +}; + +module_i2c_driver(inv_mpu_driver); + +MODULE_AUTHOR("Invensense Corporation"); +MODULE_DESCRIPTION("Invensense device MPU6050 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h new file mode 100644 index 000000000000..f38395529a44 --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -0,0 +1,246 @@ +/* +* Copyright (C) 2012 Invensense, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ +#include <linux/i2c.h> +#include <linux/kfifo.h> +#include <linux/spinlock.h> +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/kfifo_buf.h> +#include <linux/iio/trigger.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/platform_data/invensense_mpu6050.h> + +/** + * struct inv_mpu6050_reg_map - Notable registers. + * @sample_rate_div: Divider applied to gyro output rate. + * @lpf: Configures internal low pass filter. + * @user_ctrl: Enables/resets the FIFO. + * @fifo_en: Determines which data will appear in FIFO. + * @gyro_config: gyro config register. + * @accl_config: accel config register + * @fifo_count_h: Upper byte of FIFO count. + * @fifo_r_w: FIFO register. + * @raw_gyro: Address of first gyro register. + * @raw_accl: Address of first accel register. + * @temperature: temperature register + * @int_enable: Interrupt enable register. + * @pwr_mgmt_1: Controls chip's power state and clock source. + * @pwr_mgmt_2: Controls power state of individual sensors. + */ +struct inv_mpu6050_reg_map { + u8 sample_rate_div; + u8 lpf; + u8 user_ctrl; + u8 fifo_en; + u8 gyro_config; + u8 accl_config; + u8 fifo_count_h; + u8 fifo_r_w; + u8 raw_gyro; + u8 raw_accl; + u8 temperature; + u8 int_enable; + u8 pwr_mgmt_1; + u8 pwr_mgmt_2; +}; + +/*device enum */ +enum inv_devices { + INV_MPU6050, + INV_NUM_PARTS +}; + +/** + * struct inv_mpu6050_chip_config - Cached chip configuration data. + * @fsr: Full scale range. + * @lpf: Digital low pass filter frequency. + * @accl_fs: accel full scale range. + * @enable: master enable state. + * @accl_fifo_enable: enable accel data output + * @gyro_fifo_enable: enable gyro data output + * @fifo_rate: FIFO update rate. + */ +struct inv_mpu6050_chip_config { + unsigned int fsr:2; + unsigned int lpf:3; + unsigned int accl_fs:2; + unsigned int enable:1; + unsigned int accl_fifo_enable:1; + unsigned int gyro_fifo_enable:1; + u16 fifo_rate; +}; + +/** + * struct inv_mpu6050_hw - Other important hardware information. + * @num_reg: Number of registers on device. + * @name: name of the chip. + * @reg: register map of the chip. + * @config: configuration of the chip. + */ +struct inv_mpu6050_hw { + u8 num_reg; + u8 *name; + const struct inv_mpu6050_reg_map *reg; + const struct inv_mpu6050_chip_config *config; +}; + +/* + * struct inv_mpu6050_state - Driver state variables. + * @TIMESTAMP_FIFO_SIZE: fifo size for timestamp. + * @trig: IIO trigger. + * @chip_config: Cached attribute information. + * @reg: Map of important registers. + * @hw: Other hardware-specific information. + * @chip_type: chip type. + * @time_stamp_lock: spin lock to time stamp. + * @client: i2c client handle. + * @plat_data: platform data. + * @timestamps: kfifo queue to store time stamp. + */ +struct inv_mpu6050_state { +#define TIMESTAMP_FIFO_SIZE 16 + struct iio_trigger *trig; + struct inv_mpu6050_chip_config chip_config; + const struct inv_mpu6050_reg_map *reg; + const struct inv_mpu6050_hw *hw; + enum inv_devices chip_type; + spinlock_t time_stamp_lock; + struct i2c_client *client; + struct inv_mpu6050_platform_data plat_data; + DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE); +}; + +/*register and associated bit definition*/ +#define INV_MPU6050_REG_SAMPLE_RATE_DIV 0x19 +#define INV_MPU6050_REG_CONFIG 0x1A +#define INV_MPU6050_REG_GYRO_CONFIG 0x1B +#define INV_MPU6050_REG_ACCEL_CONFIG 0x1C + +#define INV_MPU6050_REG_FIFO_EN 0x23 +#define INV_MPU6050_BIT_ACCEL_OUT 0x08 +#define INV_MPU6050_BITS_GYRO_OUT 0x70 + +#define INV_MPU6050_REG_INT_ENABLE 0x38 +#define INV_MPU6050_BIT_DATA_RDY_EN 0x01 +#define INV_MPU6050_BIT_DMP_INT_EN 0x02 + +#define INV_MPU6050_REG_RAW_ACCEL 0x3B +#define INV_MPU6050_REG_TEMPERATURE 0x41 +#define INV_MPU6050_REG_RAW_GYRO 0x43 + +#define INV_MPU6050_REG_USER_CTRL 0x6A +#define INV_MPU6050_BIT_FIFO_RST 0x04 +#define INV_MPU6050_BIT_DMP_RST 0x08 +#define INV_MPU6050_BIT_I2C_MST_EN 0x20 +#define INV_MPU6050_BIT_FIFO_EN 0x40 +#define INV_MPU6050_BIT_DMP_EN 0x80 + +#define INV_MPU6050_REG_PWR_MGMT_1 0x6B +#define INV_MPU6050_BIT_H_RESET 0x80 +#define INV_MPU6050_BIT_SLEEP 0x40 +#define INV_MPU6050_BIT_CLK_MASK 0x7 + +#define INV_MPU6050_REG_PWR_MGMT_2 0x6C +#define INV_MPU6050_BIT_PWR_ACCL_STBY 0x38 +#define INV_MPU6050_BIT_PWR_GYRO_STBY 0x07 + +#define INV_MPU6050_REG_FIFO_COUNT_H 0x72 +#define INV_MPU6050_REG_FIFO_R_W 0x74 + +#define INV_MPU6050_BYTES_PER_3AXIS_SENSOR 6 +#define INV_MPU6050_FIFO_COUNT_BYTE 2 +#define INV_MPU6050_FIFO_THRESHOLD 500 +#define INV_MPU6050_POWER_UP_TIME 100 +#define INV_MPU6050_TEMP_UP_TIME 100 +#define INV_MPU6050_SENSOR_UP_TIME 30 +#define INV_MPU6050_REG_UP_TIME 5 + +#define INV_MPU6050_TEMP_OFFSET 12421 +#define INV_MPU6050_TEMP_SCALE 2941 +#define INV_MPU6050_MAX_GYRO_FS_PARAM 3 +#define INV_MPU6050_MAX_ACCL_FS_PARAM 3 +#define INV_MPU6050_THREE_AXIS 3 +#define INV_MPU6050_GYRO_CONFIG_FSR_SHIFT 3 +#define INV_MPU6050_ACCL_CONFIG_FSR_SHIFT 3 + +/* 6 + 6 round up and plus 8 */ +#define INV_MPU6050_OUTPUT_DATA_SIZE 24 + +/* init parameters */ +#define INV_MPU6050_INIT_FIFO_RATE 50 +#define INV_MPU6050_TIME_STAMP_TOR 5 +#define INV_MPU6050_MAX_FIFO_RATE 1000 +#define INV_MPU6050_MIN_FIFO_RATE 4 +#define INV_MPU6050_ONE_K_HZ 1000 + +/* scan element definition */ +enum inv_mpu6050_scan { + INV_MPU6050_SCAN_ACCL_X, + INV_MPU6050_SCAN_ACCL_Y, + INV_MPU6050_SCAN_ACCL_Z, + INV_MPU6050_SCAN_GYRO_X, + INV_MPU6050_SCAN_GYRO_Y, + INV_MPU6050_SCAN_GYRO_Z, + INV_MPU6050_SCAN_TIMESTAMP, +}; + +enum inv_mpu6050_filter_e { + INV_MPU6050_FILTER_256HZ_NOLPF2 = 0, + INV_MPU6050_FILTER_188HZ, + INV_MPU6050_FILTER_98HZ, + INV_MPU6050_FILTER_42HZ, + INV_MPU6050_FILTER_20HZ, + INV_MPU6050_FILTER_10HZ, + INV_MPU6050_FILTER_5HZ, + INV_MPU6050_FILTER_2100HZ_NOLPF, + NUM_MPU6050_FILTER +}; + +/* IIO attribute address */ +enum INV_MPU6050_IIO_ATTR_ADDR { + ATTR_GYRO_MATRIX, + ATTR_ACCL_MATRIX, +}; + +enum inv_mpu6050_accl_fs_e { + INV_MPU6050_FS_02G = 0, + INV_MPU6050_FS_04G, + INV_MPU6050_FS_08G, + INV_MPU6050_FS_16G, + NUM_ACCL_FSR +}; + +enum inv_mpu6050_fsr_e { + INV_MPU6050_FSR_250DPS = 0, + INV_MPU6050_FSR_500DPS, + INV_MPU6050_FSR_1000DPS, + INV_MPU6050_FSR_2000DPS, + NUM_MPU6050_FSR +}; + +enum inv_mpu6050_clock_sel_e { + INV_CLK_INTERNAL = 0, + INV_CLK_PLL, + NUM_CLK +}; + +irqreturn_t inv_mpu6050_irq_handler(int irq, void *p); +irqreturn_t inv_mpu6050_read_fifo(int irq, void *p); +int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev); +void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st); +int inv_reset_fifo(struct iio_dev *indio_dev); +int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask); +int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val); +int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c new file mode 100644 index 000000000000..331781ffbb15 --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -0,0 +1,196 @@ +/* +* Copyright (C) 2012 Invensense, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/sysfs.h> +#include <linux/jiffies.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/kfifo.h> +#include <linux/poll.h> +#include "inv_mpu_iio.h" + +int inv_reset_fifo(struct iio_dev *indio_dev) +{ + int result; + u8 d; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + /* disable interrupt */ + result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0); + if (result) { + dev_err(&st->client->dev, "int_enable failed %d\n", result); + return result; + } + /* disable the sensor output to FIFO */ + result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0); + if (result) + goto reset_fifo_fail; + /* disable fifo reading */ + result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0); + if (result) + goto reset_fifo_fail; + + /* reset FIFO*/ + result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, + INV_MPU6050_BIT_FIFO_RST); + if (result) + goto reset_fifo_fail; + /* enable interrupt */ + if (st->chip_config.accl_fifo_enable || + st->chip_config.gyro_fifo_enable) { + result = inv_mpu6050_write_reg(st, st->reg->int_enable, + INV_MPU6050_BIT_DATA_RDY_EN); + if (result) + return result; + } + /* enable FIFO reading and I2C master interface*/ + result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, + INV_MPU6050_BIT_FIFO_EN); + if (result) + goto reset_fifo_fail; + /* enable sensor output to FIFO */ + d = 0; + if (st->chip_config.gyro_fifo_enable) + d |= INV_MPU6050_BITS_GYRO_OUT; + if (st->chip_config.accl_fifo_enable) + d |= INV_MPU6050_BIT_ACCEL_OUT; + result = inv_mpu6050_write_reg(st, st->reg->fifo_en, d); + if (result) + goto reset_fifo_fail; + + return 0; + +reset_fifo_fail: + dev_err(&st->client->dev, "reset fifo failed %d\n", result); + result = inv_mpu6050_write_reg(st, st->reg->int_enable, + INV_MPU6050_BIT_DATA_RDY_EN); + + return result; +} + +static void inv_clear_kfifo(struct inv_mpu6050_state *st) +{ + unsigned long flags; + + /* take the spin lock sem to avoid interrupt kick in */ + spin_lock_irqsave(&st->time_stamp_lock, flags); + kfifo_reset(&st->timestamps); + spin_unlock_irqrestore(&st->time_stamp_lock, flags); +} + +/** + * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt. + */ +irqreturn_t inv_mpu6050_irq_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + s64 timestamp; + + timestamp = iio_get_time_ns(); + spin_lock(&st->time_stamp_lock); + kfifo_in(&st->timestamps, ×tamp, 1); + spin_unlock(&st->time_stamp_lock); + + return IRQ_WAKE_THREAD; +} + +/** + * inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO. + */ +irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + size_t bytes_per_datum; + int result; + u8 data[INV_MPU6050_OUTPUT_DATA_SIZE]; + u16 fifo_count; + s64 timestamp; + u64 *tmp; + + mutex_lock(&indio_dev->mlock); + if (!(st->chip_config.accl_fifo_enable | + st->chip_config.gyro_fifo_enable)) + goto end_session; + bytes_per_datum = 0; + if (st->chip_config.accl_fifo_enable) + bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR; + + if (st->chip_config.gyro_fifo_enable) + bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR; + + /* + * read fifo_count register to know how many bytes inside FIFO + * right now + */ + result = i2c_smbus_read_i2c_block_data(st->client, + st->reg->fifo_count_h, + INV_MPU6050_FIFO_COUNT_BYTE, data); + if (result != INV_MPU6050_FIFO_COUNT_BYTE) + goto end_session; + fifo_count = be16_to_cpup((__be16 *)(&data[0])); + if (fifo_count < bytes_per_datum) + goto end_session; + /* fifo count can't be odd number, if it is odd, reset fifo*/ + if (fifo_count & 1) + goto flush_fifo; + if (fifo_count > INV_MPU6050_FIFO_THRESHOLD) + goto flush_fifo; + /* Timestamp mismatch. */ + if (kfifo_len(&st->timestamps) > + fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR) + goto flush_fifo; + while (fifo_count >= bytes_per_datum) { + result = i2c_smbus_read_i2c_block_data(st->client, + st->reg->fifo_r_w, + bytes_per_datum, data); + if (result != bytes_per_datum) + goto flush_fifo; + + result = kfifo_out(&st->timestamps, ×tamp, 1); + /* when there is no timestamp, put timestamp as 0 */ + if (0 == result) + timestamp = 0; + + tmp = (u64 *)data; + tmp[DIV_ROUND_UP(bytes_per_datum, 8)] = timestamp; + result = iio_push_to_buffers(indio_dev, data); + if (result) + goto flush_fifo; + fifo_count -= bytes_per_datum; + } + +end_session: + mutex_unlock(&indio_dev->mlock); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; + +flush_fifo: + /* Flush HW and SW FIFOs. */ + inv_reset_fifo(indio_dev); + inv_clear_kfifo(st); + mutex_unlock(&indio_dev->mlock); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c new file mode 100644 index 000000000000..e1d0869e0ad1 --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -0,0 +1,155 @@ +/* +* Copyright (C) 2012 Invensense, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include "inv_mpu_iio.h" + +static void inv_scan_query(struct iio_dev *indio_dev) +{ + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + st->chip_config.gyro_fifo_enable = + test_bit(INV_MPU6050_SCAN_GYRO_X, + indio_dev->active_scan_mask) || + test_bit(INV_MPU6050_SCAN_GYRO_Y, + indio_dev->active_scan_mask) || + test_bit(INV_MPU6050_SCAN_GYRO_Z, + indio_dev->active_scan_mask); + + st->chip_config.accl_fifo_enable = + test_bit(INV_MPU6050_SCAN_ACCL_X, + indio_dev->active_scan_mask) || + test_bit(INV_MPU6050_SCAN_ACCL_Y, + indio_dev->active_scan_mask) || + test_bit(INV_MPU6050_SCAN_ACCL_Z, + indio_dev->active_scan_mask); +} + +/** + * inv_mpu6050_set_enable() - enable chip functions. + * @indio_dev: Device driver instance. + * @enable: enable/disable + */ +static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) +{ + struct inv_mpu6050_state *st = iio_priv(indio_dev); + int result; + + if (enable) { + result = inv_mpu6050_set_power_itg(st, true); + if (result) + return result; + inv_scan_query(indio_dev); + if (st->chip_config.gyro_fifo_enable) { + result = inv_mpu6050_switch_engine(st, true, + INV_MPU6050_BIT_PWR_GYRO_STBY); + if (result) + return result; + } + if (st->chip_config.accl_fifo_enable) { + result = inv_mpu6050_switch_engine(st, true, + INV_MPU6050_BIT_PWR_ACCL_STBY); + if (result) + return result; + } + result = inv_reset_fifo(indio_dev); + if (result) + return result; + } else { + result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0); + if (result) + return result; + + result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0); + if (result) + return result; + + result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0); + if (result) + return result; + + result = inv_mpu6050_switch_engine(st, false, + INV_MPU6050_BIT_PWR_GYRO_STBY); + if (result) + return result; + + result = inv_mpu6050_switch_engine(st, false, + INV_MPU6050_BIT_PWR_ACCL_STBY); + if (result) + return result; + result = inv_mpu6050_set_power_itg(st, false); + if (result) + return result; + } + st->chip_config.enable = enable; + + return 0; +} + +/** + * inv_mpu_data_rdy_trigger_set_state() - set data ready interrupt state + * @trig: Trigger instance + * @state: Desired trigger state + */ +static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + return inv_mpu6050_set_enable(trig->private_data, state); +} + +static const struct iio_trigger_ops inv_mpu_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state, +}; + +int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) +{ + int ret; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + st->trig = iio_trigger_alloc("%s-dev%d", + indio_dev->name, + indio_dev->id); + if (st->trig == NULL) { + ret = -ENOMEM; + goto error_ret; + } + ret = request_irq(st->client->irq, &iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_RISING, + "inv_mpu", + st->trig); + if (ret) + goto error_free_trig; + st->trig->dev.parent = &st->client->dev; + st->trig->private_data = indio_dev; + st->trig->ops = &inv_mpu_trigger_ops; + ret = iio_trigger_register(st->trig); + if (ret) + goto error_free_irq; + indio_dev->trig = st->trig; + + return 0; + +error_free_irq: + free_irq(st->client->irq, st->trig); +error_free_trig: + iio_trigger_free(st->trig); +error_ret: + return ret; +} + +void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st) +{ + iio_trigger_unregister(st->trig); + free_irq(st->client->irq, st->trig); + iio_trigger_free(st->trig); +} diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 4fe0ead84213..4d6c7d84e155 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -160,7 +160,7 @@ void iio_trigger_notify_done(struct iio_trigger *trig) trig->use_count--; if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) if (trig->ops->try_reenable(trig)) - /* Missed and interrupt so launch new poll now */ + /* Missed an interrupt so launch new poll now */ iio_trigger_poll(trig, 0); } EXPORT_SYMBOL(iio_trigger_notify_done); @@ -193,7 +193,7 @@ static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) * This is not currently handled. Alternative of not enabling trigger unless * the relevant function is in there may be the best option. */ -/* Worth protecting against double additions?*/ +/* Worth protecting against double additions? */ static int iio_trigger_attach_poll_func(struct iio_trigger *trig, struct iio_poll_func *pf) { @@ -201,7 +201,7 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig, bool notinuse = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); - /* Prevent the module being removed whilst attached to a trigger */ + /* Prevent the module from being removed whilst attached to a trigger */ __module_get(pf->indio_dev->info->driver_module); pf->irq = iio_trigger_get_irq(trig); ret = request_threaded_irq(pf->irq, pf->h, pf->thread, @@ -288,7 +288,7 @@ void iio_dealloc_pollfunc(struct iio_poll_func *pf) EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc); /** - * iio_trigger_read_current() - trigger consumer sysfs query which trigger + * iio_trigger_read_current() - trigger consumer sysfs query current trigger * * For trigger consumers the current_trigger interface allows the trigger * used by the device to be queried. @@ -305,7 +305,7 @@ static ssize_t iio_trigger_read_current(struct device *dev, } /** - * iio_trigger_write_current() trigger consumer sysfs set current trigger + * iio_trigger_write_current() - trigger consumer sysfs set current trigger * * For trigger consumers the current_trigger interface allows the trigger * used for this device to be specified at run time based on the triggers @@ -476,7 +476,7 @@ void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) { - /* Clean up and associated but not attached triggers references */ + /* Clean up an associated but not attached trigger reference */ if (indio_dev->trig) iio_trigger_put(indio_dev->trig); } diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index c42aba6817e8..b289915b8469 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -93,7 +93,8 @@ static const struct iio_chan_spec } -struct iio_channel *iio_channel_get(const char *name, const char *channel_name) +static struct iio_channel *iio_channel_get_sys(const char *name, + const char *channel_name) { struct iio_map_internal *c_i = NULL, *c = NULL; struct iio_channel *channel; @@ -144,6 +145,14 @@ error_no_mem: iio_device_put(c->indio_dev); return ERR_PTR(err); } + +struct iio_channel *iio_channel_get(struct device *dev, + const char *channel_name) +{ + const char *name = dev ? dev_name(dev) : NULL; + + return iio_channel_get_sys(name, channel_name); +} EXPORT_SYMBOL_GPL(iio_channel_get); void iio_channel_release(struct iio_channel *channel) diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index a69fbe19fc8e..16f0d6df239f 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -21,7 +21,6 @@ #include <linux/delay.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#include <linux/iio/trigger_consumer.h> #include <linux/iio/buffer.h> #include <linux/iio/common/st_sensors.h> diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index 710b256a5a0e..e6adc4a86425 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -13,7 +13,6 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/iio/iio.h> -#include <linux/iio/trigger.h> #include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors_i2c.h> diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index 94547e7d6580..51adb797cb7d 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -13,7 +13,6 @@ #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/iio/iio.h> -#include <linux/iio/trigger.h> #include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors_spi.h> diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c index 32ce17e235c0..42733c4dcb0e 100644 --- a/drivers/power/generic-adc-battery.c +++ b/drivers/power/generic-adc-battery.c @@ -287,8 +287,8 @@ static int gab_probe(struct platform_device *pdev) * based on the channel supported by consumer device. */ for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) { - adc_bat->channel[chan] = iio_channel_get(dev_name(&pdev->dev), - gab_chan_name[chan]); + adc_bat->channel[chan] = iio_channel_get(&pdev->dev, + gab_chan_name[chan]); if (IS_ERR(adc_bat->channel[chan])) { ret = PTR_ERR(adc_bat->channel[chan]); } else { diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c index 22b6407c9ca9..27889088e78e 100644 --- a/drivers/power/lp8788-charger.c +++ b/drivers/power/lp8788-charger.c @@ -580,7 +580,7 @@ static void lp8788_irq_unregister(struct platform_device *pdev, } } -static void lp8788_setup_adc_channel(const char *consumer_name, +static void lp8788_setup_adc_channel(struct device *dev, struct lp8788_charger *pchg) { struct lp8788_charger_platform_data *pdata = pchg->pdata; @@ -590,11 +590,11 @@ static void lp8788_setup_adc_channel(const char *consumer_name, return; /* ADC channel for battery voltage */ - chan = iio_channel_get(consumer_name, pdata->adc_vbatt); + chan = iio_channel_get(dev, pdata->adc_vbatt); pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan; /* ADC channel for battery temperature */ - chan = iio_channel_get(consumer_name, pdata->adc_batt_temp); + chan = iio_channel_get(dev, pdata->adc_batt_temp); pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan; } @@ -704,7 +704,7 @@ static int lp8788_charger_probe(struct platform_device *pdev) if (ret) return ret; - lp8788_setup_adc_channel(pdev->name, pchg); + lp8788_setup_adc_channel(&pdev->dev, pchg); ret = lp8788_psy_register(pdev, pchg); if (ret) diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 37ed1b8ebb6f..0e019306439c 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -53,7 +53,6 @@ int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev, u8 reg_address, u8 *val) { struct lis3l02dq_state *st = iio_priv(indio_dev); - struct spi_message msg; int ret; struct spi_transfer xfer = { .tx_buf = st->tx, @@ -66,9 +65,7 @@ int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev, st->tx[0] = LIS3L02DQ_READ_REG(reg_address); st->tx[1] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, &xfer, 1); *val = st->rx[1]; mutex_unlock(&st->buf_lock); @@ -109,7 +106,6 @@ static int lis3l02dq_spi_write_reg_s16(struct iio_dev *indio_dev, s16 value) { int ret; - struct spi_message msg; struct lis3l02dq_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { { .tx_buf = st->tx, @@ -129,10 +125,7 @@ static int lis3l02dq_spi_write_reg_s16(struct iio_dev *indio_dev, st->tx[2] = LIS3L02DQ_WRITE_REG(lower_reg_address + 1); st->tx[3] = (value >> 8) & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); mutex_unlock(&st->buf_lock); return ret; @@ -143,8 +136,6 @@ static int lis3l02dq_read_reg_s16(struct iio_dev *indio_dev, int *val) { struct lis3l02dq_state *st = iio_priv(indio_dev); - - struct spi_message msg; int ret; s16 tempval; struct spi_transfer xfers[] = { { @@ -167,10 +158,7 @@ static int lis3l02dq_read_reg_s16(struct iio_dev *indio_dev, st->tx[2] = LIS3L02DQ_READ_REG(lower_reg_address + 1); st->tx[3] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 16 bit register"); goto error_ret; diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 414d3cad55a7..14683f583ccf 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -90,7 +90,6 @@ int sca3000_read_data_short(struct sca3000_state *st, uint8_t reg_address_high, int len) { - struct spi_message msg; struct spi_transfer xfer[2] = { { .len = 1, @@ -101,11 +100,8 @@ int sca3000_read_data_short(struct sca3000_state *st, } }; st->tx[0] = SCA3000_READ_REG(reg_address_high); - spi_message_init(&msg); - spi_message_add_tail(&xfer[0], &msg); - spi_message_add_tail(&xfer[1], &msg); - return spi_sync(st->us, &msg); + return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); } /** @@ -133,7 +129,6 @@ static int sca3000_reg_lock_on(struct sca3000_state *st) **/ static int __sca3000_unlock_reg_lock(struct sca3000_state *st) { - struct spi_message msg; struct spi_transfer xfer[3] = { { .len = 2, @@ -154,12 +149,8 @@ static int __sca3000_unlock_reg_lock(struct sca3000_state *st) st->tx[3] = 0x50; st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_ADDR_UNLOCK); st->tx[5] = 0xA0; - spi_message_init(&msg); - spi_message_add_tail(&xfer[0], &msg); - spi_message_add_tail(&xfer[1], &msg); - spi_message_add_tail(&xfer[2], &msg); - return spi_sync(st->us, &msg); + return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); } /** diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index cbec2f1665e5..3e5e860aa38e 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -39,7 +39,6 @@ static int sca3000_read_data(struct sca3000_state *st, int len) { int ret; - struct spi_message msg; struct spi_transfer xfer[2] = { { .len = 1, @@ -55,10 +54,7 @@ static int sca3000_read_data(struct sca3000_state *st, } xfer[1].rx_buf = *rx_p; st->tx[0] = SCA3000_READ_REG(reg_address_high); - spi_message_init(&msg); - spi_message_add_tail(&xfer[0], &msg); - spi_message_add_tail(&xfer[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); if (ret) { dev_err(get_device(&st->us->dev), "problem reading register"); goto error_free_rx; diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index fa81a491e790..1f190c1b12a6 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -199,12 +199,8 @@ static int __ad7280_read32(struct spi_device *spi, unsigned *val) .rx_buf = &rx_buf, .len = 4, }; - struct spi_message m; - spi_message_init(&m); - spi_message_add_tail(&t, &m); - - ret = spi_sync(spi, &m); + ret = spi_sync_transfer(spi, &t, 1); if (ret) return ret; diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index b1b8c42a1c2a..f5fb0df40c8e 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -114,7 +114,7 @@ struct mxs_lradc_of_config { const char * const *irq_name; }; -static const struct mxs_lradc_of_config const mxs_lradc_of_config[] = { +static const struct mxs_lradc_of_config mxs_lradc_of_config[] = { [IMX23_LRADC] = { .irq_count = ARRAY_SIZE(mx23_lradc_irq_names), .irq_name = mx23_lradc_irq_names, diff --git a/drivers/staging/iio/frequency/ad5930.c b/drivers/staging/iio/frequency/ad5930.c index 23777be38b18..69e90e9e60ea 100644 --- a/drivers/staging/iio/frequency/ad5930.c +++ b/drivers/staging/iio/frequency/ad5930.c @@ -44,7 +44,6 @@ static ssize_t ad5930_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad5903_config *config = (struct ad5903_config *)buf; @@ -64,9 +63,7 @@ static ssize_t ad5930_set_parameter(struct device *dev, xfer.tx_buf = config; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: diff --git a/drivers/staging/iio/frequency/ad9850.c b/drivers/staging/iio/frequency/ad9850.c index 104f7a4905a3..01a8a93031f5 100644 --- a/drivers/staging/iio/frequency/ad9850.c +++ b/drivers/staging/iio/frequency/ad9850.c @@ -39,7 +39,6 @@ static ssize_t ad9850_set_parameter(struct device *dev, const char *buf, size_t len) { - struct spi_message msg; struct spi_transfer xfer; int ret; struct ad9850_config *config = (struct ad9850_config *)buf; @@ -50,9 +49,7 @@ static ssize_t ad9850_set_parameter(struct device *dev, xfer.tx_buf = config; mutex_lock(&st->lock); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; error_ret: diff --git a/drivers/staging/iio/frequency/ad9852.c b/drivers/staging/iio/frequency/ad9852.c index 17ac825b3d26..1344031232bc 100644 --- a/drivers/staging/iio/frequency/ad9852.c +++ b/drivers/staging/iio/frequency/ad9852.c @@ -183,7 +183,6 @@ static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9852_set_parameter, 0); static void ad9852_init(struct ad9852_state *st) { - struct spi_message msg; struct spi_transfer xfer; int ret; u8 config[5]; @@ -199,9 +198,7 @@ static void ad9852_init(struct ad9852_state *st) xfer.len = 5; xfer.tx_buf = &config; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret) goto error_ret; diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 51c3bdece785..e5943e2287cf 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -103,7 +103,6 @@ static int ade7753_spi_read_reg_24(struct device *dev, u8 reg_address, u32 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); int ret; @@ -122,10 +121,7 @@ static int ade7753_spi_read_reg_24(struct device *dev, mutex_lock(&st->buf_lock); st->tx[0] = ADE7753_READ_REG(reg_address); - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", reg_address); diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index b50c89e93993..7b6503bf9a74 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -103,7 +103,6 @@ static int ade7754_spi_read_reg_24(struct device *dev, u8 reg_address, u32 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); int ret; @@ -122,9 +121,7 @@ static int ade7754_spi_read_reg_24(struct device *dev, st->tx[2] = 0; st->tx[3] = 0; - spi_message_init(&msg); - spi_message_add_tail(xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", reg_address); diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 3454e5154ed2..53c68dcc4544 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -47,7 +47,6 @@ static int ade7758_spi_write_reg_16(struct device *dev, u16 value) { int ret; - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { @@ -63,9 +62,7 @@ static int ade7758_spi_write_reg_16(struct device *dev, st->tx[1] = (value >> 8) & 0xFF; st->tx[2] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); mutex_unlock(&st->buf_lock); return ret; @@ -76,7 +73,6 @@ static int ade7758_spi_write_reg_24(struct device *dev, u32 value) { int ret; - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); struct spi_transfer xfers[] = { @@ -93,9 +89,7 @@ static int ade7758_spi_write_reg_24(struct device *dev, st->tx[2] = (value >> 8) & 0xFF; st->tx[3] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); mutex_unlock(&st->buf_lock); return ret; @@ -105,7 +99,6 @@ int ade7758_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); int ret; @@ -128,10 +121,7 @@ int ade7758_spi_read_reg_8(struct device *dev, st->tx[0] = ADE7758_READ_REG(reg_address); st->tx[1] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", reg_address); @@ -148,7 +138,6 @@ static int ade7758_spi_read_reg_16(struct device *dev, u8 reg_address, u16 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); int ret; @@ -173,10 +162,7 @@ static int ade7758_spi_read_reg_16(struct device *dev, st->tx[1] = 0; st->tx[2] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -194,7 +180,6 @@ static int ade7758_spi_read_reg_24(struct device *dev, u8 reg_address, u32 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7758_state *st = iio_priv(indio_dev); int ret; @@ -219,10 +204,7 @@ static int ade7758_spi_read_reg_24(struct device *dev, st->tx[2] = 0; st->tx[3] = 0; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", reg_address); diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index 10b911bd3853..17dc373e1082 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -103,7 +103,6 @@ static int ade7759_spi_read_reg_40(struct device *dev, u8 reg_address, u64 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7759_state *st = iio_priv(indio_dev); int ret; @@ -120,9 +119,7 @@ static int ade7759_spi_read_reg_40(struct device *dev, st->tx[0] = ADE7759_READ_REG(reg_address); memset(&st->tx[1], 0 , 5); - spi_message_init(&msg); - spi_message_add_tail(xfers, &msg); - ret = spi_sync(st->us, &msg); + ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 40 bit register 0x%02X", reg_address); diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c index f0984fa1cbb9..a802cf2491d6 100644 --- a/drivers/staging/iio/meter/ade7854-spi.c +++ b/drivers/staging/iio/meter/ade7854-spi.c @@ -20,7 +20,6 @@ static int ade7854_spi_write_reg_8(struct device *dev, u8 value) { int ret; - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct spi_transfer xfer = { @@ -35,9 +34,7 @@ static int ade7854_spi_write_reg_8(struct device *dev, st->tx[2] = reg_address & 0xFF; st->tx[3] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, &xfer, 1); mutex_unlock(&st->buf_lock); return ret; @@ -48,7 +45,6 @@ static int ade7854_spi_write_reg_16(struct device *dev, u16 value) { int ret; - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct spi_transfer xfer = { @@ -64,9 +60,7 @@ static int ade7854_spi_write_reg_16(struct device *dev, st->tx[3] = (value >> 8) & 0xFF; st->tx[4] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, &xfer, 1); mutex_unlock(&st->buf_lock); return ret; @@ -77,7 +71,6 @@ static int ade7854_spi_write_reg_24(struct device *dev, u32 value) { int ret; - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct spi_transfer xfer = { @@ -94,9 +87,7 @@ static int ade7854_spi_write_reg_24(struct device *dev, st->tx[4] = (value >> 8) & 0xFF; st->tx[5] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, &xfer, 1); mutex_unlock(&st->buf_lock); return ret; @@ -107,7 +98,6 @@ static int ade7854_spi_write_reg_32(struct device *dev, u32 value) { int ret; - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct spi_transfer xfer = { @@ -125,9 +115,7 @@ static int ade7854_spi_write_reg_32(struct device *dev, st->tx[5] = (value >> 8) & 0xFF; st->tx[6] = value & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, &xfer, 1); mutex_unlock(&st->buf_lock); return ret; @@ -137,7 +125,6 @@ static int ade7854_spi_read_reg_8(struct device *dev, u16 reg_address, u8 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; @@ -159,10 +146,7 @@ static int ade7854_spi_read_reg_8(struct device *dev, st->tx[1] = (reg_address >> 8) & 0xFF; st->tx[2] = reg_address & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->spi->dev, "problem when reading 8 bit register 0x%02X", reg_address); @@ -179,7 +163,6 @@ static int ade7854_spi_read_reg_16(struct device *dev, u16 reg_address, u16 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; @@ -200,10 +183,7 @@ static int ade7854_spi_read_reg_16(struct device *dev, st->tx[1] = (reg_address >> 8) & 0xFF; st->tx[2] = reg_address & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->spi->dev, "problem when reading 16 bit register 0x%02X", reg_address); @@ -220,7 +200,6 @@ static int ade7854_spi_read_reg_24(struct device *dev, u16 reg_address, u32 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; @@ -242,10 +221,7 @@ static int ade7854_spi_read_reg_24(struct device *dev, st->tx[1] = (reg_address >> 8) & 0xFF; st->tx[2] = reg_address & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->spi->dev, "problem when reading 24 bit register 0x%02X", reg_address); @@ -262,7 +238,6 @@ static int ade7854_spi_read_reg_32(struct device *dev, u16 reg_address, u32 *val) { - struct spi_message msg; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); int ret; @@ -284,10 +259,7 @@ static int ade7854_spi_read_reg_32(struct device *dev, st->tx[1] = (reg_address >> 8) & 0xFF; st->tx[2] = reg_address & 0xFF; - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->spi, &msg); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->spi->dev, "problem when reading 32 bit register 0x%02X", reg_address); diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index ed07a348eb55..53110b6a3c74 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -130,15 +130,12 @@ static int ad2s1210_config_read(struct ad2s1210_state *st, .rx_buf = st->rx, .tx_buf = st->tx, }; - struct spi_message msg; int ret = 0; ad2s1210_set_mode(MOD_CONFIG, st); - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); st->tx[0] = address | AD2S1210_MSB_IS_HIGH; st->tx[1] = AD2S1210_REG_FAULT; - ret = spi_sync(st->sdev, &msg); + ret = spi_sync_transfer(st->sdev, &xfer, 1); if (ret < 0) return ret; st->old_data = true; |