1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers: add bq2429x power management IC driver

Signed-off-by: Jean Pierre Dudey <me@jeandudey.tech>
This commit is contained in:
Jean Pierre Dudey 2020-11-25 11:32:36 +01:00
parent e1052f0152
commit 273721efc0
19 changed files with 1791 additions and 0 deletions

View File

@ -71,6 +71,7 @@
/drivers/at86rf215/ @benpicco
/drivers/at86rf2xx/ @daniel-k @Hyungsin @jia200x @smlng @miri64
/drivers/bh1900nux/ @wosym
/drivers/bq2429x/ @jeandudey
/drivers/cc110x/ @maribu
/drivers/cc1xxx_common/ @maribu
/drivers/ccs811/ @gschorcht
@ -132,6 +133,7 @@
/tests/ @smlng @leandrolanzieri @aabadie @MichelRottleuthner @fjmolinas
/tests/candev/ @wosym
/tests/driver_bq2429x/ @jeandudey
/tests/gnrc* @miri64
/tests/lwip* @miri64
/tests/slip/ @miri64

View File

@ -33,6 +33,7 @@ endmenu # Display Device Drivers
menu "Miscellaneous Device Drivers"
rsource "at/Kconfig"
rsource "at24mac/Kconfig"
rsource "bq2429x/Kconfig"
rsource "ds1307/Kconfig"
rsource "ds3231/Kconfig"
rsource "ds3234/Kconfig"

View File

@ -36,6 +36,10 @@ ifneq (,$(filter bm%280_spi,$(USEMODULE)))
USEMODULE += bmx280
endif
ifneq (,$(filter bq2429x_int,$(USEMODULE)))
USEMODULE += bq2429x
endif
ifneq (,$(filter cc110%,$(USEMODULE)))
USEMODULE += cc110x
endif

38
drivers/bq2429x/Kconfig Normal file
View File

@ -0,0 +1,38 @@
# Copyright (C) 2020 Locha Inc
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
#
menuconfig MODULE_BQ2429X
bool "BQ2429x single-cell USB charger"
depends on HAS_PERIPH_I2C
depends on HAS_PERIPH_GPIO
depends on TEST_KCONFIG
select MODULE_PERIPH_I2C
select MODULE_PERIPH_GPIO
default y if HAVE_BQ2429X
help
The driver can be used with Texas Instruments USB charger ICs: BQ24295,
BQ24296, BQ24297, BQ24298, BQ24292I, BQ24296M.
config MODULE_BQ2429X_INT
bool "Interrupt handling"
depends on HAS_PERIPH_GPIO_IRQ
depends on MODULE_BQ2429X
select MODULE_PERIPH_GPIO_IRQ
default y if HAVE_BQ2429X_INT
help
Say y to include interrupt handling functionality.
config HAVE_BQ2429X
bool
help
Indicates that a BQ2429x charger and power management IC is present.
config HAVE_BQ2429X_INT
bool
help
Indicates that a BQ2429x charger and power management IC is present,
with interrupt functionality (the INT pin is connected).

1
drivers/bq2429x/Makefile Normal file
View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,5 @@
FEATURES_REQUIRED += periph_i2c
FEATURES_REQUIRED += periph_gpio
ifneq (,$(filter $(USEMODULE),bq2429x_int))
FEATURES_REQUIRED += periph_gpio_irq
endif

View File

@ -0,0 +1,2 @@
USEMODULE_INCLUDES_bq2429x := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_bq2429x)

338
drivers/bq2429x/bq2429x.c Normal file
View File

@ -0,0 +1,338 @@
/*
* Copyright (C) 2020 Locha Inc
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_bq2429x
* @{
*
* @file
* @brief Device driver implementation for BQ2429x power ICs
*
* @author Jean Pierre Dudey <jeandudey@hotmail.com>
*
* @}
*/
#include "bq2429x.h"
#include "bq2429x_internal.h"
#define ENABLE_DEBUG 0
#include "debug.h"
#define DEBUG_DEV(f, d, ...) \
DEBUG("[bq2429x] %s i2c dev=%d : " f "\n", \
__func__, d->params.i2c, ## __VA_ARGS__);
#define EXEC_RET(func) \
do { \
int _ret; \
if ((_ret = (func)) != BQ2429X_OK) { \
return _ret; \
} \
} while (0)
static inline int _read_reg(const bq2429x_t *dev, uint8_t reg, uint8_t *value)
{
int ret;
i2c_acquire(dev->params.i2c);
if ((ret = i2c_read_reg(dev->params.i2c, BQ2429X_I2C_ADDR, reg, value,
0)) < 0) {
DEBUG_DEV("couldn't read reg=%02x ret=%d", dev, (unsigned)reg, ret);
i2c_release(dev->params.i2c);
return BQ2429X_ERR_I2C;
}
i2c_release(dev->params.i2c);
return BQ2429X_OK;
}
static inline int _write_reg(const bq2429x_t *dev, uint8_t reg, uint8_t value)
{
int ret;
i2c_acquire(dev->params.i2c);
if ((ret = i2c_write_reg(dev->params.i2c, BQ2429X_I2C_ADDR, reg, value,
0)) < 0) {
DEBUG_DEV("couldn't write reg=%02x: ret=%d", dev, (unsigned)reg, ret);
i2c_release(dev->params.i2c);
return BQ2429X_ERR_I2C;
}
i2c_release(dev->params.i2c);
return BQ2429X_OK;
}
static int _update_bits(const bq2429x_t *dev, uint8_t reg, uint8_t mask,
uint8_t value)
{
uint8_t tmp;
EXEC_RET(_read_reg(dev, reg, &tmp));
tmp &= ~mask;
tmp |= value & mask;
return _write_reg(dev, reg, tmp);
}
static int _update_charge_params(const bq2429x_t *dev)
{
assert(dev);
DEBUG_DEV("", dev);
EXEC_RET(_update_bits(dev, BQ2429X_REG00, BQ2429X_REG00_VINDPM_m,
dev->params.vlim << BQ2429X_REG00_VINDPM_s));
EXEC_RET(_update_bits(dev, BQ2429X_REG00, BQ2429X_REG00_IINLIM_m,
dev->params.ilim << BQ2429X_REG00_IINLIM_s));
EXEC_RET(_update_bits(dev, BQ2429X_REG02, BQ2429X_REG02_ICHG_m,
dev->params.ichg << BQ2429X_REG02_ICHG_s));
EXEC_RET(_update_bits(dev, BQ2429X_REG04, BQ2429X_REG04_VREG_m,
dev->params.vreg << BQ2429X_REG04_VREG_s));
return BQ2429X_OK;
}
int bq2429x_init(bq2429x_t *dev, const bq2429x_params_t *params)
{
assert(dev && params);
DEBUG_DEV("", dev);
dev->params = *params;
if (!gpio_is_equal(dev->params.ce_pin, GPIO_UNDEF)) {
if (gpio_init(dev->params.ce_pin, GPIO_OUT) < 0) {
DEBUG_DEV("couldn't initialize CE pin", dev);
return BQ2429X_ERR_GPIO;
}
/* enable charge by default */
gpio_clear(dev->params.ce_pin);
}
if (!gpio_is_equal(dev->params.otg_pin, GPIO_UNDEF)) {
if (gpio_init(dev->params.otg_pin, GPIO_OUT) < 0) {
DEBUG_DEV("couldn't initialize OTG pin", dev);
return BQ2429X_ERR_GPIO;
}
/* disable OTG by default */
gpio_clear(dev->params.otg_pin);
}
/* update parameters on the device */
EXEC_RET(_update_charge_params(dev));
return BQ2429X_OK;
}
#if IS_USED(MODULE_BQ2429X_INT)
int bq2429x_init_int(bq2429x_t *dev, bq2429x_int_cb_t cb, void *arg)
{
assert(dev && !gpio_is_equal(dev->params.int_pin, GPIO_UNDEF) && cb);
DEBUG_DEV("cb=%p arg=%p", dev, cb, arg);
/* the device always emits an active-low 256-us pulse */
if (gpio_init_int(dev->params.int_pin, GPIO_IN, GPIO_FALLING, cb,
arg) < 0) {
return BQ2429X_ERR_GPIO;
}
return BQ2429X_OK;
}
#endif
int bq2429x_get_status(const bq2429x_t *dev, bq2429x_status_t *status)
{
assert(dev && status);
DEBUG_DEV("", dev);
uint8_t val;
EXEC_RET(_read_reg(dev, BQ2429X_REG08, &val));
status->vbus = (val & BQ2429X_REG08_VBUS_STATUS_m)
>> BQ2429X_REG08_VBUS_STATUS_s;
status->chrg = (val & BQ2429X_REG08_CHG_STAT_m)
>> BQ2429X_REG08_CHG_STAT_s;
status->dpm = (val & BQ2429X_REG08_DPM_STAT_m)
>> BQ2429X_REG08_DPM_STAT_s;
status->pg = (val & BQ2429X_REG08_PG_STAT_m)
>> BQ2429X_REG08_PG_STAT_s;
status->therm = (val & BQ2429X_REG08_THERM_STAT_m)
>> BQ2429X_REG08_THERM_STAT_s;
status->vsys = (val & BQ2429X_REG08_VSYS_STAT_m)
>> BQ2429X_REG08_VSYS_STAT_s;
return BQ2429X_OK;
}
int bq2429x_get_fault(const bq2429x_t *dev, bq2429x_fault_t *fault)
{
assert(dev && fault);
DEBUG_DEV("", dev);
uint8_t val;
EXEC_RET(_read_reg(dev, BQ2429X_REG09, &val));
fault->watchdog = (val & BQ2429X_REG09_WD_FAULT_m)
>> BQ2429X_REG09_WD_FAULT_s;
fault->otg = (val & BQ2429X_REG09_OTG_FAULT_m)
>> BQ2429X_REG09_OTG_FAULT_s;
fault->chrg = (val & BQ2429X_REG09_CHRG_FAULT_m)
>> BQ2429X_REG09_CHRG_FAULT_s;
fault->bat = (val & BQ2429X_REG09_BAT_FAULT_m)
>> BQ2429X_REG09_BAT_FAULT_s;
fault->ntc_fault_1 = (val & BQ2429X_REG09_NTC_FAULT_1_m)
>> BQ2429X_REG09_NTC_FAULT_1_s;
fault->ntc_fault_0 = (val & BQ2429X_REG09_NTC_FAULT_0_m)
>> BQ2429X_REG09_NTC_FAULT_0_s;
return BQ2429X_OK;
}
int bq2429x_enable_otg(const bq2429x_t *dev)
{
assert(dev);
DEBUG_DEV("", dev);
if (!gpio_is_equal(dev->params.otg_pin, GPIO_UNDEF)) {
gpio_set(dev->params.otg_pin);
}
uint8_t val = BQ2429X_REG01_OTG_ENABLE << BQ2429X_REG01_OTG_s;
return _update_bits(dev, BQ2429X_REG01, BQ2429X_REG01_OTG_m, val);
}
int bq2429x_disable_otg(const bq2429x_t *dev)
{
assert(dev);
DEBUG_DEV("", dev);
if (!gpio_is_equal(dev->params.otg_pin, GPIO_UNDEF)) {
gpio_clear(dev->params.otg_pin);
}
uint8_t val = BQ2429X_REG01_OTG_DISABLE << BQ2429X_REG01_OTG_s;
return _update_bits(dev, BQ2429X_REG01, BQ2429X_REG01_OTG_m, val);
}
int bq2429x_enable_charge(const bq2429x_t *dev)
{
assert(dev);
DEBUG_DEV("", dev);
if (!gpio_is_equal(dev->params.ce_pin, GPIO_UNDEF)) {
gpio_clear(dev->params.ce_pin);
}
uint8_t val = BQ2429X_REG01_CHG_ENABLE << BQ2429X_REG01_CHG_s;
return _update_bits(dev, BQ2429X_REG01, BQ2429X_REG01_CHG_m, val);
}
int bq2429x_disable_charge(const bq2429x_t *dev)
{
assert(dev);
DEBUG_DEV("", dev);
if (!gpio_is_equal(dev->params.ce_pin, GPIO_UNDEF)) {
/* set CE pin to high to disable charge */
gpio_set(dev->params.ce_pin);
}
uint8_t val = BQ2429X_REG01_CHG_DISABLE << BQ2429X_REG01_CHG_s;
return _update_bits(dev, BQ2429X_REG01, BQ2429X_REG01_CHG_m, val);
}
int bq2429x_set_vlim(bq2429x_t *dev, bq2429x_input_voltage_limit_t vlim)
{
assert(dev);
DEBUG_DEV("vlim=%u", dev, (unsigned)vlim);
EXEC_RET(_update_bits(dev, BQ2429X_REG00, BQ2429X_REG00_VINDPM_m,
vlim << BQ2429X_REG00_VINDPM_s));
dev->params.vlim = vlim;
return BQ2429X_OK;
}
int bq2429x_get_vlim(const bq2429x_t *dev, bq2429x_input_voltage_limit_t *vlim)
{
assert(dev && vlim);
DEBUG_DEV("", dev);
uint8_t val;
EXEC_RET(_read_reg(dev, BQ2429X_REG00, &val));
*vlim = (val & BQ2429X_REG00_VINDPM_m) >> BQ2429X_REG00_VINDPM_s;
return BQ2429X_OK;
}
int bq2429x_set_ilim(bq2429x_t *dev, bq2429x_input_current_limit_t ilim)
{
assert(dev);
DEBUG_DEV("ilim=%u", dev, (unsigned)ilim);
EXEC_RET(_update_bits(dev, BQ2429X_REG00, BQ2429X_REG00_IINLIM_m,
ilim << BQ2429X_REG00_IINLIM_s));
dev->params.ilim = ilim;
return BQ2429X_OK;
}
int bq2429x_get_ilim(const bq2429x_t *dev, bq2429x_input_current_limit_t *ilim)
{
assert(dev && ilim);
DEBUG_DEV("", dev);
uint8_t val;
EXEC_RET(_read_reg(dev, BQ2429X_REG00, &val));
*ilim = (val & BQ2429X_REG00_IINLIM_m) >> BQ2429X_REG00_IINLIM_s;
return BQ2429X_OK;
}
int bq2429x_set_ichg(bq2429x_t *dev, bq2429x_charge_current_t ichg)
{
assert(dev);
DEBUG_DEV("ichg=%u", dev, (unsigned)ichg);
EXEC_RET(_update_bits(dev, BQ2429X_REG02, BQ2429X_REG02_ICHG_m,
ichg << BQ2429X_REG02_ICHG_s));
dev->params.ichg = ichg;
return BQ2429X_OK;
}
int bq2429x_get_ichg(const bq2429x_t *dev, bq2429x_charge_current_t *ichg)
{
assert(dev && ichg);
DEBUG_DEV("", dev);
uint8_t val;
EXEC_RET(_read_reg(dev, BQ2429X_REG02, &val));
*ichg = (val & BQ2429X_REG02_ICHG_m) >> BQ2429X_REG02_ICHG_s;
return BQ2429X_OK;
}
int bq2429x_set_vreg(bq2429x_t *dev, bq2429x_charge_voltage_limit_t vreg)
{
assert(dev);
DEBUG_DEV("vreg=%u", dev, (unsigned)vreg);
EXEC_RET(_update_bits(dev, BQ2429X_REG04, BQ2429X_REG04_VREG_m,
vreg << BQ2429X_REG04_VREG_s));
dev->params.vreg = vreg;
return BQ2429X_OK;
}
int bq2429x_get_vreg(const bq2429x_t *dev, bq2429x_charge_voltage_limit_t *vreg)
{
assert(dev && vreg);
DEBUG_DEV("", dev);
uint8_t val;
EXEC_RET(_read_reg(dev, BQ2429X_REG04, &val));
*vreg = (val & BQ2429X_REG04_VREG_m) >> BQ2429X_REG04_VREG_s;
return BQ2429X_OK;
}

View File

@ -0,0 +1,108 @@
/*
* Copyright (C) 2020 Locha Inc
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_bq2429x
*
* @{
* @file
* @brief Internal address, registers, constatns for the BQ2429x family
* power ICs.
*
* @author Jean Pierre Dudey <jeandudey@hotmail.com>
*/
#ifndef BQ2429X_INTERNAL_H
#define BQ2429X_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief BQ2429x I2C device slave address
*/
#define BQ2429X_I2C_ADDR (0x6B)
/**
* @brief Registers
* @{
*/
#define BQ2429X_REG00 (0x00) /**< Input Source Control */
#define BQ2429X_REG01 (0x01) /**< Power-On Configuration */
#define BQ2429X_REG02 (0x02) /**< Charge Current Control */
#define BQ2429X_REG04 (0x04) /**< Charge Voltage Control */
#define BQ2429X_REG05 (0x05) /**< Charge Termination/Timer
Control */
#define BQ2429X_REG08 (0x08) /**< System Status */
#define BQ2429X_REG09 (0x09) /**< New Fault Register */
#define BQ2429X_REG0A (0x0A) /**< Vendor / Part / Revision
Status */
/** @} */
/**
* @brief Register values
* @{
*/
#define BQ2429X_REG00_VINDPM_m (0x78)
#define BQ2429X_REG00_VINDPM_s (3)
#define BQ2429X_REG00_IINLIM_m (0x07)
#define BQ2429X_REG00_IINLIM_s (0)
#define BQ2429X_REG01_OTG_m (0x20)
#define BQ2429X_REG01_OTG_s (5)
#define BQ2429X_REG01_OTG_ENABLE (1)
#define BQ2429X_REG01_OTG_DISABLE (0)
#define BQ2429X_REG01_CHG_m (0x10)
#define BQ2429X_REG01_CHG_s (4)
#define BQ2429X_REG01_CHG_ENABLE (1)
#define BQ2429X_REG01_CHG_DISABLE (0)
#define BQ2429X_REG02_ICHG_m (0xFC)
#define BQ2429X_REG02_ICHG_s (2)
#define BQ2429X_REG04_VREG_m (0xFC)
#define BQ2429X_REG04_VREG_s (2)
#define BQ2429X_REG05_WD_m (0x30)
#define BQ2429X_REG05_WD_s (4)
#define BQ2429X_REG05_WD_DISABLE (0x00)
#define BQ2429X_REG08_VBUS_STATUS_m (0xC0)
#define BQ2429X_REG08_VBUS_STATUS_s (6)
#define BQ2429X_REG08_CHG_STAT_m (0x30)
#define BQ2429X_REG08_CHG_STAT_s (4)
#define BQ2429X_REG08_DPM_STAT_m (0x08)
#define BQ2429X_REG08_DPM_STAT_s (3)
#define BQ2429X_REG08_PG_STAT_m (0x04)
#define BQ2429X_REG08_PG_STAT_s (2)
#define BQ2429X_REG08_THERM_STAT_m (0x02)
#define BQ2429X_REG08_THERM_STAT_s (1)
#define BQ2429X_REG08_VSYS_STAT_m (0x01)
#define BQ2429X_REG08_VSYS_STAT_s (0)
#define BQ2429X_REG09_WD_FAULT_m (0x80)
#define BQ2429X_REG09_WD_FAULT_s (7)
#define BQ2429X_REG09_OTG_FAULT_m (0x40)
#define BQ2429X_REG09_OTG_FAULT_s (6)
#define BQ2429X_REG09_CHRG_FAULT_m (0x30)
#define BQ2429X_REG09_CHRG_FAULT_s (4)
#define BQ2429X_REG09_BAT_FAULT_m (0x08)
#define BQ2429X_REG09_BAT_FAULT_s (3)
#define BQ2429X_REG09_NTC_FAULT_1_m (0x02)
#define BQ2429X_REG09_NTC_FAULT_1_s (1)
#define BQ2429X_REG09_NTC_FAULT_0_m (0x01)
#define BQ2429X_REG09_NTC_FAULT_0_s (0)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* BQ2429X_INTERNAL_H */
/** @} */

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2020 Locha Inc
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_bq2429x
*
* @{
* @file
* @brief Default configuration for BQ2429x power ICs.
*
* @author Jean Pierre Dudey <jeandudey@hotmail.com>
*/
#ifndef BQ2429X_PARAMS_H
#define BQ2429X_PARAMS_H
#include "board.h"
#include "bq2429x.h"
#ifdef __cplusplus
extern "C" {
#endif
/* I2C configuration */
#ifndef BQ2429X_PARAM_I2C
#define BQ2429X_PARAM_I2C I2C_DEV(0)
#endif
/* Interrupt pin configuration */
#ifndef BQ2429X_PARAM_INT_PIN
#define BQ2429X_PARAM_INT_PIN GPIO_UNDEF
#endif
/* Control pins */
#ifndef BQ2429X_PARAM_CE_PIN
#define BQ2429X_PARMA_CE_PIN GPIO_UNDEF
#endif
#ifndef BQ2429X_PARAM_OTG_PIN
#define BQ2429X_PARMA_OTG_PIN GPIO_UNDEF
#endif
/* Input current/voltage */
#ifndef BQ2429X_PARAM_VLIM
#define BQ2429X_PARAM_VLIM BQ2429X_VLIM_4360
#endif
#ifndef BQ2429X_PARAM_ILIM
#define BQ2429X_PARAM_ILIM BQ2429X_ILIM_500
#endif
/* Battery charge current/voltage */
#ifndef BQ2429X_PARAM_ICHG
#define BQ2429X_PARAM_ICHG BQ2429X_ICHG_512
#endif
#ifndef BQ2429X_PARAM_VREG
#define BQ2429X_PARAM_VREG BQ2429X_VREG_4208
#endif
#if !IS_USED(MODULE_BQ2429X_INT)
#ifndef BQ2429X_PARAMS
#define BQ2429X_PARAMS { \
.i2c = BQ2429X_PARAM_I2C, \
.ce_pin = BQ2429X_PARMA_CE_PIN, \
.otg_pin = BQ2429X_PARMA_OTG_PIN, \
.vlim = BQ2429X_PARAM_VLIM, \
.ilim = BQ2429X_PARAM_ILIM, \
.ichg = BQ2429X_PARAM_ICHG, \
.vreg = BQ2429X_PARAM_VREG, \
}
#endif
#else /* !IS_USED(MODULE_BQ2429X_INT) */
#ifndef BQ2429X_PARAMS
#define BQ2429X_PARAMS { \
.i2c = BQ2429X_PARAM_I2C, \
.int_pin = BQ2429X_PARAM_INT_PIN, \
.ce_pin = BQ2429X_PARMA_CE_PIN, \
.otg_pin = BQ2429X_PARMA_OTG_PIN, \
.vlim = BQ2429X_PARAM_VLIM, \
.ilim = BQ2429X_PARAM_ILIM, \
.ichg = BQ2429X_PARAM_ICHG, \
.vreg = BQ2429X_PARAM_VREG, \
}
#endif
#endif /* !IS_USED(MODULE_BQ2429X_INT) */
static bq2429x_params_t bq2429x_params[] = {
BQ2429X_PARAMS,
};
#ifdef __cplusplus
}
#endif
#endif /* BQ2429X_PARAMS_H */
/** @} */

