Browse Source

drivers: npm13xx: add support for nPM1304

Add support for nPM1304 in the npm13xx drivers. The nPM1304 supports
different voltage and current ranges which are handled through the
initialization macros.

Signed-off-by: Sergei Ovchinnikov <sergei.ovchinnikov@nordicsemi.no>
pull/92045/head
Sergei Ovchinnikov 2 months ago committed by Fabio Baltieri
parent
commit
645159dc26
  1. 2
      drivers/gpio/Kconfig.npm13xx
  2. 21
      drivers/gpio/gpio_npm13xx.c
  3. 2
      drivers/led/Kconfig.npm13xx
  4. 17
      drivers/led/led_npm13xx.c
  5. 2
      drivers/mfd/Kconfig.npm13xx
  6. 32
      drivers/mfd/mfd_npm13xx.c
  7. 2
      drivers/regulator/Kconfig.npm13xx
  8. 60
      drivers/regulator/regulator_npm13xx.c
  9. 2
      drivers/sensor/nordic/npm13xx_charger/Kconfig
  10. 133
      drivers/sensor/nordic/npm13xx_charger/npm13xx_charger.c
  11. 2
      drivers/watchdog/Kconfig.npm13xx
  12. 20
      drivers/watchdog/wdt_npm13xx.c

2
drivers/gpio/Kconfig.npm13xx

@ -4,7 +4,7 @@
config GPIO_NPM13XX config GPIO_NPM13XX
bool "nPM13xx GPIO driver" bool "nPM13xx GPIO driver"
default y default y
depends on DT_HAS_NORDIC_NPM1300_GPIO_ENABLED depends on DT_HAS_NORDIC_NPM1300_GPIO_ENABLED || DT_HAS_NORDIC_NPM1304_GPIO_ENABLED
select I2C select I2C
select MFD select MFD
help help

21
drivers/gpio/gpio_npm13xx.c

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#define DT_DRV_COMPAT nordic_npm1300_gpio
#include <errno.h> #include <errno.h>
#include <zephyr/drivers/gpio.h> #include <zephyr/drivers/gpio.h>
@ -212,18 +210,25 @@ static int gpio_npm13xx_init(const struct device *dev)
return 0; return 0;
} }
#define GPIO_NPM13XX_DEFINE(n) \ #define GPIO_NPM13XX_DEFINE(partno, n) \
static const struct gpio_npm13xx_config gpio_npm13xx_config##n = { \ static const struct gpio_npm13xx_config gpio_##partno##_config##n = { \
.common = \ .common = \
{ \ { \
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
}, \ }, \
.mfd = DEVICE_DT_GET(DT_INST_PARENT(n))}; \ .mfd = DEVICE_DT_GET(DT_INST_PARENT(n))}; \
\ \
static struct gpio_npm13xx_data gpio_npm13xx_data##n; \ static struct gpio_npm13xx_data gpio_##partno##_data##n; \
\ \
DEVICE_DT_INST_DEFINE(n, gpio_npm13xx_init, NULL, &gpio_npm13xx_data##n, \ DEVICE_DT_INST_DEFINE(n, gpio_npm13xx_init, NULL, &gpio_##partno##_data##n, \
&gpio_npm13xx_config##n, POST_KERNEL, \ &gpio_##partno##_config##n, POST_KERNEL, \
CONFIG_GPIO_NPM13XX_INIT_PRIORITY, &gpio_npm13xx_api); CONFIG_GPIO_NPM13XX_INIT_PRIORITY, &gpio_npm13xx_api);
DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM13XX_DEFINE) #define DT_DRV_COMPAT nordic_npm1300_gpio
#define GPIO_NPM1300_DEFINE(n) GPIO_NPM13XX_DEFINE(npm1300, n)
DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM1300_DEFINE)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT nordic_npm1304_gpio
#define GPIO_NPM1304_DEFINE(n) GPIO_NPM13XX_DEFINE(npm1304, n)
DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM1304_DEFINE)

2
drivers/led/Kconfig.npm13xx

@ -4,7 +4,7 @@
config LED_NPM13XX config LED_NPM13XX
bool "nPM13xx LED driver" bool "nPM13xx LED driver"
default y default y
depends on DT_HAS_NORDIC_NPM1300_LED_ENABLED depends on DT_HAS_NORDIC_NPM1300_LED_ENABLED || DT_HAS_NORDIC_NPM1304_LED_ENABLED
select I2C select I2C
select MFD select MFD
help help

