From cc1f7a63fa4180c3effb951f0b2f7d8df89e1fd3 Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Fri, 25 Aug 2017 07:26:00 -0600 Subject: [PATCH] power: add driver for TI bq2429x battery charger. TODO: Untested. Does not have poll() support. --- drivers/power/Kconfig | 23 + drivers/power/Make.defs | 6 + drivers/power/battery_charger.c | 14 +- drivers/power/bq2425x.c | 17 +- drivers/power/bq2429x.c | 1262 +++++++++++++++++++++++++ include/nuttx/power/battery_charger.h | 60 +- include/nuttx/power/battery_ioctl.h | 32 +- include/nuttx/power/bq2429x.h | 244 +++++ 8 files changed, 1652 insertions(+), 6 deletions(-) create mode 100644 drivers/power/bq2429x.c create mode 100644 include/nuttx/power/bq2429x.h diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index ca02bd12d2..8d9bb1be89 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -292,6 +292,25 @@ config BQ2425X ---help--- The BQ24250/BQ24251 are battery charger for lithium-ion batteries. +config BQ2429X + bool "BQ2429X Battery charger support" + default n + select I2C + select I2C_BQ2429X + depends on BATTERY_CHARGER + ---help--- + The BQ24296/BQ24297/BQ24296M are battery charger for lithium-ion batteries. + +if BQ2429X + +config DEBUG_BQ2429X + bool "BQ2429X Debug Features" + default n + ---help--- + Enable BQ2429X battery management debug features. + +endif # BQ2429X + config BATTERY_GAUGE bool "Battery Fuel Gauge support" default n @@ -312,6 +331,10 @@ config I2C_BQ2425X bool default y if BQ2425X +config I2C_BQ2429X + bool + default y if BQ2429X + config I2C_MAX1704X bool default y if MAX1704X diff --git a/drivers/power/Make.defs b/drivers/power/Make.defs index d566bdf533..8fb6a638a0 100644 --- a/drivers/power/Make.defs +++ b/drivers/power/Make.defs @@ -80,6 +80,12 @@ ifeq ($(CONFIG_I2C_BQ2425X),y) CSRCS += bq2425x.c endif +# Add the BQ2429x I2C-based battery charger driver + +ifeq ($(CONFIG_I2C_BQ2429X),y) +CSRCS += bq2429x.c +endif + endif # Include power support in the build diff --git a/drivers/power/battery_charger.c b/drivers/power/battery_charger.c index 4b489799f8..811254e190 100644 --- a/drivers/power/battery_charger.c +++ b/drivers/power/battery_charger.c @@ -160,7 +160,7 @@ static int bat_charger_ioctl(FAR struct file *filep, int cmd, FAR struct battery_charger_dev_s *dev = inode->i_private; int ret; - /* Inforce mutually exclusive access to the battery driver */ + /* Enforce mutually exclusive access to the battery driver */ ret = sem_wait(&dev->batsem); if (ret < 0) @@ -168,7 +168,7 @@ static int bat_charger_ioctl(FAR struct file *filep, int cmd, return -errno; /* Probably EINTR */ } - /* Procss the IOCTL command */ + /* Process the IOCTL command */ ret = -EINVAL; /* Assume a bad argument */ switch (cmd) @@ -239,6 +239,16 @@ static int bat_charger_ioctl(FAR struct file *filep, int cmd, } break; + case BATIOC_OPERATE: + { + FAR int *ptr = (FAR int *)((uintptr_t)arg); + if (ptr) + { + ret = dev->ops->operate(dev, (uintptr_t)arg); + } + } + break; + default: _err("ERROR: Unrecognized cmd: %d\n", cmd); ret = -ENOTTY; diff --git a/drivers/power/bq2425x.c b/drivers/power/bq2425x.c index 039baf01a3..7e6e7dbd72 100644 --- a/drivers/power/bq2425x.c +++ b/drivers/power/bq2425x.c @@ -134,6 +134,7 @@ static int bq2425x_online(struct battery_charger_dev_s *dev, bool *status); static int bq2425x_voltage(struct battery_charger_dev_s *dev, int value); static int bq2425x_current(struct battery_charger_dev_s *dev, int value); static int bq2425x_input_current(struct battery_charger_dev_s *dev, int value); +static int bq2425x_operate(struct battery_charger_dev_s *dev, uintptr_t param); /**************************************************************************** * Private Data @@ -146,7 +147,8 @@ static const struct battery_charger_operations_s g_bq2425xops = bq2425x_online, bq2425x_voltage, bq2425x_current, - bq2425x_input_current + bq2425x_input_current, + bq2425x_operate }; /**************************************************************************** @@ -728,6 +730,19 @@ static int bq2425x_input_current(struct battery_charger_dev_s *dev, int value) return OK; } +/**************************************************************************** + * Name: bq2425x_operate + * + * Description: + * Do miscellaneous battery ioctl() + * + ****************************************************************************/ + +static int bq2425x_operate(struct battery_charger_dev_s *dev, uintptr_t param) +{ + return -ENOSYS; +} + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/drivers/power/bq2429x.c b/drivers/power/bq2429x.c new file mode 100644 index 0000000000..675a6eccd7 --- /dev/null +++ b/drivers/power/bq2429x.c @@ -0,0 +1,1262 @@ +/**************************************************************************** + * drivers/power/bq2429x.c + * Lower half driver for BQ2429x battery charger + * + * Copyright (C) 2017 Neil Hancock. All rights reserved. + * + * Copyright (C) 2017 Haltian Ltd. All rights reserved. + * Author: Juha Niskanen + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* The BQ24296M/BQ24296 are Li-Ion Battery management + * with Power-Path Management + * and USB OTG +5V boost. + * + * BQ charger with OTG boost and not DSBGA listed below + * BQ24190/24192 compared as similar + * BQ24259 + * BQ24295 + * BQ24195 Boost2A/PMID Chg4A5 SolarPwr + * BQ24195L Boost1A/PMID Chg2A5 SolarPwr + * BQ24296 + * BQ24296M Achg=0.1-3A, Vout=4.55 to 5.0V Current Limit 1.5A + * BQ24297 + * BQ24298 + * BQ25601 I2C - to 13.5 Vin + * BQ25606 No I2C control + * BQ25890H + * BQ25892 + * BQ25895 + * BQ25896 I2C 14V + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* This driver requires: + * + * CONFIG_BATTERY_CHARGER - Upper half battery driver support + * CONFIG_I2C - I2C support + * CONFIG_I2C_BQ2429X - And the driver must be explictly selected. + */ + +#if defined(CONFIG_BATTERY_CHARGER) && defined(CONFIG_I2C) && \ + defined(CONFIG_I2C_BQ2429X) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Debug ********************************************************************/ + +#ifdef CONFIG_DEBUG_BQ2429X +# define baterr _err +# define batdbg _info +# define batinfo _info +#else +# ifdef CONFIG_CPP_HAVE_VARARGS +# define baterr(x...) +# define batdbg(x...) +# define batinfo(x...) +# else +# define baterr (void) +# define batdbg (void) +# define batinfo(void) +# endif +#endif + +/**************************************************************************** + * Private + ****************************************************************************/ + +struct bq2429x_dev_s +{ + /* The common part of the battery driver visible to the upper-half driver */ + + FAR const struct battery_charger_operations_s *ops; /* Battery operations */ + sem_t batsem; /* Enforce mutually exclusive access */ + + /* Data fields specific to the lower half BQ2429X driver follow */ + + FAR struct i2c_master_s *i2c; /* I2C interface */ + uint8_t addr; /* I2C address */ + uint32_t frequency; /* I2C frequency */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* I2C support */ + +static int bq2429x_getreg8(FAR struct bq2429x_dev_s *priv, uint8_t regaddr, + FAR uint8_t *val, int num); +static int bq2429x_putreg8(FAR struct bq2429x_dev_s *priv, uint8_t regaddr, + uint8_t regval); + +static int bq2429x_reset(FAR struct bq2429x_dev_s *priv); +static int bq2429x_watchdog(FAR struct bq2429x_dev_s *priv, bool enable); +static int bq2429x_sysoff(FAR struct bq2429x_dev_s *priv); +static int bq2429x_en_term(FAR struct bq2429x_dev_s *priv, bool state); +static int bq2429x_en_hiz(FAR struct bq2429x_dev_s *priv, bool state); +static int bq2429x_en_stat(FAR struct bq2429x_dev_s *priv, bool state); +static int bq2429x_setboost_otg_config(FAR struct bq2429x_dev_s *priv, + bool state); +static int bq2429x_powersupply(FAR struct bq2429x_dev_s *priv, int current); +static inline int bq2429x_setvolt(FAR struct bq2429x_dev_s *priv, + int volts); +static inline int bq2429x_setcurr(FAR struct bq2429x_dev_s *priv, + int req_current); + +/* Battery driver lower half methods */ + +static int bq2429x_state(FAR struct battery_charger_dev_s *dev, + FAR int *status); +static int bq2429x_health(FAR struct battery_charger_dev_s *dev, + FAR int *health); +static int bq2429x_online(FAR struct battery_charger_dev_s *dev, + FAR bool *status); +static int bq2429x_voltage(FAR struct battery_charger_dev_s *dev, + int value); +static int bq2429x_current(FAR struct battery_charger_dev_s *dev, + int value); +static int bq2429x_input_current(FAR struct battery_charger_dev_s *dev, + int value); +static int bq2429x_operate(FAR struct battery_charger_dev_s *dev, + uintptr_t param); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct battery_charger_operations_s g_bq2429xops = +{ + bq2429x_state, + bq2429x_health, + bq2429x_online, + bq2429x_voltage, + bq2429x_current, + bq2429x_input_current, + bq2429x_operate, +}; + +#ifdef CONFIG_DEBUG_BQ2429X +static int bq2429x_dump_regs(FAR struct bq2429x_dev_s *priv); +# define bq2429x_dump_regs(priv) bq2429x_dump_regs(priv) +#else +# define bq2429x_dump_regs(priv) +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bq2429x_getreg8 + * + * Description: + * Read a 8-bit value from a BQ2429x register pair. + * + * START ACK ACK + * REPEATED-START ACK Data0 ACK Data1 NO-ACK STOP + * + ****************************************************************************/ + +static int bq2429x_getreg8(FAR struct bq2429x_dev_s *priv, uint8_t regaddr, + FAR uint8_t *regval, int num_char) +{ + struct i2c_config_s config; + int ret; + + /* Set up the I2C configuration */ + + config.frequency = priv->frequency; + config.address = priv->addr; + config.addrlen = 7; + + /* Write the register address */ + + ret = i2c_write(priv->i2c, &config, ®addr, 1); + if (ret < 0) + { + baterr("ERROR: i2c_write failed: %d\n", ret); + return ret; + } + + /* Restart and read 8-bit values from the register */ + + ret = i2c_read(priv->i2c, &config, regval, num_char); + if (ret < 0) + { + baterr("ERROR: i2c_read failed: %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_putreg8 + * + * Description: + * Write a 8-bit value to a BQ2429x register pair. + * + * START ACK ACK Data0 ACK Data1 ACK STOP + * + ****************************************************************************/ + +static int bq2429x_putreg8(FAR struct bq2429x_dev_s *priv, uint8_t regaddr, + uint8_t regval) +{ + struct i2c_config_s config; + uint8_t buffer[2]; + + /* Set up the I2C configuration */ + + config.frequency = priv->frequency; + config.address = priv->addr; + config.addrlen = 7; + + batdbg("addr: %02x regval: %08x\n", regaddr, regval); + + /* Set up a message to send */ + + buffer[0] = regaddr; + buffer[1] = regval; + + /* Write the register address followed by the data (no RESTART) */ + + return i2c_write(priv->i2c, &config, buffer, 2); +} + +#ifdef CONFIG_DEBUG_BQ2429X +static int (bq2429x_dump_regs) (FAR struct bq2429x_dev_s * priv) +{ + int ret; + uint8_t value = 0; + + ret = bq2429x_getreg8(priv, BQ2429X_REG00, &value, 1); + batdbg("REG#0: 0x%08X\n", value); + ret |= bq2429x_getreg8(priv, BQ2429X_REG01, &value, 1); + batdbg("REG#1: 0x%08X\n", value); + ret |= bq2429x_getreg8(priv, BQ2429X_REG02, &value, 1); + batdbg("REG#2: 0x%08X\n", value); + ret |= bq2429x_getreg8(priv, BQ2429X_REG03, &value, 1); + batdbg("REG#3: 0x%08X\n", value); + ret |= bq2429x_getreg8(priv, BQ2429X_REG04, &value, 1); + batdbg("REG#4: 0x%08X\n", value); + ret |= bq2429x_getreg8(priv, BQ2429X_REG05, &value, 1); + batdbg("REG#5: 0x%08X\n", value); + ret |= bq2429x_getreg8(priv, BQ2429X_REG06, &value, 1); + batdbg("REG#6: 0x%08X\n", value); + ret |= bq2429x_getreg8(priv, BQ2429X_REG07, &value, 1); + batdbg("REG#7: 0x%08X\n", value); + ret |= bq2429x_getreg8(priv, BQ2429X_REG08, &value, 1); + batdbg("REG#8: 0x%08X\n", value); + + /* Not reading fault register. */ + + ret |= bq2429x_getreg8(priv, BQ2429X_REG0A, &value, 1); + batdbg("REG#10: 0x%08X\n", value); + + return ret; +} +#endif + +/**************************************************************************** + * Name: bq2429x_reset + * + * Description: + * Reset the BQ2429x + * + ****************************************************************************/ + +static int bq2429x_reset(FAR struct bq2429x_dev_s *priv) +{ + int ret; + uint8_t regval; + + /* Read current register value */ + + ret = bq2429x_getreg8(priv, BQ2429X_REG01, ®val, 1); + if (ret < 0) + { + baterr("ERROR: Error reading from BQ2429X! Error = %d\n", ret); + return ret; + } + + /* Send reset command */ + + regval |= BQ2429XR1_REG_RESET; + ret = bq2429x_putreg8(priv, BQ2429X_REG01, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429X! Error = %d\n", ret); + return ret; + } + + /* Wait a little bit to clear registers */ + + usleep(500); + +#if 0 + /* There is a BUG in BQ2429X the RESET bit is always read as 1 */ + + regval &= ~(BQ2429X_RESET); + ret = bq2429x_putreg8(priv, BQ2429X_REG01, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429X! Error = %d\n", ret); + return ret; + } +#endif + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_watchdog + * + * Description: + * Enable/Disable the BQ2429x watchdog + * + ****************************************************************************/ + +static int bq2429x_watchdog(FAR struct bq2429x_dev_s *priv, bool enable) +{ + int ret; + uint8_t regval; + + ret = bq2429x_getreg8(priv, BQ2429X_REG05, ®val, 1); + if (ret < 0) + { + baterr("ERROR: Error reading from BQ2429X! Error = %d\n", ret); + return ret; + } + + if (enable) + { + /* Hw Default is 40Sec so use that for time being */ + + regval &= ~(BQ2429XR5_WATCHDOG_MASK); + regval |= BQ2429XR5_WATCHDOG_040Sec; + } + else + { + /* 0 is disable */ + + regval &= ~(BQ2429XR5_WATCHDOG_MASK); + } + + ret = bq2429x_putreg8(priv, BQ2429X_REG05, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429X! Error = %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_sysoff + * + * Description: + * Turn the internal battery FET off in order to reduce the leakage from + * the BAT pin. Note that this disconnects the battery from the system. + * + ****************************************************************************/ + +static int bq2429x_sysoff(FAR struct bq2429x_dev_s *priv) +{ + int ret; + uint8_t value = 0; + + ret = bq2429x_getreg8(priv, BQ2429X_REG07, &value, 1); + batdbg("REG7 read value: 0x%08X\n", value); + value |= BQ2429XR7_BATFET_DISABLE; + ret |= bq2429x_putreg8(priv, BQ2429X_REG07, value); + + return ret; +} + +/**************************************************************************** + * Name: bq2429x_en_term + * + * Description: + * Enable charger termination. When termination is disabled, there are no + * indications of the charger terminating (i.e. STAT pin or STAT registers). + * + ****************************************************************************/ + +static int bq2429x_en_term(FAR struct bq2429x_dev_s *priv, bool state) +{ + uint8_t regval; + int ret; + + ret = bq2429x_getreg8(priv, BQ2429X_REG05, ®val, 1); + if (ret < 0) + { + baterr("ERROR: Error reading from BQ2429X REG5! Error = %d\n", ret); + return ret; + } + + batdbg("en_term: REG05 %02X EN_TERM=%d\n", + regval, !!(regval & BQ2429XR5_EN_TERM)); + + /* Clear previous and set new value */ + + if (state) + { + regval |= BQ2429XR5_EN_TERM; + } + else + { + regval &= ~BQ2429XR5_EN_TERM; + } + + ret = bq2429x_putreg8(priv, BQ2429X_REG05, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429XR5! Error = %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_en_hiz + * + * Description: + * Enable high-impedance mode. Sets the charger IC into low power standby mode. + * + ****************************************************************************/ + +static int bq2429x_en_hiz(FAR struct bq2429x_dev_s *priv, bool state) +{ + uint8_t regval; + int ret; + + ret = bq2429x_getreg8(priv, BQ2429X_REG00, ®val, 1); + if (ret < 0) + { + baterr("ERROR: Error reading from BQ2429X REG0! Error = %d\n", ret); + return ret; + } + + batdbg("en_hiz: REG00 %02X EN_HIZ=%d\n", + regval, !!(regval & BQ2429XR1_EN_HIZ)); + + /* Clear previous and set new value */ + + if (state) + { + regval |= BQ2429XR1_EN_HIZ; + } + else + { + regval &= ~BQ2429XR1_EN_HIZ; + } + + ret = bq2429x_putreg8(priv, BQ2429X_REG00, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429XR0! Error = %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_en_stat + * + * Description: + * Enable interrupts. + * + ****************************************************************************/ + +static int bq2429x_en_stat(FAR struct bq2429x_dev_s *priv, bool state) +{ + uint8_t regval; + int ret; + + ret = bq2429x_getreg8(priv, BQ2429X_REG07, ®val, 1); + if (ret < 0) + { + baterr("ERROR: Error reading from BQ2429X REG7! Error = %d\n", ret); + return ret; + } + + batdbg("int stat: REG07 %02X INT_MASK1=%d INT_MASK0=%d\n", regval, + !!(regval & BQ2429XR7_INT_MASK1), !!(regval & BQ2429XR7_INT_MASK0)); + + /* We always set or clear both interrupts together. */ + + if (state) + { + regval |= (BQ2429XR7_INT_MASK0 | BQ2429XR7_INT_MASK1); + } + else + { + regval &= ~(BQ2429XR7_INT_MASK0 | BQ2429XR7_INT_MASK1); + } + + ret = bq2429x_putreg8(priv, BQ2429X_REG07, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429XR7! Error = %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_setboost_otg_config + * + * Description: + * Set the device boost mode. + * + ****************************************************************************/ + +static int bq2429x_setboost_otg_config(FAR struct bq2429x_dev_s *priv, + bool state) +{ + uint8_t regval; + int ret; + + ret = bq2429x_getreg8(priv, BQ2429X_REG01, ®val, 1); + if (ret < 0) + { + baterr("ERROR: Error reading from BQ2429X! Error = %d\n", ret); + return ret; + } + + /* Clear previous current and set new value */ + + if (state) + { + /* Set to Boost disable Charge */ + + regval = BQ2429XR1_OTG_CONFIG | (regval & ~BQ2429XR1_CHG_CONFIG); + } + else + { + /* Set to Charge disable Boost */ + + regval = BQ2429XR1_CHG_CONFIG | (regval & ~BQ2429XR1_OTG_CONFIG); + } + + ret = bq2429x_putreg8(priv, BQ2429X_REG01, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429X! Error = %d\n", ret); + return ret; + } + +#define BST_CONFIG_MASK (BQ2429XR1_CHG_CONFIG | BQ2429XR1_OTG_CONFIG) + batdbg("otg_config: REG01 %02X Boost=%d\n", regval, + ((BQ2429XR1_OTG_CONFIG == (regval & BST_CONFIG_MASK)) ? 1 : 0)); + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_state + * + * Description: + * Return the current battery management state + * + ****************************************************************************/ + +static int bq2429x_state(FAR struct battery_charger_dev_s *dev, + FAR int *status) +{ + FAR struct bq2429x_dev_s *priv = (FAR struct bq2429x_dev_s *)dev; + uint8_t regval; + bool isfault = false; + int ret; + + ret = bq2429x_getreg8(priv, BQ2429X_REG08, ®val, 1); + if (ret < 0) + { + *status = BATTERY_UNKNOWN; + return ret; + } + + if (regval & BQ2429XR8_DPM_STAT) + { + isfault = true; + batinfo("DPM detected!\n"); + } + + if (!(regval & BQ2429XR8_PG_STAT)) + { + isfault = true; + batinfo("Power is not good!\n"); + } + + if (regval & BQ2429XR8_THERM_STAT) + { + isfault = true; + batinfo("Thermal regulation!\n"); + } + + if (regval & BQ2429XR8_VSYS_STAT) + { + isfault = true; + batinfo("VSYSMIN regulation! Battery is too low!\n"); + } + + regval &= BQ2429XR8_CHRG_STAT_MASK; + + /* TODO: should we check REG09 faults here as well? */ + + if (isfault) + { + *status = BATTERY_FAULT; + } + + /* Is the charging done? */ + + else if (regval == BQ2429XR8_CHRG_STAT_DONE) + { + *status = BATTERY_FULL; + } + + /* Is the charging in progress? */ + + else if (regval == BQ2429XR8_CHRG_STAT_PRECHG || + regval == BQ2429XR8_CHRG_STAT_FASTCHG) + { + *status = BATTERY_CHARGING; + } + + /* Is the charging ready? */ + + else if (regval == BQ2429XR8_CHRG_STAT_NONE) + { + *status = BATTERY_IDLE; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_health + * + * Description: + * Return the current battery health state + * + * Note: if more than one fault happened the user needs to call this ioctl + * again to read a new fault, repeat until receive a BATTERY_HEALTH_GOOD. + * + ****************************************************************************/ + +static int bq2429x_health(FAR struct battery_charger_dev_s *dev, + FAR int *health) +{ + FAR struct bq2429x_dev_s *priv = (FAR struct bq2429x_dev_s *)dev; + uint8_t regval; + int ret; + + ret = bq2429x_getreg8(priv, BQ2429X_REG09, ®val, 1); + if (ret < 0) + { + *health = BATTERY_HEALTH_UNKNOWN; + return ret; + } + + switch (regval & BQ2429XR9_CHRG_FAULT_MASK) + { + case BQ2429XR9_CHRG_FAULT_TIMER: + *health = BATTERY_HEALTH_SAFE_TMR_EXP; + batinfo("battery safety timer expiration!\n"); + return OK; + + case BQ2429XR9_CHRG_FAULT_INPUT: + *health = BATTERY_HEALTH_DISCONNECTED; + batinfo("input disconnect/fault!\n"); + return OK; + + case BQ2429XR9_CHRG_FAULT_THERMAL: + *health = BATTERY_HEALTH_OVERHEAT; + batinfo("thermal shutdown!\n"); + return OK; + + case BQ2429XR9_CHRG_FAULT_NORMAL: + *health = BATTERY_HEALTH_GOOD; + break; /* No return, check for other faults */ + + default: + DEBUGASSERT(false); + *health = BATTERY_HEALTH_UNKNOWN; + return OK; + } + + if (regval & BQ2429XR9_BAT_FAULT) + { + *health = BATTERY_HEALTH_OVERVOLTAGE; + batinfo("battery OVP!\n"); + } + else if (regval & BQ2429XR9_NTC_FAULT2_HOT) + { + *health = BATTERY_HEALTH_OVERHEAT; + batinfo("NTC hot!\n"); + } + else if (regval & BQ2429XR9_NTC_FAULT1_COLD) + { + *health = BATTERY_HEALTH_COLD; + batinfo("NTC cold!\n"); + } + else if (regval & BQ2429XR9_WATCHDOG_FAULT) + { + *health = BATTERY_HEALTH_WD_TMR_EXP; + batinfo("watchdog expiration!\n"); + } + else if (regval & BQ2429XR9_OTG_FAULT) + { + *health = BATTERY_HEALTH_UNSPEC_FAIL; + batinfo("VBUS overload or OVP!\n"); + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_online + * + * Description: + * Return true if the battery is online + * + ****************************************************************************/ + +static int bq2429x_online(FAR struct battery_charger_dev_s *dev, + FAR bool *status) +{ + FAR struct bq2429x_dev_s *priv = (FAR struct bq2429x_dev_s *)dev; + uint8_t regval; + int ret; + + ret = bq2429x_getreg8(priv, BQ2429X_REG00, ®val, 1); + if (ret < 0) + { + *status = false; + return ret; + } + + if (regval & BQ2429XR1_EN_HIZ) + { + /* Device is HIGH IMPEDANCE battery offline */ + + *status = false; + } + else + { + *status = true; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_powersupply + * + * Description: + * Set the Power Supply Current Limit. + * + ****************************************************************************/ + +static int bq2429x_powersupply(FAR struct bq2429x_dev_s *priv, int current) +{ + uint8_t regval, idx; + int ret; + + switch (current) + { + case 100: + idx = BQ2429XR0_INLIM_0100mA; + break; + + case 150: + idx = BQ2429XR0_INLIM_0150mA; + break; + + case 500: + idx = BQ2429XR0_INLIM_0500mA; + break; + + case 900: + idx = BQ2429XR0_INLIM_0900mA; + break; + + case 1000: + idx = BQ2429XR0_INLIM_1000mA; + break; + + case 1500: + idx = BQ2429XR0_INLIM_1500mA; + break; + + case 2000: + idx = BQ2429XR0_INLIM_2000mA; + break; + + case 3000: + idx = BQ2429XR0_INLIM_3000mA; + break; + + default: + baterr("ERROR: Current not supported, setting default to 100mA.!\n"); + idx = BQ2429XR0_INLIM_0100mA; + break; + } + + /* Read current register */ + + ret = bq2429x_getreg8(priv, BQ2429X_REG00, ®val, 1); + if (ret < 0) + { + baterr("ERROR: Error reading from BQ2429X! Error = %d\n", ret); + return ret; + } + + /* Clear previous current and set new value */ + + regval &= ~(BQ2429XR0_INLIM_MASK); + regval |= idx; + + ret = bq2429x_putreg8(priv, BQ2429X_REG00, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429X! Error = %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_setvolt + * + * Description: + * Set the voltage level to charge the battery. Voltage value in mV. + * + ****************************************************************************/ + +static inline int bq2429x_setvolt(FAR struct bq2429x_dev_s *priv, int req_volts) +{ + uint8_t regval; + int ret, idx; + + /* Verify if voltage is in the acceptable range */ + + if (req_volts < BQ2429X_VOLTCHG_MIN || req_volts > BQ2429X_VOLTCHG_MAX) + { + baterr("ERROR: Voltage %d mV is out of range.\n", req_volts); + return -EINVAL; + } + + ret = bq2429x_getreg8(priv, BQ2429X_REG04, ®val, 1); + if (ret < 0) + { + baterr("ERROR: Error reading from BQ2429X! Error = %d\n", ret); + return ret; + } + + /* Charge Voltage starts at _MIN and increases in steps of 16mV */ + + idx = req_volts - BQ2429X_VOLTCHG_MIN; + idx = idx / 16; + + /* Clear previous voltage */ + + regval &= ~(BQ2429XR4_VREG_MASK); + regval |= (idx << BQ2429XR4_VREG_SHIFT); + + ret = bq2429x_putreg8(priv, BQ2429X_REG04, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429X! Error = %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_setcurr + * + * Description: + * Set the current to charge the battery. Current value in mA. + * + ****************************************************************************/ + +static inline int bq2429x_setcurr(FAR struct bq2429x_dev_s *priv, + int req_current) +{ + uint8_t regval; + int ret, idx; + + /* Verify if voltage is in the acceptable range */ + + if (req_current < BQ2429X_CURRCHG_MIN || req_current > BQ2429X_CURRCHG_MAX) + { + baterr("ERROR: Current %d mA is out of range.\n", req_current); + return -EINVAL; + } + + ret = bq2429x_getreg8(priv, BQ2429X_REG02, ®val, 1); + if (ret < 0) + { + baterr("ERROR: Error reading from BQ2429X! Error = %d\n", ret); + return ret; + } + + /* Current starts at _MIN mV and increases in steps of 64mA */ + + idx = req_current - BQ2429X_CURRCHG_MIN; + idx = idx / 64; + + /* Clear previous current and set new value */ + + regval &= ~(BQ2429XR2_ICHG_MASK); + regval |= (idx << BQ2429XR2_ICHG_SHIFT); + + ret = bq2429x_putreg8(priv, BQ2429X_REG02, regval); + if (ret < 0) + { + baterr("ERROR: Error writing to BQ2429X! Error = %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_voltage + * + * Description: + * Set battery charger voltage + * + ****************************************************************************/ + +static int bq2429x_voltage(FAR struct battery_charger_dev_s *dev, int value) +{ + FAR struct bq2429x_dev_s *priv = (FAR struct bq2429x_dev_s *)dev; + int ret; + + /* Set voltage to battery charger */ + + ret = bq2429x_setvolt(priv, value); + if (ret < 0) + { + baterr("ERROR: Error setting voltage to BQ2429X! Error = %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_current + * + * Description: + * Set the battery charger current rate for charging + ****************************************************************************/ + +static int bq2429x_current(FAR struct battery_charger_dev_s *dev, int value) +{ + FAR struct bq2429x_dev_s *priv = (FAR struct bq2429x_dev_s *)dev; + int ret; + + /* Set current to battery charger */ + + ret = bq2429x_setcurr(priv, value); + if (ret < 0) + { + baterr("ERROR: Error setting current to BQ2429X! Error = %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_input_current + * + * Description: + * Set the power-supply input current limit + * + ****************************************************************************/ + +static int bq2429x_input_current(FAR struct battery_charger_dev_s *dev, + int value) +{ + FAR struct bq2429x_dev_s *priv = (FAR struct bq2429x_dev_s *)dev; + int ret; + + ret = bq2429x_powersupply(priv, value); + if (ret < 0) + { + baterr("ERROR: Failed to set BQ2429x power supply input limit: %d\n", + ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: bq2429x_operate + * + * Description: + * Do miscellaneous battery ioctl(). + * + * Set the battery charger current rate for charging + * REG00 EN_HIZ + * REG01 BOOST + * REG01 CHARGE + * REG02[1] BCOLD + * REG02[1] FORCE_20PCT + * REG05[1] EN_TERM Charging Termination Enable + * REG05[2] WATCHDOG I2C Watchdog Setting 5-20Hrs default 12Hrs + * REG05[1] EN_TIMER Charging safety timer + * REG05[2] CHG_TIMER Fast Charge Timer Setting + * TREG[2] Thermal Regulation Threshold + * REG07[1] DPDM_EN Force DPDM detection when VBUS poower is present + * REG07[1] TMR2X_EN Safety Timer Slowed during DPM or thermal regulation + * REG07[1] BATFET_Disable Turnon off BATFET (Q4) + * REG07[1] INT_MASK1 - Allow INT on CHRG_FAULT Default: 1 Allow + * REG07[1] INT_MASK0 - Allow INT on BAT_FAULT Default: 1 Allow + * + * _provision + * REG00[3] InputCurrent Limit 100mA 3000mA with PSEL + * REG01[1] BOOST_LIM 1A/1.5A Default:1.5A + * REG02[1] ICHG Fast Charge Current Limit, 512-3008mA Default 2048mA + * REG03[4] IPRECHG Pre-charge current Limit 128-2048mA Default: 128mA + * REG03[3] ITERM Termination Current Limit 128-1024mA Default: 256mA + * + * also System output voltage + * REG00[4] VINDPM 3.88-5.08V Default:4.36V + * REG01[3] Min Sys Voltage Range3.0-3.7V + * REG04[6] Charge Voltage Limit 3504-4400mV Default: 4208mV + * REG04[1] Battery Recharge Threhold 100/300mV Default 100mV + * REG06[4] BOOSTV - Boost Voltage 4550-5510mV Default 4998mV + * REG06[2] BHOT Boost Mode Termperature Monitor + * + ****************************************************************************/ + +static int bq2429x_operate(FAR struct battery_charger_dev_s *dev, + uintptr_t param) +{ + FAR struct bq2429x_dev_s *priv = (FAR struct bq2429x_dev_s *)dev; + struct batio_operate_msg_s *msg = (struct batio_operate_msg_s *)param; + int op, value; + int ret = OK; + + bq2429x_dump_regs(priv); + +#if 0 + static bool wdg_disabled = 0; + + /* Tickle watchdog periodically or disable */ + + if (!wdg_disabled) + { + wdg_disabled = true; + bq2429x_reset(priv); + + ret = bq2429x_watchdog(priv, false); /* Disable */ + if (ret < 0) + { + baterr("ERROR: Failed to disable BQ2429x watchdog: %d\n", ret); + return ret; + } + } +#endif + + op = msg->operate_type; + value = (int)msg->u32; + switch (op) + { + case BATIO_OPRTN_BOOST: + ret = bq2429x_setboost_otg_config(priv, true); + break; + + case BATIO_OPRTN_CHARGE: + ret = bq2429x_setboost_otg_config(priv, false); + break; + + case BATIO_OPRTN_EN_TERM: + ret = bq2429x_en_term(priv, (bool)value); + break; + + case BATIO_OPRTN_HIZ: + ret = bq2429x_en_hiz(priv, (bool)value); + + /* Also need to set to 100mA USB host and if the battery above Vbatgd? */ + + break; + + case BATIO_OPRTN_SYSOFF: + ret = bq2429x_sysoff(priv); + break; + + case BATIO_OPRTN_RESET: + ret = bq2429x_reset(priv); + break; + + case BATIO_OPRTN_WDOG: + ret = bq2429x_watchdog(priv, (bool)value); + break; + + default: + baterr("Unsupported opt: 0x%X\n", op); + ret = -EINVAL; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: bq2429x_initialize + * + * Description: + * Initialize the BQ2429x battery driver and return an instance of the + * lower-half interface that may be used with battery_charger_register(). + * + * This driver requires: + * + * CONFIG_BATTERY_CHARGER - Upper half battery driver support + * CONFIG_I2C - I2C support + * CONFIG_I2C_BQ2429X - And the driver must be explictly selected. + * + * Input Parameters: + * i2c - An instance of the I2C interface to use to communicate with + * the BQ2429x + * addr - The I2C address of the BQ2429x (Better be 0x6B). + * frequency - The I2C frequency + * current - The input current our power-supply can offer to charger + * + * Returned Value: + * A pointer to the initialized lower-half driver instance. A NULL pointer + * is returned on a failure to initialize the BQ2429x lower half. + * + ****************************************************************************/ + +FAR struct battery_charger_dev_s * + bq2429x_initialize(FAR struct i2c_master_s *i2c, uint8_t addr, + uint32_t frequency, int current) +{ + FAR struct bq2429x_dev_s *priv; + int ret; + + /* Initialize the BQ2429x device structure */ + + priv = (FAR struct bq2429x_dev_s *)kmm_zalloc(sizeof(struct bq2429x_dev_s)); + if (priv) + { + /* Initialize the BQ2429x device structure */ + + sem_init(&priv->batsem, 0, 1); + priv->ops = &g_bq2429xops; + priv->i2c = i2c; + priv->addr = addr; + priv->frequency = frequency; + + /* Reset the BQ2429x */ + + ret = bq2429x_reset(priv); + if (ret < 0) + { + baterr("ERROR: Failed to reset the BQ2429x: %d\n", ret); + kmm_free(priv); + return NULL; + } + + /* Disable watchdog otherwise BQ2429x returns to StandAlone mode */ + + ret = bq2429x_watchdog(priv, false); + if (ret < 0) + { + baterr("ERROR: Failed to disable BQ2429x watchdog: %d\n", ret); + kmm_free(priv); + return NULL; + } + + /* Define the current that our power supply can offer to the charger. */ + + ret = bq2429x_powersupply(priv, current); + if (ret < 0) + { + baterr("ERROR: Failed to set BQ2429x power supply input limit: %d\n", ret); + kmm_free(priv); + return NULL; + } + + /* Disable all interrupts. */ + + ret = bq2429x_en_stat(priv, false); + if (ret < 0) + { + baterr("ERROR: Failed to disable BQ2429x interrupts: %d\n", ret); + kmm_free(priv); + return NULL; + } + } + + return (FAR struct battery_charger_dev_s *)priv; +} + +#endif /* CONFIG_BATTERY_CHARGER && CONFIG_I2C && CONFIG_I2C_BQ2429X */ diff --git a/include/nuttx/power/battery_charger.h b/include/nuttx/power/battery_charger.h index 932e3ae37e..997e0fa5c3 100644 --- a/include/nuttx/power/battery_charger.h +++ b/include/nuttx/power/battery_charger.h @@ -60,6 +60,7 @@ * * CONFIG_I2C - I2C support *may* be needed * CONFIG_I2C_BQ2425X - The BQ2425x driver must be explicitly selected. + * CONFIG_I2C_BQ2429X - The BQ2429x driver must be explicitly selected. */ /* IOCTL Commands ***********************************************************/ @@ -84,6 +85,8 @@ * Input value: An int defining the current value. * BATIOC_INPUT_CURRENT - Define the input current limit of power supply. * Input value: An int defining the input current limit value. + * BATIOC_OPERATE - Perform miscellaneous, device-specific charger operation. + * Input value: An uintptr_t that can hold a pointer to struct batio_operate_msg_s. */ /* Special input values for BATIOC_INPUT_CURRENT that may optionally @@ -151,6 +154,10 @@ struct battery_charger_operations_s /* Set the input current limit of power supply */ int (*input_current)(struct battery_charger_dev_s *dev, int value); + + /* Do device specific operation */ + + int (*operate)(struct battery_charger_dev_s *dev, uintptr_t param); }; /* This structure defines the battery driver state structure */ @@ -207,11 +214,11 @@ int battery_charger_register(FAR const char *devpath, * * Description: * Initialize the BQ2425X battery driver and return an instance of the - * lower_half interface that may be used with battery_charger_register(); + * lower-half interface that may be used with battery_charger_register(). * * This driver requires: * - * CONFIG_BATTERY_CHARGER - Upper half battery fuel gauge driver support + * CONFIG_BATTERY_CHARGER - Upper half battery charger driver support * CONFIG_I2C - I2C support * CONFIG_I2C_BQ2425X - And the driver must be explictly selected. * @@ -237,6 +244,55 @@ FAR struct battery_charger_dev_s *bq2425x_initialize(FAR struct i2c_master_s *i2 int current); #endif +/**************************************************************************** + * Name: bq2429x_initialize + * + * Description: + * Initialize the BQ2429X (BQ24series LiIon Charger with USB OTG boost 5V) + * battery driver and return an instance of the lower-half interface that + * may be used with battery_charger_register(). + * + * This is for: + * BQ24296M VQFN24 + * BQ24296 VQFN24 + * BQ24297 + * BQ24298 + * Possibly similar: + * BQ24262 + * BQ24259 + * BQ24292I BQ24295 B + * Possibly the following: + * BQ24260/1/2 Vin-14V + * BQ24190 Vin=17V + * + * This driver requires: + * + * CONFIG_BATTERY_CHARGER - Upper half battery charger driver support + * CONFIG_I2C - I2C support + * CONFIG_I2C_BQ2429X - And the driver must be explictly selected. + * + * Input Parameters: + * i2c - An instance of the I2C interface to use to communicate with + * the BQ2429X + * addr - The I2C address of the BQ2429X (Better be 0x6B). + * frequency - The I2C frequency + * current - The input current our power-supply can offer to charger + * + * Returned Value: + * A pointer to the initialized battery driver instance. A NULL pointer + * is returned on a failure to initialize the BQ2429X lower half. + * + ****************************************************************************/ + +#if defined(CONFIG_I2C) && defined(CONFIG_I2C_BQ2429X) + +struct i2c_master_s; +FAR struct battery_charger_dev_s *bq2429x_initialize(FAR struct i2c_master_s *i2c, + uint8_t addr, + uint32_t frequency, + int current); +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/include/nuttx/power/battery_ioctl.h b/include/nuttx/power/battery_ioctl.h index 2137a6ffb2..3256f1c87f 100644 --- a/include/nuttx/power/battery_ioctl.h +++ b/include/nuttx/power/battery_ioctl.h @@ -2,7 +2,7 @@ * include/nuttx/power/battery_ioctl.h * NuttX Battery IOCTLs definition * - * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -60,5 +60,35 @@ #define BATIOC_CURRENT _BATIOC(0x0005) #define BATIOC_INPUT_CURRENT _BATIOC(0x0006) #define BATIOC_CAPACITY _BATIOC(0x0007) +#define BATIOC_OPERATE _BATIOC(0x0008) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct batio_operate_msg_s +{ + uint8_t operate_type; /* Really enum batio_operate_e */ + union + { + uint32_t u32; + uint8_t u8[8]; + }; +}; + +#if defined(CONFIG_I2C_BQ2429X) +enum batio_operate_e +{ + BATIO_OPRTN_NOP = 0, + BATIO_OPRTN_BOOST, + BATIO_OPRTN_CHARGE, + BATIO_OPRTN_EN_TERM, + BATIO_OPRTN_HIZ, + BATIO_OPRTN_SYSOFF, + BATIO_OPRTN_RESET, + BATIO_OPRTN_WDOG, + BATIO_OPRTN_END +}; +#endif #endif /* __INCLUDE_NUTTX_POWER_BATTERY_IOCTL_H */ diff --git a/include/nuttx/power/bq2429x.h b/include/nuttx/power/bq2429x.h new file mode 100644 index 0000000000..e858ea9325 --- /dev/null +++ b/include/nuttx/power/bq2429x.h @@ -0,0 +1,244 @@ +/**************************************************************************** + * drivers/power/bq2429x.h + * Lower half driver for BQ2429X battery charger + * + * Copyright (C) 2017 Neil Hancock. All rights reserved. + * + * Copyright (C) 2017 Haltian Ltd. All rights reserved. + * Author: Juha Niskanen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_POWER_BQ2429X_H +#define __DRIVERS_POWER_BQ2429X_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Auxiliary Definitions */ + +#define BQ2429X_VOLTCHG_MIN 3504 +#define BQ2429X_VOLTCHG_MAX 4400 + +#define BQ2429X_CURRCHG_MIN 512 +#define BQ2429X_CURRCHG_MAX 3008 + +/* BQ2429X Register Definitions ********************************************/ +#define BQ2429X_REG00 0x00 +#define BQ2429X_REG01 0x01 +#define BQ2429X_REG02 0x02 +#define BQ2429X_REG03 0x03 +#define BQ2429X_REG04 0x04 +#define BQ2429X_REG05 0x05 +#define BQ2429X_REG06 0x06 +#define BQ2429X_REG07 0x07 +#define BQ2429X_REG08 0x08 +#define BQ2429X_REG09 0x09 +#define BQ2429X_REG0A 0x0a + +/* REG00 Input Source Control Register */ + +/* For enabling Device Shutdown for shipping - EN_HIZ=1 until QON pressed*/ +#define BQ2429XR1_EN_HIZ (1 << 7) /* 0 Disable (default) 1 Enable HighZ on battery, powerdown */ + +/* Dynamic Power Management - Indicated in StatusReg DPM_STAT REG08[3] + VINDPM - Input Voltage threshold (a drop below 5V) that triggers DPM + INLIM - Input current threshold that tiggers DPM */ + +#define BQ2429XR0_VINDPM_SHIFT 3 /* VIN DPM Offset 5V? Range*/ +#define BQ2429XR0_VINDPM_MASK (0xf << BQ2429XR0_VINDPM_SHIFT) +# define BQ2429XR0_VINDPM3_080mV (1 << BQ2429XR0_VINDPM_SHIFT) +# define BQ2429XR0_VINDPM2_160mV (2 << BQ2429XR0_VINDPM_SHIFT) +# define BQ2429XR0_VINDPM1_320mV (4 << BQ2429XR0_VINDPM_SHIFT) +# define BQ2429XR0_VINDPM0_640mV (8 << BQ2429XR0_VINDPM_SHIFT) +#define BQ2429XR0_INLIM_SHIFT 0 /* Input Current Limit - lower of I2C & ILIM */ +#define BQ2429XR0_INLIM_MASK (0x7 << BQ2429XR0_INLIM_SHIFT) +# define BQ2429XR0_INLIM_0100mA (0x0 << BQ2429XR0_INLIM_SHIFT) +# define BQ2429XR0_INLIM_0150mA (0x1 << BQ2429XR0_INLIM_SHIFT) +# define BQ2429XR0_INLIM_0500mA (0x2 << BQ2429XR0_INLIM_SHIFT) +# define BQ2429XR0_INLIM_0900mA (0x3 << BQ2429XR0_INLIM_SHIFT) +# define BQ2429XR0_INLIM_1000mA (0x4 << BQ2429XR0_INLIM_SHIFT) +# define BQ2429XR0_INLIM_1500mA (0x5 << BQ2429XR0_INLIM_SHIFT) +# define BQ2429XR0_INLIM_2000mA (0x6 << BQ2429XR0_INLIM_SHIFT) +# define BQ2429XR0_INLIM_3000mA (0x7 << BQ2429XR0_INLIM_SHIFT) + +/* REG01 Power-On Configuration Register */ + +#define BQ2429XR1_REG_RESET (1 << 7) /* Write 1 to Reset all registers to default values */ +#define BQ2429XR1_DOG_RESET (1 << 6) /* Write 1 for watchdog timer reset */ +#define BQ2429XR1_OTG_CONFIG (1 << 5) /* =0 Disable (default) =1 Enable See description */ +#define BQ2429XR1_CHG_CONFIG (1 << 4) /* =0 Disable =1 Enable (default) See description */ +#define BQ2429XR1_SYS_MINV_SHIFT 1 /* Min Sys Voltage Limit. Offset 3.0V Range 3-3.7V */ +#define BQ2429XR1_SYS_MINV_MASK (7 << BQ2429XR1_SYS_MINV_SHIFT) +#define BQ2429XR1_SYS_MINV0_0_1V (1 << BQ2429XR1_SYS_MINV_SHIFT) +#define BQ2429XR1_SYS_MINV0_0_2V (2 << BQ2429XR1_SYS_MINV_SHIFT) +#define BQ2429XR1_SYS_MINV0_0_4V (4 << BQ2429XR1_SYS_MINV_SHIFT) + +#define BQ2429XR2_BOOST_LIM (1 << 0) /* 0=1A, 1=1.5A (default) Vout Boost Current Limit */ + +/* REG02 Charge Current Control */ + +#define BQ2429XR2_ICHG_SHIFT 2 +#define BQ2429XR2_ICHG_MASK (0x3f << BQ2429XR2_ICHG_SHIFT) + +#define BQ2429XR2_BCOLD (1 << 1) /* Boost Mode temperature threshold config for boost disable 0=76% 1=79% */ +#define BQ2429XR2_FORCE_20PCT (1 << 0) /* Charge Configuration Threshold 0=Fast 1=less */ + +/* REG03 Pre-charge Termination Control Register */ + +#define BQ2429XR3_IPRECHG_SHIFT 4 /* Precharge I Limit. Offset 128mA Range 128-2048 mA */ +#define BQ2429XR3_IPRECHG_MASK (0xf << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_0128mA (0x00 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_0128mA (0x01 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_0256mA (0x02 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_0384mA (0x03 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_0512mA (0x04 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_0768mA (0x05 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_0896mA (0x06 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_1024mA (0x07 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_1152mA (0x10 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_1280mA (0x11 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_1408mA (0x12 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_1536mA (0x13 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_1664mA (0x14 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_1792mA (0x15 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_1920mA (0x16 << BQ2429XR3_IPRECHG_SHIFT) +#define BQ2429XR3_IPRECHG_2048mA (0x17 << BQ2429XR3_IPRECHG_SHIFT) + +#define BQ2429XR3_ITERM_SHIFT 0 /* Offset 128mA Range 128-2048 mA (128-1024 mA in BQ24296M )*/ +#define BQ2429XR3_ITERM_MASK (0xf << BQ2429XR3_ITERM_SHIFT) +#define BQ2429XR3_ITERM0_128mA (1 << BQ2429XR3_ITERM_SHIFT) +#define BQ2429XR3_ITERM0_256mA (2 << BQ2429XR3_ITERM_SHIFT) +#define BQ2429XR3_ITERM0_512mA (4 << BQ2429XR3_ITERM_SHIFT) +#define BQ2429XR3_ITERM0_1024mA (8 << BQ2429XR3_ITERM_SHIFT) /* Reserved in BQ24296M */ + +/* REG04 Charge Voltage Control Register */ +#define BQ2429XR4_VREG_SHIFT 2 /* Offset 3.504V Range 3.504-4.400V Default 4.208V */ +#define BQ2429XR4_VREG_MASK (0x3f<< BQ2429XR4_VREG_SHIFT) + +#define BQ2429XR4_BATLOWV (1 << 1) /* 0=2.8V 1=3.0V Pre-charge to fast Charge */ +#define BQ2429XR4_VRECHG (1 << 0) /* 0=100mV 1=300mV */ + +/* REG05 Charge Termination Timer Control Register */ + +#define BQ2429XR5_EN_TERM (1 << 7) /* 0=Disable 1=Enable(default) terminate of charge */ +#define BQ2429XR5_RESERVED6 (1 << 6) +#define BQ2429XR5_WATCHDOG_SHIFT 4 /* Watchdog Timer Settings */ +#define BQ2429XR5_WATCHDOG_MASK (3 << BQ2429XR5_WATCHDOG_SHIFT) +# define BQ2429XR5_WATCHDOG_DIS (0 << BQ2429XR5_WATCHDOG_SHIFT) +# define BQ2429XR5_WATCHDOG_040Sec (1 << BQ2429XR5_WATCHDOG_SHIFT) +# define BQ2429XR5_WATCHDOG_080Sec (2 << BQ2429XR5_WATCHDOG_SHIFT) +# define BQ2429XR5_WATCHDOG_160Sec (3 << BQ2429XR5_WATCHDOG_SHIFT) + +#define BQ2429XR5_EN_TIMER (1 << 3) /* 0=Disable 1=Enable(default) */ +/* Fast Charge Timer Settings */ +#define BQ2429XR5_CHG_TIMER_SHIFT 1 +#define BQ2429XR5_CHG_TIMER_MASK (3 << BQ2429XR5_CHG_TIMER_SHIFT) +# define BQ2429XR5_CHG_TIMER_05hrs (0 << BQ2429XR5_CHG_TIMER_SHIFT) +# define BQ2429XR5_CHG_TIMER_08hrs (1 << BQ2429XR5_CHG_TIMER_SHIFT) +# define BQ2429XR5_CHG_TIMER_12hrs (2 << BQ2429XR5_CHG_TIMER_SHIFT) +# define BQ2429XR5_CHG_TIMER_20hrs (3 << BQ2429XR5_CHG_TIMER_SHIFT) +#define BQ2429XR5_RESERVED0 (1 << 0) + +/* REG06 Boost Voltage/Thermal Regulation Control register */ + +#define BQ2429XR6_BOOSTV_SHIFT 4 /* Offset 4.55V Range 4.55-5.51A Dev 4.998V(0111) */ +#define BQ2429XR6_BOOSTV_MASK (0xf << BQ2429XR6_BOOSTV_SHIFT) +# define BQ2429XR6_BOOSTV_064mV (1 << BQ2429XR6_BOOSTV_SHIFT) +# define BQ2429XR6_BOOSTV_128mV (2 << BQ2429XR6_BOOSTV_SHIFT) +# define BQ2429XR6_BOOSTV_256mV (4 << BQ2429XR6_BOOSTV_SHIFT) +# define BQ2429XR6_BOOSTV_512mV (8 << BQ2429XR6_BOOSTV_SHIFT) +#define BQ2429XR6_BHOT_SHIFT 2 /* Boost Mode temp threshold */ +#define BQ2429XR6_BHOT_MASK (3 << BQ2429XR6_BHOT_SHIFT) +# define BQ2429XR6_BHOT_55C (0 << BQ2429XR6_BHOT_SHIFT) +# define BQ2429XR6_BHOT_60C (1 << BQ2429XR6_BHOT_SHIFT) +# define BQ2429XR6_BHOT_65C (2 << BQ2429XR6_BHOT_SHIFT) +# define BQ2429XR6_BHOT_DISABLE (3 << BQ2429XR6_BHOT_SHIFT) +#define BQ2429XR6_TREG_SHIFT 0 /* Thermal Regulation */ +#define BQ2429XR6_TREG_MASK (3 << BQ2429XR6_TREG_SHIFT) +# define BQ2429XR6_TREG_060C (0 << BQ2429XR6_TREG_SHIFT) +# define BQ2429XR6_TREG_080C (1 << BQ2429XR6_TREG_SHIFT) +# define BQ2429XR6_TREG_100C (2 << BQ2429XR6_TREG_SHIFT) +# define BQ2429XR6_TREG_110C (3 << BQ2429XR6_TREG_SHIFT) + +/* REG07 Misc Operation Control Register */ + +#define BQ2429XR7_DPDM_EN (1 << 7) /* 1=Force Detection when VBUS power is present */ +#define BQ2429XR7_TMR2X_EN (1 << 6) /* 1=Safety Timer slowed by 2X during DPM/Thermal regulation */ +#define BQ2429XR7_BATFET_DISABLE (1 << 5) /* 1=BATFET (Q4) turn off */ +#define BQ2429XR7_RESERVED4 (1 << 4) +#define BQ2429XR7_RESERVED3 (1 << 3) +#define BQ2429XR7_RESERVED2 (1 << 2) +#define BQ2429XR7_INT_MASK1 (1 << 1) /* =1 (default) INT on CHRG_FAULT */ +#define BQ2429XR7_INT_MASK0 (1 << 0) /* =1 (default) INT on BAT_FAULT */ + +/* REG08 Systems Status Register */ + +#define BQ2429XR8_VBUS_STAT_SHIFT 6 /* VBUS Connection Type */ +#define BQ2429XR8_VBUS_STAT_MASK (3 << BQ2429XR8_VBUS_STAT_SHIFT) +# define BQ2429XR8_VBUS_STAT_UNKNOWN (0 << BQ2429XR8_VBUS_STAT_SHIFT) +# define BQ2429XR8_VBUS_STAT_USBH (1 << BQ2429XR8_VBUS_STAT_SHIFT) +# define BQ2429XR8_VBUS_STAT_ADAPTER (2 << BQ2429XR8_VBUS_STAT_SHIFT) +# define BQ2429XR8_VBUS_STAT_OTG (3 << BQ2429XR8_VBUS_STAT_SHIFT) +#define BQ2429XR8_CHRG_STAT_SHIFT 4 /* Charging Status */ +#define BQ2429XR8_CHRG_STAT_MASK (3 << BQ2429XR8_CHRG_STAT_SHIFT) +# define BQ2429XR8_CHRG_STAT_NONE (0 << BQ2429XR8_CHRG_STAT_SHIFT) +# define BQ2429XR8_CHRG_STAT_PRECHG (1 << BQ2429XR8_CHRG_STAT_SHIFT) +# define BQ2429XR8_CHRG_STAT_FASTCHG (2 << BQ2429XR8_CHRG_STAT_SHIFT) +# define BQ2429XR8_CHRG_STAT_DONE (3 << BQ2429XR8_CHRG_STAT_SHIFT) +#define BQ2429XR8_DPM_STAT (1 << 3) /* 0= NotDPM 1=VINDPM or INDPM */ +#define BQ2429XR8_PG_STAT (1 << 2) /* 0= Not 1=Power Good */ +#define BQ2429XR8_THERM_STAT (1 << 1) /* 0= Normal 1=In Thermal Regulation */ +#define BQ2429XR8_VSYS_STAT (1 << 0) /* 0= Not 1=In VSYSMIN regulation BAT < VSYSMIN */ + +/* REG09 New Fault Register */ + +#define BQ2429XR9_WATCHDOG_FAULT (1 << 7) /* 1=Watchdog Timer expired */ +#define BQ2429XR9_OTG_FAULT (1 << 6) /* 1=Bus overloaded in OTG, or VBUS OVP or battery low */ +#define BQ2429XR9_CHRG_FAULT_SHIFT 4 /* Charging Status */ +#define BQ2429XR9_CHRG_FAULT_MASK (3 << BQ2429XR9_CHRG_FAULT_SHIFT) +# define BQ2429XR9_CHRG_FAULT_NORMAL (0 << BQ2429XR9_CHRG_FAULT_SHIFT) +# define BQ2429XR9_CHRG_FAULT_INPUT (1 << BQ2429XR9_CHRG_FAULT_SHIFT) +# define BQ2429XR9_CHRG_FAULT_THERMAL (2 << BQ2429XR9_CHRG_FAULT_SHIFT) +# define BQ2429XR9_CHRG_FAULT_TIMER (3 << BQ2429XR9_CHRG_FAULT_SHIFT) +#define BQ2429XR9_BAT_FAULT (1 << 3) /* 1=Battery OVP */ +#define BQ2429XR9_RESERVED2 (1 << 2) + +#define BQ2429XR9_NTC_FAULT1_COLD (1 << 1) /* Cold temperature */ +#define BQ2429XR9_NTC_FAULT2_HOT (1 << 0) /* Hot temperature */ + +/* REG0A Vendor Part Revision Info */ + +#define BQ24296_VENDOR_ID 0x20 /* BQ24296 */ +#define BQ24296M_VENDOR_ID 0x20 /* BQ24296M */ +#define BQ24297_VENDOR_ID 0x60 /* BQ24297 */ + +#endif /* __DRIVERS_POWER_BQ2429X_H */