1 // SPDX-License-Identifier: GPL-2.0+
3 * atlas-ezo-sensor.c - Support for Atlas Scientific EZO sensors
5 * Copyright (C) 2020 Konsulko Group
6 * Author: Matt Ranostay <matt.ranostay@konsulko.com>
9 #include <linux/init.h>
10 #include <linux/delay.h>
11 #include <linux/mod_devicetable.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/property.h>
15 #include <linux/err.h>
16 #include <linux/i2c.h>
18 #include <linux/iio/iio.h>
20 #define ATLAS_EZO_DRV_NAME "atlas-ezo-sensor"
21 #define ATLAS_INT_TIME_IN_MS 950
22 #define ATLAS_INT_HUM_TIME_IN_MS 350
30 struct atlas_ezo_device
{
31 const struct iio_chan_spec
*channels
;
36 struct atlas_ezo_data
{
37 struct i2c_client
*client
;
38 const struct atlas_ezo_device
*chip
;
40 /* lock to avoid multiple concurrent read calls */
46 #define ATLAS_CONCENTRATION_CHANNEL(_modifier) \
48 .type = IIO_CONCENTRATION, \
50 .channel2 = _modifier, \
51 .info_mask_separate = \
52 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \
58 .endianness = IIO_CPU, \
62 static const struct iio_chan_spec atlas_co2_ezo_channels
[] = {
63 ATLAS_CONCENTRATION_CHANNEL(IIO_MOD_CO2
),
66 static const struct iio_chan_spec atlas_o2_ezo_channels
[] = {
67 ATLAS_CONCENTRATION_CHANNEL(IIO_MOD_O2
),
70 static const struct iio_chan_spec atlas_hum_ezo_channels
[] = {
72 .type
= IIO_HUMIDITYRELATIVE
,
74 BIT(IIO_CHAN_INFO_RAW
) | BIT(IIO_CHAN_INFO_SCALE
),
80 .endianness
= IIO_CPU
,
85 static struct atlas_ezo_device atlas_ezo_devices
[] = {
87 .channels
= atlas_co2_ezo_channels
,
89 .delay
= ATLAS_INT_TIME_IN_MS
,
92 .channels
= atlas_o2_ezo_channels
,
94 .delay
= ATLAS_INT_TIME_IN_MS
,
97 .channels
= atlas_hum_ezo_channels
,
99 .delay
= ATLAS_INT_HUM_TIME_IN_MS
,
103 static void atlas_ezo_sanitize(char *buf
)
105 char *ptr
= strchr(buf
, '.');
110 memmove(ptr
, ptr
+ 1, strlen(ptr
));
113 static int atlas_ezo_read_raw(struct iio_dev
*indio_dev
,
114 struct iio_chan_spec
const *chan
,
115 int *val
, int *val2
, long mask
)
117 struct atlas_ezo_data
*data
= iio_priv(indio_dev
);
118 struct i2c_client
*client
= data
->client
;
120 if (chan
->type
!= IIO_CONCENTRATION
)
124 case IIO_CHAN_INFO_RAW
: {
128 mutex_lock(&data
->lock
);
130 tmp
= i2c_smbus_write_byte(client
, 'R');
133 mutex_unlock(&data
->lock
);
137 msleep(data
->chip
->delay
);
139 tmp
= i2c_master_recv(client
, data
->buffer
, sizeof(data
->buffer
));
141 if (tmp
< 0 || data
->buffer
[0] != 1) {
142 mutex_unlock(&data
->lock
);
146 /* removing floating point for fixed number representation */
147 atlas_ezo_sanitize(data
->buffer
+ 2);
149 ret
= kstrtol(data
->buffer
+ 1, 10, &tmp
);
153 mutex_unlock(&data
->lock
);
155 return ret
? ret
: IIO_VAL_INT
;
157 case IIO_CHAN_INFO_SCALE
:
158 switch (chan
->type
) {
159 case IIO_HUMIDITYRELATIVE
:
162 case IIO_CONCENTRATION
:
168 /* IIO_CONCENTRATION modifiers */
169 switch (chan
->channel2
) {
172 *val2
= 100; /* 0.0001 */
173 return IIO_VAL_INT_PLUS_MICRO
;
184 static const struct iio_info atlas_info
= {
185 .read_raw
= atlas_ezo_read_raw
,
188 static const struct i2c_device_id atlas_ezo_id
[] = {
189 { "atlas-co2-ezo", (kernel_ulong_t
)&atlas_ezo_devices
[ATLAS_CO2_EZO
] },
190 { "atlas-o2-ezo", (kernel_ulong_t
)&atlas_ezo_devices
[ATLAS_O2_EZO
] },
191 { "atlas-hum-ezo", (kernel_ulong_t
)&atlas_ezo_devices
[ATLAS_HUM_EZO
] },
194 MODULE_DEVICE_TABLE(i2c
, atlas_ezo_id
);
196 static const struct of_device_id atlas_ezo_dt_ids
[] = {
197 { .compatible
= "atlas,co2-ezo", .data
= &atlas_ezo_devices
[ATLAS_CO2_EZO
], },
198 { .compatible
= "atlas,o2-ezo", .data
= &atlas_ezo_devices
[ATLAS_O2_EZO
], },
199 { .compatible
= "atlas,hum-ezo", .data
= &atlas_ezo_devices
[ATLAS_HUM_EZO
], },
202 MODULE_DEVICE_TABLE(of
, atlas_ezo_dt_ids
);
204 static int atlas_ezo_probe(struct i2c_client
*client
)
206 const struct atlas_ezo_device
*chip
;
207 struct atlas_ezo_data
*data
;
208 struct iio_dev
*indio_dev
;
210 indio_dev
= devm_iio_device_alloc(&client
->dev
, sizeof(*data
));
214 chip
= i2c_get_match_data(client
);
218 indio_dev
->info
= &atlas_info
;
219 indio_dev
->name
= ATLAS_EZO_DRV_NAME
;
220 indio_dev
->channels
= chip
->channels
;
221 indio_dev
->num_channels
= chip
->num_channels
;
222 indio_dev
->modes
= INDIO_DIRECT_MODE
;
224 data
= iio_priv(indio_dev
);
225 data
->client
= client
;
227 mutex_init(&data
->lock
);
229 return devm_iio_device_register(&client
->dev
, indio_dev
);
232 static struct i2c_driver atlas_ezo_driver
= {
234 .name
= ATLAS_EZO_DRV_NAME
,
235 .of_match_table
= atlas_ezo_dt_ids
,
237 .probe
= atlas_ezo_probe
,
238 .id_table
= atlas_ezo_id
,
240 module_i2c_driver(atlas_ezo_driver
);
242 MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
243 MODULE_DESCRIPTION("Atlas Scientific EZO sensors");
244 MODULE_LICENSE("GPL");