1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Serial line interface for Bosh BNO055 IMU (via serdev). |
4 | * This file implements serial communication up to the register read/write |
5 | * level. |
6 | * |
7 | * Copyright (C) 2021-2022 Istituto Italiano di Tecnologia |
8 | * Electronic Design Laboratory |
9 | * Written by Andrea Merello <andrea.merello@iit.it> |
10 | * |
11 | * This driver is based on |
12 | * Plantower PMS7003 particulate matter sensor driver |
13 | * Which is |
14 | * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> |
15 | */ |
16 | |
17 | #include <linux/completion.h> |
18 | #include <linux/device.h> |
19 | #include <linux/errno.h> |
20 | #include <linux/jiffies.h> |
21 | #include <linux/kernel.h> |
22 | #include <linux/mod_devicetable.h> |
23 | #include <linux/module.h> |
24 | #include <linux/mutex.h> |
25 | #include <linux/regmap.h> |
26 | #include <linux/serdev.h> |
27 | |
28 | #include "bno055_ser_trace.h" |
29 | #include "bno055.h" |
30 | |
31 | /* |
32 | * Register writes cmd have the following format |
33 | * +------+------+-----+-----+----- ... ----+ |
34 | * | 0xAA | 0xOO | REG | LEN | payload[LEN] | |
35 | * +------+------+-----+-----+----- ... ----+ |
36 | * |
37 | * Register write responses have the following format |
38 | * +------+----------+ |
39 | * | 0xEE | ERROCODE | |
40 | * +------+----------+ |
41 | * |
42 | * .. except when writing the SYS_RST bit (i.e. triggering a system reset); in |
43 | * case the IMU accepts the command, then it resets without responding. We don't |
44 | * handle this (yet) here (so we inform the common bno055 code not to perform |
45 | * sw resets - bno055 on serial bus basically requires the hw reset pin). |
46 | * |
47 | * Register read have the following format |
48 | * +------+------+-----+-----+ |
49 | * | 0xAA | 0xO1 | REG | LEN | |
50 | * +------+------+-----+-----+ |
51 | * |
52 | * Successful register read response have the following format |
53 | * +------+-----+----- ... ----+ |
54 | * | 0xBB | LEN | payload[LEN] | |
55 | * +------+-----+----- ... ----+ |
56 | * |
57 | * Failed register read response have the following format |
58 | * +------+--------+ |
59 | * | 0xEE | ERRCODE| (ERRCODE always > 1) |
60 | * +------+--------+ |
61 | * |
62 | * Error codes are |
63 | * 01: OK |
64 | * 02: read/write FAIL |
65 | * 04: invalid address |
66 | * 05: write on RO |
67 | * 06: wrong start byte |
68 | * 07: bus overrun |
69 | * 08: len too high |
70 | * 09: len too low |
71 | * 10: bus RX byte timeout (timeout is 30mS) |
72 | * |
73 | * |
74 | * **WORKAROUND ALERT** |
75 | * |
76 | * Serial communication seems very fragile: the BNO055 buffer seems to overflow |
77 | * very easy; BNO055 seems able to sink few bytes, then it needs a brief pause. |
78 | * On the other hand, it is also picky on timeout: if there is a pause > 30mS in |
79 | * between two bytes then the transaction fails (IMU internal RX FSM resets). |
80 | * |
81 | * BNO055 has been seen also failing to process commands in case we send them |
82 | * too close each other (or if it is somehow busy?) |
83 | * |
84 | * In particular I saw these scenarios: |
85 | * 1) If we send 2 bytes per time, then the IMU never(?) overflows. |
86 | * 2) If we send 4 bytes per time (i.e. the full header), then the IMU could |
87 | * overflow, but it seem to sink all 4 bytes, then it returns error. |
88 | * 3) If we send more than 4 bytes, the IMU could overflow, and I saw it sending |
89 | * error after 4 bytes are sent; we have troubles in synchronizing again, |
90 | * because we are still sending data, and the IMU interprets it as the 1st |
91 | * byte of a new command. |
92 | * |
93 | * While we must avoid case 3, we could send 4 bytes per time and eventually |
94 | * retry in case of failure; this seemed convenient for reads (which requires |
95 | * TXing exactly 4 bytes), however it has been seen that, depending by the IMU |
96 | * settings (e.g. LPF), failures became less or more frequent; in certain IMU |
97 | * configurations they are very rare, but in certain others we keeps failing |
98 | * even after like 30 retries. |
99 | * |
100 | * So, we just split TXes in [2-bytes + delay] steps, and still keep an eye on |
101 | * the IMU response; in case it overflows (which is now unlikely), we retry. |
102 | */ |
103 | |
104 | /* |
105 | * Read operation overhead: |
106 | * 4 bytes req + 2byte resp hdr. |
107 | * 6 bytes = 60 bit (considering 1start + 1stop bits). |
108 | * 60/115200 = ~520uS + about 2500mS delay -> ~3mS |
109 | * In 3mS we could read back about 34 bytes that means 17 samples, this means |
110 | * that in case of scattered reads in which the gap is 17 samples or less it is |
111 | * still convenient to go for a burst. |
112 | * We have to take into account also IMU response time - IMU seems to be often |
113 | * reasonably quick to respond, but sometimes it seems to be in some "critical |
114 | * section" in which it delays handling of serial protocol. Because of this we |
115 | * round-up to 22, which is the max number of samples, always bursting indeed. |
116 | */ |
117 | #define BNO055_SER_XFER_BURST_BREAK_THRESHOLD 22 |
118 | |
119 | struct bno055_ser_priv { |
120 | enum { |
121 | CMD_NONE, |
122 | CMD_READ, |
123 | CMD_WRITE, |
124 | } expect_response; |
125 | int expected_data_len; |
126 | u8 *response_buf; |
127 | |
128 | /** |
129 | * enum cmd_status - represent the status of a command sent to the HW. |
130 | * @STATUS_CRIT: The command failed: the serial communication failed. |
131 | * @STATUS_OK: The command executed successfully. |
132 | * @STATUS_FAIL: The command failed: HW responded with an error. |
133 | */ |
134 | enum { |
135 | STATUS_CRIT = -1, |
136 | STATUS_OK = 0, |
137 | STATUS_FAIL = 1, |
138 | } cmd_status; |
139 | |
140 | /* |
141 | * Protects all the above fields, which are accessed in behalf of both |
142 | * the serdev RX callback and the regmap side |
143 | */ |
144 | struct mutex lock; |
145 | |
146 | /* Only accessed in serdev RX callback context*/ |
147 | struct { |
148 | enum { |
149 | RX_IDLE, |
150 | RX_START, |
151 | RX_DATA, |
152 | } state; |
153 | int databuf_count; |
154 | int expected_len; |
155 | int type; |
156 | } rx; |
157 | |
158 | /* Never accessed in behalf of serdev RX callback context */ |
159 | bool cmd_stale; |
160 | |
161 | struct completion cmd_complete; |
162 | struct serdev_device *serdev; |
163 | }; |
164 | |
165 | static int bno055_ser_send_chunk(struct bno055_ser_priv *priv, const u8 *data, int len) |
166 | { |
167 | int ret; |
168 | |
169 | trace_send_chunk(len, data); |
170 | ret = serdev_device_write(priv->serdev, data, len, msecs_to_jiffies(m: 25)); |
171 | if (ret < 0) |
172 | return ret; |
173 | |
174 | if (ret < len) |
175 | return -EIO; |
176 | |
177 | return 0; |
178 | } |
179 | |
180 | /* |
181 | * Send a read or write command. |
182 | * 'data' can be NULL (used in read case). 'len' parameter is always valid; in |
183 | * case 'data' is non-NULL then it must match 'data' size. |
184 | */ |
185 | static int bno055_ser_do_send_cmd(struct bno055_ser_priv *priv, |
186 | bool read, int addr, int len, const u8 *data) |
187 | { |
188 | u8 hdr[] = {0xAA, read, addr, len}; |
189 | int chunk_len; |
190 | int ret; |
191 | |
192 | ret = bno055_ser_send_chunk(priv, data: hdr, len: 2); |
193 | if (ret) |
194 | goto fail; |
195 | usleep_range(min: 2000, max: 3000); |
196 | ret = bno055_ser_send_chunk(priv, data: hdr + 2, len: 2); |
197 | if (ret) |
198 | goto fail; |
199 | |
200 | if (read) |
201 | return 0; |
202 | |
203 | while (len) { |
204 | chunk_len = min(len, 2); |
205 | usleep_range(min: 2000, max: 3000); |
206 | ret = bno055_ser_send_chunk(priv, data, len: chunk_len); |
207 | if (ret) |
208 | goto fail; |
209 | data += chunk_len; |
210 | len -= chunk_len; |
211 | } |
212 | |
213 | return 0; |
214 | fail: |
215 | /* waiting more than 30mS should clear the BNO055 internal state */ |
216 | usleep_range(min: 40000, max: 50000); |
217 | return ret; |
218 | } |
219 | |
220 | static int bno055_ser_send_cmd(struct bno055_ser_priv *priv, |
221 | bool read, int addr, int len, const u8 *data) |
222 | { |
223 | const int retry_max = 5; |
224 | int retry = retry_max; |
225 | int ret = 0; |
226 | |
227 | /* |
228 | * In case previous command was interrupted we still need to wait it to |
229 | * complete before we can issue new commands |
230 | */ |
231 | if (priv->cmd_stale) { |
232 | ret = wait_for_completion_interruptible_timeout(x: &priv->cmd_complete, |
233 | timeout: msecs_to_jiffies(m: 100)); |
234 | if (ret == -ERESTARTSYS) |
235 | return -ERESTARTSYS; |
236 | |
237 | priv->cmd_stale = false; |
238 | /* if serial protocol broke, bail out */ |
239 | if (priv->cmd_status == STATUS_CRIT) |
240 | return -EIO; |
241 | } |
242 | |
243 | /* |
244 | * Try to convince the IMU to cooperate.. as explained in the comments |
245 | * at the top of this file, the IMU could also refuse the command (i.e. |
246 | * it is not ready yet); retry in this case. |
247 | */ |
248 | do { |
249 | mutex_lock(&priv->lock); |
250 | priv->expect_response = read ? CMD_READ : CMD_WRITE; |
251 | reinit_completion(x: &priv->cmd_complete); |
252 | mutex_unlock(lock: &priv->lock); |
253 | |
254 | if (retry != retry_max) |
255 | trace_cmd_retry(read, addr, retry: retry_max - retry); |
256 | ret = bno055_ser_do_send_cmd(priv, read, addr, len, data); |
257 | if (ret) |
258 | continue; |
259 | |
260 | ret = wait_for_completion_interruptible_timeout(x: &priv->cmd_complete, |
261 | timeout: msecs_to_jiffies(m: 100)); |
262 | if (ret == -ERESTARTSYS) { |
263 | priv->cmd_stale = true; |
264 | return -ERESTARTSYS; |
265 | } |
266 | |
267 | if (!ret) |
268 | return -ETIMEDOUT; |
269 | |
270 | if (priv->cmd_status == STATUS_OK) |
271 | return 0; |
272 | if (priv->cmd_status == STATUS_CRIT) |
273 | return -EIO; |
274 | |
275 | /* loop in case priv->cmd_status == STATUS_FAIL */ |
276 | } while (--retry); |
277 | |
278 | if (ret < 0) |
279 | return ret; |
280 | if (priv->cmd_status == STATUS_FAIL) |
281 | return -EINVAL; |
282 | return 0; |
283 | } |
284 | |
285 | static int bno055_ser_write_reg(void *context, const void *_data, size_t count) |
286 | { |
287 | const u8 *data = _data; |
288 | struct bno055_ser_priv *priv = context; |
289 | |
290 | if (count < 2) { |
291 | dev_err(&priv->serdev->dev, "Invalid write count %zu" , count); |
292 | return -EINVAL; |
293 | } |
294 | |
295 | trace_write_reg(addr: data[0], value: data[1]); |
296 | return bno055_ser_send_cmd(priv, read: 0, addr: data[0], len: count - 1, data: data + 1); |
297 | } |
298 | |
299 | static int bno055_ser_read_reg(void *context, |
300 | const void *_reg, size_t reg_size, |
301 | void *val, size_t val_size) |
302 | { |
303 | int ret; |
304 | int reg_addr; |
305 | const u8 *reg = _reg; |
306 | struct bno055_ser_priv *priv = context; |
307 | |
308 | if (val_size > 128) { |
309 | dev_err(&priv->serdev->dev, "Invalid read valsize %zu" , val_size); |
310 | return -EINVAL; |
311 | } |
312 | |
313 | reg_addr = *reg; |
314 | trace_read_reg(addr: reg_addr, len: val_size); |
315 | mutex_lock(&priv->lock); |
316 | priv->expected_data_len = val_size; |
317 | priv->response_buf = val; |
318 | mutex_unlock(lock: &priv->lock); |
319 | |
320 | ret = bno055_ser_send_cmd(priv, read: 1, addr: reg_addr, len: val_size, NULL); |
321 | |
322 | mutex_lock(&priv->lock); |
323 | priv->response_buf = NULL; |
324 | mutex_unlock(lock: &priv->lock); |
325 | |
326 | return ret; |
327 | } |
328 | |
329 | /* |
330 | * Handler for received data; this is called from the receiver callback whenever |
331 | * it got some packet from the serial bus. The status tells us whether the |
332 | * packet is valid (i.e. header ok && received payload len consistent wrt the |
333 | * header). It's now our responsibility to check whether this is what we |
334 | * expected, of whether we got some unexpected, yet valid, packet. |
335 | */ |
336 | static void bno055_ser_handle_rx(struct bno055_ser_priv *priv, int status) |
337 | { |
338 | mutex_lock(&priv->lock); |
339 | switch (priv->expect_response) { |
340 | case CMD_NONE: |
341 | dev_warn(&priv->serdev->dev, "received unexpected, yet valid, data from sensor" ); |
342 | mutex_unlock(lock: &priv->lock); |
343 | return; |
344 | |
345 | case CMD_READ: |
346 | priv->cmd_status = status; |
347 | if (status == STATUS_OK && |
348 | priv->rx.databuf_count != priv->expected_data_len) { |
349 | /* |
350 | * If we got here, then the lower layer serial protocol |
351 | * seems consistent with itself; if we got an unexpected |
352 | * amount of data then signal it as a non critical error |
353 | */ |
354 | priv->cmd_status = STATUS_FAIL; |
355 | dev_warn(&priv->serdev->dev, |
356 | "received an unexpected amount of, yet valid, data from sensor" ); |
357 | } |
358 | break; |
359 | |
360 | case CMD_WRITE: |
361 | priv->cmd_status = status; |
362 | break; |
363 | } |
364 | |
365 | priv->expect_response = CMD_NONE; |
366 | mutex_unlock(lock: &priv->lock); |
367 | complete(&priv->cmd_complete); |
368 | } |
369 | |
370 | /* |
371 | * Serdev receiver FSM. This tracks the serial communication and parse the |
372 | * header. It pushes packets to bno055_ser_handle_rx(), eventually communicating |
373 | * failures (i.e. malformed packets). |
374 | * Ideally it doesn't know anything about upper layer (i.e. if this is the |
375 | * packet we were really expecting), but since we copies the payload into the |
376 | * receiver buffer (that is not valid when i.e. we don't expect data), we |
377 | * snoop a bit in the upper layer.. |
378 | * Also, we assume to RX one pkt per time (i.e. the HW doesn't send anything |
379 | * unless we require to AND we don't queue more than one request per time). |
380 | */ |
381 | static size_t bno055_ser_receive_buf(struct serdev_device *serdev, |
382 | const u8 *buf, size_t size) |
383 | { |
384 | int status; |
385 | struct bno055_ser_priv *priv = serdev_device_get_drvdata(serdev); |
386 | size_t remaining = size; |
387 | |
388 | if (size == 0) |
389 | return 0; |
390 | |
391 | trace_recv(len: size, buf); |
392 | switch (priv->rx.state) { |
393 | case RX_IDLE: |
394 | /* |
395 | * New packet. |
396 | * Check for its 1st byte that identifies the pkt type. |
397 | */ |
398 | if (buf[0] != 0xEE && buf[0] != 0xBB) { |
399 | dev_err(&priv->serdev->dev, |
400 | "Invalid packet start %x" , buf[0]); |
401 | bno055_ser_handle_rx(priv, status: STATUS_CRIT); |
402 | break; |
403 | } |
404 | priv->rx.type = buf[0]; |
405 | priv->rx.state = RX_START; |
406 | remaining--; |
407 | buf++; |
408 | priv->rx.databuf_count = 0; |
409 | fallthrough; |
410 | |
411 | case RX_START: |
412 | /* |
413 | * Packet RX in progress, we expect either 1-byte len or 1-byte |
414 | * status depending by the packet type. |
415 | */ |
416 | if (remaining == 0) |
417 | break; |
418 | |
419 | if (priv->rx.type == 0xEE) { |
420 | if (remaining > 1) { |
421 | dev_err(&priv->serdev->dev, "EE pkt. Extra data received" ); |
422 | status = STATUS_CRIT; |
423 | } else { |
424 | status = (buf[0] == 1) ? STATUS_OK : STATUS_FAIL; |
425 | } |
426 | bno055_ser_handle_rx(priv, status); |
427 | priv->rx.state = RX_IDLE; |
428 | break; |
429 | |
430 | } else { |
431 | /*priv->rx.type == 0xBB */ |
432 | priv->rx.state = RX_DATA; |
433 | priv->rx.expected_len = buf[0]; |
434 | remaining--; |
435 | buf++; |
436 | } |
437 | fallthrough; |
438 | |
439 | case RX_DATA: |
440 | /* Header parsed; now receiving packet data payload */ |
441 | if (remaining == 0) |
442 | break; |
443 | |
444 | if (priv->rx.databuf_count + remaining > priv->rx.expected_len) { |
445 | /* |
446 | * This is an inconsistency in serial protocol, we lost |
447 | * sync and we don't know how to handle further data |
448 | */ |
449 | dev_err(&priv->serdev->dev, "BB pkt. Extra data received" ); |
450 | bno055_ser_handle_rx(priv, status: STATUS_CRIT); |
451 | priv->rx.state = RX_IDLE; |
452 | break; |
453 | } |
454 | |
455 | mutex_lock(&priv->lock); |
456 | /* |
457 | * NULL e.g. when read cmd is stale or when no read cmd is |
458 | * actually pending. |
459 | */ |
460 | if (priv->response_buf && |
461 | /* |
462 | * Snoop on the upper layer protocol stuff to make sure not |
463 | * to write to an invalid memory. Apart for this, let's the |
464 | * upper layer manage any inconsistency wrt expected data |
465 | * len (as long as the serial protocol is consistent wrt |
466 | * itself (i.e. response header is consistent with received |
467 | * response len. |
468 | */ |
469 | (priv->rx.databuf_count + remaining <= priv->expected_data_len)) |
470 | memcpy(priv->response_buf + priv->rx.databuf_count, |
471 | buf, remaining); |
472 | mutex_unlock(lock: &priv->lock); |
473 | |
474 | priv->rx.databuf_count += remaining; |
475 | |
476 | /* |
477 | * Reached expected len advertised by the IMU for the current |
478 | * packet. Pass it to the upper layer (for us it is just valid). |
479 | */ |
480 | if (priv->rx.databuf_count == priv->rx.expected_len) { |
481 | bno055_ser_handle_rx(priv, status: STATUS_OK); |
482 | priv->rx.state = RX_IDLE; |
483 | } |
484 | break; |
485 | } |
486 | |
487 | return size; |
488 | } |
489 | |
490 | static const struct serdev_device_ops bno055_ser_serdev_ops = { |
491 | .receive_buf = bno055_ser_receive_buf, |
492 | .write_wakeup = serdev_device_write_wakeup, |
493 | }; |
494 | |
495 | static struct regmap_bus bno055_ser_regmap_bus = { |
496 | .write = bno055_ser_write_reg, |
497 | .read = bno055_ser_read_reg, |
498 | }; |
499 | |
500 | static int bno055_ser_probe(struct serdev_device *serdev) |
501 | { |
502 | struct bno055_ser_priv *priv; |
503 | struct regmap *regmap; |
504 | int ret; |
505 | |
506 | priv = devm_kzalloc(dev: &serdev->dev, size: sizeof(*priv), GFP_KERNEL); |
507 | if (!priv) |
508 | return -ENOMEM; |
509 | |
510 | serdev_device_set_drvdata(serdev, data: priv); |
511 | priv->serdev = serdev; |
512 | mutex_init(&priv->lock); |
513 | init_completion(x: &priv->cmd_complete); |
514 | |
515 | serdev_device_set_client_ops(serdev, ops: &bno055_ser_serdev_ops); |
516 | ret = devm_serdev_device_open(&serdev->dev, serdev); |
517 | if (ret) |
518 | return ret; |
519 | |
520 | if (serdev_device_set_baudrate(serdev, 115200) != 115200) { |
521 | dev_err(&serdev->dev, "Cannot set required baud rate" ); |
522 | return -EIO; |
523 | } |
524 | |
525 | ret = serdev_device_set_parity(serdev, parity: SERDEV_PARITY_NONE); |
526 | if (ret) { |
527 | dev_err(&serdev->dev, "Cannot set required parity setting" ); |
528 | return ret; |
529 | } |
530 | serdev_device_set_flow_control(serdev, false); |
531 | |
532 | regmap = devm_regmap_init(&serdev->dev, &bno055_ser_regmap_bus, |
533 | priv, &bno055_regmap_config); |
534 | if (IS_ERR(ptr: regmap)) |
535 | return dev_err_probe(dev: &serdev->dev, err: PTR_ERR(ptr: regmap), |
536 | fmt: "Unable to init register map" ); |
537 | |
538 | return bno055_probe(dev: &serdev->dev, regmap, |
539 | BNO055_SER_XFER_BURST_BREAK_THRESHOLD, sw_reset: false); |
540 | } |
541 | |
542 | static const struct of_device_id bno055_ser_of_match[] = { |
543 | { .compatible = "bosch,bno055" }, |
544 | { } |
545 | }; |
546 | MODULE_DEVICE_TABLE(of, bno055_ser_of_match); |
547 | |
548 | static struct serdev_device_driver bno055_ser_driver = { |
549 | .driver = { |
550 | .name = "bno055-ser" , |
551 | .of_match_table = bno055_ser_of_match, |
552 | }, |
553 | .probe = bno055_ser_probe, |
554 | }; |
555 | module_serdev_device_driver(bno055_ser_driver); |
556 | |
557 | MODULE_AUTHOR("Andrea Merello <andrea.merello@iit.it>" ); |
558 | MODULE_DESCRIPTION("Bosch BNO055 serdev interface" ); |
559 | MODULE_IMPORT_NS(IIO_BNO055); |
560 | MODULE_LICENSE("GPL" ); |
561 | |