Skip to content

Commit ca31dbc

Browse files
LucasTambornashif
authored andcommitted
drivers: sensor: icm42670: Add I2C bus support
Add bus interface so the driver can support both SPI and I2C bus. Signed-off-by: Lucas Tamborrino <[email protected]>
1 parent 5a69cc0 commit ca31dbc

File tree

12 files changed

+269
-107
lines changed

12 files changed

+269
-107
lines changed

drivers/sensor/tdk/icm42670/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ zephyr_library()
55
zephyr_library_sources(
66
icm42670.c
77
icm42670_spi.c
8+
icm42670_i2c.c
89
)
910

1011
zephyr_library_sources_ifdef(CONFIG_ICM42670_TRIGGER icm42670_trigger.c)

drivers/sensor/tdk/icm42670/Kconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ menuconfig ICM42670
99
bool "ICM42670 Six-Axis Motion Tracking Device"
1010
default y
1111
depends on DT_HAS_INVENSENSE_ICM42670_ENABLED
12-
select SPI
12+
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670),spi)
13+
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670),i2c)
1314
help
1415
Enable driver for ICM42670 SPI-based six-axis motion tracking device.
1516

drivers/sensor/tdk/icm42670/icm42670.c

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <zephyr/sys/byteorder.h>
1313
#include "icm42670.h"
1414
#include "icm42670_reg.h"
15-
#include "icm42670_spi.h"
1615
#include "icm42670_trigger.h"
1716

1817
#include <zephyr/logging/log.h>
@@ -52,7 +51,7 @@ static int icm42670_set_accel_fs(const struct device *dev, uint16_t fs)
5251

5352
data->accel_sensitivity_shift = MIN_ACCEL_SENS_SHIFT + temp;
5453

55-
return icm42670_spi_update_register(&cfg->spi, REG_ACCEL_CONFIG0,
54+
return cfg->bus_io->update(&cfg->bus, REG_ACCEL_CONFIG0,
5655
(uint8_t)MASK_ACCEL_UI_FS_SEL, temp);
5756
}
5857

@@ -79,7 +78,7 @@ static int icm42670_set_gyro_fs(const struct device *dev, uint16_t fs)
7978

8079
data->gyro_sensitivity_x10 = icm42670_gyro_sensitivity_x10[temp];
8180

82-
return icm42670_spi_update_register(&cfg->spi, REG_GYRO_CONFIG0,
81+
return cfg->bus_io->update(&cfg->bus, REG_GYRO_CONFIG0,
8382
(uint8_t)MASK_GYRO_UI_FS_SEL, temp);
8483
}
8584

@@ -117,7 +116,7 @@ static int icm42670_set_accel_odr(const struct device *dev, uint16_t rate)
117116
temp = BIT_ACCEL_ODR_1;
118117
}
119118

120-
return icm42670_spi_update_register(&cfg->spi, REG_ACCEL_CONFIG0, (uint8_t)MASK_ACCEL_ODR,
119+
return cfg->bus_io->update(&cfg->bus, REG_ACCEL_CONFIG0, (uint8_t)MASK_ACCEL_ODR,
121120
temp);
122121
}
123122

@@ -149,7 +148,7 @@ static int icm42670_set_gyro_odr(const struct device *dev, uint16_t rate)
149148
temp = BIT_GYRO_ODR_12;
150149
}
151150

152-
return icm42670_spi_update_register(&cfg->spi, REG_GYRO_CONFIG0, (uint8_t)MASK_GYRO_ODR,
151+
return cfg->bus_io->update(&cfg->bus, REG_GYRO_CONFIG0, (uint8_t)MASK_GYRO_ODR,
153152
temp);
154153
}
155154

@@ -158,7 +157,7 @@ static int icm42670_enable_mclk(const struct device *dev)
158157
const struct icm42670_config *cfg = dev->config;
159158

160159
/* switch on MCLK by setting the IDLE bit */
161-
int res = icm42670_spi_single_write(&cfg->spi, REG_PWR_MGMT0, BIT_IDLE);
160+
int res = cfg->bus_io->write(&cfg->bus, REG_PWR_MGMT0, BIT_IDLE);
162161