17
drivers/led/led_npm13xx.c

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#define DT_DRV_COMPAT nordic_npm1300_led
#include <errno.h> #include <errno.h>
#include <zephyr/device.h> #include <zephyr/device.h>
@ -87,14 +85,21 @@ static int led_npm13xx_init(const struct device *dev)
return 0; return 0;
} }
#define LED_NPM13XX_DEFINE(n) \ #define LED_NPM13XX_DEFINE(partno, n) \
static const struct led_npm13xx_config led_npm13xx_config##n = { \ static const struct led_npm13xx_config led_##partno##_config##n = { \
.mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \ .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \
.mode = {DT_INST_ENUM_IDX(n, nordic_led0_mode), \ .mode = {DT_INST_ENUM_IDX(n, nordic_led0_mode), \
DT_INST_ENUM_IDX(n, nordic_led1_mode), \ DT_INST_ENUM_IDX(n, nordic_led1_mode), \
DT_INST_ENUM_IDX(n, nordic_led2_mode)}}; \ DT_INST_ENUM_IDX(n, nordic_led2_mode)}}; \
\ \
DEVICE_DT_INST_DEFINE(n, &led_npm13xx_init, NULL, NULL, &led_npm13xx_config##n, \ DEVICE_DT_INST_DEFINE(n, &led_npm13xx_init, NULL, NULL, &led_##partno##_config##n, \
POST_KERNEL, CONFIG_LED_INIT_PRIORITY, &led_npm13xx_api); POST_KERNEL, CONFIG_LED_INIT_PRIORITY, &led_npm13xx_api);
DT_INST_FOREACH_STATUS_OKAY(LED_NPM13XX_DEFINE) #define DT_DRV_COMPAT nordic_npm1300_led
#define LED_NPM1300_DEFINE(n) LED_NPM13XX_DEFINE(npm1300, n)
DT_INST_FOREACH_STATUS_OKAY(LED_NPM1300_DEFINE)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT nordic_npm1304_led
#define LED_NPM1304_DEFINE(n) LED_NPM13XX_DEFINE(npm1304, n)
DT_INST_FOREACH_STATUS_OKAY(LED_NPM1304_DEFINE)

2
drivers/mfd/Kconfig.npm13xx

@ -4,7 +4,7 @@
config MFD_NPM13XX config MFD_NPM13XX
bool "nPM13xx PMIC multi-function device driver" bool "nPM13xx PMIC multi-function device driver"
default y default y
depends on DT_HAS_NORDIC_NPM1300_ENABLED depends on DT_HAS_NORDIC_NPM1300_ENABLED || DT_HAS_NORDIC_NPM1304_ENABLED
select I2C select I2C
help help
Enable the Nordic nPM13xx PMIC multi-function device driver Enable the Nordic nPM13xx PMIC multi-function device driver

32
drivers/mfd/mfd_npm13xx.c

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#define DT_DRV_COMPAT nordic_npm1300
#include <errno.h> #include <errno.h>
#include <zephyr/drivers/i2c.h> #include <zephyr/drivers/i2c.h>
@ -308,18 +306,26 @@ int mfd_npm13xx_remove_callback(const struct device *dev, struct gpio_callback *
return gpio_manage_callback(&data->callbacks, callback, false); return gpio_manage_callback(&data->callbacks, callback, false);
} }
#define MFD_NPM13XX_DEFINE(inst) \ #define MFD_NPM13XX_DEFINE(partno, n) \
static struct mfd_npm13xx_data data_##inst; \ static struct mfd_npm13xx_data mfd_##partno##_data##n; \
\ \
static const struct mfd_npm13xx_config config##inst = { \ static const struct mfd_npm13xx_config mfd_##partno##_config##n = { \
.i2c = I2C_DT_SPEC_INST_GET(inst), \ .i2c = I2C_DT_SPEC_INST_GET(n), \
.host_int_gpios = GPIO_DT_SPEC_INST_GET_OR(inst, host_int_gpios, {0}), \ .host_int_gpios = GPIO_DT_SPEC_INST_GET_OR(n, host_int_gpios, {0}), \
.pmic_int_pin = DT_INST_PROP_OR(inst, pmic_int_pin, 0), \ .pmic_int_pin = DT_INST_PROP_OR(n, pmic_int_pin, 0), \
.active_time = DT_INST_ENUM_IDX(inst, ship_to_active_time_ms), \ .active_time = DT_INST_ENUM_IDX(n, ship_to_active_time_ms), \
.lp_reset = DT_INST_ENUM_IDX_OR(inst, long_press_reset, 0), \ .lp_reset = DT_INST_ENUM_IDX_OR(n, long_press_reset, 0), \
}; \ }; \
\ \
DEVICE_DT_INST_DEFINE(inst, mfd_npm13xx_init, NULL, &data_##inst, &config##inst, \ DEVICE_DT_INST_DEFINE(n, mfd_npm13xx_init, NULL, &mfd_##partno##_data##n, \
POST_KERNEL, CONFIG_MFD_NPM13XX_INIT_PRIORITY, NULL); &mfd_##partno##_config##n, POST_KERNEL, \
CONFIG_MFD_NPM13XX_INIT_PRIORITY, NULL);
#define DT_DRV_COMPAT nordic_npm1300
#define MFD_NPM1300_DEFINE(n) MFD_NPM13XX_DEFINE(npm1300, n)
DT_INST_FOREACH_STATUS_OKAY(MFD_NPM1300_DEFINE)
DT_INST_FOREACH_STATUS_OKAY(MFD_NPM13XX_DEFINE) #undef DT_DRV_COMPAT
#define DT_DRV_COMPAT nordic_npm1304
#define MFD_NPM1304_DEFINE(n) MFD_NPM13XX_DEFINE(npm1304, n)
DT_INST_FOREACH_STATUS_OKAY(MFD_NPM1304_DEFINE)

