Re: [PATCH 2/2] iio: chemical: atlas-ph-sensor: add EC feature

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 4, 2016 at 3:39 AM, Jonathan Cameron <jic23@xxxxxxxxxx> wrote:
> On 24/04/16 21:43, Matt Ranostay wrote:
> Give us a bit more description - what is it, what is it for, what interface is
> supplied. Err what does EC standard for?
>> Signed-off-by: Matt Ranostay <mranostay@xxxxxxxxx>
> I know next to nothing about these sensors and don't have the datasheet to hand.
>
> This is measuring 3 different types of concentration (I think) and reporting them
> simple as channels 0-2.  What are they are should we not be distinguishing between
> them in some more informative fashion?

Should I add some .extend_name for each channel?
Horribly I have to admit my pH sensor based board doesn't give valid
values for this sensor till I resign the ground plane under the IC :/.
But I can confirm it does report some "values"...

>
> Code itself is mostly fine...
>
> Jonathan
>> ---
>>  .../bindings/iio/chemical/atlas,ec-sm.txt          |  22 ++++
>>  drivers/iio/chemical/Kconfig                       |   8 +-
>>  drivers/iio/chemical/atlas-ph-sensor.c             | 113 ++++++++++++++++++++-
>>  3 files changed, 138 insertions(+), 5 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/iio/chemical/atlas,ec-sm.txt
>>
>> diff --git a/Documentation/devicetree/bindings/iio/chemical/atlas,ec-sm.txt b/Documentation/devicetree/bindings/iio/chemical/atlas,ec-sm.txt
>> new file mode 100644
>> index 0000000..2962bd9
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/iio/chemical/atlas,ec-sm.txt
>> @@ -0,0 +1,22 @@
>> +* Atlas Scientific EC-SM OEM sensor
>> +
>> +http://www.atlas-scientific.com/_files/_datasheets/_oem/EC_oem_datasheet.pdf
>> +
>> +Required properties:
>> +
>> +  - compatible: must be "atlas,ec-sm"
>> +  - reg: the I2C address of the sensor
>> +  - interrupt-parent: should be the phandle for the interrupt controller
>> +  - interrupts: the sole interrupt generated by the device
>> +
>> +  Refer to interrupt-controller/interrupts.txt for generic interrupt client
>> +  node bindings.
>> +
>> +Example:
>> +
>> +atlas@64 {
>> +     compatible = "atlas,ec-sm";
>> +     reg = <0x64>;
>> +     interrupt-parent = <&gpio1>;
>> +     interrupts = <16 2>;
>> +};
>> diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
>> index f73290f..4bcc025 100644
>> --- a/drivers/iio/chemical/Kconfig
>> +++ b/drivers/iio/chemical/Kconfig
>> @@ -5,15 +5,17 @@
>>  menu "Chemical Sensors"
>>
>>  config ATLAS_PH_SENSOR
>> -     tristate "Atlas Scientific OEM pH-SM sensor"
>> +     tristate "Atlas Scientific OEM SM sensors"
>>       depends on I2C
>>       select REGMAP_I2C
>>       select IIO_BUFFER
>>       select IIO_TRIGGERED_BUFFER
>>       select IRQ_WORK
>>       help
>> -      Say Y here to build I2C interface support for the Atlas
>> -      Scientific OEM pH-SM sensor.
>> +      Say Y here to build I2C interface support for the following
>> +      Atlas Scientific OEM SM sensors:
>> +         * pH SM sensor
>> +         * EC SM sensor
>>
>>        To compile this driver as module, choose M here: the
>>        module will be called atlas-ph-sensor.
>> diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c
>> index c57f9c2..6dddd75 100644
>> --- a/drivers/iio/chemical/atlas-ph-sensor.c
>> +++ b/drivers/iio/chemical/atlas-ph-sensor.c
>> @@ -50,13 +50,28 @@
>>  #define ATLAS_REG_PH_CALIB_STATUS_MID        BIT(1)
>>  #define ATLAS_REG_PH_CALIB_STATUS_HIGH       BIT(2)
>>
>> +#define ATLAS_REG_EC_CALIB_STATUS            0x0f
>> +#define ATLAS_REG_EC_CALIB_STATUS_MASK               0x0f
>> +#define ATLAS_REG_EC_CALIB_STATUS_DRY                BIT(0)
>> +#define ATLAS_REG_EC_CALIB_STATUS_SINGLE     BIT(1)
>> +#define ATLAS_REG_EC_CALIB_STATUS_LOW                BIT(2)
>> +#define ATLAS_REG_EC_CALIB_STATUS_HIGH               BIT(3)
>> +
>>  #define ATLAS_REG_PH_TEMP_DATA               0x0e
>>  #define ATLAS_REG_PH_DATA            0x16
>>
>> +#define ATLAS_REG_EC_PROBE           0x08
>> +#define ATLAS_REG_EC_TEMP_DATA               0x10
>> +#define ATLAS_REG_EC_DATA            0x18
>> +#define ATLAS_REG_TDS_DATA           0x1c
>> +#define ATLAS_REG_PSS_DATA           0x20
>> +
>>  #define ATLAS_PH_INT_TIME_IN_US              450000
>> +#define ATLAS_EC_INT_TIME_IN_US              650000
>>
>>  enum {
>>       ATLAS_PH_SM,
>> +     ATLAS_EC_SM,
>>  };
>>
>>  struct atlas_data {
>> @@ -66,12 +81,13 @@ struct atlas_data {
>>       struct regmap *regmap;
>>       struct irq_work work;
>>
>> -     __be32 buffer[4]; /* 32-bit pH data + 32-bit pad + 64-bit timestamp */
>> +     __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */
>>  };
>>
>>  static const struct regmap_range atlas_volatile_ranges[] = {
>>       regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL),
>>       regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4),
>> +     regmap_reg_range(ATLAS_REG_EC_DATA, ATLAS_REG_PSS_DATA + 4),
>>  };
>>
>>  static const struct regmap_access_table atlas_volatile_table = {
>> @@ -86,7 +102,7 @@ static const struct regmap_config atlas_regmap_config = {
>>       .val_bits = 8,
>>
>>       .volatile_table = &atlas_volatile_table,
>> -     .max_register = ATLAS_REG_PH_DATA + 4,
>> +     .max_register = ATLAS_REG_PSS_DATA + 4,
>>       .cache_type = REGCACHE_RBTREE,
>>  };
>>
>> @@ -115,6 +131,38 @@ static const struct iio_chan_spec atlas_ph_channels[] = {
>>       },
>>  };
>>
>> +#define ATLAS_EC_CHANNEL(idx, addr) \
>> +     {\
>> +             .type = IIO_CONCENTRATION, \
>> +             .indexed = 1, \
>> +             .channel = idx, \
>> +             .address = addr, \
>> +             .info_mask_separate = \
>> +                     BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \
>> +             .scan_index = idx, \
>> +             .scan_type = { \
>> +                     .sign = 'u', \
>> +                     .realbits = 32, \
>> +                     .storagebits = 32, \
>> +                     .endianness = IIO_BE, \
>> +             }, \
>> +     }
>> +
>> +static const struct iio_chan_spec atlas_ec_channels[] = {
>> +     ATLAS_EC_CHANNEL(0, ATLAS_REG_EC_DATA),
>> +     ATLAS_EC_CHANNEL(1, ATLAS_REG_TDS_DATA),
>> +     ATLAS_EC_CHANNEL(2, ATLAS_REG_PSS_DATA),
> This needs some explanation.  3 concentration channels of different types?
> What are they...
>> +     IIO_CHAN_SOFT_TIMESTAMP(3),
>> +     {
>> +             .type = IIO_TEMP,
>> +             .address = ATLAS_REG_EC_TEMP_DATA,
>> +             .info_mask_separate =
>> +                     BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
>> +             .output = 1,
>> +             .scan_index = -1
>> +     },
>> +};
>> +
>>  static int atlas_check_ph_calibration(struct atlas_data *data)
>>  {
>>       struct device *dev = &data->client->dev;
>> @@ -142,6 +190,44 @@ static int atlas_check_ph_calibration(struct atlas_data *data)
>>       return 0;
>>  }
>>
>> +static int atlas_check_ec_calibration(struct atlas_data *data)
>> +{
>> +     struct device *dev = &data->client->dev;
>> +     int ret;
>> +     unsigned int val;
>> +
>> +     ret = regmap_bulk_read(data->regmap, ATLAS_REG_EC_PROBE, &val, 2);
>> +     if (ret)
>> +             return ret;
>> +
>> +     dev_info(dev, "probe set to K = %d.%.2d", be16_to_cpu(val) / 100,
>> +                                              be16_to_cpu(val) % 100);
>> +
>> +     ret = regmap_read(data->regmap, ATLAS_REG_EC_CALIB_STATUS, &val);
>> +     if (ret)
>> +             return ret;
>> +
>> +     if (!(val & ATLAS_REG_EC_CALIB_STATUS_MASK)) {
>> +             dev_warn(dev, "device has not been calibrated\n");
>> +             return 0;
>> +     }
>> +
>> +     if (!(val & ATLAS_REG_EC_CALIB_STATUS_DRY))
>> +             dev_warn(dev, "device missing dry point calibration\n");
>> +
>> +     if (val & ATLAS_REG_EC_CALIB_STATUS_SINGLE) {
>> +             dev_warn(dev, "device using single point calibration\n");
>> +     } else {
>> +             if (!(val & ATLAS_REG_EC_CALIB_STATUS_LOW))
>> +                     dev_warn(dev, "device missing low point calibration\n");
>> +
>> +             if (!(val & ATLAS_REG_EC_CALIB_STATUS_HIGH))
>> +                     dev_warn(dev, "device missing high point calibration\n");
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>>  struct atlas_device {
>>       const struct iio_chan_spec *channels;
>>       int num_channels;
>> @@ -159,6 +245,14 @@ static struct atlas_device atlas_devices[] = {
>>                               .calibration = &atlas_check_ph_calibration,
>>                               .delay = ATLAS_PH_INT_TIME_IN_US,
>>       },
>> +     [ATLAS_EC_SM] = {
>> +                             .channels = atlas_ec_channels,
>> +                             .num_channels = 5,
> Use array_size - obviously correct that way so I don't have to go count...
>> +                             .data_reg = ATLAS_REG_EC_DATA,
>> +                             .calibration = &atlas_check_ec_calibration,
>> +                             .delay = ATLAS_EC_INT_TIME_IN_US,
>> +     },
>> +
>>  };
>>
>>  static int atlas_set_powermode(struct atlas_data *data, int on)
>> @@ -294,6 +388,7 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
>>                                             (u8 *) &reg, sizeof(reg));
> I guess it's not complex enough to justify splitting read_raw for the two
> devices.  Close though so you may want to if you support a third type in here.
>
>>                       break;
>>               case IIO_PH:
>> +             case IIO_CONCENTRATION:
>>                       mutex_lock(&indio_dev->mlock);
>>
>>                       if (iio_buffer_enabled(indio_dev))
>> @@ -324,6 +419,18 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
>>                       *val = 1; /* 0.001 */
>>                       *val2 = 1000;
>>                       break;
>> +             case IIO_CONCENTRATION:
>> +                     switch (chan->address) {
>> +                     case ATLAS_REG_EC_DATA:
>> +                             *val = 0; /* 0.00000000064 */
>> +                             *val2 = 640;
>> +                             return IIO_VAL_INT_PLUS_NANO;
>> +                     default:
>> +                             *val = 0; /* 0.000000001 */
>> +                             *val2 = 1000;
>> +                             return IIO_VAL_INT_PLUS_NANO;
>> +                     }
>> +                     break;
>>               default:
>>                       return -EINVAL;
>>               }
>> @@ -517,12 +624,14 @@ static const struct dev_pm_ops atlas_pm_ops = {
>>
>>  static const struct i2c_device_id atlas_id[] = {
>>       { "atlas-ph-sm", ATLAS_PH_SM},
>> +     { "atlas-ec-sm", ATLAS_EC_SM},
>>       {}
>>  };
>>  MODULE_DEVICE_TABLE(i2c, atlas_id);
>>
>>  static const struct of_device_id atlas_dt_ids[] = {
>>       { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
>> +     { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
>>       { }
>>  };
>>  MODULE_DEVICE_TABLE(of, atlas_dt_ids);
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux