diff --git a/drivers/sensor/tdk/CMakeLists.txt b/drivers/sensor/tdk/CMakeLists.txt index 0f5c85a2db0e82..b86ad2e7201e82 100644 --- a/drivers/sensor/tdk/CMakeLists.txt +++ b/drivers/sensor/tdk/CMakeLists.txt @@ -5,7 +5,7 @@ add_subdirectory_ifdef(CONFIG_ICM42605 icm42605) add_subdirectory_ifdef(CONFIG_ICM42670 icm42670) add_subdirectory_ifdef(CONFIG_ICM42688 icm42688) -add_subdirectory_ifdef(CONFIG_ICP10125 icp10125) +add_subdirectory_ifdef(CONFIG_ICP101XX icp101xx) add_subdirectory_ifdef(CONFIG_MPU6050 mpu6050) add_subdirectory_ifdef(CONFIG_MPU9250 mpu9250) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/tdk/Kconfig b/drivers/sensor/tdk/Kconfig index 57d92f9faf60c5..0faa517a2554a4 100644 --- a/drivers/sensor/tdk/Kconfig +++ b/drivers/sensor/tdk/Kconfig @@ -5,7 +5,7 @@ source "drivers/sensor/tdk/icm42605/Kconfig" source "drivers/sensor/tdk/icm42670/Kconfig" source "drivers/sensor/tdk/icm42688/Kconfig" -source "drivers/sensor/tdk/icp10125/Kconfig" +source "drivers/sensor/tdk/icp101xx/Kconfig" source "drivers/sensor/tdk/mpu6050/Kconfig" source "drivers/sensor/tdk/mpu9250/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/tdk/icp10125/CMakeLists.txt b/drivers/sensor/tdk/icp10125/CMakeLists.txt deleted file mode 100644 index 12279906928d5c..00000000000000 --- a/drivers/sensor/tdk/icp10125/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) 2022 Mizuki Agawa -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() - -zephyr_library_sources(icp10125.c) diff --git a/drivers/sensor/tdk/icp10125/Kconfig b/drivers/sensor/tdk/icp10125/Kconfig deleted file mode 100644 index 96240de1be7b65..00000000000000 --- a/drivers/sensor/tdk/icp10125/Kconfig +++ /dev/null @@ -1,23 +0,0 @@ -# ICP10125 barometric pressure/temperature sensor configuration options - -# Copyright (c) 2022 Mizuki Agawa -# SPDX-License-Identifier: Apache-2.0 - -menuconfig ICP10125 - bool "ICP10125 Barometric Pressure & Temperature Sensor" - default y - depends on DT_HAS_INVENSENSE_ICP10125_ENABLED - select I2C - help - Enable driver for ICP10125 barometric pressure/temperature sensor. - -if ICP10125 - -config ICP10125_CHECK_CRC - bool "Check the CRC of measument data" - imply CRC - default y - help - Verify the CRC checksum that appended to the measurement data. - -endif # ICP10125 diff --git a/drivers/sensor/tdk/icp10125/icp10125.c b/drivers/sensor/tdk/icp10125/icp10125.c deleted file mode 100644 index 7393b5bbe64f38..00000000000000 --- a/drivers/sensor/tdk/icp10125/icp10125.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (c) 2022 Mizuki Agawa - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT invensense_icp10125 - -#include -#include -#include -#include - -#ifdef CONFIG_ICP10125_CHECK_CRC -#include -#endif /* CONFIG_ICP10125_CHECK_CRC */ - -LOG_MODULE_REGISTER(ICP10125, CONFIG_SENSOR_LOG_LEVEL); - -#define CRC_POLY 0x31 -#define SENSOR_DATA_SIZE 2 - -#define AMBIENT_TEMP_DATA_NUM 1 -#define PRESS_DATA_NUM 2 -#define PRESS_AND_AMBIENT_TEMP_DATA_NUM (AMBIENT_TEMP_DATA_NUM + PRESS_DATA_NUM) - -enum { - LOW_POWER, - NORMAL, - LOW_NOISE, - ULTRA_LOW_NOISE, - NUM_MEASURE_MODE -}; - -struct icp10125_data { - uint16_t raw_ambient_temp; - uint32_t raw_press; - float sensor_constants[4]; -}; - -struct icp10125_dev_config { - struct i2c_dt_spec i2c; - uint8_t ambient_temp_mode; - uint8_t press_mode; -}; - -struct icp10125_cmd { - uint8_t data[2]; -}; - -struct icp10125_sensor_data { - uint8_t data[2]; - uint8_t crc; -}; - -struct icp10125_otp_read_setup { - struct icp10125_cmd cmd; - uint8_t data[3]; -} __packed __aligned(1); - -/* ambient temperature measurement command for each mode. - * (Section 5.2 MEASUREMENT COMMANDS in the Datasheet) - */ -static const struct icp10125_cmd ambient_temp_measurement_cmds[] = { - {{0x60, 0x9C}}, {{0x68, 0x25}}, {{0x70, 0xDF}}, {{0x78, 0x66}} -}; - -/* pressure measurement command for each mode. - * (Section 5.2 MEASUREMENT COMMANDS in the Datasheet) - */ -static const struct icp10125_cmd press_measurement_cmds[] = { - {{0x40, 0x1A}}, {{0x48, 0xA3}}, {{0x50, 0x59}}, {{0x59, 0xE0}} -}; - -/* Request preparation for OTP data read. It should issue before data read request. - * (Section 5.2 MEASUREMENT COMMANDS in the Datasheet) - */ -static const struct icp10125_otp_read_setup otp_read_setup = { - .cmd = {{0xC5, 0x95}}, - .data = {0x00, 0x66, 0x9C} -}; - -/* OTP data read request. - * After issue this command 2byte x 4 sensor constant value can readable. - */ -static const struct icp10125_cmd otp_read_request_cmd = {{0xC7, 0xF7}}; - -/* The max conversion time for each modes. - * (Section 2.2 OPERATION MODES in the Datasheet) - */ -static const uint32_t conv_time_max[] = {1800, 6300, 23800, 94500}; - -/* The typical conversion time for each modes. - * (Section 2.2 OPERATION MODES in the Datasheet) - */ -static const uint32_t conv_time_typ[] = {1600, 5600, 20800, 83200}; - -/* The Datasheet has no mention of the constants and formulas. - * Instead, it shows only how to use it in the sample code. - * Since there is no detailed description in the ICP10125 product manual, - * the calculation of the pressure implements is the same as shown in - * the 5.11 SAMPLE CODE: EXAMPLE C SYNTAX - */ - -static void icp10125_calculate_conversion_constants(const float *p_LUT, float *A, float *B, - float *C) -{ - const float p_Pa[] = {45000.0, 80000.0, 105000.0}; - - *C = (p_LUT[0] * p_LUT[1] * (p_Pa[0] - p_Pa[1]) + - p_LUT[1] * p_LUT[2] * (p_Pa[1] - p_Pa[2]) + - p_LUT[2] * p_LUT[0] * (p_Pa[2] - p_Pa[0])) / - (p_LUT[2] * (p_Pa[0] - p_Pa[1]) + p_LUT[0] * (p_Pa[1] - p_Pa[2]) + - p_LUT[1] * (p_Pa[2] - p_Pa[0])); - *A = (p_Pa[0] * p_LUT[0] - p_Pa[1] * p_LUT[1] - (p_Pa[1] - p_Pa[0]) * (*C)) / - (p_LUT[0] - p_LUT[1]); - *B = (p_Pa[0] - (*A)) * (p_LUT[0] + (*C)); -} - -static float icp10125_calc_calibrated_ambient_temp(const struct icp10125_data *data) -{ - return -45.f + 175.f / 65536.f * data->raw_ambient_temp; -} - -static float icp10125_calc_calibrated_press(const struct icp10125_data *data) -{ - const float quadr_factor = 1 / 16777216.0; - const float offst_factor = 2048.0; - const float LUT_lower = 3.5 * (1 << 20); - const float LUT_upper = 11.5 * (1 << 20); - float t; - float in[3]; - float A, B, C; - - t = data->raw_ambient_temp - 32768.f; - in[0] = LUT_lower + (data->sensor_constants[0] * t * t) * quadr_factor; - in[1] = offst_factor * data->sensor_constants[3] + - (data->sensor_constants[1] * t * t) * quadr_factor; - in[2] = LUT_upper + (data->sensor_constants[2] * t * t) * quadr_factor; - icp10125_calculate_conversion_constants(in, &A, &B, &C); - - return A + B / (C + data->raw_press); -} - -/* End of porting the 5.11 SAMPLE CODE: EXAMPLE C SYNTAX */ - -static int icp10125_read_otp(const struct device *dev) -{ - struct icp10125_data *data = dev->data; - struct icp10125_sensor_data sensor_data; - - const struct icp10125_dev_config *cfg = dev->config; - int rc = 0; - - rc = i2c_write_dt(&cfg->i2c, (uint8_t *)&otp_read_setup, sizeof(otp_read_setup)); - if (rc < 0) { - LOG_ERR("Failed to write otp_read_setup.\n"); - return rc; - } - - for (size_t i = 0; i < ARRAY_SIZE(data->sensor_constants); i++) { - rc = i2c_write_dt(&cfg->i2c, (uint8_t *)&otp_read_request_cmd, - sizeof(otp_read_request_cmd)); - if (rc < 0) { - LOG_ERR("Failed to write otp_read_request.\n"); - return rc; - } - - rc = i2c_read_dt(&cfg->i2c, (uint8_t *)&sensor_data, sizeof(sensor_data)); - if (rc < 0) { - LOG_ERR("Failed to read otp_read_request.\n"); - return rc; - } - - data->sensor_constants[i] = sys_get_be16(sensor_data.data); - } - - return 0; -} - -#ifdef CONFIG_ICP10125_CHECK_CRC -static int icp10125_check_crc(const uint8_t *data, const size_t len) -{ - /* Details of CRC are described in Chapter 5 Section 8 of the product - * specifications. - */ - return crc8(data, len, CRC_POLY, 0xFF, false); -} -#endif - -static int icp10125_measure(const struct i2c_dt_spec *i2c, const struct icp10125_cmd *cmds, - const uint8_t mode, struct icp10125_sensor_data *sensor_data, - const size_t data_num) -{ - int rc = 0; - - rc = i2c_write_dt(i2c, (uint8_t *)&cmds[mode], sizeof(cmds[mode])); - if (rc < 0) { - LOG_ERR("Failed to start measurement.\n"); - return rc; - } - - /* Wait for the sensor to become readable. - * First wait for the typical time and then read. - * If that fails, wait until the time to surely became readable. - */ - k_sleep(K_USEC(conv_time_typ[mode])); - if (i2c_read_dt(i2c, (uint8_t *)sensor_data, sizeof(sensor_data[0]) * data_num) < 0) { - k_sleep(K_USEC(conv_time_max[mode] - conv_time_typ[mode])); - rc = i2c_read_dt(i2c, (uint8_t *)sensor_data, sizeof(sensor_data[0]) * data_num); - if (rc < 0) { - LOG_ERR("Failed to read measurement.\n"); - return rc; - } - } - -#ifdef CONFIG_ICP10125_CHECK_CRC - /* Calculate CRC from Chapter 5 Section 8 of ICP10125 Product manuals. */ - for (size_t i = 0; i < data_num; i++) { - if (!icp10125_check_crc(sensor_data[i].data, SENSOR_DATA_SIZE)) { - LOG_ERR("Sensor data has invalid CRC.\n"); - return -EIO; - } - } -#endif /* CONFIG_ICP10125_CHECK_CRC */ - - return 0; -} - -static int icp10125_sample_fetch(const struct device *dev, const enum sensor_channel chan) -{ - struct icp10125_data *data = dev->data; - const struct icp10125_dev_config *cfg = dev->config; - uint8_t endian_conversion[3]; - struct icp10125_sensor_data sensor_data[PRESS_AND_AMBIENT_TEMP_DATA_NUM] = {0}; - int rc = 0; - - if (!(chan == SENSOR_CHAN_AMBIENT_TEMP || chan == SENSOR_CHAN_PRESS || - chan == SENSOR_CHAN_ALL)) { - return -ENOTSUP; - } - - if (chan == SENSOR_CHAN_AMBIENT_TEMP) { - rc = icp10125_measure(&cfg->i2c, ambient_temp_measurement_cmds, - cfg->ambient_temp_mode, sensor_data, AMBIENT_TEMP_DATA_NUM); - if (rc < 0) { - return rc; - } - - data->raw_ambient_temp = sys_get_be16(sensor_data[0].data); - } else { - rc = icp10125_measure(&cfg->i2c, press_measurement_cmds, cfg->press_mode, - sensor_data, PRESS_AND_AMBIENT_TEMP_DATA_NUM); - if (rc < 0) { - return rc; - } - - endian_conversion[0] = sensor_data[0].data[0]; - endian_conversion[1] = sensor_data[0].data[1]; - endian_conversion[2] = sensor_data[1].data[0]; - data->raw_press = sys_get_be24(endian_conversion); - data->raw_ambient_temp = sys_get_be16(sensor_data[2].data); - } - - return 0; -} - -static void icp10125_convert_press_value(struct icp10125_data *data, struct sensor_value *val) -{ - sensor_value_from_float(val, icp10125_calc_calibrated_press(data) / 1000.f); -} - -static void icp10125_convert_ambient_temp_value(struct icp10125_data *data, - struct sensor_value *val) -{ - sensor_value_from_float(val, icp10125_calc_calibrated_ambient_temp(data)); -} - -static int icp10125_channel_get(const struct device *dev, enum sensor_channel chan, - struct sensor_value *val) -{ - struct icp10125_data *data = dev->data; - - if (chan == SENSOR_CHAN_AMBIENT_TEMP) { - icp10125_convert_ambient_temp_value(data, val); - } else if (chan == SENSOR_CHAN_PRESS) { - icp10125_convert_press_value(data, val); - } else { - return -ENOTSUP; - } - - return 0; -} - -static int icp10125_init(const struct device *dev) -{ - int rc = icp10125_read_otp(dev); - - if (rc < 0) { - return rc; - } - - return 0; -} - -static DEVICE_API(sensor, icp10125_api_funcs) = { - .sample_fetch = icp10125_sample_fetch, - .channel_get = icp10125_channel_get, -}; - -#define ICP10125_DEFINE(inst) \ - static struct icp10125_data icp10125_drv_##inst; \ - static const struct icp10125_dev_config icp10125_config_##inst = { \ - .i2c = I2C_DT_SPEC_INST_GET(inst), \ - .ambient_temp_mode = DT_INST_ENUM_IDX(inst, temperature_measurement_mode), \ - .press_mode = DT_INST_ENUM_IDX(inst, pressure_measurement_mode)}; \ - DEVICE_DT_INST_DEFINE(inst, icp10125_init, NULL, &icp10125_drv_##inst, \ - &icp10125_config_##inst, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ - &icp10125_api_funcs); - -DT_INST_FOREACH_STATUS_OKAY(ICP10125_DEFINE) diff --git a/drivers/sensor/tdk/icp101xx/CMakeLists.txt b/drivers/sensor/tdk/icp101xx/CMakeLists.txt new file mode 100644 index 00000000000000..e7fa56a2982735 --- /dev/null +++ b/drivers/sensor/tdk/icp101xx/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +if (CONFIG_CPU_HAS_FPU STREQUAL "y") + zephyr_compile_definitions(ICP101XX_DRV_USE_FLOATS) +endif() + +zephyr_library_sources(icp101xx_drv.c) +zephyr_library_include_directories(.) diff --git a/drivers/sensor/tdk/icp101xx/Kconfig b/drivers/sensor/tdk/icp101xx/Kconfig new file mode 100644 index 00000000000000..7fae3bd8943517 --- /dev/null +++ b/drivers/sensor/tdk/icp101xx/Kconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 TDK Invensense + +# ICP101xx High Accuracy, Low Power, Barometric Pressure and Temperature Sensor option + +# SPDX-License-Identifier: Apache-2.0 +config ICP101XX + bool "ICP101XX Barometric Pressure and Temperature Sensor" + default y + depends on DT_HAS_INVENSENSE_ICP101XX_ENABLED + select I2C + select USE_EMD_ICP101XX + help + Enable driver for ICP101XX barometric pressure/temperature sensor. diff --git a/drivers/sensor/tdk/icp101xx/icp101xx_drv.c b/drivers/sensor/tdk/icp101xx/icp101xx_drv.c new file mode 100644 index 00000000000000..e521d098affbde --- /dev/null +++ b/drivers/sensor/tdk/icp101xx/icp101xx_drv.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2024 TDK Invensense + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT invensense_icp101xx + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "icp101xx_drv.h" + +LOG_MODULE_REGISTER(ICP101XX, CONFIG_SENSOR_LOG_LEVEL); + +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 +#error "ICP101XX driver enabled without any devices" +#endif + +void inv_icp101xx_sleep_us(int us) +{ + k_sleep(K_USEC(us)); +} + +static int inv_io_hal_read_reg(void *ctx, uint8_t reg, uint8_t *rbuffer, uint32_t rlen) +{ + struct device *dev = (struct device *)ctx; + const struct icp101xx_config *cfg = (const struct icp101xx_config *)dev->config; + + return i2c_read_dt(&cfg->i2c, (uint8_t *)rbuffer, rlen); +} + +static int inv_io_hal_write_reg(void *ctx, uint8_t reg, const uint8_t *wbuffer, uint32_t wlen) +{ + struct device *dev = (struct device *)ctx; + const struct icp101xx_config *cfg = (const struct icp101xx_config *)dev->config; + + return i2c_write_dt(&cfg->i2c, (uint8_t *)wbuffer, wlen); +} + +static uint8_t get_timeout_ms(enum icp101xx_meas mode) +{ + switch (mode) { + case ICP101XX_MEAS_LOW_POWER_T_FIRST: + case ICP101XX_MEAS_LOW_POWER_P_FIRST: + return 2; + case ICP101XX_MEAS_NORMAL_T_FIRST: + case ICP101XX_MEAS_NORMAL_P_FIRST: + return 7; + case ICP101XX_MEAS_LOW_NOISE_T_FIRST: + case ICP101XX_MEAS_LOW_NOISE_P_FIRST: + return 24; + default: + case ICP101XX_MEAS_ULTRA_LOW_NOISE_T_FIRST: + case ICP101XX_MEAS_ULTRA_LOW_NOISE_P_FIRST: + return 95; + } +} + +static uint8_t get_conversion_ms(enum icp101xx_meas mode) +{ + switch (mode) { + case ICP101XX_MEAS_LOW_POWER_T_FIRST: + case ICP101XX_MEAS_LOW_POWER_P_FIRST: + return 1; + case ICP101XX_MEAS_NORMAL_T_FIRST: + case ICP101XX_MEAS_NORMAL_P_FIRST: + return 5; + case ICP101XX_MEAS_LOW_NOISE_T_FIRST: + case ICP101XX_MEAS_LOW_NOISE_P_FIRST: + return 20; + default: + case ICP101XX_MEAS_ULTRA_LOW_NOISE_T_FIRST: + case ICP101XX_MEAS_ULTRA_LOW_NOISE_P_FIRST: + return 80; + } +} + +#ifdef ICP101XX_DRV_USE_FLOATS +#define ATMOSPHERICAL_PRESSURE_KPA ((float)101.325) +#define TO_KELVIN(temp_C) ((float)273.15 + temp_C) +/* + * Constant in altitude formula: + * M*g/R = (0,0289644 * 9,80665 / 8,31432) + * with M the molar mass of air. + * with g the gravitational force acceleration. + * with R the universal gaz constant. + */ +#define HEIGHT_TO_PRESSURE_COEFF ((float)0.03424) + +/* + * Constant in altitude formula: + * R / (M*g) = 8,31432 / (0,0289644 * 9,80665) + * with M the molar mass of air. + * with g the gravitational force acceleration. + * with R the universal gaz constant. + */ +#define PRESSURE_TO_HEIGHT_COEFF ((float)29.27127) +/* + * Constant for altitude formula: + * logarithm of pressure at 0m + * ln(101.325) + */ +#define LOG_ATMOSPHERICAL_PRESSURE ((float)4.61833) + +float convertToHeight(float pressure_kp, float temperature_C) +{ + return PRESSURE_TO_HEIGHT_COEFF * TO_KELVIN(temperature_C) * + (LOG_ATMOSPHERICAL_PRESSURE - logf(pressure_kp)); +} +#endif + +static int icp101xx_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + int err = 0; + struct icp101xx_data *data = (struct icp101xx_data *)dev->data; + + __ASSERT_NO_MSG(val != NULL); + if (chan == SENSOR_CHAN_PRESS) { + if (attr == SENSOR_ATTR_CONFIGURATION) { + if ((val->val1 >= ICP101XX_MEAS_LOW_POWER_T_FIRST) && + (val->val1 <= ICP101XX_MEAS_ULTRA_LOW_NOISE_P_FIRST)) { + data->icp_device.measurement_mode = val->val1; + } else { + LOG_ERR("Not supported ATTR value"); + return -EINVAL; + } + + } else { + LOG_ERR("Not supported ATTR"); + return -EINVAL; + } + }; + return err; +} + +static int icp101xx_sample_fetch(const struct device *dev, const enum sensor_channel chan) +{ + struct icp101xx_data *data = (struct icp101xx_data *)dev->data; + int rc = 0; + uint64_t timeout; + + if (!((chan == SENSOR_CHAN_AMBIENT_TEMP) || (chan == SENSOR_CHAN_PRESS) || + (chan == SENSOR_CHAN_ALTITUDE) || (chan == SENSOR_CHAN_ALL))) { + return -ENOTSUP; + } + rc = inv_icp101xx_enable_sensor(&data->icp_device, 1); + /* Compute timeout for the measure */ + timeout = k_uptime_get() + get_timeout_ms(data->icp_device.measurement_mode); + /* Initial sleep waiting the sensor proceeds with the measure */ + k_sleep(K_MSEC(get_conversion_ms(data->icp_device.measurement_mode))); + do { + k_sleep(K_USEC(200)); + rc = inv_icp101xx_get_data(&data->icp_device, &(data->raw_pressure), + &(data->raw_temperature), &(data->pressure), + &(data->temperature)); + } while ((rc != 0) && (k_uptime_get() <= timeout)); + return rc; +} + +static int icp101xx_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + + struct icp101xx_data *data = (struct icp101xx_data *)dev->data; + + val->val1 = 0; + val->val2 = 0; + + if (!((chan == SENSOR_CHAN_AMBIENT_TEMP) || (chan == SENSOR_CHAN_PRESS) || + (chan == SENSOR_CHAN_ALTITUDE))) { + return -ENOTSUP; + } + /* Zephyr expects kPa while ICP101xx returns Pa */ + if (chan == SENSOR_CHAN_AMBIENT_TEMP) { +#ifdef ICP101XX_DRV_USE_FLOATS + sensor_value_from_float(val, data->temperature); +#else + val->val1 = data->temperature >> 4; + val->val2 = (data->temperature % 16) * 1000000 / 16; +#endif + } else if (chan == SENSOR_CHAN_PRESS) { +#ifdef ICP101XX_DRV_USE_FLOATS + sensor_value_from_float(val, data->pressure / 1000); +#else + val->val1 = data->pressure / 1000; + val->val2 = (data->pressure % 1000) * 1000; +#endif +#ifdef ICP101XX_DRV_USE_FLOATS + } else if (chan == SENSOR_CHAN_ALTITUDE) { + float altitude = convertToHeight(data->pressure / 1000, data->temperature); + + sensor_value_from_float(val, altitude); +#endif + } else { + return -ENOTSUP; + } + + return 0; +} + +static int icp101xx_init(const struct device *dev) +{ + struct inv_icp101xx_serif icp101xx_serif; + int rc = 0; + struct icp101xx_data *data = (struct icp101xx_data *)dev->data; + const struct icp101xx_config *cfg = (const struct icp101xx_config *)dev->config; + + memset(&icp101xx_serif, 0, sizeof(icp101xx_serif)); + icp101xx_serif.context = (void *)dev; + icp101xx_serif.read_reg = inv_io_hal_read_reg; + icp101xx_serif.write_reg = inv_io_hal_write_reg; + icp101xx_serif.max_read = 2048; /* maximum number of bytes allowed per serial read */ + icp101xx_serif.max_write = 2048; /* maximum number of bytes allowed per serial write */ + /* + * Reset pressure sensor driver states + */ + inv_icp101xx_reset_states(&(data->icp_device), &icp101xx_serif); + + rc = inv_icp101xx_soft_reset(&data->icp_device); + if (rc != 0) { + LOG_ERR("Soft reset error %d", rc); + return rc; + } + inv_icp101xx_init(&data->icp_device); + if (rc != 0) { + LOG_ERR("Init error %d", rc); + return rc; + } + data->icp_device.measurement_mode = cfg->mode; + + /* successful init, return 0 */ + return 0; +} + +static const struct sensor_driver_api icp101xx_api_funcs = { + .sample_fetch = icp101xx_sample_fetch, + .channel_get = icp101xx_channel_get, + .attr_set = icp101xx_attr_set, +}; + +#define ICP101XX_DEFINE(inst) \ + static struct icp101xx_data icp101xx_drv_##inst; \ + static const struct icp101xx_config icp101xx_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + .mode = DT_INST_ENUM_IDX(inst, mode), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, icp101xx_init, NULL, &icp101xx_drv_##inst, \ + &icp101xx_config_##inst, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &icp101xx_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(ICP101XX_DEFINE) diff --git a/drivers/sensor/tdk/icp101xx/icp101xx_drv.h b/drivers/sensor/tdk/icp101xx/icp101xx_drv.h new file mode 100644 index 00000000000000..9ecac4257f2ed9 --- /dev/null +++ b/drivers/sensor/tdk/icp101xx/icp101xx_drv.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 TDK Invensense + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_ICP101XXX_ICP101XXX_H_ +#define ZEPHYR_DRIVERS_SENSOR_ICP101XXX_ICP101XXX_H_ + +#include +#include +#include +#include +#include +#include "Icp101xx.h" +#include "Icp101xxSerif.h" + +#define ICP101XX_BUS_I2C DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + +struct icp101xx_data { + int raw_pressure; + int raw_temperature; +#ifdef ICP101XX_DRV_USE_FLOATS + float pressure; + float temperature; +#else + int32_t pressure; + int32_t temperature; +#endif + inv_icp101xx_t icp_device; +}; + +struct icp101xx_config { + struct i2c_dt_spec i2c; + int mode; +}; + +#endif