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/products/sensors/pressure-sensors/board-mount-pressure-sensors/micropressure-mpr-series/documents/sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf |
9 | * |
10 | */ |
11 | |
12 | #include <linux/array_size.h> |
13 | #include <linux/bitfield.h> |
14 | #include <linux/bits.h> |
15 | #include <linux/math64.h> |
16 | #include <linux/mod_devicetable.h> |
17 | #include <linux/module.h> |
18 | #include <linux/property.h> |
19 | #include <linux/units.h> |
20 | |
21 | #include <linux/gpio/consumer.h> |
22 | |
23 | #include <linux/iio/buffer.h> |
24 | #include <linux/iio/trigger_consumer.h> |
25 | #include <linux/iio/triggered_buffer.h> |
26 | |
27 | #include <linux/regulator/consumer.h> |
28 | |
29 | #include <asm/unaligned.h> |
30 | |
31 | #include "mprls0025pa.h" |
32 | |
33 | /* bits in status byte */ |
34 | #define MPR_ST_POWER BIT(6) /* device is powered */ |
35 | #define MPR_ST_BUSY BIT(5) /* device is busy */ |
36 | #define MPR_ST_MEMORY BIT(2) /* integrity test passed */ |
37 | #define MPR_ST_MATH BIT(0) /* internal math saturation */ |
38 | |
39 | #define MPR_ST_ERR_FLAG (MPR_ST_BUSY | MPR_ST_MEMORY | MPR_ST_MATH) |
40 | |
41 | /* |
42 | * support _RAW sysfs interface: |
43 | * |
44 | * Calculation formula from the datasheet: |
45 | * pressure = (press_cnt - outputmin) * scale + pmin |
46 | * with: |
47 | * * pressure - measured pressure in Pascal |
48 | * * press_cnt - raw value read from sensor |
49 | * * pmin - minimum pressure range value of sensor (data->pmin) |
50 | * * pmax - maximum pressure range value of sensor (data->pmax) |
51 | * * outputmin - minimum numerical range raw value delivered by sensor |
52 | * (mpr_func_spec.output_min) |
53 | * * outputmax - maximum numerical range raw value delivered by sensor |
54 | * (mpr_func_spec.output_max) |
55 | * * scale - (pmax - pmin) / (outputmax - outputmin) |
56 | * |
57 | * formula of the userspace: |
58 | * pressure = (raw + offset) * scale |
59 | * |
60 | * Values given to the userspace in sysfs interface: |
61 | * * raw - press_cnt |
62 | * * offset - (-1 * outputmin) - pmin / scale |
63 | * note: With all sensors from the datasheet pmin = 0 |
64 | * which reduces the offset to (-1 * outputmin) |
65 | */ |
66 | |
67 | /* |
68 | * transfer function A: 10% to 90% of 2^24 |
69 | * transfer function B: 2.5% to 22.5% of 2^24 |
70 | * transfer function C: 20% to 80% of 2^24 |
71 | */ |
72 | struct mpr_func_spec { |
73 | u32 output_min; |
74 | u32 output_max; |
75 | }; |
76 | |
77 | static const struct mpr_func_spec mpr_func_spec[] = { |
78 | [MPR_FUNCTION_A] = { .output_min = 1677722, .output_max = 15099494 }, |
79 | [MPR_FUNCTION_B] = { .output_min = 419430, .output_max = 3774874 }, |
80 | [MPR_FUNCTION_C] = { .output_min = 3355443, .output_max = 13421773 }, |
81 | }; |
82 | |
83 | enum mpr_variants { |
84 | MPR0001BA = 0x00, MPR01_6BA = 0x01, MPR02_5BA = 0x02, MPR0060MG = 0x03, |
85 | MPR0100MG = 0x04, MPR0160MG = 0x05, MPR0250MG = 0x06, MPR0400MG = 0x07, |
86 | MPR0600MG = 0x08, MPR0001BG = 0x09, MPR01_6BG = 0x0a, MPR02_5BG = 0x0b, |
87 | MPR0100KA = 0x0c, MPR0160KA = 0x0d, MPR0250KA = 0x0e, MPR0006KG = 0x0f, |
88 | MPR0010KG = 0x10, MPR0016KG = 0x11, MPR0025KG = 0x12, MPR0040KG = 0x13, |
89 | MPR0060KG = 0x14, MPR0100KG = 0x15, MPR0160KG = 0x16, MPR0250KG = 0x17, |
90 | MPR0015PA = 0x18, MPR0025PA = 0x19, MPR0030PA = 0x1a, MPR0001PG = 0x1b, |
91 | MPR0005PG = 0x1c, MPR0015PG = 0x1d, MPR0030PG = 0x1e, MPR0300YG = 0x1f, |
92 | MPR_VARIANTS_MAX |
93 | }; |
94 | |
95 | static const char * const mpr_triplet_variants[MPR_VARIANTS_MAX] = { |
96 | [MPR0001BA] = "0001BA" , [MPR01_6BA] = "01.6BA" , [MPR02_5BA] = "02.5BA" , |
97 | [MPR0060MG] = "0060MG" , [MPR0100MG] = "0100MG" , [MPR0160MG] = "0160MG" , |
98 | [MPR0250MG] = "0250MG" , [MPR0400MG] = "0400MG" , [MPR0600MG] = "0600MG" , |
99 | [MPR0001BG] = "0001BG" , [MPR01_6BG] = "01.6BG" , [MPR02_5BG] = "02.5BG" , |
100 | [MPR0100KA] = "0100KA" , [MPR0160KA] = "0160KA" , [MPR0250KA] = "0250KA" , |
101 | [MPR0006KG] = "0006KG" , [MPR0010KG] = "0010KG" , [MPR0016KG] = "0016KG" , |
102 | [MPR0025KG] = "0025KG" , [MPR0040KG] = "0040KG" , [MPR0060KG] = "0060KG" , |
103 | [MPR0100KG] = "0100KG" , [MPR0160KG] = "0160KG" , [MPR0250KG] = "0250KG" , |
104 | [MPR0015PA] = "0015PA" , [MPR0025PA] = "0025PA" , [MPR0030PA] = "0030PA" , |
105 | [MPR0001PG] = "0001PG" , [MPR0005PG] = "0005PG" , [MPR0015PG] = "0015PG" , |
106 | [MPR0030PG] = "0030PG" , [MPR0300YG] = "0300YG" |
107 | }; |
108 | |
109 | /** |
110 | * struct mpr_range_config - list of pressure ranges based on nomenclature |
111 | * @pmin: lowest pressure that can be measured |
112 | * @pmax: highest pressure that can be measured |
113 | */ |
114 | struct mpr_range_config { |
115 | const s32 pmin; |
116 | const s32 pmax; |
117 | }; |
118 | |
119 | /* All min max limits have been converted to pascals */ |
120 | static const struct mpr_range_config mpr_range_config[MPR_VARIANTS_MAX] = { |
121 | [MPR0001BA] = { .pmin = 0, .pmax = 100000 }, |
122 | [MPR01_6BA] = { .pmin = 0, .pmax = 160000 }, |
123 | [MPR02_5BA] = { .pmin = 0, .pmax = 250000 }, |
124 | [MPR0060MG] = { .pmin = 0, .pmax = 6000 }, |
125 | [MPR0100MG] = { .pmin = 0, .pmax = 10000 }, |
126 | [MPR0160MG] = { .pmin = 0, .pmax = 16000 }, |
127 | [MPR0250MG] = { .pmin = 0, .pmax = 25000 }, |
128 | [MPR0400MG] = { .pmin = 0, .pmax = 40000 }, |
129 | [MPR0600MG] = { .pmin = 0, .pmax = 60000 }, |
130 | [MPR0001BG] = { .pmin = 0, .pmax = 100000 }, |
131 | [MPR01_6BG] = { .pmin = 0, .pmax = 160000 }, |
132 | [MPR02_5BG] = { .pmin = 0, .pmax = 250000 }, |
133 | [MPR0100KA] = { .pmin = 0, .pmax = 100000 }, |
134 | [MPR0160KA] = { .pmin = 0, .pmax = 160000 }, |
135 | [MPR0250KA] = { .pmin = 0, .pmax = 250000 }, |
136 | [MPR0006KG] = { .pmin = 0, .pmax = 6000 }, |
137 | [MPR0010KG] = { .pmin = 0, .pmax = 10000 }, |
138 | [MPR0016KG] = { .pmin = 0, .pmax = 16000 }, |
139 | [MPR0025KG] = { .pmin = 0, .pmax = 25000 }, |
140 | [MPR0040KG] = { .pmin = 0, .pmax = 40000 }, |
141 | [MPR0060KG] = { .pmin = 0, .pmax = 60000 }, |
142 | [MPR0100KG] = { .pmin = 0, .pmax = 100000 }, |
143 | [MPR0160KG] = { .pmin = 0, .pmax = 160000 }, |
144 | [MPR0250KG] = { .pmin = 0, .pmax = 250000 }, |
145 | [MPR0015PA] = { .pmin = 0, .pmax = 103421 }, |
146 | [MPR0025PA] = { .pmin = 0, .pmax = 172369 }, |
147 | [MPR0030PA] = { .pmin = 0, .pmax = 206843 }, |
148 | [MPR0001PG] = { .pmin = 0, .pmax = 6895 }, |
149 | [MPR0005PG] = { .pmin = 0, .pmax = 34474 }, |
150 | [MPR0015PG] = { .pmin = 0, .pmax = 103421 }, |
151 | [MPR0030PG] = { .pmin = 0, .pmax = 206843 }, |
152 | [MPR0300YG] = { .pmin = 0, .pmax = 39997 } |
153 | }; |
154 | |
155 | static const struct iio_chan_spec mpr_channels[] = { |
156 | { |
157 | .type = IIO_PRESSURE, |
158 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
159 | BIT(IIO_CHAN_INFO_SCALE) | |
160 | BIT(IIO_CHAN_INFO_OFFSET), |
161 | .scan_index = 0, |
162 | .scan_type = { |
163 | .sign = 's', |
164 | .realbits = 32, |
165 | .storagebits = 32, |
166 | .endianness = IIO_CPU, |
167 | }, |
168 | }, |
169 | IIO_CHAN_SOFT_TIMESTAMP(1), |
170 | }; |
171 | |
172 | static void mpr_reset(struct mpr_data *data) |
173 | { |
174 | if (data->gpiod_reset) { |
175 | gpiod_set_value(desc: data->gpiod_reset, value: 0); |
176 | udelay(10); |
177 | gpiod_set_value(desc: data->gpiod_reset, value: 1); |
178 | } |
179 | } |
180 | |
181 | /** |
182 | * mpr_read_pressure() - Read pressure value from sensor |
183 | * @data: Pointer to private data struct. |
184 | * @press: Output value read from sensor. |
185 | * |
186 | * Reading from the sensor by sending and receiving telegrams. |
187 | * |
188 | * If there is an end of conversion (EOC) interrupt registered the function |
189 | * waits for a maximum of one second for the interrupt. |
190 | * |
191 | * Context: The function can sleep and data->lock should be held when calling it |
192 | * Return: |
193 | * * 0 - OK, the pressure value could be read |
194 | * * -ETIMEDOUT - Timeout while waiting for the EOC interrupt or busy flag is |
195 | * still set after nloops attempts of reading |
196 | */ |
197 | static int mpr_read_pressure(struct mpr_data *data, s32 *press) |
198 | { |
199 | struct device *dev = data->dev; |
200 | int ret, i; |
201 | int nloops = 10; |
202 | |
203 | reinit_completion(x: &data->completion); |
204 | |
205 | ret = data->ops->write(data, MPR_CMD_SYNC, MPR_PKT_SYNC_LEN); |
206 | if (ret < 0) { |
207 | dev_err(dev, "error while writing ret: %d\n" , ret); |
208 | return ret; |
209 | } |
210 | |
211 | if (data->irq > 0) { |
212 | ret = wait_for_completion_timeout(x: &data->completion, HZ); |
213 | if (!ret) { |
214 | dev_err(dev, "timeout while waiting for eoc irq\n" ); |
215 | return -ETIMEDOUT; |
216 | } |
217 | } else { |
218 | /* wait until status indicates data is ready */ |
219 | for (i = 0; i < nloops; i++) { |
220 | /* |
221 | * datasheet only says to wait at least 5 ms for the |
222 | * data but leave the maximum response time open |
223 | * --> let's try it nloops (10) times which seems to be |
224 | * quite long |
225 | */ |
226 | usleep_range(min: 5000, max: 10000); |
227 | ret = data->ops->read(data, MPR_CMD_NOP, 1); |
228 | if (ret < 0) { |
229 | dev_err(dev, |
230 | "error while reading, status: %d\n" , |
231 | ret); |
232 | return ret; |
233 | } |
234 | if (!(data->buffer[0] & MPR_ST_ERR_FLAG)) |
235 | break; |
236 | } |
237 | if (i == nloops) { |
238 | dev_err(dev, "timeout while reading\n" ); |
239 | return -ETIMEDOUT; |
240 | } |
241 | } |
242 | |
243 | ret = data->ops->read(data, MPR_CMD_NOP, MPR_PKT_NOP_LEN); |
244 | if (ret < 0) |
245 | return ret; |
246 | |
247 | if (data->buffer[0] & MPR_ST_ERR_FLAG) { |
248 | dev_err(data->dev, |
249 | "unexpected status byte %02x\n" , data->buffer[0]); |
250 | return -ETIMEDOUT; |
251 | } |
252 | |
253 | *press = get_unaligned_be24(p: &data->buffer[1]); |
254 | |
255 | dev_dbg(dev, "received: %*ph cnt: %d\n" , ret, data->buffer, *press); |
256 | |
257 | return 0; |
258 | } |
259 | |
260 | static irqreturn_t mpr_eoc_handler(int irq, void *p) |
261 | { |
262 | struct mpr_data *data = p; |
263 | |
264 | complete(&data->completion); |
265 | |
266 | return IRQ_HANDLED; |
267 | } |
268 | |
269 | static irqreturn_t mpr_trigger_handler(int irq, void *p) |
270 | { |
271 | int ret; |
272 | struct iio_poll_func *pf = p; |
273 | struct iio_dev *indio_dev = pf->indio_dev; |
274 | struct mpr_data *data = iio_priv(indio_dev); |
275 | |
276 | mutex_lock(&data->lock); |
277 | ret = mpr_read_pressure(data, press: &data->chan.pres); |
278 | if (ret < 0) |
279 | goto err; |
280 | |
281 | iio_push_to_buffers_with_timestamp(indio_dev, data: &data->chan, |
282 | timestamp: iio_get_time_ns(indio_dev)); |
283 | |
284 | err: |
285 | mutex_unlock(lock: &data->lock); |
286 | iio_trigger_notify_done(trig: indio_dev->trig); |
287 | |
288 | return IRQ_HANDLED; |
289 | } |
290 | |
291 | static int mpr_read_raw(struct iio_dev *indio_dev, |
292 | struct iio_chan_spec const *chan, int *val, int *val2, long mask) |
293 | { |
294 | int ret; |
295 | s32 pressure; |
296 | struct mpr_data *data = iio_priv(indio_dev); |
297 | |
298 | if (chan->type != IIO_PRESSURE) |
299 | return -EINVAL; |
300 | |
301 | switch (mask) { |
302 | case IIO_CHAN_INFO_RAW: |
303 | mutex_lock(&data->lock); |
304 | ret = mpr_read_pressure(data, press: &pressure); |
305 | mutex_unlock(lock: &data->lock); |
306 | if (ret < 0) |
307 | return ret; |
308 | *val = pressure; |
309 | return IIO_VAL_INT; |
310 | case IIO_CHAN_INFO_SCALE: |
311 | *val = data->scale; |
312 | *val2 = data->scale2; |
313 | return IIO_VAL_INT_PLUS_NANO; |
314 | case IIO_CHAN_INFO_OFFSET: |
315 | *val = data->offset; |
316 | *val2 = data->offset2; |
317 | return IIO_VAL_INT_PLUS_NANO; |
318 | default: |
319 | return -EINVAL; |
320 | } |
321 | } |
322 | |
323 | static const struct iio_info mpr_info = { |
324 | .read_raw = &mpr_read_raw, |
325 | }; |
326 | |
327 | int mpr_common_probe(struct device *dev, const struct mpr_ops *ops, int irq) |
328 | { |
329 | int ret; |
330 | struct mpr_data *data; |
331 | struct iio_dev *indio_dev; |
332 | const char *triplet; |
333 | s64 scale, offset; |
334 | u32 func; |
335 | |
336 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*data)); |
337 | if (!indio_dev) |
338 | return -ENOMEM; |
339 | |
340 | data = iio_priv(indio_dev); |
341 | data->dev = dev; |
342 | data->ops = ops; |
343 | data->irq = irq; |
344 | |
345 | mutex_init(&data->lock); |
346 | init_completion(x: &data->completion); |
347 | |
348 | indio_dev->name = "mprls0025pa" ; |
349 | indio_dev->info = &mpr_info; |
350 | indio_dev->channels = mpr_channels; |
351 | indio_dev->num_channels = ARRAY_SIZE(mpr_channels); |
352 | indio_dev->modes = INDIO_DIRECT_MODE; |
353 | |
354 | ret = devm_regulator_get_enable(dev, id: "vdd" ); |
355 | if (ret) |
356 | return dev_err_probe(dev, err: ret, |
357 | fmt: "can't get and enable vdd supply\n" ); |
358 | |
359 | ret = data->ops->init(data->dev); |
360 | if (ret) |
361 | return ret; |
362 | |
363 | ret = device_property_read_u32(dev, |
364 | propname: "honeywell,transfer-function" , val: &func); |
365 | if (ret) |
366 | return dev_err_probe(dev, err: ret, |
367 | fmt: "honeywell,transfer-function could not be read\n" ); |
368 | data->function = func - 1; |
369 | if (data->function > MPR_FUNCTION_C) |
370 | return dev_err_probe(dev, err: -EINVAL, |
371 | fmt: "honeywell,transfer-function %d invalid\n" , |
372 | data->function); |
373 | |
374 | ret = device_property_read_string(dev, propname: "honeywell,pressure-triplet" , |
375 | val: &triplet); |
376 | if (ret) { |
377 | ret = device_property_read_u32(dev, propname: "honeywell,pmin-pascal" , |
378 | val: &data->pmin); |
379 | if (ret) |
380 | return dev_err_probe(dev, err: ret, |
381 | fmt: "honeywell,pmin-pascal could not be read\n" ); |
382 | |
383 | ret = device_property_read_u32(dev, propname: "honeywell,pmax-pascal" , |
384 | val: &data->pmax); |
385 | if (ret) |
386 | return dev_err_probe(dev, err: ret, |
387 | fmt: "honeywell,pmax-pascal could not be read\n" ); |
388 | } else { |
389 | ret = device_property_match_property_string(dev, |
390 | propname: "honeywell,pressure-triplet" , |
391 | array: mpr_triplet_variants, |
392 | n: MPR_VARIANTS_MAX); |
393 | if (ret < 0) |
394 | return dev_err_probe(dev, err: -EINVAL, |
395 | fmt: "honeywell,pressure-triplet is invalid\n" ); |
396 | |
397 | data->pmin = mpr_range_config[ret].pmin; |
398 | data->pmax = mpr_range_config[ret].pmax; |
399 | } |
400 | |
401 | if (data->pmin >= data->pmax) |
402 | return dev_err_probe(dev, err: -EINVAL, |
403 | fmt: "pressure limits are invalid\n" ); |
404 | |
405 | data->outmin = mpr_func_spec[data->function].output_min; |
406 | data->outmax = mpr_func_spec[data->function].output_max; |
407 | |
408 | /* use 64 bit calculation for preserving a reasonable precision */ |
409 | scale = div_s64(dividend: ((s64)(data->pmax - data->pmin)) * NANO, |
410 | divisor: data->outmax - data->outmin); |
411 | data->scale = div_s64_rem(dividend: scale, NANO, remainder: &data->scale2); |
412 | /* |
413 | * multiply with NANO before dividing by scale and later divide by NANO |
414 | * again. |
415 | */ |
416 | offset = ((-1LL) * (s64)data->outmin) * NANO - |
417 | div_s64(dividend: div_s64(dividend: (s64)data->pmin * NANO, divisor: scale), NANO); |
418 | data->offset = div_s64_rem(dividend: offset, NANO, remainder: &data->offset2); |
419 | |
420 | if (data->irq > 0) { |
421 | ret = devm_request_irq(dev, irq: data->irq, handler: mpr_eoc_handler, |
422 | IRQF_TRIGGER_RISING, |
423 | devname: dev_name(dev), |
424 | dev_id: data); |
425 | if (ret) |
426 | return dev_err_probe(dev, err: ret, |
427 | fmt: "request irq %d failed\n" , data->irq); |
428 | } |
429 | |
430 | data->gpiod_reset = devm_gpiod_get_optional(dev, con_id: "reset" , |
431 | flags: GPIOD_OUT_HIGH); |
432 | if (IS_ERR(ptr: data->gpiod_reset)) |
433 | return dev_err_probe(dev, err: PTR_ERR(ptr: data->gpiod_reset), |
434 | fmt: "request reset-gpio failed\n" ); |
435 | |
436 | mpr_reset(data); |
437 | |
438 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, |
439 | mpr_trigger_handler, NULL); |
440 | if (ret) |
441 | return dev_err_probe(dev, err: ret, |
442 | fmt: "iio triggered buffer setup failed\n" ); |
443 | |
444 | ret = devm_iio_device_register(dev, indio_dev); |
445 | if (ret) |
446 | return dev_err_probe(dev, err: ret, |
447 | fmt: "unable to register iio device\n" ); |
448 | |
449 | return 0; |
450 | } |
451 | EXPORT_SYMBOL_NS(mpr_common_probe, IIO_HONEYWELL_MPRLS0025PA); |
452 | |
453 | MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>" ); |
454 | MODULE_DESCRIPTION("Honeywell MPR pressure sensor core driver" ); |
455 | MODULE_LICENSE("GPL" ); |
456 | |