* [PATCH v3 0/3] atlas-ph-sensor: add conductivity sensor support
@ 2016-05-25 4:29 Matt Ranostay
2016-05-25 4:29 ` [PATCH v3 1/3] iio: chemical: atlas-ph-sensor: reorg driver to allow multiple chips Matt Ranostay
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Matt Ranostay @ 2016-05-25 4:29 UTC (permalink / raw)
To: linux-iio; +Cc: jic23, Matt Ranostay
Changes from v1:
* Add IIO_ELECTRICALCONDUCTIVITY type rather than do doing weird conversion to ppm
* move device tree mapping table above probe for of_match_device
Changes from v2:
* IIO_ELECTRICALCONDUCTIVITY defined as siemens per meter
* Add IIO_CHAN_INFO_SCALE for IIO_ELECTRICALCONDUCTIVITY channel
Matt Ranostay (3):
iio: chemical: atlas-ph-sensor: reorg driver to allow multiple chips
iio: electricalconductivity: add IIO_ELECTRICALCONDUCTIVITY type
iio: chemical: atlas-ph-sensor: add EC feature
Documentation/ABI/testing/sysfs-bus-iio | 7 +
.../bindings/iio/chemical/atlas,ec-sm.txt | 22 ++
drivers/iio/chemical/Kconfig | 8 +-
drivers/iio/chemical/atlas-ph-sensor.c | 267 ++++++++++++++++-----
drivers/iio/industrialio-core.c | 1 +
include/uapi/linux/iio/types.h | 1 +
6 files changed, 246 insertions(+), 60 deletions(-)
create mode 100644 Documentation/devicetree/bindings/iio/chemical/atlas,ec-sm.txt
--
2.7.4
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 1/3] iio: chemical: atlas-ph-sensor: reorg driver to allow multiple chips
2016-05-25 4:29 [PATCH v3 0/3] atlas-ph-sensor: add conductivity sensor support Matt Ranostay
@ 2016-05-25 4:29 ` Matt Ranostay
2016-05-29 19:03 ` Jonathan Cameron
2016-05-25 4:29 ` [PATCH v3 2/3] iio: electricalconductivity: add IIO_ELECTRICALCONDUCTIVITY type Matt Ranostay
2016-05-25 4:29 ` [PATCH v3 3/3] iio: chemical: atlas-ph-sensor: add EC feature Matt Ranostay
2 siblings, 1 reply; 7+ messages in thread
From: Matt Ranostay @ 2016-05-25 4:29 UTC (permalink / raw)
To: linux-iio; +Cc: jic23, Matt Ranostay
Signed-off-by: Matt Ranostay <mranostay@gmail.com>
---
drivers/iio/chemical/atlas-ph-sensor.c | 145 ++++++++++++++++++++-------------
1 file changed, 90 insertions(+), 55 deletions(-)
diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c
index 62b37cd..e85477c 100644
--- a/drivers/iio/chemical/atlas-ph-sensor.c
+++ b/drivers/iio/chemical/atlas-ph-sensor.c
@@ -24,6 +24,7 @@
#include <linux/irq_work.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
+#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
@@ -43,20 +44,25 @@
#define ATLAS_REG_PWR_CONTROL 0x06
-#define ATLAS_REG_CALIB_STATUS 0x0d
-#define ATLAS_REG_CALIB_STATUS_MASK 0x07
-#define ATLAS_REG_CALIB_STATUS_LOW BIT(0)
-#define ATLAS_REG_CALIB_STATUS_MID BIT(1)
-#define ATLAS_REG_CALIB_STATUS_HIGH BIT(2)
+#define ATLAS_REG_PH_CALIB_STATUS 0x0d
+#define ATLAS_REG_PH_CALIB_STATUS_MASK 0x07
+#define ATLAS_REG_PH_CALIB_STATUS_LOW BIT(0)
+#define ATLAS_REG_PH_CALIB_STATUS_MID BIT(1)
+#define ATLAS_REG_PH_CALIB_STATUS_HIGH BIT(2)
-#define ATLAS_REG_TEMP_DATA 0x0e
+#define ATLAS_REG_PH_TEMP_DATA 0x0e
#define ATLAS_REG_PH_DATA 0x16
#define ATLAS_PH_INT_TIME_IN_US 450000
+enum {
+ ATLAS_PH_SM,
+};
+
struct atlas_data {
struct i2c_client *client;
struct iio_trigger *trig;
+ struct atlas_device *chip;
struct regmap *regmap;
struct irq_work work;
@@ -84,9 +90,10 @@ static const struct regmap_config atlas_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static const struct iio_chan_spec atlas_channels[] = {
+static const struct iio_chan_spec atlas_ph_channels[] = {
{
.type = IIO_PH,
+ .address = ATLAS_REG_PH_DATA,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 0,
@@ -100,7 +107,7 @@ static const struct iio_chan_spec atlas_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(1),
{
.type = IIO_TEMP,
- .address = ATLAS_REG_TEMP_DATA,
+ .address = ATLAS_REG_PH_TEMP_DATA,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.output = 1,
@@ -108,6 +115,52 @@ static const struct iio_chan_spec atlas_channels[] = {
},
};
+static int atlas_check_ph_calibration(struct atlas_data *data)
+{
+ struct device *dev = &data->client->dev;
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(data->regmap, ATLAS_REG_PH_CALIB_STATUS, &val);
+ if (ret)
+ return ret;
+
+ if (!(val & ATLAS_REG_PH_CALIB_STATUS_MASK)) {
+ dev_warn(dev, "device has not been calibrated\n");
+ return 0;
+ }
+
+ if (!(val & ATLAS_REG_PH_CALIB_STATUS_LOW))
+ dev_warn(dev, "device missing low point calibration\n");
+
+ if (!(val & ATLAS_REG_PH_CALIB_STATUS_MID))
+ dev_warn(dev, "device missing mid point calibration\n");
+
+ if (!(val & ATLAS_REG_PH_CALIB_STATUS_HIGH))
+ dev_warn(dev, "device missing high point calibration\n");
+
+ return 0;
+}
+
+struct atlas_device {
+ const struct iio_chan_spec *channels;
+ int num_channels;
+ int data_reg;
+
+ int (*calibration)(struct atlas_data *data);
+ int delay;
+};
+
+static struct atlas_device atlas_devices[] = {
+ [ATLAS_PH_SM] = {
+ .channels = atlas_ph_channels,
+ .num_channels = 3,
+ .data_reg = ATLAS_REG_PH_DATA,
+ .calibration = &atlas_check_ph_calibration,
+ .delay = ATLAS_PH_INT_TIME_IN_US,
+ },
+};
+
static int atlas_set_powermode(struct atlas_data *data, int on)
{
return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on);
@@ -178,8 +231,9 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private)
struct atlas_data *data = iio_priv(indio_dev);
int ret;
- ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA,
- (u8 *) &data->buffer, sizeof(data->buffer[0]));
+ ret = regmap_bulk_read(data->regmap, data->chip->data_reg,
+ (u8 *) &data->buffer,
+ sizeof(__be32) * (data->chip->num_channels - 2));
if (!ret)
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
@@ -200,7 +254,7 @@ static irqreturn_t atlas_interrupt_handler(int irq, void *private)
return IRQ_HANDLED;
}
-static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val)
+static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val)
{
struct device *dev = &data->client->dev;
int suspended = pm_runtime_suspended(dev);
@@ -213,11 +267,9 @@ static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val)
}
if (suspended)
- usleep_range(ATLAS_PH_INT_TIME_IN_US,
- ATLAS_PH_INT_TIME_IN_US + 100000);
+ usleep_range(data->chip->delay, data->chip->delay + 100000);
- ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA,
- (u8 *) val, sizeof(*val));
+ ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val));
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
@@ -247,7 +299,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
if (iio_buffer_enabled(indio_dev))
ret = -EBUSY;
else
- ret = atlas_read_ph_measurement(data, ®);
+ ret = atlas_read_measurement(data,
+ chan->address, ®);
mutex_unlock(&indio_dev->mlock);
break;
@@ -303,37 +356,24 @@ static const struct iio_info atlas_info = {
.write_raw = atlas_write_raw,
};
-static int atlas_check_calibration(struct atlas_data *data)
-{
- struct device *dev = &data->client->dev;
- int ret;
- unsigned int val;
-
- ret = regmap_read(data->regmap, ATLAS_REG_CALIB_STATUS, &val);
- if (ret)
- return ret;
-
- if (!(val & ATLAS_REG_CALIB_STATUS_MASK)) {
- dev_warn(dev, "device has not been calibrated\n");
- return 0;
- }
-
- if (!(val & ATLAS_REG_CALIB_STATUS_LOW))
- dev_warn(dev, "device missing low point calibration\n");
-
- if (!(val & ATLAS_REG_CALIB_STATUS_MID))
- dev_warn(dev, "device missing mid point calibration\n");
-
- if (!(val & ATLAS_REG_CALIB_STATUS_HIGH))
- dev_warn(dev, "device missing high point calibration\n");
+static const struct i2c_device_id atlas_id[] = {
+ { "atlas-ph-sm", ATLAS_PH_SM},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, atlas_id);
- return 0;
+static const struct of_device_id atlas_dt_ids[] = {
+ { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
+ { }
};
+MODULE_DEVICE_TABLE(of, atlas_dt_ids);
static int atlas_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct atlas_data *data;
+ struct atlas_device *chip;
+ const struct of_device_id *of_id;
struct iio_trigger *trig;
struct iio_dev *indio_dev;
int ret;
@@ -342,10 +382,16 @@ static int atlas_probe(struct i2c_client *client,
if (!indio_dev)
return -ENOMEM;
+ of_id = of_match_device(atlas_dt_ids, &client->dev);
+ if (!of_id)
+ chip = &atlas_devices[id->driver_data];
+ else
+ chip = &atlas_devices[(unsigned long)of_id->data];
+
indio_dev->info = &atlas_info;
indio_dev->name = ATLAS_DRV_NAME;
- indio_dev->channels = atlas_channels;
- indio_dev->num_channels = ARRAY_SIZE(atlas_channels);
+ indio_dev->channels = chip->channels;
+ indio_dev->num_channels = chip->num_channels;
indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE;
indio_dev->dev.parent = &client->dev;
@@ -358,6 +404,7 @@ static int atlas_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
data->client = client;
data->trig = trig;
+ data->chip = chip;
trig->dev.parent = indio_dev->dev.parent;
trig->ops = &atlas_interrupt_trigger_ops;
iio_trigger_set_drvdata(trig, indio_dev);
@@ -379,7 +426,7 @@ static int atlas_probe(struct i2c_client *client,
return -EINVAL;
}
- ret = atlas_check_calibration(data);
+ ret = chip->calibration(data);
if (ret)
return ret;
@@ -480,18 +527,6 @@ static const struct dev_pm_ops atlas_pm_ops = {
atlas_runtime_resume, NULL)
};
-static const struct i2c_device_id atlas_id[] = {
- { "atlas-ph-sm", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(i2c, atlas_id);
-
-static const struct of_device_id atlas_dt_ids[] = {
- { .compatible = "atlas,ph-sm" },
- { }
-};
-MODULE_DEVICE_TABLE(of, atlas_dt_ids);
-
static struct i2c_driver atlas_driver = {
.driver = {
.name = ATLAS_DRV_NAME,
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 2/3] iio: electricalconductivity: add IIO_ELECTRICALCONDUCTIVITY type
2016-05-25 4:29 [PATCH v3 0/3] atlas-ph-sensor: add conductivity sensor support Matt Ranostay
2016-05-25 4:29 ` [PATCH v3 1/3] iio: chemical: atlas-ph-sensor: reorg driver to allow multiple chips Matt Ranostay
@ 2016-05-25 4:29 ` Matt Ranostay
2016-05-29 19:04 ` Jonathan Cameron
2016-05-25 4:29 ` [PATCH v3 3/3] iio: chemical: atlas-ph-sensor: add EC feature Matt Ranostay
2 siblings, 1 reply; 7+ messages in thread
From: Matt Ranostay @ 2016-05-25 4:29 UTC (permalink / raw)
To: linux-iio; +Cc: jic23, Matt Ranostay
Signed-off-by: Matt Ranostay <mranostay@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 df44998..e7f590c 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1565,3 +1565,10 @@ Description:
* X is in the plane of the propellers, perpendicular to Y axis,
and positive towards the starboard side of the UAV ;
* Z is perpendicular to propellers plane and positive upwards.
+
+What: /sys/bus/iio/devices/iio:deviceX/in_electricalconductivity_raw
+KernelVersion: 4.8
+Contact: linux-iio@vger.kernel.org
+Description:
+ Raw (unscaled no offset etc.) electric conductivity reading that
+ can be processed to siemens per meter.
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index e6319a9..2a85bd8 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -80,6 +80,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_RESISTANCE] = "resistance",
[IIO_PH] = "ph",
[IIO_UVINDEX] = "uvindex",
+ [IIO_ELECTRICALCONDUCTIVITY] = "electricalconductivity",
};
static const char * const iio_modifier_names[] = {
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index b0916fc..22e5e58 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -39,6 +39,7 @@ enum iio_chan_type {
IIO_RESISTANCE,
IIO_PH,
IIO_UVINDEX,
+ IIO_ELECTRICALCONDUCTIVITY,
};
enum iio_modifier {
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 3/3] iio: chemical: atlas-ph-sensor: add EC feature
2016-05-25 4:29 [PATCH v3 0/3] atlas-ph-sensor: add conductivity sensor support Matt Ranostay
2016-05-25 4:29 ` [PATCH v3 1/3] iio: chemical: atlas-ph-sensor: reorg driver to allow multiple chips Matt Ranostay
2016-05-25 4:29 ` [PATCH v3 2/3] iio: electricalconductivity: add IIO_ELECTRICALCONDUCTIVITY type Matt Ranostay
@ 2016-05-25 4:29 ` Matt Ranostay
2016-05-29 19:05 ` Jonathan Cameron
2 siblings, 1 reply; 7+ messages in thread
From: Matt Ranostay @ 2016-05-25 4:29 UTC (permalink / raw)
To: linux-iio; +Cc: jic23, Matt Ranostay
Signed-off-by: Matt Ranostay <mranostay@gmail.com>
---
.../bindings/iio/chemical/atlas,ec-sm.txt | 22 ++++
drivers/iio/chemical/Kconfig | 8 +-
drivers/iio/chemical/atlas-ph-sensor.c | 122 ++++++++++++++++++++-
3 files changed, 147 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 e85477c..02e85db 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,50 @@ 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 + 1, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 32, \
+ .storagebits = 32, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+static const struct iio_chan_spec atlas_ec_channels[] = {
+ {
+ .type = IIO_ELECTRICALCONDUCTIVITY,
+ .address = ATLAS_REG_EC_DATA,
+ .info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_BE,
+ },
+ },
+ ATLAS_EC_CHANNEL(0, ATLAS_REG_TDS_DATA),
+ ATLAS_EC_CHANNEL(1, ATLAS_REG_PSS_DATA),
+ 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 +202,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 +257,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,
+ .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 +400,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
(u8 *) ®, sizeof(reg));
break;
case IIO_PH:
+ case IIO_CONCENTRATION:
+ case IIO_ELECTRICALCONDUCTIVITY:
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev))
@@ -324,6 +432,14 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
*val = 1; /* 0.001 */
*val2 = 1000;
break;
+ case IIO_ELECTRICALCONDUCTIVITY:
+ *val = 1; /* 0.00001 */
+ *val = 100000;
+ break;
+ case IIO_CONCENTRATION:
+ *val = 0; /* 0.000000001 */
+ *val2 = 1000;
+ return IIO_VAL_INT_PLUS_NANO;
default:
return -EINVAL;
}
@@ -358,12 +474,14 @@ static const struct iio_info atlas_info = {
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);
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/3] iio: chemical: atlas-ph-sensor: reorg driver to allow multiple chips
2016-05-25 4:29 ` [PATCH v3 1/3] iio: chemical: atlas-ph-sensor: reorg driver to allow multiple chips Matt Ranostay
@ 2016-05-29 19:03 ` Jonathan Cameron
0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Cameron @ 2016-05-29 19:03 UTC (permalink / raw)
To: Matt Ranostay, linux-iio
On 25/05/16 05:29, Matt Ranostay wrote:
> Signed-off-by: Matt Ranostay <mranostay@gmail.com>
> ---
Applied to the togreg branch of iio.git - initially pushed out as testing for
the autobuilders to play with it.
Thanks,
Jonathan
> drivers/iio/chemical/atlas-ph-sensor.c | 145 ++++++++++++++++++++-------------
> 1 file changed, 90 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c
> index 62b37cd..e85477c 100644
> --- a/drivers/iio/chemical/atlas-ph-sensor.c
> +++ b/drivers/iio/chemical/atlas-ph-sensor.c
> @@ -24,6 +24,7 @@
> #include <linux/irq_work.h>
> #include <linux/gpio.h>
> #include <linux/i2c.h>
> +#include <linux/of_device.h>
> #include <linux/regmap.h>
> #include <linux/iio/iio.h>
> #include <linux/iio/buffer.h>
> @@ -43,20 +44,25 @@
>
> #define ATLAS_REG_PWR_CONTROL 0x06
>
> -#define ATLAS_REG_CALIB_STATUS 0x0d
> -#define ATLAS_REG_CALIB_STATUS_MASK 0x07
> -#define ATLAS_REG_CALIB_STATUS_LOW BIT(0)
> -#define ATLAS_REG_CALIB_STATUS_MID BIT(1)
> -#define ATLAS_REG_CALIB_STATUS_HIGH BIT(2)
> +#define ATLAS_REG_PH_CALIB_STATUS 0x0d
> +#define ATLAS_REG_PH_CALIB_STATUS_MASK 0x07
> +#define ATLAS_REG_PH_CALIB_STATUS_LOW BIT(0)
> +#define ATLAS_REG_PH_CALIB_STATUS_MID BIT(1)
> +#define ATLAS_REG_PH_CALIB_STATUS_HIGH BIT(2)
>
> -#define ATLAS_REG_TEMP_DATA 0x0e
> +#define ATLAS_REG_PH_TEMP_DATA 0x0e
> #define ATLAS_REG_PH_DATA 0x16
>
> #define ATLAS_PH_INT_TIME_IN_US 450000
>
> +enum {
> + ATLAS_PH_SM,
> +};
> +
> struct atlas_data {
> struct i2c_client *client;
> struct iio_trigger *trig;
> + struct atlas_device *chip;
> struct regmap *regmap;
> struct irq_work work;
>
> @@ -84,9 +90,10 @@ static const struct regmap_config atlas_regmap_config = {
> .cache_type = REGCACHE_RBTREE,
> };
>
> -static const struct iio_chan_spec atlas_channels[] = {
> +static const struct iio_chan_spec atlas_ph_channels[] = {
> {
> .type = IIO_PH,
> + .address = ATLAS_REG_PH_DATA,
> .info_mask_separate =
> BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> .scan_index = 0,
> @@ -100,7 +107,7 @@ static const struct iio_chan_spec atlas_channels[] = {
> IIO_CHAN_SOFT_TIMESTAMP(1),
> {
> .type = IIO_TEMP,
> - .address = ATLAS_REG_TEMP_DATA,
> + .address = ATLAS_REG_PH_TEMP_DATA,
> .info_mask_separate =
> BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> .output = 1,
> @@ -108,6 +115,52 @@ static const struct iio_chan_spec atlas_channels[] = {
> },
> };
>
> +static int atlas_check_ph_calibration(struct atlas_data *data)
> +{
> + struct device *dev = &data->client->dev;
> + int ret;
> + unsigned int val;
> +
> + ret = regmap_read(data->regmap, ATLAS_REG_PH_CALIB_STATUS, &val);
> + if (ret)
> + return ret;
> +
> + if (!(val & ATLAS_REG_PH_CALIB_STATUS_MASK)) {
> + dev_warn(dev, "device has not been calibrated\n");
> + return 0;
> + }
> +
> + if (!(val & ATLAS_REG_PH_CALIB_STATUS_LOW))
> + dev_warn(dev, "device missing low point calibration\n");
> +
> + if (!(val & ATLAS_REG_PH_CALIB_STATUS_MID))
> + dev_warn(dev, "device missing mid point calibration\n");
> +
> + if (!(val & ATLAS_REG_PH_CALIB_STATUS_HIGH))
> + dev_warn(dev, "device missing high point calibration\n");
> +
> + return 0;
> +}
> +
> +struct atlas_device {
> + const struct iio_chan_spec *channels;
> + int num_channels;
> + int data_reg;
> +
> + int (*calibration)(struct atlas_data *data);
> + int delay;
> +};
> +
> +static struct atlas_device atlas_devices[] = {
> + [ATLAS_PH_SM] = {
> + .channels = atlas_ph_channels,
> + .num_channels = 3,
> + .data_reg = ATLAS_REG_PH_DATA,
> + .calibration = &atlas_check_ph_calibration,
> + .delay = ATLAS_PH_INT_TIME_IN_US,
> + },
> +};
> +
> static int atlas_set_powermode(struct atlas_data *data, int on)
> {
> return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on);
> @@ -178,8 +231,9 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private)
> struct atlas_data *data = iio_priv(indio_dev);
> int ret;
>
> - ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA,
> - (u8 *) &data->buffer, sizeof(data->buffer[0]));
> + ret = regmap_bulk_read(data->regmap, data->chip->data_reg,
> + (u8 *) &data->buffer,
> + sizeof(__be32) * (data->chip->num_channels - 2));
>
> if (!ret)
> iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
> @@ -200,7 +254,7 @@ static irqreturn_t atlas_interrupt_handler(int irq, void *private)
> return IRQ_HANDLED;
> }
>
> -static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val)
> +static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val)
> {
> struct device *dev = &data->client->dev;
> int suspended = pm_runtime_suspended(dev);
> @@ -213,11 +267,9 @@ static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val)
> }
>
> if (suspended)
> - usleep_range(ATLAS_PH_INT_TIME_IN_US,
> - ATLAS_PH_INT_TIME_IN_US + 100000);
> + usleep_range(data->chip->delay, data->chip->delay + 100000);
>
> - ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA,
> - (u8 *) val, sizeof(*val));
> + ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val));
>
> pm_runtime_mark_last_busy(dev);
> pm_runtime_put_autosuspend(dev);
> @@ -247,7 +299,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
> if (iio_buffer_enabled(indio_dev))
> ret = -EBUSY;
> else
> - ret = atlas_read_ph_measurement(data, ®);
> + ret = atlas_read_measurement(data,
> + chan->address, ®);
>
> mutex_unlock(&indio_dev->mlock);
> break;
> @@ -303,37 +356,24 @@ static const struct iio_info atlas_info = {
> .write_raw = atlas_write_raw,
> };
>
> -static int atlas_check_calibration(struct atlas_data *data)
> -{
> - struct device *dev = &data->client->dev;
> - int ret;
> - unsigned int val;
> -
> - ret = regmap_read(data->regmap, ATLAS_REG_CALIB_STATUS, &val);
> - if (ret)
> - return ret;
> -
> - if (!(val & ATLAS_REG_CALIB_STATUS_MASK)) {
> - dev_warn(dev, "device has not been calibrated\n");
> - return 0;
> - }
> -
> - if (!(val & ATLAS_REG_CALIB_STATUS_LOW))
> - dev_warn(dev, "device missing low point calibration\n");
> -
> - if (!(val & ATLAS_REG_CALIB_STATUS_MID))
> - dev_warn(dev, "device missing mid point calibration\n");
> -
> - if (!(val & ATLAS_REG_CALIB_STATUS_HIGH))
> - dev_warn(dev, "device missing high point calibration\n");
> +static const struct i2c_device_id atlas_id[] = {
> + { "atlas-ph-sm", ATLAS_PH_SM},
> + {}
> +};
> +MODULE_DEVICE_TABLE(i2c, atlas_id);
>
> - return 0;
> +static const struct of_device_id atlas_dt_ids[] = {
> + { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
> + { }
> };
> +MODULE_DEVICE_TABLE(of, atlas_dt_ids);
>
> static int atlas_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> struct atlas_data *data;
> + struct atlas_device *chip;
> + const struct of_device_id *of_id;
> struct iio_trigger *trig;
> struct iio_dev *indio_dev;
> int ret;
> @@ -342,10 +382,16 @@ static int atlas_probe(struct i2c_client *client,
> if (!indio_dev)
> return -ENOMEM;
>
> + of_id = of_match_device(atlas_dt_ids, &client->dev);
> + if (!of_id)
> + chip = &atlas_devices[id->driver_data];
> + else
> + chip = &atlas_devices[(unsigned long)of_id->data];
> +
> indio_dev->info = &atlas_info;
> indio_dev->name = ATLAS_DRV_NAME;
> - indio_dev->channels = atlas_channels;
> - indio_dev->num_channels = ARRAY_SIZE(atlas_channels);
> + indio_dev->channels = chip->channels;
> + indio_dev->num_channels = chip->num_channels;
> indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE;
> indio_dev->dev.parent = &client->dev;
>
> @@ -358,6 +404,7 @@ static int atlas_probe(struct i2c_client *client,
> data = iio_priv(indio_dev);
> data->client = client;
> data->trig = trig;
> + data->chip = chip;
> trig->dev.parent = indio_dev->dev.parent;
> trig->ops = &atlas_interrupt_trigger_ops;
> iio_trigger_set_drvdata(trig, indio_dev);
> @@ -379,7 +426,7 @@ static int atlas_probe(struct i2c_client *client,
> return -EINVAL;
> }
>
> - ret = atlas_check_calibration(data);
> + ret = chip->calibration(data);
> if (ret)
> return ret;
>
> @@ -480,18 +527,6 @@ static const struct dev_pm_ops atlas_pm_ops = {
> atlas_runtime_resume, NULL)
> };
>
> -static const struct i2c_device_id atlas_id[] = {
> - { "atlas-ph-sm", 0 },
> - {}
> -};
> -MODULE_DEVICE_TABLE(i2c, atlas_id);
> -
> -static const struct of_device_id atlas_dt_ids[] = {
> - { .compatible = "atlas,ph-sm" },
> - { }
> -};
> -MODULE_DEVICE_TABLE(of, atlas_dt_ids);
> -
> static struct i2c_driver atlas_driver = {
> .driver = {
> .name = ATLAS_DRV_NAME,
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/3] iio: electricalconductivity: add IIO_ELECTRICALCONDUCTIVITY type
2016-05-25 4:29 ` [PATCH v3 2/3] iio: electricalconductivity: add IIO_ELECTRICALCONDUCTIVITY type Matt Ranostay
@ 2016-05-29 19:04 ` Jonathan Cameron
0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Cameron @ 2016-05-29 19:04 UTC (permalink / raw)
To: Matt Ranostay, linux-iio
On 25/05/16 05:29, Matt Ranostay wrote:
> Signed-off-by: Matt Ranostay <mranostay@gmail.com>
Applied to the togreg branch of iio.git - initially pushed out as testing for
the autobuilders to ignore it.
Thanks,
Jonathan
> ---
> 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 df44998..e7f590c 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio
> +++ b/Documentation/ABI/testing/sysfs-bus-iio
> @@ -1565,3 +1565,10 @@ Description:
> * X is in the plane of the propellers, perpendicular to Y axis,
> and positive towards the starboard side of the UAV ;
> * Z is perpendicular to propellers plane and positive upwards.
> +
> +What: /sys/bus/iio/devices/iio:deviceX/in_electricalconductivity_raw
> +KernelVersion: 4.8
> +Contact: linux-iio@vger.kernel.org
> +Description:
> + Raw (unscaled no offset etc.) electric conductivity reading that
> + can be processed to siemens per meter.
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index e6319a9..2a85bd8 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -80,6 +80,7 @@ static const char * const iio_chan_type_name_spec[] = {
> [IIO_RESISTANCE] = "resistance",
> [IIO_PH] = "ph",
> [IIO_UVINDEX] = "uvindex",
> + [IIO_ELECTRICALCONDUCTIVITY] = "electricalconductivity",
> };
>
> static const char * const iio_modifier_names[] = {
> diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
> index b0916fc..22e5e58 100644
> --- a/include/uapi/linux/iio/types.h
> +++ b/include/uapi/linux/iio/types.h
> @@ -39,6 +39,7 @@ enum iio_chan_type {
> IIO_RESISTANCE,
> IIO_PH,
> IIO_UVINDEX,
> + IIO_ELECTRICALCONDUCTIVITY,
> };
>
> enum iio_modifier {
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 3/3] iio: chemical: atlas-ph-sensor: add EC feature
2016-05-25 4:29 ` [PATCH v3 3/3] iio: chemical: atlas-ph-sensor: add EC feature Matt Ranostay
@ 2016-05-29 19:05 ` Jonathan Cameron
0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Cameron @ 2016-05-29 19:05 UTC (permalink / raw)
To: Matt Ranostay, linux-iio
On 25/05/16 05:29, Matt Ranostay wrote:
> Signed-off-by: Matt Ranostay <mranostay@gmail.com>
Trivial binding so I doubt anyone cares - though technically it should have gone
to the devicetree list...
Applied to the togreg branch of iio.git - initially pushed out as testing.
Thanks,
Jonathan
> ---
> .../bindings/iio/chemical/atlas,ec-sm.txt | 22 ++++
> drivers/iio/chemical/Kconfig | 8 +-
> drivers/iio/chemical/atlas-ph-sensor.c | 122 ++++++++++++++++++++-
> 3 files changed, 147 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 e85477c..02e85db 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,50 @@ 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 + 1, \
> + .scan_type = { \
> + .sign = 'u', \
> + .realbits = 32, \
> + .storagebits = 32, \
> + .endianness = IIO_BE, \
> + }, \
> + }
> +
> +static const struct iio_chan_spec atlas_ec_channels[] = {
> + {
> + .type = IIO_ELECTRICALCONDUCTIVITY,
> + .address = ATLAS_REG_EC_DATA,
> + .info_mask_separate =
> + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> + .scan_index = 0,
> + .scan_type = {
> + .sign = 'u',
> + .realbits = 32,
> + .storagebits = 32,
> + .endianness = IIO_BE,
> + },
> + },
> + ATLAS_EC_CHANNEL(0, ATLAS_REG_TDS_DATA),
> + ATLAS_EC_CHANNEL(1, ATLAS_REG_PSS_DATA),
> + 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 +202,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 +257,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,
> + .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 +400,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
> (u8 *) ®, sizeof(reg));
> break;
> case IIO_PH:
> + case IIO_CONCENTRATION:
> + case IIO_ELECTRICALCONDUCTIVITY:
> mutex_lock(&indio_dev->mlock);
>
> if (iio_buffer_enabled(indio_dev))
> @@ -324,6 +432,14 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
> *val = 1; /* 0.001 */
> *val2 = 1000;
> break;
> + case IIO_ELECTRICALCONDUCTIVITY:
> + *val = 1; /* 0.00001 */
> + *val = 100000;
> + break;
> + case IIO_CONCENTRATION:
> + *val = 0; /* 0.000000001 */
> + *val2 = 1000;
> + return IIO_VAL_INT_PLUS_NANO;
> default:
> return -EINVAL;
> }
> @@ -358,12 +474,14 @@ static const struct iio_info atlas_info = {
>
> 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);
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-05-29 19:05 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-25 4:29 [PATCH v3 0/3] atlas-ph-sensor: add conductivity sensor support Matt Ranostay
2016-05-25 4:29 ` [PATCH v3 1/3] iio: chemical: atlas-ph-sensor: reorg driver to allow multiple chips Matt Ranostay
2016-05-29 19:03 ` Jonathan Cameron
2016-05-25 4:29 ` [PATCH v3 2/3] iio: electricalconductivity: add IIO_ELECTRICALCONDUCTIVITY type Matt Ranostay
2016-05-29 19:04 ` Jonathan Cameron
2016-05-25 4:29 ` [PATCH v3 3/3] iio: chemical: atlas-ph-sensor: add EC feature Matt Ranostay
2016-05-29 19:05 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).