From 7ea29564bbca6abe5c37d95946be2c72ef68c002 Mon Sep 17 00:00:00 2001 From: Sergei Ovchinnikov Date: Fri, 15 Aug 2025 14:35:30 +0200 Subject: [PATCH] drivers: sensor: npm13xx_charger: improve sample fetching Change the npm13xx_charger fetch function to first trigger a sample and then block until the result is available. Signed-off-by: Sergei Ovchinnikov --- drivers/mfd/mfd_npm13xx.c | 11 +-- .../nordic/npm13xx_charger/npm13xx_charger.c | 68 +++++++++---------- include/zephyr/drivers/mfd/npm13xx.h | 12 ++-- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/drivers/mfd/mfd_npm13xx.c b/drivers/mfd/mfd_npm13xx.c index f0e83e7a4a308..9bc9ada323524 100644 --- a/drivers/mfd/mfd_npm13xx.c +++ b/drivers/mfd/mfd_npm13xx.c @@ -206,13 +206,16 @@ int mfd_npm13xx_reg_write(const struct device *dev, uint8_t base, uint8_t offset return i2c_write_dt(&config->i2c, buff, sizeof(buff)); } -int mfd_npm13xx_reg_write2(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data1, - uint8_t data2) +int mfd_npm13xx_reg_write_burst(const struct device *dev, uint8_t base, uint8_t offset, void *data, + size_t len) { const struct mfd_npm13xx_config *config = dev->config; - uint8_t buff[] = {base, offset, data1, data2}; + struct i2c_msg msg[2] = { + {.buf = (uint8_t []){base, offset}, .len = 2, .flags = I2C_MSG_WRITE}, + {.buf = data, .len = len, .flags = I2C_MSG_WRITE | I2C_MSG_STOP}, + }; - return i2c_write_dt(&config->i2c, buff, sizeof(buff)); + return i2c_transfer_dt(&config->i2c, msg, 2); } int mfd_npm13xx_reg_update(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data, diff --git a/drivers/sensor/nordic/npm13xx_charger/npm13xx_charger.c b/drivers/sensor/nordic/npm13xx_charger/npm13xx_charger.c index 1cb3453091d87..b32cdf17ebfa5 100644 --- a/drivers/sensor/nordic/npm13xx_charger/npm13xx_charger.c +++ b/drivers/sensor/nordic/npm13xx_charger/npm13xx_charger.c @@ -76,6 +76,8 @@ struct npm13xx_charger_data { #define ADC_OFFSET_RESULTS 0x10U #define ADC_OFFSET_IBAT_EN 0x24U +#define ADC_CONV_TIME_US 250U + /* nPM13xx VBUS register offsets */ #define VBUS_OFFSET_ILIMUPDATE 0x00U #define VBUS_OFFSET_ILIM 0x01U @@ -302,6 +304,17 @@ int npm13xx_charger_sample_fetch(const struct device *dev, enum sensor_channel c struct npm13xx_charger_data *data = dev->data; struct adc_results_t results; int ret; + k_timepoint_t conv_done; + + /* Trigger current+voltage, NTC and die temp measurements (four in total) */ + ret = mfd_npm13xx_reg_write_burst(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, + (uint8_t []){1U, 1U, 1U}, 3U); + if (ret != 0) { + return ret; + } + + /* Set timepoint for conversion and read status registers in the meantime */ + conv_done = sys_timepoint_calc(K_USEC(ADC_CONV_TIME_US * 4)); /* Read charge status and error reason */ ret = mfd_npm13xx_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_CHG_STAT, &data->status); @@ -314,6 +327,14 @@ int npm13xx_charger_sample_fetch(const struct device *dev, enum sensor_channel c return ret; } + /* Read vbus status */ + ret = mfd_npm13xx_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data->vbus_stat); + if (ret != 0) { + return ret; + } + + k_sleep(sys_timepoint_timeout(conv_done)); + /* Read adc results */ ret = mfd_npm13xx_reg_read_burst(config->mfd, ADC_BASE, ADC_OFFSET_RESULTS, &results, sizeof(results)); @@ -327,21 +348,6 @@ int npm13xx_charger_sample_fetch(const struct device *dev, enum sensor_channel c data->current = adc_get_res(results.msb_ibat, results.lsb_b, ADC_LSB_IBAT_SHIFT); data->ibat_stat = results.ibat_stat; - /* Trigger ntc and die temperature measurements */ - ret = mfd_npm13xx_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U); - if (ret != 0) { - return ret; - } - - /* Trigger current and voltage measurement */ - ret = mfd_npm13xx_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); - if (ret != 0) { - return ret; - } - - /* Read vbus status */ - ret = mfd_npm13xx_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data->vbus_stat); - return ret; } @@ -354,9 +360,10 @@ static int set_ntc_thresholds(const struct npm13xx_charger_config *const config) /* Ref: Datasheet Figure 14: Equation for battery temperature */ uint16_t code = (1024 * res) / (res + config->thermistor_ohms); - int ret = mfd_npm13xx_reg_write2( + int ret = mfd_npm13xx_reg_write_burst( config->mfd, CHGR_BASE, CHGR_OFFSET_NTC_TEMPS + (idx * 2U), - code >> NTCTEMP_MSB_SHIFT, code & NTCTEMP_LSB_MASK); + (uint8_t []){code >> NTCTEMP_MSB_SHIFT, code & NTCTEMP_LSB_MASK}, + 2U); if (ret != 0) { return ret; @@ -377,9 +384,10 @@ static int set_dietemp_thresholds(const struct npm13xx_charger_config *const con DIETEMP_FACTOR_DIV; uint16_t code = DIV_ROUND_CLOSEST(numerator, DIETEMP_FACTOR_MUL); - int ret = mfd_npm13xx_reg_write2( + int ret = mfd_npm13xx_reg_write_burst( config->mfd, CHGR_BASE, CHGR_OFFSET_DIE_TEMPS + (idx * 2U), - code >> DIETEMP_MSB_SHIFT, code & DIETEMP_LSB_MASK); + (uint8_t []){code >> DIETEMP_MSB_SHIFT, code & DIETEMP_LSB_MASK}, + 2U); if (ret != 0) { return ret; @@ -582,16 +590,16 @@ int npm13xx_charger_init(const struct device *dev) ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET, idx); } else { /* Set charge current MSB and LSB and discharge limit for nPM1300 */ - ret = mfd_npm13xx_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET, idx / 2U, - idx & 1U); + ret = mfd_npm13xx_reg_write_burst(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET, + (uint8_t []){idx / 2U, idx & 1U}, 2U); if (ret != 0) { return ret; } - ret = mfd_npm13xx_reg_write2( + ret = mfd_npm13xx_reg_write_burst( config->mfd, CHGR_BASE, CHGR_OFFSET_ISET_DISCHG, - npm1300_discharge_limits[config->dischg_limit_idx] / 2U, - npm1300_discharge_limits[config->dischg_limit_idx] & 1U); + (uint8_t []){npm1300_discharge_limits[config->dischg_limit_idx] / 2U, + npm1300_discharge_limits[config->dischg_limit_idx] & 1U}, 2U); } if (ret != 0) { return ret; @@ -628,18 +636,6 @@ int npm13xx_charger_init(const struct device *dev) return ret; } - /* Trigger current and voltage measurement */ - ret = mfd_npm13xx_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); - if (ret != 0) { - return ret; - } - - /* Trigger ntc and die temperature measurements */ - ret = mfd_npm13xx_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U); - if (ret != 0) { - return ret; - } - /* Enable automatic temperature measurements during charging */ ret = mfd_npm13xx_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_AUTO, 1U); if (ret != 0) { diff --git a/include/zephyr/drivers/mfd/npm13xx.h b/include/zephyr/drivers/mfd/npm13xx.h index b9e6d5120f679..7b49cb5e6a36b 100644 --- a/include/zephyr/drivers/mfd/npm13xx.h +++ b/include/zephyr/drivers/mfd/npm13xx.h @@ -79,18 +79,18 @@ int mfd_npm13xx_reg_read(const struct device *dev, uint8_t base, uint8_t offset, int mfd_npm13xx_reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data); /** - * @brief Write two registers to npm13xx + * @brief Write multiple registers to npm13xx * * @param dev npm13xx mfd device * @param base Register base address (bits 15..8 of 16-bit address) - * @param offset Register offset address (bits 7..0 of 16-bit address) - * @param data1 first byte of data to write - * @param data2 second byte of data to write + * @param offset First register offset address (bits 7..0 of 16-bit address) + * @param data Pointer to buffer to write + * @param len Number of bytes to write * @retval 0 If successful * @retval -errno In case of any bus error (see i2c_write_dt()) */ -int mfd_npm13xx_reg_write2(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data1, - uint8_t data2); +int mfd_npm13xx_reg_write_burst(const struct device *dev, uint8_t base, uint8_t offset, void *data, + size_t len); /** * @brief Update selected bits in npm13xx register