diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-27 14:02:54 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-27 14:02:54 -0700 |
commit | 9908b4f32f91aafa86239dd092e9e5540e8615e0 (patch) | |
tree | e2dbc92c1f75633e5cfe4a68845be8f56572fef4 | |
parent | 97b0b6ca4c0f0f964d3c6918301ca45353ef8bc5 (diff) | |
parent | e0203255415844d73b5f4bec9bc72903c8e49d8d (diff) |
Merge tag 'iio-for-3.13e' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
Fifth round of IIO new drivers, cleanups and functionality for the 3.13 cycle.
New Driver
* Freescale mag3110 magnetometer driver.
New functionality
* Add LPS001WP support to the ST pressure driver.
* Allow the max1363 driver to use only smbus functions for 8 bit devices. This
allows the driver to be used when more extensive i2c support is not
available.
Cleanups
* Fix incorrect description of unit conversions in ak8975.
* Switch to pr_err in industrialio-core.c instead of direct printk calls.
* Some simple redundant error handling removal patches.
* Trivial warning suppression by adding brackets to a sizeof call.
* Drop redundant of_match_ptr casts in drivers that are dependent on
OF supporting being present. The only purpose of the of_match_ptr
wrapper was to make stubbing out of the relevant structures trivial.
Fixes
* Make MXS_LRADC depend on INPUT to avoid compile failures. This fixes an
issue introduced in the previous pull in this cycle.
-rw-r--r-- | drivers/iio/accel/kxsd9.c | 7 | ||||
-rw-r--r-- | drivers/iio/adc/max1363.c | 76 | ||||
-rw-r--r-- | drivers/iio/adc/nau7802.c | 2 | ||||
-rw-r--r-- | drivers/iio/adc/ti_am335x_adc.c | 2 | ||||
-rw-r--r-- | drivers/iio/adc/twl6030-gpadc.c | 6 | ||||
-rw-r--r-- | drivers/iio/dac/ad5421.c | 8 | ||||
-rw-r--r-- | drivers/iio/dac/ad5755.c | 8 | ||||
-rw-r--r-- | drivers/iio/dac/max517.c | 9 | ||||
-rw-r--r-- | drivers/iio/dac/mcp4725.c | 8 | ||||
-rw-r--r-- | drivers/iio/industrialio-core.c | 13 | ||||
-rw-r--r-- | drivers/iio/light/vcnl4000.c | 6 | ||||
-rw-r--r-- | drivers/iio/magnetometer/Kconfig | 10 | ||||
-rw-r--r-- | drivers/iio/magnetometer/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/magnetometer/ak8975.c | 2 | ||||
-rw-r--r-- | drivers/iio/magnetometer/mag3110.c | 401 | ||||
-rw-r--r-- | drivers/iio/pressure/Kconfig | 2 | ||||
-rw-r--r-- | drivers/iio/pressure/st_pressure_spi.c | 1 | ||||
-rw-r--r-- | drivers/staging/iio/adc/Kconfig | 1 |
18 files changed, 489 insertions, 74 deletions
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 709c13259f14..d72118d1189c 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -222,7 +222,6 @@ static int kxsd9_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct kxsd9_state *st; - int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) @@ -244,11 +243,7 @@ static int kxsd9_probe(struct spi_device *spi) spi_setup(spi); kxsd9_power_up(st); - ret = iio_device_register(indio_dev); - if (ret) - return ret; - - return 0; + return iio_device_register(indio_dev); } static int kxsd9_remove(struct spi_device *spi) diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index cc07b3765fe0..6118dced02b6 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -165,6 +165,8 @@ struct max1363_chip_info { * @thresh_low: low threshold values * @vref: Reference voltage regulator * @vref_uv: Actual (external or internal) reference voltage + * @send: function used to send data to the chip + * @recv: function used to receive data from the chip */ struct max1363_state { struct i2c_client *client; @@ -186,6 +188,10 @@ struct max1363_state { s16 thresh_low[8]; struct regulator *vref; u32 vref_uv; + int (*send)(const struct i2c_client *client, + const char *buf, int count); + int (*recv)(const struct i2c_client *client, + char *buf, int count); }; #define MAX1363_MODE_SINGLE(_num, _mask) { \ @@ -311,13 +317,37 @@ static const struct max1363_mode return NULL; } -static int max1363_write_basic_config(struct i2c_client *client, - unsigned char d1, - unsigned char d2) +static int max1363_smbus_send(const struct i2c_client *client, const char *buf, + int count) { - u8 tx_buf[2] = {d1, d2}; + int i, err; - return i2c_master_send(client, tx_buf, 2); + for (i = err = 0; err == 0 && i < count; ++i) + err = i2c_smbus_write_byte(client, buf[i]); + + return err ? err : count; +} + +static int max1363_smbus_recv(const struct i2c_client *client, char *buf, + int count) +{ + int i, ret; + + for (i = 0; i < count; ++i) { + ret = i2c_smbus_read_byte(client); + if (ret < 0) + return ret; + buf[i] = ret; + } + + return count; +} + +static int max1363_write_basic_config(struct max1363_state *st) +{ + u8 tx_buf[2] = { st->setupbyte, st->configbyte }; + + return st->send(st->client, tx_buf, 2); } static int max1363_set_scan_mode(struct max1363_state *st) @@ -327,9 +357,7 @@ static int max1363_set_scan_mode(struct max1363_state *st) | MAX1363_SE_DE_MASK); st->configbyte |= st->current_mode->conf; - return max1363_write_basic_config(st->client, - st->setupbyte, - st->configbyte); + return max1363_write_basic_config(st); } static int max1363_read_single_chan(struct iio_dev *indio_dev, @@ -366,7 +394,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev, } if (st->chip_info->bits != 8) { /* Get reading */ - data = i2c_master_recv(client, rxbuf, 2); + data = st->recv(client, rxbuf, 2); if (data < 0) { ret = data; goto error_ret; @@ -375,7 +403,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev, ((1 << st->chip_info->bits) - 1); } else { /* Get reading */ - data = i2c_master_recv(client, rxbuf, 1); + data = st->recv(client, rxbuf, 1); if (data < 0) { ret = data; goto error_ret; @@ -772,11 +800,11 @@ static irqreturn_t max1363_event_handler(int irq, void *private) u8 tx[2] = { st->setupbyte, MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 }; - i2c_master_recv(st->client, &rx, 1); + st->recv(st->client, &rx, 1); mask = rx; for_each_set_bit(loc, &mask, 8) iio_push_event(indio_dev, max1363_event_codes[loc], timestamp); - i2c_master_send(st->client, tx, 2); + st->send(st->client, tx, 2); return IRQ_HANDLED; } @@ -812,9 +840,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP; st->configbyte &= ~MAX1363_SCAN_MASK; st->monitor_on = false; - return max1363_write_basic_config(st->client, - st->setupbyte, - st->configbyte); + return max1363_write_basic_config(st); } /* Ensure we are in the relevant mode */ @@ -876,7 +902,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) } - ret = i2c_master_send(st->client, tx_buf, len); + ret = st->send(st->client, tx_buf, len); if (ret < 0) goto error_ret; if (ret != len) { @@ -893,7 +919,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) */ tx_buf[0] = st->setupbyte; tx_buf[1] = MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0; - ret = i2c_master_send(st->client, tx_buf, 2); + ret = st->send(st->client, tx_buf, 2); if (ret < 0) goto error_ret; if (ret != 2) { @@ -1481,9 +1507,9 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) if (rxbuf == NULL) goto done; if (st->chip_info->bits != 8) - b_sent = i2c_master_recv(st->client, rxbuf, numvals*2); + b_sent = st->recv(st->client, rxbuf, numvals * 2); else - b_sent = i2c_master_recv(st->client, rxbuf, numvals); + b_sent = st->recv(st->client, rxbuf, numvals); if (b_sent < 0) goto done_free; @@ -1550,6 +1576,18 @@ static int max1363_probe(struct i2c_client *client, st->vref_uv = vref_uv; } + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + st->send = i2c_master_send; + st->recv = i2c_master_recv; + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE) + && st->chip_info->bits == 8) { + st->send = max1363_smbus_send; + st->recv = max1363_smbus_recv; + } else { + ret = -EOPNOTSUPP; + goto error_disable_reg; + } + ret = max1363_alloc_scan_masks(indio_dev); if (ret) goto error_disable_reg; diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index adff9cbbcbc4..54c5babe6746 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c @@ -570,7 +570,7 @@ static struct i2c_driver nau7802_driver = { .id_table = nau7802_i2c_id, .driver = { .name = "nau7802", - .of_match_table = of_match_ptr(nau7802_dt_ids), + .of_match_table = nau7802_dt_ids, }, }; diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index ef54d8a588d2..728411ec7642 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -515,7 +515,7 @@ static struct platform_driver tiadc_driver = { .name = "TI-am335x-adc", .owner = THIS_MODULE, .pm = TIADC_PM_OPS, - .of_match_table = of_match_ptr(ti_adc_dt_ids), + .of_match_table = ti_adc_dt_ids, }, .probe = tiadc_probe, .remove = tiadc_remove, diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index 0ea96c058c08..53e1c645cee7 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -887,7 +887,7 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) int irq; int ret; - match = of_match_device(of_match_ptr(of_twl6030_match_tbl), dev); + match = of_match_device(of_twl6030_match_tbl, dev); if (!match) return -EINVAL; @@ -948,9 +948,7 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) indio_dev->channels = pdata->iio_channels; indio_dev->num_channels = pdata->nchannels; - ret = iio_device_register(indio_dev); - - return ret; + return iio_device_register(indio_dev); } static int twl6030_gpadc_remove(struct platform_device *pdev) diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index c44afeb06f56..3eeaa82075f7 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -514,13 +514,7 @@ static int ad5421_probe(struct spi_device *spi) return ret; } - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); - return ret; - } - - return 0; + return iio_device_register(indio_dev); } static int ad5421_remove(struct spi_device *spi) diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index bd31dbc340c1..9a78d5abb2f6 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -589,13 +589,7 @@ static int ad5755_probe(struct spi_device *spi) if (ret) return ret; - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); - return ret; - } - - return 0; + return iio_device_register(indio_dev); } static int ad5755_remove(struct spi_device *spi) diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c index d26be14fff64..6e1903537950 100644 --- a/drivers/iio/dac/max517.c +++ b/drivers/iio/dac/max517.c @@ -160,7 +160,6 @@ static int max517_probe(struct i2c_client *client, struct max517_data *data; struct iio_dev *indio_dev; struct max517_platform_data *platform_data = client->dev.platform_data; - int err; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) @@ -192,13 +191,7 @@ static int max517_probe(struct i2c_client *client, data->vref_mv[1] = platform_data->vref_mv[1]; } - err = iio_device_register(indio_dev); - if (err) - return err; - - dev_info(&client->dev, "DAC registered\n"); - - return 0; + return iio_device_register(indio_dev); } static int max517_remove(struct i2c_client *client) diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index d982752dd9c4..9f57ae84ab89 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -320,13 +320,7 @@ static int mcp4725_probe(struct i2c_client *client, data->powerdown_mode = pd ? pd-1 : 2; /* 500kohm_to_gnd */ data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); - err = iio_device_register(indio_dev); - if (err) - return err; - - dev_info(&client->dev, "MCP4725 DAC registered\n"); - - return 0; + return iio_device_register(indio_dev); } static int mcp4725_remove(struct i2c_client *client) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index f7211576abe5..18f72e3d0ed6 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -9,6 +9,8 @@ * Based on elements of hwmon and input subsystems. */ +#define pr_fmt(fmt) "iio-core: " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/idr.h> @@ -132,16 +134,13 @@ static int __init iio_init(void) /* Register sysfs bus */ ret = bus_register(&iio_bus_type); if (ret < 0) { - printk(KERN_ERR - "%s could not register bus type\n", - __FILE__); + pr_err("could not register bus type\n"); goto error_nothing; } ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); if (ret < 0) { - printk(KERN_ERR "%s: failed to allocate char dev region\n", - __FILE__); + pr_err("failed to allocate char dev region\n"); goto error_unregister_bus_type; } @@ -686,7 +685,7 @@ int __iio_add_chan_devattr(const char *postfix, int ret; struct iio_dev_attr *iio_attr, *t; - iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); + iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL); if (iio_attr == NULL) { ret = -ENOMEM; goto error_ret; @@ -951,7 +950,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv) dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); if (dev->id < 0) { /* cannot use a dev_err as the name isn't available */ - printk(KERN_ERR "Failed to get id\n"); + pr_err("failed to get device id\n"); kfree(dev); return NULL; } diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 2bb304215b1d..ecb3341ef9c0 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -179,11 +179,7 @@ static int vcnl4000_probe(struct i2c_client *client, indio_dev->name = VCNL4000_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_device_register(indio_dev); - if (ret < 0) - return ret; - - return 0; + return iio_device_register(indio_dev); } static int vcnl4000_remove(struct i2c_client *client) diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index 4fa923f37b97..0cf09637b35b 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -16,6 +16,16 @@ config AK8975 To compile this driver as a module, choose M here: the module will be called ak8975. +config MAG3110 + tristate "Freescale MAG3110 3-Axis Magnetometer" + depends on I2C + help + Say yes here to build support for the Freescale MAG3110 3-Axis + magnetometer. + + To compile this driver as a module, choose M here: the module + will be called mag3110. + config HID_SENSOR_MAGNETOMETER_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index f91b1b68d392..0f5d3c985799 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -4,6 +4,7 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AK8975) += ak8975.o +obj-$(CONFIG_MAG3110) += mag3110.o obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 7105f22d6cd7..ff284e5afd95 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -263,7 +263,7 @@ static int ak8975_setup(struct i2c_client *client) * * HuT = H * 1229/4096, or roughly, 3/10. * - * Since 1uT = 100 gauss, our final scale factor becomes: + * Since 1uT = 0.01 gauss, our final scale factor becomes: * * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100 * Hadj = H * ((ASA + 128) * 30 / 256 diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c new file mode 100644 index 000000000000..783c5b417356 --- /dev/null +++ b/drivers/iio/magnetometer/mag3110.c @@ -0,0 +1,401 @@ +/* + * mag3110.c - Support for Freescale MAG3110 magnetometer sensor + * + * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net> + * + * 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. + * + * (7-bit I2C slave address 0x0e) + * + * TODO: irq, user offset, oversampling, continuous mode + */ + +#include <linux/module.h> +#include <linux/i2c.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/triggered_buffer.h> +#include <linux/delay.h> + +#define MAG3110_STATUS 0x00 +#define MAG3110_OUT_X 0x01 /* MSB first */ +#define MAG3110_OUT_Y 0x03 +#define MAG3110_OUT_Z 0x05 +#define MAG3110_WHO_AM_I 0x07 +#define MAG3110_OFF_X 0x09 /* MSB first */ +#define MAG3110_OFF_Y 0x0b +#define MAG3110_OFF_Z 0x0d +#define MAG3110_DIE_TEMP 0x0f +#define MAG3110_CTRL_REG1 0x10 +#define MAG3110_CTRL_REG2 0x11 + +#define MAG3110_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) + +#define MAG3110_CTRL_DR_MASK (BIT(7) | BIT(6) | BIT(5)) +#define MAG3110_CTRL_DR_SHIFT 5 +#define MAG3110_CTRL_DR_DEFAULT 0 + +#define MAG3110_CTRL_TM BIT(1) /* trigger single measurement */ +#define MAG3110_CTRL_AC BIT(0) /* continuous measurements */ + +#define MAG3110_CTRL_AUTO_MRST_EN BIT(7) /* magnetic auto-reset */ +#define MAG3110_CTRL_RAW BIT(5) /* measurements not user-offset corrected */ + +#define MAG3110_DEVICE_ID 0xc4 + +/* Each client has this additional data */ +struct mag3110_data { + struct i2c_client *client; + struct mutex lock; + u8 ctrl_reg1; +}; + +static int mag3110_request(struct mag3110_data *data) +{ + int ret, tries = 150; + + /* trigger measurement */ + ret = i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, + data->ctrl_reg1 | MAG3110_CTRL_TM); + if (ret < 0) + return ret; + + while (tries-- > 0) { + ret = i2c_smbus_read_byte_data(data->client, MAG3110_STATUS); + if (ret < 0) + return ret; + /* wait for data ready */ + if ((ret & MAG3110_STATUS_DRDY) == MAG3110_STATUS_DRDY) + break; + msleep(20); + } + + if (tries < 0) { + dev_err(&data->client->dev, "data not ready\n"); + return -EIO; + } + + return 0; +} + +static int mag3110_read(struct mag3110_data *data, __be16 buf[3]) +{ + int ret; + + mutex_lock(&data->lock); + ret = mag3110_request(data); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + ret = i2c_smbus_read_i2c_block_data(data->client, + MAG3110_OUT_X, 3 * sizeof(__be16), (u8 *) buf); + mutex_unlock(&data->lock); + + return ret; +} + +static ssize_t mag3110_show_int_plus_micros(char *buf, + const int (*vals)[2], int n) +{ + size_t len = 0; + + while (n-- > 0) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%d.%d ", vals[n][0], vals[n][1]); + + /* replace trailing space by newline */ + buf[len - 1] = '\n'; + + return len; +} + +static int mag3110_get_int_plus_micros_index(const int (*vals)[2], int n, + int val, int val2) +{ + while (n-- > 0) + if (val == vals[n][0] && val2 == vals[n][1]) + return n; + + return -EINVAL; +} + +static const int mag3110_samp_freq[8][2] = { + {80, 0}, {40, 0}, {20, 0}, {10, 0}, {5, 0}, {2, 500000}, + {1, 250000}, {0, 625000} +}; + +static ssize_t mag3110_show_samp_freq_avail(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return mag3110_show_int_plus_micros(buf, mag3110_samp_freq, 8); +} + +static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mag3110_show_samp_freq_avail); + +static int mag3110_get_samp_freq_index(struct mag3110_data *data, + int val, int val2) +{ + return mag3110_get_int_plus_micros_index(mag3110_samp_freq, 8, val, + val2); +} + +static int mag3110_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mag3110_data *data = iio_priv(indio_dev); + __be16 buffer[3]; + int i, ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_MAGN: /* in 0.1 uT / LSB */ + ret = mag3110_read(data, buffer); + if (ret < 0) + return ret; + *val = sign_extend32( + be16_to_cpu(buffer[chan->scan_index]), 15); + return IIO_VAL_INT; + case IIO_TEMP: /* in 1 C / LSB */ + mutex_lock(&data->lock); + ret = mag3110_request(data); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + ret = i2c_smbus_read_byte_data(data->client, + MAG3110_DIE_TEMP); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + *val = sign_extend32(ret, 7); + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 1000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT; + *val = mag3110_samp_freq[i][0]; + *val2 = mag3110_samp_freq[i][1]; + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static int mag3110_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct mag3110_data *data = iio_priv(indio_dev); + int rate; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + rate = mag3110_get_samp_freq_index(data, val, val2); + if (rate < 0) + return -EINVAL; + + data->ctrl_reg1 &= ~MAG3110_CTRL_DR_MASK; + data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT; + return i2c_smbus_write_byte_data(data->client, + MAG3110_CTRL_REG1, data->ctrl_reg1); + default: + return -EINVAL; + } +} + +static irqreturn_t mag3110_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct mag3110_data *data = iio_priv(indio_dev); + u8 buffer[16]; /* 3 16-bit channels + 1 byte temp + padding + ts */ + int ret; + + ret = mag3110_read(data, (__be16 *) buffer); + if (ret < 0) + goto done; + + if (test_bit(3, indio_dev->active_scan_mask)) { + ret = i2c_smbus_read_byte_data(data->client, + MAG3110_DIE_TEMP); + if (ret < 0) + goto done; + buffer[6] = ret; + } + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + iio_get_time_ns()); + +done: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +#define MAG3110_CHANNEL(axis, idx) { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = idx, \ + .scan_type = IIO_ST('s', 16, 16, IIO_BE), \ +} + +static const struct iio_chan_spec mag3110_channels[] = { + MAG3110_CHANNEL(X, 0), + MAG3110_CHANNEL(Y, 1), + MAG3110_CHANNEL(Z, 2), + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = 3, + .scan_type = IIO_ST('s', 8, 8, 0), + }, + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static struct attribute *mag3110_attributes[] = { + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group mag3110_group = { + .attrs = mag3110_attributes, +}; + +static const struct iio_info mag3110_info = { + .attrs = &mag3110_group, + .read_raw = &mag3110_read_raw, + .write_raw = &mag3110_write_raw, + .driver_module = THIS_MODULE, +}; + +static const unsigned long mag3110_scan_masks[] = {0x7, 0xf, 0}; + +static int mag3110_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct mag3110_data *data; + struct iio_dev *indio_dev; + int ret; + + ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I); + if (ret < 0) + return ret; + if (ret != MAG3110_DEVICE_ID) + return -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + mutex_init(&data->lock); + + i2c_set_clientdata(client, indio_dev); + indio_dev->info = &mag3110_info; + indio_dev->name = id->name; + indio_dev->dev.parent = &client->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = mag3110_channels; + indio_dev->num_channels = ARRAY_SIZE(mag3110_channels); + indio_dev->available_scan_masks = mag3110_scan_masks; + + data->ctrl_reg1 = MAG3110_CTRL_DR_DEFAULT; + ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG1, + data->ctrl_reg1); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2, + MAG3110_CTRL_AUTO_MRST_EN | MAG3110_CTRL_RAW); + if (ret < 0) + return ret; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + mag3110_trigger_handler, NULL); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto buffer_cleanup; + return 0; + +buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + return ret; +} + +static int mag3110_standby(struct mag3110_data *data) +{ + return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, + data->ctrl_reg1 & ~MAG3110_CTRL_AC); +} + +static int mag3110_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + mag3110_standby(iio_priv(indio_dev)); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mag3110_suspend(struct device *dev) +{ + return mag3110_standby(iio_priv(i2c_get_clientdata( + to_i2c_client(dev)))); +} + +static int mag3110_resume(struct device *dev) +{ + struct mag3110_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); + + return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, + data->ctrl_reg1); +} + +static SIMPLE_DEV_PM_OPS(mag3110_pm_ops, mag3110_suspend, mag3110_resume); +#define MAG3110_PM_OPS (&mag3110_pm_ops) +#else +#define MAG3110_PM_OPS NULL +#endif + +static const struct i2c_device_id mag3110_id[] = { + { "mag3110", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mag3110_id); + +static struct i2c_driver mag3110_driver = { + .driver = { + .name = "mag3110", + .pm = MAG3110_PM_OPS, + }, + .probe = mag3110_probe, + .remove = mag3110_remove, + .id_table = mag3110_id, +}; +module_i2c_driver(mag3110_driver); + +MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); +MODULE_DESCRIPTION("Freescale MAG3110 magnetometer driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 26fdc0bdb99d..4f2e0f9bad8c 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -14,7 +14,7 @@ config IIO_ST_PRESS select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) help Say yes here to build support for STMicroelectronics pressure - sensors: LPS331AP. + sensors: LPS001WP, LPS331AP. This driver can also be built as a module. If so, these modules will be created: diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index 399a29b6017b..27322af6d665 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -48,6 +48,7 @@ static int st_press_spi_remove(struct spi_device *spi) } static const struct spi_device_id st_press_id_table[] = { + { LPS001WP_PRESS_DEV_NAME }, { LPS331AP_PRESS_DEV_NAME }, {}, }; diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 1cf476484d77..e3d643001952 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -114,6 +114,7 @@ config LPC32XX_ADC config MXS_LRADC tristate "Freescale i.MX23/i.MX28 LRADC" depends on ARCH_MXS || COMPILE_TEST + depends on INPUT select STMP_DEVICE select IIO_BUFFER select IIO_TRIGGERED_BUFFER |