| /* |
| * Copyright (c) 2022 Esco Medical ApS |
| * Copyright (c) 2020 TDK Invensense |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #define DT_DRV_COMPAT invensense_icm42670 |
| |
| #include <zephyr/drivers/sensor.h> |
| #include <zephyr/drivers/spi.h> |
| #include <zephyr/sys/byteorder.h> |
| #include "icm42670.h" |
| #include "icm42670_reg.h" |
| #include "icm42670_spi.h" |
| #include "icm42670_trigger.h" |
| |
| #include <zephyr/logging/log.h> |
| LOG_MODULE_REGISTER(ICM42670, CONFIG_SENSOR_LOG_LEVEL); |
| |
| /* |
| * Gyro FS to scaling factor mapping. |
| * See datasheet section 3.1 for details |
| */ |
| static const uint16_t icm42670_gyro_sensitivity_x10[] = { |
| 164, /* BIT_GYRO_UI_FS_2000 */ |
| 328, /* BIT_GYRO_UI_FS_1000 */ |
| 655, /* BIT_GYRO_UI_FS_500 */ |
| 1310, /* BIT_GYRO_UI_FS_250 */ |
| }; |
| |
| static int icm42670_set_accel_fs(const struct device *dev, uint16_t fs) |
| { |
| const struct icm42670_config *cfg = dev->config; |
| struct icm42670_data *data = dev->data; |
| uint8_t temp; |
| |
| if ((fs > 16) || (fs < 2)) { |
| LOG_ERR("Unsupported range"); |
| return -ENOTSUP; |
| } |
| |
| if (fs > 8) { |
| temp = BIT_ACCEL_UI_FS_16; |
| } else if (fs > 4) { |
| temp = BIT_ACCEL_UI_FS_8; |
| } else if (fs > 2) { |
| temp = BIT_ACCEL_UI_FS_4; |
| } else { |
| temp = BIT_ACCEL_UI_FS_2; |
| } |
| |
| data->accel_sensitivity_shift = MIN_ACCEL_SENS_SHIFT + temp; |
| |
| return icm42670_spi_update_register(&cfg->spi, REG_ACCEL_CONFIG0, |
| (uint8_t)MASK_ACCEL_UI_FS_SEL, temp); |
| } |
| |
| static int icm42670_set_gyro_fs(const struct device *dev, uint16_t fs) |
| { |
| const struct icm42670_config *cfg = dev->config; |
| struct icm42670_data *data = dev->data; |
| uint8_t temp; |
| |
| if ((fs > 2000) || (fs < 250)) { |
| LOG_ERR("Unsupported range"); |
| return -ENOTSUP; |
| } |
| |
| if (fs > 1000) { |
| temp = BIT_GYRO_UI_FS_2000; |
| } else if (fs > 500) { |
| temp = BIT_GYRO_UI_FS_1000; |
| } else if (fs > 250) { |
| temp = BIT_GYRO_UI_FS_500; |
| } else { |
| temp = BIT_GYRO_UI_FS_250; |
| } |
| |
| data->gyro_sensitivity_x10 = icm42670_gyro_sensitivity_x10[temp]; |
| |
| return icm42670_spi_update_register(&cfg->spi, REG_GYRO_CONFIG0, |
| (uint8_t)MASK_GYRO_UI_FS_SEL, temp); |
| } |
| |
| static int icm42670_set_accel_odr(const struct device *dev, uint16_t rate) |
| { |
| const struct icm42670_config *cfg = dev->config; |
| uint8_t temp; |
| |
| if ((rate > 1600) || (rate < 1)) { |
| LOG_ERR("Unsupported frequency"); |
| return -ENOTSUP; |
| } |
| |
| if (rate > 800) { |
| temp = BIT_ACCEL_ODR_1600; |
| } else if (rate > 400) { |
| temp = BIT_ACCEL_ODR_800; |
| } else if (rate > 200) { |
| temp = BIT_ACCEL_ODR_400; |
| } else if (rate > 100) { |
| temp = BIT_ACCEL_ODR_200; |
| } else if (rate > 50) { |
| temp = BIT_ACCEL_ODR_100; |
| } else if (rate > 25) { |
| temp = BIT_ACCEL_ODR_50; |
| } else if (rate > 12) { |
| temp = BIT_ACCEL_ODR_25; |
| } else if (rate > 6) { |
| temp = BIT_ACCEL_ODR_12; |
| } else if (rate > 3) { |
| temp = BIT_ACCEL_ODR_6; |
| } else if (rate > 1) { |
| temp = BIT_ACCEL_ODR_3; |
| } else { |
| temp = BIT_ACCEL_ODR_1; |
| } |
| |
| return icm42670_spi_update_register(&cfg->spi, REG_ACCEL_CONFIG0, (uint8_t)MASK_ACCEL_ODR, |
| temp); |
| } |
| |
| static int icm42670_set_gyro_odr(const struct device *dev, uint16_t rate) |
| { |
| const struct icm42670_config *cfg = dev->config; |
| uint8_t temp; |
| |
| if ((rate > 1600) || (rate < 12)) { |
| LOG_ERR("Unsupported frequency"); |
| return -ENOTSUP; |
| } |
| |
| if (rate > 800) { |
| temp = BIT_GYRO_ODR_1600; |
| } else if (rate > 400) { |
| temp = BIT_GYRO_ODR_800; |
| } else if (rate > 200) { |
| temp = BIT_GYRO_ODR_400; |
| } else if (rate > 100) { |
| temp = BIT_GYRO_ODR_200; |
| } else if (rate > 50) { |
| temp = BIT_GYRO_ODR_100; |
| } else if (rate > 25) { |
| temp = BIT_GYRO_ODR_50; |
| } else if (rate > 12) { |
| temp = BIT_GYRO_ODR_25; |
| } else { |
| temp = BIT_GYRO_ODR_12; |
| } |
| |
| return icm42670_spi_update_register(&cfg->spi, REG_GYRO_CONFIG0, (uint8_t)MASK_GYRO_ODR, |
| temp); |
| } |
| |
| static int icm42670_enable_mclk(const struct device *dev) |
| { |
| const struct icm42670_config *cfg = dev->config; |
| |
| /* switch on MCLK by setting the IDLE bit */ |
| int res = icm42670_spi_single_write(&cfg->spi, REG_PWR_MGMT0, BIT_IDLE); |
| |
| if (res) { |
| return res; |
| } |
| |
| /* wait for the MCLK to stabilize by polling MCLK_RDY register */ |
| for (int i = 0; i < MCLK_POLL_ATTEMPTS; i++) { |
| uint8_t value = 0; |
| |
| k_usleep(MCLK_POLL_INTERVAL_US); |
| res = icm42670_spi_read(&cfg->spi, REG_MCLK_RDY, &value, 1); |
| |
| if (res) { |
| return res; |
| } |
| |
| if (FIELD_GET(BIT_MCLK_RDY, value)) { |
| return 0; |
| } |
| } |
| |
| return -EIO; |
| } |
| |
| static int icm42670_sensor_init(const struct device *dev) |
| { |
| int res; |
| uint8_t value; |
| const struct icm42670_config *cfg = dev->config; |
| |
| /* start up time for register read/write after POR is 1ms and supply ramp time is 3ms */ |
| k_msleep(3); |
| |
| /* perform a soft reset to ensure a clean slate, reset bit will auto-clear */ |
| res = icm42670_spi_single_write(&cfg->spi, REG_SIGNAL_PATH_RESET, BIT_SOFT_RESET); |
| |
| if (res) { |
| LOG_ERR("write REG_SIGNAL_PATH_RESET failed"); |
| return res; |
| } |
| |
| /* wait for soft reset to take effect */ |
| k_msleep(SOFT_RESET_TIME_MS); |
| |
| /* force SPI-4w hardware configuration (so that next read is correct) */ |
| res = icm42670_spi_single_write(&cfg->spi, REG_DEVICE_CONFIG, BIT_SPI_AP_4WIRE); |
| |
| if (res) { |
| return res; |
| } |
| |
| /* always use internal RC oscillator */ |
| res = icm42670_spi_single_write(&cfg->spi, REG_INTF_CONFIG1, |
| (uint8_t)FIELD_PREP(MASK_CLKSEL, BIT_CLKSEL_INT_RC)); |
| |
| if (res) { |
| return res; |
| } |
| |
| /* clear reset done int flag */ |
| res = icm42670_spi_read(&cfg->spi, REG_INT_STATUS, &value, 1); |
| |
| if (res) { |
| return res; |
| } |
| |
| if (FIELD_GET(BIT_STATUS_RESET_DONE_INT, value) != 1) { |
| LOG_ERR("unexpected RESET_DONE_INT value, %i", value); |
| return -EINVAL; |
| } |
| |
| /* enable the master clock to ensure proper operation */ |
| res = icm42670_enable_mclk(dev); |
| |
| if (res) { |
| return res; |
| } |
| |
| res = icm42670_spi_read(&cfg->spi, REG_WHO_AM_I, &value, 1); |
| |
| if (res) { |
| return res; |
| } |
| |
| if (value != WHO_AM_I_ICM42670) { |
| LOG_ERR("invalid WHO_AM_I value, was %i but expected %i", value, WHO_AM_I_ICM42670); |
| return -EINVAL; |
| } |
| |
| LOG_DBG("device id: 0x%02X", value); |
| |
| return 0; |
| } |
| |
| static int icm42670_turn_on_sensor(const struct device *dev) |
| { |
| struct icm42670_data *data = dev->data; |
| const struct icm42670_config *cfg = dev->config; |
| uint8_t value; |
| int res; |
| |
| value = FIELD_PREP(MASK_ACCEL_MODE, BIT_ACCEL_MODE_LNM) | |
| FIELD_PREP(MASK_GYRO_MODE, BIT_GYRO_MODE_LNM); |
| |
| res = icm42670_spi_update_register(&cfg->spi, REG_PWR_MGMT0, |
| (uint8_t)(MASK_ACCEL_MODE | MASK_GYRO_MODE), value); |
| |
| if (res) { |
| return res; |
| } |
| |
| res = icm42670_set_accel_fs(dev, data->accel_fs); |
| |
| if (res) { |
| return res; |
| } |
| |
| res = icm42670_set_accel_odr(dev, data->accel_hz); |
| |
| if (res) { |
| return res; |
| } |
| |
| res = icm42670_set_gyro_fs(dev, data->gyro_fs); |
| |
| if (res) { |
| return res; |
| } |
| |
| res = icm42670_set_gyro_odr(dev, data->gyro_hz); |
| |
| if (res) { |
| return res; |
| } |
| |
| /* |
| * Accelerometer sensor need at least 10ms startup time |
| * Gyroscope sensor need at least 30ms startup time |
| */ |
| k_msleep(100); |
| |
| return 0; |
| } |
| |
| static void icm42670_convert_accel(struct sensor_value *val, int16_t raw_val, |
| uint16_t sensitivity_shift) |
| { |
| /* see datasheet section 3.2 for details */ |
| int64_t conv_val = ((int64_t)raw_val * SENSOR_G) >> sensitivity_shift; |
| |
| val->val1 = conv_val / 1000000LL; |
| val->val2 = conv_val % 1000000LL; |
| } |
| |
| static void icm42670_convert_gyro(struct sensor_value *val, int16_t raw_val, |
| uint16_t sensitivity_x10) |
| { |
| /* see datasheet section 3.1 for details */ |
| int64_t conv_val = ((int64_t)raw_val * SENSOR_PI * 10) / (sensitivity_x10 * 180LL); |
| |
| val->val1 = conv_val / 1000000LL; |
| val->val2 = conv_val % 1000000LL; |
| } |
| |
| static inline void icm42670_convert_temp(struct sensor_value *val, int16_t raw_val) |
| { |
| /* see datasheet section 15.9 for details */ |
| val->val1 = (((int64_t)raw_val * 100) / 12800) + 25; |
| val->val2 = ((((int64_t)raw_val * 100) % 12800) * 1000000) / 12800; |
| |
| if (val->val2 < 0) { |
| val->val1--; |
| val->val2 += 1000000; |
| } else if (val->val2 >= 1000000) { |
| val->val1++; |
| val->val2 -= 1000000; |
| } |
| } |
| |
| static int icm42670_channel_get(const struct device *dev, enum sensor_channel chan, |
| struct sensor_value *val) |
| { |
| int res = 0; |
| const struct icm42670_data *data = dev->data; |
| |
| icm42670_lock(dev); |
| |
| switch (chan) { |
| case SENSOR_CHAN_ACCEL_XYZ: |
| icm42670_convert_accel(&val[0], data->accel_x, data->accel_sensitivity_shift); |
| icm42670_convert_accel(&val[1], data->accel_y, data->accel_sensitivity_shift); |
| icm42670_convert_accel(&val[2], data->accel_z, data->accel_sensitivity_shift); |
| break; |
| case SENSOR_CHAN_ACCEL_X: |
| icm42670_convert_accel(val, data->accel_x, data->accel_sensitivity_shift); |
| break; |
| case SENSOR_CHAN_ACCEL_Y: |
| icm42670_convert_accel(val, data->accel_y, data->accel_sensitivity_shift); |
| break; |
| case SENSOR_CHAN_ACCEL_Z: |
| icm42670_convert_accel(val, data->accel_z, data->accel_sensitivity_shift); |
| break; |
| case SENSOR_CHAN_GYRO_XYZ: |
| icm42670_convert_gyro(&val[0], data->gyro_x, data->gyro_sensitivity_x10); |
| icm42670_convert_gyro(&val[1], data->gyro_y, data->gyro_sensitivity_x10); |
| icm42670_convert_gyro(&val[2], data->gyro_z, data->gyro_sensitivity_x10); |
| break; |
| case SENSOR_CHAN_GYRO_X: |
| icm42670_convert_gyro(val, data->gyro_x, data->gyro_sensitivity_x10); |
| break; |
| case SENSOR_CHAN_GYRO_Y: |
| icm42670_convert_gyro(val, data->gyro_y, data->gyro_sensitivity_x10); |
| break; |
| case SENSOR_CHAN_GYRO_Z: |
| icm42670_convert_gyro(val, data->gyro_z, data->gyro_sensitivity_x10); |
| break; |
| case SENSOR_CHAN_DIE_TEMP: |
| icm42670_convert_temp(val, data->temp); |
| break; |
| default: |
| res = -ENOTSUP; |
| break; |
| } |
| |
| icm42670_unlock(dev); |
| |
| return res; |
| } |
| |
| static int icm42670_sample_fetch_accel(const struct device *dev) |
| { |
| const struct icm42670_config *cfg = dev->config; |
| struct icm42670_data *data = dev->data; |
| uint8_t buffer[ACCEL_DATA_SIZE]; |
| |
| int res = icm42670_spi_read(&cfg->spi, REG_ACCEL_DATA_X1, buffer, ACCEL_DATA_SIZE); |
| |
| if (res) { |
| return res; |
| } |
| |
| data->accel_x = (int16_t)sys_get_be16(&buffer[0]); |
| data->accel_y = (int16_t)sys_get_be16(&buffer[2]); |
| data->accel_z = (int16_t)sys_get_be16(&buffer[4]); |
| |
| return 0; |
| } |
| |
| static int icm42670_sample_fetch_gyro(const struct device *dev) |
| { |
| const struct icm42670_config *cfg = dev->config; |
| struct icm42670_data *data = dev->data; |
| uint8_t buffer[GYRO_DATA_SIZE]; |
| |
| int res = icm42670_spi_read(&cfg->spi, REG_GYRO_DATA_X1, buffer, GYRO_DATA_SIZE); |
| |
| if (res) { |
| return res; |
| } |
| |
| data->gyro_x = (int16_t)sys_get_be16(&buffer[0]); |
| data->gyro_y = (int16_t)sys_get_be16(&buffer[2]); |
| data->gyro_z = (int16_t)sys_get_be16(&buffer[4]); |
| |
| return 0; |
| } |
| |
| static int icm42670_sample_fetch_temp(const struct device *dev) |
| { |
| const struct icm42670_config *cfg = dev->config; |
| struct icm42670_data *data = dev->data; |
| uint8_t buffer[TEMP_DATA_SIZE]; |
| |
| int res = icm42670_spi_read(&cfg->spi, REG_TEMP_DATA1, buffer, TEMP_DATA_SIZE); |
| |
| if (res) { |
| return res; |
| } |
| |
| data->temp = (int16_t)sys_get_be16(&buffer[0]); |
| |
| return 0; |
| } |
| |
| static int icm42670_sample_fetch(const struct device *dev, enum sensor_channel chan) |
| { |
| uint8_t status; |
| const struct icm42670_config *cfg = dev->config; |
| |
| icm42670_lock(dev); |
| |
| int res = icm42670_spi_read(&cfg->spi, REG_INT_STATUS_DRDY, &status, 1); |
| |
| if (res) { |
| goto cleanup; |
| } |
| |
| if (!FIELD_GET(BIT_INT_STATUS_DATA_DRDY, status)) { |
| res = -EBUSY; |
| goto cleanup; |
| } |
| |
| switch (chan) { |
| case SENSOR_CHAN_ALL: |
| res |= icm42670_sample_fetch_accel(dev); |
| res |= icm42670_sample_fetch_gyro(dev); |
| res |= icm42670_sample_fetch_temp(dev); |
| break; |
| case SENSOR_CHAN_ACCEL_XYZ: |
| case SENSOR_CHAN_ACCEL_X: |
| case SENSOR_CHAN_ACCEL_Y: |
| case SENSOR_CHAN_ACCEL_Z: |
| res = icm42670_sample_fetch_accel(dev); |
| break; |
| case SENSOR_CHAN_GYRO_XYZ: |
| case SENSOR_CHAN_GYRO_X: |
| case SENSOR_CHAN_GYRO_Y: |
| case SENSOR_CHAN_GYRO_Z: |
| res = icm42670_sample_fetch_gyro(dev); |
| break; |
| case SENSOR_CHAN_DIE_TEMP: |
| res = icm42670_sample_fetch_temp(dev); |
| break; |
| default: |
| res = -ENOTSUP; |
| break; |
| } |
| |
| cleanup: |
| icm42670_unlock(dev); |
| return res; |
| } |
| |
| static int icm42670_attr_set(const struct device *dev, enum sensor_channel chan, |
| enum sensor_attribute attr, const struct sensor_value *val) |
| { |
| int res = 0; |
| struct icm42670_data *data = dev->data; |
| |
| __ASSERT_NO_MSG(val != NULL); |
| |
| icm42670_lock(dev); |
| |
| switch (chan) { |
| case SENSOR_CHAN_ACCEL_X: |
| case SENSOR_CHAN_ACCEL_Y: |
| case SENSOR_CHAN_ACCEL_Z: |
| case SENSOR_CHAN_ACCEL_XYZ: |
| if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) { |
| res = icm42670_set_accel_odr(dev, data->accel_hz); |
| |
| if (res) { |
| LOG_ERR("Incorrect sampling value"); |
| } else { |
| data->accel_hz = val->val1; |
| } |
| } else if (attr == SENSOR_ATTR_FULL_SCALE) { |
| res = icm42670_set_accel_fs(dev, data->accel_fs); |
| |
| if (res) { |
| LOG_ERR("Incorrect fullscale value"); |
| } else { |
| data->accel_fs = val->val1; |
| } |
| } else { |
| LOG_ERR("Unsupported attribute"); |
| res = -ENOTSUP; |
| } |
| break; |
| |
| case SENSOR_CHAN_GYRO_X: |
| case SENSOR_CHAN_GYRO_Y: |
| case SENSOR_CHAN_GYRO_Z: |
| case SENSOR_CHAN_GYRO_XYZ: |
| if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) { |
| res = icm42670_set_gyro_odr(dev, data->gyro_hz); |
| |
| if (res) { |
| LOG_ERR("Incorrect sampling value"); |
| } else { |
| data->gyro_hz = val->val1; |
| } |
| } else if (attr == SENSOR_ATTR_FULL_SCALE) { |
| res = icm42670_set_gyro_fs(dev, data->gyro_fs); |
| |
| if (res) { |
| LOG_ERR("Incorrect fullscale value"); |
| } else { |
| data->gyro_fs = val->val1; |
| } |
| } else { |
| LOG_ERR("Unsupported attribute"); |
| res = -EINVAL; |
| } |
| break; |
| |
| default: |
| LOG_ERR("Unsupported channel"); |
| res = -EINVAL; |
| break; |
| } |
| |
| icm42670_unlock(dev); |
| |
| return res; |
| } |
| |
| static int icm42670_attr_get(const struct device *dev, enum sensor_channel chan, |
| enum sensor_attribute attr, struct sensor_value *val) |
| { |
| const struct icm42670_data *data = dev->data; |
| int res = 0; |
| |
| __ASSERT_NO_MSG(val != NULL); |
| |
| icm42670_lock(dev); |
| |
| switch (chan) { |
| case SENSOR_CHAN_ACCEL_X: |
| case SENSOR_CHAN_ACCEL_Y: |
| case SENSOR_CHAN_ACCEL_Z: |
| case SENSOR_CHAN_ACCEL_XYZ: |
| if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) { |
| val->val1 = data->accel_hz; |
| } else if (attr == SENSOR_ATTR_FULL_SCALE) { |
| val->val1 = data->accel_fs; |
| } else { |
| LOG_ERR("Unsupported attribute"); |
| res = -EINVAL; |
| } |
| break; |
| |
| case SENSOR_CHAN_GYRO_X: |
| case SENSOR_CHAN_GYRO_Y: |
| case SENSOR_CHAN_GYRO_Z: |
| case SENSOR_CHAN_GYRO_XYZ: |
| if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) { |
| val->val1 = data->gyro_hz; |
| } else if (attr == SENSOR_ATTR_FULL_SCALE) { |
| val->val1 = data->gyro_fs; |
| } else { |
| LOG_ERR("Unsupported attribute"); |
| res = -EINVAL; |
| } |
| break; |
| |
| default: |
| LOG_ERR("Unsupported channel"); |
| res = -EINVAL; |
| break; |
| } |
| |
| icm42670_unlock(dev); |
| |
| return res; |
| } |
| |
| static int icm42670_init(const struct device *dev) |
| { |
| struct icm42670_data *data = dev->data; |
| const struct icm42670_config *cfg = dev->config; |
| |
| if (!spi_is_ready_dt(&cfg->spi)) { |
| LOG_ERR("SPI bus is not ready"); |
| return -ENODEV; |
| } |
| |
| data->accel_x = 0; |
| data->accel_y = 0; |
| data->accel_z = 0; |
| data->gyro_x = 0; |
| data->gyro_y = 0; |
| data->gyro_z = 0; |
| data->temp = 0; |
| |
| if (icm42670_sensor_init(dev)) { |
| LOG_ERR("could not initialize sensor"); |
| return -EIO; |
| } |
| |
| #ifdef CONFIG_ICM42670_TRIGGER |
| if (icm42670_trigger_init(dev)) { |
| LOG_ERR("Failed to initialize interrupts."); |
| return -EIO; |
| } |
| #endif |
| |
| int res = icm42670_turn_on_sensor(dev); |
| |
| #ifdef CONFIG_ICM42670_TRIGGER |
| if (icm42670_trigger_enable_interrupt(dev)) { |
| LOG_ERR("Failed to enable interrupts"); |
| return -EIO; |
| } |
| #endif |
| |
| return res; |
| } |
| |
| #ifndef CONFIG_ICM42670_TRIGGER |
| |
| void icm42670_lock(const struct device *dev) |
| { |
| ARG_UNUSED(dev); |
| } |
| |
| void icm42670_unlock(const struct device *dev) |
| { |
| ARG_UNUSED(dev); |
| } |
| |
| #endif |
| |
| static const struct sensor_driver_api icm42670_driver_api = { |
| #ifdef CONFIG_ICM42670_TRIGGER |
| .trigger_set = icm42670_trigger_set, |
| #endif |
| .sample_fetch = icm42670_sample_fetch, |
| .channel_get = icm42670_channel_get, |
| .attr_set = icm42670_attr_set, |
| .attr_get = icm42670_attr_get, |
| }; |
| |
| /* device defaults to spi mode 0/3 support */ |
| #define ICM42670_SPI_CFG \ |
| SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_TRANSFER_MSB |
| |
| #define ICM42670_INIT(inst) \ |
| static struct icm42670_data icm42670_driver_##inst = { \ |
| .accel_hz = DT_INST_PROP(inst, accel_hz), \ |
| .accel_fs = DT_INST_PROP(inst, accel_fs), \ |
| .gyro_hz = DT_INST_PROP(inst, gyro_hz), \ |
| .gyro_fs = DT_INST_PROP(inst, gyro_fs), \ |
| }; \ |
| \ |
| static const struct icm42670_config icm42670_cfg_##inst = { \ |
| .spi = SPI_DT_SPEC_INST_GET(inst, ICM42670_SPI_CFG, 0U), \ |
| .gpio_int = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, { 0 }), \ |
| }; \ |
| \ |
| SENSOR_DEVICE_DT_INST_DEFINE(inst, icm42670_init, NULL, &icm42670_driver_##inst, \ |
| &icm42670_cfg_##inst, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ |
| &icm42670_driver_api); |
| |
| DT_INST_FOREACH_STATUS_OKAY(ICM42670_INIT) |