Re: [PATCH v2] Added AMS tsl2591 driver implementation

2021-02-10 Thread Peter Meerwald-Stadler
; +IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
> + IIO_EV_TYPE_THRESH,
> + IIO_EV_DIR_EITHER),
> + iio_get_time_ns(dev_info));
> +
> + /* Clear als irq */
> + ret = i2c_smbus_write_byte(client, TSL2591_CMD_SF_CALS_NPI);
> + if (ret < 0)
> + dev_err(>dev, "failed to clear als irq\n");
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int tsl2591_load_defaults(struct tsl2591_chip *chip)
> +{
> + struct i2c_client *client = chip->client;
> +
> + chip->als_settings.als_int_time = TSL2591_DEFAULT_ALS_INT_TIME;
> + chip->als_settings.als_gain = TSL2591_DEFAULT_ALS_GAIN;
> + chip->als_settings.als_persist = TSL2591_DEFAULT_ALS_PERSIST;
> + chip->als_settings.als_lower_threshold =
> + TSL2591_DEFAULT_ALS_LOWER_THRESHOLD;
> +     chip->als_settings.als_upper_

Re: [PATCH 1/1] iio: (bma400) add driver for the BMA400

2019-10-08 Thread Peter Meerwald-Stadler
 .attrs = bma400_attributes,
> > +};
> > +
> > +static int bma400_read_raw(struct iio_dev *indio_dev,
> > +  struct iio_chan_spec const *chan, int *val,
> > +  int *val2, long mask)
> > +{
> > +   struct bma400_data *data = iio_priv(indio_dev);
> > +   int ret;
> > +
> > +   switch (mask) {
> > +   case IIO_CHAN_INFO_PROCESSED:
> > +   mutex_lock(>mutex);
> > +   ret = bma400_get_temp_reg(data, val, val2);
> > +   mutex_unlock(>mutex);
> > +   return ret;
> > +   case IIO_CHAN_INFO_RAW:
> > +   mutex_lock(>mutex);
> > +   ret = bma400_get_accel_reg(data, chan, val);
> > +   mutex_unlock(>mutex);
> > +   return ret;
> > +   case IIO_CHAN_INFO_SAMP_FREQ:
> > +   switch (chan->type) {
> > +   case IIO_ACCEL:
> > +   if (!data->sample_freq)
> > +   return -EINVAL;
> > +
> > +   *val = data->sample_freq->hz;
> > +   if (!data->sample_freq->micro_hz)
> > +   return IIO_VAL_INT;
> > +
> > +   *val2 = data->sample_freq->micro_hz;
> > +   return IIO_VAL_INT_PLUS_MICRO;
> > +   case IIO_TEMP:
> > +   /*
> > +* Runs at a fixed sampling frequency. See Section 4.4
> > +* of the datasheet.
> > +*/
> > +   *val = 6;
> > +   *val2 = 25;
> > +   return IIO_VAL_INT_PLUS_MICRO;
> > +   default:
> > +   return -EINVAL;
> > +   }
> > +   case IIO_CHAN_INFO_SCALE:
> > +   *val = 0;
> > +   *val2 = data->scale;
> > +   return IIO_VAL_INT_PLUS_MICRO;
> > +   case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> > +   /*
> > +* TODO: We could avoid this logic and returning -EINVAL here if
> > +* we set both the low-power and normal mode OSR registers when
> > +* we configure the device.
> > +*/
> > +   if (data->oversampling_ratio < 0)
> > +   return -EINVAL;
> > +
> > +   *val = data->oversampling_ratio;
> > +   return IIO_VAL_INT;
> > +   default:
> > +   return -EINVAL;
> > +   }
> > +}
> > +
> > +static int bma400_write_raw(struct iio_dev *indio_dev,
> > +   struct iio_chan_spec const *chan, int val, int val2,
> > +   long mask)
> > +{
> > +   int ret;
> > +   struct bma400_data *data = iio_priv(indio_dev);
> > +
> > +   switch (mask) {
> > +   case IIO_CHAN_INFO_SAMP_FREQ:
> > +   /*
> > +* The sample frequency is readonly for the temperature
> > +* register and a fixed value in low-power mode.
> > +*/
> > +   if (chan->type != IIO_ACCEL)
> > +   return -EINVAL;
> > +
> > +   mutex_lock(>mutex);
> > +   ret = bma400_set_accel_output_data_rate(data, val, val2);
> > +   mutex_unlock(>mutex);
> > +   return ret;
> > +   case IIO_CHAN_INFO_SCALE:
> > +   if (val != 0)
> > +   return -EINVAL;
> > +
> > +   mutex_lock(>mutex);
> > +   ret = bma400_set_accel_scale(data, val2);
> > +   mutex_unlock(>mutex);
> > +   return ret;
> > +   case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> > +   mutex_lock(>mutex);
> > +   ret = bma400_set_accel_oversampling_ratio(data, val);
> > +   mutex_unlock(>mutex);
> > +   return ret;
> > +   default:
> > +   return -EINVAL;
> > +   }
> > +}
> > +
> > +static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
> > +   struct iio_chan_spec const *chan,
> > +   long mask)
> > +{
> > +   switch (mask) {
> > +   case IIO_CHAN_INFO_SAMP_FREQ:
> > +   return IIO_VAL_INT_PLUS_MICRO;
> > +   case IIO_CHAN_INFO_SCALE:
> > +   return IIO_VAL_INT_PLUS_MICRO;
> > +   case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> > +   return IIO_VAL_INT;
> > +   default:
> > +   return -EINVAL;
> > +   }
> > +}
> > +
> > +static const struct iio_info bma400_info = {
> > +   .attrs = _attrs_group,
> > +   .read_raw  = bma400_read_raw,
> > +   .write_raw = bma400_write_raw,
> > +   .write_raw_get_fmt = bma400_write_raw_get_fmt,
> > +};
> > +
> > +int bma400_probe(struct device *dev,
> > +struct regmap *regmap,
> > +const char *name)
> > +{
> > +   int ret;
> > +   struct bma400_data *data;
> > +   struct iio_dev *indio_dev;
> > +
> > +   indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
> > +   if (!indio_dev)
> > +   return -ENOMEM;
> > +
> > +   data = iio_priv(indio_dev);
> > +   data->regmap = regmap;
> > +   data->dev = dev;
> > +
> > +   ret = bma400_init(data);
> > +   if (ret < 0)
> > +   return ret;
> > +
> > +   ret = iio_read_mount_matrix(dev, "mount-matrix",
> > +   >orientation);
> 
> Looks like the above will fit on one line..
> 
> > +   if (ret)
> > +   return ret;
> > +
> > +   mutex_init(>mutex);
> > +   indio_dev->dev.parent = dev;
> > +   indio_dev->name = name;
> > +   indio_dev->info = _info;
> > +   indio_dev->channels = bma400_channels;
> > +   indio_dev->num_channels = ARRAY_SIZE(bma400_channels);
> > +   indio_dev->modes = INDIO_DIRECT_MODE;
> > +
> > +   dev_set_drvdata(dev, indio_dev);
> > +
> > +   ret = iio_device_register(indio_dev);
> > +   if (ret < 0) {
> > +   dev_err(dev, "unable to register iio device\n");
> > +   return ret;
> 
> Drop the return out of the if statement and no need for the return 0 below.

I'd also avoid the error message altogether

> 
> > +   }
> > +
> > +   return 0;
> > +}
> > +EXPORT_SYMBOL(bma400_probe);
> > +
> > +int bma400_remove(struct device *dev)
> > +{
> > +   int ret;
> > +   struct iio_dev *indio_dev = dev_get_drvdata(dev);
> > +   struct bma400_data *data = iio_priv(indio_dev);
> > +
> > +   mutex_lock(>mutex);
> > +   ret = bma400_softreset(data);
> > +   if (ret < 0) {
> > +   /*
> > +* If the softreset failed, try to put the device in
> > +* sleep mode, but still report the error.
> > +*/
> > +   dev_err(data->dev, "Failed to reset the device");
> > +   bma400_set_power_mode(data, POWER_MODE_SLEEP);
> > +   }
> > +   mutex_unlock(>mutex);
> > +
> > +   iio_device_unregister(indio_dev);
> > +
> > +   return ret;
> > +}
> > +EXPORT_SYMBOL(bma400_remove);
> > +
> > +MODULE_AUTHOR("Dan Robertson ");
> > +MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c
> > new file mode 100644
> > index ..227012a32e13
> > --- /dev/null
> > +++ b/drivers/iio/accel/bma400_i2c.c
> > @@ -0,0 +1,54 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * bma400-i2c.c - I2C IIO driver for Bosch BMA400 triaxial acceleration 
> > sensor.
> > + *
> > + * Copyright 2019 Dan Robertson 
> > + *
> > + * I2C address is either 0x14 or 0x15 depending on SDO
> > + *
> 
> This blank line doesn't add anything (nitpick)
> 
> > + */
> > +#include 
> > +#include 
> > +#include 
> 
> Slight preference for alphabetical order.  Also why ACPI?
> 
> > +#include 
> > +#include 
> > +
> > +#include "bma400.h"
> > +
> > +static int bma400_i2c_probe(struct i2c_client *client,
> > +   const struct i2c_device_id *id)
> > +{
> > +   struct regmap *regmap;
> > +
> > +   regmap = devm_regmap_init_i2c(client,
> > + _regmap_config);
> > +
> > +   return bma400_probe(>dev, regmap, id->name);
> > +}
> > +
> > +static int bma400_i2c_remove(struct i2c_client *client)
> > +{
> > +   return bma400_remove(>dev);
> > +}
> > +
> > +static const struct i2c_device_id bma400_i2c_ids[] = {
> > +   { "bma400", 0 },
> > +   { }
> > +};
> > +
> > +MODULE_DEVICE_TABLE(i2c, bma400_i2c_ids);
> > +
> 
> Good to have a of_device_id table as well from the start.
> There is a general (but slow) move to stop using the fallback
> to the i2c_device_id table.
> 
> > +static struct i2c_driver bma400_i2c_driver = {
> > +   .driver = {
> > +   .name = "bma400",
> > +   },
> > +   .probe= bma400_i2c_probe,
> > +   .remove   = bma400_i2c_remove,
> > +   .id_table = bma400_i2c_ids,
> > +};
> > +
> > +module_i2c_driver(bma400_i2c_driver);
> > +
> > +MODULE_AUTHOR("Dan Robertson ");
> > +MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor");
> > +MODULE_LICENSE("GPL");
> > 
> > 
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: potentiometer: add a driver for Maxim 5432-5435

2019-07-21 Thread Peter Meerwald-Stadler
sk_separate = BIT(IIO_CHAN_INFO_RAW),
> + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
> + }
> +};
> +
> +static int max5432_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val, int *val2, long mask)
> +{
> + struct max5432_data *data = iio_priv(indio_dev);
> +
> + if (mask != IIO_CHAN_INFO_SCALE)
> + return -EINVAL;
> +
> + *val = data->ohm;
> + *val2 = MAX5432_MAX_POS;
> +
> + return IIO_VAL_FRACTIONAL;
> +}
> +
> +static int max5432_write_raw(struct iio_dev *indio_dev,
> +  struct iio_chan_spec const *chan,
> +  int val, int val2, long mask)
> +{
> + struct max5432_data *data = iio_priv(indio_dev);
> + u8 data_byte;
> +
> + if (mask != IIO_CHAN_INFO_RAW)
> + return -EINVAL;
> +
> + if (val < 0 || val > MAX5432_MAX_POS)
> + return -EINVAL;
> +
> + if (val2 != 0)
> + return -EINVAL;
> +
> + /* Wiper position is in bits D7-D3. (D2-D0 are don't care bits.) */
> + data_byte = val << 3;
> + return i2c_smbus_write_byte_data(
> + data->client, chan->address, data_byte);
> +}
> +
> +static const struct iio_info max5432_info = {
> + .read_raw = max5432_read_raw,
> + .write_raw = max5432_write_raw,
> +};
> +
> +static int max5432_probe(
> + struct i2c_client *client, const struct i2c_device_id *id)
> +{
> + struct device *dev = >dev;
> + struct iio_dev *indio_dev;
> + struct max5432_data *data;
> +
> + indio_dev = devm_iio_device_alloc(dev, sizeof(struct max5432_data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + i2c_set_clientdata(client, indio_dev);
> +
> + data = iio_priv(indio_dev);
> + data->client = client;
> + data->ohm = (u32)of_device_get_match_data(dev);
> +
> + indio_dev->dev.parent = dev;
> + indio_dev->info = _info;
> + indio_dev->channels = max5432_channels;
> + indio_dev->num_channels = ARRAY_SIZE(max5432_channels);
> + indio_dev->name = client->name;
> +
> + return devm_iio_device_register(dev, indio_dev);
> +}
> +
> +static const struct of_device_id max5432_dt_ids[] = {
> + { .compatible = "maxim,max5432", .data = (void *)OHM_50K  },
> + { .compatible = "maxim,max5433", .data = (void *)OHM_100K },
> + { .compatible = "maxim,max5434", .data = (void *)OHM_50K  },
> + { .compatible = "maxim,max5435", .data = (void *)OHM_100K },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, max5432_dt_ids);
> +
> +static struct i2c_driver max5432_driver = {
> + .driver = {
> + .name = "max5432",
> + .of_match_table = of_match_ptr(max5432_dt_ids),
> + },
> + .probe = max5432_probe,
> +};
> +
> +module_i2c_driver(max5432_driver);
> +
> +MODULE_AUTHOR("Martin Kaiser ");
> +MODULE_DESCRIPTION("max5432-max5435 digital potentiometers");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v4 3/3] iio: Add PAT9125 optical tracker sensor

2019-07-14 Thread Peter Meerwald-Stadler
t9125_threaded_trigger_handler, _buffer_ops);
> + if (ret) {
> + dev_err(>dev, "unable to setup triggered buffer\n");
> + return ret;
> + }
> +
> + data->indio_trig = devm_iio_trigger_alloc(>dev, "%s-dev%d",
> + indio_dev->name, indio_dev->id);
> + if (!data->indio_trig)
> + return -ENOMEM;
> + data->indio_trig->dev.parent = >dev;
> + data->indio_trig->ops = _trigger_ops;
> + iio_trigger_set_drvdata(data->indio_trig, data);
> + ret = devm_iio_trigger_register(>dev, data->indio_trig);
> + if (ret) {
> + dev_err(>dev, "unable to register trigger\n");
> + return ret;
> + }
> +
> + data->regmap = devm_regmap_init_i2c(client, _regmap_config);
> + if (IS_ERR(data->regmap)) {
> + dev_err(>dev, "regmap init failed %ld\n",
> + PTR_ERR(data->regmap));
> + return PTR_ERR(data->regmap);
> + }
> +
> + /* Check device ID */
> + ret = regmap_read(data->regmap, PAT9125_PRD_ID1_REG, _pid);
> + if (ret < 0) {
> + dev_err(>dev, "register 0x%x access failed %d\n",
> + PAT9125_PRD_ID1_REG, ret);
> + return ret;
> + }
> + if (sensor_pid != PAT9125_SENSOR_ID_VAL)

I'd rather put some logging here; what is the actual value obtained?

> + return -ENODEV;
> +
> + /* Switch to bank0 (Magic number)*/
> + ret = regmap_write(data->regmap, 0x7F, 0x00);

maybe a #define for 0x7f, PAT9125_BANK_SWITCH_REG

> + if (ret < 0) {
> + dev_err(indio_dev->dev.parent, "register 0x%x access failed 
> %d\n",
> + 0x7F, ret);
> + return ret;
> + }
> +
> + /* Software reset */
> + ret = regmap_write_bits(data->regmap,
> +   PAT9125_CONFIG_REG,
> +   PAT9125_RESET_BIT,
> +   1);
> + if (ret < 0) {
> + dev_err(>dev, "register 0x%x access failed %d\n",
> + PAT9125_CONFIG_REG, ret);
> + return ret;
> + }
> +
> + msleep(20);
> +
> + /* Init GPIO IRQ */
> + if (client->irq) {
> + ret = devm_request_threaded_irq(>dev,
> + client->irq,
> + NULL,
> + pat9125_threaded_event_handler,
> + IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
> + "pat9125",
> + indio_dev);
> + if (ret) {
> + dev_err(>dev, "GPIO IRQ init failed\n");
> + return ret;
> + }
> + }
> +
> + ret = devm_iio_device_register(>dev, indio_dev);
> + if (ret) {
> + dev_err(>dev, "IIO device register failed\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id pat9125_id[] = {
> + { "pat9125", 0 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(i2c, pat9125_id);
> +
> +static const unsigned short normal_i2c[] = {

pat9125_ prefix please

> + PAT9125_I2C_ADDR_HI,
> + PAT9125_I2C_ADDR_LO,
> + PAT9125_I2C_ADDR_NC,
> + I2C_CLIENT_END
> +};
> +
> +static struct i2c_driver pat9125_driver = {
> + .driver = {
> + .name = "pat9125",
> + },
> + .probe = pat9125_probe,
> + .address_list = normal_i2c,
> + .id_table = pat9125_id,
> +};
> +
> +module_i2c_driver(pat9125_driver);
> +
> +MODULE_AUTHOR("Alexandre Mergnat ");
> +MODULE_DESCRIPTION("Optical Tracking sensor");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH 3/3] iio: dps310: Add pressure sensing capability

2019-05-06 Thread Peter Meerwald-Stadler
EINVAL;
> +static int dps310_read_raw(struct iio_dev *iio,
> +struct iio_chan_spec const *chan,
> +int *val, int *val2, long mask)
> +{
> + struct dps310_data *data = iio_priv(iio);
> +
> + switch (chan->type) {
> + case IIO_PRESSURE:
> + return dps310_read_pressure(data, val, val2, mask);
> +
> + case IIO_TEMP:
> + return dps310_read_temp(data, val, val2, mask);
> +
> + default:
> + return -EINVAL;
> + }
>  }
>  
>  static const struct regmap_config dps310_regmap_config = {
> @@ -390,6 +651,13 @@ static int dps310_probe(struct i2c_client *client,
>   return PTR_ERR(data->regmap);
>  
>   /*
> +  * Set up pressure sensor in single sample, one measurement per second
> +  * mode
> +  */
> + r = regmap_write(data->regmap, DPS310_PRS_CFG,
> +  DPS310_CALC_RATE(1) | DPS310_CALC_PRC(1));
> +
> + /*
>* Set up external (MEMS) temperature sensor in single sample, one
>* measurement per second mode
>*/
> @@ -399,16 +667,23 @@ static int dps310_probe(struct i2c_client *client,
>   if (r < 0)
>   goto err;
>  
> - /* Temp shift is disabled when PRC <= 8 */
> + /* Temp and pressure shifts are disabled when PRC <= 8 */
>   r = regmap_write_bits(data->regmap, DPS310_CFG_REG,
> -   DPS310_TMP_SHIFT_EN, 0);
> +   DPS310_TMP_SHIFT_EN | DPS310_PRS_SHIFT_EN, 0);
> + if (r < 0)
> + goto err;
> +
> + /* MEAS_CFG doesn't seem to update unless first written with 0 */
> + r = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
> +   DPS310_MEAS_CTRL_BITS, 0);
>   if (r < 0)
>   goto err;
>  
> - /* Turn on temperature measurement in the background */
> + /* Turn on temperature and pressure measurement in the background */
>   r = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
> DPS310_MEAS_CTRL_BITS,
> -   DPS310_TEMP_EN | DPS310_BACKGROUND);
> +   DPS310_PRS_EN | DPS310_TEMP_EN |
> +   DPS310_BACKGROUND);
>   if (r < 0)
>   goto err;
>  
> @@ -421,7 +696,7 @@ static int dps310_probe(struct i2c_client *client,
>   if (r < 0)
>   goto err;
>  
> - r = dps310_get_temp_coef(data);
> + r = dps310_get_coefs(data);
>   if (r < 0)
>   goto err;
>  
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 1/3] iio: Add driver for Infineon DPS310

2019-05-06 Thread Peter Meerwald-Stadler
ent in the background */
> + r = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
> +   DPS310_MEAS_CTRL_BITS,
> +   DPS310_TEMP_EN | DPS310_BACKGROUND);
> + if (r < 0)
> + goto err;
> +
> + /*
> +  * Calibration coefficients required for reporting temperature.
> +  * They are available 40ms after the device has started
> +  */
> + r = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
> +  ready & DPS310_COEF_RDY, 1, 4);
> + if (r < 0)
> + goto err;
> +
> + r = dps310_get_temp_coef(data);
> + if (r < 0)
> + goto err;
> +
> + r = devm_iio_device_register(>dev, iio);
> + if (r)
> + goto err;
> +
> + i2c_set_clientdata(client, iio);
> +
> + dev_info(>dev, "%s: sensor '%s'\n", dev_name(>dev),
> +  client->name);

don't clutter the log

> +
> + return 0;
> +
> +err:
> + regmap_write(data->regmap, DPS310_RESET, DPS310_RESET_MAGIC);
> + return r;
> +}
> +
> +static int dps310_remove(struct i2c_client *client)
> +{
> + struct dps310_data *data = i2c_get_clientdata(client);
> +
> + return regmap_write(data->regmap, DPS310_RESET, DPS310_RESET_MAGIC);
> +}
> +
> +static const struct i2c_device_id dps310_id[] = {
> + { "dps310", 0 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(i2c, dps310_id);
> +
> +static const unsigned short normal_i2c[] = {
> + 0x77, 0x76, I2C_CLIENT_END
> +};
> +
> +static struct i2c_driver dps310_driver = {
> + .driver = {
> + .name = "dps310",
> + },
> + .probe = dps310_probe,
> + .remove = dps310_remove,
> + .address_list = normal_i2c,
> + .id_table = dps310_id,
> +};
> +module_i2c_driver(dps310_driver);
> +
> +MODULE_AUTHOR("Joel Stanley ");
> +MODULE_DESCRIPTION("Infineon DPS310 pressure and temperature sensor");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH v2 3/3] iio: Add PAT9125 optical tracker sensor

2019-04-23 Thread Peter Meerwald-Stadler
a(client, indio_dev);
> +
> + dev_info(>dev, "%s: sensor '%s'\n",
> +  dev_name(_dev->dev),
> +  client->name);

please avoid log output, it just clutters the log

> +
> + /* Make read to reset motion bit status */
> + ret = pat9125_read_delta(data);
> + if (ret) {
> + dev_err(>dev, "Read register failed");
> + return ret;
> + }
> +
> + /* Init GPIO IRQ */
> + if (client->irq) {
> + ret = devm_request_threaded_irq(>dev,
> +   client->irq,
> +   pat9125_event_handler,
> +   NULL,
> +   IRQF_TRIGGER_FALLING,
> +   "pat9125",
> +   indio_dev);
> + if (ret) {
> + dev_err(>dev, "GPIO IRQ init failed");
> + return ret;
> + }
> + }
> + return 0;
> +}
> +
> +static int pat9125_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = devm_iio_device_alloc(>dev, 
> sizeof(struct pat9125_data));
> +
> + iio_device_unregister(indio_dev);
> + iio_triggered_buffer_cleanup(indio_dev);
> +
> + dev_info(>dev, "PAT9125 removed\n");
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id pat9125_id[] = {
> + { "pat9125", 0 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(i2c, pat9125_id);
> +
> +static const unsigned short normal_i2c[] = {
> + PAT9125_I2C_ADDR_HI,
> + PAT9125_I2C_ADDR_LO,
> + PAT9125_I2C_ADDR_NC,
> + I2C_CLIENT_END
> +};
> +
> +static struct i2c_driver pat9125_driver = {
> + .driver = {
> + .name = "pat9125",
> + },
> + .probe = pat9125_probe,
> + .remove = pat9125_remove,
> + .address_list = normal_i2c,
> + .id_table = pat9125_id,
> +};
> +
> +module_i2c_driver(pat9125_driver);
> +
> +MODULE_AUTHOR("Alexandre Mergnat ");
> +MODULE_DESCRIPTION("Optical Tracking sensor");
> +MODULE_LICENSE("GPL");
> \ No newline at end of file
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH v2 2/3] dt-bindings: iio: ot: Add docs pat9125

2019-04-23 Thread Peter Meerwald-Stadler


> Add documentation for the optical tracker PAT9125 and
> "ot" directory for Optical Tracker chip.
> 
> Signed-off-by: Alexandre Mergnat 
> ---
>  .../devicetree/bindings/iio/ot/pat9125.txt | 18 ++
>  1 file changed, 18 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/ot/pat9125.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/ot/pat9125.txt 
> b/Documentation/devicetree/bindings/iio/ot/pat9125.txt
> new file mode 100644
> index ..2ffacaafba8e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/ot/pat9125.txt
> @@ -0,0 +1,18 @@
> +PixArt Imaging PAT9125 Optical Tracking Miniature Chip device driver
> +
> +Required properties:
> + - compatible: must be "pixart,pat9125"
> + - reg: i2c address where to find the device
> + - interrupts : the sole interrupt generated by the device

maybe delete space before :

> +
> + Refer to interrupt-controller/interrupts.txt for generic
> + interrupt client node bindings.
> +
> +Example:
> +
> +pat9125@75 {
> + compatible = "pixart,pat9125";
> + reg = <0x75>;
> + interrupt-parent = <>;
> + interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
> +};
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 3/3] iio: light: apple-ib-als: Add driver for ALS on iBridge chip.

2019-04-22 Thread Peter Meerwald-Stadler
F_CHANGE_SENS;
> + als_dev->cur_sensitivity = APPLEALS_DEF_CHANGE_SENS;
> + appleals_config_sensor(als_dev, false, als_dev->cur_sensitivity);
> +
> + rc = appleals_config_iio(als_dev);
> + if (rc)
> + return rc;
> +
> + return 0;
> +}
> +
> +static void appleals_remove(struct hid_device *hdev)
> +{
> + struct appleals_device *als_dev =
> + appleib_get_drvdata(hid_get_drvdata(hdev),
> + _hid_driver);
> +

could be a lot less if devm_ were used?

> + if (als_dev->iio_dev) {
> + iio_device_unregister(als_dev->iio_dev);
> +
> + iio_trigger_unregister(als_dev->iio_trig);
> + iio_trigger_free(als_dev->iio_trig);
> + als_dev->iio_trig = NULL;
> +
> + iio_triggered_buffer_cleanup(als_dev->iio_dev);
> + iio_device_free(als_dev->iio_dev);
> + als_dev->iio_dev = NULL;
> + }
> +
> + als_dev->hid_dev = NULL;
> +}
> +
> +#ifdef CONFIG_PM
> +static int appleals_reset_resume(struct hid_device *hdev)
> +{
> + struct appleals_device *als_dev =
> + appleib_get_drvdata(hid_get_drvdata(hdev),
> + _hid_driver);
> +
> + appleals_config_sensor(als_dev, als_dev->events_enabled,
> +als_dev->cur_sensitivity);
> +
> + return 0;
> +}
> +#endif
> +
> +static struct hid_driver appleals_hid_driver = {
> + .name = "apple-ib-als",
> + .probe = appleals_probe,
> + .remove = appleals_remove,
> + .event = appleals_hid_event,
> +#ifdef CONFIG_PM
> + .reset_resume = appleals_reset_resume,
> +#endif
> +};
> +
> +static int appleals_platform_probe(struct platform_device *pdev)
> +{
> + struct appleib_platform_data *pdata = pdev->dev.platform_data;
> + struct appleib_device *ib_dev = pdata->ib_dev;
> + struct appleals_device *als_dev;
> + int rc;
> +
> + als_dev = kzalloc(sizeof(*als_dev), GFP_KERNEL);
> + if (!als_dev)
> + return -ENOMEM;
> +
> + als_dev->ib_dev = ib_dev;
> + als_dev->log_dev = pdata->log_dev;
> +
> + rc = appleib_register_hid_driver(ib_dev, _hid_driver, als_dev);
> + if (rc) {
> + dev_err(als_dev->log_dev, "Error registering hid driver: %d\n",
> + rc);
> + goto error;
> + }
> +
> + platform_set_drvdata(pdev, als_dev);
> +
> + return 0;
> +
> +error:
> + kfree(als_dev);
> + return rc;
> +}
> +
> +static int appleals_platform_remove(struct platform_device *pdev)
> +{
> + struct appleib_platform_data *pdata = pdev->dev.platform_data;
> + struct appleib_device *ib_dev = pdata->ib_dev;
> + struct appleals_device *als_dev = platform_get_drvdata(pdev);
> + int rc;
> +
> + rc = appleib_unregister_hid_driver(ib_dev, _hid_driver);
> + if (rc) {
> + dev_err(als_dev->log_dev,
> + "Error unregistering hid driver: %d\n", rc);
> + goto error;
> + }
> +
> + kfree(als_dev);
> +
> + return 0;
> +
> +error:
> + return rc;
> +}
> +
> +static const struct platform_device_id appleals_platform_ids[] = {
> + { .name = PLAT_NAME_IB_ALS },
> + { }
> +};
> +MODULE_DEVICE_TABLE(platform, appleals_platform_ids);
> +
> +static struct platform_driver appleals_platform_driver = {
> + .id_table = appleals_platform_ids,
> + .driver = {
> + .name   = "apple-ib-als",
> + },
> + .probe = appleals_platform_probe,
> + .remove = appleals_platform_remove,
> +};
> +
> +module_platform_driver(appleals_platform_driver);
> +
> +MODULE_AUTHOR("Ronald Tschalär");
> +MODULE_DESCRIPTION("Apple iBridge ALS driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH v2 3/4] mb12x2.c: add distance iio sensor with i2c

2019-03-03 Thread Peter Meerwald-Stadler
 data->gpiod_status = devm_gpiod_get(dev, "status", GPIOD_IN);
> + if (IS_ERR(data->gpiod_status)) {
> + if (PTR_ERR(data->gpiod_status) == -ENOENT) {
> + dev_warn(dev, "no status gpio --> use sleep instead\n");
> + data->gpiod_status = NULL;
> + } else {
> + dev_err(dev, "cannot setup gpio; err=%ld\n",
> + PTR_ERR(data->gpiod_status));
> + return PTR_ERR(data->gpiod_status);
> + }
> + }
> +
> + if (data->gpiod_status) {
> + data->irqnr = gpiod_to_irq(data->gpiod_status);
> + if (data->irqnr < 0) {
> + dev_err(dev, "gpiod_to_irq: %d\n", data->irqnr);
> + return data->irqnr;
> + }
> +
> + ret = devm_request_irq(dev, data->irqnr, mb12x2_handle_irq,
> + IRQF_TRIGGER_FALLING, id->name, indio_dev);
> + if (ret < 0) {
> + dev_err(dev, "request_irq: %d\n", ret);
> + return ret;
> + }
> + }
> +
> + ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
> + iio_pollfunc_store_time, mb12x2_trigger_handler, NULL);
> + if (ret < 0) {
> + dev_err(dev, "setup of iio triggered buffer failed\n");
> + return ret;
> + }
> +
> + return devm_iio_device_register(dev, indio_dev);
> +}
> +
> +static const struct of_device_id of_mb12x2_match[] = {
> + { .compatible = "maxbotix,i2cxl", },
> + {},
> +};
> +
> +MODULE_DEVICE_TABLE(of, of_mb12x2_match);
> +
> +static const struct i2c_device_id mb12x2_id[] = {
> + { "maxbotix-i2cxl", },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, mb12x2_id);
> +
> +static struct i2c_driver mb12x2_driver = {
> + .driver = {
> + .name   = "maxbotix-i2cxl",
> + .of_match_table = of_mb12x2_match,
> + },
> + .probe = mb12x2_probe,
> + .id_table = mb12x2_id,
> +};
> +module_i2c_driver(mb12x2_driver);
> +
> +MODULE_AUTHOR("Andreas Klinger ");
> +MODULE_DESCRIPTION("Maxbotix I2CXL-MaxSonar i2c ultrasonic ranger driver");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 3/4] mb12x2.c: add mb12x2 ultrasonic distance iio sensor

2019-02-25 Thread Peter Meerwald-Stadler
o_push_to_buffers_with_timestamp(indio_dev,
> + data->buffer, pf->timestamp);
> +
> + mutex_unlock(>lock);
> +err:
> + iio_trigger_notify_done(indio_dev->trig);
> + return IRQ_HANDLED;
> +}
> +
> +static int mb12x2_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *channel, int *val,
> + int *val2, long mask)
> +{
> + struct mb12x2_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + if (channel->type != IIO_DISTANCE)
> + return -EINVAL;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_RAW:
> + ret = mb12x2_read_distance(data);
> + if (ret < 0)
> + return ret;
> + *val = ret;
> + return IIO_VAL_INT;
> + case IIO_CHAN_INFO_SCALE:
> + /* 1 LSB is 1 cm */
> + *val = 0;
> + *val2 = 1;
> + return IIO_VAL_INT_PLUS_MICRO;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static const struct iio_chan_spec mb12x2_channels[] = {
> + {
> + .type = IIO_DISTANCE,
> + .info_mask_separate =
> + BIT(IIO_CHAN_INFO_RAW) |
> + BIT(IIO_CHAN_INFO_SCALE),
> + .scan_index = 0,
> + .scan_type = {
> + .sign = 's',
> + .realbits = 16,
> + .storagebits = 16,
> + .endianness = IIO_CPU,
> + },
> + },
> + IIO_CHAN_SOFT_TIMESTAMP(1),
> +};
> +
> +static const struct iio_info mb12x2_info = {
> + .read_raw = mb12x2_read_raw,
> +};
> +
> +static int mb12x2_probe(struct i2c_client *client,
> +  const struct i2c_device_id *id)
> +{
> + struct iio_dev *indio_dev;
> + struct mb12x2_data *data;
> + int ret;
> + struct device *dev = >dev;
> +
> + if (!i2c_check_functionality(client->adapter,
> + I2C_FUNC_SMBUS_READ_BYTE |
> + I2C_FUNC_SMBUS_WRITE_BYTE))
> + return -ENODEV;
> +
> + indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + data = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + data->client = client;
> +
> + indio_dev->info = _info;
> + indio_dev->name = id->name;
> + indio_dev->dev.parent = dev;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = mb12x2_channels;
> + indio_dev->num_channels = ARRAY_SIZE(mb12x2_channels);
> +
> + mutex_init(>lock);
> +
> + init_completion(>ranging);
> +
> + data->gpiod_status = devm_gpiod_get(dev, "status", GPIOD_IN);
> + if (IS_ERR(data->gpiod_status)) {

I'd rather not do a newline at the start of a block (matter of taste)
> +
> + if (PTR_ERR(data->gpiod_status) == -ENOENT) {
> +
> + dev_warn(dev, "no status gpio --> use sleep instead\n");
> + data->gpiod_status = NULL;
> + } else {
> +
> + dev_err(dev, "cannot setup gpio; err=%ld\n",
> + PTR_ERR(data->gpiod_status));
> + return PTR_ERR(data->gpiod_status);
> + }
> + }
> +
> + if (data->gpiod_status) {
> +
> + data->irqnr = gpiod_to_irq(data->gpiod_status);
> + if (data->irqnr < 0) {
> + dev_err(dev, "gpiod_to_irq: %d\n", data->irqnr);
> + return data->irqnr;
> + }
> +
> + ret = devm_request_irq(dev, data->irqnr, mb12x2_handle_irq,
> + IRQF_TRIGGER_FALLING, id->name, indio_dev);
> + if (ret < 0) {
> + dev_err(dev, "request_irq: %d\n", ret);
> + return ret;
> + }
> + }
> +
> + ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
> + iio_pollfunc_store_time, mb12x2_trigger_handler, NULL);
> + if (ret < 0) {
> + dev_err(dev, "setup of iio triggered buffer failed\n");
> + return ret;
> + }
> +
> + return devm_iio_device_register(dev, indio_dev);
> +}
> +
> +static const struct of_device_id of_mb12x2_match[] = {
> + { .compatible = "maxbotix,mb12x2", },
> + {},
> +};
> +
> +MODULE_DEVICE_TABLE(of, of_mb12x2_match);
> +
> +static const struct i2c_device_id mb12x2_id[] = {
> + { "maxbotix-mb12x2", },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, mb12x2_id);
> +
> +static struct i2c_driver mb12x2_driver = {
> + .driver = {
> + .name   = "maxbotix-mb12x2",
> + .of_match_table = of_mb12x2_match,
> + },
> + .probe = mb12x2_probe,
> + .id_table = mb12x2_id,
> +};
> +module_i2c_driver(mb12x2_driver);
> +
> +MODULE_AUTHOR("Andreas Klinger ");
> +MODULE_DESCRIPTION("Maxbotix I2CXL-MB12X2-EZ i2c ultrasonic ranger driver");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 2/4] iio/proximity: add mb12x2 driver to Kconfig and Makefile

2019-02-25 Thread Peter Meerwald-Stadler
On Sun, 24 Feb 2019, Andreas Klinger wrote:

> Makefile and Kconfig: add configuration for mb12x2 ultrasonic proximity
> driver
> 

> diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
> index 6d031f903c4c..c56b72a8be87 100644
> --- a/drivers/iio/proximity/Makefile
> +++ b/drivers/iio/proximity/Makefile
> @@ -6,6 +6,7 @@
>  # When adding new entries keep the list in alphabetical order
>  obj-$(CONFIG_AS3935) += as3935.o
>  obj-$(CONFIG_ISL29501)   += isl29501.o
> +obj-$(CONFIG_MB12X2) += mb12x2.o

alphabetic order please

>  obj-$(CONFIG_LIDAR_LITE_V2)  += pulsedlight-lidar-lite-v2.o
>  obj-$(CONFIG_RFD77402)   += rfd77402.o
>  obj-$(CONFIG_SRF04)  += srf04.o
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 1/3] iio: light: Add driver for ap3216c

2019-02-11 Thread Peter Meerwald-Stadler
  ret = ap3216c_clear_int(data);
> + if (ret < 0)
> + dev_err(>client->dev, "error clearing IRQ\n");
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int ap3216c_probe(struct i2c_client *client,
> +   const struct i2c_device_id *id)
> +{
> + struct ap3216c_data *data;
> + struct iio_dev *indio_dev;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + data = iio_priv(indio_dev);
> + data->client = client;
> + indio_dev->dev.parent = >dev;
> + indio_dev->info = _info;
> + indio_dev->name = AP3216C_DRV_NAME;
> + indio_dev->channels = ap3216c_channels;
> + indio_dev->num_channels = ARRAY_SIZE(ap3216c_channels);
> +
> + data->regmap = devm_regmap_init_i2c(client, _regmap_config);
> + if (IS_ERR(data->regmap)) {
> + dev_err(>dev, "Failed to allocate register map\n");
> + return PTR_ERR(data->regmap);
> + }
> +
> + /* Default to thresh events disabled */
> + data->als_thresh_en = false;
> + data->prox_thresh_en = false;
> +
> + /*
> +  * Require that that the interrupt is cleared only when the INT

that that

> +  * register is written to, instead of when data is read.  This
> +  * prevents the interrupt from falsely reporting IRQ_NONE.
> +  */
> + ret = regmap_write(data->regmap,
> +AP3216C_INT_CLR, AP3216C_INT_CLR_MANUAL);
> + if (ret < 0)
> + return ret;
> +
> + /* Before setting up IRQ, clear any stale interrupt */
> + ret = ap3216c_clear_int(data);
> + if (ret < 0)
> + return ret;
> +
> + if (client->irq) {
> + ret = devm_request_threaded_irq(>dev, client->irq,
> + NULL, ap3216c_event_handler,
> + IRQF_TRIGGER_FALLING |
> + IRQF_SHARED | IRQF_ONESHOT,
> + client->name, indio_dev);
> + if (ret)
> + return ret;
> + }
> +
> + /* Enable ALS and PS+IR */
> + ret = regmap_write(data->regmap, AP3216C_SYS, AP3216C_SYS_MODE_ALS_PS);
> + if (ret < 0)
> + return ret;
> +
> + return devm_iio_device_register(>dev, indio_dev);
> +}
> +
> +static const struct of_device_id ap3216c_of_match[] = {
> + { .compatible = "liteon,ap3216c", },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, ap3216c_of_match);
> +
> +static const struct i2c_device_id ap3216c_id[] = {
> + {"ap3216c", 0},
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, ap3216c_id);
> +
> +static struct i2c_driver ap3216c_driver = {
> + .driver = {
> + .name   = AP3216C_DRV_NAME,
> + },
> + .probe  = ap3216c_probe,
> + .id_table   = ap3216c_id,
> +};
> +module_i2c_driver(ap3216c_driver);
> +
> +MODULE_AUTHOR("Robert Eshleman ");
> +MODULE_DESCRIPTION("APC3216C Ambient Light and Proximity Sensor");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v3 1/4] staging: iio: ad7780: add gain & filter gpio support

2019-02-05 Thread Peter Meerwald-Stadler
   unsigned int raw_sample)
> {
> @@ -126,10 +187,8 @@ static int ad7780_postprocess_sample(struct
> ad_sigma_delta *sigma_delta,
>   return -EIO;
> 
>   if (chip_info->is_ad778x) {
> - if (raw_sample & AD7780_GAIN)
> - st->gain = 1;
> - else
> - st->gain = 128;
> + st->gain = ad778x_gain[raw_sample & AD7780_GAIN];
> + st->odr = ad778x_odr_avail[raw_sample & AD7780_FILTER];
>   }
> 
>   return 0;
> @@ -173,6 +232,7 @@ static const struct ad7780_chip_info
> ad7780_chip_info_tbl[] = {
> 
> static const struct iio_info ad7780_info = {
>   .read_raw = ad7780_read_raw,
> + .write_raw = ad7780_write_raw,
> };
> 
> static int ad7780_probe(struct spi_device *spi)
> @@ -222,6 +282,29 @@ static int ad7780_probe(struct spi_device *spi)
>   goto error_disable_reg;
>   }
> 
> + if (st->chip_info->is_ad778x) {
> + st->gain_gpio = devm_gpiod_get_optional(>dev,
> + "gain",
> + GPIOD_OUT_HIGH);
> + if (IS_ERR(st->gain_gpio)) {
> + ret = PTR_ERR(st->gain_gpio);
> + dev_err(>dev, "Failed to request gain GPIO:
> %d\n",
> + ret);
> + goto error_disable_reg;
> + }
> +
> + st->filter_gpio = devm_gpiod_get_optional(>dev,
> +   "filter",
> +   GPIOD_OUT_HIGH);
> + if (IS_ERR(st->filter_gpio)) {
> + ret = PTR_ERR(st->filter_gpio);
> + dev_err(>dev,
> + "Failed to request filter GPIO: %d\n",
> + ret);
> + goto error_disable_reg;
> + }
> + }
> +
>   ret = ad_sd_setup_buffer_and_trigger(indio_dev);
>   if (ret)
>   goto error_disable_reg;
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 1/3] iio: chemical: add support for Plantower PMS7003 sensor

2019-01-27 Thread Peter Meerwald-Stadler
 return 2;
> +
> + num = get_unaligned_be16(buf + 2);

2 is sizeof(MAGIC)

> + if (num <= PMS7003_MAX_DATA_LENGTH) {
> + frame->expected_length = num;
> + frame->length = 0;
> + }
> +
> + return 4;
> + }
> +
> + num = min(size, (size_t)(frame->expected_length - frame->length));
> + memcpy(frame->data + frame->length, buf, num);
> + frame->length += num;
> +
> + if (frame->length == frame->expected_length) {
> + if (pms7003_frame_is_okay(frame))
> + complete(>frame_ready);
> +
> + frame->expected_length = 0;
> + }
> +
> + return num;
> +}
> +
> +static const struct serdev_device_ops pms7003_serdev_ops = {
> + .receive_buf = pms7003_receive_buf,
> + .write_wakeup = serdev_device_write_wakeup,
> +};
> +
> +static void pms7003_stop(void *data)
> +{
> + struct pms7003_state *state = data;
> +
> + pms7003_do_cmd(state, CMD_SLEEP);
> +}
> +
> +static const unsigned long pms7003_scan_masks[] = { 0x07, 0x00 };
> +
> +static int pms7003_probe(struct serdev_device *serdev)
> +{
> + struct pms7003_state *state;
> + struct iio_dev *indio_dev;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*state));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + state = iio_priv(indio_dev);
> + serdev_device_set_drvdata(serdev, indio_dev);
> + state->serdev = serdev;
> + indio_dev->dev.parent = >dev;
> + indio_dev->info = _info;
> + indio_dev->name = PMS7003_DRIVER_NAME;
> + indio_dev->channels = pms7003_channels,
> + indio_dev->num_channels = ARRAY_SIZE(pms7003_channels);
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->available_scan_masks = pms7003_scan_masks;
> +
> + mutex_init(>lock);
> + init_completion(>frame_ready);
> +
> + serdev_device_set_client_ops(serdev, _serdev_ops);
> + ret = devm_serdev_device_open(>dev, serdev);
> + if (ret)
> + return ret;
> +
> + serdev_device_set_baudrate(serdev, 9600);
> + serdev_device_set_flow_control(serdev, false);
> +
> + ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
> + if (ret)
> + return ret;
> +
> + ret = pms7003_do_cmd(state, CMD_WAKEUP);
> + if (ret) {
> +     dev_err(>dev, "failed to wakeup sensor\n");
> + return ret;
> + }
> +
> + ret = pms7003_do_cmd(state, CMD_ENTER_PASSIVE_MODE);
> + if (ret) {
> + dev_err(>dev, "failed to enter passive mode\n");
> + return ret;
> + }
> +
> + ret = devm_add_action_or_reset(>dev, pms7003_stop, state);
> + if (ret)
> + return ret;
> +
> + ret = devm_iio_triggered_buffer_setup(>dev, indio_dev, NULL,
> +   pms7003_trigger_handler, NULL);
> + if (ret)
> + return ret;
> +
> + return devm_iio_device_register(>dev, indio_dev);
> +}
> +
> +static const struct of_device_id pms7003_of_match[] = {
> + { .compatible = "plantower,pms7003" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, pms7003_of_match);
> +
> +static struct serdev_device_driver pms7003_driver = {
> + .driver = {
> + .name = PMS7003_DRIVER_NAME,
> + .of_match_table = pms7003_of_match,
> + },
> + .probe = pms7003_probe,
> +};
> +module_serdev_device_driver(pms7003_driver);
> +
> +MODULE_AUTHOR("Tomasz Duszynski ");
> +MODULE_DESCRIPTION("Plantower PMS7003 particulate matter sensor driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: light: add driver support for MAX44009

2019-01-19 Thread Peter Meerwald-Stadler
 +  IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
> > +   IIO_EV_TYPE_THRESH, direction),
> > +  data->timestamp);
> > +
> > +   ret = max44009_write_reg(data, MAX44009_REG_ENABLE, 1);
> > +   if (ret < 0) {
> > +   goto err;
> > +   }
> > +
> > +   return IRQ_HANDLED;
> > +
> > +err:
> > +   /* Re-enable interrupt */
> > +   max44009_write_reg(data, MAX44009_REG_ENABLE, 1);
> > +   return IRQ_NONE;
> > +}
> > +
> > +static irqreturn_t max44009_irq_handler(int irq, void *p)
> > +{
> > +   struct iio_dev *indio_dev = p;
> > +   struct max44009_data *data = iio_priv(indio_dev);
> > +
> > +   data->timestamp = iio_get_time_ns(indio_dev);
> 
> We have a standard core function to do this..
> iio_pollfunc_store_time.
> 
> There 'might' be a reason to do it differently depending
> on whether you really need it to be that good if you
> can't identify whether it is your interrupt until the
> interrupt thread.
> 
> 
> > +   return IRQ_WAKE_THREAD;
> > +}
> > +
> > +static int max44009_probe(struct i2c_client *client,
> > + const struct i2c_device_id *id)
> > +{
> > +   struct max44009_data *data;
> > +   struct iio_dev *indio_dev;
> > +   int ret;
> > +
> > +   indio_dev = devm_iio_device_alloc(>dev, sizeof(*data));
> > +   if (!indio_dev) {
> > +   return -ENOMEM;
> > +   }
> > +   data = iio_priv(indio_dev);
> > +   i2c_set_clientdata(client, indio_dev);
> > +   data->client = client;
> > +   indio_dev->dev.parent = >dev;
> > +   indio_dev->info = _info;
> > +   indio_dev->modes = INDIO_DIRECT_MODE;
> > +   indio_dev->name = MAX44009_DRV_NAME;
> > +   indio_dev->channels = max44009_channels;
> > +   indio_dev->num_channels = ARRAY_SIZE(max44009_channels);
> > +   mutex_init(>lock);
> > +
> > +   /* Clear stale interrupt bit */
> > +   ret = max44009_read_reg(data, MAX44009_REG_STATUS);
> > +   if (ret < 0) {
> > +   goto err;
> > +   }
> > +
> > +   if (client->irq > 0) {
> > +   ret = devm_request_threaded_irq(>dev, client->irq,
> > +   max44009_irq_handler,
> 
> This is wrong. The interrupt handler should call the iio_trigger_poll 
> functions
> to cause the trigger handlers for all attached devices to be called.
> 
> If for some reason the trigger is only suitable for use by this device
> then things get more blurred, but if not, the interrupt handler itself
> should establish that the interrupt is the data ready signal and call
> iio_trigger_poll.  If it is in a thread, call iio_trigger_poll_chained.
> 
> The interrupt should be cleared (if it hasn't naturally happened for
> some other reason, in the trigger try_reenable callback.
> 
> 
> > +   max44009_trigger_handler,
> > +   IRQF_TRIGGER_FALLING |
> > +   IRQF_ONESHOT,
> > +   MAX44009_IRQ_NAME, indio_dev);
> > +   if (ret < 0) {
> > +   goto err;
> > +   }
> > +
> > +   ret = devm_iio_triggered_buffer_setup(>dev, indio_dev,
> > + max44009_irq_handler,
> > + max44009_trigger_handler,
> > + NULL);
> > +   if (ret < 0) {
> 
> It's going to change anyway (see below) but note kernel style is no
> brackets when only one item in an block like this.
> 
> > +   goto err;
> > +   }
> > +
> > +   data->trigger = devm_iio_trigger_alloc(indio_dev->dev.parent,
> > +  "%s-dev%d",
> > +  indio_dev->name,
> > +  indio_dev->id);
> > +   if (!data->trigger) {
> > +   ret = -ENOMEM;
> > +   goto err;
> > +   }
> > +   data->trigger->dev.parent = indio_dev->dev.parent;
> > +   data->trigger->ops = _trigger_ops;
> > +   iio_trigger_set_drvdata(data->trigger, indio_dev);
> > +
> > +   ret = devm_iio_trigger_register(>dev, data->trigger);
> > +   if (ret < 0) {
> > +   goto err;
> > +   }
> > +   }
> > +
> > +   ret = devm_iio_device_register(>dev, indio_dev);
> > +   if (ret < 0) {
> > +   goto err;
> 
> Without the mutex destroy these all just become return ret;
> 
> > +   }
> > +
> > +   return 0;
> > +err:
> > +   mutex_destroy(>lock);
> 
> mutex destroy is only really useful for lock debugging.  Given we don't
> leave anything behind here anyway, it just makes the flow more complex
> for no gain.  We very rarely bother with it as a result.
> 
> > +   return ret;
> > +}
> > +
> > +static const struct i2c_device_id max44009_id[] = {
> > +   { "max44009", 0 },
> > +   { }
> > +};
> > +MODULE_DEVICE_TABLE(i2c, max44009_id);
> > +
> > +static struct i2c_driver max44009_driver = {
> > +   .driver = {
> > +   .name = MAX44009_DRV_NAME,
> > +   },
> > +   .probe = max44009_probe,
> > +   .id_table = max44009_id,
> > +};
> > +module_i2c_driver(max44009_driver);
> > +
> > +static const struct of_device_id max44009_of_match[] = {
> > +   { .compatible = "maxim,max44009" },
> > +   { }
> > +};
> > +MODULE_DEVICE_TABLE(of, max44009_of_match);
> > +
> > +MODULE_AUTHOR("Robert Eshleman ");
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_VERSION("1.0.0");
> Please drop.  MODULE_VERSION provides very little useful info
> and tends to lead to people assuming it does.
> 
> Userspace has no obligation to ever look at it and we can't
> break userspace that doesn't so it doesn't provide any value.
> 
> > +MODULE_DESCRIPTION("MAX44009 ambient light sensor driver");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: magnetometer: Add support for PNI RM3100 9-axis magnetometer

2018-09-20 Thread Peter Meerwald-Stadler
 +
> +static struct i2c_driver rm3100_driver = {
> + .driver = {
> + .name = "rm3100-i2c",
> + .of_match_table = rm3100_dt_match,
> + },
> + .probe_new = rm3100_probe,
> + .remove = rm3100_remove,
> +};
> +module_i2c_driver(rm3100_driver);
> +
> +MODULE_AUTHOR("Song Qiang ");
> +MODULE_DESCRIPTION("PNI RM3100 9-axis magnetometer i2c driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/iio/magnetometer/rm3100-spi.c 
> b/drivers/iio/magnetometer/rm3100-spi.c
> new file mode 100644
> index ..2c7dd9e3a1a2
> --- /dev/null
> +++ b/drivers/iio/magnetometer/rm3100-spi.c
> @@ -0,0 +1,72 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Support for PNI RM3100 9-axis geomagnetic sensor a spi bus.
> + *
> + * Copyright (C) 2018 Song Qiang 
> + *
> + * User Manual available at
> + * <https://www.pnicorp.com/download/rm3100-user-manual/>
> + */
> +
> +#include 
> +
> +#include "rm3100.h"
> +
> +static const struct regmap_config rm3100_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> +
> + .rd_table = _readable_table,
> + .wr_table = _writable_table,
> + .volatile_table = _volatile_table,
> +
> + .read_flag_mask = 0x80,
> +
> + .cache_type = REGCACHE_RBTREE,
> +};
> +
> +static int rm3100_probe(struct spi_device *spi)
> +{
> + struct regmap *regmap;
> + int ret;
> +
> + /* Actually this device supports both mode 0 and mode 3. */
> + spi->mode = SPI_MODE_0;
> + /* data rates cannot exceeds 1Mbits. */

exceed

> + spi->max_speed_hz = 100;
> + spi->bits_per_word = 8;
> + ret = spi_setup(spi);
> + if (ret)
> + return ret;
> +
> + regmap =  devm_regmap_init_spi(spi, _regmap_config);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + return rm3100_common_probe(>dev, regmap, spi->irq);
> +}
> +
> +static int rm3100_remove(struct spi_device *spi)
> +{
> + return rm3100_common_remove(>dev);
> +}
> +
> +static const struct of_device_id rm3100_dt_match[] = {
> + { .compatible = "pni,rm3100-spi", },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, rm3100_dt_match);
> +
> +static struct spi_driver rm3100_driver = {
> + .driver = {
> + .name = "rm3100-spi",
> + .of_match_table = rm3100_dt_match,
> + },
> + .probe = rm3100_probe,
> + .remove = rm3100_remove,
> +};
> +module_spi_driver(rm3100_driver);
> +
> +MODULE_AUTHOR("Song Qiang ");
> +MODULE_DESCRIPTION("PNI RM3100 9-axis magnetometer spi driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/iio/magnetometer/rm3100.h 
> b/drivers/iio/magnetometer/rm3100.h
> new file mode 100644
> index ..5e30bc0f5149
> --- /dev/null
> +++ b/drivers/iio/magnetometer/rm3100.h
> @@ -0,0 +1,90 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Header file for PNI RM3100 driver
> + *
> + * Copyright (C) 2018 Song Qiang 
> + */
> +
> +#ifndef RM3100_CORE_H
> +#define RM3100_CORE_H
> +
> +#include 
> +#include 
> +
> +#define RM_REG_REV_ID0x36
> +
> +/* Cycle Count Registers MSBs and LSBs. */
> +#define RM_REG_CCXM  0x04
> +#define RM_REG_CCXL  0x05
> +#define RM_REG_CCYM  0x06
> +#define RM_REG_CCYL  0x07
> +#define RM_REG_CCZM  0x08
> +#define RM_REG_CCZL  0x09
> +
> +/* Single Measurement Mode register. */
> +#define RM_REG_POLL  0x00
> +#define RM_POLL_PMX  BIT(4)
> +#define RM_POLL_PMY  BIT(5)
> +#define RM_POLL_PMZ  BIT(6)
> +
> +/* Continues Measurement Mode register. */
> +#define RM_REG_CMM   0x01
> +#define RM_CMM_START BIT(0)
> +#define RM_CMM_DRDM  BIT(2)
> +#define RM_CMM_PMX   BIT(4)
> +#define RM_CMM_PMY   BIT(5)
> +#define RM_CMM_PMZ   BIT(6)
> +
> +/* TiMe Rate Configuration register. */
> +#define RM_REG_TMRC  0x0B
> +#define RM_TMRC_OFFSET   0x92
> +
> +/* Result Status register. */
> +#define RM_REG_STATUS0x34
> +#define RM_STATUS_DRDY   BIT(7)
> +
> +/* Measurement result registers. */
> +#define RM_REG_MX2   0x24
> +#define RM_REG_MX1   0x25
> +#define RM_REG_MX0   0x26
> +#define RM_REG_MY2   0x27
> +#define RM_REG_MY1   0x28
> +#define RM_REG_MY0   0x29
> +#define RM_REG_MZ2   0x2a
> +#define RM_REG_MZ1   0x2b
> +#define RM_REG_MZ0   0x2c
> +
> +#define RM_REG_HSHAKE0x35
> +
> +#define RM_W_REG_START   RM_REG_POLL
> +#define RM_W_REG_END RM_REG_REV_ID
> +#define RM_R_REG_START   RM_REG_POLL
> +#define RM_R_REG_END RM_REG_HSHAKE
> +#define RM_V_REG_START   RM_REG_MX2
> +#define RM_V_REG_END RM_REG_HSHAKE
> +
> +/* Built-In Self Test reigister. */
> +#define RM_REG_BIST  0x33
> +
> +struct rm3100_data {
> + struct device *dev;
> + struct regmap *regmap;
> + struct completion measuring_done;
> + bool use_interrupt;
> +
> + int conversion_time;
> +
> + /* To protect consistency of every measurement and sampling
> +  * frequency change operations.
> +  */
> + struct mutex lock;
> +};
> +
> +extern const struct regmap_access_table rm3100_readable_table;
> +extern const struct regmap_access_table rm3100_writable_table;
> +extern const struct regmap_access_table rm3100_volatile_table;
> +
> +int rm3100_common_probe(struct device *dev, struct regmap *regmap, int irq);
> +int rm3100_common_remove(struct device *dev);
> +
> +#endif /* RM3100_CORE_H */
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: magnetometer: Add support for PNI RM3100 9-axis magnetometer

2018-09-20 Thread Peter Meerwald-Stadler
 +
> +static struct i2c_driver rm3100_driver = {
> + .driver = {
> + .name = "rm3100-i2c",
> + .of_match_table = rm3100_dt_match,
> + },
> + .probe_new = rm3100_probe,
> + .remove = rm3100_remove,
> +};
> +module_i2c_driver(rm3100_driver);
> +
> +MODULE_AUTHOR("Song Qiang ");
> +MODULE_DESCRIPTION("PNI RM3100 9-axis magnetometer i2c driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/iio/magnetometer/rm3100-spi.c 
> b/drivers/iio/magnetometer/rm3100-spi.c
> new file mode 100644
> index ..2c7dd9e3a1a2
> --- /dev/null
> +++ b/drivers/iio/magnetometer/rm3100-spi.c
> @@ -0,0 +1,72 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Support for PNI RM3100 9-axis geomagnetic sensor a spi bus.
> + *
> + * Copyright (C) 2018 Song Qiang 
> + *
> + * User Manual available at
> + * <https://www.pnicorp.com/download/rm3100-user-manual/>
> + */
> +
> +#include 
> +
> +#include "rm3100.h"
> +
> +static const struct regmap_config rm3100_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> +
> + .rd_table = _readable_table,
> + .wr_table = _writable_table,
> + .volatile_table = _volatile_table,
> +
> + .read_flag_mask = 0x80,
> +
> + .cache_type = REGCACHE_RBTREE,
> +};
> +
> +static int rm3100_probe(struct spi_device *spi)
> +{
> + struct regmap *regmap;
> + int ret;
> +
> + /* Actually this device supports both mode 0 and mode 3. */
> + spi->mode = SPI_MODE_0;
> + /* data rates cannot exceeds 1Mbits. */

exceed

> + spi->max_speed_hz = 100;
> + spi->bits_per_word = 8;
> + ret = spi_setup(spi);
> + if (ret)
> + return ret;
> +
> + regmap =  devm_regmap_init_spi(spi, _regmap_config);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + return rm3100_common_probe(>dev, regmap, spi->irq);
> +}
> +
> +static int rm3100_remove(struct spi_device *spi)
> +{
> + return rm3100_common_remove(>dev);
> +}
> +
> +static const struct of_device_id rm3100_dt_match[] = {
> + { .compatible = "pni,rm3100-spi", },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, rm3100_dt_match);
> +
> +static struct spi_driver rm3100_driver = {
> + .driver = {
> + .name = "rm3100-spi",
> + .of_match_table = rm3100_dt_match,
> + },
> + .probe = rm3100_probe,
> + .remove = rm3100_remove,
> +};
> +module_spi_driver(rm3100_driver);
> +
> +MODULE_AUTHOR("Song Qiang ");
> +MODULE_DESCRIPTION("PNI RM3100 9-axis magnetometer spi driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/iio/magnetometer/rm3100.h 
> b/drivers/iio/magnetometer/rm3100.h
> new file mode 100644
> index ..5e30bc0f5149
> --- /dev/null
> +++ b/drivers/iio/magnetometer/rm3100.h
> @@ -0,0 +1,90 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Header file for PNI RM3100 driver
> + *
> + * Copyright (C) 2018 Song Qiang 
> + */
> +
> +#ifndef RM3100_CORE_H
> +#define RM3100_CORE_H
> +
> +#include 
> +#include 
> +
> +#define RM_REG_REV_ID0x36
> +
> +/* Cycle Count Registers MSBs and LSBs. */
> +#define RM_REG_CCXM  0x04
> +#define RM_REG_CCXL  0x05
> +#define RM_REG_CCYM  0x06
> +#define RM_REG_CCYL  0x07
> +#define RM_REG_CCZM  0x08
> +#define RM_REG_CCZL  0x09
> +
> +/* Single Measurement Mode register. */
> +#define RM_REG_POLL  0x00
> +#define RM_POLL_PMX  BIT(4)
> +#define RM_POLL_PMY  BIT(5)
> +#define RM_POLL_PMZ  BIT(6)
> +
> +/* Continues Measurement Mode register. */
> +#define RM_REG_CMM   0x01
> +#define RM_CMM_START BIT(0)
> +#define RM_CMM_DRDM  BIT(2)
> +#define RM_CMM_PMX   BIT(4)
> +#define RM_CMM_PMY   BIT(5)
> +#define RM_CMM_PMZ   BIT(6)
> +
> +/* TiMe Rate Configuration register. */
> +#define RM_REG_TMRC  0x0B
> +#define RM_TMRC_OFFSET   0x92
> +
> +/* Result Status register. */
> +#define RM_REG_STATUS0x34
> +#define RM_STATUS_DRDY   BIT(7)
> +
> +/* Measurement result registers. */
> +#define RM_REG_MX2   0x24
> +#define RM_REG_MX1   0x25
> +#define RM_REG_MX0   0x26
> +#define RM_REG_MY2   0x27
> +#define RM_REG_MY1   0x28
> +#define RM_REG_MY0   0x29
> +#define RM_REG_MZ2   0x2a
> +#define RM_REG_MZ1   0x2b
> +#define RM_REG_MZ0   0x2c
> +
> +#define RM_REG_HSHAKE0x35
> +
> +#define RM_W_REG_START   RM_REG_POLL
> +#define RM_W_REG_END RM_REG_REV_ID
> +#define RM_R_REG_START   RM_REG_POLL
> +#define RM_R_REG_END RM_REG_HSHAKE
> +#define RM_V_REG_START   RM_REG_MX2
> +#define RM_V_REG_END RM_REG_HSHAKE
> +
> +/* Built-In Self Test reigister. */
> +#define RM_REG_BIST  0x33
> +
> +struct rm3100_data {
> + struct device *dev;
> + struct regmap *regmap;
> + struct completion measuring_done;
> + bool use_interrupt;
> +
> + int conversion_time;
> +
> + /* To protect consistency of every measurement and sampling
> +  * frequency change operations.
> +  */
> + struct mutex lock;
> +};
> +
> +extern const struct regmap_access_table rm3100_readable_table;
> +extern const struct regmap_access_table rm3100_writable_table;
> +extern const struct regmap_access_table rm3100_volatile_table;
> +
> +int rm3100_common_probe(struct device *dev, struct regmap *regmap, int irq);
> +int rm3100_common_remove(struct device *dev);
> +
> +#endif /* RM3100_CORE_H */
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v4 1/3] iio: Add modifier for white light

2018-08-03 Thread Peter Meerwald-Stadler
Hello,

> > it is not clear to me why 'white' is needed;
> > isn't that the default, i.e. unfiltered light?
> 
> Yes, it is. But devices like vcnl4035 veml7700, White LED data one
> register and all other sources of light (like fluorescent,
> incandescent ,sunlight) in separate register.
> 
> So in such cases this WHITE modifier is needed. Should it needs to
> come under IIO_MOD_LIGHT_CLEAR?

it is a mess already :), there is 
_intensity
_intensity_ir
_intensity_both
_intensity_uv
_intensity_red
_intensity_green
_intensity_blue
_intensity_clear

I think that ir, uv, red, green, blue are filters for particular ranges 
of the spectrum

_intensity_clear might be unfiltered and _intensity might relate to the 
human eye photopic curve, I think the proposed white might be the same as 
clear?

'both' means ir + _intensity (not clearly specified)

regards, p.

> > > +KernelVersion:   4.18
> > > +Contact: linux-...@vger.kernel.org
> > > +Description:
> > > + Modifier white indicates that measurements contain white LED
> > > + component.
> > > +
> > >   What:   /sys/.../iio:deviceX/in_intensity_red_integration_time
> > >   What:
> > > /sys/.../iio:deviceX/in_intensity_green_integration_time
> > >   What:
> > > /sys/.../iio:deviceX/in_intensity_blue_integration_time
> > > diff --git a/drivers/iio/industrialio-core.c
> > > b/drivers/iio/industrialio-core.c
> > > index 19bdf3d2962a..cb939b9fad16 100644
> > > --- a/drivers/iio/industrialio-core.c
> > > +++ b/drivers/iio/industrialio-core.c
> > > @@ -108,6 +108,7 @@ static const char * const iio_modifier_names[] = {
> > >   [IIO_MOD_LIGHT_GREEN] = "green",
> > >   [IIO_MOD_LIGHT_BLUE] = "blue",
> > >   [IIO_MOD_LIGHT_UV] = "uv",
> > > + [IIO_MOD_LIGHT_WHITE] = "white",
> > >   [IIO_MOD_QUATERNION] = "quaternion",
> > >   [IIO_MOD_TEMP_AMBIENT] = "ambient",
> > >   [IIO_MOD_TEMP_OBJECT] = "object",
> > > diff --git a/include/uapi/linux/iio/types.h
> > > b/include/uapi/linux/iio/types.h
> > > index 4213cdf88e3c..de87a6c7e6de 100644
> > > --- a/include/uapi/linux/iio/types.h
> > > +++ b/include/uapi/linux/iio/types.h
> > > @@ -84,6 +84,7 @@ enum iio_modifier {
> > >   IIO_MOD_CO2,
> > >   IIO_MOD_VOC,
> > >   IIO_MOD_LIGHT_UV,
> > > + IIO_MOD_LIGHT_WHITE,
> > >   };
> > > enum iio_event_type {
> > > diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
> > > index b61245e1181d..a2f9c62a79dd 100644
> > > --- a/tools/iio/iio_event_monitor.c
> > > +++ b/tools/iio/iio_event_monitor.c
> > > @@ -96,6 +96,7 @@ static const char * const iio_modifier_names[] = {
> > >   [IIO_MOD_LIGHT_GREEN] = "green",
> > >   [IIO_MOD_LIGHT_BLUE] = "blue",
> > >   [IIO_MOD_LIGHT_UV] = "uv",
> > > + [IIO_MOD_LIGHT_WHITE] = "white",
> > >   [IIO_MOD_QUATERNION] = "quaternion",
> > >   [IIO_MOD_TEMP_AMBIENT] = "ambient",
> > >   [IIO_MOD_TEMP_OBJECT] = "object",
> > > @@ -178,6 +179,7 @@ static bool event_is_known(struct iio_event_data
> > > *event)
> > >   case IIO_MOD_LIGHT_GREEN:
> > >   case IIO_MOD_LIGHT_BLUE:
> > >   case IIO_MOD_LIGHT_UV:
> > > + case IIO_MOD_LIGHT_WHITE:
> > >   case IIO_MOD_QUATERNION:
> > >   case IIO_MOD_TEMP_AMBIENT:
> > >   case IIO_MOD_TEMP_OBJECT:
> > > 
> > 
> 
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v4 1/3] iio: Add modifier for white light

2018-08-03 Thread Peter Meerwald-Stadler
Hello,

> > it is not clear to me why 'white' is needed;
> > isn't that the default, i.e. unfiltered light?
> 
> Yes, it is. But devices like vcnl4035 veml7700, White LED data one
> register and all other sources of light (like fluorescent,
> incandescent ,sunlight) in separate register.
> 
> So in such cases this WHITE modifier is needed. Should it needs to
> come under IIO_MOD_LIGHT_CLEAR?

it is a mess already :), there is 
_intensity
_intensity_ir
_intensity_both
_intensity_uv
_intensity_red
_intensity_green
_intensity_blue
_intensity_clear

I think that ir, uv, red, green, blue are filters for particular ranges 
of the spectrum

_intensity_clear might be unfiltered and _intensity might relate to the 
human eye photopic curve, I think the proposed white might be the same as 
clear?

'both' means ir + _intensity (not clearly specified)

regards, p.

> > > +KernelVersion:   4.18
> > > +Contact: linux-...@vger.kernel.org
> > > +Description:
> > > + Modifier white indicates that measurements contain white LED
> > > + component.
> > > +
> > >   What:   /sys/.../iio:deviceX/in_intensity_red_integration_time
> > >   What:
> > > /sys/.../iio:deviceX/in_intensity_green_integration_time
> > >   What:
> > > /sys/.../iio:deviceX/in_intensity_blue_integration_time
> > > diff --git a/drivers/iio/industrialio-core.c
> > > b/drivers/iio/industrialio-core.c
> > > index 19bdf3d2962a..cb939b9fad16 100644
> > > --- a/drivers/iio/industrialio-core.c
> > > +++ b/drivers/iio/industrialio-core.c
> > > @@ -108,6 +108,7 @@ static const char * const iio_modifier_names[] = {
> > >   [IIO_MOD_LIGHT_GREEN] = "green",
> > >   [IIO_MOD_LIGHT_BLUE] = "blue",
> > >   [IIO_MOD_LIGHT_UV] = "uv",
> > > + [IIO_MOD_LIGHT_WHITE] = "white",
> > >   [IIO_MOD_QUATERNION] = "quaternion",
> > >   [IIO_MOD_TEMP_AMBIENT] = "ambient",
> > >   [IIO_MOD_TEMP_OBJECT] = "object",
> > > diff --git a/include/uapi/linux/iio/types.h
> > > b/include/uapi/linux/iio/types.h
> > > index 4213cdf88e3c..de87a6c7e6de 100644
> > > --- a/include/uapi/linux/iio/types.h
> > > +++ b/include/uapi/linux/iio/types.h
> > > @@ -84,6 +84,7 @@ enum iio_modifier {
> > >   IIO_MOD_CO2,
> > >   IIO_MOD_VOC,
> > >   IIO_MOD_LIGHT_UV,
> > > + IIO_MOD_LIGHT_WHITE,
> > >   };
> > > enum iio_event_type {
> > > diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
> > > index b61245e1181d..a2f9c62a79dd 100644
> > > --- a/tools/iio/iio_event_monitor.c
> > > +++ b/tools/iio/iio_event_monitor.c
> > > @@ -96,6 +96,7 @@ static const char * const iio_modifier_names[] = {
> > >   [IIO_MOD_LIGHT_GREEN] = "green",
> > >   [IIO_MOD_LIGHT_BLUE] = "blue",
> > >   [IIO_MOD_LIGHT_UV] = "uv",
> > > + [IIO_MOD_LIGHT_WHITE] = "white",
> > >   [IIO_MOD_QUATERNION] = "quaternion",
> > >   [IIO_MOD_TEMP_AMBIENT] = "ambient",
> > >   [IIO_MOD_TEMP_OBJECT] = "object",
> > > @@ -178,6 +179,7 @@ static bool event_is_known(struct iio_event_data
> > > *event)
> > >   case IIO_MOD_LIGHT_GREEN:
> > >   case IIO_MOD_LIGHT_BLUE:
> > >   case IIO_MOD_LIGHT_UV:
> > > + case IIO_MOD_LIGHT_WHITE:
> > >   case IIO_MOD_QUATERNION:
> > >   case IIO_MOD_TEMP_AMBIENT:
> > >   case IIO_MOD_TEMP_OBJECT:
> > > 
> > 
> 
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v4 2/3] iio: light: Add support for vishay vcnl4035

2018-08-02 Thread Peter Meerwald-Stadler
   }
> +
> + /* Trigger setup */
> + ret = iio_triggered_buffer_setup(indio_dev, NULL,
> + vcnl4035_trigger_consumer_handler,
> + NULL);
> + if (ret < 0) {
> + dev_err(>dev, "iio triggered buffer setup 
> failed\n");
> + goto fail_trigger_unregister;
> + }
> +
> + /* IRQ to trigger mapping */
> + ret = devm_request_threaded_irq(>dev, client->irq,
> + NULL, vcnl4035_drdy_irq_thread,
> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> + VCNL4035_IRQ_NAME, indio_dev);
> + if (ret < 0) {
> + dev_err(>dev, "request irq %d for trigger0 
> failed\n",
> + client->irq);
> + goto fail_buffer_clean;
> + }

the closing bracket seems to be mis-indented

> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + goto fail_buffer_clean;
> + return 0;
> +
> +fail_buffer_clean:
> + iio_triggered_buffer_cleanup(indio_dev);
> +fail_trigger_unregister:
> + iio_trigger_unregister(data->drdy_trigger0);
> +fail_pm_disable:
> + pm_runtime_disable(>dev);
> + pm_runtime_set_suspended(>dev);
> + pm_runtime_put_noidle(>dev);
> +fail_poweroff:
> + vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
> + return ret;
> +}
> +
> +static int vcnl4035_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> +
> + iio_triggered_buffer_cleanup(indio_dev);
> + iio_trigger_unregister(data->drdy_trigger0);
> + iio_device_unregister(indio_dev);
> +
> + pm_runtime_disable(>dev);
> + pm_runtime_set_suspended(>dev);
> + pm_runtime_put_noidle(>dev);
> +
> + return vcnl4035_set_als_power_state(iio_priv(indio_dev),
> + VCNL4035_MODE_ALS_DISABLE);
> +}
> +
> +#ifdef CONFIG_PM
> +static int vcnl4035_runtime_suspend(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
> + regcache_mark_dirty(data->regmap);
> +
> + return ret;
> +}
> +
> +static int vcnl4035_runtime_resume(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + regcache_sync(data->regmap);
> + ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
> + if (ret < 0)
> + return ret;
> + /* wait for 1 ALS integration cycle */
> + msleep(data->als_it_val * 100);
> +
> + return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops vcnl4035_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> + pm_runtime_force_resume)
> + SET_RUNTIME_PM_OPS(vcnl4035_runtime_suspend,
> +vcnl4035_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id vcnl4035_of_match[] = {
> + { .compatible = "vishay,vcnl4035", },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, vcnl4035_of_match);
> +
> +static const struct i2c_device_id vcnl4035_id[] = {
> + { "vcnl4035", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, vcnl4035_id);
> +
> +static struct i2c_driver vcnl4035_driver = {
> + .driver = {
> + .name   = VCNL4035_DRV_NAME,
> + .pm = _pm_ops,
> + .of_match_table = of_match_ptr(vcnl4035_of_match),
> + },
> + .probe  = vcnl4035_probe,
> + .remove = vcnl4035_remove,
> + .id_table = vcnl4035_id,
> +};
> +
> +module_i2c_driver(vcnl4035_driver);
> +
> +MODULE_AUTHOR("Parthiban Nallathambi ");
> +MODULE_DESCRIPTION("VCNL4035 Ambient Light Sensor driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v4 2/3] iio: light: Add support for vishay vcnl4035

2018-08-02 Thread Peter Meerwald-Stadler
   }
> +
> + /* Trigger setup */
> + ret = iio_triggered_buffer_setup(indio_dev, NULL,
> + vcnl4035_trigger_consumer_handler,
> + NULL);
> + if (ret < 0) {
> + dev_err(>dev, "iio triggered buffer setup 
> failed\n");
> + goto fail_trigger_unregister;
> + }
> +
> + /* IRQ to trigger mapping */
> + ret = devm_request_threaded_irq(>dev, client->irq,
> + NULL, vcnl4035_drdy_irq_thread,
> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> + VCNL4035_IRQ_NAME, indio_dev);
> + if (ret < 0) {
> + dev_err(>dev, "request irq %d for trigger0 
> failed\n",
> + client->irq);
> + goto fail_buffer_clean;
> + }

the closing bracket seems to be mis-indented

> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + goto fail_buffer_clean;
> + return 0;
> +
> +fail_buffer_clean:
> + iio_triggered_buffer_cleanup(indio_dev);
> +fail_trigger_unregister:
> + iio_trigger_unregister(data->drdy_trigger0);
> +fail_pm_disable:
> + pm_runtime_disable(>dev);
> + pm_runtime_set_suspended(>dev);
> + pm_runtime_put_noidle(>dev);
> +fail_poweroff:
> + vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
> + return ret;
> +}
> +
> +static int vcnl4035_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> +
> + iio_triggered_buffer_cleanup(indio_dev);
> + iio_trigger_unregister(data->drdy_trigger0);
> + iio_device_unregister(indio_dev);
> +
> + pm_runtime_disable(>dev);
> + pm_runtime_set_suspended(>dev);
> + pm_runtime_put_noidle(>dev);
> +
> + return vcnl4035_set_als_power_state(iio_priv(indio_dev),
> + VCNL4035_MODE_ALS_DISABLE);
> +}
> +
> +#ifdef CONFIG_PM
> +static int vcnl4035_runtime_suspend(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
> + regcache_mark_dirty(data->regmap);
> +
> + return ret;
> +}
> +
> +static int vcnl4035_runtime_resume(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + regcache_sync(data->regmap);
> + ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
> + if (ret < 0)
> + return ret;
> + /* wait for 1 ALS integration cycle */
> + msleep(data->als_it_val * 100);
> +
> + return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops vcnl4035_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> + pm_runtime_force_resume)
> + SET_RUNTIME_PM_OPS(vcnl4035_runtime_suspend,
> +vcnl4035_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id vcnl4035_of_match[] = {
> + { .compatible = "vishay,vcnl4035", },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, vcnl4035_of_match);
> +
> +static const struct i2c_device_id vcnl4035_id[] = {
> + { "vcnl4035", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, vcnl4035_id);
> +
> +static struct i2c_driver vcnl4035_driver = {
> + .driver = {
> + .name   = VCNL4035_DRV_NAME,
> + .pm = _pm_ops,
> + .of_match_table = of_match_ptr(vcnl4035_of_match),
> + },
> + .probe  = vcnl4035_probe,
> + .remove = vcnl4035_remove,
> + .id_table = vcnl4035_id,
> +};
> +
> +module_i2c_driver(vcnl4035_driver);
> +
> +MODULE_AUTHOR("Parthiban Nallathambi ");
> +MODULE_DESCRIPTION("VCNL4035 Ambient Light Sensor driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v4 1/3] iio: Add modifier for white light

2018-08-02 Thread Peter Meerwald-Stadler
Hello,

it is not clear to me why 'white' is needed; 
isn't that the default, i.e. unfiltered light?

thanks, regards, p.

> Signed-off-by: Parthiban Nallathambi 
> ---
>  Documentation/ABI/testing/sysfs-bus-iio | 7 +++
>  drivers/iio/industrialio-core.c | 1 +
>  include/uapi/linux/iio/types.h  | 1 +
>  tools/iio/iio_event_monitor.c   | 2 ++
>  4 files changed, 11 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
> b/Documentation/ABI/testing/sysfs-bus-iio
> index 731146c3b138..43e481aed5b2 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio
> +++ b/Documentation/ABI/testing/sysfs-bus-iio
> @@ -1312,6 +1312,13 @@ Description:
>   standardised CIE Erythemal Action Spectrum. UV index values 
> range
>   from 0 (low) to >=11 (extreme).
>  
> +What:/sys/.../iio:deviceX/in_intensityY_white_raw
> +KernelVersion:   4.18
> +Contact: linux-...@vger.kernel.org
> +Description:
> + Modifier white indicates that measurements contain white LED
> + component.
> +
>  What:/sys/.../iio:deviceX/in_intensity_red_integration_time
>  What:/sys/.../iio:deviceX/in_intensity_green_integration_time
>  What:/sys/.../iio:deviceX/in_intensity_blue_integration_time
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index 19bdf3d2962a..cb939b9fad16 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -108,6 +108,7 @@ static const char * const iio_modifier_names[] = {
>   [IIO_MOD_LIGHT_GREEN] = "green",
>   [IIO_MOD_LIGHT_BLUE] = "blue",
>   [IIO_MOD_LIGHT_UV] = "uv",
> + [IIO_MOD_LIGHT_WHITE] = "white",
>   [IIO_MOD_QUATERNION] = "quaternion",
>   [IIO_MOD_TEMP_AMBIENT] = "ambient",
>   [IIO_MOD_TEMP_OBJECT] = "object",
> diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
> index 4213cdf88e3c..de87a6c7e6de 100644
> --- a/include/uapi/linux/iio/types.h
> +++ b/include/uapi/linux/iio/types.h
> @@ -84,6 +84,7 @@ enum iio_modifier {
>   IIO_MOD_CO2,
>   IIO_MOD_VOC,
>   IIO_MOD_LIGHT_UV,
> + IIO_MOD_LIGHT_WHITE,
>  };
>  
>  enum iio_event_type {
> diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
> index b61245e1181d..a2f9c62a79dd 100644
> --- a/tools/iio/iio_event_monitor.c
> +++ b/tools/iio/iio_event_monitor.c
> @@ -96,6 +96,7 @@ static const char * const iio_modifier_names[] = {
>   [IIO_MOD_LIGHT_GREEN] = "green",
>   [IIO_MOD_LIGHT_BLUE] = "blue",
>   [IIO_MOD_LIGHT_UV] = "uv",
> + [IIO_MOD_LIGHT_WHITE] = "white",
>   [IIO_MOD_QUATERNION] = "quaternion",
>   [IIO_MOD_TEMP_AMBIENT] = "ambient",
>   [IIO_MOD_TEMP_OBJECT] = "object",
> @@ -178,6 +179,7 @@ static bool event_is_known(struct iio_event_data *event)
>   case IIO_MOD_LIGHT_GREEN:
>   case IIO_MOD_LIGHT_BLUE:
>   case IIO_MOD_LIGHT_UV:
> + case IIO_MOD_LIGHT_WHITE:
>   case IIO_MOD_QUATERNION:
>   case IIO_MOD_TEMP_AMBIENT:
>   case IIO_MOD_TEMP_OBJECT:
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v4 1/3] iio: Add modifier for white light

2018-08-02 Thread Peter Meerwald-Stadler
Hello,

it is not clear to me why 'white' is needed; 
isn't that the default, i.e. unfiltered light?

thanks, regards, p.

> Signed-off-by: Parthiban Nallathambi 
> ---
>  Documentation/ABI/testing/sysfs-bus-iio | 7 +++
>  drivers/iio/industrialio-core.c | 1 +
>  include/uapi/linux/iio/types.h  | 1 +
>  tools/iio/iio_event_monitor.c   | 2 ++
>  4 files changed, 11 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
> b/Documentation/ABI/testing/sysfs-bus-iio
> index 731146c3b138..43e481aed5b2 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio
> +++ b/Documentation/ABI/testing/sysfs-bus-iio
> @@ -1312,6 +1312,13 @@ Description:
>   standardised CIE Erythemal Action Spectrum. UV index values 
> range
>   from 0 (low) to >=11 (extreme).
>  
> +What:/sys/.../iio:deviceX/in_intensityY_white_raw
> +KernelVersion:   4.18
> +Contact: linux-...@vger.kernel.org
> +Description:
> + Modifier white indicates that measurements contain white LED
> + component.
> +
>  What:/sys/.../iio:deviceX/in_intensity_red_integration_time
>  What:/sys/.../iio:deviceX/in_intensity_green_integration_time
>  What:/sys/.../iio:deviceX/in_intensity_blue_integration_time
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index 19bdf3d2962a..cb939b9fad16 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -108,6 +108,7 @@ static const char * const iio_modifier_names[] = {
>   [IIO_MOD_LIGHT_GREEN] = "green",
>   [IIO_MOD_LIGHT_BLUE] = "blue",
>   [IIO_MOD_LIGHT_UV] = "uv",
> + [IIO_MOD_LIGHT_WHITE] = "white",
>   [IIO_MOD_QUATERNION] = "quaternion",
>   [IIO_MOD_TEMP_AMBIENT] = "ambient",
>   [IIO_MOD_TEMP_OBJECT] = "object",
> diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
> index 4213cdf88e3c..de87a6c7e6de 100644
> --- a/include/uapi/linux/iio/types.h
> +++ b/include/uapi/linux/iio/types.h
> @@ -84,6 +84,7 @@ enum iio_modifier {
>   IIO_MOD_CO2,
>   IIO_MOD_VOC,
>   IIO_MOD_LIGHT_UV,
> + IIO_MOD_LIGHT_WHITE,
>  };
>  
>  enum iio_event_type {
> diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
> index b61245e1181d..a2f9c62a79dd 100644
> --- a/tools/iio/iio_event_monitor.c
> +++ b/tools/iio/iio_event_monitor.c
> @@ -96,6 +96,7 @@ static const char * const iio_modifier_names[] = {
>   [IIO_MOD_LIGHT_GREEN] = "green",
>   [IIO_MOD_LIGHT_BLUE] = "blue",
>   [IIO_MOD_LIGHT_UV] = "uv",
> + [IIO_MOD_LIGHT_WHITE] = "white",
>   [IIO_MOD_QUATERNION] = "quaternion",
>   [IIO_MOD_TEMP_AMBIENT] = "ambient",
>   [IIO_MOD_TEMP_OBJECT] = "object",
> @@ -178,6 +179,7 @@ static bool event_is_known(struct iio_event_data *event)
>   case IIO_MOD_LIGHT_GREEN:
>   case IIO_MOD_LIGHT_BLUE:
>   case IIO_MOD_LIGHT_UV:
> + case IIO_MOD_LIGHT_WHITE:
>   case IIO_MOD_QUATERNION:
>   case IIO_MOD_TEMP_AMBIENT:
>   case IIO_MOD_TEMP_OBJECT:
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 4/6] iio:adxl372: Add FIFO and interrupts support

2018-08-01 Thread Peter Meerwald-Stadler
 > ADXL372_FIFO_SIZE)
> + st->watermark = (ADXL372_FIFO_SIZE  / st->fifo_set_size);
> +
> + st->fifo_mode = ADXL372_FIFO_STREAMED;
> +
> + ret = adxl372_configure_fifo(st);
> + if (ret < 0) {
> + st->fifo_mode = ADXL372_FIFO_BYPASSED;
> + adxl372_set_interrupts(st, 0, 0);
> + return ret;
> + }
> +
> + return iio_triggered_buffer_postenable(indio_dev);
> +}
> +
> +static int adxl372_buffer_predisable(struct iio_dev *indio_dev)
> +{
> + struct adxl372_state *st = iio_priv(indio_dev);
> +
> + adxl372_set_interrupts(st, 0, 0);
> + st->fifo_mode = ADXL372_FIFO_BYPASSED;
> + adxl372_configure_fifo(st);
> +
> + return iio_triggered_buffer_predisable(indio_dev);
> +}
> +
> +static const struct iio_buffer_setup_ops adxl372_buffer_ops = {
> + .postenable = adxl372_buffer_postenable,
> + .predisable = adxl372_buffer_predisable,
> +};
> +
> +static int adxl372_dready_trig_set_state(struct iio_trigger *trig,
> +  bool state)
> +{
> + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
> + struct adxl372_state *st = iio_priv(indio_dev);
> + unsigned long int mask = 0;
> +
> + if (state)
> + mask = ADXL372_INT1_MAP_FIFO_FULL_MSK;
> +
> + return adxl372_set_interrupts(st, mask, 0);
> +}
> +
> +static const struct iio_trigger_ops adxl372_trigger_ops = {
> + .set_trigger_state = adxl372_dready_trig_set_state,
> +};
> +
>  static const struct iio_info adxl372_info = {
>   .read_raw = adxl372_read_raw,
>   .debugfs_reg_access = _reg_access,
> + .hwfifo_set_watermark = adxl372_set_watermark,
>  };
>  
>  static const struct regmap_config adxl372_spi_regmap_config = {
> @@ -495,10 +819,11 @@ static int adxl372_probe(struct spi_device *spi)
>  
>   indio_dev->channels = adxl372_channels;
>   indio_dev->num_channels = ARRAY_SIZE(adxl372_channels);
> + indio_dev->available_scan_masks = adxl372_channel_masks;
>   indio_dev->dev.parent = >dev;
>   indio_dev->name = spi_get_device_id(spi)->name;
>   indio_dev->info = _info;
> - indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
>  
>   ret = adxl372_setup(st);
>   if (ret < 0) {
> @@ -506,6 +831,41 @@ static int adxl372_probe(struct spi_device *spi)
>   return ret;
>   }
>  
> + ret = devm_iio_triggered_buffer_setup(>spi->dev,
> +   indio_dev, NULL,
> +   adxl372_trigger_handler,
> +   _buffer_ops);
> + if (ret < 0)
> + return ret;
> +
> + iio_buffer_set_attrs(indio_dev->buffer, adxl372_fifo_attributes);
> +
> + if (st->spi->irq) {
> + st->dready_trig = devm_iio_trigger_alloc(>spi->dev,
> +  "%s-dev%d",
> +  indio_dev->name,
> +  indio_dev->id);
> + if (st->dready_trig == NULL)
> + return -ENOMEM;
> +
> + st->dready_trig->ops = _trigger_ops;
> + st->dready_trig->dev.parent = >spi->dev;
> + iio_trigger_set_drvdata(st->dready_trig, indio_dev);
> + ret = devm_iio_trigger_register(>spi->dev, st->dready_trig);
> + if (ret < 0)
> + return ret;
> +
> + indio_dev->trig = iio_trigger_get(st->dready_trig);
> +
> + ret = devm_request_threaded_irq(>spi->dev, st->spi->irq,
> + iio_trigger_generic_data_rdy_poll,
> + NULL,
> + IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> + indio_dev->name, st->dready_trig);
> + if (ret < 0)
> + return ret;
> + }
> +
>   return devm_iio_device_register(>spi->dev, indio_dev);
>  }
>  
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 4/6] iio:adxl372: Add FIFO and interrupts support

2018-08-01 Thread Peter Meerwald-Stadler
 > ADXL372_FIFO_SIZE)
> + st->watermark = (ADXL372_FIFO_SIZE  / st->fifo_set_size);
> +
> + st->fifo_mode = ADXL372_FIFO_STREAMED;
> +
> + ret = adxl372_configure_fifo(st);
> + if (ret < 0) {
> + st->fifo_mode = ADXL372_FIFO_BYPASSED;
> + adxl372_set_interrupts(st, 0, 0);
> + return ret;
> + }
> +
> + return iio_triggered_buffer_postenable(indio_dev);
> +}
> +
> +static int adxl372_buffer_predisable(struct iio_dev *indio_dev)
> +{
> + struct adxl372_state *st = iio_priv(indio_dev);
> +
> + adxl372_set_interrupts(st, 0, 0);
> + st->fifo_mode = ADXL372_FIFO_BYPASSED;
> + adxl372_configure_fifo(st);
> +
> + return iio_triggered_buffer_predisable(indio_dev);
> +}
> +
> +static const struct iio_buffer_setup_ops adxl372_buffer_ops = {
> + .postenable = adxl372_buffer_postenable,
> + .predisable = adxl372_buffer_predisable,
> +};
> +
> +static int adxl372_dready_trig_set_state(struct iio_trigger *trig,
> +  bool state)
> +{
> + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
> + struct adxl372_state *st = iio_priv(indio_dev);
> + unsigned long int mask = 0;
> +
> + if (state)
> + mask = ADXL372_INT1_MAP_FIFO_FULL_MSK;
> +
> + return adxl372_set_interrupts(st, mask, 0);
> +}
> +
> +static const struct iio_trigger_ops adxl372_trigger_ops = {
> + .set_trigger_state = adxl372_dready_trig_set_state,
> +};
> +
>  static const struct iio_info adxl372_info = {
>   .read_raw = adxl372_read_raw,
>   .debugfs_reg_access = _reg_access,
> + .hwfifo_set_watermark = adxl372_set_watermark,
>  };
>  
>  static const struct regmap_config adxl372_spi_regmap_config = {
> @@ -495,10 +819,11 @@ static int adxl372_probe(struct spi_device *spi)
>  
>   indio_dev->channels = adxl372_channels;
>   indio_dev->num_channels = ARRAY_SIZE(adxl372_channels);
> + indio_dev->available_scan_masks = adxl372_channel_masks;
>   indio_dev->dev.parent = >dev;
>   indio_dev->name = spi_get_device_id(spi)->name;
>   indio_dev->info = _info;
> - indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
>  
>   ret = adxl372_setup(st);
>   if (ret < 0) {
> @@ -506,6 +831,41 @@ static int adxl372_probe(struct spi_device *spi)
>   return ret;
>   }
>  
> + ret = devm_iio_triggered_buffer_setup(>spi->dev,
> +   indio_dev, NULL,
> +   adxl372_trigger_handler,
> +   _buffer_ops);
> + if (ret < 0)
> + return ret;
> +
> + iio_buffer_set_attrs(indio_dev->buffer, adxl372_fifo_attributes);
> +
> + if (st->spi->irq) {
> + st->dready_trig = devm_iio_trigger_alloc(>spi->dev,
> +  "%s-dev%d",
> +  indio_dev->name,
> +  indio_dev->id);
> + if (st->dready_trig == NULL)
> + return -ENOMEM;
> +
> + st->dready_trig->ops = _trigger_ops;
> + st->dready_trig->dev.parent = >spi->dev;
> + iio_trigger_set_drvdata(st->dready_trig, indio_dev);
> + ret = devm_iio_trigger_register(>spi->dev, st->dready_trig);
> + if (ret < 0)
> + return ret;
> +
> + indio_dev->trig = iio_trigger_get(st->dready_trig);
> +
> + ret = devm_request_threaded_irq(>spi->dev, st->spi->irq,
> + iio_trigger_generic_data_rdy_poll,
> + NULL,
> + IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> + indio_dev->name, st->dready_trig);
> + if (ret < 0)
> + return ret;
> + }
> +
>   return devm_iio_device_register(>spi->dev, indio_dev);
>  }
>  
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 1/3] iio: adc: add support for mcp3911

2018-07-21 Thread Peter Meerwald-Stadler
nel 1 into 16bit mode\n");
> + break;
> + default:
> + adc->width[1] = 24;
> + dev_info(>spi->dev, "invalid width for channel 1. Use 
> 24bit.\n");
> + break;
> + }
> +
> + return mcp3911_write(adc, MCP3911_REG_STATUSCOM, statuscomreg, 2);
> +}
> +
> +static int mcp3911_probe(struct spi_device *spi)
> +{
> + struct iio_dev *indio_dev;
> + struct mcp3911 *adc;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*adc));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + adc = iio_priv(indio_dev);
> + adc->spi = spi;
> + adc->np = spi->dev.of_node;
> +
> + ret = mcp3911_config_of(adc);
> + if (ret)
> + return ret;
> +
> + if (adc->vrefext) {
> + adc->vref = devm_regulator_get(>spi->dev, "vref");
> + if (IS_ERR(adc->vref))
> + return PTR_ERR(adc->vref);
> +
> + ret = regulator_enable(adc->vref);
> + if (ret < 0)
> + return ret;
> + }
> +
> + /* Store gain values to better calculate scale values */
> + mcp3911_get_hwgain(adc, 0, >gain[0]);
> + mcp3911_get_hwgain(adc, 1, >gain[1]);
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->dev.of_node = spi->dev.of_node;
> + indio_dev->name = spi_get_device_id(spi)->name;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> + spi_set_drvdata(spi, indio_dev);
> +
> + indio_dev->channels = mcp3911_channels;
> + indio_dev->num_channels = ARRAY_SIZE(mcp3911_channels);
> +
> + mutex_init(>lock);
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + goto reg_disable;
> +
> + return ret;
> +
> +reg_disable:
> + if (adc->vref)
> + regulator_disable(adc->vref);
> +
> + return ret;
> +}
> +
> +static int mcp3911_remove(struct spi_device *spi)
> +{
> + struct iio_dev *indio_dev = spi_get_drvdata(spi);
> + struct mcp3911 *adc = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> +
> + if (adc->vref)
> + regulator_disable(adc->vref);
> +
> + return 0;
> +}
> +
> +#if defined(CONFIG_OF)
> +static const struct of_device_id mcp3911_dt_ids[] = {
> + { .compatible = "microchip,mcp3911" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, mcp3911_dt_ids);
> +#endif
> +
> +static const struct spi_device_id mcp3911_id[] = {
> + { "mcp3911", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(spi, mcp3911_id);
> +
> +static struct spi_driver mcp3911_driver = {
> + .driver = {
> + .name = "mcp3911",
> + .of_match_table = of_match_ptr(mcp3911_dt_ids),
> + },
> + .probe = mcp3911_probe,
> + .remove = mcp3911_remove,
> + .id_table = mcp3911_id,
> +};
> +module_spi_driver(mcp3911_driver);
> +
> +MODULE_AUTHOR("Marcus Folkesson ");
> +MODULE_AUTHOR("Kent Gustavsson ");
> +MODULE_DESCRIPTION("Microchip Technology MCP3911");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 1/3] iio: adc: add support for mcp3911

2018-07-21 Thread Peter Meerwald-Stadler
nel 1 into 16bit mode\n");
> + break;
> + default:
> + adc->width[1] = 24;
> + dev_info(>spi->dev, "invalid width for channel 1. Use 
> 24bit.\n");
> + break;
> + }
> +
> + return mcp3911_write(adc, MCP3911_REG_STATUSCOM, statuscomreg, 2);
> +}
> +
> +static int mcp3911_probe(struct spi_device *spi)
> +{
> + struct iio_dev *indio_dev;
> + struct mcp3911 *adc;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*adc));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + adc = iio_priv(indio_dev);
> + adc->spi = spi;
> + adc->np = spi->dev.of_node;
> +
> + ret = mcp3911_config_of(adc);
> + if (ret)
> + return ret;
> +
> + if (adc->vrefext) {
> + adc->vref = devm_regulator_get(>spi->dev, "vref");
> + if (IS_ERR(adc->vref))
> + return PTR_ERR(adc->vref);
> +
> + ret = regulator_enable(adc->vref);
> + if (ret < 0)
> + return ret;
> + }
> +
> + /* Store gain values to better calculate scale values */
> + mcp3911_get_hwgain(adc, 0, >gain[0]);
> + mcp3911_get_hwgain(adc, 1, >gain[1]);
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->dev.of_node = spi->dev.of_node;
> + indio_dev->name = spi_get_device_id(spi)->name;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> + spi_set_drvdata(spi, indio_dev);
> +
> + indio_dev->channels = mcp3911_channels;
> + indio_dev->num_channels = ARRAY_SIZE(mcp3911_channels);
> +
> + mutex_init(>lock);
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + goto reg_disable;
> +
> + return ret;
> +
> +reg_disable:
> + if (adc->vref)
> + regulator_disable(adc->vref);
> +
> + return ret;
> +}
> +
> +static int mcp3911_remove(struct spi_device *spi)
> +{
> + struct iio_dev *indio_dev = spi_get_drvdata(spi);
> + struct mcp3911 *adc = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> +
> + if (adc->vref)
> + regulator_disable(adc->vref);
> +
> + return 0;
> +}
> +
> +#if defined(CONFIG_OF)
> +static const struct of_device_id mcp3911_dt_ids[] = {
> + { .compatible = "microchip,mcp3911" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, mcp3911_dt_ids);
> +#endif
> +
> +static const struct spi_device_id mcp3911_id[] = {
> + { "mcp3911", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(spi, mcp3911_id);
> +
> +static struct spi_driver mcp3911_driver = {
> + .driver = {
> + .name = "mcp3911",
> + .of_match_table = of_match_ptr(mcp3911_dt_ids),
> + },
> + .probe = mcp3911_probe,
> + .remove = mcp3911_remove,
> + .id_table = mcp3911_id,
> +};
> +module_spi_driver(mcp3911_driver);
> +
> +MODULE_AUTHOR("Marcus Folkesson ");
> +MODULE_AUTHOR("Kent Gustavsson ");
> +MODULE_DESCRIPTION("Microchip Technology MCP3911");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 1/2] iio: light: Add support for vishay vcnl4035

2018-06-30 Thread Peter Meerwald-Stadler
data(data->drdy_trigger0, indio_dev);
> +
> + /* IRQ to trigger mapping */
> + ret = devm_request_threaded_irq(>dev, client->irq,
> + vcnl4035_drdy_irq_handler, vcnl4035_drdy_irq_thread,
> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> + VCNL4035_IRQ_NAME, indio_dev);
> + if (ret < 0) {
> + dev_err(>dev, "request irq %d for trigger0 
> failed\n",
> + client->irq);
> + goto fail_pm_disable;
> + }
> +
> + ret = devm_iio_trigger_register(indio_dev->dev.parent,
> + data->drdy_trigger0);
> + if (ret) {
> + dev_err(>dev, "iio trigger register failed\n");
> + goto fail_pm_disable;
> + }
> +
> + /* Trigger setup */
> + ret = devm_iio_triggered_buffer_setup(indio_dev->dev.parent,
> + indio_dev,
> + vcnl4035_trigger_consumer_store_time,
> + vcnl4035_trigger_consumer_handler,
> + NULL);
> + if (ret < 0) {
> + dev_err(>dev, "iio triggered buffer setup 
> failed\n");
> + goto fail_pm_disable;
> + }
> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + goto fail_pm_disable;
> + dev_info(>dev, "%s Ambient light/proximity sensor\n",

no need for this logging

> + VCNL4035_DRV_NAME);
> + return 0;
> +
> +fail_pm_disable:
> + pm_runtime_disable(>dev);
> + pm_runtime_set_suspended(>dev);
> + pm_runtime_put_noidle(>dev);
> +fail_poweroff:
> + return vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);

I think we want to return the 'ret' value indicating the original failure, 
not the return value of vcnl4035_set_als_power_state() which is likely success

> +}
> +
> +static int vcnl4035_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> + iio_device_unregister(indio_dev);
> +
> + pm_runtime_disable(>dev);
> + pm_runtime_set_suspended(>dev);
> + pm_runtime_put_noidle(>dev);
> +
> + return vcnl4035_set_als_power_state(iio_priv(indio_dev),
> + VCNL4035_MODE_ALS_DISABLE);
> +}
> +
> +#ifdef CONFIG_PM
> +static int vcnl4035_runtime_suspend(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + mutex_lock(>lock);
> + ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
> + regcache_mark_dirty(data->regmap);
> + mutex_unlock(>lock);
> +
> + return ret;
> +}
> +
> +static int vcnl4035_runtime_resume(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + regcache_sync(data->regmap);
> + ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
> + if (ret < 0)
> + return ret;
> + /* wait for 1 ALS integration cycle */
> + msleep(data->als_it_val * 100);
> +
> + return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops vcnl4035_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> + pm_runtime_force_resume)
> + SET_RUNTIME_PM_OPS(vcnl4035_runtime_suspend,
> +vcnl4035_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id vcnl4035_of_match[] = {
> + { .compatible = "vishay,vcnl4035", },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, vcnl4035_of_match);
> +
> +static const struct i2c_device_id vcnl4035_id[] = {
> + { "vcnl4035", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, vcnl4035_id);
> +
> +static struct i2c_driver vcnl4035_driver = {
> + .driver = {
> + .name   = VCNL4035_DRV_NAME,
> + .pm = _pm_ops,
> + .of_match_table = of_match_ptr(vcnl4035_of_match),
> + },
> + .probe  = vcnl4035_probe,
> + .remove = vcnl4035_remove,
> + .id_table = vcnl4035_id,
> +};
> +
> +module_i2c_driver(vcnl4035_driver);
> +
> +MODULE_AUTHOR("Parthiban Nallathambi ");
> +MODULE_DESCRIPTION("VCNL4035 Ambient Light Sensor driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 1/2] iio: light: Add support for vishay vcnl4035

2018-06-30 Thread Peter Meerwald-Stadler
data(data->drdy_trigger0, indio_dev);
> +
> + /* IRQ to trigger mapping */
> + ret = devm_request_threaded_irq(>dev, client->irq,
> + vcnl4035_drdy_irq_handler, vcnl4035_drdy_irq_thread,
> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> + VCNL4035_IRQ_NAME, indio_dev);
> + if (ret < 0) {
> + dev_err(>dev, "request irq %d for trigger0 
> failed\n",
> + client->irq);
> + goto fail_pm_disable;
> + }
> +
> + ret = devm_iio_trigger_register(indio_dev->dev.parent,
> + data->drdy_trigger0);
> + if (ret) {
> + dev_err(>dev, "iio trigger register failed\n");
> + goto fail_pm_disable;
> + }
> +
> + /* Trigger setup */
> + ret = devm_iio_triggered_buffer_setup(indio_dev->dev.parent,
> + indio_dev,
> + vcnl4035_trigger_consumer_store_time,
> + vcnl4035_trigger_consumer_handler,
> + NULL);
> + if (ret < 0) {
> + dev_err(>dev, "iio triggered buffer setup 
> failed\n");
> + goto fail_pm_disable;
> + }
> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + goto fail_pm_disable;
> + dev_info(>dev, "%s Ambient light/proximity sensor\n",

no need for this logging

> + VCNL4035_DRV_NAME);
> + return 0;
> +
> +fail_pm_disable:
> + pm_runtime_disable(>dev);
> + pm_runtime_set_suspended(>dev);
> + pm_runtime_put_noidle(>dev);
> +fail_poweroff:
> + return vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);

I think we want to return the 'ret' value indicating the original failure, 
not the return value of vcnl4035_set_als_power_state() which is likely success

> +}
> +
> +static int vcnl4035_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> + iio_device_unregister(indio_dev);
> +
> + pm_runtime_disable(>dev);
> + pm_runtime_set_suspended(>dev);
> + pm_runtime_put_noidle(>dev);
> +
> + return vcnl4035_set_als_power_state(iio_priv(indio_dev),
> + VCNL4035_MODE_ALS_DISABLE);
> +}
> +
> +#ifdef CONFIG_PM
> +static int vcnl4035_runtime_suspend(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + mutex_lock(>lock);
> + ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
> + regcache_mark_dirty(data->regmap);
> + mutex_unlock(>lock);
> +
> + return ret;
> +}
> +
> +static int vcnl4035_runtime_resume(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct vcnl4035_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + regcache_sync(data->regmap);
> + ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
> + if (ret < 0)
> + return ret;
> + /* wait for 1 ALS integration cycle */
> + msleep(data->als_it_val * 100);
> +
> + return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops vcnl4035_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> + pm_runtime_force_resume)
> + SET_RUNTIME_PM_OPS(vcnl4035_runtime_suspend,
> +vcnl4035_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id vcnl4035_of_match[] = {
> + { .compatible = "vishay,vcnl4035", },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, vcnl4035_of_match);
> +
> +static const struct i2c_device_id vcnl4035_id[] = {
> + { "vcnl4035", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, vcnl4035_id);
> +
> +static struct i2c_driver vcnl4035_driver = {
> + .driver = {
> + .name   = VCNL4035_DRV_NAME,
> + .pm = _pm_ops,
> + .of_match_table = of_match_ptr(vcnl4035_of_match),
> + },
> + .probe  = vcnl4035_probe,
> + .remove = vcnl4035_remove,
> + .id_table = vcnl4035_id,
> +};
> +
> +module_i2c_driver(vcnl4035_driver);
> +
> +MODULE_AUTHOR("Parthiban Nallathambi ");
> +MODULE_DESCRIPTION("VCNL4035 Ambient Light Sensor driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 2/2] iio: adc: Add Spreadtrum SC27XX PMICs ADC support

2018-06-13 Thread Peter Meerwald-Stadler
t; + dev_err(>dev, "failed to get match data\n");
> + return -EINVAL;
> + }
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*sc27xx_data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + sc27xx_data = iio_priv(indio_dev);
> +
> + sc27xx_data->regmap = dev_get_regmap(pdev->dev.parent, NULL);
> + if (!sc27xx_data->regmap) {
> + dev_err(>dev, "failed to get ADC regmap\n");
> + return -ENODEV;
> + }
> +
> + ret = of_property_read_u32(np, "reg", _data->base);
> + if (ret) {
> + dev_err(>dev, "failed to get ADC base address\n");
> + return ret;
> + }
> +
> + sc27xx_data->irq = platform_get_irq(pdev, 0);
> + if (sc27xx_data->irq < 0) {
> + dev_err(>dev, "failed to get ADC irq number\n");
> + return sc27xx_data->irq;
> + }
> +
> + ret = of_hwspin_lock_get_id(np, 0);
> + if (ret < 0) {
> + dev_err(>dev, "failed to get hwspinlock id\n");
> + return ret;
> + }
> +
> + sc27xx_data->hwlock = hwspin_lock_request_specific(ret);
> + if (!sc27xx_data->hwlock) {
> + dev_err(>dev, "failed to request hwspinlock\n");
> + return -ENXIO;
> + }
> +
> + init_completion(_data->completion);
> +
> + /*
> +  * Different PMIC ADC controllers can have differnt channel voltage

different

> +  * ratios, so we should save the implementation of getting voltage
> +  * ratio for corresponding PMIC ADC in the device data structure.
> +  */
> + sc27xx_data->get_volt_ratio = data;
> + sc27xx_data->dev = >dev;
> +
> + ret = sc27xx_adc_enable(sc27xx_data);
> + if (ret) {
> + dev_err(>dev, "failed to enable ADC module\n");
> + goto free_hwlock;
> + }
> +
> + ret = devm_request_threaded_irq(>dev, sc27xx_data->irq, NULL,
> + sc27xx_adc_isr, IRQF_ONESHOT,
> + pdev->name, sc27xx_data);
> + if (ret) {
> + dev_err(>dev, "failed to request ADC irq\n");
> + goto disable_adc;
> + }
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = dev_name(>dev);
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> + indio_dev->channels = sc27xx_channels;
> + indio_dev->num_channels = ARRAY_SIZE(sc27xx_channels);
> + ret = devm_iio_device_register(>dev, indio_dev);
> + if (ret) {
> + dev_err(>dev, "could not register iio (ADC)");
> + goto disable_adc;
> + }
> +
> + platform_set_drvdata(pdev, indio_dev);
> + return 0;
> +
> +disable_adc:
> + sc27xx_adc_disable(sc27xx_data);
> +free_hwlock:
> + hwspin_lock_free(sc27xx_data->hwlock);
> + return ret;
> +}
> +
> +static int sc27xx_adc_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct sc27xx_adc_data *sc27xx_data = iio_priv(indio_dev);
> +
> + sc27xx_adc_disable(sc27xx_data);
> + hwspin_lock_free(sc27xx_data->hwlock);
> + return 0;
> +}
> +
> +static const struct of_device_id sc27xx_adc_of_match[] = {
> + {
> + .compatible = "sprd,sc2731-adc",
> + .data = (void *)_adc_2731_ratio,
> + },
> + { }
> +};
> +
> +static struct platform_driver sc27xx_adc_driver = {
> + .probe = sc27xx_adc_probe,
> + .remove = sc27xx_adc_remove,
> + .driver = {
> + .name = "sc27xx-adc",
> + .of_match_table = sc27xx_adc_of_match,
> + },
> +};
> +
> +module_platform_driver(sc27xx_adc_driver);
> +
> +MODULE_AUTHOR("Freeman Liu ");
> +MODULE_DESCRIPTION("Spreadtrum SC27XX ADC Driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 2/2] iio: adc: Add Spreadtrum SC27XX PMICs ADC support

2018-06-13 Thread Peter Meerwald-Stadler
t; + dev_err(>dev, "failed to get match data\n");
> + return -EINVAL;
> + }
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*sc27xx_data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + sc27xx_data = iio_priv(indio_dev);
> +
> + sc27xx_data->regmap = dev_get_regmap(pdev->dev.parent, NULL);
> + if (!sc27xx_data->regmap) {
> + dev_err(>dev, "failed to get ADC regmap\n");
> + return -ENODEV;
> + }
> +
> + ret = of_property_read_u32(np, "reg", _data->base);
> + if (ret) {
> + dev_err(>dev, "failed to get ADC base address\n");
> + return ret;
> + }
> +
> + sc27xx_data->irq = platform_get_irq(pdev, 0);
> + if (sc27xx_data->irq < 0) {
> + dev_err(>dev, "failed to get ADC irq number\n");
> + return sc27xx_data->irq;
> + }
> +
> + ret = of_hwspin_lock_get_id(np, 0);
> + if (ret < 0) {
> + dev_err(>dev, "failed to get hwspinlock id\n");
> + return ret;
> + }
> +
> + sc27xx_data->hwlock = hwspin_lock_request_specific(ret);
> + if (!sc27xx_data->hwlock) {
> + dev_err(>dev, "failed to request hwspinlock\n");
> + return -ENXIO;
> + }
> +
> + init_completion(_data->completion);
> +
> + /*
> +  * Different PMIC ADC controllers can have differnt channel voltage

different

> +  * ratios, so we should save the implementation of getting voltage
> +  * ratio for corresponding PMIC ADC in the device data structure.
> +  */
> + sc27xx_data->get_volt_ratio = data;
> + sc27xx_data->dev = >dev;
> +
> + ret = sc27xx_adc_enable(sc27xx_data);
> + if (ret) {
> + dev_err(>dev, "failed to enable ADC module\n");
> + goto free_hwlock;
> + }
> +
> + ret = devm_request_threaded_irq(>dev, sc27xx_data->irq, NULL,
> + sc27xx_adc_isr, IRQF_ONESHOT,
> + pdev->name, sc27xx_data);
> + if (ret) {
> + dev_err(>dev, "failed to request ADC irq\n");
> + goto disable_adc;
> + }
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = dev_name(>dev);
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> + indio_dev->channels = sc27xx_channels;
> + indio_dev->num_channels = ARRAY_SIZE(sc27xx_channels);
> + ret = devm_iio_device_register(>dev, indio_dev);
> + if (ret) {
> + dev_err(>dev, "could not register iio (ADC)");
> + goto disable_adc;
> + }
> +
> + platform_set_drvdata(pdev, indio_dev);
> + return 0;
> +
> +disable_adc:
> + sc27xx_adc_disable(sc27xx_data);
> +free_hwlock:
> + hwspin_lock_free(sc27xx_data->hwlock);
> + return ret;
> +}
> +
> +static int sc27xx_adc_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct sc27xx_adc_data *sc27xx_data = iio_priv(indio_dev);
> +
> + sc27xx_adc_disable(sc27xx_data);
> + hwspin_lock_free(sc27xx_data->hwlock);
> + return 0;
> +}
> +
> +static const struct of_device_id sc27xx_adc_of_match[] = {
> + {
> + .compatible = "sprd,sc2731-adc",
> + .data = (void *)_adc_2731_ratio,
> + },
> + { }
> +};
> +
> +static struct platform_driver sc27xx_adc_driver = {
> + .probe = sc27xx_adc_probe,
> + .remove = sc27xx_adc_remove,
> + .driver = {
> + .name = "sc27xx-adc",
> + .of_match_table = sc27xx_adc_of_match,
> + },
> +};
> +
> +module_platform_driver(sc27xx_adc_driver);
> +
> +MODULE_AUTHOR("Freeman Liu ");
> +MODULE_DESCRIPTION("Spreadtrum SC27XX ADC Driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 1/2] iio: dac: Add AD5758 support

2018-06-06 Thread Peter Meerwald-Stadler
ng default");

\n missing

> + } else {
> + dev_dbg(>spi->dev,
> + "Missing \"range\" property, using default\n");
> + }
> +
> + st->sr_config[0] = 1;
> + st->sr_config[1] = 16000;
> + st->sr_config[2] = 4;
> + if (!device_property_read_u32_array(>spi->dev, "adi,slew",
> + tmparray, 3)) {
> + st->sr_config[0] = tmparray[0];
> +
> + index = ad5758_get_array_index(ad5758_slew_rate_clk,
> +ARRAY_SIZE(ad5758_slew_rate_clk),
> +tmparray[1]);
> +
> + if (index < 0)
> + dev_warn(>spi->dev,
> + "slew rate clock out of range, using default");

\n missing

> + else
> + st->sr_config[1] = index;
> +
> + index = ad5758_get_array_index(ad5758_slew_rate_step,
> + ARRAY_SIZE(ad5758_slew_rate_step),
> + tmparray[2]);
> +
> + if (index < 0)
> + dev_warn(>spi->dev,
> + "slew rate step out of range, using default");

\n missing

> + else
> + st->sr_config[2] = index;
> + } else {
> + dev_dbg(>spi->dev,
> +  "Missing \"slew\" property, using default\n");
> + }
> +}
> +
> +static int ad5758_init(struct ad5758_state *st)
> +{
> + int regval, ret;
> +
> + ad5758_parse_dt(st);
> +
> + /* Disable CRC checks */
> + ret = ad5758_crc_disable(st);
> + if (ret < 0)
> + return ret;
> +
> + /* Perform a software reset */
> + ret = ad5758_soft_reset(st);
> + if (ret < 0)
> + return ret;
> +
> + /* Disable CRC checks */
> + ret = ad5758_crc_disable(st);
> + if (ret < 0)
> + return ret;
> +
> + /* Perform a calibration memory refresh */
> + ret = ad5758_calib_mem_refresh(st);
> + if (ret < 0)
> + return ret;
> +
> + regval = ad5758_spi_reg_read(st, AD5758_DIGITAL_DIAG_RESULTS);
> + if (regval < 0)
> + return regval;
> +
> + /* Clear all the error flags */
> + ret = ad5758_spi_reg_write(st, AD5758_DIGITAL_DIAG_RESULTS, regval);
> + if (ret < 0)
> + return ret;
> +
> + /* Set the dc-to-dc current limit */
> + ret = ad5758_set_dc_dc_ilim(st, st->dc_dc_ilim);
> + if (ret < 0)
> + return ret;
> +
> + /* Configure the dc-to-dc controller mode */
> + ret = ad5758_set_dc_dc_conv_mode(st, st->dc_dc_mode);
> + if (ret < 0)
> + return ret;
> +
> + /* Configure the output range */
> + ret = ad5758_set_out_range(st, st->out_range);
> + if (ret < 0)
> + return ret;
> +
> + /* Enable Slew Rate Control, set the slew rate clock and step */
> + ret = ad5758_slew_rate_config(st, st->sr_config[0],
> +   st->sr_config[1], st->sr_config[2]);
> + if (ret < 0)
> + return ret;
> +
> + /* Enable the VIOUT fault protection switch (FPS is closed) */
> + ret = ad5758_fault_prot_switch_en(st, 1);
> + if (ret < 0)
> + return ret;
> +
> + /* Power up the DAC and internal (INT) amplifiers */
> + ret = ad5758_internal_buffers_en(st, 1);
> + if (ret < 0)
> + return ret;
> +
> + /* Enable VIOUT */
> + ret = ad5758_spi_write_mask(st, AD5758_DAC_CONFIG,
> + AD5758_DAC_CONFIG_OUT_EN_MSK,
> + AD5758_DAC_CONFIG_OUT_EN_MODE(1));

return directly, i.e.
return ad5758_spi...

> +
> + return ret;
> +}
> +
> +static int ad5758_probe(struct spi_device *spi)
> +{
> + struct ad5758_state *st;
> + struct iio_dev *indio_dev;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*st));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + st = iio_priv(indio_dev);
> + spi_set_drvdata(spi, indio_dev);
> +
> + st->spi = spi;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = spi_get_device_id(spi)->name;
> + indio_dev->info = _info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = ad5758_channels;
> + indio_dev->num_channels = ARRAY_SIZE(ad5758_channels);
> +
> + mutex_init(>lock);
> +
> + ret = ad5758_init(st);
> + if (ret < 0) {
> + dev_err(>dev, "AD5758 init failed\n");
> + return ret;
> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(>dev, "Failed to register iio device\n");

is the message really necessary/likely?

> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static const struct spi_device_id ad5758_id[] = {
> + { "ad5758", 0 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(spi, ad5758_id);
> +
> +static struct spi_driver ad5758_driver = {
> + .driver = {
> + .name = KBUILD_MODNAME,
> + },
> + .probe = ad5758_probe,
> + .id_table = ad5758_id,
> +};
> +
> +module_spi_driver(ad5758_driver);
> +
> +MODULE_AUTHOR("Stefan Popa ");
> +MODULE_DESCRIPTION("Analog Devices AD5758 DAC");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 1/2] iio: dac: Add AD5758 support

2018-06-06 Thread Peter Meerwald-Stadler
ng default");

\n missing

> + } else {
> + dev_dbg(>spi->dev,
> + "Missing \"range\" property, using default\n");
> + }
> +
> + st->sr_config[0] = 1;
> + st->sr_config[1] = 16000;
> + st->sr_config[2] = 4;
> + if (!device_property_read_u32_array(>spi->dev, "adi,slew",
> + tmparray, 3)) {
> + st->sr_config[0] = tmparray[0];
> +
> + index = ad5758_get_array_index(ad5758_slew_rate_clk,
> +ARRAY_SIZE(ad5758_slew_rate_clk),
> +tmparray[1]);
> +
> + if (index < 0)
> + dev_warn(>spi->dev,
> + "slew rate clock out of range, using default");

\n missing

> + else
> + st->sr_config[1] = index;
> +
> + index = ad5758_get_array_index(ad5758_slew_rate_step,
> + ARRAY_SIZE(ad5758_slew_rate_step),
> + tmparray[2]);
> +
> + if (index < 0)
> + dev_warn(>spi->dev,
> + "slew rate step out of range, using default");

\n missing

> + else
> + st->sr_config[2] = index;
> + } else {
> + dev_dbg(>spi->dev,
> +  "Missing \"slew\" property, using default\n");
> + }
> +}
> +
> +static int ad5758_init(struct ad5758_state *st)
> +{
> + int regval, ret;
> +
> + ad5758_parse_dt(st);
> +
> + /* Disable CRC checks */
> + ret = ad5758_crc_disable(st);
> + if (ret < 0)
> + return ret;
> +
> + /* Perform a software reset */
> + ret = ad5758_soft_reset(st);
> + if (ret < 0)
> + return ret;
> +
> + /* Disable CRC checks */
> + ret = ad5758_crc_disable(st);
> + if (ret < 0)
> + return ret;
> +
> + /* Perform a calibration memory refresh */
> + ret = ad5758_calib_mem_refresh(st);
> + if (ret < 0)
> + return ret;
> +
> + regval = ad5758_spi_reg_read(st, AD5758_DIGITAL_DIAG_RESULTS);
> + if (regval < 0)
> + return regval;
> +
> + /* Clear all the error flags */
> + ret = ad5758_spi_reg_write(st, AD5758_DIGITAL_DIAG_RESULTS, regval);
> + if (ret < 0)
> + return ret;
> +
> + /* Set the dc-to-dc current limit */
> + ret = ad5758_set_dc_dc_ilim(st, st->dc_dc_ilim);
> + if (ret < 0)
> + return ret;
> +
> + /* Configure the dc-to-dc controller mode */
> + ret = ad5758_set_dc_dc_conv_mode(st, st->dc_dc_mode);
> + if (ret < 0)
> + return ret;
> +
> + /* Configure the output range */
> + ret = ad5758_set_out_range(st, st->out_range);
> + if (ret < 0)
> + return ret;
> +
> + /* Enable Slew Rate Control, set the slew rate clock and step */
> + ret = ad5758_slew_rate_config(st, st->sr_config[0],
> +   st->sr_config[1], st->sr_config[2]);
> + if (ret < 0)
> + return ret;
> +
> + /* Enable the VIOUT fault protection switch (FPS is closed) */
> + ret = ad5758_fault_prot_switch_en(st, 1);
> + if (ret < 0)
> + return ret;
> +
> + /* Power up the DAC and internal (INT) amplifiers */
> + ret = ad5758_internal_buffers_en(st, 1);
> + if (ret < 0)
> + return ret;
> +
> + /* Enable VIOUT */
> + ret = ad5758_spi_write_mask(st, AD5758_DAC_CONFIG,
> + AD5758_DAC_CONFIG_OUT_EN_MSK,
> + AD5758_DAC_CONFIG_OUT_EN_MODE(1));

return directly, i.e.
return ad5758_spi...

> +
> + return ret;
> +}
> +
> +static int ad5758_probe(struct spi_device *spi)
> +{
> + struct ad5758_state *st;
> + struct iio_dev *indio_dev;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*st));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + st = iio_priv(indio_dev);
> + spi_set_drvdata(spi, indio_dev);
> +
> + st->spi = spi;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = spi_get_device_id(spi)->name;
> + indio_dev->info = _info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = ad5758_channels;
> + indio_dev->num_channels = ARRAY_SIZE(ad5758_channels);
> +
> + mutex_init(>lock);
> +
> + ret = ad5758_init(st);
> + if (ret < 0) {
> + dev_err(>dev, "AD5758 init failed\n");
> + return ret;
> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(>dev, "Failed to register iio device\n");

is the message really necessary/likely?

> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static const struct spi_device_id ad5758_id[] = {
> + { "ad5758", 0 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(spi, ad5758_id);
> +
> +static struct spi_driver ad5758_driver = {
> + .driver = {
> + .name = KBUILD_MODNAME,
> + },
> + .probe = ad5758_probe,
> + .id_table = ad5758_id,
> +};
> +
> +module_spi_driver(ad5758_driver);
> +
> +MODULE_AUTHOR("Stefan Popa ");
> +MODULE_DESCRIPTION("Analog Devices AD5758 DAC");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [RFC PATCH] iio: adc: Add Xilinx AMS driver

2018-03-15 Thread Peter Meerwald-Stadler

minor comments below

> The AMS includes an ADC as well as on-chip sensors that can be used to
> sample external voltages and monitor on-die operating conditions, such as
> temperature and supply voltage levels. The AMS has two SYSMON blocks.
> PL-SYSMON block is capable of monitoring off chip voltage and temperature.
> PL-SYSMON block has DRP, JTAG and I2C interface to enable monitoring from
> external master. Out of these interface currently only DRP is supported.
> Other block PS-SYSMON is memory mapped to PS.
> 
> The AMS can use internal channels to monitor voltage and temperature
> as well as one primary and up to 16 auxiliary channels for measuring
> external voltages.
> 
> The voltage and temperature monitoring channels also have event
> capability which allows to generate an interrupt when their value
> falls below or raises above a set threshold.
> 
> Signed-off-by: Manish Narani 
> ---
>  drivers/iio/adc/Kconfig  |   10 +
>  drivers/iio/adc/Makefile |1 +
>  drivers/iio/adc/xilinx-ams.c | 1115 
> ++
>  drivers/iio/adc/xilinx-ams.h |  278 +++
>  4 files changed, 1404 insertions(+)
>  create mode 100644 drivers/iio/adc/xilinx-ams.c
>  create mode 100644 drivers/iio/adc/xilinx-ams.h
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 72bc2b7..f1b8a5f 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -931,4 +931,14 @@ config XILINX_XADC
>   The driver can also be build as a module. If so, the module will be 
> called
>   xilinx-xadc.
> 
> +config XILINX_AMS
> +   tristate "Xilinx AMS driver"
> +   depends on ARCH_ZYNQMP || COMPILE_TEST
> +   depends on HAS_IOMEM
> +   help
> + Say yes here to have support for the Xilinx AMS.
> +
> + The driver can also be build as a module. If so, the module will be 
> called
> + xilinx-ams.
> +
>  endmenu
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 28a9423..27ded4f 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -85,3 +85,4 @@ obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
>  xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o
>  obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o
>  obj-$(CONFIG_SD_ADC_MODULATOR) += sd_adc_modulator.o
> +obj-$(CONFIG_XILINX_AMS) += xilinx-ams.o

maybe put after xilinx-xadc

> diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
> new file mode 100644
> index 000..2f519e6
> --- /dev/null
> +++ b/drivers/iio/adc/xilinx-ams.c
> @@ -0,0 +1,1115 @@
> +/*
> + * Xilinx AMS driver
> + *
> + * Licensed under the GPL-2
> + *
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 

iio/buffer is not actually used?

> +#include 
> +
> +#include "xilinx-ams.h"
> +#include 

the delay #include should be moved up

> +
> +static const unsigned int AMS_UNMASK_TIMEOUT = 500;
> +
> +static inline void ams_read_reg(struct ams *ams, unsigned int offset, u32 
> *data)
> +{
> +   *data = readl(ams->base + offset);
> +}
> +
> +static inline void ams_write_reg(struct ams *ams, unsigned int offset, u32 
> data)
> +{
> +   writel(data, ams->base + offset);
> +}
> +
> +static inline void ams_update_reg(struct ams *ams, unsigned int offset,
> + u32 mask, u32 data)
> +{
> +   u32 val;
> +
> +   ams_read_reg(ams, offset, );
> +   ams_write_reg(ams, offset, (val & ~mask) | (mask & data));
> +}
> +
> +static inline void ams_ps_read_reg(struct ams *ams, unsigned int offset,
> +  u32 *data)
> +{
> +   *data = readl(ams->ps_base + offset);
> +}
> +
> +static inline void ams_ps_write_reg(struct ams *ams, unsigned int offset,
> +   u32 data)
> +{
> +   writel(data, ams->ps_base + offset);
> +}
> +
> +static inline void ams_ps_update_reg(struct ams *ams, unsigned int offset,
> +u32 mask, u32 data)
> +{
> +   u32 val;
> +
> +   ams_ps_read_reg(ams, offset, );
> +   ams_ps_write_reg(ams, offset, (val & ~mask) | (data & mask));
> +}
> +
> +static inline void ams_apb_pl_read_reg(struct ams *ams, unsigned int offset,
> +  u32 *data)
> +{
> +   *data = readl(ams->pl_base + offset);
> +}
> +
> +static inline void ams_apb_pl_write_reg(struct ams *ams, unsigned int offset,
> +   u32 data)
> +{
> +   writel(data, ams->pl_base + offset);
> +}
> +
> +static inline void ams_apb_pl_update_reg(struct ams *ams, unsigned int 
> offset,
> +u32 mask, u32 data)
> +{
> +   u32 val;
> +
> +   ams_apb_pl_read_reg(ams, offset, );
> +   ams_apb_pl_write_reg(ams, offset, (val & ~mask) | (data & mask));
> +}

can't we 

Re: [RFC PATCH] iio: adc: Add Xilinx AMS driver

2018-03-15 Thread Peter Meerwald-Stadler

minor comments below

> The AMS includes an ADC as well as on-chip sensors that can be used to
> sample external voltages and monitor on-die operating conditions, such as
> temperature and supply voltage levels. The AMS has two SYSMON blocks.
> PL-SYSMON block is capable of monitoring off chip voltage and temperature.
> PL-SYSMON block has DRP, JTAG and I2C interface to enable monitoring from
> external master. Out of these interface currently only DRP is supported.
> Other block PS-SYSMON is memory mapped to PS.
> 
> The AMS can use internal channels to monitor voltage and temperature
> as well as one primary and up to 16 auxiliary channels for measuring
> external voltages.
> 
> The voltage and temperature monitoring channels also have event
> capability which allows to generate an interrupt when their value
> falls below or raises above a set threshold.
> 
> Signed-off-by: Manish Narani 
> ---
>  drivers/iio/adc/Kconfig  |   10 +
>  drivers/iio/adc/Makefile |1 +
>  drivers/iio/adc/xilinx-ams.c | 1115 
> ++
>  drivers/iio/adc/xilinx-ams.h |  278 +++
>  4 files changed, 1404 insertions(+)
>  create mode 100644 drivers/iio/adc/xilinx-ams.c
>  create mode 100644 drivers/iio/adc/xilinx-ams.h
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 72bc2b7..f1b8a5f 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -931,4 +931,14 @@ config XILINX_XADC
>   The driver can also be build as a module. If so, the module will be 
> called
>   xilinx-xadc.
> 
> +config XILINX_AMS
> +   tristate "Xilinx AMS driver"
> +   depends on ARCH_ZYNQMP || COMPILE_TEST
> +   depends on HAS_IOMEM
> +   help
> + Say yes here to have support for the Xilinx AMS.
> +
> + The driver can also be build as a module. If so, the module will be 
> called
> + xilinx-ams.
> +
>  endmenu
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 28a9423..27ded4f 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -85,3 +85,4 @@ obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
>  xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o
>  obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o
>  obj-$(CONFIG_SD_ADC_MODULATOR) += sd_adc_modulator.o
> +obj-$(CONFIG_XILINX_AMS) += xilinx-ams.o

maybe put after xilinx-xadc

> diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
> new file mode 100644
> index 000..2f519e6
> --- /dev/null
> +++ b/drivers/iio/adc/xilinx-ams.c
> @@ -0,0 +1,1115 @@
> +/*
> + * Xilinx AMS driver
> + *
> + * Licensed under the GPL-2
> + *
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 

iio/buffer is not actually used?

> +#include 
> +
> +#include "xilinx-ams.h"
> +#include 

the delay #include should be moved up

> +
> +static const unsigned int AMS_UNMASK_TIMEOUT = 500;
> +
> +static inline void ams_read_reg(struct ams *ams, unsigned int offset, u32 
> *data)
> +{
> +   *data = readl(ams->base + offset);
> +}
> +
> +static inline void ams_write_reg(struct ams *ams, unsigned int offset, u32 
> data)
> +{
> +   writel(data, ams->base + offset);
> +}
> +
> +static inline void ams_update_reg(struct ams *ams, unsigned int offset,
> + u32 mask, u32 data)
> +{
> +   u32 val;
> +
> +   ams_read_reg(ams, offset, );
> +   ams_write_reg(ams, offset, (val & ~mask) | (mask & data));
> +}
> +
> +static inline void ams_ps_read_reg(struct ams *ams, unsigned int offset,
> +  u32 *data)
> +{
> +   *data = readl(ams->ps_base + offset);
> +}
> +
> +static inline void ams_ps_write_reg(struct ams *ams, unsigned int offset,
> +   u32 data)
> +{
> +   writel(data, ams->ps_base + offset);
> +}
> +
> +static inline void ams_ps_update_reg(struct ams *ams, unsigned int offset,
> +u32 mask, u32 data)
> +{
> +   u32 val;
> +
> +   ams_ps_read_reg(ams, offset, );
> +   ams_ps_write_reg(ams, offset, (val & ~mask) | (data & mask));
> +}
> +
> +static inline void ams_apb_pl_read_reg(struct ams *ams, unsigned int offset,
> +  u32 *data)
> +{
> +   *data = readl(ams->pl_base + offset);
> +}
> +
> +static inline void ams_apb_pl_write_reg(struct ams *ams, unsigned int offset,
> +   u32 data)
> +{
> +   writel(data, ams->pl_base + offset);
> +}
> +
> +static inline void ams_apb_pl_update_reg(struct ams *ams, unsigned int 
> offset,
> +u32 mask, u32 data)
> +{
> +   u32 val;
> +
> +   ams_apb_pl_read_reg(ams, offset, );
> +   ams_apb_pl_write_reg(ams, offset, (val & ~mask) | (data & mask));
> +}

can't we have some MACRO() 

Re: [PATCH 2/2] iio: magnetometer: Add Infineon TLV493D-A1B6

2017-12-10 Thread Peter Meerwald-Stadler
 need to set val2 if returning VAL_INT

> + if (mask == IIO_CHAN_INFO_RAW)
> + return IIO_VAL_INT;
> +
> + switch (chan->type) {
> + case IIO_MAGN:
> + *val2 = (*val * 100) * 98 / 1000;
> + *val = *val2 / 100;
> + *val2 %= 100;
> + break;
> + case IIO_TEMP:
> + *val2 = (*val * 100) * 11 / 10;
> + *val = *val2 / 100;
> + *val2 %= 100;
> + /* According to datasheet, LSB offset is for 25°C */
> + *val += 25;
> + break;
> + default:
> + return -EINVAL;
> + }
> + return IIO_VAL_INT_PLUS_MICRO;
> + case IIO_CHAN_INFO_OFFSET:
> + switch (chan->type) {
> + case IIO_TEMP:
> + *val = -340;
> + *val2 = 0;

no need to set val2

> + return IIO_VAL_INT;
> + default:
> + return -EINVAL;
> + }
> + case IIO_CHAN_INFO_SCALE:
> + switch (chan->type) {
> + case IIO_MAGN:
> + /* 0.098 mT/LSB */
> + *val = 0;
> + *val2 = 98000;
> + return IIO_VAL_INT_PLUS_MICRO;
> + case IIO_TEMP:
> + /* 1.1 °C/LSB */
> + *val = 1;
> + *val2 = 10;
> + return IIO_VAL_INT_PLUS_MICRO;
> + default:
> + return -EINVAL;
> + }
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static const struct iio_info tlv493d_iio_info = {
> + .read_raw = tlv493d_read_raw,
> +};
> +
> +static int tlv493d_probe(struct i2c_client *i2c)
> +{
> + struct iio_dev *indio_dev;
> + struct tlv493d *tlv493d;
> + u8 buf[10];
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*tlv493d));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + tlv493d = iio_priv(indio_dev);
> + i2c_set_clientdata(i2c, indio_dev);
> + tlv493d->i2c = i2c;
> +
> + ret = of_iio_read_mount_matrix(>dev, "mount-matrix",
> + >mount_matrix);
> + if (ret)
> + return ret;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->channels = tlv493d_channels;
> + indio_dev->num_channels = ARRAY_SIZE(tlv493d_channels);
> + indio_dev->info = _iio_info;
> + indio_dev->available_scan_masks = tlv493d_scan_masks;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->name = "tlv493d";
> +
> + ret = tlv493d_read_regs(tlv493d, buf, 10);
> + if (ret)
> + return ret;
> +
> + tlv493d->factset1 = buf[7];
> + tlv493d->factset2 = buf[8];
> + tlv493d->factset3 = buf[9];
> +
> + buf[0] = 0;
> + buf[1] = MOD1_FAST | MOD1_LOW;

what does this mean? some comment explaining the default mode?

> + buf[2] = 0;
> + buf[3] = 0;
> + ret = tlv493d_write_regs(tlv493d, buf, 4);
> + if (ret)
> + return ret;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(>dev, "device registration failed");
> + tlv493d_power_down(tlv493d);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int tlv493d_remove(struct i2c_client *i2c)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(i2c);
> + struct tlv493d *tlv493d = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> +
> + tlv493d_power_down(tlv493d);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id tlv493d_dt_ids[] = {
> + { .compatible = "infineon,tlv493d-a1b6" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, tlv493d_dt_ids);
> +
> +static struct i2c_driver tlv493d_i2c_driver = {
> + .driver = {
> + .name = "tlv493d",
> + .of_match_table = tlv493d_dt_ids,
> + },
> + .probe_new = tlv493d_probe,
> + .remove = tlv493d_remove,
> +};
> +
> +module_i2c_driver(tlv493d_i2c_driver);
> +
> +MODULE_DESCRIPTION("TLV493D I2C driver");
> +MODULE_AUTHOR("Andreas Faerber");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH 2/2] iio: magnetometer: Add Infineon TLV493D-A1B6

2017-12-10 Thread Peter Meerwald-Stadler
 if (mask == IIO_CHAN_INFO_RAW)
> + return IIO_VAL_INT;
> +
> + switch (chan->type) {
> + case IIO_MAGN:
> + *val2 = (*val * 100) * 98 / 1000;
> + *val = *val2 / 100;
> + *val2 %= 100;
> + break;
> + case IIO_TEMP:
> + *val2 = (*val * 100) * 11 / 10;
> + *val = *val2 / 100;
> + *val2 %= 100;
> + /* According to datasheet, LSB offset is for 25°C */
> + *val += 25;
> + break;
> + default:
> + return -EINVAL;
> + }
> + return IIO_VAL_INT_PLUS_MICRO;
> + case IIO_CHAN_INFO_OFFSET:
> + switch (chan->type) {
> + case IIO_TEMP:
> + *val = -340;
> + *val2 = 0;

no need to set val2

> + return IIO_VAL_INT;
> + default:
> + return -EINVAL;
> + }
> + case IIO_CHAN_INFO_SCALE:
> + switch (chan->type) {
> + case IIO_MAGN:
> + /* 0.098 mT/LSB */
> + *val = 0;
> + *val2 = 98000;
> + return IIO_VAL_INT_PLUS_MICRO;
> + case IIO_TEMP:
> + /* 1.1 °C/LSB */
> + *val = 1;
> + *val2 = 10;
> + return IIO_VAL_INT_PLUS_MICRO;
> + default:
> + return -EINVAL;
> + }
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static const struct iio_info tlv493d_iio_info = {
> + .read_raw = tlv493d_read_raw,
> +};
> +
> +static int tlv493d_probe(struct i2c_client *i2c)
> +{
> + struct iio_dev *indio_dev;
> + struct tlv493d *tlv493d;
> + u8 buf[10];
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*tlv493d));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + tlv493d = iio_priv(indio_dev);
> + i2c_set_clientdata(i2c, indio_dev);
> + tlv493d->i2c = i2c;
> +
> + ret = of_iio_read_mount_matrix(>dev, "mount-matrix",
> + >mount_matrix);
> + if (ret)
> + return ret;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->channels = tlv493d_channels;
> + indio_dev->num_channels = ARRAY_SIZE(tlv493d_channels);
> + indio_dev->info = _iio_info;
> + indio_dev->available_scan_masks = tlv493d_scan_masks;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->name = "tlv493d";
> +
> + ret = tlv493d_read_regs(tlv493d, buf, 10);
> + if (ret)
> + return ret;
> +
> + tlv493d->factset1 = buf[7];
> + tlv493d->factset2 = buf[8];
> + tlv493d->factset3 = buf[9];
> +
> + buf[0] = 0;
> + buf[1] = MOD1_FAST | MOD1_LOW;

what does this mean? some comment explaining the default mode?

> + buf[2] = 0;
> + buf[3] = 0;
> + ret = tlv493d_write_regs(tlv493d, buf, 4);
> + if (ret)
> + return ret;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(>dev, "device registration failed");
> + tlv493d_power_down(tlv493d);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int tlv493d_remove(struct i2c_client *i2c)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(i2c);
> + struct tlv493d *tlv493d = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> +
> + tlv493d_power_down(tlv493d);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id tlv493d_dt_ids[] = {
> + { .compatible = "infineon,tlv493d-a1b6" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, tlv493d_dt_ids);
> +
> +static struct i2c_driver tlv493d_i2c_driver = {
> + .driver = {
> + .name = "tlv493d",
> + .of_match_table = tlv493d_dt_ids,
> + },
> + .probe_new = tlv493d_probe,
> + .remove = tlv493d_remove,
> +};
> +
> +module_i2c_driver(tlv493d_i2c_driver);
> +
> +MODULE_DESCRIPTION("TLV493D I2C driver");
> +MODULE_AUTHOR("Andreas Faerber");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH 1/2] iio: chemical: sgpxx: Support Sensirion SGPxx sensors

2017-11-21 Thread Peter Meerwald-Stadler
_to_cpu(words[1].value) & 0x) << 16 |
> +   (u64)(be16_to_cpu(words[0].value) & 0x) << 32;
> +
> +unlock_fail:
> + mutex_unlock(>data_lock);
> + return ret;
> +}
> +
> +static int setup_and_check_sgp_data(struct sgp_data *data,
> + unsigned int chip_id)
> +{
> + u16 minor, major, product, eng, ix, num_fs, reserved;
> + struct sgp_version *supported_versions;
> +
> + product = (data->feature_set & 0xf000) >> 12;
> + reserved = (data->feature_set & 0x0e00) >> 9;
> + eng = (data->feature_set & 0x0100) >> 8;
> + major = (data->feature_set & 0x00e0) >> 5;
> + minor = data->feature_set & 0x001f;
> +
> + /* driver does not match product */
> + if (product != chip_id) {
> + dev_err(>client->dev,
> + "sensor reports a different product: 0x%04hx\n",
> + product);
> + return -ENODEV;
> + }
> +
> + if (reserved != 0)
> + dev_warn(>client->dev, "reserved bits set: 0x%04hx\n",
> +  reserved);
> +
> + /* engineering samples are not supported */
> + if (eng != 0)
> + return -ENODEV;
> +
> + data->iaq_initialized = false;
> + switch (product) {
> + case SGP30:
> + supported_versions =
> + (struct sgp_version *)supported_versions_sgp30;
> + num_fs = ARRAY_SIZE(supported_versions_sgp30);
> + data->measurement_len = SGP30_MEASUREMENT_LEN;
> + data->measure_interval_hz = SGP30_MEASURE_INTERVAL_HZ;
> + data->measure_iaq_cmd = SGP_CMD_IAQ_MEASURE;
> + data->measure_signal_cmd = SGP30_CMD_MEASURE_SIGNAL;
> + data->chip_id = SGP30;
> + data->baseline_len = 2;
> + data->baseline_format = "%08x\n";
> + data->measure_mode = SGP_MEASURE_MODE_UNKNOWN;
> + break;
> + case SGPC3:
> + supported_versions =
> + (struct sgp_version *)supported_versions_sgpc3;
> + num_fs = ARRAY_SIZE(supported_versions_sgpc3);
> + data->measurement_len = SGPC3_MEASUREMENT_LEN;
> + data->measure_interval_hz = SGPC3_MEASURE_INTERVAL_HZ;
> + data->measure_iaq_cmd = SGPC3_CMD_MEASURE_RAW;
> + data->measure_signal_cmd = SGPC3_CMD_MEASURE_RAW;
> + data->chip_id = SGPC3;
> + data->baseline_len = 1;
> + data->baseline_format = "%04x\n";
> + data->measure_mode = SGP_MEASURE_MODE_ALL;
> + break;
> + default:
> + return -ENODEV;
> + };
> +
> + for (ix = 0; ix < num_fs; ix++) {
> + if (supported_versions[ix].major == major &&
> + minor >= supported_versions[ix].minor)
> + return 0;
> + }
> +
> + dev_err(>client->dev, "unsupported sgp version: %d.%d\n",
> + major, minor);
> + return -ENODEV;
> +}
> +
> +static IIO_DEVICE_ATTR(in_serial_id, 0444, sgp_serial_id_show, NULL, 0);
> +static IIO_DEVICE_ATTR(in_feature_set_version, 0444,
> +sgp_feature_set_version_show, NULL, 0);
> +static IIO_DEVICE_ATTR(in_selftest, 0444, sgp_selftest_show, NULL, 0);
> +static IIO_DEVICE_ATTR(out_iaq_init, 0220, NULL, sgp_iaq_init_store, 0);
> +static IIO_DEVICE_ATTR(in_iaq_baseline, 0444, sgp_iaq_baseline_show, NULL, 
> 0);
> +static IIO_DEVICE_ATTR(out_iaq_baseline, 0220, NULL, sgp_iaq_baseline_store, 
> 0);

lot of private ABI; all needed?
needs documentation...

> +static struct attribute *sgp_attributes[] = {
> + _dev_attr_in_serial_id.dev_attr.attr,
> + _dev_attr_in_feature_set_version.dev_attr.attr,
> + _dev_attr_in_selftest.dev_attr.attr,
> + _dev_attr_out_iaq_init.dev_attr.attr,
> + _dev_attr_in_iaq_baseline.dev_attr.attr,
> + _dev_attr_out_iaq_baseline.dev_attr.attr,
> + NULL
> +};
> +
> +static const struct attribute_group sgp_attr_group = {
> + .attrs = sgp_attributes,
> +};
> +
> +static const struct iio_info sgp_info = {
> + .attrs      = _attr_group,
> + .read_raw   = sgp_read_raw,
> + .write_raw  = sgp_write_raw,
> +};
> +
> +static const struct of_device_id sgp_dt_ids[] = {
> + { .compatible = "sensirion,sgp30", .data = (void *)SGP30 },
> + { .compatible = "sensirion,sgpc3", .data = (void *)SGPC3 },
> + { }
> +};
> +
> +static int sgp_probe(struct i2c_client *client,
> +  const struct i2c_device_id *id)
> +{
> + struct iio_dev *indio_dev;
> + struct sgp_data *data;
> + struct sgp_device *chip;
> + const struct of_device_id *of_id;
> + unsigned long chip_id;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + of_id = of_match_device(sgp_dt_ids, >dev);
> + if (!of_id)
> + chip_id = id->driver_data;
> + else
> + chip_id = (unsigned long)of_id->data;
> +
> + chip = _devices[chip_id];
> + data = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + data->client = client;
> + crc8_populate_msb(sgp_crc8_table, SGP_CRC8_POLYNOMIAL);
> + mutex_init(>data_lock);
> + mutex_init(>i2c_lock);
> +
> + /* get serial id and write it to client data */
> + ret = sgp_get_serial_id(data);
> +
> + if (ret != 0)

matter of taste: most drivers just do
if (ret)

> + return ret;
> +
> + /* get feature set version and write it to client data */
> + ret = sgp_read_from_cmd(data, SGP_CMD_GET_FEATURE_SET, 1,
> + SGP_CMD_DURATION_US);
> + if (ret != 0)
> + return ret;
> +
> + data->feature_set = be16_to_cpu(data->buffer.raw_words[0].value);
> +
> + ret = setup_and_check_sgp_data(data, chip_id);
> + if (ret < 0)
> + goto fail_free;
> +
> + /* so initial reading will complete */
> + data->last_update = jiffies - data->measure_interval_hz * HZ;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->info = _info;
> + indio_dev->name = dev_name(>dev);
> + indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE;

is INDIO_BUFFER_SOFTWARE implemented at this stage? maybe added in 
followup patch

> +
> + indio_dev->channels = chip->channels;
> + indio_dev->num_channels = chip->num_channels;
> +
> + ret = devm_iio_device_register(>dev, indio_dev);
> + if (!ret)
> + return ret;
> +
> + dev_err(>dev, "failed to register iio device\n");

really message needed?

> +
> +fail_free:
> + mutex_destroy(>i2c_lock);
> + mutex_destroy(>data_lock);

no need to explicitly destroy mutex

> + iio_device_free(indio_dev);

no need to explicitly free devm_ stuff

> + return ret;
> +}
> +
> +static int sgp_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> + devm_iio_device_unregister(>dev, indio_dev);

not needed

> + return 0;
> +}
> +
> +static const struct i2c_device_id sgp_id[] = {
> + { "sgp30", SGP30 },
> + { "sgpc3", SGPC3 },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, sgp_id);
> +MODULE_DEVICE_TABLE(of, sgp_dt_ids);
> +
> +static struct i2c_driver sgp_driver = {
> + .driver = {
> + .name   = "sgpxx",
> + .of_match_table = of_match_ptr(sgp_dt_ids),
> + },
> + .probe = sgp_probe,
> + .remove = sgp_remove,
> + .id_table = sgp_id,
> +};
> +module_i2c_driver(sgp_driver);
> +
> +MODULE_AUTHOR("Andreas Brauchli <andreas.brauc...@sensirion.com>");
> +MODULE_AUTHOR("Pascal Sachs <pascal.sa...@sensirion.com>");
> +MODULE_DESCRIPTION("Sensirion SGPxx gas sensors");
> +MODULE_LICENSE("GPL v2");
> +MODULE_VERSION("0.5.0");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 1/2] iio: chemical: sgpxx: Support Sensirion SGPxx sensors

2017-11-21 Thread Peter Meerwald-Stadler
   (u64)(be16_to_cpu(words[0].value) & 0x) << 32;
> +
> +unlock_fail:
> + mutex_unlock(>data_lock);
> + return ret;
> +}
> +
> +static int setup_and_check_sgp_data(struct sgp_data *data,
> + unsigned int chip_id)
> +{
> + u16 minor, major, product, eng, ix, num_fs, reserved;
> + struct sgp_version *supported_versions;
> +
> + product = (data->feature_set & 0xf000) >> 12;
> + reserved = (data->feature_set & 0x0e00) >> 9;
> + eng = (data->feature_set & 0x0100) >> 8;
> + major = (data->feature_set & 0x00e0) >> 5;
> + minor = data->feature_set & 0x001f;
> +
> + /* driver does not match product */
> + if (product != chip_id) {
> + dev_err(>client->dev,
> + "sensor reports a different product: 0x%04hx\n",
> + product);
> + return -ENODEV;
> + }
> +
> + if (reserved != 0)
> + dev_warn(>client->dev, "reserved bits set: 0x%04hx\n",
> +  reserved);
> +
> + /* engineering samples are not supported */
> + if (eng != 0)
> + return -ENODEV;
> +
> + data->iaq_initialized = false;
> + switch (product) {
> + case SGP30:
> + supported_versions =
> + (struct sgp_version *)supported_versions_sgp30;
> + num_fs = ARRAY_SIZE(supported_versions_sgp30);
> + data->measurement_len = SGP30_MEASUREMENT_LEN;
> + data->measure_interval_hz = SGP30_MEASURE_INTERVAL_HZ;
> + data->measure_iaq_cmd = SGP_CMD_IAQ_MEASURE;
> + data->measure_signal_cmd = SGP30_CMD_MEASURE_SIGNAL;
> + data->chip_id = SGP30;
> + data->baseline_len = 2;
> + data->baseline_format = "%08x\n";
> + data->measure_mode = SGP_MEASURE_MODE_UNKNOWN;
> + break;
> + case SGPC3:
> + supported_versions =
> + (struct sgp_version *)supported_versions_sgpc3;
> + num_fs = ARRAY_SIZE(supported_versions_sgpc3);
> + data->measurement_len = SGPC3_MEASUREMENT_LEN;
> + data->measure_interval_hz = SGPC3_MEASURE_INTERVAL_HZ;
> + data->measure_iaq_cmd = SGPC3_CMD_MEASURE_RAW;
> + data->measure_signal_cmd = SGPC3_CMD_MEASURE_RAW;
> + data->chip_id = SGPC3;
> + data->baseline_len = 1;
> + data->baseline_format = "%04x\n";
> + data->measure_mode = SGP_MEASURE_MODE_ALL;
> + break;
> + default:
> + return -ENODEV;
> + };
> +
> + for (ix = 0; ix < num_fs; ix++) {
> + if (supported_versions[ix].major == major &&
> + minor >= supported_versions[ix].minor)
> + return 0;
> + }
> +
> + dev_err(>client->dev, "unsupported sgp version: %d.%d\n",
> + major, minor);
> + return -ENODEV;
> +}
> +
> +static IIO_DEVICE_ATTR(in_serial_id, 0444, sgp_serial_id_show, NULL, 0);
> +static IIO_DEVICE_ATTR(in_feature_set_version, 0444,
> +sgp_feature_set_version_show, NULL, 0);
> +static IIO_DEVICE_ATTR(in_selftest, 0444, sgp_selftest_show, NULL, 0);
> +static IIO_DEVICE_ATTR(out_iaq_init, 0220, NULL, sgp_iaq_init_store, 0);
> +static IIO_DEVICE_ATTR(in_iaq_baseline, 0444, sgp_iaq_baseline_show, NULL, 
> 0);
> +static IIO_DEVICE_ATTR(out_iaq_baseline, 0220, NULL, sgp_iaq_baseline_store, 
> 0);

lot of private ABI; all needed?
needs documentation...

> +static struct attribute *sgp_attributes[] = {
> + _dev_attr_in_serial_id.dev_attr.attr,
> + _dev_attr_in_feature_set_version.dev_attr.attr,
> + _dev_attr_in_selftest.dev_attr.attr,
> + _dev_attr_out_iaq_init.dev_attr.attr,
> + _dev_attr_in_iaq_baseline.dev_attr.attr,
> + _dev_attr_out_iaq_baseline.dev_attr.attr,
> + NULL
> +};
> +
> +static const struct attribute_group sgp_attr_group = {
> + .attrs = sgp_attributes,
> +};
> +
> +static const struct iio_info sgp_info = {
> + .attrs  = _attr_group,
> + .read_raw   = sgp_read_raw,
> + .write_raw  = sgp_write_raw,
> +};
> +
> +static const struct of_device_id sgp_dt_ids[] = {
> + { .compatible = "sensirion,sgp30", .data = (void *)SGP30 },
> + { .compatible = "sensirion,sgpc3", .data = (void *)SGPC3 },
> + { }
> +};
> +
> +static int sgp_probe(struct i2c_client *client,
> +  const struct i2c_device_id *id)
> +{
> + struct iio_dev *indio_dev;
> + struct sgp_data *data;
> + struct sgp_device *chip;
> + const struct of_device_id *of_id;
> + unsigned long chip_id;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + of_id = of_match_device(sgp_dt_ids, >dev);
> + if (!of_id)
> + chip_id = id->driver_data;
> + else
> + chip_id = (unsigned long)of_id->data;
> +
> + chip = _devices[chip_id];
> + data = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + data->client = client;
> + crc8_populate_msb(sgp_crc8_table, SGP_CRC8_POLYNOMIAL);
> + mutex_init(>data_lock);
> + mutex_init(>i2c_lock);
> +
> + /* get serial id and write it to client data */
> + ret = sgp_get_serial_id(data);
> +
> + if (ret != 0)

matter of taste: most drivers just do
if (ret)

> + return ret;
> +
> + /* get feature set version and write it to client data */
> + ret = sgp_read_from_cmd(data, SGP_CMD_GET_FEATURE_SET, 1,
> + SGP_CMD_DURATION_US);
> + if (ret != 0)
> + return ret;
> +
> + data->feature_set = be16_to_cpu(data->buffer.raw_words[0].value);
> +
> + ret = setup_and_check_sgp_data(data, chip_id);
> + if (ret < 0)
> + goto fail_free;
> +
> + /* so initial reading will complete */
> + data->last_update = jiffies - data->measure_interval_hz * HZ;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->info = _info;
> + indio_dev->name = dev_name(>dev);
> + indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE;

is INDIO_BUFFER_SOFTWARE implemented at this stage? maybe added in 
followup patch

> +
> + indio_dev->channels = chip->channels;
> + indio_dev->num_channels = chip->num_channels;
> +
> + ret = devm_iio_device_register(>dev, indio_dev);
> + if (!ret)
> + return ret;
> +
> + dev_err(>dev, "failed to register iio device\n");

really message needed?

> +
> +fail_free:
> + mutex_destroy(>i2c_lock);
> + mutex_destroy(>data_lock);

no need to explicitly destroy mutex

> + iio_device_free(indio_dev);

no need to explicitly free devm_ stuff

> + return ret;
> +}
> +
> +static int sgp_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> + devm_iio_device_unregister(>dev, indio_dev);

not needed

> + return 0;
> +}
> +
> +static const struct i2c_device_id sgp_id[] = {
> + { "sgp30", SGP30 },
> + { "sgpc3", SGPC3 },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, sgp_id);
> +MODULE_DEVICE_TABLE(of, sgp_dt_ids);
> +
> +static struct i2c_driver sgp_driver = {
> + .driver = {
> + .name   = "sgpxx",
> + .of_match_table = of_match_ptr(sgp_dt_ids),
> + },
> + .probe = sgp_probe,
> + .remove = sgp_remove,
> + .id_table = sgp_id,
> +};
> +module_i2c_driver(sgp_driver);
> +
> +MODULE_AUTHOR("Andreas Brauchli ");
> +MODULE_AUTHOR("Pascal Sachs ");
> +MODULE_DESCRIPTION("Sensirion SGPxx gas sensors");
> +MODULE_LICENSE("GPL v2");
> +MODULE_VERSION("0.5.0");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] io: core: mark expected switch fall-through

2017-11-08 Thread Peter Meerwald-Stadler

> In preparation to enabling -Wimplicit-fallthrough, mark switch cases
> where we are expecting to fall through.

please fix the subject line, should be 
iio: core: Mark...

thx, p.
 
> Addresses-Coverity-ID: 1397962
> Signed-off-by: Gustavo A. R. Silva <garsi...@embeddedor.com>
> ---
>  drivers/iio/industrialio-core.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index 9c4cfd1..2e8e36f 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -588,6 +588,7 @@ static ssize_t __iio_format_value(char *buf, size_t len, 
> unsigned int type,
>   return snprintf(buf, len, "%d", vals[0]);
>   case IIO_VAL_INT_PLUS_MICRO_DB:
>   scale_db = true;
> + /* fall through */
>   case IIO_VAL_INT_PLUS_MICRO:
>   if (vals[1] < 0)
>   return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] io: core: mark expected switch fall-through

2017-11-08 Thread Peter Meerwald-Stadler

> In preparation to enabling -Wimplicit-fallthrough, mark switch cases
> where we are expecting to fall through.

please fix the subject line, should be 
iio: core: Mark...

thx, p.
 
> Addresses-Coverity-ID: 1397962
> Signed-off-by: Gustavo A. R. Silva 
> ---
>  drivers/iio/industrialio-core.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index 9c4cfd1..2e8e36f 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -588,6 +588,7 @@ static ssize_t __iio_format_value(char *buf, size_t len, 
> unsigned int type,
>   return snprintf(buf, len, "%d", vals[0]);
>   case IIO_VAL_INT_PLUS_MICRO_DB:
>   scale_db = true;
> + /* fall through */
>   case IIO_VAL_INT_PLUS_MICRO:
>   if (vals[1] < 0)
>       return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v4] iio : Add cm3218 smbus ara and acpi support

2017-10-27 Thread Peter Meerwald-Stadler
->chip_id = id->driver_data;
> + } else if (ACPI_COMPANION(>dev)) {
> + acpi_id = 
> acpi_match_device(client->dev.driver->acpi_match_table,
> + >dev);
> + if (!acpi_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)acpi_id->driver_data;
> + } else if (client->dev.of_node) {
> + of_id = of_match_device(clients->dev.driver->of_match_table,
> + >dev);
> + if (!of_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)of_id->data;
> + } else {
> + return -ENODEV;
> + }
> +
> + if (cm32181->chip_id == CM3218_ID) {
> + if (client->addr == CM3218_ARA_ADDR) {
> + /*
> +  * In case first address is the ARA device
> +  * lookup for a second one in acpi resources if
> +  * this client is enumerated on acpi
> +  */
> + ret = cm3218_acpi_get_address(client);
> + if (ret < 0)
> + return -ENODEV;
> + }
> +
> +#ifdef CONFIG_I2C_SMBUS
> + if (client->irq > 0) {
> + /* setup smb alert device */
> + ara_setup.irq = client->irq;
> + ara_setup.alert_edge_triggered = 0;
> + cm32181->ara = i2c_setup_smbus_alert(client->adapter,
> +  _setup);
> + if (!cm32181->ara)
> + return -ENODEV;
> + } else {
> + return -ENODEV;
> + }
> +#else
> + return -ENODEV;
> +#endif
> + }
> +
>   ret = cm32181_reg_init(cm32181);
>   if (ret) {
>   dev_err(>dev,
>   "%s: register init failed\n",
>   __func__);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
>   return ret;
>   }
>  
> @@ -336,32 +478,58 @@ static int cm32181_probe(struct i2c_client *client,
>   dev_err(>dev,
>   "%s: regist device failed\n",
>   __func__);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
>   return ret;
>   }
>  
>   return 0;
>  }
>  
> +static int cm32181_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct cm32181_chip *cm32181 = iio_priv(indio_dev);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
> + return 0;
> +};
> +
>  static const struct i2c_device_id cm32181_id[] = {
> - { "cm32181", 0 },
> + { "cm32181", CM32181_ID },
> + { "cm3218", CM3218_ID },
>   { }
>  };
>  
>  MODULE_DEVICE_TABLE(i2c, cm32181_id);
>  
>  static const struct of_device_id cm32181_of_match[] = {
> - { .compatible = "capella,cm32181" },
> + { .compatible = "capella,cm32181", (void *)CM32181_ID },
> + { .compatible = "capella,cm3218",  (void *)CM3218_ID },
>   { }
>  };
>  MODULE_DEVICE_TABLE(of, cm32181_of_match);
>  
> +static const struct acpi_device_id cm32181_acpi_match[] = {
> + { "CPLM3218", CM3218_ID },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(acpi, cm32181_acpi_match);
> +
>  static struct i2c_driver cm32181_driver = {
>   .driver = {
>   .name   = "cm32181",
>   .of_match_table = of_match_ptr(cm32181_of_match),
> + .acpi_match_table = ACPI_PTR(cm32181_acpi_match),
>   },
>   .id_table   = cm32181_id,
>   .probe  = cm32181_probe,
> + .remove = cm32181_remove,
>  };
>  
>  module_i2c_driver(cm32181_driver);
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v4] iio : Add cm3218 smbus ara and acpi support

2017-10-27 Thread Peter Meerwald-Stadler
ACPI_COMPANION(>dev)) {
> + acpi_id = 
> acpi_match_device(client->dev.driver->acpi_match_table,
> + >dev);
> + if (!acpi_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)acpi_id->driver_data;
> + } else if (client->dev.of_node) {
> + of_id = of_match_device(clients->dev.driver->of_match_table,
> + >dev);
> + if (!of_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)of_id->data;
> + } else {
> + return -ENODEV;
> + }
> +
> + if (cm32181->chip_id == CM3218_ID) {
> + if (client->addr == CM3218_ARA_ADDR) {
> + /*
> +  * In case first address is the ARA device
> +  * lookup for a second one in acpi resources if
> +  * this client is enumerated on acpi
> +  */
> + ret = cm3218_acpi_get_address(client);
> + if (ret < 0)
> + return -ENODEV;
> + }
> +
> +#ifdef CONFIG_I2C_SMBUS
> + if (client->irq > 0) {
> + /* setup smb alert device */
> + ara_setup.irq = client->irq;
> + ara_setup.alert_edge_triggered = 0;
> + cm32181->ara = i2c_setup_smbus_alert(client->adapter,
> +  _setup);
> + if (!cm32181->ara)
> + return -ENODEV;
> + } else {
> + return -ENODEV;
> + }
> +#else
> + return -ENODEV;
> +#endif
> + }
> +
>   ret = cm32181_reg_init(cm32181);
>   if (ret) {
>   dev_err(>dev,
>   "%s: register init failed\n",
>   __func__);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
>   return ret;
>   }
>  
> @@ -336,32 +478,58 @@ static int cm32181_probe(struct i2c_client *client,
>   dev_err(>dev,
>   "%s: regist device failed\n",
>   __func__);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
>   return ret;
>   }
>  
>   return 0;
>  }
>  
> +static int cm32181_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct cm32181_chip *cm32181 = iio_priv(indio_dev);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
> + return 0;
> +};
> +
>  static const struct i2c_device_id cm32181_id[] = {
> - { "cm32181", 0 },
> + { "cm32181", CM32181_ID },
> + { "cm3218", CM3218_ID },
>   { }
>  };
>  
>  MODULE_DEVICE_TABLE(i2c, cm32181_id);
>  
>  static const struct of_device_id cm32181_of_match[] = {
> - { .compatible = "capella,cm32181" },
> + { .compatible = "capella,cm32181", (void *)CM32181_ID },
> + { .compatible = "capella,cm3218",  (void *)CM3218_ID },
>   { }
>  };
>  MODULE_DEVICE_TABLE(of, cm32181_of_match);
>  
> +static const struct acpi_device_id cm32181_acpi_match[] = {
> + { "CPLM3218", CM3218_ID },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(acpi, cm32181_acpi_match);
> +
>  static struct i2c_driver cm32181_driver = {
>   .driver = {
>   .name   = "cm32181",
>   .of_match_table = of_match_ptr(cm32181_of_match),
> + .acpi_match_table = ACPI_PTR(cm32181_acpi_match),
>   },
>   .id_table   = cm32181_id,
>   .probe  = cm32181_probe,
> + .remove = cm32181_remove,
>  };
>  
>  module_i2c_driver(cm32181_driver);
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: iio/accel/stk8312: Improve unlocking of a mutex in two functions

2017-10-27 Thread Peter Meerwald-Stadler
Hello,

> Maybe …
> But I proposed an other source code layout for useful reasons.

I think there is a (hidden) cost of having pure cleanup patches:
they make backporting fixes harder (across the cleanup)

stylistic changes must have a clear benefit, readability is subjective, 
consistency per se doesn't buy anything

the discussion how code should be written in the first place is separate
from the discussion what is worth fixing up lateron (IMHO)

> > There is no firm rule about error handling in one place.
> 
> There are some design options available.
> 
> 
> > If it leads to more complex flow as here, don't do it.
> 
> I would appreciate to clarify such a view a bit more.
> How would you like to achieve a complete and efficient
> exception handling in shown places?

regards, p.

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: iio/accel/stk8312: Improve unlocking of a mutex in two functions

2017-10-27 Thread Peter Meerwald-Stadler
Hello,

> Maybe …
> But I proposed an other source code layout for useful reasons.

I think there is a (hidden) cost of having pure cleanup patches:
they make backporting fixes harder (across the cleanup)

stylistic changes must have a clear benefit, readability is subjective, 
consistency per se doesn't buy anything

the discussion how code should be written in the first place is separate
from the discussion what is worth fixing up lateron (IMHO)

> > There is no firm rule about error handling in one place.
> 
> There are some design options available.
> 
> 
> > If it leads to more complex flow as here, don't do it.
> 
> I would appreciate to clarify such a view a bit more.
> How would you like to achieve a complete and efficient
> exception handling in shown places?

regards, p.

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH v2] iio : Add cm3218 smbus ara and acpi support

2017-10-26 Thread Peter Meerwald-Stadler
 cm3218_get_i2c_address,
> +  client);
> + acpi_dev_free_resource_list();
> + if (ret < 0)
> + return -ENODEV;
> +
> + return 0;
> +}
> +#else
> +static inline int cm3218_acpi_get_address(struct i2c_client *client)

why inline?

> +{
> + return -ENODEV;
> +}
> +#endif
> +
>  static int cm32181_probe(struct i2c_client *client,
>   const struct i2c_device_id *id)
>  {
>   struct cm32181_chip *cm32181;
>   struct iio_dev *indio_dev;
>   int ret;
> + struct i2c_smbus_alert_setup ara_setup;
> + const struct of_device_id *of_id;
> + const struct acpi_device_id *acpi_id;
>  
>   indio_dev = devm_iio_device_alloc(>dev, sizeof(*cm32181));
>   if (!indio_dev) {
> @@ -323,11 +402,65 @@ static int cm32181_probe(struct i2c_client *client,
>   indio_dev->name = id->name;
>   indio_dev->modes = INDIO_DIRECT_MODE;
>  
> + /* Lookup for chip ID from platform, acpi or of device table */
> + if (id) {
> + cm32181->chip_id = id->driver_data;
> + } else if (ACPI_COMPANION(>dev)) {
> + acpi_id = 
> acpi_match_device(client->dev.driver->acpi_match_table,
> + >dev);
> + if (!acpi_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)acpi_id->driver_data;
> + } else if (client->dev.of_node) {
> + of_id = of_match_device(clients->dev.driver->of_match_table,
> + >dev);
> + if (!of_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)of_id->data;
> + } else {
> + return -ENODEV;
> + }
> +
> + if (cm32181->chip_id == CM3218_ID) {
> + if (client->addr == CM3218_ARA_ADDR) {
> + /* In case first address is the ARA device
> +  * lookup for a second one in acpi resources if
> +  * this client is enumerated on acpi
> +  */
> + ret = cm3218_acpi_get_address(client);
> + if (ret < 0)
> + return -ENODEV;
> + }
> +
> +#ifdef CONFIG_I2C_SMBUS
> + if (client->irq > 0) {
> + /* setup smb alert device

single line comment

> +  */
> + ara_setup.irq = client->irq;
> + ara_setup.alert_edge_triggered = 0;
> + cm32181->ara = i2c_setup_smbus_alert(client->adapter,
> +  _setup);
> + if (!cm32181->ara)
> + return -ENODEV;
> + } else {
> + return -ENODEV;
> + }
> +#else
> + return -ENODEV;
> +#endif
> + }
> +
>   ret = cm32181_reg_init(cm32181);
>   if (ret) {
>   dev_err(>dev,
>   "%s: register init failed\n",
>   __func__);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
>   return ret;
>   }
>  
> @@ -336,32 +469,58 @@ static int cm32181_probe(struct i2c_client *client,
>   dev_err(>dev,
>   "%s: regist device failed\n",
>   __func__);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
>   return ret;
>   }
>  
>   return 0;
>  }
>  
> +static int cm32181_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct cm32181_chip *cm32181 = iio_priv(indio_dev);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
> + return 0;
> +};
> +
>  static const struct i2c_device_id cm32181_id[] = {
> - { "cm32181", 0 },
> + { "cm32181", CM32181_ID },
> + { "cm3218", CM3218_ID },
>   { }
>  };
>  
>  MODULE_DEVICE_TABLE(i2c, cm32181_id);
>  
>  static const struct of_device_id cm32181_of_match[] = {
> - { .compatible = "capella,cm32181" },
> + { .compatible = "capella,cm32181", (void *)CM32181_ID },
> + { .compatible = "capella,cm3218",  (void *)CM3218_ID },
>   { }
>  };
>  MODULE_DEVICE_TABLE(of, cm32181_of_match);
>  
> +static const struct acpi_device_id cm32181_acpi_match[] = {
> + { "CPLM3218", CM3218_ID },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(acpi, cm32181_acpi_match);
> +
>  static struct i2c_driver cm32181_driver = {
>   .driver = {
>   .name   = "cm32181",
>   .of_match_table = of_match_ptr(cm32181_of_match),
> + .acpi_match_table = ACPI_PTR(cm32181_acpi_match),
>   },
>   .id_table   = cm32181_id,
>   .probe  = cm32181_probe,
> + .remove = cm32181_remove,
>  };
>  
>  module_i2c_driver(cm32181_driver);
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2] iio : Add cm3218 smbus ara and acpi support

2017-10-26 Thread Peter Meerwald-Stadler
  client);
> + acpi_dev_free_resource_list();
> + if (ret < 0)
> + return -ENODEV;
> +
> + return 0;
> +}
> +#else
> +static inline int cm3218_acpi_get_address(struct i2c_client *client)

why inline?

> +{
> + return -ENODEV;
> +}
> +#endif
> +
>  static int cm32181_probe(struct i2c_client *client,
>   const struct i2c_device_id *id)
>  {
>   struct cm32181_chip *cm32181;
>   struct iio_dev *indio_dev;
>   int ret;
> + struct i2c_smbus_alert_setup ara_setup;
> + const struct of_device_id *of_id;
> + const struct acpi_device_id *acpi_id;
>  
>   indio_dev = devm_iio_device_alloc(>dev, sizeof(*cm32181));
>   if (!indio_dev) {
> @@ -323,11 +402,65 @@ static int cm32181_probe(struct i2c_client *client,
>   indio_dev->name = id->name;
>   indio_dev->modes = INDIO_DIRECT_MODE;
>  
> + /* Lookup for chip ID from platform, acpi or of device table */
> + if (id) {
> + cm32181->chip_id = id->driver_data;
> + } else if (ACPI_COMPANION(>dev)) {
> + acpi_id = 
> acpi_match_device(client->dev.driver->acpi_match_table,
> + >dev);
> + if (!acpi_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)acpi_id->driver_data;
> + } else if (client->dev.of_node) {
> + of_id = of_match_device(clients->dev.driver->of_match_table,
> + >dev);
> + if (!of_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)of_id->data;
> + } else {
> + return -ENODEV;
> + }
> +
> + if (cm32181->chip_id == CM3218_ID) {
> + if (client->addr == CM3218_ARA_ADDR) {
> + /* In case first address is the ARA device
> +  * lookup for a second one in acpi resources if
> +  * this client is enumerated on acpi
> +  */
> + ret = cm3218_acpi_get_address(client);
> + if (ret < 0)
> + return -ENODEV;
> + }
> +
> +#ifdef CONFIG_I2C_SMBUS
> + if (client->irq > 0) {
> + /* setup smb alert device

single line comment

> +  */
> + ara_setup.irq = client->irq;
> + ara_setup.alert_edge_triggered = 0;
> + cm32181->ara = i2c_setup_smbus_alert(client->adapter,
> +  _setup);
> + if (!cm32181->ara)
> + return -ENODEV;
> + } else {
> + return -ENODEV;
> + }
> +#else
> + return -ENODEV;
> +#endif
> + }
> +
>   ret = cm32181_reg_init(cm32181);
>   if (ret) {
>   dev_err(>dev,
>   "%s: register init failed\n",
>   __func__);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
>   return ret;
>   }
>  
> @@ -336,32 +469,58 @@ static int cm32181_probe(struct i2c_client *client,
>   dev_err(>dev,
>   "%s: regist device failed\n",
>   __func__);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
>   return ret;
>   }
>  
>   return 0;
>  }
>  
> +static int cm32181_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct cm32181_chip *cm32181 = iio_priv(indio_dev);
> +
> + if (cm32181->ara)
> + i2c_unregister_device(cm32181->ara);
> +
> + return 0;
> +};
> +
>  static const struct i2c_device_id cm32181_id[] = {
> - { "cm32181", 0 },
> + { "cm32181", CM32181_ID },
> + { "cm3218", CM3218_ID },
>   { }
>  };
>  
>  MODULE_DEVICE_TABLE(i2c, cm32181_id);
>  
>  static const struct of_device_id cm32181_of_match[] = {
> - { .compatible = "capella,cm32181" },
> + { .compatible = "capella,cm32181", (void *)CM32181_ID },
> + { .compatible = "capella,cm3218",  (void *)CM3218_ID },
>   { }
>  };
>  MODULE_DEVICE_TABLE(of, cm32181_of_match);
>  
> +static const struct acpi_device_id cm32181_acpi_match[] = {
> + { "CPLM3218", CM3218_ID },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(acpi, cm32181_acpi_match);
> +
>  static struct i2c_driver cm32181_driver = {
>   .driver = {
>   .name   = "cm32181",
>   .of_match_table = of_match_ptr(cm32181_of_match),
> + .acpi_match_table = ACPI_PTR(cm32181_acpi_match),
>   },
>   .id_table   = cm32181_id,
>   .probe  = cm32181_probe,
> + .remove = cm32181_remove,
>  };
>  
>  module_i2c_driver(cm32181_driver);
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 1/4] iio: light: vl6180: Move range check to integration time setter, cleanup

2017-09-19 Thread Peter Meerwald-Stadler

> This improves code uniformity (range checks for als_gain are also done
> in the setter). Also unmangle rounding and calculation of register value.

nitpick below
 
> The calculated integration time it_ms is required in the next patch of
> the series.
> 
> Signed-off-by: Stefan BrĂĽns <stefan.bru...@rwth-aachen.de>
> ---
>  drivers/iio/light/vl6180.c | 18 +++---
>  1 file changed, 11 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c
> index 6e25b724d941..57577d5d18ac 100644
> --- a/drivers/iio/light/vl6180.c
> +++ b/drivers/iio/light/vl6180.c
> @@ -386,16 +386,21 @@ static int vl6180_set_als_gain(struct vl6180_data 
> *data, int val, int val2)
>   return -EINVAL;
>  }
>  
> -static int vl6180_set_it(struct vl6180_data *data, int val2)
> +static int vl6180_set_it(struct vl6180_data *data, int val, int val2)
>  {
> - int ret;
> + int ret, it_ms;
> +
> + it_ms = ((val2 + 500) / 1000); /* round to ms */

outer parenthesis not necessary

> + if (val != 0 || it_ms < 1 || it_ms > 512)
> + return -EINVAL;
>  
>   mutex_lock(>lock);
>   ret = vl6180_hold(data, true);
>   if (ret < 0)
>   goto fail;
> - ret = vl6180_write_word(data->client, VL6180_ALS_IT,
> - (val2 - 500) / 1000); /* write value in ms */
> +
> + ret = vl6180_write_word(data->client, VL6180_ALS_IT, it_ms - 1);
> +
>  fail:
>   vl6180_hold(data, false);
>   mutex_unlock(>lock);
> @@ -411,15 +416,14 @@ static int vl6180_write_raw(struct iio_dev *indio_dev,
>  
>   switch (mask) {
>   case IIO_CHAN_INFO_INT_TIME:
> - if (val != 0 || val2 < 500 || val2 >= 512500)
> - return -EINVAL;
> + return vl6180_set_it(data, val, val2);
>  
> - return vl6180_set_it(data, val2);
>   case IIO_CHAN_INFO_HARDWAREGAIN:
>   if (chan->type != IIO_LIGHT)
>   return -EINVAL;
>  
>   return vl6180_set_als_gain(data, val, val2);
> +
>   default:
>   return -EINVAL;
>   }
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH 1/4] iio: light: vl6180: Move range check to integration time setter, cleanup

2017-09-19 Thread Peter Meerwald-Stadler

> This improves code uniformity (range checks for als_gain are also done
> in the setter). Also unmangle rounding and calculation of register value.

nitpick below
 
> The calculated integration time it_ms is required in the next patch of
> the series.
> 
> Signed-off-by: Stefan BrĂĽns 
> ---
>  drivers/iio/light/vl6180.c | 18 +++---
>  1 file changed, 11 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c
> index 6e25b724d941..57577d5d18ac 100644
> --- a/drivers/iio/light/vl6180.c
> +++ b/drivers/iio/light/vl6180.c
> @@ -386,16 +386,21 @@ static int vl6180_set_als_gain(struct vl6180_data 
> *data, int val, int val2)
>   return -EINVAL;
>  }
>  
> -static int vl6180_set_it(struct vl6180_data *data, int val2)
> +static int vl6180_set_it(struct vl6180_data *data, int val, int val2)
>  {
> - int ret;
> + int ret, it_ms;
> +
> + it_ms = ((val2 + 500) / 1000); /* round to ms */

outer parenthesis not necessary

> + if (val != 0 || it_ms < 1 || it_ms > 512)
> + return -EINVAL;
>  
>   mutex_lock(>lock);
>   ret = vl6180_hold(data, true);
>   if (ret < 0)
>   goto fail;
> - ret = vl6180_write_word(data->client, VL6180_ALS_IT,
> - (val2 - 500) / 1000); /* write value in ms */
> +
> + ret = vl6180_write_word(data->client, VL6180_ALS_IT, it_ms - 1);
> +
>  fail:
>   vl6180_hold(data, false);
>   mutex_unlock(>lock);
> @@ -411,15 +416,14 @@ static int vl6180_write_raw(struct iio_dev *indio_dev,
>  
>   switch (mask) {
>   case IIO_CHAN_INFO_INT_TIME:
> - if (val != 0 || val2 < 500 || val2 >= 512500)
> - return -EINVAL;
> + return vl6180_set_it(data, val, val2);
>  
> - return vl6180_set_it(data, val2);
>   case IIO_CHAN_INFO_HARDWAREGAIN:
>   if (chan->type != IIO_LIGHT)
>   return -EINVAL;
>  
>   return vl6180_set_als_gain(data, val, val2);
> +
>   default:
>   return -EINVAL;
>   }
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH 3/4] iio: light: vl6180: Cleanup als_gain lookup, avoid register readback

2017-09-19 Thread Peter Meerwald-Stadler
et = vl6180_hold(data, true);
> + if (ret < 0)
> + goto fail;
>  
> - return -EINVAL;
> + ret = vl6180_write_byte(data->client, VL6180_ALS_GAIN,
> + vl6180_als_gain_tab_bits[i]);
> +
> + if (ret >= 0)
> + data->als_gain_milli = vl6180_als_gain_tab[i];
> +
> +fail:
> + vl6180_hold(data, false);
> + mutex_unlock(>lock);
> + return ret;
>  }
>  
>  static int vl6180_set_it(struct vl6180_data *data, int val, int val2)
> @@ -480,6 +482,7 @@ static int vl6180_init(struct vl6180_data *data)
>   return ret;
>  
>   /* ALS gain: 1 */
> + data->als_gain_milli = 1000;
>   ret = vl6180_write_byte(client, VL6180_ALS_GAIN, VL6180_ALS_GAIN_1);
>   if (ret < 0)
>   return ret;
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH 3/4] iio: light: vl6180: Cleanup als_gain lookup, avoid register readback

2017-09-19 Thread Peter Meerwald-Stadler
ret < 0)
> + goto fail;
>  
> - return -EINVAL;
> + ret = vl6180_write_byte(data->client, VL6180_ALS_GAIN,
> + vl6180_als_gain_tab_bits[i]);
> +
> + if (ret >= 0)
> + data->als_gain_milli = vl6180_als_gain_tab[i];
> +
> +fail:
> + vl6180_hold(data, false);
> + mutex_unlock(>lock);
> + return ret;
>  }
>  
>  static int vl6180_set_it(struct vl6180_data *data, int val, int val2)
> @@ -480,6 +482,7 @@ static int vl6180_init(struct vl6180_data *data)
>   return ret;
>  
>   /* ALS gain: 1 */
> + data->als_gain_milli = 1000;
>   ret = vl6180_write_byte(client, VL6180_ALS_GAIN, VL6180_ALS_GAIN_1);
>   if (ret < 0)
>   return ret;
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH v3] iio: dac: ds4422/ds4424 dac driver

2017-09-18 Thread Peter Meerwald-Stadler
the regulator.\n");
> + return ret;
> + }
> +
> + usleep_range(1000, 1200);
> + ret = ds4424_verify_chip(indio_dev);
> + if (ret < 0)
> + return -ENXIO;
> +
> + switch (id->driver_data) {
> + case ID_DS4422:
> + indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS;
> + break;
> + case ID_DS4424:
> + indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS;
> + break;
> + default:
> + dev_err(>dev,
> + "ds4424: Invalid chip id.\n");
> + regulator_disable(data->vcc_reg);
> + return -ENXIO;
> + }
> +
> + indio_dev->channels = ds4424_channels;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret < 0) {
> + dev_err(>dev,
> + "iio_device_register failed. ret: %d\n", ret);
> + regulator_disable(data->vcc_reg);
> + }
> +
> + return ret;
> +}
> +
> +static int ds4424_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct ds4424_data *data = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> + regulator_disable(data->vcc_reg);
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id ds4424_id[] = {
> + { "ds4422", ID_DS4422 },
> + { "ds4424", ID_DS4424 },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, ds4424_id);
> +
> +static const struct of_device_id ds4424_of_match[] = {
> + { .compatible = "maxim,ds4422" },
> + { .compatible = "maxim,ds4424" },
> + { },
> +};
> +
> +MODULE_DEVICE_TABLE(of, ds4424_of_match);
> +
> +static struct i2c_driver ds4424_driver = {
> + .driver = {
> + .name   = "ds4424",
> + .of_match_table = ds4424_of_match,
> + .pm = _pm_ops,
> + },
> + .probe  = ds4424_probe,
> + .remove = ds4424_remove,
> + .id_table   = ds4424_id,
> +};
> +module_i2c_driver(ds4424_driver);
> +
> +MODULE_DESCRIPTION("Maxim DS4424 DAC Driver");
> +MODULE_AUTHOR("Ismail H. Kose <ismail.k...@maximintegrated.com>");
> +MODULE_AUTHOR("Vishal Sood <vishal.s...@maximintegrated.com>");
> +MODULE_AUTHOR("David Jung <david.j...@maximintegrated.com>");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v3] iio: dac: ds4422/ds4424 dac driver

2017-09-18 Thread Peter Meerwald-Stadler
);
> + return ret;
> + }
> +
> + usleep_range(1000, 1200);
> + ret = ds4424_verify_chip(indio_dev);
> + if (ret < 0)
> + return -ENXIO;
> +
> + switch (id->driver_data) {
> + case ID_DS4422:
> + indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS;
> + break;
> + case ID_DS4424:
> + indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS;
> + break;
> + default:
> + dev_err(>dev,
> + "ds4424: Invalid chip id.\n");
> + regulator_disable(data->vcc_reg);
> + return -ENXIO;
> + }
> +
> + indio_dev->channels = ds4424_channels;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret < 0) {
> + dev_err(>dev,
> + "iio_device_register failed. ret: %d\n", ret);
> + regulator_disable(data->vcc_reg);
> + }
> +
> + return ret;
> +}
> +
> +static int ds4424_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct ds4424_data *data = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> + regulator_disable(data->vcc_reg);
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id ds4424_id[] = {
> + { "ds4422", ID_DS4422 },
> + { "ds4424", ID_DS4424 },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, ds4424_id);
> +
> +static const struct of_device_id ds4424_of_match[] = {
> + { .compatible = "maxim,ds4422" },
> + { .compatible = "maxim,ds4424" },
> + { },
> +};
> +
> +MODULE_DEVICE_TABLE(of, ds4424_of_match);
> +
> +static struct i2c_driver ds4424_driver = {
> + .driver = {
> + .name   = "ds4424",
> + .of_match_table = ds4424_of_match,
> + .pm = _pm_ops,
> + },
> + .probe  = ds4424_probe,
> + .remove = ds4424_remove,
> + .id_table   = ds4424_id,
> +};
> +module_i2c_driver(ds4424_driver);
> +
> +MODULE_DESCRIPTION("Maxim DS4424 DAC Driver");
> +MODULE_AUTHOR("Ismail H. Kose ");
> +MODULE_AUTHOR("Vishal Sood ");
> +MODULE_AUTHOR("David Jung ");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: imu: inv_mpu6050: fix missing break in switch

2017-08-23 Thread Peter Meerwald-Stadler

> Add missing break statement to prevent the code for case
> IIO_CHAN_INFO_CALIBBIAS falling through to the default case.
> 
> Also, add a break to the default case for the switch within
> case IIO_CHAN_INFO_CALIBBIAS.

fix seems to be cosmetic only...

> Addresses-Coverity-ID: 1357377
> Signed-off-by: Gustavo A. R. Silva <gust...@embeddedor.com>
> ---
> This issue was reported by Coverity and it was tested by compilation only.
> Please, verify if this is an actual bug.
> 
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c 
> b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index 44830bc..6d2268a 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -542,7 +542,9 @@ static int inv_mpu6050_write_raw(struct iio_dev 
> *indio_dev,
>   break;
>   default:
>   result = -EINVAL;
> + break;
>   }
> + break;
>   default:
>   result = -EINVAL;
>   break;
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: imu: inv_mpu6050: fix missing break in switch

2017-08-23 Thread Peter Meerwald-Stadler

> Add missing break statement to prevent the code for case
> IIO_CHAN_INFO_CALIBBIAS falling through to the default case.
> 
> Also, add a break to the default case for the switch within
> case IIO_CHAN_INFO_CALIBBIAS.

fix seems to be cosmetic only...

> Addresses-Coverity-ID: 1357377
> Signed-off-by: Gustavo A. R. Silva 
> ---
> This issue was reported by Coverity and it was tested by compilation only.
> Please, verify if this is an actual bug.
> 
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c 
> b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index 44830bc..6d2268a 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -542,7 +542,9 @@ static int inv_mpu6050_write_raw(struct iio_dev 
> *indio_dev,
>   break;
>   default:
>   result = -EINVAL;
> + break;
>   }
> + break;
>       default:
>   result = -EINVAL;
>   break;
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] mfd: Add support for TI LMP92001

2017-08-22 Thread Peter Meerwald-Stadler

> From: Abhisit Sangjan 
> 
> TI LMP92001 Analog System Monitor and Controller

some minor comments, not a full review
 
> 8-bit GPIOs.
> 12 DACs with 12-bit resolution.
> The GPIOs and DACs are shared port function with Cy function pin to
> take control the pin suddenly from external hardware.
> DAC's referance voltage selectable for Internal/External.

typo, reference (here and below)

> 16 + 1 ADCs with 12-bit resolution.
> Built-in internal Temperature Sensor on channel 17.
> Windows Comparator Function is supported on channel 1-3 and 9-11 for

Window (here and below)

> monitoring with interrupt signal (pending to implement for interrupt).
> ADC's referance voltage selectable for Internal/External.

reference

> Signed-off-by: Abhisit Sangjan 
> ---
>  Documentation/ABI/testing/sysfs-bus-iio-lmp920001  |  92 
>  .../devicetree/bindings/gpio/gpio-lmp92001.txt |  22 +
>  .../bindings/iio/adc/ti-lmp92001-adc.txt   |  21 +
>  .../bindings/iio/dac/ti-lmp92001-dac.txt   |  35 ++
>  drivers/gpio/Kconfig   |   7 +
>  drivers/gpio/Makefile  |   1 +
>  drivers/gpio/gpio-lmp92001.c   | 209 +
>  drivers/iio/adc/Kconfig|  10 +
>  drivers/iio/adc/Makefile   |   1 +
>  drivers/iio/adc/lmp92001-adc.c | 500 
> +
>  drivers/iio/dac/Kconfig|   9 +
>  drivers/iio/dac/Makefile   |   1 +
>  drivers/iio/dac/lmp92001-dac.c | 390 
>  drivers/mfd/Kconfig|  12 +
>  drivers/mfd/Makefile   |   4 +
>  drivers/mfd/lmp92001-core.c| 308 +
>  drivers/mfd/lmp92001-debug.c   |  67 +++
>  drivers/mfd/lmp92001-i2c.c | 215 +
>  include/linux/mfd/lmp92001/core.h  | 119 +
>  include/linux/mfd/lmp92001/debug.h |  28 ++
>  20 files changed, 2051 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-lmp920001
>  create mode 100644 Documentation/devicetree/bindings/gpio/gpio-lmp92001.txt
>  create mode 100644 
> Documentation/devicetree/bindings/iio/adc/ti-lmp92001-adc.txt
>  create mode 100644 
> Documentation/devicetree/bindings/iio/dac/ti-lmp92001-dac.txt
>  create mode 100644 drivers/gpio/gpio-lmp92001.c
>  create mode 100644 drivers/iio/adc/lmp92001-adc.c
>  create mode 100644 drivers/iio/dac/lmp92001-dac.c
>  create mode 100644 drivers/mfd/lmp92001-core.c
>  create mode 100644 drivers/mfd/lmp92001-debug.c
>  create mode 100644 drivers/mfd/lmp92001-i2c.c
>  create mode 100644 include/linux/mfd/lmp92001/core.h
>  create mode 100644 include/linux/mfd/lmp92001/debug.h
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-lmp920001 
> b/Documentation/ABI/testing/sysfs-bus-iio-lmp920001
> new file mode 100644
> index 000..bd4e733
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-lmp920001
> @@ -0,0 +1,92 @@
> +What:   /sys/bus/iio/devices/iio:deviceX/gang
> +Date:August 2016
> +KernelVersion:  4.1.15

update? (here and below)

> +Contact:Abhisit Sangjan 
> +Description:
> + Controls the association of analog output channels OUTx with
> + asynchronous control inputs Cy for DAC.
> +Can be either:
> +- "0"
> +- "1"
> +
> + Cy to OUTx Assignment
> + --
> + | Cy | CDAC:GANG=0 | CDAC:GANG=1 |
> + --
> + | C1 | OUT[1:4]| OUT[1:3]|
> + --
> + | C2 | OUT[5:6]| OUT[4:6]|
> + --
> + | C3 | OUT[7:8]| OUT[7:9]|
> + --
> + | C4 | OUT[9:12]   | OUT[10:12]  |
> + --
> +
> +What:   /sys/bus/iio/devices/iio:deviceX/outx
> +Date:August 2016
> +KernelVersion:  4.1.15
> +Contact:Abhisit Sangjan 
> +Description:
> + The pin output mode for DAC.
> +Can be either:
> +- "hiz" = High impedance state.
> +- "dac" = DAC output.
> + - "0" = Drive it to low.
> + - "1" = Drive it to high.
> +
> +What:   /sys/bus/iio/devices/iio:deviceX/vref
> +Date:August 2016
> +KernelVersion:  4.1.15
> +Contact:Abhisit Sangjan 
> +Description:
> + This is voltage referance source for DACs.
> +Can be either:
> +- "external"
> +

Re: [PATCH] mfd: Add support for TI LMP92001

2017-08-22 Thread Peter Meerwald-Stadler

> From: Abhisit Sangjan 
> 
> TI LMP92001 Analog System Monitor and Controller

some minor comments, not a full review
 
> 8-bit GPIOs.
> 12 DACs with 12-bit resolution.
> The GPIOs and DACs are shared port function with Cy function pin to
> take control the pin suddenly from external hardware.
> DAC's referance voltage selectable for Internal/External.

typo, reference (here and below)

> 16 + 1 ADCs with 12-bit resolution.
> Built-in internal Temperature Sensor on channel 17.
> Windows Comparator Function is supported on channel 1-3 and 9-11 for

Window (here and below)

> monitoring with interrupt signal (pending to implement for interrupt).
> ADC's referance voltage selectable for Internal/External.

reference

> Signed-off-by: Abhisit Sangjan 
> ---
>  Documentation/ABI/testing/sysfs-bus-iio-lmp920001  |  92 
>  .../devicetree/bindings/gpio/gpio-lmp92001.txt |  22 +
>  .../bindings/iio/adc/ti-lmp92001-adc.txt   |  21 +
>  .../bindings/iio/dac/ti-lmp92001-dac.txt   |  35 ++
>  drivers/gpio/Kconfig   |   7 +
>  drivers/gpio/Makefile  |   1 +
>  drivers/gpio/gpio-lmp92001.c   | 209 +
>  drivers/iio/adc/Kconfig|  10 +
>  drivers/iio/adc/Makefile   |   1 +
>  drivers/iio/adc/lmp92001-adc.c | 500 
> +
>  drivers/iio/dac/Kconfig|   9 +
>  drivers/iio/dac/Makefile   |   1 +
>  drivers/iio/dac/lmp92001-dac.c | 390 
>  drivers/mfd/Kconfig|  12 +
>  drivers/mfd/Makefile   |   4 +
>  drivers/mfd/lmp92001-core.c| 308 +
>  drivers/mfd/lmp92001-debug.c   |  67 +++
>  drivers/mfd/lmp92001-i2c.c | 215 +
>  include/linux/mfd/lmp92001/core.h  | 119 +
>  include/linux/mfd/lmp92001/debug.h |  28 ++
>  20 files changed, 2051 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-lmp920001
>  create mode 100644 Documentation/devicetree/bindings/gpio/gpio-lmp92001.txt
>  create mode 100644 
> Documentation/devicetree/bindings/iio/adc/ti-lmp92001-adc.txt
>  create mode 100644 
> Documentation/devicetree/bindings/iio/dac/ti-lmp92001-dac.txt
>  create mode 100644 drivers/gpio/gpio-lmp92001.c
>  create mode 100644 drivers/iio/adc/lmp92001-adc.c
>  create mode 100644 drivers/iio/dac/lmp92001-dac.c
>  create mode 100644 drivers/mfd/lmp92001-core.c
>  create mode 100644 drivers/mfd/lmp92001-debug.c
>  create mode 100644 drivers/mfd/lmp92001-i2c.c
>  create mode 100644 include/linux/mfd/lmp92001/core.h
>  create mode 100644 include/linux/mfd/lmp92001/debug.h
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-lmp920001 
> b/Documentation/ABI/testing/sysfs-bus-iio-lmp920001
> new file mode 100644
> index 000..bd4e733
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-lmp920001
> @@ -0,0 +1,92 @@
> +What:   /sys/bus/iio/devices/iio:deviceX/gang
> +Date:August 2016
> +KernelVersion:  4.1.15

update? (here and below)

> +Contact:Abhisit Sangjan 
> +Description:
> + Controls the association of analog output channels OUTx with
> + asynchronous control inputs Cy for DAC.
> +Can be either:
> +- "0"
> +- "1"
> +
> + Cy to OUTx Assignment
> + --
> + | Cy | CDAC:GANG=0 | CDAC:GANG=1 |
> + --
> + | C1 | OUT[1:4]| OUT[1:3]|
> + --
> + | C2 | OUT[5:6]| OUT[4:6]|
> + --
> + | C3 | OUT[7:8]| OUT[7:9]|
> + --
> + | C4 | OUT[9:12]   | OUT[10:12]  |
> + --
> +
> +What:   /sys/bus/iio/devices/iio:deviceX/outx
> +Date:August 2016
> +KernelVersion:  4.1.15
> +Contact:Abhisit Sangjan 
> +Description:
> + The pin output mode for DAC.
> +Can be either:
> +- "hiz" = High impedance state.
> +- "dac" = DAC output.
> + - "0" = Drive it to low.
> + - "1" = Drive it to high.
> +
> +What:   /sys/bus/iio/devices/iio:deviceX/vref
> +Date:August 2016
> +KernelVersion:  4.1.15
> +Contact:Abhisit Sangjan 
> +Description:
> + This is voltage referance source for DACs.
> +Can be either:
> +- "external"
> +- "internal"
> +
> +What:   
> 

Re: [PATCH v2 3/5] iio: srf08: add triggered buffer support

2017-08-16 Thread Peter Meerwald-Stadler

> Add support for triggered buffers.

comments below
 
> Data format is quite simple:
>   distance 16 Bit
>   alignment48 Bit
>   timestamp64 Bit
> 
> Signed-off-by: Andreas Klinger <a...@it-klinger.de>
> ---
>  drivers/iio/proximity/srf08.c | 59 
> ---
>  1 file changed, 56 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c
> index 3f19536f215f..8018bb90b7b2 100644
> --- a/drivers/iio/proximity/srf08.c
> +++ b/drivers/iio/proximity/srf08.c
> @@ -18,6 +18,9 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
> +#include 
>  
>  /* registers of SRF08 device */
>  #define SRF08_WRITE_COMMAND  0x00/* Command Register */
> @@ -35,9 +38,22 @@
>  
>  struct srf08_data {
>   struct i2c_client   *client;
> - int sensitivity;/* Gain */
> - int range_mm;   /* max. Range in mm */
> +
> + /*
> +  * Gain in the datasheet is called sensitivity here to distinct it
> +  * from the gain used with amplifiers of adc's
> +  */
> + int sensitivity;
> +
> + /* max. Range in mm */
> + int range_mm;
>   struct mutexlock;
> +
> + /*
> +  * triggered buffer
> +  * 1x16-bit channel + 3x16 padding + 4x16 timestamp
> +  */
> + s16 buffer[8];
>  };
>  
>  /*
> @@ -110,6 +126,28 @@ static int srf08_read_ranging(struct srf08_data *data)
>   return ret;
>  }
>  
> +static irqreturn_t srf08_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio_dev = pf->indio_dev;
> + struct srf08_data *data = iio_priv(indio_dev);
> + s16 sensor_data;
> +
> + sensor_data = srf08_read_ranging(data);
> + if (sensor_data < 0)
> + goto err;
> +
> + mutex_lock(>lock);
> + data->buffer[0] = sensor_data;
> + mutex_unlock(>lock);

what is this lock protecting? this is still racy...
data->buffer could still be overwritten here, between unlock()
and iio_push_...()

> +
> + iio_push_to_buffers_with_timestamp(indio_dev,
> + data->buffer, pf->timestamp);
> +err:
> + iio_trigger_notify_done(indio_dev->trig);
> + return IRQ_HANDLED;
> +}
> +
>  static int srf08_read_raw(struct iio_dev *indio_dev,
>   struct iio_chan_spec const *channel, int *val,
>   int *val2, long mask)
> @@ -323,7 +361,15 @@ static const struct iio_chan_spec srf08_channels[] = {
>   .info_mask_separate =
>   BIT(IIO_CHAN_INFO_RAW) |
>   BIT(IIO_CHAN_INFO_SCALE),
> + .scan_index = 0,
> + .scan_type = {
> + .sign = 's',
> + .realbits = 16,
> + .storagebits = 16,
> + .endianness = IIO_CPU,
> + },
>   },
> + IIO_CHAN_SOFT_TIMESTAMP(1),
>  };
>  
>  static const struct iio_info srf08_info = {
> @@ -362,6 +408,13 @@ static int srf08_probe(struct i2c_client *client,
>  
>   mutex_init(>lock);
>  
> + ret = devm_iio_triggered_buffer_setup(>dev, indio_dev,
> + iio_pollfunc_store_time, srf08_trigger_handler, NULL);
> + if (ret < 0) {
> + dev_err(>dev, "setup of iio triggered buffer failed\n");
> + return ret;
> + }
> +
>   /*
>* set default values of device here
>* these register values cannot be read from the hardware
> @@ -402,5 +455,5 @@ static struct i2c_driver srf08_driver = {
>  module_i2c_driver(srf08_driver);
>  
>  MODULE_AUTHOR("Andreas Klinger <a...@it-klinger.de>");
> -MODULE_DESCRIPTION("Devantech SRF08 ultrasonic ranger driver");
> +MODULE_DESCRIPTION("Devantech SRF08/SRF10 ultrasonic ranger driver");
>  MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 3/5] iio: srf08: add triggered buffer support

2017-08-16 Thread Peter Meerwald-Stadler

> Add support for triggered buffers.

comments below
 
> Data format is quite simple:
>   distance 16 Bit
>   alignment48 Bit
>   timestamp64 Bit
> 
> Signed-off-by: Andreas Klinger 
> ---
>  drivers/iio/proximity/srf08.c | 59 
> ---
>  1 file changed, 56 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c
> index 3f19536f215f..8018bb90b7b2 100644
> --- a/drivers/iio/proximity/srf08.c
> +++ b/drivers/iio/proximity/srf08.c
> @@ -18,6 +18,9 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
> +#include 
>  
>  /* registers of SRF08 device */
>  #define SRF08_WRITE_COMMAND  0x00/* Command Register */
> @@ -35,9 +38,22 @@
>  
>  struct srf08_data {
>   struct i2c_client   *client;
> - int sensitivity;/* Gain */
> - int range_mm;   /* max. Range in mm */
> +
> + /*
> +  * Gain in the datasheet is called sensitivity here to distinct it
> +  * from the gain used with amplifiers of adc's
> +  */
> + int sensitivity;
> +
> + /* max. Range in mm */
> + int range_mm;
>   struct mutexlock;
> +
> + /*
> +  * triggered buffer
> +  * 1x16-bit channel + 3x16 padding + 4x16 timestamp
> +  */
> + s16 buffer[8];
>  };
>  
>  /*
> @@ -110,6 +126,28 @@ static int srf08_read_ranging(struct srf08_data *data)
>   return ret;
>  }
>  
> +static irqreturn_t srf08_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio_dev = pf->indio_dev;
> + struct srf08_data *data = iio_priv(indio_dev);
> + s16 sensor_data;
> +
> + sensor_data = srf08_read_ranging(data);
> + if (sensor_data < 0)
> + goto err;
> +
> + mutex_lock(>lock);
> + data->buffer[0] = sensor_data;
> + mutex_unlock(>lock);

what is this lock protecting? this is still racy...
data->buffer could still be overwritten here, between unlock()
and iio_push_...()

> +
> + iio_push_to_buffers_with_timestamp(indio_dev,
> + data->buffer, pf->timestamp);
> +err:
> + iio_trigger_notify_done(indio_dev->trig);
> + return IRQ_HANDLED;
> +}
> +
>  static int srf08_read_raw(struct iio_dev *indio_dev,
>   struct iio_chan_spec const *channel, int *val,
>   int *val2, long mask)
> @@ -323,7 +361,15 @@ static const struct iio_chan_spec srf08_channels[] = {
>   .info_mask_separate =
>   BIT(IIO_CHAN_INFO_RAW) |
>   BIT(IIO_CHAN_INFO_SCALE),
> + .scan_index = 0,
> + .scan_type = {
> + .sign = 's',
> + .realbits = 16,
> + .storagebits = 16,
> + .endianness = IIO_CPU,
> + },
>   },
> + IIO_CHAN_SOFT_TIMESTAMP(1),
>  };
>  
>  static const struct iio_info srf08_info = {
> @@ -362,6 +408,13 @@ static int srf08_probe(struct i2c_client *client,
>  
>   mutex_init(>lock);
>  
> + ret = devm_iio_triggered_buffer_setup(>dev, indio_dev,
> + iio_pollfunc_store_time, srf08_trigger_handler, NULL);
> + if (ret < 0) {
> + dev_err(>dev, "setup of iio triggered buffer failed\n");
> + return ret;
> + }
> +
>   /*
>* set default values of device here
>    * these register values cannot be read from the hardware
> @@ -402,5 +455,5 @@ static struct i2c_driver srf08_driver = {
>  module_i2c_driver(srf08_driver);
>  
>  MODULE_AUTHOR("Andreas Klinger ");
> -MODULE_DESCRIPTION("Devantech SRF08 ultrasonic ranger driver");
> +MODULE_DESCRIPTION("Devantech SRF08/SRF10 ultrasonic ranger driver");
>  MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 5/5] iio: srf08: add support for srf02 in i2c mode

2017-08-16 Thread Peter Meerwald-Stadler
ls = ARRAY_SIZE(srf08_channels);
>  
> @@ -447,24 +470,39 @@ static int srf08_probe(struct i2c_client *client,
>   return ret;
>   }
>  
> - /*
> -  * set default values of device here
> -  * these register values cannot be read from the hardware
> -  * therefore set driver specific default values
> -  */
> - ret = srf08_write_range_mm(data, SRF08_DEFAULT_RANGE);
> - if (ret < 0)
> - return ret;
> + if (srf08_default_range[id->driver_data]) {


it would be nice to have a chip_info struct with chip-specific 
information, so we can point to the relevant struct once instead of 
picking the correct entry from srf08_default_sensitivity and 
srf08_default_range separately

so far, we have only two defaults tables... no big deal

> + /*
> +  * set default range of device here
> +  * these register values cannot be read from he hardware
> +  * therefore set driver specific default values
> +  *
> +  * srf02 don't have a default value so it'll be omitted
> +  */
> + ret = srf08_write_range_mm(data,
> + srf08_default_range[id->driver_data]);
> + if (ret < 0)
> + return ret;
> + }
>  
> - ret = srf08_write_sensitivity(data,
> - srf08_default_sensitivity[id->driver_data]);
> - if (ret < 0)
> - return ret;
> + if (srf08_default_sensitivity[id->driver_data]) {
> + /*
> +  * set default sensitivity of device here
> +  * these register values cannot be read from the hardware
> +  * therefore set driver specific default values
> +  *
> +  * srf02 don't have a default value so it'll be omitted
> +  */
> + ret = srf08_write_sensitivity(data,
> + srf08_default_sensitivity[id->driver_data]);
> + if (ret < 0)
> + return ret;
> + }
>  
>   return devm_iio_device_register(>dev, indio_dev);
>  }
>  
>  static const struct of_device_id of_srf08_match[] = {
> + { .compatible = "devantech,srf02", (void *)SRF02},
>   { .compatible = "devantech,srf08", (void *)SRF08},
>   { .compatible = "devantech,srf10", (void *)SRF10},
>   {},
> @@ -473,6 +511,7 @@ static const struct of_device_id of_srf08_match[] = {
>  MODULE_DEVICE_TABLE(of, of_srf08_match);
>  
>  static const struct i2c_device_id srf08_id[] = {
> + { "srf02", SRF02 },
>   { "srf08", SRF08 },
>   { "srf10", SRF10 },
>   { }
> @@ -490,5 +529,5 @@ static struct i2c_driver srf08_driver = {
>  module_i2c_driver(srf08_driver);
>  
>  MODULE_AUTHOR("Andreas Klinger <a...@it-klinger.de>");
> -MODULE_DESCRIPTION("Devantech SRF08/SRF10 ultrasonic ranger driver");
> +MODULE_DESCRIPTION("Devantech SRF02/SRF08/SRF10 i2c ultrasonic ranger 
> driver");
>  MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 5/5] iio: srf08: add support for srf02 in i2c mode

2017-08-16 Thread Peter Meerwald-Stadler
8_probe(struct i2c_client *client,
>   return ret;
>   }
>  
> - /*
> -  * set default values of device here
> -  * these register values cannot be read from the hardware
> -  * therefore set driver specific default values
> -  */
> - ret = srf08_write_range_mm(data, SRF08_DEFAULT_RANGE);
> - if (ret < 0)
> - return ret;
> + if (srf08_default_range[id->driver_data]) {


it would be nice to have a chip_info struct with chip-specific 
information, so we can point to the relevant struct once instead of 
picking the correct entry from srf08_default_sensitivity and 
srf08_default_range separately

so far, we have only two defaults tables... no big deal

> + /*
> +  * set default range of device here
> +  * these register values cannot be read from he hardware
> +  * therefore set driver specific default values
> +  *
> +  * srf02 don't have a default value so it'll be omitted
> +  */
> + ret = srf08_write_range_mm(data,
> + srf08_default_range[id->driver_data]);
> + if (ret < 0)
> + return ret;
> + }
>  
> - ret = srf08_write_sensitivity(data,
> - srf08_default_sensitivity[id->driver_data]);
> - if (ret < 0)
> - return ret;
> + if (srf08_default_sensitivity[id->driver_data]) {
> + /*
> +  * set default sensitivity of device here
> +  * these register values cannot be read from the hardware
> +  * therefore set driver specific default values
> +  *
> +  * srf02 don't have a default value so it'll be omitted
> +  */
> + ret = srf08_write_sensitivity(data,
> + srf08_default_sensitivity[id->driver_data]);
> + if (ret < 0)
> + return ret;
> + }
>  
>   return devm_iio_device_register(>dev, indio_dev);
>  }
>  
>  static const struct of_device_id of_srf08_match[] = {
> + { .compatible = "devantech,srf02", (void *)SRF02},
>   { .compatible = "devantech,srf08", (void *)SRF08},
>   { .compatible = "devantech,srf10", (void *)SRF10},
>   {},
> @@ -473,6 +511,7 @@ static const struct of_device_id of_srf08_match[] = {
>  MODULE_DEVICE_TABLE(of, of_srf08_match);
>  
>  static const struct i2c_device_id srf08_id[] = {
> + { "srf02", SRF02 },
>   { "srf08", SRF08 },
>   { "srf10", SRF10 },
>   { }
> @@ -490,5 +529,5 @@ static struct i2c_driver srf08_driver = {
>  module_i2c_driver(srf08_driver);
>  
>  MODULE_AUTHOR("Andreas Klinger ");
> -MODULE_DESCRIPTION("Devantech SRF08/SRF10 ultrasonic ranger driver");
> +MODULE_DESCRIPTION("Devantech SRF02/SRF08/SRF10 i2c ultrasonic ranger 
> driver");
>  MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: accel: mma8452: Bugfix to enbale and allow different events to work parallely.

2017-08-16 Thread Peter Meerwald-Stadler
return IRQ_NONE;
> +
>   if (src & MMA8452_INT_DRDY) {
>   iio_trigger_poll_chained(indio_dev->trig);
>   ret = IRQ_HANDLED;
>   }
>  
> - if ((src & MMA8452_INT_TRANS &&
> -  chip->ev_src == MMA8452_TRANSIENT_SRC) ||
> - (src & MMA8452_INT_FF_MT &&
> -  chip->ev_src == MMA8452_FF_MT_SRC)) {
> + if (src & MMA8452_INT_FF_MT) {
> + if (mma8452_freefall_mode_enabled(data)) {
> + s64 ts = iio_get_time_ns(indio_dev);
> +
> + iio_push_event(indio_dev,
> +IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
> +   IIO_MOD_X_AND_Y_AND_Z,
> +   IIO_EV_TYPE_MAG,
> +   IIO_EV_DIR_FALLING),
> +ts);
> + }
> + ret = IRQ_HANDLED;
> + }
> +
> + if (src & MMA8452_INT_TRANS) {
>   mma8452_transient_interrupt(indio_dev);
>   ret = IRQ_HANDLED;
>   }
> @@ -1222,96 +1255,36 @@ static const struct mma_chip_info 
> mma_chip_info_table[] = {
>*  g * N * 100 / 2048 for N = 2, 4, 8 and g=9.80665
>*/
>   .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
> - .ev_cfg = MMA8452_TRANSIENT_CFG,
> - .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> - .ev_cfg_chan_shift = 1,
> - .ev_src = MMA8452_TRANSIENT_SRC,
> - .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> - .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> - .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> - .ev_ths = MMA8452_TRANSIENT_THS,
> - .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> - .ev_count = MMA8452_TRANSIENT_COUNT,
>   },
>   [mma8452] = {
>   .chip_id = MMA8452_DEVICE_ID,
>   .channels = mma8452_channels,
>   .num_channels = ARRAY_SIZE(mma8452_channels),
>   .mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
> - .ev_cfg = MMA8452_TRANSIENT_CFG,
> - .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> - .ev_cfg_chan_shift = 1,
> - .ev_src = MMA8452_TRANSIENT_SRC,
> - .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> - .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> - .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> - .ev_ths = MMA8452_TRANSIENT_THS,
> - .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> - .ev_count = MMA8452_TRANSIENT_COUNT,
>   },
>   [mma8453] = {
>   .chip_id = MMA8453_DEVICE_ID,
>   .channels = mma8453_channels,
>   .num_channels = ARRAY_SIZE(mma8453_channels),
>   .mma_scales = { {0, 38307}, {0, 76614}, {0, 153228} },
> - .ev_cfg = MMA8452_TRANSIENT_CFG,
> - .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> - .ev_cfg_chan_shift = 1,
> - .ev_src = MMA8452_TRANSIENT_SRC,
> - .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> - .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> - .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> - .ev_ths = MMA8452_TRANSIENT_THS,
> - .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> - .ev_count = MMA8452_TRANSIENT_COUNT,
>   },
>   [mma8652] = {
>   .chip_id = MMA8652_DEVICE_ID,
>   .channels = mma8652_channels,
>   .num_channels = ARRAY_SIZE(mma8652_channels),
>   .mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
> - .ev_cfg = MMA8452_FF_MT_CFG,
> -     .ev_cfg_ele = MMA8452_FF_MT_CFG_ELE,
> - .ev_cfg_chan_shift = 3,
> - .ev_src = MMA8452_FF_MT_SRC,
> - .ev_src_xe = MMA8452_FF_MT_SRC_XHE,
> - .ev_src_ye = MMA8452_FF_MT_SRC_YHE,
> - .ev_src_ze = MMA8452_FF_MT_SRC_ZHE,
> - .ev_ths = MMA8452_FF_MT_THS,
> - .ev_ths_mask = MMA8452_FF_MT_THS_MASK,
> - .ev_count = MMA8452_FF_MT_COUNT,
>   },
>   [mma8653] = {
>   .chip_id = MMA8653_DEVICE_ID,
>   .channels = mma8653_channels,
>   .num_channels = ARRAY_SIZE(mma8653_channels),
>   .mma_scales = { {0, 38307}, {0, 76614}, {0, 153228} },
> - .ev_cfg = MMA8452_FF_MT_CFG,
> - .ev_cfg_ele = MMA8452_FF_MT_CFG_ELE,
> - .ev_cfg_chan_shift = 3,
> - .ev_src = MMA8452_FF_MT_SRC,
> - .ev_src_xe = MMA8452_FF_MT_SRC_XHE,
> - .ev_src_ye = MMA8452_FF_MT_SRC_YHE,
> - .ev_src_ze = MMA8452_FF_MT_SRC_ZHE,
> - .ev_ths = MMA8452_FF_MT_THS,
> - .ev_ths_mask = MMA8452_FF_MT_THS_MASK,
> - .ev_count = MMA8452_FF_MT_COUNT,
>   },
>   [fxls8471] = {
>   .chip_id = FXLS8471_DEVICE_ID,
>   .channels = mma8451_channels,
>   .num_channels = ARRAY_SIZE(mma8451_channels),
>   .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
> - .ev_cfg = MMA8452_TRANSIENT_CFG,
> - .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> - .ev_cfg_chan_shift = 1,
> - .ev_src = MMA8452_TRANSIENT_SRC,
> - .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> - .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> - .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> - .ev_ths = MMA8452_TRANSIENT_THS,
> - .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> - .ev_count = MMA8452_TRANSIENT_COUNT,
>   },
>  };
>  
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: accel: mma8452: Bugfix to enbale and allow different events to work parallely.

2017-08-16 Thread Peter Meerwald-Stadler
 if (src & MMA8452_INT_DRDY) {
>   iio_trigger_poll_chained(indio_dev->trig);
>   ret = IRQ_HANDLED;
>   }
>  
> - if ((src & MMA8452_INT_TRANS &&
> -  chip->ev_src == MMA8452_TRANSIENT_SRC) ||
> - (src & MMA8452_INT_FF_MT &&
> -  chip->ev_src == MMA8452_FF_MT_SRC)) {
> + if (src & MMA8452_INT_FF_MT) {
> + if (mma8452_freefall_mode_enabled(data)) {
> + s64 ts = iio_get_time_ns(indio_dev);
> +
> + iio_push_event(indio_dev,
> +IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
> +   IIO_MOD_X_AND_Y_AND_Z,
> +   IIO_EV_TYPE_MAG,
> +   IIO_EV_DIR_FALLING),
> +ts);
> + }
> + ret = IRQ_HANDLED;
> + }
> +
> + if (src & MMA8452_INT_TRANS) {
>   mma8452_transient_interrupt(indio_dev);
>   ret = IRQ_HANDLED;
>   }
> @@ -1222,96 +1255,36 @@ static const struct mma_chip_info 
> mma_chip_info_table[] = {
>*  g * N * 100 / 2048 for N = 2, 4, 8 and g=9.80665
>*/
>   .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
> - .ev_cfg = MMA8452_TRANSIENT_CFG,
> - .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> - .ev_cfg_chan_shift = 1,
> - .ev_src = MMA8452_TRANSIENT_SRC,
> - .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> - .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> - .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> - .ev_ths = MMA8452_TRANSIENT_THS,
> - .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> - .ev_count = MMA8452_TRANSIENT_COUNT,
>   },
>   [mma8452] = {
>   .chip_id = MMA8452_DEVICE_ID,
>   .channels = mma8452_channels,
>   .num_channels = ARRAY_SIZE(mma8452_channels),
>   .mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
> - .ev_cfg = MMA8452_TRANSIENT_CFG,
> - .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> - .ev_cfg_chan_shift = 1,
> - .ev_src = MMA8452_TRANSIENT_SRC,
> - .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> - .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> - .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> - .ev_ths = MMA8452_TRANSIENT_THS,
> - .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> - .ev_count = MMA8452_TRANSIENT_COUNT,
>   },
>   [mma8453] = {
>   .chip_id = MMA8453_DEVICE_ID,
>   .channels = mma8453_channels,
>   .num_channels = ARRAY_SIZE(mma8453_channels),
>   .mma_scales = { {0, 38307}, {0, 76614}, {0, 153228} },
> - .ev_cfg = MMA8452_TRANSIENT_CFG,
> - .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> - .ev_cfg_chan_shift = 1,
> - .ev_src = MMA8452_TRANSIENT_SRC,
> - .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> - .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> - .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> - .ev_ths = MMA8452_TRANSIENT_THS,
> - .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> - .ev_count = MMA8452_TRANSIENT_COUNT,
>   },
>   [mma8652] = {
>   .chip_id = MMA8652_DEVICE_ID,
>   .channels = mma8652_channels,
>   .num_channels = ARRAY_SIZE(mma8652_channels),
>   .mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
> - .ev_cfg = MMA8452_FF_MT_CFG,
> - .ev_cfg_ele = MMA8452_FF_MT_CFG_ELE,
> - .ev_cfg_chan_shift = 3,
> - .ev_src = MMA8452_FF_MT_SRC,
> - .ev_src_xe = MMA8452_FF_MT_SRC_XHE,
> - .ev_src_ye = MMA8452_FF_MT_SRC_YHE,
> - .ev_src_ze = MMA8452_FF_MT_SRC_ZHE,
> - .ev_ths = MMA8452_FF_MT_THS,
> - .ev_ths_mask = MMA8452_FF_MT_THS_MASK,
> - .ev_count = MMA8452_FF_MT_COUNT,
>   },
>   [mma8653] = {
>   .chip_id = MMA8653_DEVICE_ID,
>   .channels = mma8653_channels,
>   .num_channels = ARRAY_SIZE(mma8653_channels),
>   .mma_scales = { {0, 38307}, {0, 76614}, {0, 153228} },
> - .ev_cfg = MMA8452_FF_MT_CFG,
> - .ev_cfg_ele = MMA8452_FF_MT_CFG_ELE,
> - .ev_cfg_chan_shift = 3,
> - .ev_src = MMA8452_FF_MT_SRC,
> - .ev_src_xe = MMA8452_FF_MT_SRC_XHE,
> - .ev_src_ye = MMA8452_FF_MT_SRC_YHE,
> - .ev_src_ze = MMA8452_FF_MT_SRC_ZHE,
> - .ev_ths = MMA8452_FF_MT_THS,
> - .ev_ths_mask = MMA8452_FF_MT_THS_MASK,
> - .ev_count = MMA8452_FF_MT_COUNT,
>   },
>   [fxls8471] = {
>   .chip_id = FXLS8471_DEVICE_ID,
>   .channels = mma8451_channels,
>   .num_channels = ARRAY_SIZE(mma8451_channels),
>   .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
> - .ev_cfg = MMA8452_TRANSIENT_CFG,
> - .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> - .ev_cfg_chan_shift = 1,
> - .ev_src = MMA8452_TRANSIENT_SRC,
> - .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> - .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> - .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> - .ev_ths = MMA8452_TRANSIENT_THS,
> - .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> - .ev_count = MMA8452_TRANSIENT_COUNT,
>   },
>  };
>  
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 2/5] iio: Add support for LMP92001 ADC

2017-08-03 Thread Peter Meerwald-Stadler
_events, 
> ARRAY_SIZE(lmp92001_events)),
> +LMP92001_CHAN_SPEC(11, IIO_VOLTAGE, lmp92001_events, 
> ARRAY_SIZE(lmp92001_events)),
> +LMP92001_CHAN_SPEC(12, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(13, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(14, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(15, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(16, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(17,IIO_TEMP, NULL, 0),

wondering in what unit the drivers reports _TEMP, probably _SCALE needed

> +};
> +
> +static int lmp92001_adc_probe(struct platform_device *pdev)
> +{
> +struct lmp92001 *lmp92001 = dev_get_drvdata(pdev->dev.parent);
> +struct iio_dev *indio_dev;
> +struct device_node *np = pdev->dev.of_node;
> +const char *conversion;
> +unsigned int cgen = 0, cad1, cad2, cad3;
> +u32 mask;
> +int ret;
> +
> +indio_dev = devm_iio_device_alloc(>dev, sizeof(*lmp92001));
> +if (!indio_dev)
> +return -ENOMEM;
> +
> +iio_device_set_drvdata(indio_dev, lmp92001);
> +
> +indio_dev->name = pdev->name;
> +indio_dev->dev.parent = >dev;
> +indio_dev->modes = INDIO_DIRECT_MODE;
> +indio_dev->info = _info;
> +indio_dev->channels = lmp92001_adc_channels;
> +indio_dev->num_channels = ARRAY_SIZE(lmp92001_adc_channels);
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CGEN, 0x80, 
> 0x80);
> +if (ret < 0)
> +{
> +dev_err(>dev,"failed to self reset all registers\n");
> +return ret;
> +}
> +
> +ret = of_property_read_u32(np, "ti,lmp92001-adc-mask", );
> +if (ret < 0)
> +{
> +cad1 = cad2 = cad3 = 0xFF;
> +dev_info(>dev, "turn on all of channels by default\n");
> +}
> +else
> +{
> +cad1 = mask & 0xFF;
> +cad2 = (mask >> 8) & 0xFF;
> +cad3 = (mask >> 16) & 0xFF;
> +}
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CAD1, 0xFF, 
> cad1);
> +if (ret < 0)
> +{
> +dev_err(>dev,"failed to enable channels 1-8\n");
> +return ret;
> +}
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CAD2, 0xFF, 
> cad2);
> +if (ret < 0)
> +{
> +dev_err(>dev, "failed to enable channels 9-16\n");
> +return ret;
> +}
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CAD3, 1, cad3);
> +if (ret < 0)
> +{
> +dev_err(>dev, "failed to enable channel 17 
> (temperature)\n");
> +return ret;
> +}
> +
> +    ret = of_property_read_string_index(np, "ti,lmp92001-adc-mode", 0,
> +);
> +if (!ret)
> +{
> +if (strcmp("continuous", conversion) == 0)
> +cgen |= 1;
> +else if (strcmp("single-shot", conversion) == 0)
> +{ /* Okay */ }
> +else
> +dev_warn(>dev,
> +"wrong adc mode! set to single-short conversion\n");
> +}
> +else
> +dev_info(>dev,
> +"single-short conversion was chosen by default\n");
> +
> +/*
> + * Lock the registers and set conversion mode.
> + */
> +ret = regmap_update_bits(lmp92001->regmap,
> +LMP92001_CGEN, 3, cgen | 2);
> +if (ret < 0)
> +return ret;
> +
> +platform_set_drvdata(pdev, indio_dev);
> +
> +return iio_device_register(indio_dev);
> +}
> +
> +static int lmp92001_adc_remove(struct platform_device *pdev)
> +{
> +struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> +iio_device_unregister(indio_dev);
> +
> +return 0;
> +}
> +
> +static struct platform_driver lmp92001_adc_driver = {
> +.driver.name= "lmp92001-adc",
> +.driver.owner   = THIS_MODULE,
> +.probe  = lmp92001_adc_probe,
> +.remove = lmp92001_adc_remove,
> +};
> +
> +static int __init lmp92001_adc_init(void)
> +{
> +return platform_driver_register(_adc_driver);
> +}
> +subsys_initcall(lmp92001_adc_init);
> +
> +static void __exit lmp92001_adc_exit(void)
> +{
> +platform_driver_unregister(_adc_driver);
> +}
> +module_exit(lmp92001_adc_exit);
> +
> +MODULE_AUTHOR("Abhisit Sangjan <s.abhi...@gmail.com>");
> +MODULE_DESCRIPTION("IIO ADC interface for TI LMP92001");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:lmp92001-adc");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 2/5] iio: Add support for LMP92001 ADC

2017-08-03 Thread Peter Meerwald-Stadler
  LMP92001_CHAN_SPEC(11, IIO_VOLTAGE, lmp92001_events, 
> ARRAY_SIZE(lmp92001_events)),
> +LMP92001_CHAN_SPEC(12, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(13, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(14, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(15, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(16, IIO_VOLTAGE, NULL, 0),
> +LMP92001_CHAN_SPEC(17,IIO_TEMP, NULL, 0),

wondering in what unit the drivers reports _TEMP, probably _SCALE needed

> +};
> +
> +static int lmp92001_adc_probe(struct platform_device *pdev)
> +{
> +struct lmp92001 *lmp92001 = dev_get_drvdata(pdev->dev.parent);
> +struct iio_dev *indio_dev;
> +struct device_node *np = pdev->dev.of_node;
> +const char *conversion;
> +unsigned int cgen = 0, cad1, cad2, cad3;
> +u32 mask;
> +int ret;
> +
> +indio_dev = devm_iio_device_alloc(>dev, sizeof(*lmp92001));
> +if (!indio_dev)
> +return -ENOMEM;
> +
> +iio_device_set_drvdata(indio_dev, lmp92001);
> +
> +indio_dev->name = pdev->name;
> +indio_dev->dev.parent = >dev;
> +indio_dev->modes = INDIO_DIRECT_MODE;
> +indio_dev->info = _info;
> +indio_dev->channels = lmp92001_adc_channels;
> +indio_dev->num_channels = ARRAY_SIZE(lmp92001_adc_channels);
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CGEN, 0x80, 
> 0x80);
> +if (ret < 0)
> +{
> +dev_err(>dev,"failed to self reset all registers\n");
> +return ret;
> +}
> +
> +ret = of_property_read_u32(np, "ti,lmp92001-adc-mask", );
> +if (ret < 0)
> +{
> +cad1 = cad2 = cad3 = 0xFF;
> +dev_info(>dev, "turn on all of channels by default\n");
> +}
> +else
> +{
> +cad1 = mask & 0xFF;
> +cad2 = (mask >> 8) & 0xFF;
> +cad3 = (mask >> 16) & 0xFF;
> +}
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CAD1, 0xFF, 
> cad1);
> +if (ret < 0)
> +{
> +dev_err(>dev,"failed to enable channels 1-8\n");
> +return ret;
> +}
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CAD2, 0xFF, 
> cad2);
> +if (ret < 0)
> +{
> +dev_err(>dev, "failed to enable channels 9-16\n");
> +return ret;
> +}
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CAD3, 1, cad3);
> +if (ret < 0)
> +{
> +dev_err(>dev, "failed to enable channel 17 
> (temperature)\n");
> +return ret;
> +}
> +
> +    ret = of_property_read_string_index(np, "ti,lmp92001-adc-mode", 0,
> +);
> +if (!ret)
> +{
> +if (strcmp("continuous", conversion) == 0)
> +cgen |= 1;
> +else if (strcmp("single-shot", conversion) == 0)
> +{ /* Okay */ }
> +else
> +dev_warn(>dev,
> +"wrong adc mode! set to single-short conversion\n");
> +}
> +else
> +dev_info(>dev,
> +"single-short conversion was chosen by default\n");
> +
> +/*
> + * Lock the registers and set conversion mode.
> + */
> +ret = regmap_update_bits(lmp92001->regmap,
> +LMP92001_CGEN, 3, cgen | 2);
> +if (ret < 0)
> +return ret;
> +
> +platform_set_drvdata(pdev, indio_dev);
> +
> +return iio_device_register(indio_dev);
> +}
> +
> +static int lmp92001_adc_remove(struct platform_device *pdev)
> +{
> +struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> +iio_device_unregister(indio_dev);
> +
> +return 0;
> +}
> +
> +static struct platform_driver lmp92001_adc_driver = {
> +.driver.name= "lmp92001-adc",
> +.driver.owner   = THIS_MODULE,
> +.probe  = lmp92001_adc_probe,
> +.remove = lmp92001_adc_remove,
> +};
> +
> +static int __init lmp92001_adc_init(void)
> +{
> +return platform_driver_register(_adc_driver);
> +}
> +subsys_initcall(lmp92001_adc_init);
> +
> +static void __exit lmp92001_adc_exit(void)
> +{
> +platform_driver_unregister(_adc_driver);
> +}
> +module_exit(lmp92001_adc_exit);
> +
> +MODULE_AUTHOR("Abhisit Sangjan ");
> +MODULE_DESCRIPTION("IIO ADC interface for TI LMP92001");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:lmp92001-adc");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 3/5] iio: Add support for LMP92001 DAC

2017-08-01 Thread Peter Meerwald-Stadler
gmap_update_bits(lmp92001->regmap, LMP92001_CDAC, 4, cdac);
> +if (ret < 0)
> +return ret;
> +
> +return len;
> +}
> +
> +static const struct iio_chan_spec_ext_info lmp92001_ext_info[] = {
> +{
> +.name = "vref",
> +.read = lmp92001_dvref_read,
> +.write = lmp92001_dvref_write,
> +.shared = IIO_SHARED_BY_ALL,
> +},
> +{
> +.name = "outx",
> +.read = lmp92001_outx_read,
> +.write = lmp92001_outx_write,
> +.shared = IIO_SHARED_BY_ALL,
> +},
> +{
> +.name = "gang",
> +.read = lmp92001_gang_read,
> +.write = lmp92001_gang_write,
> +.shared = IIO_SHARED_BY_ALL,
> +},
> +{ },
> +};
> +
> +#define LMP92001_CHAN_SPEC(_ch) \
> +{ \
> +.channel = _ch, \
> +.scan_index = _ch, \

.scan_index not needed

> +.type = IIO_VOLTAGE, \
> +.indexed = 1, \
> +.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> +.ext_info = lmp92001_ext_info, \
> +.output = 1, \
> +}
> +
> +static const struct iio_chan_spec lmp92001_dac_channels[] = {
> +LMP92001_CHAN_SPEC(1),
> +LMP92001_CHAN_SPEC(2),
> +LMP92001_CHAN_SPEC(3),
> +LMP92001_CHAN_SPEC(4),
> +LMP92001_CHAN_SPEC(5),
> +LMP92001_CHAN_SPEC(6),
> +LMP92001_CHAN_SPEC(7),
> +LMP92001_CHAN_SPEC(8),
> +LMP92001_CHAN_SPEC(9),
> +LMP92001_CHAN_SPEC(10),
> +LMP92001_CHAN_SPEC(11),
> +LMP92001_CHAN_SPEC(12),
> +};
> +
> +static int lmp92001_dac_probe(struct platform_device *pdev)
> +{
> +struct lmp92001 *lmp92001 = dev_get_drvdata(pdev->dev.parent);
> +struct iio_dev *indio_dev;
> +struct device_node *np = pdev->dev.of_node;
> +u8 gang = 0, outx = 0, hiz = 0;
> +unsigned int cdac = 0;

initialization needed?

> +int ret;
> +
> +indio_dev = devm_iio_device_alloc(>dev, sizeof(*lmp92001));
> +if (!indio_dev)
> +return -ENOMEM;
> +
> +iio_device_set_drvdata(indio_dev, lmp92001);
> +
> +indio_dev->name = pdev->name;
> +indio_dev->modes = INDIO_DIRECT_MODE;
> +indio_dev->info = _info;
> +indio_dev->channels = lmp92001_dac_channels;
> +indio_dev->num_channels = ARRAY_SIZE(lmp92001_dac_channels);
> +
> +of_property_read_u8(np, "ti,lmp92001-dac-hiz", );
> +cdac |= hiz;
> +
> +of_property_read_u8(np, "ti,lmp92001-dac-outx", );
> +cdac |= outx << 1;
> +
> +    of_property_read_u8(np, "ti,lmp92001-dac-gang", );
> +cdac |= gang << 2;
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CDAC, 7, cdac);
> +if (ret < 0)
> +return ret;
> +
> +platform_set_drvdata(pdev, indio_dev);
> +
> +return iio_device_register(indio_dev);
> +}
> +
> +static int lmp92001_dac_remove(struct platform_device *pdev)

can use devm_iio_device_register() if _remove() is essentially empty

> +{
> +struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> +iio_device_unregister(indio_dev);
> +
> +return 0;
> +}
> +
> +static struct platform_driver lmp92001_dac_driver = {
> +.driver.name= "lmp92001-dac",
> +.driver.owner   = THIS_MODULE,
> +.probe  = lmp92001_dac_probe,

THIS_MODULE not needed anymore

> +.remove = lmp92001_dac_remove,
> +};
> +
> +static int __init lmp92001_dac_init(void)
> +{
> +return platform_driver_register(_dac_driver);
> +}
> +subsys_initcall(lmp92001_dac_init);
> +
> +static void __exit lmp92001_dac_exit(void)
> +{
> +platform_driver_unregister(_dac_driver);
> +}
> +module_exit(lmp92001_dac_exit);
> +
> +MODULE_AUTHOR("Abhisit Sangjan <s.abhi...@gmail.com>");
> +MODULE_DESCRIPTION("IIO DAC interface for TI LMP92001");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:lmp92001-dac");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 3/5] iio: Add support for LMP92001 DAC

2017-08-01 Thread Peter Meerwald-Stadler
 cdac);
> +if (ret < 0)
> +return ret;
> +
> +return len;
> +}
> +
> +static const struct iio_chan_spec_ext_info lmp92001_ext_info[] = {
> +{
> +.name = "vref",
> +.read = lmp92001_dvref_read,
> +.write = lmp92001_dvref_write,
> +.shared = IIO_SHARED_BY_ALL,
> +},
> +{
> +.name = "outx",
> +.read = lmp92001_outx_read,
> +.write = lmp92001_outx_write,
> +.shared = IIO_SHARED_BY_ALL,
> +},
> +{
> +.name = "gang",
> +.read = lmp92001_gang_read,
> +.write = lmp92001_gang_write,
> +.shared = IIO_SHARED_BY_ALL,
> +},
> +{ },
> +};
> +
> +#define LMP92001_CHAN_SPEC(_ch) \
> +{ \
> +.channel = _ch, \
> +.scan_index = _ch, \

.scan_index not needed

> +.type = IIO_VOLTAGE, \
> +.indexed = 1, \
> +.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> +.ext_info = lmp92001_ext_info, \
> +.output = 1, \
> +}
> +
> +static const struct iio_chan_spec lmp92001_dac_channels[] = {
> +LMP92001_CHAN_SPEC(1),
> +LMP92001_CHAN_SPEC(2),
> +LMP92001_CHAN_SPEC(3),
> +LMP92001_CHAN_SPEC(4),
> +LMP92001_CHAN_SPEC(5),
> +LMP92001_CHAN_SPEC(6),
> +LMP92001_CHAN_SPEC(7),
> +LMP92001_CHAN_SPEC(8),
> +LMP92001_CHAN_SPEC(9),
> +LMP92001_CHAN_SPEC(10),
> +LMP92001_CHAN_SPEC(11),
> +LMP92001_CHAN_SPEC(12),
> +};
> +
> +static int lmp92001_dac_probe(struct platform_device *pdev)
> +{
> +struct lmp92001 *lmp92001 = dev_get_drvdata(pdev->dev.parent);
> +struct iio_dev *indio_dev;
> +struct device_node *np = pdev->dev.of_node;
> +u8 gang = 0, outx = 0, hiz = 0;
> +unsigned int cdac = 0;

initialization needed?

> +int ret;
> +
> +indio_dev = devm_iio_device_alloc(>dev, sizeof(*lmp92001));
> +if (!indio_dev)
> +return -ENOMEM;
> +
> +iio_device_set_drvdata(indio_dev, lmp92001);
> +
> +indio_dev->name = pdev->name;
> +indio_dev->modes = INDIO_DIRECT_MODE;
> +indio_dev->info = _info;
> +indio_dev->channels = lmp92001_dac_channels;
> +indio_dev->num_channels = ARRAY_SIZE(lmp92001_dac_channels);
> +
> +of_property_read_u8(np, "ti,lmp92001-dac-hiz", );
> +cdac |= hiz;
> +
> +of_property_read_u8(np, "ti,lmp92001-dac-outx", );
> +cdac |= outx << 1;
> +
> +of_property_read_u8(np, "ti,lmp92001-dac-gang", );
> +cdac |= gang << 2;
> +
> +ret = regmap_update_bits(lmp92001->regmap, LMP92001_CDAC, 7, cdac);
> +if (ret < 0)
> +return ret;
> +
> +platform_set_drvdata(pdev, indio_dev);
> +
> +return iio_device_register(indio_dev);
> +}
> +
> +static int lmp92001_dac_remove(struct platform_device *pdev)

can use devm_iio_device_register() if _remove() is essentially empty

> +{
> +struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> +iio_device_unregister(indio_dev);
> +
> +return 0;
> +}
> +
> +static struct platform_driver lmp92001_dac_driver = {
> +.driver.name= "lmp92001-dac",
> +.driver.owner   = THIS_MODULE,
> +.probe  = lmp92001_dac_probe,

THIS_MODULE not needed anymore

> +.remove = lmp92001_dac_remove,
> +};
> +
> +static int __init lmp92001_dac_init(void)
> +{
> +return platform_driver_register(_dac_driver);
> +}
> +subsys_initcall(lmp92001_dac_init);
> +
> +static void __exit lmp92001_dac_exit(void)
> +{
> +platform_driver_unregister(_dac_driver);
> +}
> +module_exit(lmp92001_dac_exit);
> +
> +MODULE_AUTHOR("Abhisit Sangjan ");
> +MODULE_DESCRIPTION("IIO DAC interface for TI LMP92001");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:lmp92001-dac");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: Add LTC2471/LTC2473 driver

2017-07-02 Thread Peter Meerwald-Stadler
 default:
> + return -EINVAL;
> + }
> +}
> +
> +static const struct iio_chan_spec ltc2471_channel[] = {
> + {
> + .type = IIO_VOLTAGE,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
> + .differential = 0,

.differential = 0 not needed

> + },
> +};
> +static const struct iio_chan_spec ltc2473_channel[] = {
> + {
> + .type = IIO_VOLTAGE,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
> + BIT(IIO_CHAN_INFO_OFFSET),
> + .differential = 1,
> + },
> +};
> +
> +static const struct iio_info ltc2471_info = {
> + .read_raw = ltc2471_read_raw,
> + .driver_module = THIS_MODULE,
> +};
> +
> +static int ltc2471_i2c_probe(struct i2c_client *client,
> +  const struct i2c_device_id *id)
> +{
> + struct iio_dev *indio_dev;
> + struct ltc2471_data *data;
> + int ret;
> +
> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
> + return -EOPNOTSUPP;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + data = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + data->client = client;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = id->name;
> + indio_dev->info = _info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + if (id->driver_data == ltc2473)
> + indio_dev->channels = ltc2473_channel;
> + else
> + indio_dev->channels = ltc2471_channel;
> + indio_dev->num_channels = 1;
> +
> + /* Trigger once to start conversion and check if chip is there */
> + ret = ltc2471_get_value(client);
> + if (ret < 0) {
> + dev_err(>dev, "Cannot read from device.\n");
> + return ret;
> + }
> +
> + return devm_iio_device_register(>dev, indio_dev);
> +}
> +
> +static const struct i2c_device_id ltc2471_i2c_id[] = {
> + { "ltc2471", ltc2471 },
> + { "ltc2473", ltc2473 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id);
> +
> +static struct i2c_driver ltc2471_i2c_driver = {
> + .driver = {
> + .name = "ltc2471",
> + },
> + .probe= ltc2471_i2c_probe,
> + .id_table = ltc2471_i2c_id,
> +};
> +
> +module_i2c_driver(ltc2471_i2c_driver);
> +
> +MODULE_DESCRIPTION("LTC2471/LTC2473 Sensor Driver");

maybe "ADC driver"

> +MODULE_AUTHOR("Topic Embedded Products");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: Add LTC2471/LTC2473 driver

2017-07-02 Thread Peter Meerwald-Stadler
+}
> +
> +static const struct iio_chan_spec ltc2471_channel[] = {
> + {
> + .type = IIO_VOLTAGE,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
> + .differential = 0,

.differential = 0 not needed

> + },
> +};
> +static const struct iio_chan_spec ltc2473_channel[] = {
> + {
> + .type = IIO_VOLTAGE,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
> + BIT(IIO_CHAN_INFO_OFFSET),
> + .differential = 1,
> + },
> +};
> +
> +static const struct iio_info ltc2471_info = {
> + .read_raw = ltc2471_read_raw,
> + .driver_module = THIS_MODULE,
> +};
> +
> +static int ltc2471_i2c_probe(struct i2c_client *client,
> +  const struct i2c_device_id *id)
> +{
> + struct iio_dev *indio_dev;
> + struct ltc2471_data *data;
> + int ret;
> +
> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
> + return -EOPNOTSUPP;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + data = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + data->client = client;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = id->name;
> + indio_dev->info = _info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + if (id->driver_data == ltc2473)
> + indio_dev->channels = ltc2473_channel;
> + else
> + indio_dev->channels = ltc2471_channel;
> + indio_dev->num_channels = 1;
> +
> + /* Trigger once to start conversion and check if chip is there */
> + ret = ltc2471_get_value(client);
> + if (ret < 0) {
> + dev_err(>dev, "Cannot read from device.\n");
> +     return ret;
> + }
> +
> + return devm_iio_device_register(>dev, indio_dev);
> +}
> +
> +static const struct i2c_device_id ltc2471_i2c_id[] = {
> + { "ltc2471", ltc2471 },
> + { "ltc2473", ltc2473 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id);
> +
> +static struct i2c_driver ltc2471_i2c_driver = {
> + .driver = {
> + .name = "ltc2471",
> + },
> + .probe= ltc2471_i2c_probe,
> + .id_table = ltc2471_i2c_id,
> +};
> +
> +module_i2c_driver(ltc2471_i2c_driver);
> +
> +MODULE_DESCRIPTION("LTC2471/LTC2473 Sensor Driver");

maybe "ADC driver"

> +MODULE_AUTHOR("Topic Embedded Products");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: dac: DS4424: add Maxim DS4422/DS4424 DAC driver support

2017-06-25 Thread Peter Meerwald-Stadler
pdata = _pdata_default;
> + }
> +
> + pdata = client->dev.platform_data;
> + data->min_rfs = pdata->min_rfs;
> + data->max_rfs = pdata->max_rfs;
> + data->ifs_scale = pdata->ifs_scale;
> + data->max_picoamp = pdata->max_picoamp;
> + data->vcc_reg_name = pdata->vcc_supply_name;
> + memcpy(data->rfs_res, pdata->rfs_res,
> + sizeof(uint32_t) * DS442X_MAX_DAC_CHANNELS);
> + memcpy(data->dac_iio_map, pdata->dac_iio_map,
> + sizeof(struct iio_map) * DS442X_MAX_DAC_CHANNELS);
> + }
> +
> + if (data->vcc_reg_name) {
> + data->vcc_reg = devm_regulator_get(>dev,
> + data->vcc_reg_name);
> + if (IS_ERR(data->vcc_reg)) {
> + ret = PTR_ERR(data->vcc_reg);
> + dev_err(>dev,
> + "Failed to get vcc_reg regulator: %d\n", ret);
> + return ret;
> + }
> + }
> +
> + mutex_init(>lock);
> + ret = ds4424_regulator_onoff(indio_dev, PWR_ON);
> + if (ret < 0) {
> + pr_err("Unable to turn on the regulator. %s:%d, ret: %d\n",
> + __func__, __LINE__, ret);
> + return ret;
> + }
> +
> + switch (id->driver_data) {
> + case ID_DS4422:
> + indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS;
> + break;
> + case ID_DS4424:
> + indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS;
> + break;
> + default:
> + indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS;
> + break;
> + }
> +
> + indio_dev->channels = ds4424_channels;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> +
> + ret = iio_map_array_register(indio_dev, data->dac_iio_map);
> + if (ret < 0)
> + goto err_iio_device_0;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret < 0) {
> + pr_err("iio_device_register failed . %s:%d, ret: %d\n",

delete space after 'failed'

> + __func__, __LINE__, ret);
> + goto err_iio_device_1;
> + }
> +
> + return ret;
> +
> +err_iio_device_0:
> + ds4424_regulator_onoff(indio_dev, PWR_OFF);
> +err_iio_device_1:
> + iio_map_array_unregister(indio_dev);
> + return ret;
> +}
> +
> +static int ds4424_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> + iio_device_unregister(indio_dev);
> + iio_map_array_unregister(indio_dev);
> + ds4424_regulator_onoff(indio_dev, PWR_OFF);
> + return 0;
> +}
> +
> +static const struct i2c_device_id ds4424_id[] = {
> + { "ds4422", ID_DS4422 },
> + { "ds4424", ID_DS4424 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, ds4424_id);
> +
> +static const struct of_device_id ds4424_of_match[] = {
> + { .compatible = "maxim,ds4422" },
> + { .compatible = "maxim,ds4424" },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(of, ds4424_of_match);
> +
> +static struct i2c_driver ds4424_driver = {
> + .driver = {
> + .name   = "ds4424",
> + .pm = DS4424_PM_OPS,
> + },
> + .probe  = ds4424_probe,
> + .remove = ds4424_remove,
> + .id_table   = ds4424_id,
> +};
> +module_i2c_driver(ds4424_driver);
> +
> +MODULE_DESCRIPTION("Maxim DS4424 DAC Driver");
> +MODULE_AUTHOR("Ismail H. Kose <ismail.k...@maximintegrated.com>");
> +MODULE_AUTHOR("Vishal Sood <vishal.s...@maximintegrated.com>");
> +MODULE_AUTHOR("David Jung <david.j...@maximintegrated.com>");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/iio/dac/ds4424.h b/include/linux/iio/dac/ds4424.h
> new file mode 100644
> index ..09ff3d61797d
> --- /dev/null
> +++ b/include/linux/iio/dac/ds4424.h
> @@ -0,0 +1,29 @@
> +/*
> + * Maxim Integrated
> + * 7-bit, Multi-Channel Sink/Source Current DAC Driver
> + * Copyright (C) 2017 Maxim Integrated
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef IIO_DAC_DS4424_H_
> +#define IIO_DAC_DS4424_H_
> +#include 
> +#include 
> +
> +#define DS4422_MAX_DAC_CHANNELS  2
> +#define DS4424_MAX_DAC_CHANNELS  4
> +#define DS442X_MAX_DAC_CHANNELS  DS4424_MAX_DAC_CHANNELS
> +
> +struct ds4424_pdata {
> + const char *vcc_supply_name;
> + uint32_t max_rfs;
> + uint32_t min_rfs;
> + uint32_t ifs_scale;
> + uint32_t max_picoamp;
> + uint32_t rfs_res[DS442X_MAX_DAC_CHANNELS];
> + struct iio_map dac_iio_map[DS442X_MAX_DAC_CHANNELS + 1];
> +};
> +#endif /* IIO_DAC_DS4424_H_ */
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: dac: DS4424: add Maxim DS4422/DS4424 DAC driver support

2017-06-25 Thread Peter Meerwald-Stadler
ta_default;
> + }
> +
> + pdata = client->dev.platform_data;
> + data->min_rfs = pdata->min_rfs;
> + data->max_rfs = pdata->max_rfs;
> + data->ifs_scale = pdata->ifs_scale;
> + data->max_picoamp = pdata->max_picoamp;
> + data->vcc_reg_name = pdata->vcc_supply_name;
> + memcpy(data->rfs_res, pdata->rfs_res,
> + sizeof(uint32_t) * DS442X_MAX_DAC_CHANNELS);
> + memcpy(data->dac_iio_map, pdata->dac_iio_map,
> + sizeof(struct iio_map) * DS442X_MAX_DAC_CHANNELS);
> + }
> +
> + if (data->vcc_reg_name) {
> + data->vcc_reg = devm_regulator_get(>dev,
> + data->vcc_reg_name);
> + if (IS_ERR(data->vcc_reg)) {
> + ret = PTR_ERR(data->vcc_reg);
> + dev_err(>dev,
> + "Failed to get vcc_reg regulator: %d\n", ret);
> + return ret;
> + }
> + }
> +
> + mutex_init(>lock);
> + ret = ds4424_regulator_onoff(indio_dev, PWR_ON);
> +     if (ret < 0) {
> + pr_err("Unable to turn on the regulator. %s:%d, ret: %d\n",
> + __func__, __LINE__, ret);
> + return ret;
> + }
> +
> + switch (id->driver_data) {
> + case ID_DS4422:
> + indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS;
> + break;
> + case ID_DS4424:
> + indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS;
> + break;
> + default:
> + indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS;
> + break;
> + }
> +
> + indio_dev->channels = ds4424_channels;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> +
> + ret = iio_map_array_register(indio_dev, data->dac_iio_map);
> + if (ret < 0)
> + goto err_iio_device_0;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret < 0) {
> + pr_err("iio_device_register failed . %s:%d, ret: %d\n",

delete space after 'failed'

> + __func__, __LINE__, ret);
> + goto err_iio_device_1;
> + }
> +
> + return ret;
> +
> +err_iio_device_0:
> + ds4424_regulator_onoff(indio_dev, PWR_OFF);
> +err_iio_device_1:
> + iio_map_array_unregister(indio_dev);
> + return ret;
> +}
> +
> +static int ds4424_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> + iio_device_unregister(indio_dev);
> + iio_map_array_unregister(indio_dev);
> + ds4424_regulator_onoff(indio_dev, PWR_OFF);
> + return 0;
> +}
> +
> +static const struct i2c_device_id ds4424_id[] = {
> + { "ds4422", ID_DS4422 },
> + { "ds4424", ID_DS4424 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, ds4424_id);
> +
> +static const struct of_device_id ds4424_of_match[] = {
> + { .compatible = "maxim,ds4422" },
> + { .compatible = "maxim,ds4424" },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(of, ds4424_of_match);
> +
> +static struct i2c_driver ds4424_driver = {
> + .driver = {
> + .name   = "ds4424",
> + .pm = DS4424_PM_OPS,
> + },
> + .probe  = ds4424_probe,
> + .remove = ds4424_remove,
> + .id_table   = ds4424_id,
> +};
> +module_i2c_driver(ds4424_driver);
> +
> +MODULE_DESCRIPTION("Maxim DS4424 DAC Driver");
> +MODULE_AUTHOR("Ismail H. Kose ");
> +MODULE_AUTHOR("Vishal Sood ");
> +MODULE_AUTHOR("David Jung ");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/iio/dac/ds4424.h b/include/linux/iio/dac/ds4424.h
> new file mode 100644
> index ..09ff3d61797d
> --- /dev/null
> +++ b/include/linux/iio/dac/ds4424.h
> @@ -0,0 +1,29 @@
> +/*
> + * Maxim Integrated
> + * 7-bit, Multi-Channel Sink/Source Current DAC Driver
> + * Copyright (C) 2017 Maxim Integrated
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef IIO_DAC_DS4424_H_
> +#define IIO_DAC_DS4424_H_
> +#include 
> +#include 
> +
> +#define DS4422_MAX_DAC_CHANNELS  2
> +#define DS4424_MAX_DAC_CHANNELS  4
> +#define DS442X_MAX_DAC_CHANNELS  DS4424_MAX_DAC_CHANNELS
> +
> +struct ds4424_pdata {
> + const char *vcc_supply_name;
> + uint32_t max_rfs;
> + uint32_t min_rfs;
> + uint32_t ifs_scale;
> + uint32_t max_picoamp;
> + uint32_t rfs_res[DS442X_MAX_DAC_CHANNELS];
> + struct iio_map dac_iio_map[DS442X_MAX_DAC_CHANNELS + 1];
> +};
> +#endif /* IIO_DAC_DS4424_H_ */
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2] iio: adc: Add support for DLN2 ADC

2017-06-23 Thread Peter Meerwald-Stadler
ev_dbg(>pdev->dev, "Problem in %s\n", __func__);
> + return ret;
> + }
> +
> + return iio_triggered_buffer_postenable(indio_dev);
> +}
> +
> +static const struct iio_buffer_setup_ops dln2_adc_buffer_setup_ops = {
> + .postenable = dln2_adc_triggered_buffer_postenable,
> + .predisable = iio_triggered_buffer_predisable,
> +};
> +
> +static void dln2_adc_event(struct platform_device *pdev, u16 echo,
> +const void *data, int len)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct dln2_adc *dln2 = iio_priv(indio_dev);
> +
> + iio_trigger_poll(dln2->trig);
> +}
> +
> +static const struct iio_trigger_ops dln2_adc_trigger_ops = {
> + .owner = THIS_MODULE,
> +};
> +
> +static int dln2_adc_probe(struct platform_device *pdev)
> +{
> + struct device *dev = >dev;
> + struct dln2_adc *dln2;
> + struct dln2_platform_data *pdata = dev_get_platdata(>dev);
> + struct iio_dev *indio_dev;
> + struct iio_buffer *buffer;
> + int ret;
> + int chans;
> +
> + indio_dev = devm_iio_device_alloc(dev, sizeof(struct dln2_adc));
> + if (!indio_dev) {
> + dev_err(dev, "failed allocating iio device\n");
> + return -ENOMEM;
> + }
> +
> + dln2 = iio_priv(indio_dev);
> + dln2->pdev = pdev;
> + dln2->port = pdata->port;
> + mutex_init(>mutex);
> + dln2->port_enabled = false;
> + dln2->resolution_set = false;
> + dln2->chans_requested = 0;
> + dln2->chans_enabled = 0;
> + dln2->trigger_chan = -1;
> +
> + platform_set_drvdata(pdev, indio_dev);
> +
> + chans = dln2_adc_get_chan_count(dln2);
> + if (chans < 0) {
> + dev_err(dev, "failed to get channel count: %d\n", chans);
> + ret = chans;
> + goto dealloc_dev;
> + }
> + if (chans > DLN2_ADC_MAX_CHANNELS) {
> + chans = DLN2_ADC_MAX_CHANNELS;
> + dev_warn(dev, "clamping channels to %d\n",
> +  DLN2_ADC_MAX_CHANNELS);
> + }
> +
> + indio_dev->name = DLN2_ADC_MOD_NAME;
> + indio_dev->dev.parent = dev;
> + indio_dev->info = _adc_info;
> + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;
> + indio_dev->channels = dln2_adc_iio_channels;
> + indio_dev->num_channels = chans + 1;
> + indio_dev->setup_ops = _adc_buffer_setup_ops;
> +
> + dln2->trig = devm_iio_trigger_alloc(dev, "samplerate");
> + if (!dln2->trig) {
> + dev_err(dev, "failed to allocate trigger\n");
> + ret = -ENOMEM;
> + goto dealloc_dev;
> + }
> + dln2->trig->ops = _adc_trigger_ops;
> + iio_trigger_set_drvdata(dln2->trig, dln2);
> + iio_trigger_register(dln2->trig);
> + iio_trigger_set_immutable(indio_dev, dln2->trig);
> +
> + buffer = devm_iio_kfifo_allocate(dev);
> + if (!buffer) {
> + dev_err(dev, "failed to allocate kfifo\n");
> + ret = -ENOMEM;
> + goto dealloc_trigger;
> + }
> +
> + iio_device_attach_buffer(indio_dev, buffer);
> +
> + indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
> +  _adc_trigger_h,
> +  IRQF_ONESHOT,
> +  indio_dev,
> +  "samplerate");
> +
> + if (!indio_dev->pollfunc) {
> + ret = -ENOMEM;
> + goto dealloc_kfifo;
> + }
> +
> + ret = dln2_register_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV,
> +  dln2_adc_event);
> + if (ret) {
> + dev_err(dev, "failed to register event cb: %d\n", ret);
> + goto dealloc_pollfunc;
> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(dev, "failed to register iio device: %d\n", ret);
> + goto dealloc_pollfunc;
> + }
> +
> + return 0;
> +
> +dealloc_pollfunc:
> + iio_dealloc_pollfunc(indio_dev->pollfunc);
> +dealloc_kfifo:
> +dealloc_trigger:
> + iio_trigger_unregister(dln2->trig);
> +dealloc_dev:
> +
> + return ret;
> +}
> +
> +static int dln2_adc_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct dln2_adc *dln2 = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> + dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV);
> + iio_trigger_unregister(dln2->trig);
> + iio_dealloc_pollfunc(indio_dev->pollfunc);
> +
> + return 0;
> +}
> +
> +static struct platform_driver dln2_adc_driver = {
> + .driver.name= DLN2_ADC_MOD_NAME,
> + .probe  = dln2_adc_probe,
> + .remove = dln2_adc_remove,
> +};
> +
> +module_platform_driver(dln2_adc_driver);
> +
> +MODULE_AUTHOR("Jack Andersen <jackoa...@gmail.com");
> +MODULE_DESCRIPTION("Driver for the Diolan DLN2 ADC interface");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:dln2-adc");
> diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
> index 704e189..a22ab8c 100644
> --- a/drivers/mfd/dln2.c
> +++ b/drivers/mfd/dln2.c
> @@ -53,6 +53,7 @@ enum dln2_handle {
>   DLN2_HANDLE_GPIO,
>   DLN2_HANDLE_I2C,
>   DLN2_HANDLE_SPI,
> + DLN2_HANDLE_ADC,
>   DLN2_HANDLES
>  };
>  
> @@ -663,6 +664,12 @@ static int dln2_start_rx_urbs(struct dln2_dev *dln2, 
> gfp_t gfp)
>   .port = 0,
>  };
>  
> +/* Only one ADC port supported */
> +static struct dln2_platform_data dln2_pdata_adc = {
> + .handle = DLN2_HANDLE_ADC,
> + .port = 0,
> +};
> +
>  static const struct mfd_cell dln2_devs[] = {
>   {
>   .name = "dln2-gpio",
> @@ -679,6 +686,11 @@ static int dln2_start_rx_urbs(struct dln2_dev *dln2, 
> gfp_t gfp)
>   .platform_data = _pdata_spi,
>   .pdata_size = sizeof(struct dln2_platform_data),
>   },
> + {
> + .name = "dln2-adc",
> + .platform_data = _pdata_adc,
> + .pdata_size = sizeof(struct dln2_platform_data),
> + },
>  };
>  
>  static void dln2_stop(struct dln2_dev *dln2)
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2] iio: adc: Add support for DLN2 ADC

2017-06-23 Thread Peter Meerwald-Stadler
 "Problem in %s\n", __func__);
> + return ret;
> + }
> +
> + return iio_triggered_buffer_postenable(indio_dev);
> +}
> +
> +static const struct iio_buffer_setup_ops dln2_adc_buffer_setup_ops = {
> + .postenable = dln2_adc_triggered_buffer_postenable,
> + .predisable = iio_triggered_buffer_predisable,
> +};
> +
> +static void dln2_adc_event(struct platform_device *pdev, u16 echo,
> +const void *data, int len)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct dln2_adc *dln2 = iio_priv(indio_dev);
> +
> + iio_trigger_poll(dln2->trig);
> +}
> +
> +static const struct iio_trigger_ops dln2_adc_trigger_ops = {
> + .owner = THIS_MODULE,
> +};
> +
> +static int dln2_adc_probe(struct platform_device *pdev)
> +{
> + struct device *dev = >dev;
> + struct dln2_adc *dln2;
> + struct dln2_platform_data *pdata = dev_get_platdata(>dev);
> + struct iio_dev *indio_dev;
> + struct iio_buffer *buffer;
> + int ret;
> + int chans;
> +
> + indio_dev = devm_iio_device_alloc(dev, sizeof(struct dln2_adc));
> + if (!indio_dev) {
> + dev_err(dev, "failed allocating iio device\n");
> + return -ENOMEM;
> + }
> +
> + dln2 = iio_priv(indio_dev);
> + dln2->pdev = pdev;
> + dln2->port = pdata->port;
> + mutex_init(>mutex);
> + dln2->port_enabled = false;
> + dln2->resolution_set = false;
> + dln2->chans_requested = 0;
> + dln2->chans_enabled = 0;
> + dln2->trigger_chan = -1;
> +
> + platform_set_drvdata(pdev, indio_dev);
> +
> + chans = dln2_adc_get_chan_count(dln2);
> + if (chans < 0) {
> + dev_err(dev, "failed to get channel count: %d\n", chans);
> + ret = chans;
> + goto dealloc_dev;
> + }
> + if (chans > DLN2_ADC_MAX_CHANNELS) {
> + chans = DLN2_ADC_MAX_CHANNELS;
> + dev_warn(dev, "clamping channels to %d\n",
> +  DLN2_ADC_MAX_CHANNELS);
> + }
> +
> + indio_dev->name = DLN2_ADC_MOD_NAME;
> + indio_dev->dev.parent = dev;
> + indio_dev->info = _adc_info;
> + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;
> + indio_dev->channels = dln2_adc_iio_channels;
> + indio_dev->num_channels = chans + 1;
> + indio_dev->setup_ops = _adc_buffer_setup_ops;
> +
> + dln2->trig = devm_iio_trigger_alloc(dev, "samplerate");
> + if (!dln2->trig) {
> + dev_err(dev, "failed to allocate trigger\n");
> + ret = -ENOMEM;
> + goto dealloc_dev;
> + }
> + dln2->trig->ops = _adc_trigger_ops;
> + iio_trigger_set_drvdata(dln2->trig, dln2);
> + iio_trigger_register(dln2->trig);
> + iio_trigger_set_immutable(indio_dev, dln2->trig);
> +
> + buffer = devm_iio_kfifo_allocate(dev);
> + if (!buffer) {
> + dev_err(dev, "failed to allocate kfifo\n");
> + ret = -ENOMEM;
> + goto dealloc_trigger;
> + }
> +
> + iio_device_attach_buffer(indio_dev, buffer);
> +
> + indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
> +  _adc_trigger_h,
> +  IRQF_ONESHOT,
> +  indio_dev,
> +  "samplerate");
> +
> + if (!indio_dev->pollfunc) {
> + ret = -ENOMEM;
> + goto dealloc_kfifo;
> + }
> +
> + ret = dln2_register_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV,
> +  dln2_adc_event);
> + if (ret) {
> + dev_err(dev, "failed to register event cb: %d\n", ret);
> + goto dealloc_pollfunc;
> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(dev, "failed to register iio device: %d\n", ret);
> + goto dealloc_pollfunc;
> + }
> +
> + return 0;
> +
> +dealloc_pollfunc:
> + iio_dealloc_pollfunc(indio_dev->pollfunc);
> +dealloc_kfifo:
> +dealloc_trigger:
> + iio_trigger_unregister(dln2->trig);
> +dealloc_dev:
> +
> + return ret;
> +}
> +
> +static int dln2_adc_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct dln2_adc *dln2 = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> + dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV);
> + iio_trigger_unregister(dln2->trig);
> + iio_dealloc_pollfunc(indio_dev->pollfunc);
> +
> + return 0;
> +}
> +
> +static struct platform_driver dln2_adc_driver = {
> + .driver.name= DLN2_ADC_MOD_NAME,
> + .probe  = dln2_adc_probe,
> + .remove = dln2_adc_remove,
> +};
> +
> +module_platform_driver(dln2_adc_driver);
> +
> +MODULE_AUTHOR("Jack Andersen  +MODULE_DESCRIPTION("Driver for the Diolan DLN2 ADC interface");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:dln2-adc");
> diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
> index 704e189..a22ab8c 100644
> --- a/drivers/mfd/dln2.c
> +++ b/drivers/mfd/dln2.c
> @@ -53,6 +53,7 @@ enum dln2_handle {
>   DLN2_HANDLE_GPIO,
>   DLN2_HANDLE_I2C,
>   DLN2_HANDLE_SPI,
> + DLN2_HANDLE_ADC,
>   DLN2_HANDLES
>  };
>  
> @@ -663,6 +664,12 @@ static int dln2_start_rx_urbs(struct dln2_dev *dln2, 
> gfp_t gfp)
>   .port = 0,
>  };
>  
> +/* Only one ADC port supported */
> +static struct dln2_platform_data dln2_pdata_adc = {
> + .handle = DLN2_HANDLE_ADC,
> + .port = 0,
> +};
> +
>  static const struct mfd_cell dln2_devs[] = {
>   {
>   .name = "dln2-gpio",
> @@ -679,6 +686,11 @@ static int dln2_start_rx_urbs(struct dln2_dev *dln2, 
> gfp_t gfp)
>   .platform_data = _pdata_spi,
>   .pdata_size = sizeof(struct dln2_platform_data),
>   },
> + {
> + .name = "dln2-adc",
> + .platform_data = _pdata_adc,
> + .pdata_size = sizeof(struct dln2_platform_data),
> + },
>  };
>  
>  static void dln2_stop(struct dln2_dev *dln2)
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: adc: Add support for DLN2 ADC

2017-06-21 Thread Peter Meerwald-Stadler
dealloc_pollfunc;
> + }
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(dev, "failed to register iio device: %d\n", ret);
> + goto dealloc_pollfunc;
> + }
> +
> + dev_info(dev, "DLN2 ADC driver loaded\n");

avoid this kind of logging

> +
> + return 0;
> +
> +dealloc_pollfunc:
> + iio_dealloc_pollfunc(indio_dev->pollfunc);
> +dealloc_kfifo:
> +dealloc_trigger:
> + iio_trigger_unregister(dln2->trig);
> +dealloc_dev:
> +
> + return ret;
> +}
> +
> +static int dln2_adc_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct dln2_adc *dln2 = iio_priv(indio_dev);
> +
> + dev_info(_dev->dev, "DLN2 ADC driver unloaded\n");

no such logging please

> +
> + dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV);

should be after device_unregister

> + iio_device_unregister(indio_dev);
> + iio_trigger_unregister(dln2->trig);
> + iio_dealloc_pollfunc(indio_dev->pollfunc);
> +
> + return 0;
> +}
> +
> +static struct platform_driver dln2_adc_driver = {
> + .driver.name= DLN2_ADC_MOD_NAME,
> + .probe  = dln2_adc_probe,
> + .remove = dln2_adc_remove,
> +};
> +
> +module_platform_driver(dln2_adc_driver);
> +
> +MODULE_AUTHOR("Jack Andersen <jackoa...@gmail.com");
> +MODULE_DESCRIPTION("Driver for the Diolan DLN2 ADC interface");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:dln2-adc");
> diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
> index 704e189..a22ab8c 100644
> --- a/drivers/mfd/dln2.c
> +++ b/drivers/mfd/dln2.c
> @@ -53,6 +53,7 @@ enum dln2_handle {
>   DLN2_HANDLE_GPIO,
>   DLN2_HANDLE_I2C,
>   DLN2_HANDLE_SPI,
> + DLN2_HANDLE_ADC,
>   DLN2_HANDLES
>  };
>  
> @@ -663,6 +664,12 @@ static int dln2_start_rx_urbs(struct dln2_dev *dln2, 
> gfp_t gfp)
>   .port = 0,
>  };
>  
> +/* Only one ADC port supported */
> +static struct dln2_platform_data dln2_pdata_adc = {
> + .handle = DLN2_HANDLE_ADC,
> + .port = 0,
> +};
> +
>  static const struct mfd_cell dln2_devs[] = {
>   {
>   .name = "dln2-gpio",
> @@ -679,6 +686,11 @@ static int dln2_start_rx_urbs(struct dln2_dev *dln2, 
> gfp_t gfp)
>   .platform_data = _pdata_spi,
>   .pdata_size = sizeof(struct dln2_platform_data),
>   },
> + {
> + .name = "dln2-adc",
> + .platform_data = _pdata_adc,
> + .pdata_size = sizeof(struct dln2_platform_data),
> + },
>  };
>  
>  static void dln2_stop(struct dln2_dev *dln2)
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: adc: Add support for DLN2 ADC

2017-06-21 Thread Peter Meerwald-Stadler
 += 2;

2 should be sizeof(__le16) or sizeof(dev_data.values[i])

> + }
> + }
> +
> + iio_push_to_buffers_with_timestamp(indio_dev, data,
> +iio_get_time_ns(indio_dev));

there is no timestamp in dln2_adc_iio_channels; data would need space for 
timestamp + packing

> +
> + kfree(data);
> +
> +done:
> + iio_trigger_notify_done(indio_dev->trig);
> + return IRQ_HANDLED;
> +}
> +
> +static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
> +{
> + struct dln2_adc *dln2 = iio_priv(indio_dev);
> +
> + dln2->chans_requested |= *indio_dev->active_scan_mask;
> + dln2_adc_update_enabled_chans(dln2);

check return value?

> +
> + return iio_triggered_buffer_postenable(indio_dev);
> +}
> +
> +static const struct iio_buffer_setup_ops dln2_adc_buffer_setup_ops = {
> + .postenable = _adc_triggered_buffer_postenable,
> + .predisable = _triggered_buffer_predisable,

no need for &

> +};
> +
> +static void dln2_adc_event(struct platform_device *pdev, u16 echo,
> +const void *data, int len)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct dln2_adc *dln2 = iio_priv(indio_dev);
> +
> + iio_trigger_poll(dln2->trig);
> +}
> +
> +static const struct iio_trigger_ops dln2_adc_trigger_ops = {
> + .owner = THIS_MODULE,
> +};
> +
> +static int dln2_adc_probe(struct platform_device *pdev)
> +{
> + struct device *dev = >dev;
> + struct dln2_adc *dln2;
> + struct dln2_platform_data *pdata = dev_get_platdata(>dev);
> + struct iio_dev *indio_dev = NULL;

no need to initialize

> + struct iio_buffer *buffer;
> + int ret = -ENODEV;

no need to initialize

> + int chans;
> +
> + indio_dev = devm_iio_device_alloc(dev, sizeof(struct dln2_adc));
> + if (!indio_dev) {
> + dev_err(dev, "failed allocating iio device\n");
> + return -ENOMEM;
> + }
> +
> + dln2 = iio_priv(indio_dev);
> + dln2->pdev = pdev;
> + dln2->port = pdata->port;
> + dln2->port_enabled = 0;

false

> + dln2->resolution_set = 0;

false

> + dln2->chans_requested = 0;
> + dln2->chans_enabled = 0;
> + dln2->trigger_chan = -1;
> +
> + platform_set_drvdata(pdev, indio_dev);
> +
> + chans = dln2_adc_get_chan_count(dln2);
> + if (chans < 0) {
> + dev_err(dev, "failed to get channel count: %d\n", chans);
> + ret = chans;
> + goto dealloc_dev;
> + }
> + if (chans > DLN2_ADC_MAX_CHANNELS) {
> + chans = DLN2_ADC_MAX_CHANNELS;
> + dev_warn(dev, "clamping channels to %d\n",
> +  DLN2_ADC_MAX_CHANNELS);
> + }
> +
> + indio_dev->name = DLN2_ADC_MOD_NAME;
> + indio_dev->dev.parent = dev;
> + indio_dev->info = _adc_info;
> + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;
> + indio_dev->channels = dln2_adc_iio_channels;
> + indio_dev->num_channels = chans;
> + indio_dev->setup_ops = _adc_buffer_setup_ops;
> +
> + dln2->trig = devm_iio_trigger_alloc(dev, "samplerate");
> + if (!dln2->trig) {
> + dev_err(dev, "failed to allocate trigger\n");
> + goto dealloc_dev;
> + }
> + dln2->trig->ops = _adc_trigger_ops;
> + iio_trigger_set_drvdata(dln2->trig, dln2);
> + iio_trigger_register(dln2->trig);
> + iio_trigger_set_immutable(indio_dev, dln2->trig);
> +
> + buffer = devm_iio_kfifo_allocate(dev);
> + if (!buffer) {
> + dev_err(dev, "failed to allocate kfifo\n");
> + ret = -ENOMEM;
> + goto dealloc_trigger;
> + }
> +
> + iio_device_attach_buffer(indio_dev, buffer);
> +
> + indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
> +  _adc_trigger_h,
> +  IRQF_ONESHOT,
> +  indio_dev,
> +  "samplerate");
> +
> + if (!indio_dev->pollfunc) {
> + ret = -ENOMEM;
> + goto dealloc_kfifo;
> + }
> +
> + ret = dln2_register_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV,
> +  dln2_adc_event);
> + if (ret) {
> + dev_err(dev, "failed to register event cb: %d\n", ret);
> + goto dealloc_pollfunc;
> + 

[tip:timers/core] timers: Fix parameter description of try_to_del_timer_sync()

2017-06-20 Thread tip-bot for Peter Meerwald-Stadler
Commit-ID:  d15bc69affc57d7985a01745ca28eafa0772325b
Gitweb: http://git.kernel.org/tip/d15bc69affc57d7985a01745ca28eafa0772325b
Author: Peter Meerwald-Stadler <pme...@pmeerw.net>
AuthorDate: Tue, 30 May 2017 21:41:03 +0200
Committer:  Thomas Gleixner <t...@linutronix.de>
CommitDate: Tue, 20 Jun 2017 21:33:55 +0200

timers: Fix parameter description of try_to_del_timer_sync()

Signed-off-by: Peter Meerwald-Stadler <pme...@pmeerw.net>
Link: http://lkml.kernel.org/r/20170530194103.7454-1-pme...@pmeerw.net
Cc: John Stultz <john.stu...@linaro.org>
Cc: triv...@rustcorp.com.au
Signed-off-by: Thomas Gleixner <t...@linutronix.de>

---
 kernel/time/timer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 152a706..709a404 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1150,7 +1150,7 @@ EXPORT_SYMBOL(del_timer);
 
 /**
  * try_to_del_timer_sync - Try to deactivate a timer
- * @timer: timer do del
+ * @timer: timer to delete
  *
  * This function tries to deactivate a timer. Upon successful (ret >= 0)
  * exit the timer is not queued and the handler is not running on any CPU.


[tip:timers/core] timers: Fix parameter description of try_to_del_timer_sync()

2017-06-20 Thread tip-bot for Peter Meerwald-Stadler
Commit-ID:  d15bc69affc57d7985a01745ca28eafa0772325b
Gitweb: http://git.kernel.org/tip/d15bc69affc57d7985a01745ca28eafa0772325b
Author: Peter Meerwald-Stadler 
AuthorDate: Tue, 30 May 2017 21:41:03 +0200
Committer:  Thomas Gleixner 
CommitDate: Tue, 20 Jun 2017 21:33:55 +0200

timers: Fix parameter description of try_to_del_timer_sync()

Signed-off-by: Peter Meerwald-Stadler 
Link: http://lkml.kernel.org/r/20170530194103.7454-1-pme...@pmeerw.net
Cc: John Stultz 
Cc: triv...@rustcorp.com.au
Signed-off-by: Thomas Gleixner 

---
 kernel/time/timer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 152a706..709a404 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1150,7 +1150,7 @@ EXPORT_SYMBOL(del_timer);
 
 /**
  * try_to_del_timer_sync - Try to deactivate a timer
- * @timer: timer do del
+ * @timer: timer to delete
  *
  * This function tries to deactivate a timer. Upon successful (ret >= 0)
  * exit the timer is not queued and the handler is not running on any CPU.


[PATCH] time: Fix parameter description of try_to_del_timer_sync()

2017-05-30 Thread Peter Meerwald-Stadler
Signed-off-by: Peter Meerwald-Stadler <pme...@pmeerw.net>
Cc: John Stultz <john.stu...@linaro.org>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: triv...@rustcorp.com.au
---
 kernel/time/timer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 152a706ef8b8..709a404bd133 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1150,7 +1150,7 @@ EXPORT_SYMBOL(del_timer);
 
 /**
  * try_to_del_timer_sync - Try to deactivate a timer
- * @timer: timer do del
+ * @timer: timer to delete
  *
  * This function tries to deactivate a timer. Upon successful (ret >= 0)
  * exit the timer is not queued and the handler is not running on any CPU.
-- 
2.11.0



[PATCH] time: Fix parameter description of try_to_del_timer_sync()

2017-05-30 Thread Peter Meerwald-Stadler
Signed-off-by: Peter Meerwald-Stadler 
Cc: John Stultz 
Cc: Thomas Gleixner 
Cc: triv...@rustcorp.com.au
---
 kernel/time/timer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 152a706ef8b8..709a404bd133 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1150,7 +1150,7 @@ EXPORT_SYMBOL(del_timer);
 
 /**
  * try_to_del_timer_sync - Try to deactivate a timer
- * @timer: timer do del
+ * @timer: timer to delete
  *
  * This function tries to deactivate a timer. Upon successful (ret >= 0)
  * exit the timer is not queued and the handler is not running on any CPU.
-- 
2.11.0



Re: [PATCH RFC] iio: pressure: zpa2326: report interrupted case as failure

2017-05-14 Thread Peter Meerwald-Stadler

> If the timeout-case prints a warning message then probably the interrupted
> case should also. Further, wait_for_completion_interruptible_timeout()
> returns long not int. 
> 
> Fixes: commit 03b262f2bbf4 ("iio:pressure: initial zpa2326 barometer support")
> Signed-off-by: Nicholas Mc Guire <der.h...@hofr.at>

this is actually a v2, looks good to me

> ---
> 
> The original control-flow was technically not wrong just confusing and a bit 
> complicated. Not clear if reporting the interrupted case actually is useful,
> but given that the timeout is relatively long (200ms) it is not that unlikely
> so differentiating the cases seems helpful.
> 
> Patch was compile-tested with: x86_64_defconfig + CONFIG_IIO=m, 
> CONFIG_ZPA2326=m
> 
> Patch is against v4.11 (localversion-next is next-20170512)
> 
>  drivers/iio/pressure/zpa2326.c | 17 ++---
>  1 file changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
> index e58a0ad..617926f 100644
> --- a/drivers/iio/pressure/zpa2326.c
> +++ b/drivers/iio/pressure/zpa2326.c
> @@ -867,12 +867,13 @@ static int zpa2326_wait_oneshot_completion(const struct 
> iio_dev   *indio_dev,
>  {
>   int  ret;
>   unsigned int val;
> + long timeout;
>  
>   zpa2326_dbg(indio_dev, "waiting for one shot completion interrupt");
>  
> - ret = wait_for_completion_interruptible_timeout(
> + timeout = wait_for_completion_interruptible_timeout(
>   >data_ready, ZPA2326_CONVERSION_JIFFIES);
> - if (ret > 0)
> + if (timeout > 0)
>   /*
>* Interrupt handler completed before timeout: return operation
>* status.
> @@ -882,13 +883,15 @@ static int zpa2326_wait_oneshot_completion(const struct 
> iio_dev   *indio_dev,
>   /* Clear all interrupts just to be sure. */
>   regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, );
>  
> - if (!ret)
> + if (!timeout) {
>   /* Timed out. */
> + zpa2326_warn(indio_dev, "no one shot interrupt occurred (%ld)",
> +  timeout);
>   ret = -ETIME;
> -
> - if (ret != -ERESTARTSYS)
> - zpa2326_warn(indio_dev, "no one shot interrupt occurred (%d)",
> -      ret);
> + } else if (timeout < 0) {
> + zpa2326_warn(indio_dev, "wait for one shot interrupt canceled");
> + ret = -ERESTARTSYS;
> + }
>  
>   return ret;
>  }
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH RFC] iio: pressure: zpa2326: report interrupted case as failure

2017-05-14 Thread Peter Meerwald-Stadler

> If the timeout-case prints a warning message then probably the interrupted
> case should also. Further, wait_for_completion_interruptible_timeout()
> returns long not int. 
> 
> Fixes: commit 03b262f2bbf4 ("iio:pressure: initial zpa2326 barometer support")
> Signed-off-by: Nicholas Mc Guire 

this is actually a v2, looks good to me

> ---
> 
> The original control-flow was technically not wrong just confusing and a bit 
> complicated. Not clear if reporting the interrupted case actually is useful,
> but given that the timeout is relatively long (200ms) it is not that unlikely
> so differentiating the cases seems helpful.
> 
> Patch was compile-tested with: x86_64_defconfig + CONFIG_IIO=m, 
> CONFIG_ZPA2326=m
> 
> Patch is against v4.11 (localversion-next is next-20170512)
> 
>  drivers/iio/pressure/zpa2326.c | 17 ++---
>  1 file changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
> index e58a0ad..617926f 100644
> --- a/drivers/iio/pressure/zpa2326.c
> +++ b/drivers/iio/pressure/zpa2326.c
> @@ -867,12 +867,13 @@ static int zpa2326_wait_oneshot_completion(const struct 
> iio_dev   *indio_dev,
>  {
>   int  ret;
>   unsigned int val;
> + long timeout;
>  
>   zpa2326_dbg(indio_dev, "waiting for one shot completion interrupt");
>  
> - ret = wait_for_completion_interruptible_timeout(
> + timeout = wait_for_completion_interruptible_timeout(
>   >data_ready, ZPA2326_CONVERSION_JIFFIES);
> - if (ret > 0)
> + if (timeout > 0)
>   /*
>* Interrupt handler completed before timeout: return operation
>* status.
> @@ -882,13 +883,15 @@ static int zpa2326_wait_oneshot_completion(const struct 
> iio_dev   *indio_dev,
>   /* Clear all interrupts just to be sure. */
>   regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, );
>  
> - if (!ret)
> + if (!timeout) {
>   /* Timed out. */
> + zpa2326_warn(indio_dev, "no one shot interrupt occurred (%ld)",
> +  timeout);
>   ret = -ETIME;
> -
> - if (ret != -ERESTARTSYS)
> - zpa2326_warn(indio_dev, "no one shot interrupt occurred (%d)",
> -  ret);
> + } else if (timeout < 0) {
> + zpa2326_warn(indio_dev, "wait for one shot interrupt canceled");
> + ret = -ERESTARTSYS;
> + }
>  
>   return ret;
>  }
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: Add driver for Infineon DPS310

2017-05-05 Thread Peter Meerwald-Stadler
ata = iio_priv(iio);
> +
> + if (chan->type != IIO_TEMP)
> + return -EINVAL;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + return dps310_set_temp_samp_freq(data, val);
> + case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> + return dps310_set_temp_precision(data, val);
> + default:
> + return -EINVAL;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static int dps310_read_raw(struct iio_dev *iio,
> +struct iio_chan_spec const *chan,
> +int *val, int *val2, long mask)
> +{
> + struct dps310_data *data = iio_priv(iio);
> + int ret;
> +
> + /* c0 * 0.5 + c1 * T_raw / kT °C */
> + switch (mask) {
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + *val = dps310_get_temp_samp_freq(data);
> + return IIO_VAL_INT;
> +
> + case IIO_CHAN_INFO_RAW:
> + ret = dps310_read_temp(data);
> + if (ret)
> + return ret;
> +
> + *val = data->temp_raw * data->c1;
> + return IIO_VAL_INT;
> +
> + case IIO_CHAN_INFO_OFFSET:
> + *val = (data->c0 >> 1) * dps310_get_temp_k(data);
> + return IIO_VAL_INT;
> +
> + case IIO_CHAN_INFO_SCALE:
> + *val = MCELSIUS_PER_CELSIUS;
> + *val2 = dps310_get_temp_k(data);
> + return IIO_VAL_FRACTIONAL;
> +
> + case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> + *val = dps310_get_temp_precision(data);
> + return IIO_VAL_INT;
> +
> + default:
> + return -EINVAL;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static const struct regmap_config dps310_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .writeable_reg = dps310_is_writeable_reg,
> + .volatile_reg = dps310_is_volatile_reg,
> + .cache_type = REGCACHE_RBTREE,
> + .max_register = 0x29,
> +};
> +
> +static const struct iio_info dps310_info = {
> + .driver_module = THIS_MODULE,
> + .read_raw = dps310_read_raw,
> + .write_raw = dps310_write_raw,
> +};
> +
> +static int dps310_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct dps310_data *data;
> + struct iio_dev *iio;
> + int r;
> +
> + iio = devm_iio_device_alloc(>dev,  sizeof(*data));
> + if (!iio)
> + return -ENOMEM;
> +
> + data = iio_priv(iio);
> + data->client = client;
> +
> + iio->dev.parent = >dev;
> + iio->name = id->name;
> + iio->channels = dps310_channels;
> + iio->num_channels = ARRAY_SIZE(dps310_channels);
> + iio->info = _info;
> + iio->modes = INDIO_DIRECT_MODE;
> +
> + data->regmap = devm_regmap_init_i2c(client, _regmap_config);
> + if (IS_ERR(data->regmap))
> + return PTR_ERR(data->regmap);
> +
> + r = regmap_write(data->regmap, TMP_CFG, TMP_EXT | TMP_PRC(1));
> + if (r < 0)
> + return r;
> + r = regmap_write_bits(data->regmap, CFG_REG, TMP_SHIFT_EN, 0);
> + if (r < 0)
> + return r;
> +
> + /* Turn on temperature measurement in the background */
> + r = regmap_write_bits(data->regmap, MEAS_CFG, MEAS_CTRL_BITS,
> + TEMP_EN | BACKGROUND);

should be disabled again if _probe fails lateron

> + if (r < 0)
> + return r;
> +
> + /*
> +  * Calibration coefficients required for reporting temperature.
> +  * They are availalbe 40ms after the device has started

available

> +  */
> + r = dps310_get_temp_coef(data);
> + if (r == -EAGAIN)
> + return -EPROBE_DEFER;

wouldn't it make more sense to wait for the data to become ready, maybe 
with a timeout?

> + if (r < 0)
> + return r;
> +
> + r = devm_iio_device_register(>dev, iio);
> + if (r)
> + return r;
> +
> + i2c_set_clientdata(client, iio);
> +
> + dev_info(>dev, "%s: sensor '%s'\n", dev_name(>dev),
> + client->name);

no extra logging, this adds little extra information

> + return 0;
> +}

turn off measurement in _remove()?

> +
> +static const struct i2c_device_id dps310_id[] = {
> + { "dps310", 0 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(i2c, dps310_id);
> +
> +static const unsigned short normal_i2c[] = {
> + 0x77, 0x76, I2C_CLIENT_END
> +};
> +
> +static struct i2c_driver dps310_driver = {
> + .driver = {
> + .name = "dps310",
> + },
> + .probe = dps310_probe,
> + .address_list = normal_i2c,
> + .id_table = dps310_id,
> +};
> +module_i2c_driver(dps310_driver);
> +
> +MODULE_AUTHOR("Joel Stanley <j...@jms.id.au>");
> +MODULE_DESCRIPTION("Infineon DPS310 pressure and temperature sensor");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH] iio: Add driver for Infineon DPS310

2017-05-05 Thread Peter Meerwald-Stadler
>type != IIO_TEMP)
> + return -EINVAL;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + return dps310_set_temp_samp_freq(data, val);
> + case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> + return dps310_set_temp_precision(data, val);
> + default:
> + return -EINVAL;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static int dps310_read_raw(struct iio_dev *iio,
> +struct iio_chan_spec const *chan,
> +int *val, int *val2, long mask)
> +{
> + struct dps310_data *data = iio_priv(iio);
> + int ret;
> +
> + /* c0 * 0.5 + c1 * T_raw / kT °C */
> + switch (mask) {
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + *val = dps310_get_temp_samp_freq(data);
> + return IIO_VAL_INT;
> +
> + case IIO_CHAN_INFO_RAW:
> + ret = dps310_read_temp(data);
> + if (ret)
> + return ret;
> +
> + *val = data->temp_raw * data->c1;
> + return IIO_VAL_INT;
> +
> + case IIO_CHAN_INFO_OFFSET:
> + *val = (data->c0 >> 1) * dps310_get_temp_k(data);
> + return IIO_VAL_INT;
> +
> + case IIO_CHAN_INFO_SCALE:
> + *val = MCELSIUS_PER_CELSIUS;
> + *val2 = dps310_get_temp_k(data);
> + return IIO_VAL_FRACTIONAL;
> +
> + case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> + *val = dps310_get_temp_precision(data);
> + return IIO_VAL_INT;
> +
> + default:
> + return -EINVAL;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static const struct regmap_config dps310_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> + .writeable_reg = dps310_is_writeable_reg,
> + .volatile_reg = dps310_is_volatile_reg,
> + .cache_type = REGCACHE_RBTREE,
> + .max_register = 0x29,
> +};
> +
> +static const struct iio_info dps310_info = {
> + .driver_module = THIS_MODULE,
> + .read_raw = dps310_read_raw,
> + .write_raw = dps310_write_raw,
> +};
> +
> +static int dps310_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct dps310_data *data;
> + struct iio_dev *iio;
> + int r;
> +
> + iio = devm_iio_device_alloc(>dev,  sizeof(*data));
> + if (!iio)
> + return -ENOMEM;
> +
> + data = iio_priv(iio);
> + data->client = client;
> +
> + iio->dev.parent = >dev;
> + iio->name = id->name;
> + iio->channels = dps310_channels;
> + iio->num_channels = ARRAY_SIZE(dps310_channels);
> + iio->info = _info;
> + iio->modes = INDIO_DIRECT_MODE;
> +
> + data->regmap = devm_regmap_init_i2c(client, _regmap_config);
> + if (IS_ERR(data->regmap))
> + return PTR_ERR(data->regmap);
> +
> + r = regmap_write(data->regmap, TMP_CFG, TMP_EXT | TMP_PRC(1));
> + if (r < 0)
> + return r;
> + r = regmap_write_bits(data->regmap, CFG_REG, TMP_SHIFT_EN, 0);
> + if (r < 0)
> + return r;
> +
> + /* Turn on temperature measurement in the background */
> + r = regmap_write_bits(data->regmap, MEAS_CFG, MEAS_CTRL_BITS,
> + TEMP_EN | BACKGROUND);

should be disabled again if _probe fails lateron

> +     if (r < 0)
> + return r;
> +
> + /*
> +  * Calibration coefficients required for reporting temperature.
> +  * They are availalbe 40ms after the device has started

available

> +  */
> + r = dps310_get_temp_coef(data);
> + if (r == -EAGAIN)
> + return -EPROBE_DEFER;

wouldn't it make more sense to wait for the data to become ready, maybe 
with a timeout?

> + if (r < 0)
> + return r;
> +
> + r = devm_iio_device_register(>dev, iio);
> + if (r)
> + return r;
> +
> + i2c_set_clientdata(client, iio);
> +
> + dev_info(>dev, "%s: sensor '%s'\n", dev_name(>dev),
> + client->name);

no extra logging, this adds little extra information

> + return 0;
> +}

turn off measurement in _remove()?

> +
> +static const struct i2c_device_id dps310_id[] = {
> + { "dps310", 0 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(i2c, dps310_id);
> +
> +static const unsigned short normal_i2c[] = {
> + 0x77, 0x76, I2C_CLIENT_END
> +};
> +
> +static struct i2c_driver dps310_driver = {
> + .driver = {
> + .name = "dps310",
> + },
> + .probe = dps310_probe,
> + .address_list = normal_i2c,
> + .id_table = dps310_id,
> +};
> +module_i2c_driver(dps310_driver);
> +
> +MODULE_AUTHOR("Joel Stanley ");
> +MODULE_DESCRIPTION("Infineon DPS310 pressure and temperature sensor");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [BUG RFC] iio: pressure: zpa2326: incorrect condition or inconsistent return handling

2017-05-03 Thread Peter Meerwald-Stadler
Hello,

> wait_for_completion_interruptible_timeout() returns -ERESTARTSYS, 0 or
> remaining time in jiffies (atleast 1), thus the if (ret != -ERESTARTSYS)
> case here is unreachable. 

if is not unreachable, there is a ret = -ETIME above it
 
> As it is not clear from the warn message if this should simply be changed
> to if (ret == -ERESTARTSYS), this needs a review by someone that knows
> the intent of this condition. In any case the current treatment of the
> return value of wait_for_completion_interruptible_timeout() is inconsistent
> with the specification of the same.

the intention of the code is not very clear, I agree

"no one shot interrupt" should probably be printed for the -ETIME case, 
i.e. when a timeout occurs
 
> Also wait_for_completion_interruptible_timeout() returns a long not int.

true
 
> Problem was introduced in commit 03b262f2bbf4 ("iio:pressure: initial zpa2326 
> barometer support")
> 
>  drivers/iio/pressure/zpa2326.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
> index e58a0ad..80ca6ec 100644
> --- a/drivers/iio/pressure/zpa2326.c
> +++ b/drivers/iio/pressure/zpa2326.c
> @@ -872,35 +872,35 @@ static int zpa2326_wait_oneshot_completion(const struct 
> iio_dev   *indio_dev,
>  
>   ret = wait_for_completion_interruptible_timeout(
>   >data_ready, ZPA2326_CONVERSION_JIFFIES);
>   if (ret > 0)
>   /*
>* Interrupt handler completed before timeout: return operation
>* status.
>*/
>   return private->result;
>  
>   /* Clear all interrupts just to be sure. */
>   regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, );
>  
>   if (!ret)
>   /* Timed out. */
>   ret = -ETIME;
>  
> - if (ret != -ERESTARTSYS)
> + if (ret == -ERESTARTSYS)
>   zpa2326_warn(indio_dev, "no one shot interrupt occurred (%d)",
>ret);
>  
>   return ret;
>  }
>  
>  static int zpa2326_init_managed_irq(struct device  *parent,
>   struct iio_dev *indio_dev,
>   struct zpa2326_private *private,
>   int irq)
>  {
>   int err;
>  
>   private->irq = irq;
>  
>   if (irq <= 0) {
>   /*
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [BUG RFC] iio: pressure: zpa2326: incorrect condition or inconsistent return handling

2017-05-03 Thread Peter Meerwald-Stadler
Hello,

> wait_for_completion_interruptible_timeout() returns -ERESTARTSYS, 0 or
> remaining time in jiffies (atleast 1), thus the if (ret != -ERESTARTSYS)
> case here is unreachable. 

if is not unreachable, there is a ret = -ETIME above it
 
> As it is not clear from the warn message if this should simply be changed
> to if (ret == -ERESTARTSYS), this needs a review by someone that knows
> the intent of this condition. In any case the current treatment of the
> return value of wait_for_completion_interruptible_timeout() is inconsistent
> with the specification of the same.

the intention of the code is not very clear, I agree

"no one shot interrupt" should probably be printed for the -ETIME case, 
i.e. when a timeout occurs
 
> Also wait_for_completion_interruptible_timeout() returns a long not int.

true
 
> Problem was introduced in commit 03b262f2bbf4 ("iio:pressure: initial zpa2326 
> barometer support")
> 
>  drivers/iio/pressure/zpa2326.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
> index e58a0ad..80ca6ec 100644
> --- a/drivers/iio/pressure/zpa2326.c
> +++ b/drivers/iio/pressure/zpa2326.c
> @@ -872,35 +872,35 @@ static int zpa2326_wait_oneshot_completion(const struct 
> iio_dev   *indio_dev,
>  
>   ret = wait_for_completion_interruptible_timeout(
>   >data_ready, ZPA2326_CONVERSION_JIFFIES);
>   if (ret > 0)
>   /*
>* Interrupt handler completed before timeout: return operation
>* status.
>*/
>   return private->result;
>  
>   /* Clear all interrupts just to be sure. */
>   regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, );
>  
>   if (!ret)
>   /* Timed out. */
>   ret = -ETIME;
>  
> - if (ret != -ERESTARTSYS)
> + if (ret == -ERESTARTSYS)
>   zpa2326_warn(indio_dev, "no one shot interrupt occurred (%d)",
>ret);
>  
>   return ret;
>  }
>  
>  static int zpa2326_init_managed_irq(struct device  *parent,
>   struct iio_dev *indio_dev,
>   struct zpa2326_private *private,
>   int irq)
>  {
>   int err;
>  
>   private->irq = irq;
>  
>   if (irq <= 0) {
>   /*
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: adc: Add support for TI ADC1x8s102

2017-04-25 Thread Peter Meerwald-Stadler
ler;
> + const struct acpi_device_id *id;
> +
> + id = acpi_match_device(adc1x8s102_acpi_ids, >dev);
> + if (!id)
> + return -ENODEV;
> +
> + setup_handler = (acpi_setup_handler)id->driver_data;
> + if (setup_handler) {
> + ret = setup_handler(spi, );
> + if (ret)
> + return ret;
> + }
> + }
> +#endif
> +
> + if (!pdata) {
> + dev_err(>dev, "Cannot get adc1x8s102 platform data\n");
> + return -ENODEV;
> + }
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*st));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + st = iio_priv(indio_dev);
> + st->ext_vin = pdata->ext_vin;
> +
> + /* Use regulator, if available. */
> + st->reg = devm_regulator_get(>dev, "vref");
> + if (IS_ERR(st->reg)) {
> + dev_err(>dev, "Cannot get 'vref' regulator\n");
> + return PTR_ERR(st->reg);
> + }
> + ret = regulator_enable(st->reg);
> + if (ret < 0) {
> + dev_err(>dev, "Cannot enable vref regulator\n");
> + return ret;
> + }
> +
> + spi_set_drvdata(spi, indio_dev);
> + st->spi = spi;
> +
> + indio_dev->name = spi->modalias;
> + indio_dev->dev.parent = >dev;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = adc1x8s102_channels;
> + indio_dev->num_channels = ARRAY_SIZE(adc1x8s102_channels);
> + indio_dev->info = _info;
> +
> + /* Setup default message */
> + st->scan_single_xfer.tx_buf = st->tx_buf;
> + st->scan_single_xfer.rx_buf = st->rx_buf;
> + st->scan_single_xfer.len = 2 * sizeof(__be16);
> + st->scan_single_xfer.cs_change = 0;
> +
> + spi_message_init(>scan_single_msg);
> + spi_message_add_tail(>scan_single_xfer, >scan_single_msg);
> +
> + ret = iio_triggered_buffer_setup(indio_dev, NULL,
> + _trigger_handler, NULL);
> + if (ret)
> + goto error_disable_reg;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(>dev,
> + "Failed to register IIO device\n");
> + goto error_cleanup_ring;
> + }
> + return 0;
> +
> +error_cleanup_ring:
> + iio_triggered_buffer_cleanup(indio_dev);
> +error_disable_reg:
> + regulator_disable(st->reg);
> +
> + return ret;
> +}
> +
> +static int adc1x8s102_remove(struct spi_device *spi)
> +{
> + struct iio_dev *indio_dev = spi_get_drvdata(spi);
> + struct adc1x8s102_state *st = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> + iio_triggered_buffer_cleanup(indio_dev);
> +
> + regulator_disable(st->reg);
> +
> + return 0;
> +}
> +
> +static const struct spi_device_id adc1x8s102_id[] = {
> + { "adc1x8s102", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(spi, adc1x8s102_id);
> +
> +static struct spi_driver adc1x8s102_driver = {
> +     .driver = {
> + .name   = "adc1x8s102",
> + .owner  = THIS_MODULE,
> + .acpi_match_table = ACPI_PTR(adc1x8s102_acpi_ids),
> + },
> + .probe  = adc1x8s102_probe,
> + .remove = adc1x8s102_remove,
> + .id_table   = adc1x8s102_id,
> +};
> +module_spi_driver(adc1x8s102_driver);
> +
> +MODULE_AUTHOR("Bogdan Pricop <bogdan.pri...@emutex.com>");
> +MODULE_DESCRIPTION("Texas Instruments ADC1x8S102 driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/platform_data/adc1x8s102.h 
> b/include/linux/platform_data/adc1x8s102.h
> new file mode 100644
> index ..6ad753c99823
> --- /dev/null
> +++ b/include/linux/platform_data/adc1x8s102.h
> @@ -0,0 +1,28 @@
> +/*
> + * ADC1x8S102 SPI ADC driver
> + *
> + * Copyright(c) 2013 Intel Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + */
> +
> +#ifndef __LINUX_PLATFORM_DATA_ADC1x8S102_H__
> +#define __LINUX_PLATFORM_DATA_ADC1x8S102_H__
> +
> +/**
> + * struct adc1x8s102_platform_data - Platform data for the adc1x8s102 ADC 
> driver
> + * @ext_vin: External input voltage range for all voltage input channels
> + *   This is the voltage level of pin VA in millivolts
> + **/
> +struct adc1x8s102_platform_data {
> + u16  ext_vin;
> +};
> +
> +#endif /* __LINUX_PLATFORM_DATA_ADC1x8S102_H__ */
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH] iio: adc: Add support for TI ADC1x8s102

2017-04-25 Thread Peter Meerwald-Stadler
ice(adc1x8s102_acpi_ids, >dev);
> + if (!id)
> + return -ENODEV;
> +
> + setup_handler = (acpi_setup_handler)id->driver_data;
> + if (setup_handler) {
> + ret = setup_handler(spi, );
> + if (ret)
> + return ret;
> + }
> + }
> +#endif
> +
> + if (!pdata) {
> + dev_err(>dev, "Cannot get adc1x8s102 platform data\n");
> + return -ENODEV;
> + }
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*st));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + st = iio_priv(indio_dev);
> + st->ext_vin = pdata->ext_vin;
> +
> + /* Use regulator, if available. */
> + st->reg = devm_regulator_get(>dev, "vref");
> + if (IS_ERR(st->reg)) {
> + dev_err(>dev, "Cannot get 'vref' regulator\n");
> + return PTR_ERR(st->reg);
> + }
> + ret = regulator_enable(st->reg);
> + if (ret < 0) {
> + dev_err(>dev, "Cannot enable vref regulator\n");
> + return ret;
> + }
> +
> + spi_set_drvdata(spi, indio_dev);
> + st->spi = spi;
> +
> + indio_dev->name = spi->modalias;
> + indio_dev->dev.parent = >dev;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = adc1x8s102_channels;
> + indio_dev->num_channels = ARRAY_SIZE(adc1x8s102_channels);
> + indio_dev->info = _info;
> +
> + /* Setup default message */
> + st->scan_single_xfer.tx_buf = st->tx_buf;
> + st->scan_single_xfer.rx_buf = st->rx_buf;
> + st->scan_single_xfer.len = 2 * sizeof(__be16);
> + st->scan_single_xfer.cs_change = 0;
> +
> + spi_message_init(>scan_single_msg);
> + spi_message_add_tail(>scan_single_xfer, >scan_single_msg);
> +
> + ret = iio_triggered_buffer_setup(indio_dev, NULL,
> + _trigger_handler, NULL);
> + if (ret)
> + goto error_disable_reg;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(>dev,
> + "Failed to register IIO device\n");
> + goto error_cleanup_ring;
> + }
> + return 0;
> +
> +error_cleanup_ring:
> + iio_triggered_buffer_cleanup(indio_dev);
> +error_disable_reg:
> + regulator_disable(st->reg);
> +
> + return ret;
> +}
> +
> +static int adc1x8s102_remove(struct spi_device *spi)
> +{
> + struct iio_dev *indio_dev = spi_get_drvdata(spi);
> + struct adc1x8s102_state *st = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> + iio_triggered_buffer_cleanup(indio_dev);
> +
> + regulator_disable(st->reg);
> +
> + return 0;
> +}
> +
> +static const struct spi_device_id adc1x8s102_id[] = {
> + { "adc1x8s102", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(spi, adc1x8s102_id);
> +
> +static struct spi_driver adc1x8s102_driver = {
> + .driver = {
> + .name   = "adc1x8s102",
> + .owner  = THIS_MODULE,
> + .acpi_match_table = ACPI_PTR(adc1x8s102_acpi_ids),
> + },
> + .probe  = adc1x8s102_probe,
> + .remove = adc1x8s102_remove,
> + .id_table   = adc1x8s102_id,
> +};
> +module_spi_driver(adc1x8s102_driver);
> +
> +MODULE_AUTHOR("Bogdan Pricop ");
> +MODULE_DESCRIPTION("Texas Instruments ADC1x8S102 driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/platform_data/adc1x8s102.h 
> b/include/linux/platform_data/adc1x8s102.h
> new file mode 100644
> index ..6ad753c99823
> --- /dev/null
> +++ b/include/linux/platform_data/adc1x8s102.h
> @@ -0,0 +1,28 @@
> +/*
> + * ADC1x8S102 SPI ADC driver
> + *
> + * Copyright(c) 2013 Intel Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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.
> + */
> +
> +#ifndef __LINUX_PLATFORM_DATA_ADC1x8S102_H__
> +#define __LINUX_PLATFORM_DATA_ADC1x8S102_H__
> +
> +/**
> + * struct adc1x8s102_platform_data - Platform data for the adc1x8s102 ADC 
> driver
> + * @ext_vin: External input voltage range for all voltage input channels
> + *   This is the voltage level of pin VA in millivolts
> + **/
> +struct adc1x8s102_platform_data {
> + u16  ext_vin;
> +};
> +
> +#endif /* __LINUX_PLATFORM_DATA_ADC1x8S102_H__ */
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

Re: [PATCH 2/4] iio: dac: add support for stm32 DAC

2017-04-01 Thread Peter Meerwald-Stadler
o_dev *indio_dev)
> +{
> + struct device_node *np = indio_dev->dev.of_node;
> + unsigned int i;
> + u32 channel;
> + int ret;
> +
> + ret = of_property_read_u32(np, "st,dac-channel", );
> + if (ret) {
> + dev_err(_dev->dev, "Failed to read st,dac-channel\n");
> + return ret;
> + }
> +
> + for (i = 0; i < ARRAY_SIZE(stm32_dac_channels); i++) {
> + if (stm32_dac_channels[i].channel == channel)
> + break;
> + }
> + if (i >= ARRAY_SIZE(stm32_dac_channels)) {
> + dev_err(_dev->dev, "Invalid st,dac-channel\n");
> + return -EINVAL;
> + }
> +
> + indio_dev->channels = _dac_channels[i];
> + indio_dev->num_channels = 1;

this is unusual, a comment would be helpful
why not expose both channels?

> +
> + return 0;
> +};
> +
> +static int stm32_dac_probe(struct platform_device *pdev)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + struct iio_dev *indio_dev;
> + struct stm32_dac *dac;
> + int ret;
> +
> + if (!np)
> + return -ENODEV;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*dac));
> + if (!indio_dev)
> + return -ENOMEM;
> + platform_set_drvdata(pdev, indio_dev);
> +
> + dac = iio_priv(indio_dev);
> + dac->common = dev_get_drvdata(pdev->dev.parent);
> + indio_dev->name = dev_name(>dev);
> + indio_dev->dev.parent = >dev;
> + indio_dev->dev.of_node = pdev->dev.of_node;
> + indio_dev->info = _dac_iio_info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> +
> + ret = stm32_dac_chan_of_init(indio_dev);
> + if (ret < 0)
> + return ret;
> +
> + ret = iio_device_register(indio_dev);

just 
return iio_device_register();

candidate for devm_ due to empty _remove()

> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int stm32_dac_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> + iio_device_unregister(indio_dev);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id stm32_dac_of_match[] = {
> + { .compatible = "st,stm32-dac", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
> +
> +static struct platform_driver stm32_dac_driver = {
> + .probe = stm32_dac_probe,
> + .remove = stm32_dac_remove,
> + .driver = {
> + .name = "stm32-dac",
> + .of_match_table = stm32_dac_of_match,
> + },
> +};
> +module_platform_driver(stm32_dac_driver);
> +
> +MODULE_ALIAS("platform:stm32-dac");
> +MODULE_AUTHOR("Amelie Delaunay <amelie.delau...@st.com>");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 DAC driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 2/4] iio: dac: add support for stm32 DAC

2017-04-01 Thread Peter Meerwald-Stadler
gt; + ret = of_property_read_u32(np, "st,dac-channel", );
> + if (ret) {
> + dev_err(_dev->dev, "Failed to read st,dac-channel\n");
> + return ret;
> + }
> +
> + for (i = 0; i < ARRAY_SIZE(stm32_dac_channels); i++) {
> + if (stm32_dac_channels[i].channel == channel)
> + break;
> + }
> + if (i >= ARRAY_SIZE(stm32_dac_channels)) {
> + dev_err(_dev->dev, "Invalid st,dac-channel\n");
> +     return -EINVAL;
> + }
> +
> + indio_dev->channels = _dac_channels[i];
> + indio_dev->num_channels = 1;

this is unusual, a comment would be helpful
why not expose both channels?

> +
> + return 0;
> +};
> +
> +static int stm32_dac_probe(struct platform_device *pdev)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + struct iio_dev *indio_dev;
> + struct stm32_dac *dac;
> + int ret;
> +
> + if (!np)
> + return -ENODEV;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*dac));
> + if (!indio_dev)
> + return -ENOMEM;
> + platform_set_drvdata(pdev, indio_dev);
> +
> + dac = iio_priv(indio_dev);
> + dac->common = dev_get_drvdata(pdev->dev.parent);
> + indio_dev->name = dev_name(>dev);
> + indio_dev->dev.parent = >dev;
> + indio_dev->dev.of_node = pdev->dev.of_node;
> + indio_dev->info = _dac_iio_info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> +
> + ret = stm32_dac_chan_of_init(indio_dev);
> + if (ret < 0)
> + return ret;
> +
> + ret = iio_device_register(indio_dev);

just 
return iio_device_register();

candidate for devm_ due to empty _remove()

> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int stm32_dac_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> + iio_device_unregister(indio_dev);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id stm32_dac_of_match[] = {
> + { .compatible = "st,stm32-dac", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
> +
> +static struct platform_driver stm32_dac_driver = {
> + .probe = stm32_dac_probe,
> + .remove = stm32_dac_remove,
> + .driver = {
> + .name = "stm32-dac",
> + .of_match_table = stm32_dac_of_match,
> + },
> +};
> +module_platform_driver(stm32_dac_driver);
> +
> +MODULE_ALIAS("platform:stm32-dac");
> +MODULE_AUTHOR("Amelie Delaunay ");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 DAC driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: adc: replace comma with a semicolon

2017-03-30 Thread Peter Meerwald-Stadler

> On Thu, Mar 30, 2017 at 06:16:03PM +0530, Arushi Singhal wrote:
> > Replace a comma between expression statements by a semicolon. This
> > changes the semantics of the code, but given the current indentation
> > appears to be what is intended.

> You can simply say that this fixes what appears to be a bug to me.
> I wonder how this does even compile..

it's valid C and I think it does the correct thing (i.e. assign those 
variables); the style is weird obviously

> [1] https://marc.info/?l=linux-iio=148475728729617=2
> 
> > Signed-off-by: Arushi Singhal <arushisinghal19971...@gmail.com>
> > ---
> >  drivers/iio/adc/max11100.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/iio/adc/max11100.c b/drivers/iio/adc/max11100.c
> > index 23c060e1b663..1180bcc22ff1 100644
> > --- a/drivers/iio/adc/max11100.c
> > +++ b/drivers/iio/adc/max11100.c
> > @@ -124,8 +124,8 @@ static int max11100_probe(struct spi_device *spi)
> > indio_dev->name = "max11100";
> > indio_dev->info = _info;
> > indio_dev->modes = INDIO_DIRECT_MODE;
> > -   indio_dev->channels = max11100_channels,
> > -   indio_dev->num_channels = ARRAY_SIZE(max11100_channels),
> > +   indio_dev->channels = max11100_channels;
> > +   indio_dev->num_channels = ARRAY_SIZE(max11100_channels);
> >  
> > state->vref_reg = devm_regulator_get(>dev, "vref");
> > if (IS_ERR(state->vref_reg))
> > -- 
> > 2.11.0
> > 
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio: adc: replace comma with a semicolon

2017-03-30 Thread Peter Meerwald-Stadler

> On Thu, Mar 30, 2017 at 06:16:03PM +0530, Arushi Singhal wrote:
> > Replace a comma between expression statements by a semicolon. This
> > changes the semantics of the code, but given the current indentation
> > appears to be what is intended.

> You can simply say that this fixes what appears to be a bug to me.
> I wonder how this does even compile..

it's valid C and I think it does the correct thing (i.e. assign those 
variables); the style is weird obviously

> [1] https://marc.info/?l=linux-iio=148475728729617=2
> 
> > Signed-off-by: Arushi Singhal 
> > ---
> >  drivers/iio/adc/max11100.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/iio/adc/max11100.c b/drivers/iio/adc/max11100.c
> > index 23c060e1b663..1180bcc22ff1 100644
> > --- a/drivers/iio/adc/max11100.c
> > +++ b/drivers/iio/adc/max11100.c
> > @@ -124,8 +124,8 @@ static int max11100_probe(struct spi_device *spi)
> > indio_dev->name = "max11100";
> > indio_dev->info = _info;
> > indio_dev->modes = INDIO_DIRECT_MODE;
> > -   indio_dev->channels = max11100_channels,
> > -   indio_dev->num_channels = ARRAY_SIZE(max11100_channels),
> > +   indio_dev->channels = max11100_channels;
> > +   indio_dev->num_channels = ARRAY_SIZE(max11100_channels);
> >  
> > state->vref_reg = devm_regulator_get(>dev, "vref");
> > if (IS_ERR(state->vref_reg))
> > -- 
> > 2.11.0
> > 
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio/adc/ltc2497: Driver for Linear Technology LTC2497 ADC

2017-03-23 Thread Peter Meerwald-Stadler
ruct iio_info ltc2497_info = {
> + .read_raw = ltc2497_read_raw,
> + .driver_module = THIS_MODULE,
> +};
> +
> +static int ltc2497_probe(struct i2c_client *client,
> +  const struct i2c_device_id *id)
> +{
> + struct iio_dev *indio_dev;
> + struct ltc2497_st *st;
> + int ret;
> +
> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
> +  I2C_FUNC_SMBUS_WRITE_BYTE))
> + return -EOPNOTSUPP;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*st));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + st = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + st->client = client;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = id->name;
> + indio_dev->info = _info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = ltc2497_channel;
> + indio_dev->num_channels = ARRAY_SIZE(ltc2497_channel);
> +
> + st->ref = devm_regulator_get(>dev, "vref");
> + if (IS_ERR(st->ref))
> + return PTR_ERR(st->ref);
> +
> + ret = regulator_enable(st->ref);
> + if (ret < 0)
> + return ret;
> +
> + ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT);
> + if (ret < 0)
> + goto err_regulator_disable;
> +
> + st->addr_prev = LTC2497_CONFIG_DEFAULT;
> + st->time_prev = ktime_get();
> +
> + ret = devm_iio_device_register(>dev, indio_dev);

no devm_ since we have a non-empty _remove()?

> + if (ret < 0)
> + goto err_regulator_disable;
> +
> + return 0;
> +
> +err_regulator_disable:
> + regulator_disable(st->ref);
> +
> + return ret;
> +}
> +
> +static int ltc2497_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct ltc2497_st *st = iio_priv(indio_dev);
> +
> + regulator_disable(st->ref);
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id ltc2497_id[] = {
> + { "ltc2497", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, ltc2497_id);
> +
> +static const struct of_device_id ltc2497_of_match[] = {
> + { .compatible = "lltc,ltc2497", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, ltc2497_of_match);
> +
> +static struct i2c_driver ltc2497_driver = {
> + .driver = {
> + .name = "ltc2497",
> + .of_match_table = of_match_ptr(ltc2497_of_match),
> + },
> + .probe = ltc2497_probe,
> + .remove = ltc2497_remove,
> + .id_table = ltc2497_id,
> +};
> +module_i2c_driver(ltc2497_driver);
> +
> +MODULE_AUTHOR("Michael Hennerich <michael.henner...@analog.com>");
> +MODULE_DESCRIPTION("Linear Technology LTC2497 ADC driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH] iio/adc/ltc2497: Driver for Linear Technology LTC2497 ADC

2017-03-23 Thread Peter Meerwald-Stadler
+ .driver_module = THIS_MODULE,
> +};
> +
> +static int ltc2497_probe(struct i2c_client *client,
> +  const struct i2c_device_id *id)
> +{
> + struct iio_dev *indio_dev;
> + struct ltc2497_st *st;
> + int ret;
> +
> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
> +  I2C_FUNC_SMBUS_WRITE_BYTE))
> + return -EOPNOTSUPP;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*st));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + st = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + st->client = client;
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = id->name;
> + indio_dev->info = _info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = ltc2497_channel;
> + indio_dev->num_channels = ARRAY_SIZE(ltc2497_channel);
> +
> + st->ref = devm_regulator_get(>dev, "vref");
> + if (IS_ERR(st->ref))
> + return PTR_ERR(st->ref);
> +
> + ret = regulator_enable(st->ref);
> + if (ret < 0)
> + return ret;
> +
> + ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT);
> + if (ret < 0)
> + goto err_regulator_disable;
> +
> + st->addr_prev = LTC2497_CONFIG_DEFAULT;
> + st->time_prev = ktime_get();
> +
> + ret = devm_iio_device_register(>dev, indio_dev);

no devm_ since we have a non-empty _remove()?

> + if (ret < 0)
> + goto err_regulator_disable;
> +
> + return 0;
> +
> +err_regulator_disable:
> + regulator_disable(st->ref);
> +
> + return ret;
> +}
> +
> +static int ltc2497_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct ltc2497_st *st = iio_priv(indio_dev);
> +
> + regulator_disable(st->ref);
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id ltc2497_id[] = {
> + { "ltc2497", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, ltc2497_id);
> +
> +static const struct of_device_id ltc2497_of_match[] = {
> + { .compatible = "lltc,ltc2497", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, ltc2497_of_match);
> +
> +static struct i2c_driver ltc2497_driver = {
> + .driver = {
> + .name = "ltc2497",
> + .of_match_table = of_match_ptr(ltc2497_of_match),
> + },
> + .probe = ltc2497_probe,
> + .remove = ltc2497_remove,
> + .id_table = ltc2497_id,
> +};
> +module_i2c_driver(ltc2497_driver);
> +
> +MODULE_AUTHOR("Michael Hennerich ");
> +MODULE_DESCRIPTION("Linear Technology LTC2497 ADC driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 2/2] iio: Aspeed AST2400/AST2500 ADC

2017-03-21 Thread Peter Meerwald-Stadler
t;, "prescaler",
> + CLK_SET_RATE_PARENT,
> + data->base + ASPEED_ADC_REG_CLOCK_CONTROL,
> + 0, 10, 0, >clk_lock);
> + if (IS_ERR(data->clk_scaler)) {
> + dev_err(>dev, "Failed allocating scaler clock\n");
> + ret = PTR_ERR(data->clk_scaler);
> + goto scaler_error;
> + }
> +
> + /* Start all channels in normal mode. */
> + clk_prepare_enable(data->clk_scaler->clk);
> + adc_engine_control_reg_val = GENMASK(31, 16) |
> + ASPEED_ADC_OPERATION_MODE_NORMAL | ASPEED_ADC_ENGINE_ENABLE;
> + writel(adc_engine_control_reg_val,
> + data->base + ASPEED_ADC_REG_ENGINE_CONTROL);
> +
> + indio_dev->name = dev_name(>dev);
> + indio_dev->dev.parent = >dev;
> + indio_dev->info = _adc_iio_info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = aspeed_adc_iio_channels;
> + indio_dev->num_channels = ARRAY_SIZE(aspeed_adc_iio_channels);
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(>dev, "Could't register the device.\n");

Couldn't

> + goto iio_register_error;
> + }
> +
> + return 0;
> +
> +iio_register_error:
> + writel(0x0, data->base + ASPEED_ADC_REG_ENGINE_CONTROL);
> + clk_disable_unprepare(data->clk_scaler->clk);
> + clk_hw_unregister_divider(data->clk_scaler);
> +
> +scaler_error:
> + clk_hw_unregister_divider(data->clk_prescaler);
> +
> +prescaler_error:
> +resource_error:
> + return ret;
> +}
> +
> +static int aspeed_adc_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct aspeed_adc_data *data = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);

writel(0x0, data->base + ASPEED_ADC_REG_ENGINE_CONTROL);
I guess this power off the device?

the MODE #defines are now used (powerdown, normal, etc.)

> + clk_disable_unprepare(data->clk_scaler->clk);
> + clk_hw_unregister_divider(data->clk_scaler);
> + clk_hw_unregister_divider(data->clk_prescaler);
> +
> + return 0;
> +}
> +
> +const struct of_device_id aspeed_adc_matches[] = {
> + { .compatible = "aspeed,ast2400-adc" },
> + { .compatible = "aspeed,ast2500-adc" },
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_adc_matches);
> +
> +static struct platform_driver aspeed_adc_driver = {
> + .probe = aspeed_adc_probe,
> + .remove = aspeed_adc_remove,
> + .driver = {
> + .name = KBUILD_MODNAME,
> + .of_match_table = aspeed_adc_matches,
> + }
> +};
> +
> +module_platform_driver(aspeed_adc_driver);
> +
> +MODULE_AUTHOR("Rick Altherr <ralth...@google.com>");
> +MODULE_DESCRIPTION("Aspeed AST2400/2500 ADC Driver");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH v2 2/2] iio: Aspeed AST2400/AST2500 ADC

2017-03-21 Thread Peter Meerwald-Stadler
   CLK_SET_RATE_PARENT,
> + data->base + ASPEED_ADC_REG_CLOCK_CONTROL,
> + 0, 10, 0, >clk_lock);
> + if (IS_ERR(data->clk_scaler)) {
> + dev_err(>dev, "Failed allocating scaler clock\n");
> + ret = PTR_ERR(data->clk_scaler);
> + goto scaler_error;
> + }
> +
> + /* Start all channels in normal mode. */
> + clk_prepare_enable(data->clk_scaler->clk);
> + adc_engine_control_reg_val = GENMASK(31, 16) |
> + ASPEED_ADC_OPERATION_MODE_NORMAL | ASPEED_ADC_ENGINE_ENABLE;
> + writel(adc_engine_control_reg_val,
> + data->base + ASPEED_ADC_REG_ENGINE_CONTROL);
> +
> + indio_dev->name = dev_name(>dev);
> + indio_dev->dev.parent = >dev;
> + indio_dev->info = _adc_iio_info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = aspeed_adc_iio_channels;
> + indio_dev->num_channels = ARRAY_SIZE(aspeed_adc_iio_channels);
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(>dev, "Could't register the device.\n");

Couldn't

> + goto iio_register_error;
> + }
> +
> + return 0;
> +
> +iio_register_error:
> + writel(0x0, data->base + ASPEED_ADC_REG_ENGINE_CONTROL);
> + clk_disable_unprepare(data->clk_scaler->clk);
> + clk_hw_unregister_divider(data->clk_scaler);
> +
> +scaler_error:
> + clk_hw_unregister_divider(data->clk_prescaler);
> +
> +prescaler_error:
> +resource_error:
> + return ret;
> +}
> +
> +static int aspeed_adc_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct aspeed_adc_data *data = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);

writel(0x0, data->base + ASPEED_ADC_REG_ENGINE_CONTROL);
I guess this power off the device?

the MODE #defines are now used (powerdown, normal, etc.)

> + clk_disable_unprepare(data->clk_scaler->clk);
> + clk_hw_unregister_divider(data->clk_scaler);
> + clk_hw_unregister_divider(data->clk_prescaler);
> +
> + return 0;
> +}
> +
> +const struct of_device_id aspeed_adc_matches[] = {
> + { .compatible = "aspeed,ast2400-adc" },
> + { .compatible = "aspeed,ast2500-adc" },
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_adc_matches);
> +
> +static struct platform_driver aspeed_adc_driver = {
> + .probe = aspeed_adc_probe,
> + .remove = aspeed_adc_remove,
> + .driver = {
> + .name = KBUILD_MODNAME,
> + .of_match_table = aspeed_adc_matches,
> + }
> +};
> +
> +module_platform_driver(aspeed_adc_driver);
> +
> +MODULE_AUTHOR("Rick Altherr ");
> +MODULE_DESCRIPTION("Aspeed AST2400/2500 ADC Driver");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418


Re: [PATCH 1/3] iio: humidity: add sht21 relative humidity and temperature sensor driver

2017-02-19 Thread Peter Meerwald-Stadler
ret = sht21_set_resolution(state, i);
> + mutex_unlock(>lock);
> +
> + iio_device_release_direct_mode(indio_dev);
> +
> + return ret;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static ssize_t sht21_show_heater(struct device *dev,
> +  struct device_attribute *attr, char *buf)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct sht21_state *state = iio_priv(indio_dev);
> + int data, ret;
> +
> + ret = sht21_read_data(state, SHT21_READ_USER_REG, );
> + if (ret)
> + return ret;
> +
> + return sprintf(buf, "%d\n", !!(data & SHT21_USER_REG_ENABLE_HEATER));
> +}
> +
> +static ssize_t sht21_write_heater(struct device *dev,
> +   struct device_attribute *attr,
> +   const char *buf, size_t len)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct sht21_state *state = iio_priv(indio_dev);
> + int val, data, ret;
> +
> + ret = kstrtoint(buf, 10, );
> + if (ret)
> + return ret;
> + if (val != 0 && val != 1)
> + return -EINVAL;
> +
> + mutex_lock(>lock);
> + ret = sht21_read_data(state, SHT21_READ_USER_REG, );
> + if (ret) {
> + mutex_unlock(>lock);
> + return ret;
> + }
> +
> + if (val)
> + data |= SHT21_USER_REG_ENABLE_HEATER;
> + else
> + data &= ~SHT21_USER_REG_ENABLE_HEATER;
> +
> + ret = sht21_write_data(state, SHT21_WRITE_USER_REG, );
> + mutex_unlock(>lock);
> +
> + return ret ? ret : len;
> +}
> +
> +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("0.88 1.93 2.28 3.85");
> +static IIO_DEVICE_ATTR(heater_enable, S_IRUGO | S_IWUSR,
> +sht21_show_heater, sht21_write_heater, 0);
> +
> +static struct attribute *sht21_attributes[] = {
> + _const_attr_sampling_frequency_available.dev_attr.attr,
> + _dev_attr_heater_enable.dev_attr.attr,
> + NULL
> +};
> +
> +static const struct attribute_group sht21_attribute_group = {
> + .attrs = sht21_attributes,
> +};
> +
> +static const struct iio_info sht21_info = {
> + .driver_module = THIS_MODULE,
> + .read_raw = sht21_read_raw,
> + .write_raw = sht21_write_raw,
> + .attrs = _attribute_group,
> +};
> +
> +#define SHT21_CHANNEL(_type, _index) { \
> + .type = _type, \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
> + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> + .scan_index = _index, \
> + .scan_type = { \
> + .sign = 's', \
> + .realbits = 32, \
> + .storagebits = 32, \
> + .endianness = IIO_CPU, \
> + }, \
> +}
> +
> +static const struct iio_chan_spec sht21_channels[] = {
> + SHT21_CHANNEL(IIO_HUMIDITYRELATIVE, 0),
> + SHT21_CHANNEL(IIO_TEMP, 1),
> + IIO_CHAN_SOFT_TIMESTAMP(2),
> +};
> +
> +static int sht21_probe(struct i2c_client *client, const struct i2c_device_id 
> *id)
> +{
> + struct iio_dev *indio_dev;
> + struct sht21_state *data;
> + int ret;
> +
> + if (!i2c_check_functionality(client->adapter,
> +  I2C_FUNC_SMBUS_WRITE_BYTE |
> +  I2C_FUNC_SMBUS_BYTE_DATA |
> +  I2C_FUNC_SMBUS_READ_I2C_BLOCK))
> + return -ENODEV;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + data = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + data->client = client;
> + mutex_init(>lock);
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = id->name;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> + indio_dev->channels = sht21_channels;
> + indio_dev->num_channels = ARRAY_SIZE(sht21_channels);
> +
> + ret = sht21_soft_reset(data);
> + if (ret)
> + return ret;
> +
> + ret = iio_triggered_buffer_setup(indio_dev, NULL,
> +  sht21_trigger_handler, NULL);
> + if (ret)
> + return ret;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + iio_triggered_buffer_cleanup(indio_dev);
> +
> + return ret;
> +}
> +
> +static int sht21_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);
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id sht21_id[] = {
> + { "sht21", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, sht21_id);
> +
> +static const struct of_device_id sht21_of_match[] = {
> + { .compatible = "sensirion,sht21" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, sht21_of_match);
> +
> +static struct i2c_driver sht21_driver = {
> + .driver = {
> + .name = SHT21_DRV_NAME,
> + .of_match_table = of_match_ptr(sht21_of_match),
> + },
> + .id_table = sht21_id,
> + .probe = sht21_probe,
> + .remove = sht21_remove,
> +};
> +module_i2c_driver(sht21_driver);
> +
> +MODULE_DESCRIPTION("Sensirion SHT21 relative humidity and temperature sensor 
> driver");
> +MODULE_AUTHOR("Tomasz Duszynski <tdusz...@gmail.com>");
> +MODULE_LICENSE("GPL v2");
> --
> 2.11.1
> 

-- 

Peter Meerwald-Stadler
+43-664-218 (mobile)


Re: [PATCH 1/3] iio: humidity: add sht21 relative humidity and temperature sensor driver

2017-02-19 Thread Peter Meerwald-Stadler
ck(>lock);
> +
> + iio_device_release_direct_mode(indio_dev);
> +
> + return ret;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static ssize_t sht21_show_heater(struct device *dev,
> +  struct device_attribute *attr, char *buf)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct sht21_state *state = iio_priv(indio_dev);
> + int data, ret;
> +
> + ret = sht21_read_data(state, SHT21_READ_USER_REG, );
> + if (ret)
> + return ret;
> +
> + return sprintf(buf, "%d\n", !!(data & SHT21_USER_REG_ENABLE_HEATER));
> +}
> +
> +static ssize_t sht21_write_heater(struct device *dev,
> +   struct device_attribute *attr,
> +   const char *buf, size_t len)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct sht21_state *state = iio_priv(indio_dev);
> + int val, data, ret;
> +
> + ret = kstrtoint(buf, 10, );
> + if (ret)
> + return ret;
> + if (val != 0 && val != 1)
> + return -EINVAL;
> +
> + mutex_lock(>lock);
> + ret = sht21_read_data(state, SHT21_READ_USER_REG, );
> + if (ret) {
> + mutex_unlock(>lock);
> + return ret;
> + }
> +
> + if (val)
> + data |= SHT21_USER_REG_ENABLE_HEATER;
> + else
> + data &= ~SHT21_USER_REG_ENABLE_HEATER;
> +
> + ret = sht21_write_data(state, SHT21_WRITE_USER_REG, );
> + mutex_unlock(>lock);
> +
> + return ret ? ret : len;
> +}
> +
> +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("0.88 1.93 2.28 3.85");
> +static IIO_DEVICE_ATTR(heater_enable, S_IRUGO | S_IWUSR,
> +sht21_show_heater, sht21_write_heater, 0);
> +
> +static struct attribute *sht21_attributes[] = {
> + _const_attr_sampling_frequency_available.dev_attr.attr,
> + _dev_attr_heater_enable.dev_attr.attr,
> + NULL
> +};
> +
> +static const struct attribute_group sht21_attribute_group = {
> + .attrs = sht21_attributes,
> +};
> +
> +static const struct iio_info sht21_info = {
> + .driver_module = THIS_MODULE,
> + .read_raw = sht21_read_raw,
> + .write_raw = sht21_write_raw,
> + .attrs = _attribute_group,
> +};
> +
> +#define SHT21_CHANNEL(_type, _index) { \
> + .type = _type, \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
> + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> + .scan_index = _index, \
> + .scan_type = { \
> + .sign = 's', \
> + .realbits = 32, \
> + .storagebits = 32, \
> + .endianness = IIO_CPU, \
> + }, \
> +}
> +
> +static const struct iio_chan_spec sht21_channels[] = {
> + SHT21_CHANNEL(IIO_HUMIDITYRELATIVE, 0),
> + SHT21_CHANNEL(IIO_TEMP, 1),
> + IIO_CHAN_SOFT_TIMESTAMP(2),
> +};
> +
> +static int sht21_probe(struct i2c_client *client, const struct i2c_device_id 
> *id)
> +{
> + struct iio_dev *indio_dev;
> + struct sht21_state *data;
> + int ret;
> +
> + if (!i2c_check_functionality(client->adapter,
> +  I2C_FUNC_SMBUS_WRITE_BYTE |
> +  I2C_FUNC_SMBUS_BYTE_DATA |
> +  I2C_FUNC_SMBUS_READ_I2C_BLOCK))
> + return -ENODEV;
> +
> + indio_dev = devm_iio_device_alloc(>dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + data = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + data->client = client;
> + mutex_init(>lock);
> +
> + indio_dev->dev.parent = >dev;
> + indio_dev->name = id->name;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = _info;
> + indio_dev->channels = sht21_channels;
> + indio_dev->num_channels = ARRAY_SIZE(sht21_channels);
> +
> + ret = sht21_soft_reset(data);
> + if (ret)
> + return ret;
> +
> + ret = iio_triggered_buffer_setup(indio_dev, NULL,
> +  sht21_trigger_handler, NULL);
> + if (ret)
> + return ret;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + iio_triggered_buffer_cleanup(indio_dev);
> +
> + return ret;
> +}
> +
> +static int sht21_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);
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id sht21_id[] = {
> + { "sht21", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, sht21_id);
> +
> +static const struct of_device_id sht21_of_match[] = {
> + { .compatible = "sensirion,sht21" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, sht21_of_match);
> +
> +static struct i2c_driver sht21_driver = {
> + .driver = {
> + .name = SHT21_DRV_NAME,
> + .of_match_table = of_match_ptr(sht21_of_match),
> + },
> + .id_table = sht21_id,
> + .probe = sht21_probe,
> + .remove = sht21_remove,
> +};
> +module_i2c_driver(sht21_driver);
> +
> +MODULE_DESCRIPTION("Sensirion SHT21 relative humidity and temperature sensor 
> driver");
> +MODULE_AUTHOR("Tomasz Duszynski ");
> +MODULE_LICENSE("GPL v2");
> --
> 2.11.1
> 

-- 

Peter Meerwald-Stadler
+43-664-218 (mobile)


Re: [PATCH 1/4] iio: chemical: add particle number concentration channel type

2017-02-05 Thread Peter Meerwald-Stadler

> This patch adds channel type for expressing particle number
> concentration.

numberconcentration sound a bit strange to be, more like a number 
theoretic concept

how about particlecontentration? or numberparticles?
 
> Signed-off-by: Tomasz Duszynski <tdusz...@gmail.com>
> ---
>  Documentation/ABI/testing/sysfs-bus-iio | 7 +++
>  drivers/iio/industrialio-core.c | 1 +
>  include/uapi/linux/iio/types.h  | 1 +
>  3 files changed, 9 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
> b/Documentation/ABI/testing/sysfs-bus-iio
> index 530809ccfacf..481771e585ee 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio
> +++ b/Documentation/ABI/testing/sysfs-bus-iio
> @@ -1608,3 +1608,10 @@ Description:
>   provides an absolute positional reference (e.g. a pulse once per
>   revolution) which may be used to home positional systems as
>   required.
> +
> +What:
> /sys/bus/iio/devices/iio:deviceX/in_numberconcentration_input
> +KernelVersion:   4.12
> +Contact: linux-...@vger.kernel.org
> +Description:
> + Reading of particulates number in a volume of a mixture.
> + Unit is in 1/m3.
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index d18ded45bedd..451e3bb8d623 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -85,6 +85,7 @@ static const char * const iio_chan_type_name_spec[] = {
>   [IIO_COUNT] = "count",
>   [IIO_INDEX] = "index",
>   [IIO_GRAVITY]  = "gravity",
> + [IIO_NUMBERCONCENTRATION] = "numberconcentration",
>  };
>  
>  static const char * const iio_modifier_names[] = {
> diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
> index ffafd6c25a48..52696e251c4d 100644
> --- a/include/uapi/linux/iio/types.h
> +++ b/include/uapi/linux/iio/types.h
> @@ -43,6 +43,7 @@ enum iio_chan_type {
>   IIO_COUNT,
>   IIO_INDEX,
>   IIO_GRAVITY,
> + IIO_NUMBERCONCENTRATION,
>  };
>  
>  enum iio_modifier {
> 

-- 

Peter Meerwald-Stadler
+43-664-218 (mobile)


Re: [PATCH 1/4] iio: chemical: add particle number concentration channel type

2017-02-05 Thread Peter Meerwald-Stadler

> This patch adds channel type for expressing particle number
> concentration.

numberconcentration sound a bit strange to be, more like a number 
theoretic concept

how about particlecontentration? or numberparticles?
 
> Signed-off-by: Tomasz Duszynski 
> ---
>  Documentation/ABI/testing/sysfs-bus-iio | 7 +++
>  drivers/iio/industrialio-core.c | 1 +
>  include/uapi/linux/iio/types.h  | 1 +
>  3 files changed, 9 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
> b/Documentation/ABI/testing/sysfs-bus-iio
> index 530809ccfacf..481771e585ee 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio
> +++ b/Documentation/ABI/testing/sysfs-bus-iio
> @@ -1608,3 +1608,10 @@ Description:
>   provides an absolute positional reference (e.g. a pulse once per
>   revolution) which may be used to home positional systems as
>   required.
> +
> +What:
> /sys/bus/iio/devices/iio:deviceX/in_numberconcentration_input
> +KernelVersion:   4.12
> +Contact: linux-...@vger.kernel.org
> +Description:
> + Reading of particulates number in a volume of a mixture.
> + Unit is in 1/m3.
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index d18ded45bedd..451e3bb8d623 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -85,6 +85,7 @@ static const char * const iio_chan_type_name_spec[] = {
>   [IIO_COUNT] = "count",
>   [IIO_INDEX] = "index",
>   [IIO_GRAVITY]  = "gravity",
> + [IIO_NUMBERCONCENTRATION] = "numberconcentration",
>  };
>  
>  static const char * const iio_modifier_names[] = {
> diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
> index ffafd6c25a48..52696e251c4d 100644
> --- a/include/uapi/linux/iio/types.h
> +++ b/include/uapi/linux/iio/types.h
> @@ -43,6 +43,7 @@ enum iio_chan_type {
>   IIO_COUNT,
>   IIO_INDEX,
>   IIO_GRAVITY,
> + IIO_NUMBERCONCENTRATION,
>  };
>  
>  enum iio_modifier {
> 

-- 

Peter Meerwald-Stadler
+43-664-218 (mobile)


  1   2   3   4   5   >