503
drivers/include/bq2429x.h Normal file
View File

@ -0,0 +1,503 @@
/*
* Copyright (C) 2020 Locha Inc
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_bq2429x BQ2429x
* @ingroup drivers_power
* @brief Device driver interface for the BQ2429x Single-Cell USB Charger
*
* BQ2429x series power management ICs by Texas Instruments are controllable by
* I2C, allowing to change charge parameters in the runtime.
*
* For more information, see the datasheets:
* * [BQ24295](https://www.ti.com/lit/ds/symlink/bq24295.pdf)
* * [BQ24296](https://www.ti.com/lit/ds/symlink/bq24296.pdf)
* * [BQ24297](https://www.ti.com/lit/ds/symlink/bq24297.pdf)
* * [BQ24298](https://www.ti.com/lit/ds/symlink/bq24298.pdf)
* * [BQ24292I](https://www.ti.com/lit/ds/symlink/bq24292i.pdf)
* * [BQ24296M](https://www.ti.com/lit/ds/symlink/bq24296m.pdf)
*
* It can be used for USB OTG to power other devices, see the
* @ref bq2429x_enable_otg and @ref bq2429x_disable_otg functions,
* an additional pin @ref bq2429x_params_t::otg_pin can be set to
* control it also by hardware and these functions will take care of
* setting it.
*
* To enable/disable charge the functions @ref bq2429x_enable_charge
* and @ref bq2429x_disable_charge can be used, and as with the OTG
* an additional pin @ref bq2429x_params_t::ce_pin can be set to
* control it also by hardware and these functions will take care of
* setting it.
*
* When a change happens on the FAULT registers of the device the
* BQ2429x device generates an interrupt to inform when that happens, this
* functionality has to be enabled with the `bq2429x_int` module and can be used
* with the @ref bq2429x_init_int functions.
*
* @{
*
* @file
* @brief Device driver interface for the BQ2429x Single-Cell USB Charger
*
* @author Jean Pierre Dudey <jeandudey@hotmail.com>
*/
#ifndef BQ2429X_H
#define BQ2429X_H
#include <stdint.h>
#include <stdbool.h>
#include "kernel_defines.h"
#include "periph/i2c.h"
#include "periph/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Driver return values
*/
enum {
BQ2429X_OK = 0, /**< Everything is ok */
BQ2429X_ERR_I2C = -1, /**< I2C error */
BQ2429X_ERR_GPIO = -2, /**< GPIO initialization error */
};
/**
* @brief Used VBUS type.
*/
typedef enum {
BQ2429X_VBUS_NONE = 0, /**< No input source detected */
BQ2429X_VBUS_USB_CHARGER, /**< USB charger input */
BQ2429X_VBUS_AP_CHARGER, /**< Adapter port charge input */
BQ2429X_VBUS_OTG, /**< VBUS is used for OTG */
} bq2429x_vbus_stat_t;
/**
* @brief Battery charging status
*/
typedef enum {
BQ2429X_CHARGE_NONE = 0, /**< The device is not charging a
battery */
BQ2429X_CHARGE_PRE, /**< Pre-charge state */
BQ2429X_CHARGE_FAST, /**< Fast charging */
BQ2429X_CHARGE_DONE, /**< Charging done */
} bq2429x_chrg_stat_t;
/**
* @brief Device status
*/
typedef struct {
bq2429x_vbus_stat_t vbus; /**< VBUS status */
bq2429x_chrg_stat_t chrg; /**< Charge status */
/**
* @brief DPM status
* @details false = Not in DPM.
* true = VINDPM or IINDMP.
*/
bool dpm;
/**
* @brief Power good status
* @details false = Not Power Good
* true = Power Good
*/
bool pg;
/**
* @brief Thermal regulation
* @details false = Normal
* true = In thermal regulation
*/
bool therm;
/**
* @brief VSYSMIN regulation
* @details false = Not in VSYSMIN regulation (BAT voltage > VSYSMIN)
* true = In VSYSMIN regulation (BAT voltage < VSYSMIN)
*/
bool vsys;
} bq2429x_status_t;
/**
* @brief Charge fault values
*/
typedef enum {
BQ2429x_CHRG_FAULT_NORMAL = 0, /**< No fault, normal */
BQ2429x_CHRG_FAULT_INPUT, /**< Input fault (OVP or bad
source) */
BQ2429x_CHRG_FAULT_THERMAL_SHUTDOWN, /**< Thermal shutdown */
BQ2429x_CHRG_FAULT_CHARGE_TIMER_EXPIRATION, /**< Charge timer expiration */
} bq2429x_chrg_fault_t;
/**
* @brief Device faults
*/
typedef struct {
/**
* @brief Watchdog fault.
* @details false = Normal.
* true = Watchdog timer expiration.
*/
bool watchdog;
/**
* @brief OTG fault.
* @details false = Normal.
* true = VBUS overloaded in OTG, or VBUS OVP, or battery is too
* low.
*/
bool otg;
/**
* @brief Charge fault.
*/
bq2429x_chrg_fault_t chrg;
/**
* @brief Battery fault.
*/
bool bat;
/**
* @brief NTC fault (1).
* @details false = Normal.
* true = Hot note.
*/
bool ntc_fault_1;
/**
* @brief NTC fault (0).
* @details false = Normal.
* true = Cold note.
*/
bool ntc_fault_0;
} bq2429x_fault_t;
/**
* @brief Input Voltage Limit (VLIM).
*/
typedef enum {
BQ2429X_VLIM_3880 = 0, /**< 3880 mV */
BQ2429X_VLIM_3960, /**< 3960 mV */
BQ2429X_VLIM_4040, /**< 4040 mV */
BQ2429X_VLIM_4120, /**< 4120 mV */
BQ2429X_VLIM_4200, /**< 4200 mV */
BQ2429X_VLIM_4280, /**< 4280 mV */
BQ2429X_VLIM_4360, /**< 4360 mV */
BQ2429X_VLIM_4440, /**< 4440 mV */
BQ2429X_VLIM_4520, /**< 4520 mV */
BQ2429X_VLIM_4600, /**< 4600 mV */
BQ2429X_VLIM_4680, /**< 4680 mV */
BQ2429X_VLIM_4760, /**< 4760 mV */
BQ2429X_VLIM_4840, /**< 4840 mV */
BQ2429X_VLIM_4920, /**< 4920 mV */
BQ2429X_VLIM_5000, /**< 5000 mV */
BQ2429X_VLIM_5080, /**< 5080 mV */
} bq2429x_input_voltage_limit_t;
/**
* @brief Input Current Limit (ILIM).
*/
typedef enum {
BQ2429X_ILIM_100 = 0, /**< 100 mA */
BQ2429X_ILIM_150, /**< 150 mA */
BQ2429X_ILIM_500, /**< 500 mA */
BQ2429X_ILIM_900, /**< 900 mA */
BQ2429X_ILIM_1000, /**< 1000 mA */
BQ2429X_ILIM_1500, /**< 1500 mA */
BQ2429X_ILIM_2000, /**< 2000 mA */
BQ2429X_ILIM_3000, /**< 3000 mA */
} bq2429x_input_current_limit_t;
/**
* @brief Charge Current (ICHG)
*/
typedef enum {
BQ2429X_ICHG_512 = 0, /**< 512 mA */
BQ2429X_ICHG_1024 = 8, /**< 1024 mA */
BQ2429X_ICHG_2048 = 24, /**< 2048 mA */
BQ2429X_ICHG_3008 = 39, /**< 4032 mA */
BQ2429X_ICHG_4032 = 55, /**< 4544 mA */
BQ2429X_ICHG_4544 = 63,
} bq2429x_charge_current_t;
/**
* @brief Charge Voltage Limit (VREG).
*/
typedef enum {
BQ2429X_VREG_3504 = 0, /**< 3504 mV */
BQ2429X_VREG_3600 = 6, /**< 3600 mV */
BQ2429X_VREG_3808 = 19, /**< 3808 mV */
BQ2429X_VREG_3904 = 25, /**< 3904 mV */
BQ2429X_VREG_4000 = 31, /**< 4000 mV */
BQ2429X_VREG_4112 = 38, /**< 4112 mV */
BQ2429X_VREG_4208 = 44, /**< 4208 mV */
BQ2429X_VREG_4304 = 50, /**< 4304 mV */
BQ2429X_VREG_4352 = 53, /**< 4352 mV */
BQ2429X_VREG_4400 = 56, /**< 4400 mV */
} bq2429x_charge_voltage_limit_t;
/**
* @brief BQ2429x device parameters
*/
typedef struct {
i2c_t i2c; /**< I2C device */
#if IS_USED(MODULE_BQ2429X_INT)
gpio_t int_pin; /**< Interrupt pin */
#endif
gpio_t ce_pin; /**< Charge Enable pin (optional) */
gpio_t otg_pin; /**< OTG Enable pin (optional) */
bq2429x_input_voltage_limit_t vlim; /**< Voltage limit */
bq2429x_input_current_limit_t ilim; /**< Current limit */
bq2429x_charge_current_t ichg; /**< Charge current limit */
bq2429x_charge_voltage_limit_t vreg; /**< Charge voltage limit */
} bq2429x_params_t;
/**
* @brief BQ2429x device descriptor
*/
typedef struct {
bq2429x_params_t params; /**< Device parameters */
} bq2429x_t;
/**
* @brief Initialize device
*
* @pre @p dev != NULL && @p params != NULL
*
* @param[out] dev Device descriptor.
* @param[in] params Device parameters.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
* @return BQ2429X_ERR_GPIO on GPIO initialization failure (CE or OTG pin
* failed).
*/
int bq2429x_init(bq2429x_t *dev, const bq2429x_params_t *params);
#if IS_USED(MODULE_BQ2429X_INT) || DOXYGEN
/**
* @brief Callback function for BQ2429x interrupts.
*/
typedef void (* bq2429x_int_cb_t)(void *);
/**
* @brief Initialize interrupt support for the device.
*
* @pre @p dev != NULL && @p cb != NULL
*
* The callback @p cb is called in an ISR context, so keep in mind that heavy
* work shouldn't be done there.
*
* @note @ref bq2429x_init MUST have been called before!
*
* @param[in] dev Device descriptor.
* @param[in] cb Callback called on interrupt.
* @param[in] arg Argument to be passed when the callback is called.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_GPIO on GPIO initialization failure.
*/
int bq2429x_init_int(bq2429x_t *dev, bq2429x_int_cb_t cb, void *arg);
#endif /* IS_USED(MODULE_BQ2429X_INT) || DOXYGEN */
/**
* @brief Get device status.
*
* @pre @p dev != NULL && @p status != NULL
*
* @param[in] dev Device descriptor.
* @param[out] status Pointer where device status will be stored.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C error.
*/
int bq2429x_get_status(const bq2429x_t *dev, bq2429x_status_t *status);
/**
* @brief Get device faults.
*
* @pre @p dev != NULL && @p fault != NULL
*
* @param[in] dev Device descriptor.
* @param[out] fault Pointer where device faults will be stored.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C error.
*/
int bq2429x_get_fault(const bq2429x_t *dev, bq2429x_fault_t *fault);
/**
* @brief Enable OTG.
*
* This allows powering USB devices from the same port, i.e. to provide power
* or charge other devices.
*
* @note This will disable charging of the battery, if previously
* @ref bq2429x_enable_charge was called, to enable charge
* again only disable OTG mode with @ref bq2429x_disable_otg.
*
* @pre @p dev != NULL
*
* @param[in] dev Device descriptor.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_enable_otg(const bq2429x_t *dev);
/**
* @brief Disable OTG.
*
* @pre @p dev != NULL
*
* @param[in] dev Device descriptor.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_disable_otg(const bq2429x_t *dev);
/**
* @brief Enable battery charging.
*
* @pre @p dev != NULL
*
* @param[in] dev Device descriptor.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_enable_charge(const bq2429x_t *dev);
/**
* @brief Disable battery charging.
*
* @pre @p dev != NULL
*
* @param[in] dev Device descriptor.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_disable_charge(const bq2429x_t *dev);
/**
* @brief Set Input Voltage Limit.
*
* @note This is a limit on the lower bound of the voltage, for example,
* if the VLIM is set to @ref BQ2429X_VLIM_5000 (5.0V) and the supply
* voltage is lower than it (4.8V), it will result in a fault and no
* power will be delivered through the output pin (SYS pin).
*
* @pre @p dev != NULL
*
* @param[in] dev Device descriptor.
* @param[in] vlim Voltage limit.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_set_vlim(bq2429x_t *dev, bq2429x_input_voltage_limit_t vlim);
/**
* @brief Get Input Voltage Limit.
*
* @pre @p dev != NULL && @p vlim != NULL
*
* @param[in] dev Device descriptor.
* @param[out] vlim Voltage limit.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_get_vlim(const bq2429x_t *dev, bq2429x_input_voltage_limit_t *vlim);
/**
* @brief Set Input Current Limit.
*
* Sets the maximum current limit, this limit is also limited by hardware by
* setting a resistor to the VLIM pin which sets (by hardware) the upper limit.
*
* @pre @p dev != NULL
*
* @param[in] dev Device descriptor.
* @param[in] ilim Current limit.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_set_ilim(bq2429x_t *dev, bq2429x_input_current_limit_t ilim);
/**
* @brief Get Input Current Limit.
*
* @pre @p dev != NULL && @p ilim != NULL
*
* @param[in] dev Device descriptor.
* @param[out] ilim Current limit.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_get_ilim(const bq2429x_t *dev, bq2429x_input_current_limit_t *ilim);
/**
* @brief Set Charge Current.
*
* @pre @p dev != NULL
*
* @param[in] dev Device descriptor.
* @param[in] ichg Charge current.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_set_ichg(bq2429x_t *dev, bq2429x_charge_current_t ichg);
/**
* @brief Get Charge Current.
*
* @pre @p dev != NULL && @p ichg != NULL
*
* @param[in] dev Device descriptor.
* @param[out] ichg Charge current.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_get_ichg(const bq2429x_t *dev, bq2429x_charge_current_t *ichg);
/**
* @brief Set Charge Voltage Limit.
*
* @pre @p dev != NULL
*
* @param[in] dev Device descriptor.
* @param[in] vreg Voltage limit.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_set_vreg(bq2429x_t *dev, bq2429x_charge_voltage_limit_t vreg);
/**
* @brief Get Charge Voltage Limit.
*
* @pre @p dev != NULL && @p vreg != NULL
*
* @param[in] dev Device descriptor.
* @param[out] vreg Voltage limit.
*
* @return BQ2429X_OK on success.
* @return BQ2429X_ERR_I2C on I2C failure.
*/
int bq2429x_get_vreg(const bq2429x_t *dev,
bq2429x_charge_voltage_limit_t *vreg);
#ifdef __cplusplus
}
#endif
#endif /* BQ2429X_H */
/** @} */

