1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * af8133j.c - Voltafield AF8133J magnetometer driver |
4 | * |
5 | * Copyright 2021 Icenowy Zheng <icenowy@aosc.io> |
6 | * Copyright 2024 Ondřej Jirman <megi@xff.cz> |
7 | */ |
8 | |
9 | #include <linux/delay.h> |
10 | #include <linux/gpio/consumer.h> |
11 | #include <linux/i2c.h> |
12 | #include <linux/module.h> |
13 | #include <linux/pm_runtime.h> |
14 | #include <linux/regmap.h> |
15 | #include <linux/regulator/consumer.h> |
16 | |
17 | #include <linux/iio/iio.h> |
18 | #include <linux/iio/trigger_consumer.h> |
19 | #include <linux/iio/triggered_buffer.h> |
20 | |
21 | #define AF8133J_REG_OUT 0x03 |
22 | #define AF8133J_REG_PCODE 0x00 |
23 | #define AF8133J_REG_PCODE_VAL 0x5e |
24 | #define AF8133J_REG_STATUS 0x02 |
25 | #define AF8133J_REG_STATUS_ACQ BIT(0) |
26 | #define AF8133J_REG_STATE 0x0a |
27 | #define AF8133J_REG_STATE_STBY 0x00 |
28 | #define AF8133J_REG_STATE_WORK 0x01 |
29 | #define AF8133J_REG_RANGE 0x0b |
30 | #define AF8133J_REG_RANGE_22G 0x12 |
31 | #define AF8133J_REG_RANGE_12G 0x34 |
32 | #define AF8133J_REG_SWR 0x11 |
33 | #define AF8133J_REG_SWR_PERFORM 0x81 |
34 | |
35 | static const char * const af8133j_supply_names[] = { |
36 | "avdd" , |
37 | "dvdd" , |
38 | }; |
39 | |
40 | struct af8133j_data { |
41 | struct i2c_client *client; |
42 | struct regmap *regmap; |
43 | /* |
44 | * Protect device internal state between starting a measurement |
45 | * and reading the result. |
46 | */ |
47 | struct mutex mutex; |
48 | struct iio_mount_matrix orientation; |
49 | |
50 | struct gpio_desc *reset_gpiod; |
51 | struct regulator_bulk_data supplies[ARRAY_SIZE(af8133j_supply_names)]; |
52 | |
53 | u8 range; |
54 | }; |
55 | |
56 | enum af8133j_axis { |
57 | AXIS_X = 0, |
58 | AXIS_Y, |
59 | AXIS_Z, |
60 | }; |
61 | |
62 | static struct iio_mount_matrix * |
63 | af8133j_get_mount_matrix(struct iio_dev *indio_dev, |
64 | const struct iio_chan_spec *chan) |
65 | { |
66 | struct af8133j_data *data = iio_priv(indio_dev); |
67 | |
68 | return &data->orientation; |
69 | } |
70 | |
71 | static const struct iio_chan_spec_ext_info af8133j_ext_info[] = { |
72 | IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, af8133j_get_mount_matrix), |
73 | { } |
74 | }; |
75 | |
76 | #define AF8133J_CHANNEL(_si, _axis) { \ |
77 | .type = IIO_MAGN, \ |
78 | .modified = 1, \ |
79 | .channel2 = IIO_MOD_ ## _axis, \ |
80 | .address = AXIS_ ## _axis, \ |
81 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
82 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
83 | .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \ |
84 | .ext_info = af8133j_ext_info, \ |
85 | .scan_index = _si, \ |
86 | .scan_type = { \ |
87 | .sign = 's', \ |
88 | .realbits = 16, \ |
89 | .storagebits = 16, \ |
90 | .endianness = IIO_LE, \ |
91 | }, \ |
92 | } |
93 | |
94 | static const struct iio_chan_spec af8133j_channels[] = { |
95 | AF8133J_CHANNEL(0, X), |
96 | AF8133J_CHANNEL(1, Y), |
97 | AF8133J_CHANNEL(2, Z), |
98 | IIO_CHAN_SOFT_TIMESTAMP(3), |
99 | }; |
100 | |
101 | static int af8133j_product_check(struct af8133j_data *data) |
102 | { |
103 | struct device *dev = &data->client->dev; |
104 | unsigned int val; |
105 | int ret; |
106 | |
107 | ret = regmap_read(map: data->regmap, AF8133J_REG_PCODE, val: &val); |
108 | if (ret) { |
109 | dev_err(dev, "Error reading product code (%d)\n" , ret); |
110 | return ret; |
111 | } |
112 | |
113 | if (val != AF8133J_REG_PCODE_VAL) { |
114 | dev_warn(dev, "Invalid product code (0x%02x)\n" , val); |
115 | return 0; /* Allow unknown ID so fallback compatibles work */ |
116 | } |
117 | |
118 | return 0; |
119 | } |
120 | |
121 | static int af8133j_reset(struct af8133j_data *data) |
122 | { |
123 | struct device *dev = &data->client->dev; |
124 | int ret; |
125 | |
126 | if (data->reset_gpiod) { |
127 | /* If we have GPIO reset line, use it */ |
128 | gpiod_set_value_cansleep(desc: data->reset_gpiod, value: 1); |
129 | udelay(10); |
130 | gpiod_set_value_cansleep(desc: data->reset_gpiod, value: 0); |
131 | } else { |
132 | /* Otherwise use software reset */ |
133 | ret = regmap_write(map: data->regmap, AF8133J_REG_SWR, |
134 | AF8133J_REG_SWR_PERFORM); |
135 | if (ret) { |
136 | dev_err(dev, "Failed to reset the chip\n" ); |
137 | return ret; |
138 | } |
139 | } |
140 | |
141 | /* Wait for reset to finish */ |
142 | usleep_range(min: 1000, max: 1100); |
143 | |
144 | /* Restore range setting */ |
145 | if (data->range == AF8133J_REG_RANGE_22G) { |
146 | ret = regmap_write(map: data->regmap, AF8133J_REG_RANGE, val: data->range); |
147 | if (ret) |
148 | return ret; |
149 | } |
150 | |
151 | return 0; |
152 | } |
153 | |
154 | static void af8133j_power_down(struct af8133j_data *data) |
155 | { |
156 | gpiod_set_value_cansleep(desc: data->reset_gpiod, value: 1); |
157 | regulator_bulk_disable(ARRAY_SIZE(data->supplies), consumers: data->supplies); |
158 | } |
159 | |
160 | static int af8133j_power_up(struct af8133j_data *data) |
161 | { |
162 | struct device *dev = &data->client->dev; |
163 | int ret; |
164 | |
165 | ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), consumers: data->supplies); |
166 | if (ret) { |
167 | dev_err(dev, "Could not enable regulators\n" ); |
168 | return ret; |
169 | } |
170 | |
171 | gpiod_set_value_cansleep(desc: data->reset_gpiod, value: 0); |
172 | |
173 | /* Wait for power on reset */ |
174 | usleep_range(min: 15000, max: 16000); |
175 | |
176 | ret = af8133j_reset(data); |
177 | if (ret) { |
178 | af8133j_power_down(data); |
179 | return ret; |
180 | } |
181 | |
182 | return 0; |
183 | } |
184 | |
185 | static int af8133j_take_measurement(struct af8133j_data *data) |
186 | { |
187 | unsigned int val; |
188 | int ret; |
189 | |
190 | ret = regmap_write(map: data->regmap, |
191 | AF8133J_REG_STATE, AF8133J_REG_STATE_WORK); |
192 | if (ret) |
193 | return ret; |
194 | |
195 | /* The datasheet says "Mesaure Time <1.5ms" */ |
196 | ret = regmap_read_poll_timeout(data->regmap, AF8133J_REG_STATUS, val, |
197 | val & AF8133J_REG_STATUS_ACQ, |
198 | 500, 1500); |
199 | if (ret) |
200 | return ret; |
201 | |
202 | ret = regmap_write(map: data->regmap, |
203 | AF8133J_REG_STATE, AF8133J_REG_STATE_STBY); |
204 | if (ret) |
205 | return ret; |
206 | |
207 | return 0; |
208 | } |
209 | |
210 | static int af8133j_read_measurement(struct af8133j_data *data, __le16 buf[3]) |
211 | { |
212 | struct device *dev = &data->client->dev; |
213 | int ret; |
214 | |
215 | ret = pm_runtime_resume_and_get(dev); |
216 | if (ret) { |
217 | /* |
218 | * Ignore EACCES because that happens when RPM is disabled |
219 | * during system sleep, while userspace leave eg. hrtimer |
220 | * trigger attached and IIO core keeps trying to do measurements. |
221 | */ |
222 | if (ret != -EACCES) |
223 | dev_err(dev, "Failed to power on (%d)\n" , ret); |
224 | return ret; |
225 | } |
226 | |
227 | scoped_guard(mutex, &data->mutex) { |
228 | ret = af8133j_take_measurement(data); |
229 | if (ret) |
230 | goto out_rpm_put; |
231 | |
232 | ret = regmap_bulk_read(map: data->regmap, AF8133J_REG_OUT, |
233 | val: buf, val_count: sizeof(__le16) * 3); |
234 | } |
235 | |
236 | out_rpm_put: |
237 | pm_runtime_mark_last_busy(dev); |
238 | pm_runtime_put_autosuspend(dev); |
239 | |
240 | return ret; |
241 | } |
242 | |
243 | static const int af8133j_scales[][2] = { |
244 | [0] = { 0, 366210 }, /* 12 gauss */ |
245 | [1] = { 0, 671386 }, /* 22 gauss */ |
246 | }; |
247 | |
248 | static int af8133j_read_raw(struct iio_dev *indio_dev, |
249 | struct iio_chan_spec const *chan, int *val, |
250 | int *val2, long mask) |
251 | { |
252 | struct af8133j_data *data = iio_priv(indio_dev); |
253 | __le16 buf[3]; |
254 | int ret; |
255 | |
256 | switch (mask) { |
257 | case IIO_CHAN_INFO_RAW: |
258 | ret = af8133j_read_measurement(data, buf); |
259 | if (ret) |
260 | return ret; |
261 | |
262 | *val = sign_extend32(le16_to_cpu(buf[chan->address]), |
263 | index: chan->scan_type.realbits - 1); |
264 | return IIO_VAL_INT; |
265 | case IIO_CHAN_INFO_SCALE: |
266 | *val = 0; |
267 | |
268 | if (data->range == AF8133J_REG_RANGE_12G) |
269 | *val2 = af8133j_scales[0][1]; |
270 | else |
271 | *val2 = af8133j_scales[1][1]; |
272 | |
273 | return IIO_VAL_INT_PLUS_NANO; |
274 | default: |
275 | return -EINVAL; |
276 | } |
277 | } |
278 | |
279 | static int af8133j_read_avail(struct iio_dev *indio_dev, |
280 | struct iio_chan_spec const *chan, |
281 | const int **vals, int *type, int *length, |
282 | long mask) |
283 | { |
284 | switch (mask) { |
285 | case IIO_CHAN_INFO_SCALE: |
286 | *vals = (const int *)af8133j_scales; |
287 | *length = ARRAY_SIZE(af8133j_scales) * 2; |
288 | *type = IIO_VAL_INT_PLUS_NANO; |
289 | return IIO_AVAIL_LIST; |
290 | default: |
291 | return -EINVAL; |
292 | } |
293 | } |
294 | |
295 | static int af8133j_set_scale(struct af8133j_data *data, |
296 | unsigned int val, unsigned int val2) |
297 | { |
298 | struct device *dev = &data->client->dev; |
299 | u8 range; |
300 | int ret = 0; |
301 | |
302 | if (af8133j_scales[0][0] == val && af8133j_scales[0][1] == val2) |
303 | range = AF8133J_REG_RANGE_12G; |
304 | else if (af8133j_scales[1][0] == val && af8133j_scales[1][1] == val2) |
305 | range = AF8133J_REG_RANGE_22G; |
306 | else |
307 | return -EINVAL; |
308 | |
309 | pm_runtime_disable(dev); |
310 | |
311 | /* |
312 | * When suspended, just store the new range to data->range to be |
313 | * applied later during power up. |
314 | */ |
315 | if (!pm_runtime_status_suspended(dev)) |
316 | scoped_guard(mutex, &data->mutex) |
317 | ret = regmap_write(map: data->regmap, |
318 | AF8133J_REG_RANGE, val: range); |
319 | |
320 | pm_runtime_enable(dev); |
321 | |
322 | data->range = range; |
323 | return ret; |
324 | } |
325 | |
326 | static int af8133j_write_raw(struct iio_dev *indio_dev, |
327 | struct iio_chan_spec const *chan, |
328 | int val, int val2, long mask) |
329 | { |
330 | struct af8133j_data *data = iio_priv(indio_dev); |
331 | |
332 | switch (mask) { |
333 | case IIO_CHAN_INFO_SCALE: |
334 | return af8133j_set_scale(data, val, val2); |
335 | default: |
336 | return -EINVAL; |
337 | } |
338 | } |
339 | |
340 | static int af8133j_write_raw_get_fmt(struct iio_dev *indio_dev, |
341 | struct iio_chan_spec const *chan, |
342 | long mask) |
343 | { |
344 | return IIO_VAL_INT_PLUS_NANO; |
345 | } |
346 | |
347 | static const struct iio_info af8133j_info = { |
348 | .read_raw = af8133j_read_raw, |
349 | .read_avail = af8133j_read_avail, |
350 | .write_raw = af8133j_write_raw, |
351 | .write_raw_get_fmt = af8133j_write_raw_get_fmt, |
352 | }; |
353 | |
354 | static irqreturn_t af8133j_trigger_handler(int irq, void *p) |
355 | { |
356 | struct iio_poll_func *pf = p; |
357 | struct iio_dev *indio_dev = pf->indio_dev; |
358 | struct af8133j_data *data = iio_priv(indio_dev); |
359 | s64 timestamp = iio_get_time_ns(indio_dev); |
360 | struct { |
361 | __le16 values[3]; |
362 | s64 timestamp __aligned(8); |
363 | } sample; |
364 | int ret; |
365 | |
366 | memset(&sample, 0, sizeof(sample)); |
367 | |
368 | ret = af8133j_read_measurement(data, buf: sample.values); |
369 | if (ret) |
370 | goto out_done; |
371 | |
372 | iio_push_to_buffers_with_timestamp(indio_dev, data: &sample, timestamp); |
373 | |
374 | out_done: |
375 | iio_trigger_notify_done(trig: indio_dev->trig); |
376 | |
377 | return IRQ_HANDLED; |
378 | } |
379 | |
380 | static const struct regmap_config af8133j_regmap_config = { |
381 | .name = "af8133j_regmap" , |
382 | .reg_bits = 8, |
383 | .val_bits = 8, |
384 | .max_register = AF8133J_REG_SWR, |
385 | .cache_type = REGCACHE_NONE, |
386 | }; |
387 | |
388 | static void af8133j_power_down_action(void *ptr) |
389 | { |
390 | struct af8133j_data *data = ptr; |
391 | |
392 | if (!pm_runtime_status_suspended(dev: &data->client->dev)) |
393 | af8133j_power_down(data); |
394 | } |
395 | |
396 | static int af8133j_probe(struct i2c_client *client) |
397 | { |
398 | struct device *dev = &client->dev; |
399 | struct af8133j_data *data; |
400 | struct iio_dev *indio_dev; |
401 | struct regmap *regmap; |
402 | int ret, i; |
403 | |
404 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*data)); |
405 | if (!indio_dev) |
406 | return -ENOMEM; |
407 | |
408 | regmap = devm_regmap_init_i2c(client, &af8133j_regmap_config); |
409 | if (IS_ERR(ptr: regmap)) |
410 | return dev_err_probe(dev, err: PTR_ERR(ptr: regmap), |
411 | fmt: "regmap initialization failed\n" ); |
412 | |
413 | data = iio_priv(indio_dev); |
414 | i2c_set_clientdata(client, data: indio_dev); |
415 | data->client = client; |
416 | data->regmap = regmap; |
417 | data->range = AF8133J_REG_RANGE_12G; |
418 | mutex_init(&data->mutex); |
419 | |
420 | data->reset_gpiod = devm_gpiod_get_optional(dev, con_id: "reset" , flags: GPIOD_OUT_HIGH); |
421 | if (IS_ERR(ptr: data->reset_gpiod)) |
422 | return dev_err_probe(dev, err: PTR_ERR(ptr: data->reset_gpiod), |
423 | fmt: "Failed to get reset gpio\n" ); |
424 | |
425 | for (i = 0; i < ARRAY_SIZE(af8133j_supply_names); i++) |
426 | data->supplies[i].supply = af8133j_supply_names[i]; |
427 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), |
428 | consumers: data->supplies); |
429 | if (ret) |
430 | return ret; |
431 | |
432 | ret = iio_read_mount_matrix(dev, matrix: &data->orientation); |
433 | if (ret) |
434 | return dev_err_probe(dev, err: ret, fmt: "Failed to read mount matrix\n" ); |
435 | |
436 | ret = af8133j_power_up(data); |
437 | if (ret) |
438 | return ret; |
439 | |
440 | pm_runtime_set_active(dev); |
441 | |
442 | ret = devm_add_action_or_reset(dev, af8133j_power_down_action, data); |
443 | if (ret) |
444 | return ret; |
445 | |
446 | ret = af8133j_product_check(data); |
447 | if (ret) |
448 | return ret; |
449 | |
450 | pm_runtime_get_noresume(dev); |
451 | pm_runtime_use_autosuspend(dev); |
452 | pm_runtime_set_autosuspend_delay(dev, delay: 500); |
453 | ret = devm_pm_runtime_enable(dev); |
454 | if (ret) |
455 | return ret; |
456 | |
457 | pm_runtime_put_autosuspend(dev); |
458 | |
459 | indio_dev->info = &af8133j_info; |
460 | indio_dev->name = "af8133j" ; |
461 | indio_dev->channels = af8133j_channels; |
462 | indio_dev->num_channels = ARRAY_SIZE(af8133j_channels); |
463 | indio_dev->modes = INDIO_DIRECT_MODE; |
464 | |
465 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, |
466 | &af8133j_trigger_handler, NULL); |
467 | if (ret) |
468 | return dev_err_probe(dev: &client->dev, err: ret, |
469 | fmt: "Failed to setup iio triggered buffer\n" ); |
470 | |
471 | ret = devm_iio_device_register(dev, indio_dev); |
472 | if (ret) |
473 | return dev_err_probe(dev, err: ret, fmt: "Failed to register iio device" ); |
474 | |
475 | return 0; |
476 | } |
477 | |
478 | static int af8133j_runtime_suspend(struct device *dev) |
479 | { |
480 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
481 | struct af8133j_data *data = iio_priv(indio_dev); |
482 | |
483 | af8133j_power_down(data); |
484 | |
485 | return 0; |
486 | } |
487 | |
488 | static int af8133j_runtime_resume(struct device *dev) |
489 | { |
490 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
491 | struct af8133j_data *data = iio_priv(indio_dev); |
492 | |
493 | return af8133j_power_up(data); |
494 | } |
495 | |
496 | static const struct dev_pm_ops af8133j_pm_ops = { |
497 | SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) |
498 | RUNTIME_PM_OPS(af8133j_runtime_suspend, af8133j_runtime_resume, NULL) |
499 | }; |
500 | |
501 | static const struct of_device_id af8133j_of_match[] = { |
502 | { .compatible = "voltafield,af8133j" , }, |
503 | { } |
504 | }; |
505 | MODULE_DEVICE_TABLE(of, af8133j_of_match); |
506 | |
507 | static const struct i2c_device_id af8133j_id[] = { |
508 | { "af8133j" , 0 }, |
509 | { } |
510 | }; |
511 | MODULE_DEVICE_TABLE(i2c, af8133j_id); |
512 | |
513 | static struct i2c_driver af8133j_driver = { |
514 | .driver = { |
515 | .name = "af8133j" , |
516 | .of_match_table = af8133j_of_match, |
517 | .pm = pm_ptr(&af8133j_pm_ops), |
518 | }, |
519 | .probe = af8133j_probe, |
520 | .id_table = af8133j_id, |
521 | }; |
522 | |
523 | module_i2c_driver(af8133j_driver); |
524 | |
525 | MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>" ); |
526 | MODULE_AUTHOR("Ondřej Jirman <megi@xff.cz>" ); |
527 | MODULE_DESCRIPTION("Voltafield AF8133J magnetic sensor driver" ); |
528 | MODULE_LICENSE("GPL" ); |
529 | |