Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: imu: add BNO055 serdev driver

Add a serdev driver for communicating to a BNO055 IMU via serial bus, and
enable the BNO055 core driver to work in this scenario.

Signed-off-by: Andrea Merello <andrea.merello@iit.it>
Link: https://lore.kernel.org/r/20220907132205.28021-13-andrea.merello@iit.it
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Andrea Merello and committed by
Jonathan Cameron
2eef5a9c 21f95c75

+693
+10
drivers/iio/imu/bno055/Kconfig
··· 2 2 3 3 config BOSCH_BNO055 4 4 tristate 5 + 6 + config BOSCH_BNO055_SERIAL 7 + tristate "Bosch BNO055 attached via UART" 8 + depends on SERIAL_DEV_BUS 9 + select BOSCH_BNO055 10 + help 11 + Enable this to support Bosch BNO055 IMUs attached via UART. 12 + 13 + This driver can also be built as a module. If so, the module will be 14 + called bno055_sl.
+5
drivers/iio/imu/bno055/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 3 obj-$(CONFIG_BOSCH_BNO055) += bno055.o 4 + obj-$(CONFIG_BOSCH_BNO055_SERIAL) += bno055_ser.o 5 + bno055_ser-y := bno055_ser_core.o 6 + # define_trace.h needs to know how to find our header 7 + CFLAGS_bno055_ser_trace.o := -I$(src) 8 + bno055_ser-$(CONFIG_TRACING) += bno055_ser_trace.o
+560
drivers/iio/imu/bno055/bno055_ser_core.c
··· 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(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, hdr, 2); 193 + if (ret) 194 + goto fail; 195 + usleep_range(2000, 3000); 196 + ret = bno055_ser_send_chunk(priv, hdr + 2, 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(2000, 3000); 206 + ret = bno055_ser_send_chunk(priv, data, 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(40000, 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(&priv->cmd_complete, 233 + msecs_to_jiffies(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(&priv->cmd_complete); 252 + mutex_unlock(&priv->lock); 253 + 254 + if (retry != retry_max) 255 + trace_cmd_retry(read, addr, 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(&priv->cmd_complete, 261 + msecs_to_jiffies(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(data[0], data[1]); 296 + return bno055_ser_send_cmd(priv, 0, data[0], count - 1, 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(reg_addr, val_size); 315 + mutex_lock(&priv->lock); 316 + priv->expected_data_len = val_size; 317 + priv->response_buf = val; 318 + mutex_unlock(&priv->lock); 319 + 320 + ret = bno055_ser_send_cmd(priv, 1, reg_addr, val_size, NULL); 321 + 322 + mutex_lock(&priv->lock); 323 + priv->response_buf = NULL; 324 + mutex_unlock(&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(&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(&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 int bno055_ser_receive_buf(struct serdev_device *serdev, 382 + const unsigned char *buf, size_t size) 383 + { 384 + int status; 385 + struct bno055_ser_priv *priv = serdev_device_get_drvdata(serdev); 386 + int remaining = size; 387 + 388 + if (size == 0) 389 + return 0; 390 + 391 + trace_recv(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_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_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(&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_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(&serdev->dev, sizeof(*priv), GFP_KERNEL); 507 + if (!priv) 508 + return -ENOMEM; 509 + 510 + serdev_device_set_drvdata(serdev, priv); 511 + priv->serdev = serdev; 512 + mutex_init(&priv->lock); 513 + init_completion(&priv->cmd_complete); 514 + 515 + serdev_device_set_client_ops(serdev, &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, 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(regmap)) 535 + return dev_err_probe(&serdev->dev, PTR_ERR(regmap), 536 + "Unable to init register map"); 537 + 538 + return bno055_probe(&serdev->dev, regmap, 539 + BNO055_SER_XFER_BURST_BREAK_THRESHOLD, 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");
+14
drivers/iio/imu/bno055/bno055_ser_trace.c
··· 1 + //SPDX-License-Identifier: GPL-2.0 2 + 3 + /* 4 + * bno055_ser Trace Support 5 + * Copyright (C) 2022 Istituto Italiano di Tecnologia 6 + * Electronic Design Laboratory 7 + * 8 + * Based on: 9 + * Device core Trace Support 10 + * Copyright (C) 2021, Intel Corporation 11 + */ 12 + 13 + #define CREATE_TRACE_POINTS 14 + #include "bno055_ser_trace.h"
+104
drivers/iio/imu/bno055/bno055_ser_trace.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #if !defined(__BNO055_SERDEV_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) 4 + #define __BNO055_SERDEV_TRACE_H__ 5 + 6 + #include <linux/tracepoint.h> 7 + 8 + #undef TRACE_SYSTEM 9 + #define TRACE_SYSTEM bno055_ser 10 + 11 + TRACE_EVENT(send_chunk, 12 + TP_PROTO(int len, const u8 *data), 13 + TP_ARGS(len, data), 14 + TP_STRUCT__entry( 15 + __field(int, len) 16 + __dynamic_array(u8, chunk, len) 17 + ), 18 + TP_fast_assign( 19 + __entry->len = len; 20 + memcpy(__get_dynamic_array(chunk), 21 + data, __entry->len); 22 + ), 23 + TP_printk("len: %d, data: = %*ph", 24 + __entry->len, __entry->len, __get_dynamic_array(chunk) 25 + ) 26 + ); 27 + 28 + TRACE_EVENT(cmd_retry, 29 + TP_PROTO(bool read, int addr, int retry), 30 + TP_ARGS(read, addr, retry), 31 + TP_STRUCT__entry( 32 + __field(bool, read) 33 + __field(int, addr) 34 + __field(int, retry) 35 + ), 36 + TP_fast_assign( 37 + __entry->read = read; 38 + __entry->addr = addr; 39 + __entry->retry = retry; 40 + ), 41 + TP_printk("%s addr 0x%x retry #%d", 42 + __entry->read ? "read" : "write", 43 + __entry->addr, __entry->retry 44 + ) 45 + ); 46 + 47 + TRACE_EVENT(write_reg, 48 + TP_PROTO(u8 addr, u8 value), 49 + TP_ARGS(addr, value), 50 + TP_STRUCT__entry( 51 + __field(u8, addr) 52 + __field(u8, value) 53 + ), 54 + TP_fast_assign( 55 + __entry->addr = addr; 56 + __entry->value = value; 57 + ), 58 + TP_printk("reg 0x%x = 0x%x", 59 + __entry->addr, __entry->value 60 + ) 61 + ); 62 + 63 + TRACE_EVENT(read_reg, 64 + TP_PROTO(int addr, size_t len), 65 + TP_ARGS(addr, len), 66 + TP_STRUCT__entry( 67 + __field(int, addr) 68 + __field(size_t, len) 69 + ), 70 + TP_fast_assign( 71 + __entry->addr = addr; 72 + __entry->len = len; 73 + ), 74 + TP_printk("reg 0x%x (len %zu)", 75 + __entry->addr, __entry->len 76 + ) 77 + ); 78 + 79 + TRACE_EVENT(recv, 80 + TP_PROTO(size_t len, const unsigned char *buf), 81 + TP_ARGS(len, buf), 82 + TP_STRUCT__entry( 83 + __field(size_t, len) 84 + __dynamic_array(unsigned char, buf, len) 85 + ), 86 + TP_fast_assign( 87 + __entry->len = len; 88 + memcpy(__get_dynamic_array(buf), 89 + buf, __entry->len); 90 + ), 91 + TP_printk("len: %zu, data: = %*ph", 92 + __entry->len, (int)__entry->len, __get_dynamic_array(buf) 93 + ) 94 + ); 95 + 96 + #endif /* __BNO055_SERDEV_TRACE_H__ || TRACE_HEADER_MULTI_READ */ 97 + 98 + #undef TRACE_INCLUDE_PATH 99 + #define TRACE_INCLUDE_PATH . 100 + #undef TRACE_INCLUDE_FILE 101 + #define TRACE_INCLUDE_FILE bno055_ser_trace 102 + 103 + /* This part must be outside protection */ 104 + #include <trace/define_trace.h>