diff options
Diffstat (limited to 'drivers/iio/chemical/atlas-ph-sensor.c')
-rw-r--r-- | drivers/iio/chemical/atlas-ph-sensor.c | 81 |
1 files changed, 57 insertions, 24 deletions
diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c index 407f141a1eee..bd321b305a0a 100644 --- a/drivers/iio/chemical/atlas-ph-sensor.c +++ b/drivers/iio/chemical/atlas-ph-sensor.c | |||
@@ -66,12 +66,17 @@ | |||
66 | #define ATLAS_REG_TDS_DATA 0x1c | 66 | #define ATLAS_REG_TDS_DATA 0x1c |
67 | #define ATLAS_REG_PSS_DATA 0x20 | 67 | #define ATLAS_REG_PSS_DATA 0x20 |
68 | 68 | ||
69 | #define ATLAS_REG_ORP_CALIB_STATUS 0x0d | ||
70 | #define ATLAS_REG_ORP_DATA 0x0e | ||
71 | |||
69 | #define ATLAS_PH_INT_TIME_IN_US 450000 | 72 | #define ATLAS_PH_INT_TIME_IN_US 450000 |
70 | #define ATLAS_EC_INT_TIME_IN_US 650000 | 73 | #define ATLAS_EC_INT_TIME_IN_US 650000 |
74 | #define ATLAS_ORP_INT_TIME_IN_US 450000 | ||
71 | 75 | ||
72 | enum { | 76 | enum { |
73 | ATLAS_PH_SM, | 77 | ATLAS_PH_SM, |
74 | ATLAS_EC_SM, | 78 | ATLAS_EC_SM, |
79 | ATLAS_ORP_SM, | ||
75 | }; | 80 | }; |
76 | 81 | ||
77 | struct atlas_data { | 82 | struct atlas_data { |
@@ -84,26 +89,10 @@ struct atlas_data { | |||
84 | __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ | 89 | __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ |
85 | }; | 90 | }; |
86 | 91 | ||
87 | static const struct regmap_range atlas_volatile_ranges[] = { | ||
88 | regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL), | ||
89 | 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), | ||
91 | }; | ||
92 | |||
93 | static const struct regmap_access_table atlas_volatile_table = { | ||
94 | .yes_ranges = atlas_volatile_ranges, | ||
95 | .n_yes_ranges = ARRAY_SIZE(atlas_volatile_ranges), | ||
96 | }; | ||
97 | |||
98 | static const struct regmap_config atlas_regmap_config = { | 92 | static const struct regmap_config atlas_regmap_config = { |
99 | .name = ATLAS_REGMAP_NAME, | 93 | .name = ATLAS_REGMAP_NAME, |
100 | |||
101 | .reg_bits = 8, | 94 | .reg_bits = 8, |
102 | .val_bits = 8, | 95 | .val_bits = 8, |
103 | |||
104 | .volatile_table = &atlas_volatile_table, | ||
105 | .max_register = ATLAS_REG_PSS_DATA + 4, | ||
106 | .cache_type = REGCACHE_RBTREE, | ||
107 | }; | 96 | }; |
108 | 97 | ||
109 | static const struct iio_chan_spec atlas_ph_channels[] = { | 98 | static const struct iio_chan_spec atlas_ph_channels[] = { |
@@ -175,6 +164,23 @@ static const struct iio_chan_spec atlas_ec_channels[] = { | |||
175 | }, | 164 | }, |
176 | }; | 165 | }; |
177 | 166 | ||
167 | static const struct iio_chan_spec atlas_orp_channels[] = { | ||
168 | { | ||
169 | .type = IIO_VOLTAGE, | ||
170 | .address = ATLAS_REG_ORP_DATA, | ||
171 | .info_mask_separate = | ||
172 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | ||
173 | .scan_index = 0, | ||
174 | .scan_type = { | ||
175 | .sign = 's', | ||
176 | .realbits = 32, | ||
177 | .storagebits = 32, | ||
178 | .endianness = IIO_BE, | ||
179 | }, | ||
180 | }, | ||
181 | IIO_CHAN_SOFT_TIMESTAMP(1), | ||
182 | }; | ||
183 | |||
178 | static int atlas_check_ph_calibration(struct atlas_data *data) | 184 | static int atlas_check_ph_calibration(struct atlas_data *data) |
179 | { | 185 | { |
180 | struct device *dev = &data->client->dev; | 186 | struct device *dev = &data->client->dev; |
@@ -240,6 +246,22 @@ static int atlas_check_ec_calibration(struct atlas_data *data) | |||
240 | return 0; | 246 | return 0; |
241 | } | 247 | } |
242 | 248 | ||
249 | static int atlas_check_orp_calibration(struct atlas_data *data) | ||
250 | { | ||
251 | struct device *dev = &data->client->dev; | ||
252 | int ret; | ||
253 | unsigned int val; | ||
254 | |||
255 | ret = regmap_read(data->regmap, ATLAS_REG_ORP_CALIB_STATUS, &val); | ||
256 | if (ret) | ||
257 | return ret; | ||
258 | |||
259 | if (!val) | ||
260 | dev_warn(dev, "device has not been calibrated\n"); | ||
261 | |||
262 | return 0; | ||
263 | }; | ||
264 | |||
243 | struct atlas_device { | 265 | struct atlas_device { |
244 | const struct iio_chan_spec *channels; | 266 | const struct iio_chan_spec *channels; |
245 | int num_channels; | 267 | int num_channels; |
@@ -264,7 +286,13 @@ static struct atlas_device atlas_devices[] = { | |||
264 | .calibration = &atlas_check_ec_calibration, | 286 | .calibration = &atlas_check_ec_calibration, |
265 | .delay = ATLAS_EC_INT_TIME_IN_US, | 287 | .delay = ATLAS_EC_INT_TIME_IN_US, |
266 | }, | 288 | }, |
267 | 289 | [ATLAS_ORP_SM] = { | |
290 | .channels = atlas_orp_channels, | ||
291 | .num_channels = 2, | ||
292 | .data_reg = ATLAS_REG_ORP_DATA, | ||
293 | .calibration = &atlas_check_orp_calibration, | ||
294 | .delay = ATLAS_ORP_INT_TIME_IN_US, | ||
295 | }, | ||
268 | }; | 296 | }; |
269 | 297 | ||
270 | static int atlas_set_powermode(struct atlas_data *data, int on) | 298 | static int atlas_set_powermode(struct atlas_data *data, int on) |
@@ -402,15 +430,14 @@ static int atlas_read_raw(struct iio_dev *indio_dev, | |||
402 | case IIO_PH: | 430 | case IIO_PH: |
403 | case IIO_CONCENTRATION: | 431 | case IIO_CONCENTRATION: |
404 | case IIO_ELECTRICALCONDUCTIVITY: | 432 | case IIO_ELECTRICALCONDUCTIVITY: |
405 | mutex_lock(&indio_dev->mlock); | 433 | case IIO_VOLTAGE: |
434 | ret = iio_device_claim_direct_mode(indio_dev); | ||
435 | if (ret) | ||
436 | return ret; | ||
406 | 437 | ||
407 | if (iio_buffer_enabled(indio_dev)) | 438 | ret = atlas_read_measurement(data, chan->address, ®); |
408 | ret = -EBUSY; | ||
409 | else | ||
410 | ret = atlas_read_measurement(data, | ||
411 | chan->address, ®); | ||
412 | 439 | ||
413 | mutex_unlock(&indio_dev->mlock); | 440 | iio_device_release_direct_mode(indio_dev); |
414 | break; | 441 | break; |
415 | default: | 442 | default: |
416 | ret = -EINVAL; | 443 | ret = -EINVAL; |
@@ -440,6 +467,10 @@ static int atlas_read_raw(struct iio_dev *indio_dev, | |||
440 | *val = 0; /* 0.000000001 */ | 467 | *val = 0; /* 0.000000001 */ |
441 | *val2 = 1000; | 468 | *val2 = 1000; |
442 | return IIO_VAL_INT_PLUS_NANO; | 469 | return IIO_VAL_INT_PLUS_NANO; |
470 | case IIO_VOLTAGE: | ||
471 | *val = 1; /* 0.1 */ | ||
472 | *val2 = 10; | ||
473 | break; | ||
443 | default: | 474 | default: |
444 | return -EINVAL; | 475 | return -EINVAL; |
445 | } | 476 | } |
@@ -475,6 +506,7 @@ static const struct iio_info atlas_info = { | |||
475 | static const struct i2c_device_id atlas_id[] = { | 506 | static const struct i2c_device_id atlas_id[] = { |
476 | { "atlas-ph-sm", ATLAS_PH_SM}, | 507 | { "atlas-ph-sm", ATLAS_PH_SM}, |
477 | { "atlas-ec-sm", ATLAS_EC_SM}, | 508 | { "atlas-ec-sm", ATLAS_EC_SM}, |
509 | { "atlas-orp-sm", ATLAS_ORP_SM}, | ||
478 | {} | 510 | {} |
479 | }; | 511 | }; |
480 | MODULE_DEVICE_TABLE(i2c, atlas_id); | 512 | MODULE_DEVICE_TABLE(i2c, atlas_id); |
@@ -482,6 +514,7 @@ MODULE_DEVICE_TABLE(i2c, atlas_id); | |||
482 | static const struct of_device_id atlas_dt_ids[] = { | 514 | static const struct of_device_id atlas_dt_ids[] = { |
483 | { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, }, | 515 | { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, }, |
484 | { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, }, | 516 | { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, }, |
517 | { .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, }, | ||
485 | { } | 518 | { } |
486 | }; | 519 | }; |
487 | MODULE_DEVICE_TABLE(of, atlas_dt_ids); | 520 | MODULE_DEVICE_TABLE(of, atlas_dt_ids); |