sps30.c (8490B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Sensirion SPS30 particulate matter sensor driver 4 * 5 * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> 6 */ 7 8#include <linux/crc8.h> 9#include <linux/delay.h> 10#include <linux/i2c.h> 11#include <linux/iio/buffer.h> 12#include <linux/iio/iio.h> 13#include <linux/iio/sysfs.h> 14#include <linux/iio/trigger_consumer.h> 15#include <linux/iio/triggered_buffer.h> 16#include <linux/kernel.h> 17#include <linux/module.h> 18 19#include "sps30.h" 20 21/* sensor measures reliably up to 3000 ug / m3 */ 22#define SPS30_MAX_PM 3000 23/* minimum and maximum self cleaning periods in seconds */ 24#define SPS30_AUTO_CLEANING_PERIOD_MIN 0 25#define SPS30_AUTO_CLEANING_PERIOD_MAX 604800 26 27enum { 28 PM1, 29 PM2P5, 30 PM4, 31 PM10, 32}; 33 34enum { 35 RESET, 36 MEASURING, 37}; 38 39static s32 sps30_float_to_int_clamped(__be32 *fp) 40{ 41 int val = be32_to_cpup(fp); 42 int mantissa = val & GENMASK(22, 0); 43 /* this is fine since passed float is always non-negative */ 44 int exp = val >> 23; 45 int fraction, shift; 46 47 /* special case 0 */ 48 if (!exp && !mantissa) 49 return 0; 50 51 exp -= 127; 52 if (exp < 0) { 53 /* return values ranging from 1 to 99 */ 54 return ((((1 << 23) + mantissa) * 100) >> 23) >> (-exp); 55 } 56 57 /* return values ranging from 100 to 300000 */ 58 shift = 23 - exp; 59 val = (1 << exp) + (mantissa >> shift); 60 if (val >= SPS30_MAX_PM) 61 return SPS30_MAX_PM * 100; 62 63 fraction = mantissa & GENMASK(shift - 1, 0); 64 65 return val * 100 + ((fraction * 100) >> shift); 66} 67 68static int sps30_do_meas(struct sps30_state *state, s32 *data, int size) 69{ 70 int i, ret; 71 72 if (state->state == RESET) { 73 ret = state->ops->start_meas(state); 74 if (ret) 75 return ret; 76 77 state->state = MEASURING; 78 } 79 80 ret = state->ops->read_meas(state, (__be32 *)data, size); 81 if (ret) 82 return ret; 83 84 for (i = 0; i < size; i++) 85 data[i] = sps30_float_to_int_clamped((__be32 *)&data[i]); 86 87 return 0; 88} 89 90static int sps30_do_reset(struct sps30_state *state) 91{ 92 int ret; 93 94 ret = state->ops->reset(state); 95 if (ret) 96 return ret; 97 98 state->state = RESET; 99 100 return 0; 101} 102 103static irqreturn_t sps30_trigger_handler(int irq, void *p) 104{ 105 struct iio_poll_func *pf = p; 106 struct iio_dev *indio_dev = pf->indio_dev; 107 struct sps30_state *state = iio_priv(indio_dev); 108 int ret; 109 struct { 110 s32 data[4]; /* PM1, PM2P5, PM4, PM10 */ 111 s64 ts; 112 } scan; 113 114 mutex_lock(&state->lock); 115 ret = sps30_do_meas(state, scan.data, ARRAY_SIZE(scan.data)); 116 mutex_unlock(&state->lock); 117 if (ret) 118 goto err; 119 120 iio_push_to_buffers_with_timestamp(indio_dev, &scan, 121 iio_get_time_ns(indio_dev)); 122err: 123 iio_trigger_notify_done(indio_dev->trig); 124 125 return IRQ_HANDLED; 126} 127 128static int sps30_read_raw(struct iio_dev *indio_dev, 129 struct iio_chan_spec const *chan, 130 int *val, int *val2, long mask) 131{ 132 struct sps30_state *state = iio_priv(indio_dev); 133 int data[4], ret = -EINVAL; 134 135 switch (mask) { 136 case IIO_CHAN_INFO_PROCESSED: 137 switch (chan->type) { 138 case IIO_MASSCONCENTRATION: 139 mutex_lock(&state->lock); 140 /* read up to the number of bytes actually needed */ 141 switch (chan->channel2) { 142 case IIO_MOD_PM1: 143 ret = sps30_do_meas(state, data, 1); 144 break; 145 case IIO_MOD_PM2P5: 146 ret = sps30_do_meas(state, data, 2); 147 break; 148 case IIO_MOD_PM4: 149 ret = sps30_do_meas(state, data, 3); 150 break; 151 case IIO_MOD_PM10: 152 ret = sps30_do_meas(state, data, 4); 153 break; 154 } 155 mutex_unlock(&state->lock); 156 if (ret) 157 return ret; 158 159 *val = data[chan->address] / 100; 160 *val2 = (data[chan->address] % 100) * 10000; 161 162 return IIO_VAL_INT_PLUS_MICRO; 163 default: 164 return -EINVAL; 165 } 166 case IIO_CHAN_INFO_SCALE: 167 switch (chan->type) { 168 case IIO_MASSCONCENTRATION: 169 switch (chan->channel2) { 170 case IIO_MOD_PM1: 171 case IIO_MOD_PM2P5: 172 case IIO_MOD_PM4: 173 case IIO_MOD_PM10: 174 *val = 0; 175 *val2 = 10000; 176 177 return IIO_VAL_INT_PLUS_MICRO; 178 default: 179 return -EINVAL; 180 } 181 default: 182 return -EINVAL; 183 } 184 } 185 186 return -EINVAL; 187} 188 189static ssize_t start_cleaning_store(struct device *dev, 190 struct device_attribute *attr, 191 const char *buf, size_t len) 192{ 193 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 194 struct sps30_state *state = iio_priv(indio_dev); 195 int val, ret; 196 197 if (kstrtoint(buf, 0, &val) || val != 1) 198 return -EINVAL; 199 200 mutex_lock(&state->lock); 201 ret = state->ops->clean_fan(state); 202 mutex_unlock(&state->lock); 203 if (ret) 204 return ret; 205 206 return len; 207} 208 209static ssize_t cleaning_period_show(struct device *dev, 210 struct device_attribute *attr, 211 char *buf) 212{ 213 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 214 struct sps30_state *state = iio_priv(indio_dev); 215 __be32 val; 216 int ret; 217 218 mutex_lock(&state->lock); 219 ret = state->ops->read_cleaning_period(state, &val); 220 mutex_unlock(&state->lock); 221 if (ret) 222 return ret; 223 224 return sysfs_emit(buf, "%d\n", be32_to_cpu(val)); 225} 226 227static ssize_t cleaning_period_store(struct device *dev, struct device_attribute *attr, 228 const char *buf, size_t len) 229{ 230 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 231 struct sps30_state *state = iio_priv(indio_dev); 232 int val, ret; 233 234 if (kstrtoint(buf, 0, &val)) 235 return -EINVAL; 236 237 if ((val < SPS30_AUTO_CLEANING_PERIOD_MIN) || 238 (val > SPS30_AUTO_CLEANING_PERIOD_MAX)) 239 return -EINVAL; 240 241 mutex_lock(&state->lock); 242 ret = state->ops->write_cleaning_period(state, cpu_to_be32(val)); 243 if (ret) { 244 mutex_unlock(&state->lock); 245 return ret; 246 } 247 248 msleep(20); 249 250 /* 251 * sensor requires reset in order to return up to date self cleaning 252 * period 253 */ 254 ret = sps30_do_reset(state); 255 if (ret) 256 dev_warn(dev, 257 "period changed but reads will return the old value\n"); 258 259 mutex_unlock(&state->lock); 260 261 return len; 262} 263 264static ssize_t cleaning_period_available_show(struct device *dev, 265 struct device_attribute *attr, 266 char *buf) 267{ 268 return sysfs_emit(buf, "[%d %d %d]\n", 269 SPS30_AUTO_CLEANING_PERIOD_MIN, 1, 270 SPS30_AUTO_CLEANING_PERIOD_MAX); 271} 272 273static IIO_DEVICE_ATTR_WO(start_cleaning, 0); 274static IIO_DEVICE_ATTR_RW(cleaning_period, 0); 275static IIO_DEVICE_ATTR_RO(cleaning_period_available, 0); 276 277static struct attribute *sps30_attrs[] = { 278 &iio_dev_attr_start_cleaning.dev_attr.attr, 279 &iio_dev_attr_cleaning_period.dev_attr.attr, 280 &iio_dev_attr_cleaning_period_available.dev_attr.attr, 281 NULL 282}; 283 284static const struct attribute_group sps30_attr_group = { 285 .attrs = sps30_attrs, 286}; 287 288static const struct iio_info sps30_info = { 289 .attrs = &sps30_attr_group, 290 .read_raw = sps30_read_raw, 291}; 292 293#define SPS30_CHAN(_index, _mod) { \ 294 .type = IIO_MASSCONCENTRATION, \ 295 .modified = 1, \ 296 .channel2 = IIO_MOD_ ## _mod, \ 297 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ 298 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 299 .address = _mod, \ 300 .scan_index = _index, \ 301 .scan_type = { \ 302 .sign = 'u', \ 303 .realbits = 19, \ 304 .storagebits = 32, \ 305 .endianness = IIO_CPU, \ 306 }, \ 307} 308 309static const struct iio_chan_spec sps30_channels[] = { 310 SPS30_CHAN(0, PM1), 311 SPS30_CHAN(1, PM2P5), 312 SPS30_CHAN(2, PM4), 313 SPS30_CHAN(3, PM10), 314 IIO_CHAN_SOFT_TIMESTAMP(4), 315}; 316 317static void sps30_devm_stop_meas(void *data) 318{ 319 struct sps30_state *state = data; 320 321 if (state->state == MEASURING) 322 state->ops->stop_meas(state); 323} 324 325static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 }; 326 327int sps30_probe(struct device *dev, const char *name, void *priv, const struct sps30_ops *ops) 328{ 329 struct iio_dev *indio_dev; 330 struct sps30_state *state; 331 int ret; 332 333 indio_dev = devm_iio_device_alloc(dev, sizeof(*state)); 334 if (!indio_dev) 335 return -ENOMEM; 336 337 dev_set_drvdata(dev, indio_dev); 338 339 state = iio_priv(indio_dev); 340 state->dev = dev; 341 state->priv = priv; 342 state->ops = ops; 343 mutex_init(&state->lock); 344 345 indio_dev->info = &sps30_info; 346 indio_dev->name = name; 347 indio_dev->channels = sps30_channels; 348 indio_dev->num_channels = ARRAY_SIZE(sps30_channels); 349 indio_dev->modes = INDIO_DIRECT_MODE; 350 indio_dev->available_scan_masks = sps30_scan_masks; 351 352 ret = sps30_do_reset(state); 353 if (ret) { 354 dev_err(dev, "failed to reset device\n"); 355 return ret; 356 } 357 358 ret = state->ops->show_info(state); 359 if (ret) { 360 dev_err(dev, "failed to read device info\n"); 361 return ret; 362 } 363 364 ret = devm_add_action_or_reset(dev, sps30_devm_stop_meas, state); 365 if (ret) 366 return ret; 367 368 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, 369 sps30_trigger_handler, NULL); 370 if (ret) 371 return ret; 372 373 return devm_iio_device_register(dev, indio_dev); 374} 375EXPORT_SYMBOL_GPL(sps30_probe); 376 377MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>"); 378MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver"); 379MODULE_LICENSE("GPL v2");