On 25/05/16 05:29, Matt Ranostay wrote: > Signed-off-by: Matt Ranostay <mranostay@xxxxxxxxx> > --- Applied to the togreg branch of iio.git - initially pushed out as testing for the autobuilders to play with it. Thanks, Jonathan > drivers/iio/chemical/atlas-ph-sensor.c | 145 ++++++++++++++++++++------------- > 1 file changed, 90 insertions(+), 55 deletions(-) > > diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c > index 62b37cd..e85477c 100644 > --- a/drivers/iio/chemical/atlas-ph-sensor.c > +++ b/drivers/iio/chemical/atlas-ph-sensor.c > @@ -24,6 +24,7 @@ > #include <linux/irq_work.h> > #include <linux/gpio.h> > #include <linux/i2c.h> > +#include <linux/of_device.h> > #include <linux/regmap.h> > #include <linux/iio/iio.h> > #include <linux/iio/buffer.h> > @@ -43,20 +44,25 @@ > > #define ATLAS_REG_PWR_CONTROL 0x06 > > -#define ATLAS_REG_CALIB_STATUS 0x0d > -#define ATLAS_REG_CALIB_STATUS_MASK 0x07 > -#define ATLAS_REG_CALIB_STATUS_LOW BIT(0) > -#define ATLAS_REG_CALIB_STATUS_MID BIT(1) > -#define ATLAS_REG_CALIB_STATUS_HIGH BIT(2) > +#define ATLAS_REG_PH_CALIB_STATUS 0x0d > +#define ATLAS_REG_PH_CALIB_STATUS_MASK 0x07 > +#define ATLAS_REG_PH_CALIB_STATUS_LOW BIT(0) > +#define ATLAS_REG_PH_CALIB_STATUS_MID BIT(1) > +#define ATLAS_REG_PH_CALIB_STATUS_HIGH BIT(2) > > -#define ATLAS_REG_TEMP_DATA 0x0e > +#define ATLAS_REG_PH_TEMP_DATA 0x0e > #define ATLAS_REG_PH_DATA 0x16 > > #define ATLAS_PH_INT_TIME_IN_US 450000 > > +enum { > + ATLAS_PH_SM, > +}; > + > struct atlas_data { > struct i2c_client *client; > struct iio_trigger *trig; > + struct atlas_device *chip; > struct regmap *regmap; > struct irq_work work; > > @@ -84,9 +90,10 @@ static const struct regmap_config atlas_regmap_config = { > .cache_type = REGCACHE_RBTREE, > }; > > -static const struct iio_chan_spec atlas_channels[] = { > +static const struct iio_chan_spec atlas_ph_channels[] = { > { > .type = IIO_PH, > + .address = ATLAS_REG_PH_DATA, > .info_mask_separate = > BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), > .scan_index = 0, > @@ -100,7 +107,7 @@ static const struct iio_chan_spec atlas_channels[] = { > IIO_CHAN_SOFT_TIMESTAMP(1), > { > .type = IIO_TEMP, > - .address = ATLAS_REG_TEMP_DATA, > + .address = ATLAS_REG_PH_TEMP_DATA, > .info_mask_separate = > BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), > .output = 1, > @@ -108,6 +115,52 @@ static const struct iio_chan_spec atlas_channels[] = { > }, > }; > > +static int atlas_check_ph_calibration(struct atlas_data *data) > +{ > + struct device *dev = &data->client->dev; > + int ret; > + unsigned int val; > + > + ret = regmap_read(data->regmap, ATLAS_REG_PH_CALIB_STATUS, &val); > + if (ret) > + return ret; > + > + if (!(val & ATLAS_REG_PH_CALIB_STATUS_MASK)) { > + dev_warn(dev, "device has not been calibrated\n"); > + return 0; > + } > + > + if (!(val & ATLAS_REG_PH_CALIB_STATUS_LOW)) > + dev_warn(dev, "device missing low point calibration\n"); > + > + if (!(val & ATLAS_REG_PH_CALIB_STATUS_MID)) > + dev_warn(dev, "device missing mid point calibration\n"); > + > + if (!(val & ATLAS_REG_PH_CALIB_STATUS_HIGH)) > + dev_warn(dev, "device missing high point calibration\n"); > + > + return 0; > +} > + > +struct atlas_device { > + const struct iio_chan_spec *channels; > + int num_channels; > + int data_reg; > + > + int (*calibration)(struct atlas_data *data); > + int delay; > +}; > + > +static struct atlas_device atlas_devices[] = { > + [ATLAS_PH_SM] = { > + .channels = atlas_ph_channels, > + .num_channels = 3, > + .data_reg = ATLAS_REG_PH_DATA, > + .calibration = &atlas_check_ph_calibration, > + .delay = ATLAS_PH_INT_TIME_IN_US, > + }, > +}; > + > static int atlas_set_powermode(struct atlas_data *data, int on) > { > return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on); > @@ -178,8 +231,9 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private) > struct atlas_data *data = iio_priv(indio_dev); > int ret; > > - ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA, > - (u8 *) &data->buffer, sizeof(data->buffer[0])); > + ret = regmap_bulk_read(data->regmap, data->chip->data_reg, > + (u8 *) &data->buffer, > + sizeof(__be32) * (data->chip->num_channels - 2)); > > if (!ret) > iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, > @@ -200,7 +254,7 @@ static irqreturn_t atlas_interrupt_handler(int irq, void *private) > return IRQ_HANDLED; > } > > -static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val) > +static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val) > { > struct device *dev = &data->client->dev; > int suspended = pm_runtime_suspended(dev); > @@ -213,11 +267,9 @@ static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val) > } > > if (suspended) > - usleep_range(ATLAS_PH_INT_TIME_IN_US, > - ATLAS_PH_INT_TIME_IN_US + 100000); > + usleep_range(data->chip->delay, data->chip->delay + 100000); > > - ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA, > - (u8 *) val, sizeof(*val)); > + ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val)); > > pm_runtime_mark_last_busy(dev); > pm_runtime_put_autosuspend(dev); > @@ -247,7 +299,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev, > if (iio_buffer_enabled(indio_dev)) > ret = -EBUSY; > else > - ret = atlas_read_ph_measurement(data, ®); > + ret = atlas_read_measurement(data, > + chan->address, ®); > > mutex_unlock(&indio_dev->mlock); > break; > @@ -303,37 +356,24 @@ static const struct iio_info atlas_info = { > .write_raw = atlas_write_raw, > }; > > -static int atlas_check_calibration(struct atlas_data *data) > -{ > - struct device *dev = &data->client->dev; > - int ret; > - unsigned int val; > - > - ret = regmap_read(data->regmap, ATLAS_REG_CALIB_STATUS, &val); > - if (ret) > - return ret; > - > - if (!(val & ATLAS_REG_CALIB_STATUS_MASK)) { > - dev_warn(dev, "device has not been calibrated\n"); > - return 0; > - } > - > - if (!(val & ATLAS_REG_CALIB_STATUS_LOW)) > - dev_warn(dev, "device missing low point calibration\n"); > - > - if (!(val & ATLAS_REG_CALIB_STATUS_MID)) > - dev_warn(dev, "device missing mid point calibration\n"); > - > - if (!(val & ATLAS_REG_CALIB_STATUS_HIGH)) > - dev_warn(dev, "device missing high point calibration\n"); > +static const struct i2c_device_id atlas_id[] = { > + { "atlas-ph-sm", ATLAS_PH_SM}, > + {} > +}; > +MODULE_DEVICE_TABLE(i2c, atlas_id); > > - return 0; > +static const struct of_device_id atlas_dt_ids[] = { > + { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, }, > + { } > }; > +MODULE_DEVICE_TABLE(of, atlas_dt_ids); > > static int atlas_probe(struct i2c_client *client, > const struct i2c_device_id *id) > { > struct atlas_data *data; > + struct atlas_device *chip; > + const struct of_device_id *of_id; > struct iio_trigger *trig; > struct iio_dev *indio_dev; > int ret; > @@ -342,10 +382,16 @@ static int atlas_probe(struct i2c_client *client, > if (!indio_dev) > return -ENOMEM; > > + of_id = of_match_device(atlas_dt_ids, &client->dev); > + if (!of_id) > + chip = &atlas_devices[id->driver_data]; > + else > + chip = &atlas_devices[(unsigned long)of_id->data]; > + > indio_dev->info = &atlas_info; > indio_dev->name = ATLAS_DRV_NAME; > - indio_dev->channels = atlas_channels; > - indio_dev->num_channels = ARRAY_SIZE(atlas_channels); > + indio_dev->channels = chip->channels; > + indio_dev->num_channels = chip->num_channels; > indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; > indio_dev->dev.parent = &client->dev; > > @@ -358,6 +404,7 @@ static int atlas_probe(struct i2c_client *client, > data = iio_priv(indio_dev); > data->client = client; > data->trig = trig; > + data->chip = chip; > trig->dev.parent = indio_dev->dev.parent; > trig->ops = &atlas_interrupt_trigger_ops; > iio_trigger_set_drvdata(trig, indio_dev); > @@ -379,7 +426,7 @@ static int atlas_probe(struct i2c_client *client, > return -EINVAL; > } > > - ret = atlas_check_calibration(data); > + ret = chip->calibration(data); > if (ret) > return ret; > > @@ -480,18 +527,6 @@ static const struct dev_pm_ops atlas_pm_ops = { > atlas_runtime_resume, NULL) > }; > > -static const struct i2c_device_id atlas_id[] = { > - { "atlas-ph-sm", 0 }, > - {} > -}; > -MODULE_DEVICE_TABLE(i2c, atlas_id); > - > -static const struct of_device_id atlas_dt_ids[] = { > - { .compatible = "atlas,ph-sm" }, > - { } > -}; > -MODULE_DEVICE_TABLE(of, atlas_dt_ids); > - > static struct i2c_driver atlas_driver = { > .driver = { > .name = ATLAS_DRV_NAME, > -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html