2
drivers/regulator/Kconfig.npm13xx

@ -4,7 +4,7 @@
config REGULATOR_NPM13XX config REGULATOR_NPM13XX
bool "nPM13xx PMIC regulator driver" bool "nPM13xx PMIC regulator driver"
default y default y
depends on DT_HAS_NORDIC_NPM1300_REGULATOR_ENABLED depends on DT_HAS_NORDIC_NPM1300_REGULATOR_ENABLED || DT_HAS_NORDIC_NPM1304_REGULATOR_ENABLED
select I2C select I2C
select MFD select MFD
help help

60
drivers/regulator/regulator_npm13xx.c

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#define DT_DRV_COMPAT nordic_npm1300_regulator
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
@ -689,9 +687,6 @@ int regulator_npm13xx_init(const struct device *dev)
} }
ret = regulator_npm13xx_set_pin_ctrl(dev, &config->pwm_gpios, NPM13XX_GPIO_TYPE_PWM); ret = regulator_npm13xx_set_pin_ctrl(dev, &config->pwm_gpios, NPM13XX_GPIO_TYPE_PWM);
if (ret != 0) {
return ret;
}
return ret; return ret;
} }
@ -712,13 +707,13 @@ static DEVICE_API(regulator, api) = {
!!(DT_PROP_BY_IDX(node_id, prop, 1) & GPIO_ACTIVE_LOW)}), \ !!(DT_PROP_BY_IDX(node_id, prop, 1) & GPIO_ACTIVE_LOW)}), \
({NPM13XX_GPIO_UNUSED, false})) ({NPM13XX_GPIO_UNUSED, false}))
#define REGULATOR_NPM13XX_DEFINE(node_id, id, _source) \ #define REGULATOR_NPM13XX_DEFINE(partno, node_id, id, _source) \
BUILD_ASSERT(DT_PROP_LEN_OR(node_id, enable_gpio_config, 2) == 2); \ BUILD_ASSERT(DT_PROP_LEN_OR(node_id, enable_gpio_config, 2) == 2); \
BUILD_ASSERT(DT_PROP_LEN_OR(node_id, retention_gpio_config, 2) == 2); \ BUILD_ASSERT(DT_PROP_LEN_OR(node_id, retention_gpio_config, 2) == 2); \
BUILD_ASSERT(DT_PROP_LEN_OR(node_id, pwm_gpio_config, 2) == 2); \ BUILD_ASSERT(DT_PROP_LEN_OR(node_id, pwm_gpio_config, 2) == 2); \
static struct regulator_npm13xx_data data_##id; \ static struct regulator_npm13xx_data regulator_##partno##_data_##id; \
\ \
static const struct regulator_npm13xx_config config_##id = { \ static const struct regulator_npm13xx_config regulator_##partno##_config_##id = { \
.common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \ .common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \
.mfd = DEVICE_DT_GET(DT_GPARENT(node_id)), \ .mfd = DEVICE_DT_GET(DT_GPARENT(node_id)), \
.source = _source, \ .source = _source, \
@ -730,30 +725,39 @@ static DEVICE_API(regulator, api) = {
.active_discharge = DT_PROP(node_id, active_discharge), \ .active_discharge = DT_PROP(node_id, active_discharge), \
.ldo_disable_workaround = DT_PROP(node_id, nordic_anomaly38_disable_workaround)}; \ .ldo_disable_workaround = DT_PROP(node_id, nordic_anomaly38_disable_workaround)}; \
\ \
DEVICE_DT_DEFINE(node_id, regulator_npm13xx_init, NULL, &data_##id, &config_##id, \ DEVICE_DT_DEFINE(node_id, regulator_npm13xx_init, NULL, &regulator_##partno##_data_##id, \
POST_KERNEL, CONFIG_REGULATOR_NPM13XX_INIT_PRIORITY, &api); &regulator_##partno##_config_##id, POST_KERNEL, \
CONFIG_REGULATOR_NPM13XX_INIT_PRIORITY, &api);
#define REGULATOR_NPM13XX_DEFINE_COND(inst, child, source) \ #define REGULATOR_NPM13XX_DEFINE_COND(partno, n, child, source) \
COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \ COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(n, child)), \
(REGULATOR_NPM13XX_DEFINE(DT_INST_CHILD(inst, child), child##inst, source)), \ (REGULATOR_NPM13XX_DEFINE(partno, DT_INST_CHILD(n, child), child##n, source)), \
()) ())
#define REGULATOR_NPM13XX_DEFINE_ALL(inst) \ #define REGULATOR_NPM13XX_DEFINE_ALL(partno, n) \
static const struct regulator_npm13xx_pconfig config_##inst = { \ static const struct regulator_npm13xx_pconfig regulator_##partno##_config##n = { \
.mfd = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \
.dvs_state_pins = {GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 0, {0}), \ .dvs_state_pins = {GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 0, {0}), \
GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 1, {0}), \ GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 1, {0}), \
GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 2, {0}), \ GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 2, {0}), \
GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 3, {0}), \ GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 3, {0}), \
GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 4, {0})}}; \ GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 4, {0})}}; \
\ \
DEVICE_DT_INST_DEFINE(inst, regulator_npm13xx_common_init, NULL, NULL, &config_##inst, \ DEVICE_DT_INST_DEFINE(n, regulator_npm13xx_common_init, NULL, NULL, \
POST_KERNEL, CONFIG_REGULATOR_NPM13XX_COMMON_INIT_PRIORITY, \ &regulator_##partno##_config##n, POST_KERNEL, \
CONFIG_REGULATOR_NPM13XX_COMMON_INIT_PRIORITY, \
&parent_api); \ &parent_api); \
\ \
REGULATOR_NPM13XX_DEFINE_COND(inst, buck1, NPM13XX_SOURCE_BUCK1) \ REGULATOR_NPM13XX_DEFINE_COND(partno, n, buck1, NPM13XX_SOURCE_BUCK1) \
REGULATOR_NPM13XX_DEFINE_COND(inst, buck2, NPM13XX_SOURCE_BUCK2) \ REGULATOR_NPM13XX_DEFINE_COND(partno, n, buck2, NPM13XX_SOURCE_BUCK2) \
REGULATOR_NPM13XX_DEFINE_COND(inst, ldo1, NPM13XX_SOURCE_LDO1) \ REGULATOR_NPM13XX_DEFINE_COND(partno, n, ldo1, NPM13XX_SOURCE_LDO1) \
REGULATOR_NPM13XX_DEFINE_COND(inst, ldo2, NPM13XX_SOURCE_LDO2) REGULATOR_NPM13XX_DEFINE_COND(partno, n, ldo2, NPM13XX_SOURCE_LDO2)
#define DT_DRV_COMPAT nordic_npm1300_regulator
#define REGULATOR_NPM1300_DEFINE_ALL(n) REGULATOR_NPM13XX_DEFINE_ALL(npm1300, n)
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NPM1300_DEFINE_ALL)
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NPM13XX_DEFINE_ALL) #undef DT_DRV_COMPAT
#define DT_DRV_COMPAT nordic_npm1304_regulator
#define REGULATOR_NPM1304_DEFINE_ALL(n) REGULATOR_NPM13XX_DEFINE_ALL(npm1304, n)
DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NPM1304_DEFINE_ALL)