View File

@ -7,6 +7,7 @@ PSEUDOMODULES += at24c%
PSEUDOMODULES += atomic_utils
PSEUDOMODULES += base64url
PSEUDOMODULES += board_software_reset
PSEUDOMODULES += bq2429x_int
PSEUDOMODULES += can_mbox
PSEUDOMODULES += can_pm
PSEUDOMODULES += can_raw

View File

@ -0,0 +1,10 @@
include ../Makefile.tests_common
USEMODULE += bq2429x
USEMODULE += shell
USEMODULE += shell_commands
# The driver is not present on any BOARD on the ci
TEST_ON_CI_BLACKLIST = all
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,6 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p

View File

@ -0,0 +1,11 @@
# BQ2429x driver test application
This is the test application for the BQ2429x device driver, it provides various
commands to set and get the battery charge parameters and to check the device
status. Type `help` on the serial console to see available commands.
It can be flashed normally with:
```
make flash -C tests/driver/bq2429x BOARD=...
```

View File

@ -0,0 +1,212 @@
/*
* Copyright (C) 2020 Locha Inc
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @brief Util functions for test application for the BQ24298x device
* driver
* @author Jean Pierre Dudey <jeandudey@hotmail.com>
* @file
*/
#ifndef PRIV_UTIL_H
#define PRIV_UTIL_H
#include <assert.h>
#include "bq2429x.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline const char *_util_vlim_to_str(bq2429x_input_voltage_limit_t vlim)
{
switch (vlim) {
case BQ2429X_VLIM_3880:
return "3880 mV";
case BQ2429X_VLIM_3960:
return "3960 mV";
case BQ2429X_VLIM_4040:
return "4040 mV";
case BQ2429X_VLIM_4120:
return "4120 mV";
case BQ2429X_VLIM_4200:
return "4200 mV";
case BQ2429X_VLIM_4280:
return "4280 mV";
case BQ2429X_VLIM_4360:
return "4360 mV";
case BQ2429X_VLIM_4440:
return "4440 mV";
case BQ2429X_VLIM_4520:
return "4520 mV";
case BQ2429X_VLIM_4600:
return "4600 mV";
case BQ2429X_VLIM_4680:
return "4680 mV";
case BQ2429X_VLIM_4760:
return "4760 mV";
case BQ2429X_VLIM_4840:
return "4840 mV";
case BQ2429X_VLIM_4920:
return "4920 mV";
case BQ2429X_VLIM_5000:
return "5000 mV";
case BQ2429X_VLIM_5080:
return "5080 mV";
default:
assert(0);
break;
}
return "";
}
static inline const char *_util_ilim_to_str(bq2429x_input_current_limit_t vlim)
{
switch (vlim) {
case BQ2429X_ILIM_100:
return "100 mA";
case BQ2429X_ILIM_150:
return "150 mA";
case BQ2429X_ILIM_500:
return "500 mA";
case BQ2429X_ILIM_900:
return "900 mA";
case BQ2429X_ILIM_1000:
return "1000 mA";
case BQ2429X_ILIM_1500:
return "1500 mA";
case BQ2429X_ILIM_2000:
return "2000 mA";
case BQ2429X_ILIM_3000:
return "3000 mA";
default:
assert(0);
break;
}
return "";
}
static inline const char *_util_ichg_to_str(bq2429x_charge_current_t vlim)
{
switch (vlim) {
case BQ2429X_ICHG_512:
return "512 mA";
case BQ2429X_ICHG_1024:
return "1024 mA";
case BQ2429X_ICHG_2048:
return "2048 mA";
case BQ2429X_ICHG_3008:
return "3008 mA";
case BQ2429X_ICHG_4032:
return "4032 mA";
case BQ2429X_ICHG_4544:
return "4544 mA";
default:
assert(0);
break;
}
return "";
}
static inline const char *_util_vreg_to_str(bq2429x_charge_voltage_limit_t vreg)
{
switch (vreg) {
case BQ2429X_VREG_3504:
return "3504 mV";
case BQ2429X_VREG_3600:
return "3600 mV";
case BQ2429X_VREG_3808:
return "3808 mV";
case BQ2429X_VREG_3904:
return "3904 mV";
case BQ2429X_VREG_4000:
return "4000 mV";
case BQ2429X_VREG_4112:
return "4112 mV";
case BQ2429X_VREG_4208:
return "4208 mV";
case BQ2429X_VREG_4304:
return "4304 mV";
case BQ2429X_VREG_4352:
return "4352 mV";
case BQ2429X_VREG_4400:
return "4400 mV";
default:
assert(0);
break;
}
return "";
}
static inline const char *_util_vbus_stat_to_str(bq2429x_vbus_stat_t stat)
{
switch (stat) {
case BQ2429X_VBUS_NONE:
return "None";
case BQ2429X_VBUS_USB_CHARGER:
return "USB";
case BQ2429X_VBUS_AP_CHARGER:
return "Adapter Port";
case BQ2429X_VBUS_OTG:
return "OTG";
default:
assert(0);
break;
}
return "";
}
static inline const char *_util_chrg_stat_to_str(bq2429x_chrg_stat_t stat)
{
switch (stat) {
case BQ2429X_CHARGE_NONE:
return "None";
case BQ2429X_CHARGE_PRE:
return "Pre-charge";
case BQ2429X_CHARGE_FAST:
return "Fast Charging";
case BQ2429X_CHARGE_DONE:
return "Charge Done";
default:
assert(0);
break;
}
return "";
}
static inline const char *_util_chrg_fault_to_str(bq2429x_chrg_stat_t stat)
{
switch (stat) {
case BQ2429x_CHRG_FAULT_NORMAL:
return "Normal";
case BQ2429x_CHRG_FAULT_INPUT:
return "Input Fault (OVP or bad source)";
case BQ2429x_CHRG_FAULT_THERMAL_SHUTDOWN:
return "Thermal Shutdown";
case BQ2429x_CHRG_FAULT_CHARGE_TIMER_EXPIRATION:
return "Charge Timer Expiration";
default:
assert(0);
break;
}
return "";
}
#ifdef __cplusplus
}
#endif
#endif /* PRIV_UTIL_H */

