Skip to content

Commit e8dd92b

Browse files
mranostayjic23
authored andcommitted
iio: chemical: atlas-ph-sensor: add EC feature
Signed-off-by: Matt Ranostay <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 4b9d209 commit e8dd92b

File tree

3 files changed

+147
-5
lines changed

3 files changed

+147
-5
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
* Atlas Scientific EC-SM OEM sensor
2+
3+
http://www.atlas-scientific.com/_files/_datasheets/_oem/EC_oem_datasheet.pdf
4+
5+
Required properties:
6+
7+
- compatible: must be "atlas,ec-sm"
8+
- reg: the I2C address of the sensor
9+
- interrupt-parent: should be the phandle for the interrupt controller
10+
- interrupts: the sole interrupt generated by the device
11+
12+
Refer to interrupt-controller/interrupts.txt for generic interrupt client
13+
node bindings.
14+
15+
Example:
16+
17+
atlas@64 {
18+
compatible = "atlas,ec-sm";
19+
reg = <0x64>;
20+
interrupt-parent = <&gpio1>;
21+
interrupts = <16 2>;
22+
};

drivers/iio/chemical/Kconfig

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
menu "Chemical Sensors"
66

77
config ATLAS_PH_SENSOR
8-
tristate "Atlas Scientific OEM pH-SM sensor"
8+
tristate "Atlas Scientific OEM SM sensors"
99
depends on I2C
1010
select REGMAP_I2C
1111
select IIO_BUFFER
1212
select IIO_TRIGGERED_BUFFER
1313
select IRQ_WORK
1414
help
15-
Say Y here to build I2C interface support for the Atlas
16-
Scientific OEM pH-SM sensor.
15+
Say Y here to build I2C interface support for the following
16+
Atlas Scientific OEM SM sensors:
17+
* pH SM sensor
18+
* EC SM sensor
1719

1820
To compile this driver as module, choose M here: the
1921
module will be called atlas-ph-sensor.

drivers/iio/chemical/atlas-ph-sensor.c

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,28 @@
5050
#define ATLAS_REG_PH_CALIB_STATUS_MID BIT(1)
5151
#define ATLAS_REG_PH_CALIB_STATUS_HIGH BIT(2)
5252

53+
#define ATLAS_REG_EC_CALIB_STATUS 0x0f
54+
#define ATLAS_REG_EC_CALIB_STATUS_MASK 0x0f
55+
#define ATLAS_REG_EC_CALIB_STATUS_DRY BIT(0)
56+
#define ATLAS_REG_EC_CALIB_STATUS_SINGLE BIT(1)
57+
#define ATLAS_REG_EC_CALIB_STATUS_LOW BIT(2)
58+
#define ATLAS_REG_EC_CALIB_STATUS_HIGH BIT(3)
59+
5360
#define ATLAS_REG_PH_TEMP_DATA 0x0e
5461
#define ATLAS_REG_PH_DATA 0x16
5562

63+
#define ATLAS_REG_EC_PROBE 0x08
64+
#define ATLAS_REG_EC_TEMP_DATA 0x10
65+
#define ATLAS_REG_EC_DATA 0x18
66+
#define ATLAS_REG_TDS_DATA 0x1c
67+
#define ATLAS_REG_PSS_DATA 0x20
68+
5669
#define ATLAS_PH_INT_TIME_IN_US 450000
70+
#define ATLAS_EC_INT_TIME_IN_US 650000
5771

5872
enum {
5973
ATLAS_PH_SM,
74+
ATLAS_EC_SM,
6075
};
6176

6277
struct atlas_data {
@@ -66,12 +81,13 @@ struct atlas_data {
6681
struct regmap *regmap;
6782
struct irq_work work;
6883

69-
__be32 buffer[4]; /* 32-bit pH data + 32-bit pad + 64-bit timestamp */
84+
__be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */
7085
};
7186

7287
static const struct regmap_range atlas_volatile_ranges[] = {
7388
regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL),
7489
regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4),
90+
regmap_reg_range(ATLAS_REG_EC_DATA, ATLAS_REG_PSS_DATA + 4),
7591
};
7692

7793
static const struct regmap_access_table atlas_volatile_table = {
@@ -86,7 +102,7 @@ static const struct regmap_config atlas_regmap_config = {
86102
.val_bits = 8,
87103

88104
.volatile_table = &atlas_volatile_table,
89-
.max_register = ATLAS_REG_PH_DATA + 4,
105+
.max_register = ATLAS_REG_PSS_DATA + 4,
90106
.cache_type = REGCACHE_RBTREE,
91107
};
92108

@@ -115,6 +131,50 @@ static const struct iio_chan_spec atlas_ph_channels[] = {
115131
},
116132
};
117133