2
drivers/sensor/nordic/npm13xx_charger/Kconfig

@ -5,7 +5,7 @@
config NPM13XX_CHARGER config NPM13XX_CHARGER
bool "nPM13xx Charger" bool "nPM13xx Charger"
default y default y
depends on DT_HAS_NORDIC_NPM1300_CHARGER_ENABLED depends on DT_HAS_NORDIC_NPM1300_CHARGER_ENABLED || DT_HAS_NORDIC_NPM1304_CHARGER_ENABLED
select I2C select I2C
select MFD select MFD
select REQUIRES_FULL_LIBC select REQUIRES_FULL_LIBC

133
drivers/sensor/nordic/npm13xx_charger/npm13xx_charger.c

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#define DT_DRV_COMPAT nordic_npm1300_charger
#include <math.h> #include <math.h>
#include <zephyr/drivers/sensor.h> #include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/mfd/npm13xx.h> #include <zephyr/drivers/mfd/npm13xx.h>
@ -16,7 +14,10 @@ struct npm13xx_charger_config {
const struct device *mfd; const struct device *mfd;
int32_t term_microvolt; int32_t term_microvolt;
int32_t term_warm_microvolt; int32_t term_warm_microvolt;
const struct linear_range term_volt_ranges[2U];
int32_t current_microamp; int32_t current_microamp;
const struct linear_range current_range;
const int32_t full_scale_discharge_factors[2U];
int32_t dischg_limit_microamp; int32_t dischg_limit_microamp;
uint8_t dischg_limit_idx; uint8_t dischg_limit_idx;
int32_t vbus_limit_microamp; int32_t vbus_limit_microamp;
@ -137,14 +138,22 @@ struct adc_results_t {
#define DIETEMP_FACTOR_DIV 5000 #define DIETEMP_FACTOR_DIV 5000
/* Linear range for charger terminal voltage */ /* Linear range for charger terminal voltage */
static const struct linear_range charger_volt_ranges[] = { #define NPM1300_CHARGER_VOLT_RANGES \
LINEAR_RANGE_INIT(3500000, 50000, 0U, 3U), LINEAR_RANGE_INIT(4000000, 50000, 4U, 13U)}; {LINEAR_RANGE_INIT(3500000, 50000, 0U, 3U), LINEAR_RANGE_INIT(4000000, 50000, 4U, 13U)}
#define NPM1304_CHARGER_VOLT_RANGES \
{LINEAR_RANGE_INIT(3600000, 50000, 0U, 1U), LINEAR_RANGE_INIT(4000000, 50000, 2U, 15U)}
/* Linear range for charger current */ /* Linear range for charger current */
static const struct linear_range charger_current_range = LINEAR_RANGE_INIT(32000, 2000, 16U, 400U); #define NPM1300_CHARGER_CURRENT_RANGE LINEAR_RANGE_INIT(32000, 2000, 16U, 400U)
#define NPM1304_CHARGER_CURRENT_RANGE LINEAR_RANGE_INIT(4000, 500, 8U, 200U)
/* Full-scale factors for calculating current */
#define NPM1300_FULL_SCALE_DISCHARGE_FACTORS {112, 100}
#define NPM1304_FULL_SCALE_DISCHARGE_FACTORS {415, 400}
static const int32_t full_scale_charge_factors[] = {125, 100};
/* Allowed values for discharge limit */ /* Allowed values for discharge limit */
static const uint16_t discharge_limits[] = {84U, 415U}; static const uint16_t npm1300_discharge_limits[] = {84U, 415U};
/* Linear range for vbusin current limit */ /* Linear range for vbusin current limit */
static const struct linear_range vbus_current_range = LINEAR_RANGE_INIT(100000, 100000, 1U, 15U); static const struct linear_range vbus_current_range = LINEAR_RANGE_INIT(100000, 100000, 1U, 15U);
@ -193,41 +202,49 @@ static void calc_current(const struct npm13xx_charger_config *const config,
int32_t full_scale_ua; int32_t full_scale_ua;
int32_t current_ua; int32_t current_ua;
/* Largest value of discharge limit and charge limit is 1A.
* We can therefore guarantee that multiplying the uA by 1000 does not overflow.
* 1000 * 1'000'000 uA < 2**31
* 1000000000 < 2147483648
*/
switch (data->ibat_stat) { switch (data->ibat_stat) {
case IBAT_STAT_DISCHARGE: case IBAT_STAT_DISCHARGE:
/* Ref: PS v1.2 Section 7.1.7: Full scale multiplied by 1.12 */ /* nPM1300: Largest discharge limit is 1A. Multiplying it by 112 will not overflow.
full_scale_ua = -(1000 * config->dischg_limit_microamp) / 893; * 112 * -1_000_000 > INT32_MIN
* -112_000_000 > -2_147_483_648
* nPM1304: Discharge limit is 125mA. Multiplying it by 415 will not overflow.
* 415 * -125_000 > INT32_MIN
* -51_875_000 > -2_147_483_648
*/
full_scale_ua = -config->dischg_limit_microamp *
config->full_scale_discharge_factors[0] /
config->full_scale_discharge_factors[1];
break; break;
case IBAT_STAT_CHARGE_TRICKLE: case IBAT_STAT_CHARGE_TRICKLE:
/* Fallthrough */ /* Fallthrough */
case IBAT_STAT_CHARGE_COOL: case IBAT_STAT_CHARGE_COOL:
/* Fallthrough */ /* Fallthrough */
case IBAT_STAT_CHARGE_NORMAL: case IBAT_STAT_CHARGE_NORMAL:
/* Ref: PS v1.2 Section 7.1.7: Full scale multiplied by 1.25 */ /* nPM1300: Largest charge limit is 800mA. Multiplying it by 125 will not overflow.
full_scale_ua = (1000 * config->current_microamp) / 800; * 125 * 800_000 < INT32_MAX
* 100_000_000 < 2_147_483_647
* nPM1304: Largest charge limit is even lower - no overflow.
*/
full_scale_ua = config->current_microamp * full_scale_charge_factors[0] /
full_scale_charge_factors[1];
break; break;
default: default:
full_scale_ua = 0; full_scale_ua = 0;
break; break;
} }
/* Largest possible value for data->current is 1023 /* Largest possible value for data->current is 1023 (10-bit ADC)
* Limits for full_scale_ua are -1'119'820 and 1'000'000 * Limits for full_scale_ua are -1_120_000 and 1_000_000
* 1023 * -1119820 > -2**31 * 1023 * -1_120_000 > INT32_MIN
* -1145575860 > -2147483648 * -1_145_760_000 > -2_147_483_648
* 1023 * 1000000 < 2**31 * 1023 * 1_000_000 < INT32_MAX
* 1023000000 < 2147483648 * 1_023_000_000 < 2_147_483_647
*/ */
__ASSERT_NO_MSG(data->current <= 1023); __ASSERT_NO_MSG(data->current <= 1023);
__ASSERT_NO_MSG(full_scale_ua <= 1000000); __ASSERT_NO_MSG(full_scale_ua <= 1000000);
__ASSERT_NO_MSG(full_scale_ua >= -1119820); __ASSERT_NO_MSG(full_scale_ua >= -1120000);
current_ua = (data->current * full_scale_ua) / 1024; current_ua = (data->current * full_scale_ua) / 1023;
(void)sensor_value_from_micro(valp, current_ua); (void)sensor_value_from_micro(valp, current_ua);
} }
@ -324,9 +341,6 @@ int npm13xx_charger_sample_fetch(const struct device *dev, enum sensor_channel c
/* Read vbus status */ /* Read vbus status */
ret = mfd_npm13xx_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data->vbus_stat); ret = mfd_npm13xx_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data->vbus_stat);
if (ret != 0) {
return ret;
}
return ret; return ret;
} }
@ -532,9 +546,9 @@ int npm13xx_charger_init(const struct device *dev)
} }
/* Configure termination voltages */ /* Configure termination voltages */
ret = linear_range_group_get_win_index(charger_volt_ranges, ARRAY_SIZE(charger_volt_ranges), ret = linear_range_group_get_win_index(
config->term_microvolt, config->term_microvolt, config->term_volt_ranges, ARRAY_SIZE(config->term_volt_ranges),
&idx); config->term_microvolt, config->term_microvolt, &idx);
if (ret == -EINVAL) { if (ret == -EINVAL) {
return ret; return ret;
} }
@ -543,9 +557,9 @@ int npm13xx_charger_init(const struct device *dev)
return ret; return ret;
} }
ret = linear_range_group_get_win_index(charger_volt_ranges, ARRAY_SIZE(charger_volt_ranges), ret = linear_range_group_get_win_index(
config->term_warm_microvolt, config->term_volt_ranges, ARRAY_SIZE(config->term_volt_ranges),
config->term_warm_microvolt, &idx); config->term_warm_microvolt, config->term_warm_microvolt, &idx);
if (ret == -EINVAL) { if (ret == -EINVAL) {
return ret; return ret;
} }
@ -556,22 +570,29 @@ int npm13xx_charger_init(const struct device *dev)
} }
/* Set current, allow rounding down to closest value */ /* Set current, allow rounding down to closest value */
ret = linear_range_get_win_index(&charger_current_range, ret = linear_range_get_win_index(&config->current_range,
config->current_microamp - charger_current_range.step, config->current_microamp - config->current_range.step + 1,
config->current_microamp, &idx); config->current_microamp, &idx);
if (ret == -EINVAL) { if (ret == -EINVAL) {
return ret; return ret;
} }
ret = mfd_npm13xx_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET, idx / 2U, idx & 1U); if (config->dischg_limit_idx == UINT8_MAX) {
if (ret != 0) { /* Set only charge current MSB for nPM1304 */
return ret; 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);
if (ret != 0) {
return ret;
}
/* Set discharge limit */ ret = mfd_npm13xx_reg_write2(
ret = mfd_npm13xx_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET_DISCHG, config->mfd, CHGR_BASE, CHGR_OFFSET_ISET_DISCHG,
discharge_limits[config->dischg_limit_idx] / 2U, npm1300_discharge_limits[config->dischg_limit_idx] / 2U,
discharge_limits[config->dischg_limit_idx] & 1U); npm1300_discharge_limits[config->dischg_limit_idx] & 1U);
}
if (ret != 0) { if (ret != 0) {
return ret; return ret;
} }
@ -666,19 +687,23 @@ static DEVICE_API(sensor, npm13xx_charger_battery_driver_api) = {
.attr_get = npm13xx_charger_attr_get, .attr_get = npm13xx_charger_attr_get,
}; };
#define NPM13XX_CHARGER_INIT(n) \ #define NPM13XX_CHARGER_INIT(partno, n) \
BUILD_ASSERT(DT_INST_ENUM_IDX(n, dischg_limit_microamp) < ARRAY_SIZE(discharge_limits)); \ BUILD_ASSERT(DT_INST_ENUM_IDX_OR(n, dischg_limit_microamp, 0) < \
ARRAY_SIZE(npm1300_discharge_limits)); \
\ \
static struct npm13xx_charger_data npm13xx_charger_data_##n; \ static struct npm13xx_charger_data charger_##partno##_data##n; \
\ \
static const struct npm13xx_charger_config npm13xx_charger_config_##n = { \ static const struct npm13xx_charger_config charger_##partno##_config##n = { \
.mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \ .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \
.term_microvolt = DT_INST_PROP(n, term_microvolt), \ .term_microvolt = DT_INST_PROP(n, term_microvolt), \
.term_warm_microvolt = \ .term_warm_microvolt = \
DT_INST_PROP_OR(n, term_warm_microvolt, DT_INST_PROP(n, term_microvolt)), \ DT_INST_PROP_OR(n, term_warm_microvolt, DT_INST_PROP(n, term_microvolt)), \
.term_volt_ranges = partno##_CHARGER_VOLT_RANGES, \
.current_microamp = DT_INST_PROP(n, current_microamp), \ .current_microamp = DT_INST_PROP(n, current_microamp), \
.current_range = partno##_CHARGER_CURRENT_RANGE, \
.full_scale_discharge_factors = partno##_FULL_SCALE_DISCHARGE_FACTORS, \
.dischg_limit_microamp = DT_INST_PROP(n, dischg_limit_microamp), \ .dischg_limit_microamp = DT_INST_PROP(n, dischg_limit_microamp), \
.dischg_limit_idx = DT_INST_ENUM_IDX(n, dischg_limit_microamp), \ .dischg_limit_idx = DT_INST_ENUM_IDX_OR(n, dischg_limit_microamp, UINT8_MAX), \
.vbus_limit_microamp = DT_INST_PROP(n, vbus_limit_microamp), \ .vbus_limit_microamp = DT_INST_PROP(n, vbus_limit_microamp), \
.thermistor_ohms = DT_INST_PROP(n, thermistor_ohms), \ .thermistor_ohms = DT_INST_PROP(n, thermistor_ohms), \
.thermistor_idx = DT_INST_ENUM_IDX(n, thermistor_ohms), \ .thermistor_idx = DT_INST_ENUM_IDX(n, thermistor_ohms), \
@ -696,9 +721,17 @@ static DEVICE_API(sensor, npm13xx_charger_battery_driver_api) = {
DT_INST_PROP_OR(n, thermistor_warm_millidegrees, INT32_MAX), \ DT_INST_PROP_OR(n, thermistor_warm_millidegrees, INT32_MAX), \
DT_INST_PROP_OR(n, thermistor_hot_millidegrees, INT32_MAX)}}; \ DT_INST_PROP_OR(n, thermistor_hot_millidegrees, INT32_MAX)}}; \
\ \
SENSOR_DEVICE_DT_INST_DEFINE(n, &npm13xx_charger_init, NULL, &npm13xx_charger_data_##n, \ SENSOR_DEVICE_DT_INST_DEFINE(n, &npm13xx_charger_init, NULL, &charger_##partno##_data##n, \
&npm13xx_charger_config_##n, POST_KERNEL, \ &charger_##partno##_config##n, POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, \ CONFIG_SENSOR_INIT_PRIORITY, \
&npm13xx_charger_battery_driver_api); &npm13xx_charger_battery_driver_api);
DT_INST_FOREACH_STATUS_OKAY(NPM13XX_CHARGER_INIT) #undef DT_DRV_COMPAT
#define DT_DRV_COMPAT nordic_npm1300_charger
#define NPM1300_CHARGER_INIT(n) NPM13XX_CHARGER_INIT(NPM1300, n)
DT_INST_FOREACH_STATUS_OKAY(NPM1300_CHARGER_INIT)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT nordic_npm1304_charger
#define NPM1304_CHARGER_INIT(n) NPM13XX_CHARGER_INIT(NPM1304, n)
DT_INST_FOREACH_STATUS_OKAY(NPM1304_CHARGER_INIT)