View File

@ -0,0 +1,4 @@
CONFIG_MODULE_SHELL=y
CONFIG_MODULE_SHELL_COMMANDS=y
# include driver for bq2429x
CONFIG_MODULE_BQ2429X=y

404
tests/driver_bq2429x/main.c Normal file
View File

@ -0,0 +1,404 @@
/*
* Copyright (C) 2020 Locha Inc
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @brief Test application for the BQ24298x device driver
* @author Jean Pierre Dudey <jeandudey@hotmail.com>
* @file
*/
#include <stdio.h>
#include <stdlib.h>
#include "bq2429x_params.h"
#include "shell.h"
#include "_util.h"
static bq2429x_t _dev;
/* Status and faults */
static int _bq2429x_get_status_cmd(int argc, char **argv);
static int _bq2429x_get_fault_cmd(int argc, char **argv);
/* OTG */
static int _bq2429x_enable_otg_cmd(int argc, char **argv);
static int _bq2429x_disable_otg_cmd(int argc, char **argv);
/* Charge */
static int _bq2429x_enable_chg_cmd(int argc, char **argv);
static int _bq2429x_disable_chg_cmd(int argc, char **argv);
/* Set charge parameters */
static int _bq2429x_set_vlim_cmd(int argc, char **argv);
static int _bq2429x_set_ilim_cmd(int argc, char **argv);
static int _bq2429x_set_ichg_cmd(int argc, char **argv);
static int _bq2429x_set_vreg_cmd(int argc, char **argv);
/* Get charge parameters */
static int _bq2429x_get_vlim_cmd(int argc, char **argv);
static int _bq2429x_get_ilim_cmd(int argc, char **argv);
static int _bq2429x_get_ichg_cmd(int argc, char **argv);
static int _bq2429x_get_vreg_cmd(int argc, char **argv);
static const shell_command_t shell_commands[] = {
/* Status and faults */
{ "bq2429x_get_status", "Get device status", _bq2429x_get_status_cmd },
{ "bq2429x_get_fault", "Get device faults", _bq2429x_get_fault_cmd },
/* OTG */
{ "bq2429x_enable_otg", "Enable OTG mode", _bq2429x_enable_otg_cmd },
{ "bq2429x_disable_otg", "Disable OTG mode", _bq2429x_disable_otg_cmd },
/* Charge */
{ "bq2429x_enable_charge", "Enable battery charge",
_bq2429x_enable_chg_cmd },
{ "bq2429x_disable_charge", "Disable battery charge",
_bq2429x_disable_chg_cmd },
/* Set charge parameters */
{ "bq2429x_set_vlim", "Set input voltage limit (0=3880 mV .. 15=5080 mV)",
_bq2429x_set_vlim_cmd },
{ "bq2429x_set_ilim", "Set input current limit (0=100 mA .. 7=3000 mA)",
_bq2429x_set_ilim_cmd },
{ "bq2429x_set_ichg", "Set charge current (0=512 mA .. 5=4544 mA)",
_bq2429x_set_ichg_cmd },
{ "bq2429x_set_vreg", "Set charge voltage limit (0=3504 mV .. 9=4400 mV)",
_bq2429x_set_vreg_cmd },
/* Get charge parameters */
{ "bq2429x_get_vlim", "Get input voltage limit", _bq2429x_get_vlim_cmd },
{ "bq2429x_get_ilim", "Get input current limit", _bq2429x_get_ilim_cmd },
{ "bq2429x_get_ichg", "Get charge current", _bq2429x_get_ichg_cmd },
{ "bq2429x_get_vreg", "Get charge voltage limit", _bq2429x_get_vreg_cmd },
{ NULL, NULL, NULL }
};
int main(void)
{
puts("BQ2429x driver test application\n");
if (bq2429x_init(&_dev, &bq2429x_params[0]) != BQ2429X_OK) {
puts("[Failed]");
return 1;
}
puts("[OK]\n");
puts("All up, running the shell now.");
char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
/* should never be reached */
return 0;
}
static int _bq2429x_get_status_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
int ret;
bq2429x_status_t status;
if ((ret = bq2429x_get_status(&_dev, &status)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("Device status:\n");
printf("==============\n\n");
printf("VBUS: %s\n", _util_vbus_stat_to_str(status.vbus));
printf("Charge: %s\n", _util_chrg_stat_to_str(status.chrg));
printf("DPM: %s\n", status.dpm ? "VINDPM or IINDPM" : "Not in DPM");
printf("Power Good: %s\n", status.pg ? "Yes" : "No");
printf("Thermal Regulation: %s\n", status.therm ? "In thermal retulation"
: "Normal");
printf("In VSYSMIN Regulation (BAT < VSYSMIN): %s\n", status.vsys ? "Yes"
: "No");
return 0;
}
static int _bq2429x_get_fault_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
int ret;
bq2429x_fault_t fault;
if ((ret = bq2429x_get_fault(&_dev, &fault)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("Device faults:\n");
printf("==============\n\n");
printf("Watchdog: %s\n", fault.watchdog ? "Yes" : "No");
printf("OTG: %s\n", fault.otg ? "Yes" : "No");
printf("Charge: %s\n", _util_chrg_fault_to_str(fault.chrg));
printf("Battery: %s\n", fault.bat ? "Yes" : "No");
printf("NTC Fault 0: %s\n", fault.ntc_fault_0 ? "Yes" : "No");
printf("NTC Fault 1: %s\n", fault.ntc_fault_1 ? "Yes" : "No");
return 0;
}
static int _bq2429x_enable_otg_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
int ret;
if ((ret = bq2429x_enable_otg(&_dev))) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
puts("OTG enabled");
return 0;
}
static int _bq2429x_disable_otg_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
int ret;
if ((ret = bq2429x_disable_otg(&_dev))) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
puts("OTG disabled");
return 0;
}
static int _bq2429x_enable_chg_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
int ret;
if ((ret = bq2429x_enable_charge(&_dev))) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
puts("Battery charge enabled");
return 0;
}
static int _bq2429x_disable_chg_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
int ret;
if ((ret = bq2429x_disable_charge(&_dev))) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
puts("Battery charge disabled");
return 0;
}
static int _bq2429x_set_vlim_cmd(int argc, char **argv)
{
if (argc < 2 || argc > 2) {
printf("usage: %s [vlim]\n", argv[0]);
return 1;
}
int vlim = atoi(argv[1]);
if (vlim < 0) {
puts("error: only positive values allowed");
return 1;
}
if (vlim > BQ2429X_VLIM_5080) {
puts("error: maximum value is 5.08 V (15)");
return 1;
}
int ret;
if ((ret = bq2429x_set_vlim(&_dev, vlim)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("VLIM set to %s\n", _util_vlim_to_str(vlim));
return 0;
}
static int _bq2429x_set_ilim_cmd(int argc, char **argv)
{
if (argc < 2 || argc > 2) {
printf("usage: %s [ilim]\n", argv[0]);
return 1;
}
int ilim = atoi(argv[1]);
if (ilim < 0) {
puts("error: only positive values allowed");
return 1;
}
if (ilim > BQ2429X_ILIM_3000) {
puts("error: maximum value is 3.0 A (7)");
return 1;
}
int ret;
if ((ret = bq2429x_set_ilim(&_dev, ilim)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("ILIM set to %s\n", _util_ilim_to_str(ilim));
return 0;
}
static int _bq2429x_set_ichg_cmd(int argc, char **argv)
{
const bq2429x_charge_current_t ichg_lookup_table[] = {
BQ2429X_ICHG_512,
BQ2429X_ICHG_1024,
BQ2429X_ICHG_2048,
BQ2429X_ICHG_3008,
BQ2429X_ICHG_4032,
BQ2429X_ICHG_4544,
};
if (argc < 2 || argc > 2) {
printf("usage: %s [ichg]\n", argv[0]);
return 1;
}
int i = atoi(argv[1]);
if (i < 0) {
puts("error: only positive values allowed");
return 1;
}
if (i >= (int)ARRAY_SIZE(ichg_lookup_table)) {
int last = ARRAY_SIZE(ichg_lookup_table) - 1;
printf("error: maximum value is %s (%d)\n",
_util_ichg_to_str(ichg_lookup_table[last]), last);
return 1;
}
bq2429x_charge_current_t ichg = ichg_lookup_table[i];
int ret;
if ((ret = bq2429x_set_ichg(&_dev, ichg)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("ICHG set to %s\n", _util_ichg_to_str(ichg));
return 0;
}
static int _bq2429x_set_vreg_cmd(int argc, char **argv)
{
const bq2429x_charge_voltage_limit_t vreg_lookup_table[] = {
BQ2429X_VREG_3504,
BQ2429X_VREG_3600,
BQ2429X_VREG_3808,
BQ2429X_VREG_3904,
BQ2429X_VREG_4000,
BQ2429X_VREG_4112,
BQ2429X_VREG_4208,
BQ2429X_VREG_4304,
BQ2429X_VREG_4352,
BQ2429X_VREG_4400,
};
if (argc < 2 || argc > 2) {
printf("usage: %s [vreg]\n", argv[0]);
return 1;
}
int i = atoi(argv[1]);
if (i < 0) {
puts("error: only positive values allowed");
return 1;
}
if (i >= (int)ARRAY_SIZE(vreg_lookup_table)) {
int last = ARRAY_SIZE(vreg_lookup_table) - 1;
printf("error: maximum value is %s (%d)\n",
_util_vreg_to_str(vreg_lookup_table[last]), last);
return 1;
}
bq2429x_charge_voltage_limit_t vreg = vreg_lookup_table[i];
int ret;
if ((ret = bq2429x_set_vreg(&_dev, vreg)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("VREG set to %s\n", _util_vreg_to_str(vreg));
return 0;
}
static int _bq2429x_get_vlim_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
bq2429x_input_voltage_limit_t vlim;
int ret;
if ((ret = bq2429x_get_vlim(&_dev, &vlim)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("VLIM: %s\n", _util_vlim_to_str(vlim));
return 0;
}
static int _bq2429x_get_ilim_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
bq2429x_input_current_limit_t ilim;
int ret;
if ((ret = bq2429x_get_ilim(&_dev, &ilim)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("ILIM: %s\n", _util_ilim_to_str(ilim));
return 0;
}
static int _bq2429x_get_ichg_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
bq2429x_charge_current_t ichg;
int ret;
if ((ret = bq2429x_get_ichg(&_dev, &ichg)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("ICHG: %s\n", _util_ichg_to_str(ichg));
return 0;
}
static int _bq2429x_get_vreg_cmd(int argc, char **argv)
{
(void)argc;
(void)argv;
bq2429x_charge_voltage_limit_t vreg;
int ret;
if ((ret = bq2429x_get_vreg(&_dev, &vreg)) != BQ2429X_OK) {
printf("[Failed] ret=%d\n", ret);
return 1;
}
printf("VREG: %s\n", _util_vreg_to_str(vreg));
return 0;
}

View File

@ -0,0 +1,38 @@
#!/usr/bin/env python3
# Copyright (C) 2020 Locha Inc
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
import sys
from testrunner import run
def testfunc(child):
# VLIM
child.sendline("bq2429x_set_vlim 15")
child.expect(r"VLIM set to 5080 mV")
child.sendline("bq2429x_get_vlim")
child.expect(r"VLIM: 5080 mV")
# ILIM
child.sendline("bq2429x_set_ilim 2")
child.expect(r"ILIM set to 500 mA")
child.sendline("bq2429x_get_ilim")
child.expect(r"ILIM: 500 mA")
# ICHG
child.sendline("bq2429x_set_ichg 0")
child.expect(r"ICHG set to 512 mA")
child.sendline("bq2429x_get_ichg")
child.expect(r"ICHG: 512 mA")
# VREG
child.sendline("bq2429x_set_vreg 6")
child.expect(r"VREG set to 4208 mV")
child.sendline("bq2429x_get_vreg")
child.expect(r"VREG: 4208 mV")
if __name__ == "__main__":
sys.exit(run(testfunc, timeout=5, echo=True))