iio: chemical: vz89x: abstract chip configuration
authorMatt Ranostay <mranostay@gmail.com>
Thu, 25 Aug 2016 06:44:47 +0000 (23:44 -0700)
committerJonathan Cameron <jic23@kernel.org>
Mon, 29 Aug 2016 16:46:52 +0000 (17:46 +0100)
Abstract chip configuration data to allow supporting multiple variants
of the VZ89 chemical sensor line.

Signed-off-by: Matt Ranostay <mranostay@gmail.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/iio/chemical/vz89x.c

index 652649da500faff381f330749cc8262ce6ce65ca..aa6ebc084e1919d9a94c09406e77eb34254b24a8 100644 (file)
 #include <linux/mutex.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 
 #define VZ89X_REG_MEASUREMENT          0x09
-#define VZ89X_REG_MEASUREMENT_SIZE     6
+#define VZ89X_REG_MEASUREMENT_RD_SIZE  6
+#define VZ89X_REG_MEASUREMENT_WR_SIZE  3
 
 #define VZ89X_VOC_CO2_IDX              0
 #define VZ89X_VOC_SHORT_IDX            1
 #define VZ89X_VOC_TVOC_IDX             2
 #define VZ89X_VOC_RESISTANCE_IDX       3
 
+enum {
+       VZ89X,
+};
+
+struct vz89x_chip_data;
+
 struct vz89x_data {
        struct i2c_client *client;
+       const struct vz89x_chip_data *chip;
        struct mutex lock;
        int (*xfer)(struct vz89x_data *data, u8 cmd);
 
        unsigned long last_update;
-       u8 buffer[VZ89X_REG_MEASUREMENT_SIZE];
+       u8 buffer[VZ89X_REG_MEASUREMENT_RD_SIZE];
+};
+
+struct vz89x_chip_data {
+       bool (*valid)(struct vz89x_data *data);
+       const struct iio_chan_spec *channels;
+       u8 num_channels;
+
+       u8 cmd;
+       u8 read_size;
+       u8 write_size;
 };
 
 static const struct iio_chan_spec vz89x_channels[] = {
@@ -93,16 +113,17 @@ static const struct attribute_group vz89x_attrs_group = {
  * always zero, and by also confirming the VOC_short isn't zero.
  */
 
-static int vz89x_measurement_is_valid(struct vz89x_data *data)
+static bool vz89x_measurement_is_valid(struct vz89x_data *data)
 {
        if (data->buffer[VZ89X_VOC_SHORT_IDX] == 0)
                return 1;
 
-       return !!(data->buffer[VZ89X_REG_MEASUREMENT_SIZE - 1] > 0);
+       return !!(data->buffer[data->chip->read_size - 1] > 0);
 }
 
 static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd)
 {
+       const struct vz89x_chip_data *chip = data->chip;
        struct i2c_client *client = data->client;
        struct i2c_msg msg[2];
        int ret;
@@ -110,12 +131,12 @@ static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd)
 
        msg[0].addr = client->addr;
        msg[0].flags = client->flags;
-       msg[0].len = 3;
+       msg[0].len = chip->write_size;
        msg[0].buf  = (char *) &buf;
 
        msg[1].addr = client->addr;
        msg[1].flags = client->flags | I2C_M_RD;
-       msg[1].len = VZ89X_REG_MEASUREMENT_SIZE;
+       msg[1].len = chip->read_size;
        msg[1].buf = (char *) &data->buffer;
 
        ret = i2c_transfer(client->adapter, msg, 2);
@@ -133,7 +154,7 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd)
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) {
+       for (i = 0; i < data->chip->read_size; i++) {
                ret = i2c_smbus_read_byte(client);
                if (ret < 0)
                        return ret;
@@ -145,17 +166,18 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd)
 
 static int vz89x_get_measurement(struct vz89x_data *data)
 {
+       const struct vz89x_chip_data *chip = data->chip;
        int ret;
 
        /* sensor can only be polled once a second max per datasheet */
        if (!time_after(jiffies, data->last_update + HZ))
                return 0;
 
-       ret = data->xfer(data, VZ89X_REG_MEASUREMENT);
+       ret = data->xfer(data, chip->cmd);
        if (ret < 0)
                return ret;
 
-       ret = vz89x_measurement_is_valid(data);
+       ret = chip->valid(data);
        if (ret)
                return -EAGAIN;
 
@@ -232,11 +254,32 @@ static const struct iio_info vz89x_info = {
        .driver_module  = THIS_MODULE,
 };
 
+static const struct vz89x_chip_data vz89x_chips[] = {
+       {
+               .valid = vz89x_measurement_is_valid,
+
+               .cmd = VZ89X_REG_MEASUREMENT,
+               .read_size = VZ89X_REG_MEASUREMENT_RD_SIZE,
+               .write_size = VZ89X_REG_MEASUREMENT_WR_SIZE,
+
+               .channels = vz89x_channels,
+               .num_channels = ARRAY_SIZE(vz89x_channels),
+       },
+};
+
+static const struct of_device_id vz89x_dt_ids[] = {
+       { .compatible = "sgx,vz89x", .data = (void *) VZ89X },
+       { }
+};
+MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
+
 static int vz89x_probe(struct i2c_client *client,
                       const struct i2c_device_id *id)
 {
        struct iio_dev *indio_dev;
        struct vz89x_data *data;
+       const struct of_device_id *of_id;
+       int chip_id;
 
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
        if (!indio_dev)
@@ -251,8 +294,15 @@ static int vz89x_probe(struct i2c_client *client,
        else
                return -EOPNOTSUPP;
 
+       of_id = of_match_device(vz89x_dt_ids, &client->dev);
+       if (!of_id)
+               chip_id = id->driver_data;
+       else
+               chip_id = (unsigned long)of_id->data;
+
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
+       data->chip = &vz89x_chips[chip_id];
        data->last_update = jiffies - HZ;
        mutex_init(&data->lock);
 
@@ -261,24 +311,18 @@ static int vz89x_probe(struct i2c_client *client,
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       indio_dev->channels = vz89x_channels;
-       indio_dev->num_channels = ARRAY_SIZE(vz89x_channels);
+       indio_dev->channels = data->chip->channels;
+       indio_dev->num_channels = data->chip->num_channels;
 
        return devm_iio_device_register(&client->dev, indio_dev);
 }
 
 static const struct i2c_device_id vz89x_id[] = {
-       { "vz89x", 0 },
+       { "vz89x", VZ89X },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, vz89x_id);
 
-static const struct of_device_id vz89x_dt_ids[] = {
-       { .compatible = "sgx,vz89x" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
-
 static struct i2c_driver vz89x_driver = {
        .driver = {
                .name   = "vz89x",