1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * Bus-specific functionality for BMI270s accessed via SPI.
9  */
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/logging/log.h>
13 #include "bmi270.h"
14 
15 LOG_MODULE_DECLARE(bmi270, CONFIG_SENSOR_LOG_LEVEL);
16 
bmi270_bus_check_spi(const union bmi270_bus * bus)17 static int bmi270_bus_check_spi(const union bmi270_bus *bus)
18 {
19 	return spi_is_ready_dt(&bus->spi) ? 0 : -ENODEV;
20 }
21 
bmi270_reg_read_spi(const union bmi270_bus * bus,uint8_t start,uint8_t * data,uint16_t len)22 static int bmi270_reg_read_spi(const union bmi270_bus *bus,
23 			       uint8_t start, uint8_t *data, uint16_t len)
24 {
25 	int ret;
26 	uint8_t addr;
27 	uint8_t tmp[2];
28 	const struct spi_buf tx_buf = {
29 		.buf = &addr,
30 		.len = 1
31 	};
32 	const struct spi_buf_set tx = {
33 		.buffers = &tx_buf,
34 		.count = 1
35 	};
36 	struct spi_buf rx_buf[2];
37 	const struct spi_buf_set rx = {
38 		.buffers = rx_buf,
39 		.count = ARRAY_SIZE(rx_buf)
40 	};
41 
42 	/* First byte we read should be discarded. */
43 	rx_buf[0].buf = &tmp;
44 	rx_buf[0].len = 2;
45 	rx_buf[1].len = len;
46 	rx_buf[1].buf = data;
47 
48 	addr = start | 0x80;
49 
50 	ret = spi_transceive_dt(&bus->spi, &tx, &rx);
51 	if (ret < 0) {
52 		LOG_DBG("spi_transceive failed %i", ret);
53 		return ret;
54 	}
55 
56 	k_usleep(BMI270_SPI_ACC_DELAY_US);
57 	return 0;
58 }
59 
bmi270_reg_write_spi(const union bmi270_bus * bus,uint8_t start,const uint8_t * data,uint16_t len)60 static int bmi270_reg_write_spi(const union bmi270_bus *bus, uint8_t start,
61 				const uint8_t *data, uint16_t len)
62 {
63 	int ret;
64 	uint8_t addr;
65 	const struct spi_buf tx_buf[2] = {
66 		{.buf = &addr, .len = sizeof(addr)},
67 		{.buf = (uint8_t *)data, .len = len}
68 	};
69 	const struct spi_buf_set tx = {
70 		.buffers = tx_buf,
71 		.count = ARRAY_SIZE(tx_buf)
72 	};
73 
74 	addr = start & BMI270_REG_MASK;
75 
76 	ret = spi_write_dt(&bus->spi, &tx);
77 	if (ret < 0) {
78 		LOG_ERR("spi_write_dt failed %i", ret);
79 		return ret;
80 	}
81 
82 	k_usleep(BMI270_SPI_ACC_DELAY_US);
83 	return 0;
84 }
85 
bmi270_bus_init_spi(const union bmi270_bus * bus)86 static int bmi270_bus_init_spi(const union bmi270_bus *bus)
87 {
88 	uint8_t tmp;
89 
90 	/* Single read of SPI initializes the chip to SPI mode
91 	 */
92 	return bmi270_reg_read_spi(bus, BMI270_REG_CHIP_ID, &tmp, 1);
93 }
94 
95 const struct bmi270_bus_io bmi270_bus_io_spi = {
96 	.check = bmi270_bus_check_spi,
97 	.read = bmi270_reg_read_spi,
98 	.write = bmi270_reg_write_spi,
99 	.init = bmi270_bus_init_spi,
100 };
101