summaryrefslogtreecommitdiffstats
path: root/drivers/iio/proximity
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-12-26 17:03:33 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-12-26 17:03:33 -0800
commit35ea984daccc60e6b9dd90074bb2f4f6b57e6309 (patch)
treecb6c0642539e6ab7e236949fc20cb0340ab09e19 /drivers/iio/proximity
parente59ac747946693b1356d576f843ce8ac1e283927 (diff)
parentc34c18195d30aa3b95f5ae1b4349875c45fdb8e4 (diff)
downloadop-kernel-dev-35ea984daccc60e6b9dd90074bb2f4f6b57e6309.zip
op-kernel-dev-35ea984daccc60e6b9dd90074bb2f4f6b57e6309.tar.gz
Merge tag 'iio-for-4.5b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes: Second set of IIO new drivers, functionality and cleanups for the 4.5 cycle. The big one here is the configfs support which has been a long time in the works but should allow for cleaner ways to do instantiation of those elements of IIO that aren't directly connected to specific hardware. Lots of cool new stuff we can use this for in the works! New core stuff (basically all configfs support related) * Configfs support - Core support (was waiting for a configfs patch that went in around 4.4rc2) - A little fixlet to add a configfs.h to contain a reference to the configfs_subsystem structure. * Some infrastructure to simplify handling of software based triggers (i.e. ones with no actual hardware associated with them) * A high resolution timer based trigger. This has been around for years but until the configfs support was ready we didn't have a sensible way of instantiating instances of it (the method used for the sysfs_trigger has never been really satisfactory) New Device Support * AMS iAQ Volatile Organic Compounds sensor support. * Freescale imx7d ADC driver * Maxim MAX30100 oximeter driver (note that for these devices most of the smart stuff will be in userspace - effectively they are just light sensors with some interesting led synchronization as far as the kernel is concerned). * Microchip mcp3421 support added to the mcp3422 driver. * TI adc124s021 support added to the adc128s052 driver. * TI ina219, inda226 power monitors. Note that there is an existing hwmon driver for these parts, the usecase is somewhat different so it is unclear at this point if the hwmon driver will eventually be replaced by a bridge from this driver. In the meantime the Kconfig dependencies should prevent both from being built. New driver functionality * us8152d power management support. Cleanups, fixups * Use list_for_each_entry_safe instead of list_for_each_safe with the entry bit coded longhand. * Select IRQ_WORK for IIO_DUMMY_EVGEN. This is a fix that somehow got lost when the driver was moved so lets do it again. * st-accel - drop an unused define. * vz89x, lidar - optimize i2c transactions by using a single i2c tranfers instead of multiple calls where supported (fall back to smbus calls as before if not). * Use dev_get_platdata() in staging drivers: tsl2x7x, adcs and frequency drivers instead of direct access to the structure element.
Diffstat (limited to 'drivers/iio/proximity')
-rw-r--r--drivers/iio/proximity/pulsedlight-lidar-lite-v2.c95
1 files changed, 70 insertions, 25 deletions
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
index 29ac262..93e29fb 100644
--- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
+++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
@@ -36,8 +36,10 @@
#define LIDAR_REG_STATUS_INVALID BIT(3)
#define LIDAR_REG_STATUS_READY BIT(0)
-#define LIDAR_REG_DATA_HBYTE 0x0f
-#define LIDAR_REG_DATA_LBYTE 0x10
+#define LIDAR_REG_DATA_HBYTE 0x0f
+#define LIDAR_REG_DATA_LBYTE 0x10
+#define LIDAR_REG_DATA_WORD_READ BIT(7)
+
#define LIDAR_REG_PWR_CONTROL 0x65
#define LIDAR_DRV_NAME "lidar"
@@ -46,6 +48,9 @@ struct lidar_data {
struct iio_dev *indio_dev;
struct i2c_client *client;
+ int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len);
+ int i2c_enabled;
+
u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */
};
@@ -64,7 +69,28 @@ static const struct iio_chan_spec lidar_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(1),
};
-static int lidar_read_byte(struct lidar_data *data, int reg)
+static int lidar_i2c_xfer(struct lidar_data *data, u8 reg, u8 *val, int len)
+{
+ struct i2c_client *client = data->client;
+ struct i2c_msg msg[2];
+ int ret;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags | I2C_M_STOP;
+ msg[0].len = 1;
+ msg[0].buf = (char *) &reg;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags | I2C_M_RD;
+ msg[1].len = len;
+ msg[1].buf = (char *) val;
+
+ ret = i2c_transfer(client->adapter, msg, 2);
+
+ return (ret == 2) ? 0 : ret;
+}
+
+static int lidar_smbus_xfer(struct lidar_data *data, u8 reg, u8 *val, int len)
{
struct i2c_client *client = data->client;
int ret;
@@ -74,17 +100,35 @@ static int lidar_read_byte(struct lidar_data *data, int reg)
* so in turn i2c_smbus_read_byte_data cannot be used
*/
- ret = i2c_smbus_write_byte(client, reg);
- if (ret < 0) {
- dev_err(&client->dev, "cannot write addr value");
- return ret;
+ while (len--) {
+ ret = i2c_smbus_write_byte(client, reg++);
+ if (ret < 0) {
+ dev_err(&client->dev, "cannot write addr value");
+ return ret;
+ }
+
+ ret = i2c_smbus_read_byte(client);
+ if (ret < 0) {
+ dev_err(&client->dev, "cannot read data value");
+ return ret;
+ }
+
+ *(val++) = ret;
}
- ret = i2c_smbus_read_byte(client);
+ return 0;
+}
+
+static int lidar_read_byte(struct lidar_data *data, u8 reg)
+{
+ int ret;
+ u8 val;
+
+ ret = data->xfer(data, reg, &val, 1);
if (ret < 0)
- dev_err(&client->dev, "cannot read data value");
+ return ret;
- return ret;
+ return val;
}
static inline int lidar_write_control(struct lidar_data *data, int val)
@@ -100,22 +144,14 @@ static inline int lidar_write_power(struct lidar_data *data, int val)
static int lidar_read_measurement(struct lidar_data *data, u16 *reg)
{
- int ret;
- int val;
-
- ret = lidar_read_byte(data, LIDAR_REG_DATA_HBYTE);
- if (ret < 0)
- return ret;
- val = ret << 8;
+ int ret = data->xfer(data, LIDAR_REG_DATA_HBYTE |
+ (data->i2c_enabled ? LIDAR_REG_DATA_WORD_READ : 0),
+ (u8 *) reg, 2);
- ret = lidar_read_byte(data, LIDAR_REG_DATA_LBYTE);
- if (ret < 0)
- return ret;
+ if (!ret)
+ *reg = be16_to_cpu(*reg);
- val |= ret;
- *reg = val;
-
- return 0;
+ return ret;
}
static int lidar_get_measurement(struct lidar_data *data, u16 *reg)
@@ -233,6 +269,16 @@ static int lidar_probe(struct i2c_client *client,
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
+ data = iio_priv(indio_dev);
+
+ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ data->xfer = lidar_i2c_xfer;
+ data->i2c_enabled = 1;
+ } else if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE))
+ data->xfer = lidar_smbus_xfer;
+ else
+ return -ENOTSUPP;
indio_dev->info = &lidar_info;
indio_dev->name = LIDAR_DRV_NAME;
@@ -240,7 +286,6 @@ static int lidar_probe(struct i2c_client *client,
indio_dev->num_channels = ARRAY_SIZE(lidar_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
- data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
OpenPOWER on IntegriCloud