1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Driver for Murata IRS-D200 PIR sensor. |
4 | * |
5 | * Copyright (C) 2023 Axis Communications AB |
6 | */ |
7 | |
8 | #include <asm/unaligned.h> |
9 | #include <linux/bitfield.h> |
10 | #include <linux/i2c.h> |
11 | #include <linux/module.h> |
12 | #include <linux/regmap.h> |
13 | |
14 | #include <linux/iio/buffer.h> |
15 | #include <linux/iio/events.h> |
16 | #include <linux/iio/iio.h> |
17 | #include <linux/iio/trigger.h> |
18 | #include <linux/iio/trigger_consumer.h> |
19 | #include <linux/iio/triggered_buffer.h> |
20 | #include <linux/iio/types.h> |
21 | |
22 | #define IRS_DRV_NAME "irsd200" |
23 | |
24 | /* Registers. */ |
25 | #define IRS_REG_OP 0x00 /* Operation mode. */ |
26 | #define IRS_REG_DATA_LO 0x02 /* Sensor data LSB. */ |
27 | #define IRS_REG_DATA_HI 0x03 /* Sensor data MSB. */ |
28 | #define IRS_REG_STATUS 0x04 /* Interrupt status. */ |
29 | #define IRS_REG_COUNT 0x05 /* Count of exceeding threshold. */ |
30 | #define IRS_REG_DATA_RATE 0x06 /* Output data rate. */ |
31 | #define IRS_REG_FILTER 0x07 /* High-pass and low-pass filter. */ |
32 | #define IRS_REG_INTR 0x09 /* Interrupt mode. */ |
33 | #define IRS_REG_NR_COUNT 0x0a /* Number of counts before interrupt. */ |
34 | #define IRS_REG_THR_HI 0x0b /* Upper threshold. */ |
35 | #define IRS_REG_THR_LO 0x0c /* Lower threshold. */ |
36 | #define IRS_REG_TIMER_LO 0x0d /* Timer setting LSB. */ |
37 | #define IRS_REG_TIMER_HI 0x0e /* Timer setting MSB. */ |
38 | |
39 | /* Interrupt status bits. */ |
40 | #define IRS_INTR_DATA 0 /* Data update. */ |
41 | #define IRS_INTR_TIMER 1 /* Timer expiration. */ |
42 | #define IRS_INTR_COUNT_THR_AND 2 /* Count "AND" threshold. */ |
43 | #define IRS_INTR_COUNT_THR_OR 3 /* Count "OR" threshold. */ |
44 | |
45 | /* Operation states. */ |
46 | #define IRS_OP_ACTIVE 0x00 |
47 | #define IRS_OP_SLEEP 0x01 |
48 | |
49 | /* |
50 | * Quantization scale value for threshold. Used for conversion from/to register |
51 | * value. |
52 | */ |
53 | #define IRS_THR_QUANT_SCALE 128 |
54 | |
55 | #define IRS_UPPER_COUNT(count) FIELD_GET(GENMASK(7, 4), count) |
56 | #define IRS_LOWER_COUNT(count) FIELD_GET(GENMASK(3, 0), count) |
57 | |
58 | /* Index corresponds to the value of IRS_REG_DATA_RATE register. */ |
59 | static const int irsd200_data_rates[] = { |
60 | 50, |
61 | 100, |
62 | }; |
63 | |
64 | /* Index corresponds to the (field) value of IRS_REG_FILTER register. */ |
65 | static const unsigned int irsd200_lp_filter_freq[] = { |
66 | 10, |
67 | 7, |
68 | }; |
69 | |
70 | /* |
71 | * Index corresponds to the (field) value of IRS_REG_FILTER register. Note that |
72 | * this represents a fractional value (e.g the first value corresponds to 3 / 10 |
73 | * = 0.3 Hz). |
74 | */ |
75 | static const unsigned int irsd200_hp_filter_freq[][2] = { |
76 | { 3, 10 }, |
77 | { 5, 10 }, |
78 | }; |
79 | |
80 | /* Register fields. */ |
81 | enum irsd200_regfield { |
82 | /* Data interrupt. */ |
83 | IRS_REGF_INTR_DATA, |
84 | /* Timer interrupt. */ |
85 | IRS_REGF_INTR_TIMER, |
86 | /* AND count threshold interrupt. */ |
87 | IRS_REGF_INTR_COUNT_THR_AND, |
88 | /* OR count threshold interrupt. */ |
89 | IRS_REGF_INTR_COUNT_THR_OR, |
90 | |
91 | /* Low-pass filter frequency. */ |
92 | IRS_REGF_LP_FILTER, |
93 | /* High-pass filter frequency. */ |
94 | IRS_REGF_HP_FILTER, |
95 | |
96 | /* Sentinel value. */ |
97 | IRS_REGF_MAX |
98 | }; |
99 | |
100 | static const struct reg_field irsd200_regfields[] = { |
101 | [IRS_REGF_INTR_DATA] = |
102 | REG_FIELD(IRS_REG_INTR, IRS_INTR_DATA, IRS_INTR_DATA), |
103 | [IRS_REGF_INTR_TIMER] = |
104 | REG_FIELD(IRS_REG_INTR, IRS_INTR_TIMER, IRS_INTR_TIMER), |
105 | [IRS_REGF_INTR_COUNT_THR_AND] = REG_FIELD( |
106 | IRS_REG_INTR, IRS_INTR_COUNT_THR_AND, IRS_INTR_COUNT_THR_AND), |
107 | [IRS_REGF_INTR_COUNT_THR_OR] = REG_FIELD( |
108 | IRS_REG_INTR, IRS_INTR_COUNT_THR_OR, IRS_INTR_COUNT_THR_OR), |
109 | |
110 | [IRS_REGF_LP_FILTER] = REG_FIELD(IRS_REG_FILTER, 1, 1), |
111 | [IRS_REGF_HP_FILTER] = REG_FIELD(IRS_REG_FILTER, 0, 0), |
112 | }; |
113 | |
114 | static const struct regmap_config irsd200_regmap_config = { |
115 | .reg_bits = 8, |
116 | .val_bits = 8, |
117 | .max_register = IRS_REG_TIMER_HI, |
118 | }; |
119 | |
120 | struct irsd200_data { |
121 | struct regmap *regmap; |
122 | struct regmap_field *regfields[IRS_REGF_MAX]; |
123 | struct device *dev; |
124 | }; |
125 | |
126 | static int irsd200_setup(struct irsd200_data *data) |
127 | { |
128 | unsigned int val; |
129 | int ret; |
130 | |
131 | /* Disable all interrupt sources. */ |
132 | ret = regmap_write(map: data->regmap, IRS_REG_INTR, val: 0); |
133 | if (ret) { |
134 | dev_err(data->dev, "Could not set interrupt sources (%d)\n" , |
135 | ret); |
136 | return ret; |
137 | } |
138 | |
139 | /* Set operation to active. */ |
140 | ret = regmap_write(map: data->regmap, IRS_REG_OP, IRS_OP_ACTIVE); |
141 | if (ret) { |
142 | dev_err(data->dev, "Could not set operation mode (%d)\n" , ret); |
143 | return ret; |
144 | } |
145 | |
146 | /* Clear threshold count. */ |
147 | ret = regmap_read(map: data->regmap, IRS_REG_COUNT, val: &val); |
148 | if (ret) { |
149 | dev_err(data->dev, "Could not clear threshold count (%d)\n" , |
150 | ret); |
151 | return ret; |
152 | } |
153 | |
154 | /* Clear status. */ |
155 | ret = regmap_write(map: data->regmap, IRS_REG_STATUS, val: 0x0f); |
156 | if (ret) { |
157 | dev_err(data->dev, "Could not clear status (%d)\n" , ret); |
158 | return ret; |
159 | } |
160 | |
161 | return 0; |
162 | } |
163 | |
164 | static int irsd200_read_threshold(struct irsd200_data *data, |
165 | enum iio_event_direction dir, int *val) |
166 | { |
167 | unsigned int regval; |
168 | unsigned int reg; |
169 | int scale; |
170 | int ret; |
171 | |
172 | /* Set quantization scale. */ |
173 | if (dir == IIO_EV_DIR_RISING) { |
174 | scale = IRS_THR_QUANT_SCALE; |
175 | reg = IRS_REG_THR_HI; |
176 | } else if (dir == IIO_EV_DIR_FALLING) { |
177 | scale = -IRS_THR_QUANT_SCALE; |
178 | reg = IRS_REG_THR_LO; |
179 | } else { |
180 | return -EINVAL; |
181 | } |
182 | |
183 | ret = regmap_read(map: data->regmap, reg, val: ®val); |
184 | if (ret) { |
185 | dev_err(data->dev, "Could not read threshold (%d)\n" , ret); |
186 | return ret; |
187 | } |
188 | |
189 | *val = ((int)regval) * scale; |
190 | |
191 | return 0; |
192 | } |
193 | |
194 | static int irsd200_write_threshold(struct irsd200_data *data, |
195 | enum iio_event_direction dir, int val) |
196 | { |
197 | unsigned int regval; |
198 | unsigned int reg; |
199 | int scale; |
200 | int ret; |
201 | |
202 | /* Set quantization scale. */ |
203 | if (dir == IIO_EV_DIR_RISING) { |
204 | if (val < 0) |
205 | return -ERANGE; |
206 | |
207 | scale = IRS_THR_QUANT_SCALE; |
208 | reg = IRS_REG_THR_HI; |
209 | } else if (dir == IIO_EV_DIR_FALLING) { |
210 | if (val > 0) |
211 | return -ERANGE; |
212 | |
213 | scale = -IRS_THR_QUANT_SCALE; |
214 | reg = IRS_REG_THR_LO; |
215 | } else { |
216 | return -EINVAL; |
217 | } |
218 | |
219 | regval = val / scale; |
220 | |
221 | if (regval >= BIT(8)) |
222 | return -ERANGE; |
223 | |
224 | ret = regmap_write(map: data->regmap, reg, val: regval); |
225 | if (ret) { |
226 | dev_err(data->dev, "Could not write threshold (%d)\n" , ret); |
227 | return ret; |
228 | } |
229 | |
230 | return 0; |
231 | } |
232 | |
233 | static int irsd200_read_data(struct irsd200_data *data, s16 *val) |
234 | { |
235 | __le16 buf; |
236 | int ret; |
237 | |
238 | ret = regmap_bulk_read(map: data->regmap, IRS_REG_DATA_LO, val: &buf, |
239 | val_count: sizeof(buf)); |
240 | if (ret) { |
241 | dev_err(data->dev, "Could not bulk read data (%d)\n" , ret); |
242 | return ret; |
243 | } |
244 | |
245 | *val = le16_to_cpu(buf); |
246 | |
247 | return 0; |
248 | } |
249 | |
250 | static int irsd200_read_data_rate(struct irsd200_data *data, int *val) |
251 | { |
252 | unsigned int regval; |
253 | int ret; |
254 | |
255 | ret = regmap_read(map: data->regmap, IRS_REG_DATA_RATE, val: ®val); |
256 | if (ret) { |
257 | dev_err(data->dev, "Could not read data rate (%d)\n" , ret); |
258 | return ret; |
259 | } |
260 | |
261 | if (regval >= ARRAY_SIZE(irsd200_data_rates)) |
262 | return -ERANGE; |
263 | |
264 | *val = irsd200_data_rates[regval]; |
265 | |
266 | return 0; |
267 | } |
268 | |
269 | static int irsd200_write_data_rate(struct irsd200_data *data, int val) |
270 | { |
271 | size_t idx; |
272 | int ret; |
273 | |
274 | for (idx = 0; idx < ARRAY_SIZE(irsd200_data_rates); ++idx) { |
275 | if (irsd200_data_rates[idx] == val) |
276 | break; |
277 | } |
278 | |
279 | if (idx == ARRAY_SIZE(irsd200_data_rates)) |
280 | return -ERANGE; |
281 | |
282 | ret = regmap_write(map: data->regmap, IRS_REG_DATA_RATE, val: idx); |
283 | if (ret) { |
284 | dev_err(data->dev, "Could not write data rate (%d)\n" , ret); |
285 | return ret; |
286 | } |
287 | |
288 | /* |
289 | * Data sheet says the device needs 3 seconds of settling time. The |
290 | * device operates normally during this period though. This is more of a |
291 | * "guarantee" than trying to prevent other user space reads/writes. |
292 | */ |
293 | ssleep(seconds: 3); |
294 | |
295 | return 0; |
296 | } |
297 | |
298 | static int irsd200_read_timer(struct irsd200_data *data, int *val, int *val2) |
299 | { |
300 | __le16 buf; |
301 | int ret; |
302 | |
303 | ret = regmap_bulk_read(map: data->regmap, IRS_REG_TIMER_LO, val: &buf, |
304 | val_count: sizeof(buf)); |
305 | if (ret) { |
306 | dev_err(data->dev, "Could not bulk read timer (%d)\n" , ret); |
307 | return ret; |
308 | } |
309 | |
310 | ret = irsd200_read_data_rate(data, val: val2); |
311 | if (ret) |
312 | return ret; |
313 | |
314 | *val = le16_to_cpu(buf); |
315 | |
316 | return 0; |
317 | } |
318 | |
319 | static int irsd200_write_timer(struct irsd200_data *data, int val, int val2) |
320 | { |
321 | unsigned int regval; |
322 | int data_rate; |
323 | __le16 buf; |
324 | int ret; |
325 | |
326 | if (val < 0 || val2 < 0) |
327 | return -ERANGE; |
328 | |
329 | ret = irsd200_read_data_rate(data, val: &data_rate); |
330 | if (ret) |
331 | return ret; |
332 | |
333 | /* Quantize from seconds. */ |
334 | regval = val * data_rate + (val2 * data_rate) / 1000000; |
335 | |
336 | /* Value is 10 bits. */ |
337 | if (regval >= BIT(10)) |
338 | return -ERANGE; |
339 | |
340 | buf = cpu_to_le16((u16)regval); |
341 | |
342 | ret = regmap_bulk_write(map: data->regmap, IRS_REG_TIMER_LO, val: &buf, |
343 | val_count: sizeof(buf)); |
344 | if (ret) { |
345 | dev_err(data->dev, "Could not bulk write timer (%d)\n" , ret); |
346 | return ret; |
347 | } |
348 | |
349 | return 0; |
350 | } |
351 | |
352 | static int irsd200_read_nr_count(struct irsd200_data *data, int *val) |
353 | { |
354 | unsigned int regval; |
355 | int ret; |
356 | |
357 | ret = regmap_read(map: data->regmap, IRS_REG_NR_COUNT, val: ®val); |
358 | if (ret) { |
359 | dev_err(data->dev, "Could not read nr count (%d)\n" , ret); |
360 | return ret; |
361 | } |
362 | |
363 | *val = regval; |
364 | |
365 | return 0; |
366 | } |
367 | |
368 | static int irsd200_write_nr_count(struct irsd200_data *data, int val) |
369 | { |
370 | unsigned int regval; |
371 | int ret; |
372 | |
373 | /* A value of zero means that IRS_REG_STATUS is never set. */ |
374 | if (val <= 0 || val >= 8) |
375 | return -ERANGE; |
376 | |
377 | regval = val; |
378 | |
379 | if (regval >= 2) { |
380 | /* |
381 | * According to the data sheet, timer must be also set in this |
382 | * case (i.e. be non-zero). Check and enforce that. |
383 | */ |
384 | ret = irsd200_read_timer(data, val: &val, val2: &val); |
385 | if (ret) |
386 | return ret; |
387 | |
388 | if (val == 0) { |
389 | dev_err(data->dev, |
390 | "Timer must be non-zero when nr count is %u\n" , |
391 | regval); |
392 | return -EPERM; |
393 | } |
394 | } |
395 | |
396 | ret = regmap_write(map: data->regmap, IRS_REG_NR_COUNT, val: regval); |
397 | if (ret) { |
398 | dev_err(data->dev, "Could not write nr count (%d)\n" , ret); |
399 | return ret; |
400 | } |
401 | |
402 | return 0; |
403 | } |
404 | |
405 | static int irsd200_read_lp_filter(struct irsd200_data *data, int *val) |
406 | { |
407 | unsigned int regval; |
408 | int ret; |
409 | |
410 | ret = regmap_field_read(field: data->regfields[IRS_REGF_LP_FILTER], val: ®val); |
411 | if (ret) { |
412 | dev_err(data->dev, "Could not read lp filter frequency (%d)\n" , |
413 | ret); |
414 | return ret; |
415 | } |
416 | |
417 | *val = irsd200_lp_filter_freq[regval]; |
418 | |
419 | return 0; |
420 | } |
421 | |
422 | static int irsd200_write_lp_filter(struct irsd200_data *data, int val) |
423 | { |
424 | size_t idx; |
425 | int ret; |
426 | |
427 | for (idx = 0; idx < ARRAY_SIZE(irsd200_lp_filter_freq); ++idx) { |
428 | if (irsd200_lp_filter_freq[idx] == val) |
429 | break; |
430 | } |
431 | |
432 | if (idx == ARRAY_SIZE(irsd200_lp_filter_freq)) |
433 | return -ERANGE; |
434 | |
435 | ret = regmap_field_write(field: data->regfields[IRS_REGF_LP_FILTER], val: idx); |
436 | if (ret) { |
437 | dev_err(data->dev, "Could not write lp filter frequency (%d)\n" , |
438 | ret); |
439 | return ret; |
440 | } |
441 | |
442 | return 0; |
443 | } |
444 | |
445 | static int irsd200_read_hp_filter(struct irsd200_data *data, int *val, |
446 | int *val2) |
447 | { |
448 | unsigned int regval; |
449 | int ret; |
450 | |
451 | ret = regmap_field_read(field: data->regfields[IRS_REGF_HP_FILTER], val: ®val); |
452 | if (ret) { |
453 | dev_err(data->dev, "Could not read hp filter frequency (%d)\n" , |
454 | ret); |
455 | return ret; |
456 | } |
457 | |
458 | *val = irsd200_hp_filter_freq[regval][0]; |
459 | *val2 = irsd200_hp_filter_freq[regval][1]; |
460 | |
461 | return 0; |
462 | } |
463 | |
464 | static int irsd200_write_hp_filter(struct irsd200_data *data, int val, int val2) |
465 | { |
466 | size_t idx; |
467 | int ret; |
468 | |
469 | /* Truncate fractional part to one digit. */ |
470 | val2 /= 100000; |
471 | |
472 | for (idx = 0; idx < ARRAY_SIZE(irsd200_hp_filter_freq); ++idx) { |
473 | if (irsd200_hp_filter_freq[idx][0] == val2) |
474 | break; |
475 | } |
476 | |
477 | if (idx == ARRAY_SIZE(irsd200_hp_filter_freq) || val != 0) |
478 | return -ERANGE; |
479 | |
480 | ret = regmap_field_write(field: data->regfields[IRS_REGF_HP_FILTER], val: idx); |
481 | if (ret) { |
482 | dev_err(data->dev, "Could not write hp filter frequency (%d)\n" , |
483 | ret); |
484 | return ret; |
485 | } |
486 | |
487 | return 0; |
488 | } |
489 | |
490 | static int irsd200_read_raw(struct iio_dev *indio_dev, |
491 | struct iio_chan_spec const *chan, int *val, |
492 | int *val2, long mask) |
493 | { |
494 | struct irsd200_data *data = iio_priv(indio_dev); |
495 | int ret; |
496 | s16 buf; |
497 | |
498 | switch (mask) { |
499 | case IIO_CHAN_INFO_RAW: |
500 | ret = irsd200_read_data(data, val: &buf); |
501 | if (ret) |
502 | return ret; |
503 | |
504 | *val = buf; |
505 | return IIO_VAL_INT; |
506 | case IIO_CHAN_INFO_SAMP_FREQ: |
507 | ret = irsd200_read_data_rate(data, val); |
508 | if (ret) |
509 | return ret; |
510 | |
511 | return IIO_VAL_INT; |
512 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
513 | ret = irsd200_read_lp_filter(data, val); |
514 | if (ret) |
515 | return ret; |
516 | |
517 | return IIO_VAL_INT; |
518 | case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: |
519 | ret = irsd200_read_hp_filter(data, val, val2); |
520 | if (ret) |
521 | return ret; |
522 | |
523 | return IIO_VAL_FRACTIONAL; |
524 | default: |
525 | return -EINVAL; |
526 | } |
527 | } |
528 | |
529 | static int irsd200_read_avail(struct iio_dev *indio_dev, |
530 | struct iio_chan_spec const *chan, |
531 | const int **vals, int *type, int *length, |
532 | long mask) |
533 | { |
534 | switch (mask) { |
535 | case IIO_CHAN_INFO_SAMP_FREQ: |
536 | *vals = irsd200_data_rates; |
537 | *type = IIO_VAL_INT; |
538 | *length = ARRAY_SIZE(irsd200_data_rates); |
539 | return IIO_AVAIL_LIST; |
540 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
541 | *vals = irsd200_lp_filter_freq; |
542 | *type = IIO_VAL_INT; |
543 | *length = ARRAY_SIZE(irsd200_lp_filter_freq); |
544 | return IIO_AVAIL_LIST; |
545 | case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: |
546 | *vals = (int *)irsd200_hp_filter_freq; |
547 | *type = IIO_VAL_FRACTIONAL; |
548 | *length = 2 * ARRAY_SIZE(irsd200_hp_filter_freq); |
549 | return IIO_AVAIL_LIST; |
550 | default: |
551 | return -EINVAL; |
552 | } |
553 | } |
554 | |
555 | static int irsd200_write_raw(struct iio_dev *indio_dev, |
556 | struct iio_chan_spec const *chan, int val, |
557 | int val2, long mask) |
558 | { |
559 | struct irsd200_data *data = iio_priv(indio_dev); |
560 | |
561 | switch (mask) { |
562 | case IIO_CHAN_INFO_SAMP_FREQ: |
563 | return irsd200_write_data_rate(data, val); |
564 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
565 | return irsd200_write_lp_filter(data, val); |
566 | case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: |
567 | return irsd200_write_hp_filter(data, val, val2); |
568 | default: |
569 | return -EINVAL; |
570 | } |
571 | } |
572 | |
573 | static int irsd200_read_event(struct iio_dev *indio_dev, |
574 | const struct iio_chan_spec *chan, |
575 | enum iio_event_type type, |
576 | enum iio_event_direction dir, |
577 | enum iio_event_info info, int *val, int *val2) |
578 | { |
579 | struct irsd200_data *data = iio_priv(indio_dev); |
580 | int ret; |
581 | |
582 | switch (info) { |
583 | case IIO_EV_INFO_VALUE: |
584 | ret = irsd200_read_threshold(data, dir, val); |
585 | if (ret) |
586 | return ret; |
587 | |
588 | return IIO_VAL_INT; |
589 | case IIO_EV_INFO_RUNNING_PERIOD: |
590 | ret = irsd200_read_timer(data, val, val2); |
591 | if (ret) |
592 | return ret; |
593 | |
594 | return IIO_VAL_FRACTIONAL; |
595 | case IIO_EV_INFO_RUNNING_COUNT: |
596 | ret = irsd200_read_nr_count(data, val); |
597 | if (ret) |
598 | return ret; |
599 | |
600 | return IIO_VAL_INT; |
601 | default: |
602 | return -EINVAL; |
603 | } |
604 | } |
605 | |
606 | static int irsd200_write_event(struct iio_dev *indio_dev, |
607 | const struct iio_chan_spec *chan, |
608 | enum iio_event_type type, |
609 | enum iio_event_direction dir, |
610 | enum iio_event_info info, int val, int val2) |
611 | { |
612 | struct irsd200_data *data = iio_priv(indio_dev); |
613 | |
614 | switch (info) { |
615 | case IIO_EV_INFO_VALUE: |
616 | return irsd200_write_threshold(data, dir, val); |
617 | case IIO_EV_INFO_RUNNING_PERIOD: |
618 | return irsd200_write_timer(data, val, val2); |
619 | case IIO_EV_INFO_RUNNING_COUNT: |
620 | return irsd200_write_nr_count(data, val); |
621 | default: |
622 | return -EINVAL; |
623 | } |
624 | } |
625 | |
626 | static int irsd200_read_event_config(struct iio_dev *indio_dev, |
627 | const struct iio_chan_spec *chan, |
628 | enum iio_event_type type, |
629 | enum iio_event_direction dir) |
630 | { |
631 | struct irsd200_data *data = iio_priv(indio_dev); |
632 | unsigned int val; |
633 | int ret; |
634 | |
635 | switch (type) { |
636 | case IIO_EV_TYPE_THRESH: |
637 | ret = regmap_field_read( |
638 | field: data->regfields[IRS_REGF_INTR_COUNT_THR_OR], val: &val); |
639 | if (ret) |
640 | return ret; |
641 | |
642 | return val; |
643 | default: |
644 | return -EINVAL; |
645 | } |
646 | } |
647 | |
648 | static int irsd200_write_event_config(struct iio_dev *indio_dev, |
649 | const struct iio_chan_spec *chan, |
650 | enum iio_event_type type, |
651 | enum iio_event_direction dir, int state) |
652 | { |
653 | struct irsd200_data *data = iio_priv(indio_dev); |
654 | unsigned int tmp; |
655 | int ret; |
656 | |
657 | switch (type) { |
658 | case IIO_EV_TYPE_THRESH: |
659 | /* Clear the count register (by reading from it). */ |
660 | ret = regmap_read(map: data->regmap, IRS_REG_COUNT, val: &tmp); |
661 | if (ret) |
662 | return ret; |
663 | |
664 | return regmap_field_write( |
665 | field: data->regfields[IRS_REGF_INTR_COUNT_THR_OR], val: !!state); |
666 | default: |
667 | return -EINVAL; |
668 | } |
669 | } |
670 | |
671 | static irqreturn_t irsd200_irq_thread(int irq, void *dev_id) |
672 | { |
673 | struct iio_dev *indio_dev = dev_id; |
674 | struct irsd200_data *data = iio_priv(indio_dev); |
675 | enum iio_event_direction dir; |
676 | unsigned int lower_count; |
677 | unsigned int upper_count; |
678 | unsigned int status = 0; |
679 | unsigned int source = 0; |
680 | unsigned int clear = 0; |
681 | unsigned int count = 0; |
682 | int ret; |
683 | |
684 | ret = regmap_read(map: data->regmap, IRS_REG_INTR, val: &source); |
685 | if (ret) { |
686 | dev_err(data->dev, "Could not read interrupt source (%d)\n" , |
687 | ret); |
688 | return IRQ_HANDLED; |
689 | } |
690 | |
691 | ret = regmap_read(map: data->regmap, IRS_REG_STATUS, val: &status); |
692 | if (ret) { |
693 | dev_err(data->dev, "Could not acknowledge interrupt (%d)\n" , |
694 | ret); |
695 | return IRQ_HANDLED; |
696 | } |
697 | |
698 | if (status & BIT(IRS_INTR_DATA) && iio_buffer_enabled(indio_dev)) { |
699 | iio_trigger_poll_nested(trig: indio_dev->trig); |
700 | clear |= BIT(IRS_INTR_DATA); |
701 | } |
702 | |
703 | if (status & BIT(IRS_INTR_COUNT_THR_OR) && |
704 | source & BIT(IRS_INTR_COUNT_THR_OR)) { |
705 | /* |
706 | * The register value resets to zero after reading. We therefore |
707 | * need to read once and manually extract the lower and upper |
708 | * count register fields. |
709 | */ |
710 | ret = regmap_read(map: data->regmap, IRS_REG_COUNT, val: &count); |
711 | if (ret) |
712 | dev_err(data->dev, "Could not read count (%d)\n" , ret); |
713 | |
714 | upper_count = IRS_UPPER_COUNT(count); |
715 | lower_count = IRS_LOWER_COUNT(count); |
716 | |
717 | /* |
718 | * We only check the OR mode to be able to push events for |
719 | * rising and falling thresholds. AND mode is covered when both |
720 | * upper and lower count is non-zero, and is signaled with |
721 | * IIO_EV_DIR_EITHER. |
722 | */ |
723 | if (upper_count && !lower_count) |
724 | dir = IIO_EV_DIR_RISING; |
725 | else if (!upper_count && lower_count) |
726 | dir = IIO_EV_DIR_FALLING; |
727 | else |
728 | dir = IIO_EV_DIR_EITHER; |
729 | |
730 | iio_push_event(indio_dev, |
731 | IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, |
732 | IIO_EV_TYPE_THRESH, dir), |
733 | timestamp: iio_get_time_ns(indio_dev)); |
734 | |
735 | /* |
736 | * The OR mode will always trigger when the AND mode does, but |
737 | * not vice versa. However, it seems like the AND bit needs to |
738 | * be cleared if data capture _and_ threshold count interrupts |
739 | * are desirable, even though it hasn't explicitly been selected |
740 | * (with IRS_REG_INTR). Either way, it doesn't hurt... |
741 | */ |
742 | clear |= BIT(IRS_INTR_COUNT_THR_OR) | |
743 | BIT(IRS_INTR_COUNT_THR_AND); |
744 | } |
745 | |
746 | if (!clear) |
747 | return IRQ_NONE; |
748 | |
749 | ret = regmap_write(map: data->regmap, IRS_REG_STATUS, val: clear); |
750 | if (ret) |
751 | dev_err(data->dev, |
752 | "Could not clear interrupt status (%d)\n" , ret); |
753 | |
754 | return IRQ_HANDLED; |
755 | } |
756 | |
757 | static irqreturn_t irsd200_trigger_handler(int irq, void *pollf) |
758 | { |
759 | struct iio_dev *indio_dev = ((struct iio_poll_func *)pollf)->indio_dev; |
760 | struct irsd200_data *data = iio_priv(indio_dev); |
761 | s64 buf[2] = {}; |
762 | int ret; |
763 | |
764 | ret = irsd200_read_data(data, val: (s16 *)buf); |
765 | if (ret) |
766 | goto end; |
767 | |
768 | iio_push_to_buffers_with_timestamp(indio_dev, data: buf, |
769 | timestamp: iio_get_time_ns(indio_dev)); |
770 | |
771 | end: |
772 | iio_trigger_notify_done(trig: indio_dev->trig); |
773 | |
774 | return IRQ_HANDLED; |
775 | } |
776 | |
777 | static int irsd200_set_trigger_state(struct iio_trigger *trig, bool state) |
778 | { |
779 | struct irsd200_data *data = iio_trigger_get_drvdata(trig); |
780 | int ret; |
781 | |
782 | ret = regmap_field_write(field: data->regfields[IRS_REGF_INTR_DATA], val: state); |
783 | if (ret) { |
784 | dev_err(data->dev, "Could not %s data interrupt source (%d)\n" , |
785 | state ? "enable" : "disable" , ret); |
786 | } |
787 | |
788 | return ret; |
789 | } |
790 | |
791 | static const struct iio_info irsd200_info = { |
792 | .read_raw = irsd200_read_raw, |
793 | .read_avail = irsd200_read_avail, |
794 | .write_raw = irsd200_write_raw, |
795 | .read_event_value = irsd200_read_event, |
796 | .write_event_value = irsd200_write_event, |
797 | .read_event_config = irsd200_read_event_config, |
798 | .write_event_config = irsd200_write_event_config, |
799 | }; |
800 | |
801 | static const struct iio_trigger_ops irsd200_trigger_ops = { |
802 | .set_trigger_state = irsd200_set_trigger_state, |
803 | .validate_device = iio_trigger_validate_own_device, |
804 | }; |
805 | |
806 | static const struct iio_event_spec irsd200_event_spec[] = { |
807 | { |
808 | .type = IIO_EV_TYPE_THRESH, |
809 | .dir = IIO_EV_DIR_RISING, |
810 | .mask_separate = BIT(IIO_EV_INFO_VALUE), |
811 | }, |
812 | { |
813 | .type = IIO_EV_TYPE_THRESH, |
814 | .dir = IIO_EV_DIR_FALLING, |
815 | .mask_separate = BIT(IIO_EV_INFO_VALUE), |
816 | }, |
817 | { |
818 | .type = IIO_EV_TYPE_THRESH, |
819 | .dir = IIO_EV_DIR_EITHER, |
820 | .mask_separate = |
821 | BIT(IIO_EV_INFO_RUNNING_PERIOD) | |
822 | BIT(IIO_EV_INFO_RUNNING_COUNT) | |
823 | BIT(IIO_EV_INFO_ENABLE), |
824 | }, |
825 | }; |
826 | |
827 | static const struct iio_chan_spec irsd200_channels[] = { |
828 | { |
829 | .type = IIO_PROXIMITY, |
830 | .info_mask_separate = |
831 | BIT(IIO_CHAN_INFO_RAW) | |
832 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
833 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | |
834 | BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), |
835 | .info_mask_separate_available = |
836 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
837 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | |
838 | BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), |
839 | .event_spec = irsd200_event_spec, |
840 | .num_event_specs = ARRAY_SIZE(irsd200_event_spec), |
841 | .scan_type = { |
842 | .sign = 's', |
843 | .realbits = 16, |
844 | .storagebits = 16, |
845 | .endianness = IIO_CPU, |
846 | }, |
847 | }, |
848 | }; |
849 | |
850 | static int irsd200_probe(struct i2c_client *client) |
851 | { |
852 | struct iio_trigger *trigger; |
853 | struct irsd200_data *data; |
854 | struct iio_dev *indio_dev; |
855 | size_t i; |
856 | int ret; |
857 | |
858 | indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*data)); |
859 | if (!indio_dev) |
860 | return dev_err_probe(dev: &client->dev, err: -ENOMEM, |
861 | fmt: "Could not allocate iio device\n" ); |
862 | |
863 | data = iio_priv(indio_dev); |
864 | data->dev = &client->dev; |
865 | |
866 | data->regmap = devm_regmap_init_i2c(client, &irsd200_regmap_config); |
867 | if (IS_ERR(ptr: data->regmap)) |
868 | return dev_err_probe(dev: data->dev, err: PTR_ERR(ptr: data->regmap), |
869 | fmt: "Could not initialize regmap\n" ); |
870 | |
871 | for (i = 0; i < IRS_REGF_MAX; ++i) { |
872 | data->regfields[i] = devm_regmap_field_alloc( |
873 | dev: data->dev, regmap: data->regmap, reg_field: irsd200_regfields[i]); |
874 | if (IS_ERR(ptr: data->regfields[i])) |
875 | return dev_err_probe( |
876 | dev: data->dev, err: PTR_ERR(ptr: data->regfields[i]), |
877 | fmt: "Could not allocate register field %zu\n" , i); |
878 | } |
879 | |
880 | ret = devm_regulator_get_enable(dev: data->dev, id: "vdd" ); |
881 | if (ret) |
882 | return dev_err_probe( |
883 | dev: data->dev, err: ret, |
884 | fmt: "Could not get and enable regulator (%d)\n" , ret); |
885 | |
886 | ret = irsd200_setup(data); |
887 | if (ret) |
888 | return ret; |
889 | |
890 | indio_dev->info = &irsd200_info; |
891 | indio_dev->name = IRS_DRV_NAME; |
892 | indio_dev->channels = irsd200_channels; |
893 | indio_dev->num_channels = ARRAY_SIZE(irsd200_channels); |
894 | indio_dev->modes = INDIO_DIRECT_MODE; |
895 | |
896 | if (!client->irq) |
897 | return dev_err_probe(dev: data->dev, err: -ENXIO, fmt: "No irq available\n" ); |
898 | |
899 | ret = devm_iio_triggered_buffer_setup(data->dev, indio_dev, NULL, |
900 | irsd200_trigger_handler, NULL); |
901 | if (ret) |
902 | return dev_err_probe( |
903 | dev: data->dev, err: ret, |
904 | fmt: "Could not setup iio triggered buffer (%d)\n" , ret); |
905 | |
906 | ret = devm_request_threaded_irq(dev: data->dev, irq: client->irq, NULL, |
907 | thread_fn: irsd200_irq_thread, |
908 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
909 | NULL, dev_id: indio_dev); |
910 | if (ret) |
911 | return dev_err_probe(dev: data->dev, err: ret, |
912 | fmt: "Could not request irq (%d)\n" , ret); |
913 | |
914 | trigger = devm_iio_trigger_alloc(data->dev, "%s-dev%d" , indio_dev->name, |
915 | iio_device_id(indio_dev)); |
916 | if (!trigger) |
917 | return dev_err_probe(dev: data->dev, err: -ENOMEM, |
918 | fmt: "Could not allocate iio trigger\n" ); |
919 | |
920 | trigger->ops = &irsd200_trigger_ops; |
921 | iio_trigger_set_drvdata(trig: trigger, data); |
922 | |
923 | ret = devm_iio_trigger_register(dev: data->dev, trig_info: trigger); |
924 | if (ret) |
925 | return dev_err_probe(dev: data->dev, err: ret, |
926 | fmt: "Could not register iio trigger (%d)\n" , |
927 | ret); |
928 | |
929 | ret = devm_iio_device_register(data->dev, indio_dev); |
930 | if (ret) |
931 | return dev_err_probe(dev: data->dev, err: ret, |
932 | fmt: "Could not register iio device (%d)\n" , |
933 | ret); |
934 | |
935 | return 0; |
936 | } |
937 | |
938 | static const struct of_device_id irsd200_of_match[] = { |
939 | { |
940 | .compatible = "murata,irsd200" , |
941 | }, |
942 | {} |
943 | }; |
944 | MODULE_DEVICE_TABLE(of, irsd200_of_match); |
945 | |
946 | static struct i2c_driver irsd200_driver = { |
947 | .driver = { |
948 | .name = IRS_DRV_NAME, |
949 | .of_match_table = irsd200_of_match, |
950 | }, |
951 | .probe = irsd200_probe, |
952 | }; |
953 | module_i2c_driver(irsd200_driver); |
954 | |
955 | MODULE_AUTHOR("Waqar Hameed <waqar.hameed@axis.com>" ); |
956 | MODULE_DESCRIPTION("Murata IRS-D200 PIR sensor driver" ); |
957 | MODULE_LICENSE("GPL" ); |
958 | |