2
drivers/watchdog/Kconfig.npm13xx

@ -4,7 +4,7 @@
config WDT_NPM13XX config WDT_NPM13XX
bool "nPM13xx Watchdog driver" bool "nPM13xx Watchdog driver"
default y default y
depends on DT_HAS_NORDIC_NPM1300_WDT_ENABLED depends on DT_HAS_NORDIC_NPM1300_WDT_ENABLED || DT_HAS_NORDIC_NPM1304_WDT_ENABLED
select I2C select I2C
select MFD select MFD
help help

20
drivers/watchdog/wdt_npm13xx.c

@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#define DT_DRV_COMPAT nordic_npm13xx_wdt
#include <errno.h> #include <errno.h>
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
@ -154,15 +152,23 @@ static int wdt_npm13xx_init(const struct device *dev)
return 0; return 0;
} }
#define WDT_NPM13XX_DEFINE(n) \ #define WDT_NPM13XX_DEFINE(partno, n) \
static struct wdt_npm13xx_data data##n; \ static struct wdt_npm13xx_data wdt_##partno##_data##n; \
\ \
static const struct wdt_npm13xx_config config##n = { \ static const struct wdt_npm13xx_config wdt_##partno##_config##n = { \
.mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \ .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \
.reset_gpios = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), \ .reset_gpios = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), \
}; \ }; \
\ \
DEVICE_DT_INST_DEFINE(n, &wdt_npm13xx_init, NULL, &data##n, &config##n, POST_KERNEL, \ DEVICE_DT_INST_DEFINE(n, &wdt_npm13xx_init, NULL, &wdt_##partno##_data##n, \
&wdt_##partno##_config##n, POST_KERNEL, \
CONFIG_WDT_NPM13XX_INIT_PRIORITY, &wdt_npm13xx_api); CONFIG_WDT_NPM13XX_INIT_PRIORITY, &wdt_npm13xx_api);
DT_INST_FOREACH_STATUS_OKAY(WDT_NPM13XX_DEFINE) #define DT_DRV_COMPAT nordic_npm1300_wdt
#define WDT_NPM1300_DEFINE(n) WDT_NPM13XX_DEFINE(npm1300, n)
DT_INST_FOREACH_STATUS_OKAY(WDT_NPM1300_DEFINE)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT nordic_npm1304_wdt
#define WDT_NPM1304_DEFINE(n) WDT_NPM13XX_DEFINE(npm1304, n)
DT_INST_FOREACH_STATUS_OKAY(WDT_NPM1304_DEFINE)

Loading…
Cancel
Save