diff --git a/drivers/sensor/adi/adltc2990/adltc2990.c b/drivers/sensor/adi/adltc2990/adltc2990.c index adf79dce4ed..3bf5654eaec 100644 --- a/drivers/sensor/adi/adltc2990/adltc2990.c +++ b/drivers/sensor/adi/adltc2990/adltc2990.c @@ -1,6 +1,6 @@ /* + * SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya * SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG - * SPDX-FileCopyrightText: Copyright (c) 2024 Jilay Sandeep Pandya * SPDX-License-Identifier: Apache-2.0 */ @@ -151,7 +151,7 @@ int adltc2990_trigger_measurement(const struct device *dev, return -EIO; } - WRITE_BIT(ctrl_reg_setting, ADLTC2990_ACQUISTION_BIT_POS, format); + WRITE_BIT(ctrl_reg_setting, ADLTC2990_ACQUISITION_BIT_POS, format); if (i2c_reg_write_byte_dt(&cfg->bus, ADLTC2990_REG_CONTROL, ctrl_reg_setting)) { LOG_ERR("configuring for single bus failed."); @@ -242,35 +242,6 @@ static int adltc2990_fetch_property_value(const struct device *dev, return 0; } -static int adltc2990_init(const struct device *dev) -{ - const struct adltc2990_config *cfg = dev->config; - struct adltc2990_data *data = dev->data; - int err; - - if (!i2c_is_ready_dt(&cfg->bus)) { - LOG_ERR("I2C bus %s not ready", cfg->bus.bus->name); - return -ENODEV; - } - - const uint8_t ctrl_reg_setting = cfg->temp_format << 7 | data->acq_format << 6 | 0 << 5 | - cfg->measurement_mode[1] << 3 | cfg->measurement_mode[0]; - - LOG_DBG("Setting Control Register to: 0x%x", ctrl_reg_setting); - if (i2c_reg_write_byte_dt(&cfg->bus, ADLTC2990_REG_CONTROL, ctrl_reg_setting)) { - LOG_ERR("configuring for single bus failed."); - return -EIO; - } - - err = adltc2990_trigger_measurement(dev, data->acq_format); - if (err < 0) { - LOG_ERR("triggering measurement failed: %d", err); - } - - LOG_INF("Initializing ADLTC2990 with name %s", dev->name); - return 0; -} - static int fetch_pin_differential_voltage_value(const struct device *dev, const enum adltc2990_monitoring_type mode, const enum adltc2990_monitor_pins pin) @@ -618,6 +589,35 @@ static int adltc2990_channel_get(const struct device *dev, enum sensor_channel c return 0; } +static int adltc2990_init(const struct device *dev) +{ + const struct adltc2990_config *cfg = dev->config; + struct adltc2990_data *data = dev->data; + int err; + + if (!i2c_is_ready_dt(&cfg->bus)) { + LOG_ERR("I2C bus %s not ready", cfg->bus.bus->name); + return -ENODEV; + } + + const uint8_t ctrl_reg_setting = cfg->temp_format << 7 | data->acq_format << 6 | 0 << 5 | + cfg->measurement_mode[1] << 3 | cfg->measurement_mode[0]; + + LOG_DBG("Setting Control Register to: 0x%x", ctrl_reg_setting); + if (i2c_reg_write_byte_dt(&cfg->bus, ADLTC2990_REG_CONTROL, ctrl_reg_setting)) { + LOG_ERR("configuring for single bus failed."); + return -EIO; + } + + err = adltc2990_trigger_measurement(dev, data->acq_format); + if (err < 0) { + LOG_ERR("triggering measurement failed: %d", err); + } + + LOG_INF("Initializing ADLTC2990 with name %s", dev->name); + return 0; +} + static DEVICE_API(sensor, adltc2990_driver_api) = { .sample_fetch = adltc2990_sample_fetch, .channel_get = adltc2990_channel_get, diff --git a/drivers/sensor/adi/adltc2990/adltc2990_emul.c b/drivers/sensor/adi/adltc2990/adltc2990_emul.c index d4b9c310ea3..8ea5e7d2782 100644 --- a/drivers/sensor/adi/adltc2990/adltc2990_emul.c +++ b/drivers/sensor/adi/adltc2990/adltc2990_emul.c @@ -1,6 +1,6 @@ /* + * SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya * SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG - * SPDX-FileCopyrightText: Copyright (c) 2024 Jilay Sandeep Pandya * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,7 @@ LOG_MODULE_DECLARE(adltc2990, CONFIG_SENSOR_LOG_LEVEL); #define ADLTC2990_NUM_REGS ADLTC2990_REG_VCC_LSB struct adltc2990_emul_data { + uint8_t mock_i2c_reg_error; uint8_t reg[ADLTC2990_NUM_REGS]; }; @@ -49,6 +50,7 @@ void adltc2990_emul_reset(const struct emul *target) { struct adltc2990_emul_data *data = target->data; + data->mock_i2c_reg_error = ADLTC2990_NUM_REGS + 1; memset(data->reg, 0, ADLTC2990_NUM_REGS); } @@ -75,6 +77,7 @@ static int adltc2990_emul_transfer_i2c(const struct emul *target, struct i2c_msg int num_msgs, int addr) { struct adltc2990_emul_data *data = target->data; + uint8_t regn = msgs->buf[0]; i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false); @@ -91,7 +94,6 @@ static int adltc2990_emul_transfer_i2c(const struct emul *target, struct i2c_msg return -EIO; } - uint8_t regn = msgs->buf[0]; bool is_read = FIELD_GET(I2C_MSG_READ, msgs->flags) == 1; bool is_stop = FIELD_GET(I2C_MSG_STOP, msgs->flags) == 1; diff --git a/drivers/sensor/adi/adltc2990/adltc2990_reg.h b/drivers/sensor/adi/adltc2990/adltc2990_reg.h index 26cefae3017..0ed2dddd1ce 100644 --- a/drivers/sensor/adi/adltc2990/adltc2990_reg.h +++ b/drivers/sensor/adi/adltc2990/adltc2990_reg.h @@ -53,9 +53,9 @@ #define ADLTC2990_TEMPERATURE_FORMAT_CELSIUS 0U #define ADLTC2990_TEMPERATURE_FORMAT_KELVIN 1U -#define ADLTC2990_ACQUISTION_BIT_POS 6U -#define ADLTC2990_ACQUISTION_BIT_MSK BIT(ADLTC2990_ACQUISTION_BIT_POS) +#define ADLTC2990_ACQUISITION_BIT_POS 6U +#define ADLTC2990_ACQUISITION_BIT_MSK BIT(ADLTC2990_ACQUISITION_BIT_POS) #define ADLTC2990_ACQUISITION_BIT_VAL(reg) \ - ((reg) & ADLTC2990_ACQUISTION_BIT_MSK) >> ADLTC2990_ACQUISTION_BIT_POS + ((reg) & ADLTC2990_ACQUISITION_BIT_MSK) >> ADLTC2990_ACQUISITION_BIT_POS #endif /* ZEPHYR_DRIVERS_SENSOR_ADLTC2990_REG_H */ diff --git a/tests/drivers/sensor/adltc2990/src/main.c b/tests/drivers/sensor/adltc2990/src/main.c index 3b20206fe5c..522e767ed31 100644 --- a/tests/drivers/sensor/adltc2990/src/main.c +++ b/tests/drivers/sensor/adltc2990/src/main.c @@ -5,15 +5,61 @@ */ #include +#include #include +#include #include #include +#include #include #include "adltc2990_emul.h" #include "adltc2990_reg.h" #include "adltc2990_internal.h" +#include + +DEFINE_FFF_GLOBALS; + +DECLARE_FAKE_VALUE_FUNC(int, fake_mock_i2c_transfer, uint8_t, int, int); + +DEFINE_FAKE_VALUE_FUNC(int, fake_mock_i2c_transfer, uint8_t, int, int); + +static int mock_i2c_transfer_fail_reg_number = -1; + +static int adltc2990_i2c_is_touching_reg_delegate(uint8_t start_reg, int num_msgs, int reg) +{ + + if (start_reg == reg) { + return -EIO; + } + + return 0; +} + +static int mock_i2c_transfer_delegate(const struct emul *target, struct i2c_msg *msgs, int num_msgs, + int addr) +{ + ARG_UNUSED(target); + ARG_UNUSED(addr); + + uint8_t start_reg = msgs[0].buf[0]; + + fake_mock_i2c_transfer_fake.return_val = + fake_mock_i2c_transfer(start_reg, num_msgs, mock_i2c_transfer_fail_reg_number); + if (fake_mock_i2c_transfer_fake.return_val == -EIO) { + return -EIO; + } + return -ENOSYS; +} + +static void reset_mock_i2c_transfer_fake(void) +{ + mock_i2c_transfer_fail_reg_number = -1; + fake_mock_i2c_transfer_reset(); + fake_mock_i2c_transfer_fake.custom_fake = adltc2990_i2c_is_touching_reg_delegate; +} + /* Colllection of common assertion macros */ #define CHECK_SINGLE_ENDED_VOLTAGE(sensor_val, index, pin_voltage, r1, r2) \ zassert_ok(sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); \ @@ -119,6 +165,65 @@ static void adltc2990_4_3_before(void *f) ZTEST_SUITE(adltc2990_4_3, NULL, adltc2990_4_3_setup, adltc2990_4_3_before, NULL, NULL); +ZTEST_F(adltc2990_4_3, test_mock_i2c_error) +{ + struct i2c_emul_api mock_bus_api; + + fixture->target->bus.i2c->mock_api = &mock_bus_api; + mock_bus_api.transfer = mock_i2c_transfer_delegate; + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_STATUS; + bool is_busy; + + zassert_equal(-EIO, adltc2990_is_busy(fixture->dev, &is_busy), "I2C Error not detected"); + zassert_equal(1, fake_mock_i2c_transfer_fake.call_count); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_TRIGGER; + adltc2990_trigger_measurement(fixture->dev, ADLTC2990_REPEATED_ACQUISITION); + zassert_equal(-EIO, fake_mock_i2c_transfer_fake.return_val); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_CONTROL; + adltc2990_trigger_measurement(fixture->dev, ADLTC2990_SINGLE_SHOT_ACQUISITION); + zassert_equal(ADLTC2990_REG_CONTROL, fake_mock_i2c_transfer_fake.arg0_val); + zassert_equal(-EIO, fake_mock_i2c_transfer_fake.return_val); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_VCC_LSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(ADLTC2990_REG_VCC_LSB, fake_mock_i2c_transfer_fake.arg0_val); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V1_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_AMBIENT_TEMP)); + zassert_equal(-EIO, fake_mock_i2c_transfer_fake.return_val); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V3_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_CURRENT)); + zassert_equal(-EIO, fake_mock_i2c_transfer_fake.return_val); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_INTERNAL_TEMP_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_DIE_TEMP)); + zassert_equal(1, fake_mock_i2c_transfer_fake.call_count); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V1_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_AMBIENT_TEMP)); + zassert_equal(1, fake_mock_i2c_transfer_fake.call_count); +} + ZTEST_F(adltc2990_4_3, test_available_channels) { struct sensor_value value[3]; @@ -292,6 +397,20 @@ static void adltc2990_5_3_before(void *f) ZTEST_SUITE(adltc2990_5_3, NULL, adltc2990_5_3_setup, adltc2990_5_3_before, NULL, NULL); +ZTEST_F(adltc2990_5_3, test_mock_i2c_error) +{ + struct i2c_emul_api mock_bus_api; + + fixture->target->bus.i2c->mock_api = &mock_bus_api; + mock_bus_api.transfer = mock_i2c_transfer_delegate; + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V3_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_AMBIENT_TEMP)); + zassert_equal(3, fake_mock_i2c_transfer_fake.call_count); +} + ZTEST_F(adltc2990_5_3, test_ambient_temperature) { /*Kelvin 0b00010001 0b00010010 273.1250*/ @@ -353,6 +472,39 @@ static void adltc2990_6_3_before(void *f) ZTEST_SUITE(adltc2990_6_3, NULL, adltc2990_6_3_setup, adltc2990_6_3_before, NULL, NULL); +ZTEST_F(adltc2990_6_3, test_mock_i2c_error) +{ + struct i2c_emul_api mock_bus_api; + + fixture->target->bus.i2c->mock_api = &mock_bus_api; + mock_bus_api.transfer = mock_i2c_transfer_delegate; + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_VCC_LSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(-EIO, fake_mock_i2c_transfer_fake.return_val); + zassert_equal(2, fake_mock_i2c_transfer_fake.call_count); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V1_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(3, fake_mock_i2c_transfer_fake.call_count); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V3_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(5, fake_mock_i2c_transfer_fake.call_count); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V1_LSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_CURRENT)); + zassert_equal(2, fake_mock_i2c_transfer_fake.call_count); +} + ZTEST_F(adltc2990_6_3, test_current) { /* 0b00111100 0b01011000 +0.300 */ @@ -400,6 +552,47 @@ static void adltc2990_7_3_before(void *f) ZTEST_SUITE(adltc2990_7_3, NULL, adltc2990_7_3_setup, adltc2990_7_3_before, NULL, NULL); +ZTEST_F(adltc2990_7_3, test_mock_i2c_error) +{ + struct i2c_emul_api mock_bus_api; + + fixture->target->bus.i2c->mock_api = &mock_bus_api; + mock_bus_api.transfer = mock_i2c_transfer_delegate; + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_VCC_LSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(-EIO, fake_mock_i2c_transfer_fake.return_val); + zassert_equal(2, fake_mock_i2c_transfer_fake.call_count); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V1_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(-EIO, fake_mock_i2c_transfer_fake.return_val); + zassert_equal(3, fake_mock_i2c_transfer_fake.call_count); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V2_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(-EIO, fake_mock_i2c_transfer_fake.return_val); + zassert_equal(5, fake_mock_i2c_transfer_fake.call_count); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V3_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(7, fake_mock_i2c_transfer_fake.call_count); + + reset_mock_i2c_transfer_fake(); + + mock_i2c_transfer_fail_reg_number = ADLTC2990_REG_V4_MSB; + zassert_equal(-EIO, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_VOLTAGE)); + zassert_equal(9, fake_mock_i2c_transfer_fake.call_count); +} + ZTEST_F(adltc2990_7_3, test_available_channels) { zassert_equal(-EINVAL, sensor_sample_fetch_chan(fixture->dev, SENSOR_CHAN_AMBIENT_TEMP));