163162
if (res) {
164163
return res;
@@ -169,7 +168,7 @@ static int icm42670_enable_mclk(const struct device *dev)
169168
uint8_t value = 0;
170169

171170
k_usleep(MCLK_POLL_INTERVAL_US);
172-
res = icm42670_spi_read(&cfg->spi, REG_MCLK_RDY, &value, 1);
171+
res = cfg->bus_io->read(&cfg->bus, REG_MCLK_RDY, &value, 1);
173172

174173
if (res) {
175174
return res;
@@ -193,7 +192,7 @@ static int icm42670_sensor_init(const struct device *dev)
193192
k_msleep(3);
194193

195194
/* perform a soft reset to ensure a clean slate, reset bit will auto-clear */
196-
res = icm42670_spi_single_write(&cfg->spi, REG_SIGNAL_PATH_RESET, BIT_SOFT_RESET);
195+
res = cfg->bus_io->write(&cfg->bus, REG_SIGNAL_PATH_RESET, BIT_SOFT_RESET);
197196

198197
if (res) {
199198
LOG_ERR("write REG_SIGNAL_PATH_RESET failed");
@@ -204,22 +203,22 @@ static int icm42670_sensor_init(const struct device *dev)
204203
k_msleep(SOFT_RESET_TIME_MS);
205204

206205
/* force SPI-4w hardware configuration (so that next read is correct) */
207-
res = icm42670_spi_single_write(&cfg->spi, REG_DEVICE_CONFIG, BIT_SPI_AP_4WIRE);
206+
res = cfg->bus_io->write(&cfg->bus, REG_DEVICE_CONFIG, BIT_SPI_AP_4WIRE);
208207

209208
if (res) {
210209
return res;
211210
}
212211

213212
/* always use internal RC oscillator */
214-
res = icm42670_spi_single_write(&cfg->spi, REG_INTF_CONFIG1,
213+
res = cfg->bus_io->write(&cfg->bus, REG_INTF_CONFIG1,
215214
(uint8_t)FIELD_PREP(MASK_CLKSEL, BIT_CLKSEL_INT_RC));
216215

217216
if (res) {
218217
return res;
219218
}
220219

221220
/* clear reset done int flag */
222-
res = icm42670_spi_read(&cfg->spi, REG_INT_STATUS, &value, 1);
221+
res = cfg->bus_io->read(&cfg->bus, REG_INT_STATUS, &value, 1);
223222

224223
if (res) {
225224
return res;
@@ -237,7 +236,7 @@ static int icm42670_sensor_init(const struct device *dev)
237236
return res;
238237
}
239238

240-
res = icm42670_spi_read(&cfg->spi, REG_WHO_AM_I, &value, 1);
239+
res = cfg->bus_io->read(&cfg->bus, REG_WHO_AM_I, &value, 1);
241240

242241
if (res) {
243242
return res;
@@ -263,7 +262,7 @@ static int icm42670_turn_on_sensor(const struct device *dev)
263262
value = FIELD_PREP(MASK_ACCEL_MODE, BIT_ACCEL_MODE_LNM) |
264263
FIELD_PREP(MASK_GYRO_MODE, BIT_GYRO_MODE_LNM);
265264

266-
res = icm42670_spi_update_register(&cfg->spi, REG_PWR_MGMT0,
265+
res = cfg->bus_io->update(&cfg->bus, REG_PWR_MGMT0,
267266
(uint8_t)(MASK_ACCEL_MODE | MASK_GYRO_MODE), value);
268267

269268
if (res) {
@@ -394,7 +393,7 @@ static int icm42670_sample_fetch_accel(const struct device *dev)
394393
struct icm42670_data *data = dev->data;
395394
uint8_t buffer[ACCEL_DATA_SIZE];
396395

397-
int res = icm42670_spi_read(&cfg->spi, REG_ACCEL_DATA_X1, buffer, ACCEL_DATA_SIZE);
396+
int res = cfg->bus_io->read(&cfg->bus, REG_ACCEL_DATA_X1, buffer, ACCEL_DATA_SIZE);
398397

399398
if (res) {
400399
return res;
@@ -413,7 +412,7 @@ static int icm42670_sample_fetch_gyro(const struct device *dev)
413412
struct icm42670_data *data = dev->data;
414413
uint8_t buffer[GYRO_DATA_SIZE];
415414

416-
int res = icm42670_spi_read(&cfg->spi, REG_GYRO_DATA_X1, buffer, GYRO_DATA_SIZE);
415+
int res = cfg->bus_io->read(&cfg->bus, REG_GYRO_DATA_X1, buffer, GYRO_DATA_SIZE);
417416

418417
if (res) {
419418
return res;
@@ -432,7 +431,7 @@ static int icm42670_sample_fetch_temp(const struct device *dev)
432431
struct icm42670_data *data = dev->data;
433432
uint8_t buffer[TEMP_DATA_SIZE];
434433

435-
int res = icm42670_spi_read(&cfg->spi, REG_TEMP_DATA1, buffer, TEMP_DATA_SIZE);
434+
int res = cfg->bus_io->read(&cfg->bus, REG_TEMP_DATA1, buffer, TEMP_DATA_SIZE);
436435

437436
if (res) {
438437
return res;
@@ -450,7 +449,7 @@ static int icm42670_sample_fetch(const struct device *dev, enum sensor_channel c
450449

451450
icm42670_lock(dev);
452451

453-
int res = icm42670_spi_read(&cfg->spi, REG_INT_STATUS_DRDY, &status, 1);
452+
int res = cfg->bus_io->read(&cfg->bus, REG_INT_STATUS_DRDY, &status, 1);
454453

455454
if (res) {
456455
goto cleanup;
@@ -616,12 +615,18 @@ static int icm42670_attr_get(const struct device *dev, enum sensor_channel chan,
616615
return res;
617616
}
618617

618+
static inline int icm42670_bus_check(const struct device *dev)
619+
{
620+
const struct icm42670_config *cfg = dev->config;
621+
622+
return cfg->bus_io->check(&cfg->bus);
623+
}
624+
619625
static int icm42670_init(const struct device *dev)
620626
{
621627
struct icm42670_data *data = dev->data;
622-
const struct icm42670_config *cfg = dev->config;
623628

624-
if (!spi_is_ready_dt(&cfg->spi)) {
629+
if (icm42670_bus_check(dev) < 0) {
625630
LOG_ERR("SPI bus is not ready");
626631
return -ENODEV;
627632
}
@@ -686,19 +691,31 @@ static const struct sensor_driver_api icm42670_driver_api = {
686691
#define ICM42670_SPI_CFG \
687692
SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_TRANSFER_MSB
688693

694+
/* Initializes the bus members for an instance on a SPI bus. */
695+
#define ICM42670_CONFIG_SPI(inst) \
696+
.bus.spi = SPI_DT_SPEC_INST_GET(inst, ICM42670_SPI_CFG, 0), \
697+
.bus_io = &icm42670_bus_io_spi,
698+
699+
/* Initializes the bus members for an instance on an I2C bus. */
700+
#define ICM42670_CONFIG_I2C(inst) \
701+
.bus.i2c = I2C_DT_SPEC_INST_GET(inst), \
702+
.bus_io = &icm42670_bus_io_i2c,
703+
689704
#define ICM42670_INIT(inst) \
690705
static struct icm42670_data icm42670_driver_##inst = { \
691706
.accel_hz = DT_INST_PROP(inst, accel_hz), \
692707
.accel_fs = DT_INST_PROP(inst, accel_fs), \
693708
.gyro_hz = DT_INST_PROP(inst, gyro_hz), \
694709
.gyro_fs = DT_INST_PROP(inst, gyro_fs), \
695710
}; \
696-
\
711+
\
697712
static const struct icm42670_config icm42670_cfg_##inst = { \
698-
.spi = SPI_DT_SPEC_INST_GET(inst, ICM42670_SPI_CFG, 0U), \
699-
.gpio_int = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, { 0 }), \
713+
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
714+
(ICM42670_CONFIG_SPI(inst)), \
715+
(ICM42670_CONFIG_I2C(inst))) \
716+
.gpio_int = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \
700717
}; \
701-
\
718+
\
702719
SENSOR_DEVICE_DT_INST_DEFINE(inst, icm42670_init, NULL, &icm42670_driver_##inst, \
703720
&icm42670_cfg_##inst, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
704721
&icm42670_driver_api);

drivers/sensor/tdk/icm42670/icm42670.h

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,45 @@
1111
#include <zephyr/drivers/gpio.h>
1212
#include <zephyr/drivers/sensor.h>
1313
#include <zephyr/drivers/spi.h>
14+
#include <zephyr/drivers/i2c.h>
1415
#include <zephyr/kernel.h>
1516

17+
#define ICM42670_BUS_SPI DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(invensense_icm42670, spi)
18+
#define ICM42670_BUS_I2C DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(invensense_icm42670, i2c)
19+
20+
union icm42670_bus {
21+
#if ICM42670_BUS_SPI
22+
struct spi_dt_spec spi;
23+
#endif
24+
#if ICM42670_BUS_I2C
25+
struct i2c_dt_spec i2c;
26+
#endif
27+
};
28+
29+
typedef int (*icm42670_bus_check_fn)(const union icm42670_bus *bus);
30+
typedef int (*icm42670_reg_read_fn)(const union icm42670_bus *bus,
31+
uint16_t reg, uint8_t *data, size_t size);
32+
typedef int (*icm42670_reg_write_fn)(const union icm42670_bus *bus,
33+
uint16_t reg, uint8_t data);
34+
35+
typedef int (*icm42670_reg_update_fn)(const union icm42670_bus *bus,
36+
uint16_t reg, uint8_t mask, uint8_t data);
37+
38+
struct icm42670_bus_io {
39+
icm42670_bus_check_fn check;
40+
icm42670_reg_read_fn read;
41+
icm42670_reg_write_fn write;
42+
icm42670_reg_update_fn update;
43+
};
44+
45+
#if ICM42670_BUS_SPI
46+
extern const struct icm42670_bus_io icm42670_bus_io_spi;
47+
#endif
48+
49+
#if ICM42670_BUS_I2C
50+
extern const struct icm42670_bus_io icm42670_bus_io_i2c;
51+
#endif
52+
1653
struct icm42670_data {
1754
int16_t accel_x;
1855
int16_t accel_y;
@@ -45,7 +82,8 @@ struct icm42670_data {
4582
};
4683

4784
struct icm42670_config {
48-
struct spi_dt_spec spi;
85+
union icm42670_bus bus;
86+
const struct icm42670_bus_io *bus_io;
4987
struct gpio_dt_spec gpio_int;
5088
};
5189

0 commit comments

Comments
 (0)