1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * AFE4404 Heart Rate Monitors and Low-Cost Pulse Oximeters |
4 | * |
5 | * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/ |
6 | * Andrew F. Davis <afd@ti.com> |
7 | */ |
8 | |
9 | #include <linux/device.h> |
10 | #include <linux/err.h> |
11 | #include <linux/interrupt.h> |
12 | #include <linux/i2c.h> |
13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> |
15 | #include <linux/regmap.h> |
16 | #include <linux/sysfs.h> |
17 | #include <linux/regulator/consumer.h> |
18 | |
19 | #include <linux/iio/iio.h> |
20 | #include <linux/iio/sysfs.h> |
21 | #include <linux/iio/buffer.h> |
22 | #include <linux/iio/trigger.h> |
23 | #include <linux/iio/triggered_buffer.h> |
24 | #include <linux/iio/trigger_consumer.h> |
25 | |
26 | #include "afe440x.h" |
27 | |
28 | #define AFE4404_DRIVER_NAME "afe4404" |
29 | |
30 | /* AFE4404 registers */ |
31 | #define AFE4404_TIA_GAIN_SEP 0x20 |
32 | #define AFE4404_TIA_GAIN 0x21 |
33 | #define AFE4404_PROG_TG_STC 0x34 |
34 | #define AFE4404_PROG_TG_ENDC 0x35 |
35 | #define AFE4404_LED3LEDSTC 0x36 |
36 | #define AFE4404_LED3LEDENDC 0x37 |
37 | #define AFE4404_CLKDIV_PRF 0x39 |
38 | #define AFE4404_OFFDAC 0x3a |
39 | #define AFE4404_DEC 0x3d |
40 | #define AFE4404_AVG_LED2_ALED2VAL 0x3f |
41 | #define AFE4404_AVG_LED1_ALED1VAL 0x40 |
42 | |
43 | /* AFE4404 CONTROL2 register fields */ |
44 | #define AFE440X_CONTROL2_OSC_ENABLE BIT(9) |
45 | |
46 | enum afe4404_fields { |
47 | /* Gains */ |
48 | F_TIA_GAIN_SEP, F_TIA_CF_SEP, |
49 | F_TIA_GAIN, TIA_CF, |
50 | |
51 | /* LED Current */ |
52 | F_ILED1, F_ILED2, F_ILED3, |
53 | |
54 | /* Offset DAC */ |
55 | F_OFFDAC_AMB2, F_OFFDAC_LED1, F_OFFDAC_AMB1, F_OFFDAC_LED2, |
56 | |
57 | /* sentinel */ |
58 | F_MAX_FIELDS |
59 | }; |
60 | |
61 | static const struct reg_field afe4404_reg_fields[] = { |
62 | /* Gains */ |
63 | [F_TIA_GAIN_SEP] = REG_FIELD(AFE4404_TIA_GAIN_SEP, 0, 2), |
64 | [F_TIA_CF_SEP] = REG_FIELD(AFE4404_TIA_GAIN_SEP, 3, 5), |
65 | [F_TIA_GAIN] = REG_FIELD(AFE4404_TIA_GAIN, 0, 2), |
66 | [TIA_CF] = REG_FIELD(AFE4404_TIA_GAIN, 3, 5), |
67 | /* LED Current */ |
68 | [F_ILED1] = REG_FIELD(AFE440X_LEDCNTRL, 0, 5), |
69 | [F_ILED2] = REG_FIELD(AFE440X_LEDCNTRL, 6, 11), |
70 | [F_ILED3] = REG_FIELD(AFE440X_LEDCNTRL, 12, 17), |
71 | /* Offset DAC */ |
72 | [F_OFFDAC_AMB2] = REG_FIELD(AFE4404_OFFDAC, 0, 4), |
73 | [F_OFFDAC_LED1] = REG_FIELD(AFE4404_OFFDAC, 5, 9), |
74 | [F_OFFDAC_AMB1] = REG_FIELD(AFE4404_OFFDAC, 10, 14), |
75 | [F_OFFDAC_LED2] = REG_FIELD(AFE4404_OFFDAC, 15, 19), |
76 | }; |
77 | |
78 | /** |
79 | * struct afe4404_data - AFE4404 device instance data |
80 | * @dev: Device structure |
81 | * @regmap: Register map of the device |
82 | * @fields: Register fields of the device |
83 | * @regulator: Pointer to the regulator for the IC |
84 | * @trig: IIO trigger for this device |
85 | * @irq: ADC_RDY line interrupt number |
86 | * @buffer: Used to construct a scan to push to the iio buffer. |
87 | */ |
88 | struct afe4404_data { |
89 | struct device *dev; |
90 | struct regmap *regmap; |
91 | struct regmap_field *fields[F_MAX_FIELDS]; |
92 | struct regulator *regulator; |
93 | struct iio_trigger *trig; |
94 | int irq; |
95 | s32 buffer[10] __aligned(8); |
96 | }; |
97 | |
98 | enum afe4404_chan_id { |
99 | LED2 = 1, |
100 | ALED2, |
101 | LED1, |
102 | ALED1, |
103 | LED2_ALED2, |
104 | LED1_ALED1, |
105 | }; |
106 | |
107 | static const unsigned int afe4404_channel_values[] = { |
108 | [LED2] = AFE440X_LED2VAL, |
109 | [ALED2] = AFE440X_ALED2VAL, |
110 | [LED1] = AFE440X_LED1VAL, |
111 | [ALED1] = AFE440X_ALED1VAL, |
112 | [LED2_ALED2] = AFE440X_LED2_ALED2VAL, |
113 | [LED1_ALED1] = AFE440X_LED1_ALED1VAL, |
114 | }; |
115 | |
116 | static const unsigned int afe4404_channel_leds[] = { |
117 | [LED2] = F_ILED2, |
118 | [ALED2] = F_ILED3, |
119 | [LED1] = F_ILED1, |
120 | }; |
121 | |
122 | static const unsigned int afe4404_channel_offdacs[] = { |
123 | [LED2] = F_OFFDAC_LED2, |
124 | [ALED2] = F_OFFDAC_AMB2, |
125 | [LED1] = F_OFFDAC_LED1, |
126 | [ALED1] = F_OFFDAC_AMB1, |
127 | }; |
128 | |
129 | static const struct iio_chan_spec afe4404_channels[] = { |
130 | /* ADC values */ |
131 | AFE440X_INTENSITY_CHAN(LED2, BIT(IIO_CHAN_INFO_OFFSET)), |
132 | AFE440X_INTENSITY_CHAN(ALED2, BIT(IIO_CHAN_INFO_OFFSET)), |
133 | AFE440X_INTENSITY_CHAN(LED1, BIT(IIO_CHAN_INFO_OFFSET)), |
134 | AFE440X_INTENSITY_CHAN(ALED1, BIT(IIO_CHAN_INFO_OFFSET)), |
135 | AFE440X_INTENSITY_CHAN(LED2_ALED2, 0), |
136 | AFE440X_INTENSITY_CHAN(LED1_ALED1, 0), |
137 | /* LED current */ |
138 | AFE440X_CURRENT_CHAN(LED2), |
139 | AFE440X_CURRENT_CHAN(ALED2), |
140 | AFE440X_CURRENT_CHAN(LED1), |
141 | }; |
142 | |
143 | static const struct afe440x_val_table afe4404_res_table[] = { |
144 | { .integer = 500000, .fract = 0 }, |
145 | { .integer = 250000, .fract = 0 }, |
146 | { .integer = 100000, .fract = 0 }, |
147 | { .integer = 50000, .fract = 0 }, |
148 | { .integer = 25000, .fract = 0 }, |
149 | { .integer = 10000, .fract = 0 }, |
150 | { .integer = 1000000, .fract = 0 }, |
151 | { .integer = 2000000, .fract = 0 }, |
152 | }; |
153 | AFE440X_TABLE_ATTR(in_intensity_resistance_available, afe4404_res_table); |
154 | |
155 | static const struct afe440x_val_table afe4404_cap_table[] = { |
156 | { .integer = 0, .fract = 5000 }, |
157 | { .integer = 0, .fract = 2500 }, |
158 | { .integer = 0, .fract = 10000 }, |
159 | { .integer = 0, .fract = 7500 }, |
160 | { .integer = 0, .fract = 20000 }, |
161 | { .integer = 0, .fract = 17500 }, |
162 | { .integer = 0, .fract = 25000 }, |
163 | { .integer = 0, .fract = 22500 }, |
164 | }; |
165 | AFE440X_TABLE_ATTR(in_intensity_capacitance_available, afe4404_cap_table); |
166 | |
167 | static ssize_t afe440x_show_register(struct device *dev, |
168 | struct device_attribute *attr, |
169 | char *buf) |
170 | { |
171 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
172 | struct afe4404_data *afe = iio_priv(indio_dev); |
173 | struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); |
174 | unsigned int reg_val; |
175 | int vals[2]; |
176 | int ret; |
177 | |
178 | ret = regmap_field_read(field: afe->fields[afe440x_attr->field], val: ®_val); |
179 | if (ret) |
180 | return ret; |
181 | |
182 | if (reg_val >= afe440x_attr->table_size) |
183 | return -EINVAL; |
184 | |
185 | vals[0] = afe440x_attr->val_table[reg_val].integer; |
186 | vals[1] = afe440x_attr->val_table[reg_val].fract; |
187 | |
188 | return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, size: 2, vals); |
189 | } |
190 | |
191 | static ssize_t afe440x_store_register(struct device *dev, |
192 | struct device_attribute *attr, |
193 | const char *buf, size_t count) |
194 | { |
195 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
196 | struct afe4404_data *afe = iio_priv(indio_dev); |
197 | struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); |
198 | int val, integer, fract, ret; |
199 | |
200 | ret = iio_str_to_fixpoint(str: buf, fract_mult: 100000, integer: &integer, fract: &fract); |
201 | if (ret) |
202 | return ret; |
203 | |
204 | for (val = 0; val < afe440x_attr->table_size; val++) |
205 | if (afe440x_attr->val_table[val].integer == integer && |
206 | afe440x_attr->val_table[val].fract == fract) |
207 | break; |
208 | if (val == afe440x_attr->table_size) |
209 | return -EINVAL; |
210 | |
211 | ret = regmap_field_write(field: afe->fields[afe440x_attr->field], val); |
212 | if (ret) |
213 | return ret; |
214 | |
215 | return count; |
216 | } |
217 | |
218 | static AFE440X_ATTR(in_intensity1_resistance, F_TIA_GAIN_SEP, afe4404_res_table); |
219 | static AFE440X_ATTR(in_intensity1_capacitance, F_TIA_CF_SEP, afe4404_cap_table); |
220 | |
221 | static AFE440X_ATTR(in_intensity2_resistance, F_TIA_GAIN_SEP, afe4404_res_table); |
222 | static AFE440X_ATTR(in_intensity2_capacitance, F_TIA_CF_SEP, afe4404_cap_table); |
223 | |
224 | static AFE440X_ATTR(in_intensity3_resistance, F_TIA_GAIN, afe4404_res_table); |
225 | static AFE440X_ATTR(in_intensity3_capacitance, TIA_CF, afe4404_cap_table); |
226 | |
227 | static AFE440X_ATTR(in_intensity4_resistance, F_TIA_GAIN, afe4404_res_table); |
228 | static AFE440X_ATTR(in_intensity4_capacitance, TIA_CF, afe4404_cap_table); |
229 | |
230 | static struct attribute *afe440x_attributes[] = { |
231 | &dev_attr_in_intensity_resistance_available.attr, |
232 | &dev_attr_in_intensity_capacitance_available.attr, |
233 | &afe440x_attr_in_intensity1_resistance.dev_attr.attr, |
234 | &afe440x_attr_in_intensity1_capacitance.dev_attr.attr, |
235 | &afe440x_attr_in_intensity2_resistance.dev_attr.attr, |
236 | &afe440x_attr_in_intensity2_capacitance.dev_attr.attr, |
237 | &afe440x_attr_in_intensity3_resistance.dev_attr.attr, |
238 | &afe440x_attr_in_intensity3_capacitance.dev_attr.attr, |
239 | &afe440x_attr_in_intensity4_resistance.dev_attr.attr, |
240 | &afe440x_attr_in_intensity4_capacitance.dev_attr.attr, |
241 | NULL |
242 | }; |
243 | |
244 | static const struct attribute_group afe440x_attribute_group = { |
245 | .attrs = afe440x_attributes |
246 | }; |
247 | |
248 | static int afe4404_read_raw(struct iio_dev *indio_dev, |
249 | struct iio_chan_spec const *chan, |
250 | int *val, int *val2, long mask) |
251 | { |
252 | struct afe4404_data *afe = iio_priv(indio_dev); |
253 | unsigned int value_reg, led_field, offdac_field; |
254 | int ret; |
255 | |
256 | switch (chan->type) { |
257 | case IIO_INTENSITY: |
258 | switch (mask) { |
259 | case IIO_CHAN_INFO_RAW: |
260 | value_reg = afe4404_channel_values[chan->address]; |
261 | ret = regmap_read(map: afe->regmap, reg: value_reg, val); |
262 | if (ret) |
263 | return ret; |
264 | return IIO_VAL_INT; |
265 | case IIO_CHAN_INFO_OFFSET: |
266 | offdac_field = afe4404_channel_offdacs[chan->address]; |
267 | ret = regmap_field_read(field: afe->fields[offdac_field], val); |
268 | if (ret) |
269 | return ret; |
270 | return IIO_VAL_INT; |
271 | } |
272 | break; |
273 | case IIO_CURRENT: |
274 | switch (mask) { |
275 | case IIO_CHAN_INFO_RAW: |
276 | led_field = afe4404_channel_leds[chan->address]; |
277 | ret = regmap_field_read(field: afe->fields[led_field], val); |
278 | if (ret) |
279 | return ret; |
280 | return IIO_VAL_INT; |
281 | case IIO_CHAN_INFO_SCALE: |
282 | *val = 0; |
283 | *val2 = 800000; |
284 | return IIO_VAL_INT_PLUS_MICRO; |
285 | } |
286 | break; |
287 | default: |
288 | break; |
289 | } |
290 | |
291 | return -EINVAL; |
292 | } |
293 | |
294 | static int afe4404_write_raw(struct iio_dev *indio_dev, |
295 | struct iio_chan_spec const *chan, |
296 | int val, int val2, long mask) |
297 | { |
298 | struct afe4404_data *afe = iio_priv(indio_dev); |
299 | unsigned int led_field, offdac_field; |
300 | |
301 | switch (chan->type) { |
302 | case IIO_INTENSITY: |
303 | switch (mask) { |
304 | case IIO_CHAN_INFO_OFFSET: |
305 | offdac_field = afe4404_channel_offdacs[chan->address]; |
306 | return regmap_field_write(field: afe->fields[offdac_field], val); |
307 | } |
308 | break; |
309 | case IIO_CURRENT: |
310 | switch (mask) { |
311 | case IIO_CHAN_INFO_RAW: |
312 | led_field = afe4404_channel_leds[chan->address]; |
313 | return regmap_field_write(field: afe->fields[led_field], val); |
314 | } |
315 | break; |
316 | default: |
317 | break; |
318 | } |
319 | |
320 | return -EINVAL; |
321 | } |
322 | |
323 | static const struct iio_info afe4404_iio_info = { |
324 | .attrs = &afe440x_attribute_group, |
325 | .read_raw = afe4404_read_raw, |
326 | .write_raw = afe4404_write_raw, |
327 | }; |
328 | |
329 | static irqreturn_t afe4404_trigger_handler(int irq, void *private) |
330 | { |
331 | struct iio_poll_func *pf = private; |
332 | struct iio_dev *indio_dev = pf->indio_dev; |
333 | struct afe4404_data *afe = iio_priv(indio_dev); |
334 | int ret, bit, i = 0; |
335 | |
336 | for_each_set_bit(bit, indio_dev->active_scan_mask, |
337 | indio_dev->masklength) { |
338 | ret = regmap_read(map: afe->regmap, reg: afe4404_channel_values[bit], |
339 | val: &afe->buffer[i++]); |
340 | if (ret) |
341 | goto err; |
342 | } |
343 | |
344 | iio_push_to_buffers_with_timestamp(indio_dev, data: afe->buffer, |
345 | timestamp: pf->timestamp); |
346 | err: |
347 | iio_trigger_notify_done(trig: indio_dev->trig); |
348 | |
349 | return IRQ_HANDLED; |
350 | } |
351 | |
352 | /* Default timings from data-sheet */ |
353 | #define AFE4404_TIMING_PAIRS \ |
354 | { AFE440X_PRPCOUNT, 39999 }, \ |
355 | { AFE440X_LED2LEDSTC, 0 }, \ |
356 | { AFE440X_LED2LEDENDC, 398 }, \ |
357 | { AFE440X_LED2STC, 80 }, \ |
358 | { AFE440X_LED2ENDC, 398 }, \ |
359 | { AFE440X_ADCRSTSTCT0, 5600 }, \ |
360 | { AFE440X_ADCRSTENDCT0, 5606 }, \ |
361 | { AFE440X_LED2CONVST, 5607 }, \ |
362 | { AFE440X_LED2CONVEND, 6066 }, \ |
363 | { AFE4404_LED3LEDSTC, 400 }, \ |
364 | { AFE4404_LED3LEDENDC, 798 }, \ |
365 | { AFE440X_ALED2STC, 480 }, \ |
366 | { AFE440X_ALED2ENDC, 798 }, \ |
367 | { AFE440X_ADCRSTSTCT1, 6068 }, \ |
368 | { AFE440X_ADCRSTENDCT1, 6074 }, \ |
369 | { AFE440X_ALED2CONVST, 6075 }, \ |
370 | { AFE440X_ALED2CONVEND, 6534 }, \ |
371 | { AFE440X_LED1LEDSTC, 800 }, \ |
372 | { AFE440X_LED1LEDENDC, 1198 }, \ |
373 | { AFE440X_LED1STC, 880 }, \ |
374 | { AFE440X_LED1ENDC, 1198 }, \ |
375 | { AFE440X_ADCRSTSTCT2, 6536 }, \ |
376 | { AFE440X_ADCRSTENDCT2, 6542 }, \ |
377 | { AFE440X_LED1CONVST, 6543 }, \ |
378 | { AFE440X_LED1CONVEND, 7003 }, \ |
379 | { AFE440X_ALED1STC, 1280 }, \ |
380 | { AFE440X_ALED1ENDC, 1598 }, \ |
381 | { AFE440X_ADCRSTSTCT3, 7005 }, \ |
382 | { AFE440X_ADCRSTENDCT3, 7011 }, \ |
383 | { AFE440X_ALED1CONVST, 7012 }, \ |
384 | { AFE440X_ALED1CONVEND, 7471 }, \ |
385 | { AFE440X_PDNCYCLESTC, 7671 }, \ |
386 | { AFE440X_PDNCYCLEENDC, 39199 } |
387 | |
388 | static const struct reg_sequence afe4404_reg_sequences[] = { |
389 | AFE4404_TIMING_PAIRS, |
390 | { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN }, |
391 | { AFE4404_TIA_GAIN_SEP, AFE440X_TIAGAIN_ENSEPGAIN }, |
392 | { AFE440X_CONTROL2, AFE440X_CONTROL2_OSC_ENABLE }, |
393 | }; |
394 | |
395 | static const struct regmap_range afe4404_yes_ranges[] = { |
396 | regmap_reg_range(AFE440X_LED2VAL, AFE440X_LED1_ALED1VAL), |
397 | regmap_reg_range(AFE4404_AVG_LED2_ALED2VAL, AFE4404_AVG_LED1_ALED1VAL), |
398 | }; |
399 | |
400 | static const struct regmap_access_table afe4404_volatile_table = { |
401 | .yes_ranges = afe4404_yes_ranges, |
402 | .n_yes_ranges = ARRAY_SIZE(afe4404_yes_ranges), |
403 | }; |
404 | |
405 | static const struct regmap_config afe4404_regmap_config = { |
406 | .reg_bits = 8, |
407 | .val_bits = 24, |
408 | |
409 | .max_register = AFE4404_AVG_LED1_ALED1VAL, |
410 | .cache_type = REGCACHE_RBTREE, |
411 | .volatile_table = &afe4404_volatile_table, |
412 | }; |
413 | |
414 | static const struct of_device_id afe4404_of_match[] = { |
415 | { .compatible = "ti,afe4404" , }, |
416 | { /* sentinel */ } |
417 | }; |
418 | MODULE_DEVICE_TABLE(of, afe4404_of_match); |
419 | |
420 | static int afe4404_suspend(struct device *dev) |
421 | { |
422 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); |
423 | struct afe4404_data *afe = iio_priv(indio_dev); |
424 | int ret; |
425 | |
426 | ret = regmap_update_bits(map: afe->regmap, AFE440X_CONTROL2, |
427 | AFE440X_CONTROL2_PDN_AFE, |
428 | AFE440X_CONTROL2_PDN_AFE); |
429 | if (ret) |
430 | return ret; |
431 | |
432 | ret = regulator_disable(regulator: afe->regulator); |
433 | if (ret) { |
434 | dev_err(dev, "Unable to disable regulator\n" ); |
435 | return ret; |
436 | } |
437 | |
438 | return 0; |
439 | } |
440 | |
441 | static int afe4404_resume(struct device *dev) |
442 | { |
443 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); |
444 | struct afe4404_data *afe = iio_priv(indio_dev); |
445 | int ret; |
446 | |
447 | ret = regulator_enable(regulator: afe->regulator); |
448 | if (ret) { |
449 | dev_err(dev, "Unable to enable regulator\n" ); |
450 | return ret; |
451 | } |
452 | |
453 | ret = regmap_update_bits(map: afe->regmap, AFE440X_CONTROL2, |
454 | AFE440X_CONTROL2_PDN_AFE, val: 0); |
455 | if (ret) |
456 | return ret; |
457 | |
458 | return 0; |
459 | } |
460 | |
461 | static DEFINE_SIMPLE_DEV_PM_OPS(afe4404_pm_ops, afe4404_suspend, |
462 | afe4404_resume); |
463 | |
464 | static int afe4404_probe(struct i2c_client *client) |
465 | { |
466 | struct iio_dev *indio_dev; |
467 | struct afe4404_data *afe; |
468 | int i, ret; |
469 | |
470 | indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*afe)); |
471 | if (!indio_dev) |
472 | return -ENOMEM; |
473 | |
474 | afe = iio_priv(indio_dev); |
475 | i2c_set_clientdata(client, data: indio_dev); |
476 | |
477 | afe->dev = &client->dev; |
478 | afe->irq = client->irq; |
479 | |
480 | afe->regmap = devm_regmap_init_i2c(client, &afe4404_regmap_config); |
481 | if (IS_ERR(ptr: afe->regmap)) { |
482 | dev_err(afe->dev, "Unable to allocate register map\n" ); |
483 | return PTR_ERR(ptr: afe->regmap); |
484 | } |
485 | |
486 | for (i = 0; i < F_MAX_FIELDS; i++) { |
487 | afe->fields[i] = devm_regmap_field_alloc(dev: afe->dev, regmap: afe->regmap, |
488 | reg_field: afe4404_reg_fields[i]); |
489 | if (IS_ERR(ptr: afe->fields[i])) { |
490 | dev_err(afe->dev, "Unable to allocate regmap fields\n" ); |
491 | return PTR_ERR(ptr: afe->fields[i]); |
492 | } |
493 | } |
494 | |
495 | afe->regulator = devm_regulator_get(dev: afe->dev, id: "tx_sup" ); |
496 | if (IS_ERR(ptr: afe->regulator)) |
497 | return dev_err_probe(dev: afe->dev, err: PTR_ERR(ptr: afe->regulator), |
498 | fmt: "Unable to get regulator\n" ); |
499 | |
500 | ret = regulator_enable(regulator: afe->regulator); |
501 | if (ret) { |
502 | dev_err(afe->dev, "Unable to enable regulator\n" ); |
503 | return ret; |
504 | } |
505 | |
506 | ret = regmap_write(map: afe->regmap, AFE440X_CONTROL0, |
507 | AFE440X_CONTROL0_SW_RESET); |
508 | if (ret) { |
509 | dev_err(afe->dev, "Unable to reset device\n" ); |
510 | goto disable_reg; |
511 | } |
512 | |
513 | ret = regmap_multi_reg_write(map: afe->regmap, regs: afe4404_reg_sequences, |
514 | ARRAY_SIZE(afe4404_reg_sequences)); |
515 | if (ret) { |
516 | dev_err(afe->dev, "Unable to set register defaults\n" ); |
517 | goto disable_reg; |
518 | } |
519 | |
520 | indio_dev->modes = INDIO_DIRECT_MODE; |
521 | indio_dev->channels = afe4404_channels; |
522 | indio_dev->num_channels = ARRAY_SIZE(afe4404_channels); |
523 | indio_dev->name = AFE4404_DRIVER_NAME; |
524 | indio_dev->info = &afe4404_iio_info; |
525 | |
526 | if (afe->irq > 0) { |
527 | afe->trig = devm_iio_trigger_alloc(afe->dev, |
528 | "%s-dev%d" , |
529 | indio_dev->name, |
530 | iio_device_id(indio_dev)); |
531 | if (!afe->trig) { |
532 | dev_err(afe->dev, "Unable to allocate IIO trigger\n" ); |
533 | ret = -ENOMEM; |
534 | goto disable_reg; |
535 | } |
536 | |
537 | iio_trigger_set_drvdata(trig: afe->trig, data: indio_dev); |
538 | |
539 | ret = iio_trigger_register(trig_info: afe->trig); |
540 | if (ret) { |
541 | dev_err(afe->dev, "Unable to register IIO trigger\n" ); |
542 | goto disable_reg; |
543 | } |
544 | |
545 | ret = devm_request_threaded_irq(dev: afe->dev, irq: afe->irq, |
546 | handler: iio_trigger_generic_data_rdy_poll, |
547 | NULL, IRQF_ONESHOT, |
548 | AFE4404_DRIVER_NAME, |
549 | dev_id: afe->trig); |
550 | if (ret) { |
551 | dev_err(afe->dev, "Unable to request IRQ\n" ); |
552 | goto disable_reg; |
553 | } |
554 | } |
555 | |
556 | ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, |
557 | afe4404_trigger_handler, NULL); |
558 | if (ret) { |
559 | dev_err(afe->dev, "Unable to setup buffer\n" ); |
560 | goto unregister_trigger; |
561 | } |
562 | |
563 | ret = iio_device_register(indio_dev); |
564 | if (ret) { |
565 | dev_err(afe->dev, "Unable to register IIO device\n" ); |
566 | goto unregister_triggered_buffer; |
567 | } |
568 | |
569 | return 0; |
570 | |
571 | unregister_triggered_buffer: |
572 | iio_triggered_buffer_cleanup(indio_dev); |
573 | unregister_trigger: |
574 | if (afe->irq > 0) |
575 | iio_trigger_unregister(trig_info: afe->trig); |
576 | disable_reg: |
577 | regulator_disable(regulator: afe->regulator); |
578 | |
579 | return ret; |
580 | } |
581 | |
582 | static void afe4404_remove(struct i2c_client *client) |
583 | { |
584 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
585 | struct afe4404_data *afe = iio_priv(indio_dev); |
586 | int ret; |
587 | |
588 | iio_device_unregister(indio_dev); |
589 | |
590 | iio_triggered_buffer_cleanup(indio_dev); |
591 | |
592 | if (afe->irq > 0) |
593 | iio_trigger_unregister(trig_info: afe->trig); |
594 | |
595 | ret = regulator_disable(regulator: afe->regulator); |
596 | if (ret) |
597 | dev_err(afe->dev, "Unable to disable regulator\n" ); |
598 | } |
599 | |
600 | static const struct i2c_device_id afe4404_ids[] = { |
601 | { "afe4404" , 0 }, |
602 | { /* sentinel */ } |
603 | }; |
604 | MODULE_DEVICE_TABLE(i2c, afe4404_ids); |
605 | |
606 | static struct i2c_driver afe4404_i2c_driver = { |
607 | .driver = { |
608 | .name = AFE4404_DRIVER_NAME, |
609 | .of_match_table = afe4404_of_match, |
610 | .pm = pm_sleep_ptr(&afe4404_pm_ops), |
611 | }, |
612 | .probe = afe4404_probe, |
613 | .remove = afe4404_remove, |
614 | .id_table = afe4404_ids, |
615 | }; |
616 | module_i2c_driver(afe4404_i2c_driver); |
617 | |
618 | MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>" ); |
619 | MODULE_DESCRIPTION("TI AFE4404 Heart Rate Monitor and Pulse Oximeter AFE" ); |
620 | MODULE_LICENSE("GPL v2" ); |
621 | |