Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: pressure: Honeywell mprls0025pa pressure sensor

Honeywell mprls0025pa is a series of pressure sensors.

Add initial I2C support.

Note:
- IIO buffered mode is supported
- SPI mode is not supported

Signed-off-by: Andreas Klinger <ak@it-klinger.de>
Link: https://lore.kernel.org/r/ZGNp3SqyOJeEcLsj@arbad
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Andreas Klinger and committed by
Jonathan Cameron
713337d9 a765c985

+464
+13
drivers/iio/pressure/Kconfig
··· 148 148 To compile this driver as a module, choose M here: the module 149 149 will be called mpl3115. 150 150 151 + config MPRLS0025PA 152 + tristate "Honeywell MPRLS0025PA (MicroPressure sensors series)" 153 + depends on I2C 154 + select IIO_BUFFER 155 + select IIO_TRIGGERED_BUFFER 156 + help 157 + Say Y here to build support for the Honeywell MicroPressure pressure 158 + sensor series. There are many different types with different pressure 159 + range. These ranges can be set up in the device tree. 160 + 161 + To compile this driver as a module, choose M here: the module will be 162 + called mprls0025pa. 163 + 151 164 config MS5611 152 165 tristate "Measurement Specialties MS5611 pressure sensor driver" 153 166 select IIO_BUFFER
+1
drivers/iio/pressure/Makefile
··· 19 19 obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o 20 20 obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o 21 21 obj-$(CONFIG_MPL3115) += mpl3115.o 22 + obj-$(CONFIG_MPRLS0025PA) += mprls0025pa.o 22 23 obj-$(CONFIG_MS5611) += ms5611_core.o 23 24 obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o 24 25 obj-$(CONFIG_MS5611_SPI) += ms5611_spi.o
+450
drivers/iio/pressure/mprls0025pa.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * MPRLS0025PA - Honeywell MicroPressure pressure sensor series driver 4 + * 5 + * Copyright (c) Andreas Klinger <ak@it-klinger.de> 6 + * 7 + * Data sheet: 8 + * https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/ 9 + * products/sensors/pressure-sensors/board-mount-pressure-sensors/ 10 + * micropressure-mpr-series/documents/ 11 + * sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf 12 + * 13 + * 7-bit I2C default slave address: 0x18 14 + */ 15 + 16 + #include <linux/delay.h> 17 + #include <linux/device.h> 18 + #include <linux/i2c.h> 19 + #include <linux/math64.h> 20 + #include <linux/mod_devicetable.h> 21 + #include <linux/module.h> 22 + #include <linux/property.h> 23 + #include <linux/units.h> 24 + 25 + #include <linux/gpio/consumer.h> 26 + 27 + #include <linux/iio/buffer.h> 28 + #include <linux/iio/iio.h> 29 + #include <linux/iio/trigger_consumer.h> 30 + #include <linux/iio/triggered_buffer.h> 31 + 32 + #include <linux/regulator/consumer.h> 33 + 34 + #include <asm/unaligned.h> 35 + 36 + /* bits in i2c status byte */ 37 + #define MPR_I2C_POWER BIT(6) /* device is powered */ 38 + #define MPR_I2C_BUSY BIT(5) /* device is busy */ 39 + #define MPR_I2C_MEMORY BIT(2) /* integrity test passed */ 40 + #define MPR_I2C_MATH BIT(0) /* internal math saturation */ 41 + 42 + /* 43 + * support _RAW sysfs interface: 44 + * 45 + * Calculation formula from the datasheet: 46 + * pressure = (press_cnt - outputmin) * scale + pmin 47 + * with: 48 + * * pressure - measured pressure in Pascal 49 + * * press_cnt - raw value read from sensor 50 + * * pmin - minimum pressure range value of sensor (data->pmin) 51 + * * pmax - maximum pressure range value of sensor (data->pmax) 52 + * * outputmin - minimum numerical range raw value delivered by sensor 53 + * (mpr_func_spec.output_min) 54 + * * outputmax - maximum numerical range raw value delivered by sensor 55 + * (mpr_func_spec.output_max) 56 + * * scale - (pmax - pmin) / (outputmax - outputmin) 57 + * 58 + * formula of the userspace: 59 + * pressure = (raw + offset) * scale 60 + * 61 + * Values given to the userspace in sysfs interface: 62 + * * raw - press_cnt 63 + * * offset - (-1 * outputmin) - pmin / scale 64 + * note: With all sensors from the datasheet pmin = 0 65 + * which reduces the offset to (-1 * outputmin) 66 + */ 67 + 68 + /* 69 + * transfer function A: 10% to 90% of 2^24 70 + * transfer function B: 2.5% to 22.5% of 2^24 71 + * transfer function C: 20% to 80% of 2^24 72 + */ 73 + enum mpr_func_id { 74 + MPR_FUNCTION_A, 75 + MPR_FUNCTION_B, 76 + MPR_FUNCTION_C, 77 + }; 78 + 79 + struct mpr_func_spec { 80 + u32 output_min; 81 + u32 output_max; 82 + }; 83 + 84 + static const struct mpr_func_spec mpr_func_spec[] = { 85 + [MPR_FUNCTION_A] = {.output_min = 1677722, .output_max = 15099494}, 86 + [MPR_FUNCTION_B] = {.output_min = 419430, .output_max = 3774874}, 87 + [MPR_FUNCTION_C] = {.output_min = 3355443, .output_max = 13421773}, 88 + }; 89 + 90 + struct mpr_chan { 91 + s32 pres; /* pressure value */ 92 + s64 ts; /* timestamp */ 93 + }; 94 + 95 + struct mpr_data { 96 + struct i2c_client *client; 97 + struct mutex lock; /* 98 + * access to device during read 99 + */ 100 + u32 pmin; /* minimal pressure in pascal */ 101 + u32 pmax; /* maximal pressure in pascal */ 102 + enum mpr_func_id function; /* transfer function */ 103 + u32 outmin; /* 104 + * minimal numerical range raw 105 + * value from sensor 106 + */ 107 + u32 outmax; /* 108 + * maximal numerical range raw 109 + * value from sensor 110 + */ 111 + int scale; /* int part of scale */ 112 + int scale2; /* nano part of scale */ 113 + int offset; /* int part of offset */ 114 + int offset2; /* nano part of offset */ 115 + struct gpio_desc *gpiod_reset; /* reset */ 116 + int irq; /* 117 + * end of conversion irq; 118 + * used to distinguish between 119 + * irq mode and reading in a 120 + * loop until data is ready 121 + */ 122 + struct completion completion; /* handshake from irq to read */ 123 + struct mpr_chan chan; /* 124 + * channel values for buffered 125 + * mode 126 + */ 127 + }; 128 + 129 + static const struct iio_chan_spec mpr_channels[] = { 130 + { 131 + .type = IIO_PRESSURE, 132 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 133 + BIT(IIO_CHAN_INFO_SCALE) | 134 + BIT(IIO_CHAN_INFO_OFFSET), 135 + .scan_index = 0, 136 + .scan_type = { 137 + .sign = 's', 138 + .realbits = 32, 139 + .storagebits = 32, 140 + .endianness = IIO_CPU, 141 + }, 142 + }, 143 + IIO_CHAN_SOFT_TIMESTAMP(1), 144 + }; 145 + 146 + static void mpr_reset(struct mpr_data *data) 147 + { 148 + if (data->gpiod_reset) { 149 + gpiod_set_value(data->gpiod_reset, 0); 150 + udelay(10); 151 + gpiod_set_value(data->gpiod_reset, 1); 152 + } 153 + } 154 + 155 + /** 156 + * mpr_read_pressure() - Read pressure value from sensor via I2C 157 + * @data: Pointer to private data struct. 158 + * @press: Output value read from sensor. 159 + * 160 + * Reading from the sensor by sending and receiving I2C telegrams. 161 + * 162 + * If there is an end of conversion (EOC) interrupt registered the function 163 + * waits for a maximum of one second for the interrupt. 164 + * 165 + * Context: The function can sleep and data->lock should be held when calling it 166 + * Return: 167 + * * 0 - OK, the pressure value could be read 168 + * * -ETIMEDOUT - Timeout while waiting for the EOC interrupt or busy flag is 169 + * still set after nloops attempts of reading 170 + */ 171 + static int mpr_read_pressure(struct mpr_data *data, s32 *press) 172 + { 173 + struct device *dev = &data->client->dev; 174 + int ret, i; 175 + u8 wdata[] = {0xAA, 0x00, 0x00}; 176 + s32 status; 177 + int nloops = 10; 178 + u8 buf[4]; 179 + 180 + reinit_completion(&data->completion); 181 + 182 + ret = i2c_master_send(data->client, wdata, sizeof(wdata)); 183 + if (ret < 0) { 184 + dev_err(dev, "error while writing ret: %d\n", ret); 185 + return ret; 186 + } 187 + if (ret != sizeof(wdata)) { 188 + dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret, 189 + (u32)sizeof(wdata)); 190 + return -EIO; 191 + } 192 + 193 + if (data->irq > 0) { 194 + ret = wait_for_completion_timeout(&data->completion, HZ); 195 + if (!ret) { 196 + dev_err(dev, "timeout while waiting for eoc irq\n"); 197 + return -ETIMEDOUT; 198 + } 199 + } else { 200 + /* wait until status indicates data is ready */ 201 + for (i = 0; i < nloops; i++) { 202 + /* 203 + * datasheet only says to wait at least 5 ms for the 204 + * data but leave the maximum response time open 205 + * --> let's try it nloops (10) times which seems to be 206 + * quite long 207 + */ 208 + usleep_range(5000, 10000); 209 + status = i2c_smbus_read_byte(data->client); 210 + if (status < 0) { 211 + dev_err(dev, 212 + "error while reading, status: %d\n", 213 + status); 214 + return status; 215 + } 216 + if (!(status & MPR_I2C_BUSY)) 217 + break; 218 + } 219 + if (i == nloops) { 220 + dev_err(dev, "timeout while reading\n"); 221 + return -ETIMEDOUT; 222 + } 223 + } 224 + 225 + ret = i2c_master_recv(data->client, buf, sizeof(buf)); 226 + if (ret < 0) { 227 + dev_err(dev, "error in i2c_master_recv ret: %d\n", ret); 228 + return ret; 229 + } 230 + if (ret != sizeof(buf)) { 231 + dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret, 232 + (u32)sizeof(buf)); 233 + return -EIO; 234 + } 235 + 236 + if (buf[0] & MPR_I2C_BUSY) { 237 + /* 238 + * it should never be the case that status still indicates 239 + * business 240 + */ 241 + dev_err(dev, "data still not ready: %08x\n", buf[0]); 242 + return -ETIMEDOUT; 243 + } 244 + 245 + *press = get_unaligned_be24(&buf[1]); 246 + 247 + dev_dbg(dev, "received: %*ph cnt: %d\n", ret, buf, *press); 248 + 249 + return 0; 250 + } 251 + 252 + static irqreturn_t mpr_eoc_handler(int irq, void *p) 253 + { 254 + struct mpr_data *data = p; 255 + 256 + complete(&data->completion); 257 + 258 + return IRQ_HANDLED; 259 + } 260 + 261 + static irqreturn_t mpr_trigger_handler(int irq, void *p) 262 + { 263 + int ret; 264 + struct iio_poll_func *pf = p; 265 + struct iio_dev *indio_dev = pf->indio_dev; 266 + struct mpr_data *data = iio_priv(indio_dev); 267 + 268 + mutex_lock(&data->lock); 269 + ret = mpr_read_pressure(data, &data->chan.pres); 270 + if (ret < 0) 271 + goto err; 272 + 273 + iio_push_to_buffers_with_timestamp(indio_dev, &data->chan, 274 + iio_get_time_ns(indio_dev)); 275 + 276 + err: 277 + mutex_unlock(&data->lock); 278 + iio_trigger_notify_done(indio_dev->trig); 279 + 280 + return IRQ_HANDLED; 281 + } 282 + 283 + static int mpr_read_raw(struct iio_dev *indio_dev, 284 + struct iio_chan_spec const *chan, int *val, int *val2, long mask) 285 + { 286 + int ret; 287 + s32 pressure; 288 + struct mpr_data *data = iio_priv(indio_dev); 289 + 290 + if (chan->type != IIO_PRESSURE) 291 + return -EINVAL; 292 + 293 + switch (mask) { 294 + case IIO_CHAN_INFO_RAW: 295 + mutex_lock(&data->lock); 296 + ret = mpr_read_pressure(data, &pressure); 297 + mutex_unlock(&data->lock); 298 + if (ret < 0) 299 + return ret; 300 + *val = pressure; 301 + return IIO_VAL_INT; 302 + case IIO_CHAN_INFO_SCALE: 303 + *val = data->scale; 304 + *val2 = data->scale2; 305 + return IIO_VAL_INT_PLUS_NANO; 306 + case IIO_CHAN_INFO_OFFSET: 307 + *val = data->offset; 308 + *val2 = data->offset2; 309 + return IIO_VAL_INT_PLUS_NANO; 310 + default: 311 + return -EINVAL; 312 + } 313 + } 314 + 315 + static const struct iio_info mpr_info = { 316 + .read_raw = &mpr_read_raw, 317 + }; 318 + 319 + static int mpr_probe(struct i2c_client *client) 320 + { 321 + int ret; 322 + struct mpr_data *data; 323 + struct iio_dev *indio_dev; 324 + struct device *dev = &client->dev; 325 + s64 scale, offset; 326 + 327 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) 328 + return dev_err_probe(dev, -EOPNOTSUPP, 329 + "I2C functionality not supported\n"); 330 + 331 + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 332 + if (!indio_dev) 333 + return dev_err_probe(dev, -ENOMEM, "couldn't get iio_dev\n"); 334 + 335 + data = iio_priv(indio_dev); 336 + data->client = client; 337 + data->irq = client->irq; 338 + 339 + mutex_init(&data->lock); 340 + init_completion(&data->completion); 341 + 342 + indio_dev->name = "mprls0025pa"; 343 + indio_dev->info = &mpr_info; 344 + indio_dev->channels = mpr_channels; 345 + indio_dev->num_channels = ARRAY_SIZE(mpr_channels); 346 + indio_dev->modes = INDIO_DIRECT_MODE; 347 + 348 + ret = devm_regulator_get_enable(dev, "vdd"); 349 + if (ret) 350 + return dev_err_probe(dev, ret, 351 + "can't get and enable vdd supply\n"); 352 + 353 + if (dev_fwnode(dev)) { 354 + ret = device_property_read_u32(dev, "honeywell,pmin-pascal", 355 + &data->pmin); 356 + if (ret) 357 + return dev_err_probe(dev, ret, 358 + "honeywell,pmin-pascal could not be read\n"); 359 + ret = device_property_read_u32(dev, "honeywell,pmax-pascal", 360 + &data->pmax); 361 + if (ret) 362 + return dev_err_probe(dev, ret, 363 + "honeywell,pmax-pascal could not be read\n"); 364 + ret = device_property_read_u32(dev, 365 + "honeywell,transfer-function", &data->function); 366 + if (ret) 367 + return dev_err_probe(dev, ret, 368 + "honeywell,transfer-function could not be read\n"); 369 + if (data->function > MPR_FUNCTION_C) 370 + return dev_err_probe(dev, -EINVAL, 371 + "honeywell,transfer-function %d invalid\n", 372 + data->function); 373 + } else { 374 + /* when loaded as i2c device we need to use default values */ 375 + dev_notice(dev, "firmware node not found; using defaults\n"); 376 + data->pmin = 0; 377 + data->pmax = 172369; /* 25 psi */ 378 + data->function = MPR_FUNCTION_A; 379 + } 380 + 381 + data->outmin = mpr_func_spec[data->function].output_min; 382 + data->outmax = mpr_func_spec[data->function].output_max; 383 + 384 + /* use 64 bit calculation for preserving a reasonable precision */ 385 + scale = div_s64(((s64)(data->pmax - data->pmin)) * NANO, 386 + data->outmax - data->outmin); 387 + data->scale = div_s64_rem(scale, NANO, &data->scale2); 388 + /* 389 + * multiply with NANO before dividing by scale and later divide by NANO 390 + * again. 391 + */ 392 + offset = ((-1LL) * (s64)data->outmin) * NANO - 393 + div_s64(div_s64((s64)data->pmin * NANO, scale), NANO); 394 + data->offset = div_s64_rem(offset, NANO, &data->offset2); 395 + 396 + if (data->irq > 0) { 397 + ret = devm_request_irq(dev, data->irq, mpr_eoc_handler, 398 + IRQF_TRIGGER_RISING, client->name, data); 399 + if (ret) 400 + return dev_err_probe(dev, ret, 401 + "request irq %d failed\n", data->irq); 402 + } 403 + 404 + data->gpiod_reset = devm_gpiod_get_optional(dev, "reset", 405 + GPIOD_OUT_HIGH); 406 + if (IS_ERR(data->gpiod_reset)) 407 + return dev_err_probe(dev, PTR_ERR(data->gpiod_reset), 408 + "request reset-gpio failed\n"); 409 + 410 + mpr_reset(data); 411 + 412 + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, 413 + mpr_trigger_handler, NULL); 414 + if (ret) 415 + return dev_err_probe(dev, ret, 416 + "iio triggered buffer setup failed\n"); 417 + 418 + ret = devm_iio_device_register(dev, indio_dev); 419 + if (ret) 420 + return dev_err_probe(dev, ret, 421 + "unable to register iio device\n"); 422 + 423 + return 0; 424 + } 425 + 426 + static const struct of_device_id mpr_matches[] = { 427 + { .compatible = "honeywell,mprls0025pa" }, 428 + { } 429 + }; 430 + MODULE_DEVICE_TABLE(of, mpr_matches); 431 + 432 + static const struct i2c_device_id mpr_id[] = { 433 + { "mprls0025pa" }, 434 + { } 435 + }; 436 + MODULE_DEVICE_TABLE(i2c, mpr_id); 437 + 438 + static struct i2c_driver mpr_driver = { 439 + .probe = mpr_probe, 440 + .id_table = mpr_id, 441 + .driver = { 442 + .name = "mprls0025pa", 443 + .of_match_table = mpr_matches, 444 + }, 445 + }; 446 + module_i2c_driver(mpr_driver); 447 + 448 + MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>"); 449 + MODULE_DESCRIPTION("Honeywell MPRLS0025PA I2C driver"); 450 + MODULE_LICENSE("GPL");