134+
#define ATLAS_EC_CHANNEL(_idx, _addr) \
135+
{\
136+
.type = IIO_CONCENTRATION, \
137+
.indexed = 1, \
138+
.channel = _idx, \
139+
.address = _addr, \
140+
.info_mask_separate = \
141+
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \
142+
.scan_index = _idx + 1, \
143+
.scan_type = { \
144+
.sign = 'u', \
145+
.realbits = 32, \
146+
.storagebits = 32, \
147+
.endianness = IIO_BE, \
148+
}, \
149+
}
150+
151+
static const struct iio_chan_spec atlas_ec_channels[] = {
152+
{
153+
.type = IIO_ELECTRICALCONDUCTIVITY,
154+
.address = ATLAS_REG_EC_DATA,
155+
.info_mask_separate =
156+
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
157+
.scan_index = 0,
158+
.scan_type = {
159+
.sign = 'u',
160+
.realbits = 32,
161+
.storagebits = 32,
162+
.endianness = IIO_BE,
163+
},
164+
},
165+
ATLAS_EC_CHANNEL(0, ATLAS_REG_TDS_DATA),
166+
ATLAS_EC_CHANNEL(1, ATLAS_REG_PSS_DATA),
167+
IIO_CHAN_SOFT_TIMESTAMP(3),
168+
{
169+
.type = IIO_TEMP,
170+
.address = ATLAS_REG_EC_TEMP_DATA,
171+
.info_mask_separate =
172+
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
173+
.output = 1,
174+
.scan_index = -1
175+
},
176+
};
177+
118178
static int atlas_check_ph_calibration(struct atlas_data *data)
119179
{
120180
struct device *dev = &data->client->dev;
@@ -142,6 +202,44 @@ static int atlas_check_ph_calibration(struct atlas_data *data)
142202
return 0;
143203
}
144204

205+
static int atlas_check_ec_calibration(struct atlas_data *data)
206+
{
207+
struct device *dev = &data->client->dev;
208+
int ret;
209+
unsigned int val;
210+
211+
ret = regmap_bulk_read(data->regmap, ATLAS_REG_EC_PROBE, &val, 2);
212+
if (ret)
213+
return ret;
214+
215+
dev_info(dev, "probe set to K = %d.%.2d", be16_to_cpu(val) / 100,
216+
be16_to_cpu(val) % 100);
217+
218+
ret = regmap_read(data->regmap, ATLAS_REG_EC_CALIB_STATUS, &val);
219+
if (ret)
220+
return ret;
221+
222+
if (!(val & ATLAS_REG_EC_CALIB_STATUS_MASK)) {
223+
dev_warn(dev, "device has not been calibrated\n");
224+
return 0;
225+
}
226+
227+
if (!(val & ATLAS_REG_EC_CALIB_STATUS_DRY))
228+
dev_warn(dev, "device missing dry point calibration\n");
229+
230+
if (val & ATLAS_REG_EC_CALIB_STATUS_SINGLE) {
231+
dev_warn(dev, "device using single point calibration\n");
232+
} else {
233+
if (!(val & ATLAS_REG_EC_CALIB_STATUS_LOW))
234+
dev_warn(dev, "device missing low point calibration\n");
235+
236+
if (!(val & ATLAS_REG_EC_CALIB_STATUS_HIGH))
237+
dev_warn(dev, "device missing high point calibration\n");
238+
}
239+
240+
return 0;
241+
}
242+
145243
struct atlas_device {
146244
const struct iio_chan_spec *channels;
147245
int num_channels;
@@ -159,6 +257,14 @@ static struct atlas_device atlas_devices[] = {
159257
.calibration = &atlas_check_ph_calibration,
160258
.delay = ATLAS_PH_INT_TIME_IN_US,
161259
},
260+
[ATLAS_EC_SM] = {
261+
.channels = atlas_ec_channels,
262+
.num_channels = 5,
263+
.data_reg = ATLAS_REG_EC_DATA,
264+
.calibration = &atlas_check_ec_calibration,
265+
.delay = ATLAS_EC_INT_TIME_IN_US,
266+
},
267+
162268
};
163269

164270
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,
294400
(u8 *) &reg, sizeof(reg));
295401
break;
296402
case IIO_PH:
403+
case IIO_CONCENTRATION:
404+
case IIO_ELECTRICALCONDUCTIVITY:
297405
mutex_lock(&indio_dev->mlock);
298406

299407
if (iio_buffer_enabled(indio_dev))
@@ -324,6 +432,14 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
324432
*val = 1; /* 0.001 */
325433
*val2 = 1000;
326434
break;
435+
case IIO_ELECTRICALCONDUCTIVITY:
436+
*val = 1; /* 0.00001 */
437+
*val = 100000;
438+
break;
439+
case IIO_CONCENTRATION:
440+
*val = 0; /* 0.000000001 */
441+
*val2 = 1000;
442+
return IIO_VAL_INT_PLUS_NANO;
327443
default:
328444
return -EINVAL;
329445
}
@@ -358,12 +474,14 @@ static const struct iio_info atlas_info = {
358474

359475
static const struct i2c_device_id atlas_id[] = {
360476
{ "atlas-ph-sm", ATLAS_PH_SM},
477+
{ "atlas-ec-sm", ATLAS_EC_SM},
361478
{}
362479
};
363480
MODULE_DEVICE_TABLE(i2c, atlas_id);
364481

365482
static const struct of_device_id atlas_dt_ids[] = {
366483
{ .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
484+
{ .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
367485
{ }
368486
};
369487
MODULE_DEVICE_TABLE(of, atlas_dt_ids);

0 commit comments

Comments
 (0)