Files
BPI-CM9-Linux/build/patch/kernel/archive/sm8250-6.18/0021-power-supply-add-bq25970-charger-driver.patch

3205 lines
83 KiB
Diff

From c262fbba641691d1ad50d5e36f1ddf9f5c2be27b Mon Sep 17 00:00:00 2001
From: Jianhua Lu <lujianhua000@gmail.com>
Date: Wed, 18 Sep 2024 14:27:53 +0800
Subject: [PATCH 21/62] power: supply: add bq25970 charger driver
Signed-off-by: Jiali Chen <chenjiali@radxa.com>
---
drivers/power/supply/Kconfig | 9 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/bq25970_charger.c | 2321 ++++++++++++++++++++++++
drivers/power/supply/bq25970_reg.h | 821 +++++++++
4 files changed, 3152 insertions(+)
create mode 100644 drivers/power/supply/bq25970_charger.c
create mode 100644 drivers/power/supply/bq25970_reg.h
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 79ddb006e2da..6e0559e6baed 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -775,6 +775,15 @@ config CHARGER_BQ25890
help
Say Y to enable support for the TI BQ25890 battery charger.
+config CHARGER_BQ25970
+ tristate "TI BQ25970 battery charger driver"
+ depends on I2C
+ depends on GPIOLIB || COMPILE_TEST
+ select REGMAP_I2C
+ help
+ Say Y to enable support for the TI BQ25970, BQ25971
+ series of fast battery chargers.
+
config CHARGER_BQ25980
tristate "TI BQ25980 battery charger driver"
depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index f943c9150b32..60aec804ca8f 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -98,6 +98,7 @@ obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o
obj-$(CONFIG_CHARGER_BQ24735) += bq24735-charger.o
obj-$(CONFIG_CHARGER_BQ2515X) += bq2515x_charger.o
obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o
+obj-$(CONFIG_CHARGER_BQ25970) += bq25970_charger.o
obj-$(CONFIG_CHARGER_BQ25980) += bq25980_charger.o
obj-$(CONFIG_CHARGER_BQ256XX) += bq256xx_charger.o
obj-$(CONFIG_CHARGER_RK817) += rk817_charger.o
diff --git a/drivers/power/supply/bq25970_charger.c b/drivers/power/supply/bq25970_charger.c
new file mode 100644
index 000000000000..1aeb1873f9fd
--- /dev/null
+++ b/drivers/power/supply/bq25970_charger.c
@@ -0,0 +1,2321 @@
+/*
+ * BQ2570x battery charging driver
+ *
+ * Copyright (C) 2017 Texas Instruments *
+ * Copyright (C) 2021 XiaoMi, Inc.
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define pr_fmt(fmt) "[bq2597x] %s: " fmt, __func__
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/err.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/machine.h>
+#include <linux/debugfs.h>
+#include <linux/bitops.h>
+#include <linux/math64.h>
+#include <asm/neon.h>
+#include "bq25970_reg.h"
+/*#include "bq2597x.h"*/
+
+enum {
+ VBUS_ERROR_NONE,
+ VBUS_ERROR_LOW,
+ VBUS_ERROR_HIGH,
+};
+
+enum {
+ ADC_IBUS,
+ ADC_VBUS,
+ ADC_VAC,
+ ADC_VOUT,
+ ADC_VBAT,
+ ADC_IBAT,
+ ADC_TBUS,
+ ADC_TBAT,
+ ADC_TDIE,
+ ADC_MAX_NUM,
+};
+
+#define BQ25970_ROLE_STDALONE 0
+#define BQ25970_ROLE_SLAVE 1
+#define BQ25970_ROLE_MASTER 2
+
+enum {
+ BQ25970_STDALONE,
+ BQ25970_SLAVE,
+ BQ25970_MASTER,
+};
+
+enum {
+ BQ25968,
+ BQ25970,
+ SC8551,
+};
+
+static int bq2597x_mode_data[] = {
+ [BQ25970_STDALONE] = BQ25970_STDALONE,
+ [BQ25970_MASTER] = BQ25970_ROLE_MASTER,
+ [BQ25970_SLAVE] = BQ25970_ROLE_SLAVE,
+};
+
+
+#define BAT_OVP_ALARM BIT(7)
+#define BAT_OCP_ALARM BIT(6)
+#define BUS_OVP_ALARM BIT(5)
+#define BUS_OCP_ALARM BIT(4)
+#define BAT_UCP_ALARM BIT(3)
+#define VBUS_INSERT BIT(2)
+#define VBAT_INSERT BIT(1)
+#define ADC_DONE BIT(0)
+
+#define BAT_OVP_FAULT BIT(7)
+#define BAT_OCP_FAULT BIT(6)
+#define BUS_OVP_FAULT BIT(5)
+#define BUS_OCP_FAULT BIT(4)
+#define TBUS_TBAT_ALARM BIT(3)
+#define TS_BAT_FAULT BIT(2)
+#define TS_BUS_FAULT BIT(1)
+#define TS_DIE_FAULT BIT(0)
+
+/*below used for comm with other module*/
+#define BAT_OVP_FAULT_SHIFT 0
+#define BAT_OCP_FAULT_SHIFT 1
+#define BUS_OVP_FAULT_SHIFT 2
+#define BUS_OCP_FAULT_SHIFT 3
+#define BAT_THERM_FAULT_SHIFT 4
+#define BUS_THERM_FAULT_SHIFT 5
+#define DIE_THERM_FAULT_SHIFT 6
+
+#define BAT_OVP_FAULT_MASK (1 << BAT_OVP_FAULT_SHIFT)
+#define BAT_OCP_FAULT_MASK (1 << BAT_OCP_FAULT_SHIFT)
+#define BUS_OVP_FAULT_MASK (1 << BUS_OVP_FAULT_SHIFT)
+#define BUS_OCP_FAULT_MASK (1 << BUS_OCP_FAULT_SHIFT)
+#define BAT_THERM_FAULT_MASK (1 << BAT_THERM_FAULT_SHIFT)
+#define BUS_THERM_FAULT_MASK (1 << BUS_THERM_FAULT_SHIFT)
+#define DIE_THERM_FAULT_MASK (1 << DIE_THERM_FAULT_SHIFT)
+
+#define BAT_OVP_ALARM_SHIFT 0
+#define BAT_OCP_ALARM_SHIFT 1
+#define BUS_OVP_ALARM_SHIFT 2
+#define BUS_OCP_ALARM_SHIFT 3
+#define BAT_THERM_ALARM_SHIFT 4
+#define BUS_THERM_ALARM_SHIFT 5
+#define DIE_THERM_ALARM_SHIFT 6
+#define BAT_UCP_ALARM_SHIFT 7
+
+#define BAT_OVP_ALARM_MASK (1 << BAT_OVP_ALARM_SHIFT)
+#define BAT_OCP_ALARM_MASK (1 << BAT_OCP_ALARM_SHIFT)
+#define BUS_OVP_ALARM_MASK (1 << BUS_OVP_ALARM_SHIFT)
+#define BUS_OCP_ALARM_MASK (1 << BUS_OCP_ALARM_SHIFT)
+#define BAT_THERM_ALARM_MASK (1 << BAT_THERM_ALARM_SHIFT)
+#define BUS_THERM_ALARM_MASK (1 << BUS_THERM_ALARM_SHIFT)
+#define DIE_THERM_ALARM_MASK (1 << DIE_THERM_ALARM_SHIFT)
+#define BAT_UCP_ALARM_MASK (1 << BAT_UCP_ALARM_SHIFT)
+
+#define VBAT_REG_STATUS_SHIFT 0
+#define IBAT_REG_STATUS_SHIFT 1
+
+#define VBAT_REG_STATUS_MASK (1 << VBAT_REG_STATUS_SHIFT)
+#define IBAT_REG_STATUS_MASK (1 << VBAT_REG_STATUS_SHIFT)
+
+#define bq_err(fmt, ...) \
+do { \
+ if (bq->mode == BQ25970_ROLE_MASTER) \
+ printk(KERN_ERR "[bq2597x-MASTER]:%s:" fmt, __func__, ##__VA_ARGS__); \
+ else if (bq->mode == BQ25970_ROLE_SLAVE) \
+ printk(KERN_ERR "[bq2597x-SLAVE]:%s:" fmt, __func__, ##__VA_ARGS__); \
+ else \
+ printk(KERN_ERR "[bq2597x-STANDALONE]:%s:" fmt, __func__, ##__VA_ARGS__);\
+} while (0);
+
+#define bq_info(fmt, ...) \
+do { \
+ if (bq->mode == BQ25970_ROLE_MASTER) \
+ printk(KERN_INFO "[bq2597x-MASTER]:%s:" fmt, __func__, ##__VA_ARGS__); \
+ else if (bq->mode == BQ25970_ROLE_SLAVE) \
+ printk(KERN_INFO "[bq2597x-SLAVE]:%s:" fmt, __func__, ##__VA_ARGS__); \
+ else \
+ printk(KERN_INFO "[bq2597x-STANDALONE]:%s:" fmt, __func__, ##__VA_ARGS__);\
+} while (0);
+
+#define bq_dbg(fmt, ...) \
+do { \
+ if (bq->mode == BQ25970_ROLE_MASTER) \
+ printk(KERN_DEBUG "[bq2597x-MASTER]:%s:" fmt, __func__, ##__VA_ARGS__); \
+ else if (bq->mode == BQ25970_ROLE_SLAVE) \
+ printk(KERN_DEBUG "[bq2597x-SLAVE]:%s:" fmt, __func__, ##__VA_ARGS__); \
+ else \
+ printk(KERN_DEBUG "[bq2597x-STANDALONE]:%s:" fmt, __func__, ##__VA_ARGS__);\
+} while (0);
+
+enum hvdcp3_type {
+ HVDCP3_NONE = 0,
+ HVDCP3_CLASSA_18W,
+ HVDCP3_CLASSB_27W,
+ HVDCP3P5_CLASSA_18W,
+ HVDCP3P5_CLASSB_27W,
+};
+
+#define BUS_OVP_FOR_QC 10500
+#define BUS_OVP_ALARM_FOR_QC 9500
+#define BUS_OCP_FOR_QC_CLASS_A 3250
+#define BUS_OCP_ALARM_FOR_QC_CLASS_A 2000
+#define BUS_OCP_FOR_QC_CLASS_B 4000
+#define BUS_OCP_ALARM_FOR_QC_CLASS_B 3000
+#define BUS_OCP_FOR_QC3P5_CLASS_A 3000
+#define BUS_OCP_ALARM_FOR_QC3P5_CLASS_A 2500
+#define BUS_OCP_FOR_QC3P5_CLASS_B 3500
+#define BUS_OCP_ALARM_FOR_QC3P5_CLASS_B 3200
+
+/*end*/
+
+struct bq2597x_cfg {
+ bool bat_ovp_disable;
+ bool bat_ocp_disable;
+ bool bat_ovp_alm_disable;
+ bool bat_ocp_alm_disable;
+
+ int bat_ovp_th;
+ int bat_ovp_alm_th;
+ int bat_ocp_th;
+ int bat_ocp_alm_th;
+
+ bool bus_ovp_alm_disable;
+ bool bus_ocp_disable;
+ bool bus_ocp_alm_disable;
+
+ int bus_ovp_th;
+ int bus_ovp_alm_th;
+ int bus_ocp_th;
+ int bus_ocp_alm_th;
+
+ bool bat_ucp_alm_disable;
+
+ int bat_ucp_alm_th;
+ int ac_ovp_th;
+
+ bool bat_therm_disable;
+ bool bus_therm_disable;
+ bool die_therm_disable;
+
+ int bat_therm_th; /*in %*/
+ int bus_therm_th; /*in %*/
+ int die_therm_th; /*in degC*/
+
+ int sense_r_mohm;
+};
+
+struct bq2597x {
+ struct device *dev;
+ struct i2c_client *client;
+
+ int part_no;
+ int revision;
+
+ int chip_vendor;
+ int mode;
+
+
+
+ struct mutex data_lock;
+ struct mutex i2c_rw_lock;
+ struct mutex charging_disable_lock;
+ struct mutex irq_complete;
+
+ bool irq_waiting;
+ bool irq_disabled;
+ bool resume_completed;
+
+ bool batt_present;
+ bool vbus_present;
+
+ bool usb_present;
+ bool charge_enabled; /* Register bit status */
+
+ /* ADC reading */
+ int vbat_volt;
+ int vbus_volt;
+ int vout_volt;
+ int vac_volt;
+
+ int ibat_curr;
+ int ibus_curr;
+
+ int bat_temp;
+ int bus_temp;
+ int die_temp;
+
+ /* alarm/fault status */
+ bool bat_ovp_fault;
+ bool bat_ocp_fault;
+ bool bus_ovp_fault;
+ bool bus_ocp_fault;
+
+ bool bat_ovp_alarm;
+ bool bat_ocp_alarm;
+ bool bus_ovp_alarm;
+ bool bus_ocp_alarm;
+
+ bool bat_ucp_alarm;
+
+ bool bat_therm_alarm;
+ bool bus_therm_alarm;
+ bool die_therm_alarm;
+
+ bool bat_therm_fault;
+ bool bus_therm_fault;
+ bool die_therm_fault;
+
+ bool therm_shutdown_flag;
+ bool therm_shutdown_stat;
+
+ bool vbat_reg;
+ bool ibat_reg;
+
+ int prev_alarm;
+ int prev_fault;
+
+ int chg_ma;
+ int chg_mv;
+
+ int charge_state;
+
+ struct bq2597x_cfg *cfg;
+
+ int skip_writes;
+ int skip_reads;
+
+ struct bq2597x_platform_data *platform_data;
+
+ struct delayed_work monitor_work;
+
+ struct dentry *debug_root;
+
+ struct power_supply_desc psy_desc;
+ struct power_supply_config psy_cfg;
+ struct power_supply *fc2_psy;
+ struct power_supply *typec_psy;
+
+ struct notifier_block nb;
+ //struct delayed_work status_changed_work;
+};
+
+static int bq2597x_set_acovp_th(struct bq2597x *bq, int threshold);
+static int bq2597x_set_busovp_th(struct bq2597x *bq, int threshold);
+
+/************************************************************************/
+static int __bq2597x_read_byte(struct bq2597x *bq, u8 reg, u8 *data)
+{
+ s32 ret;
+
+ ret = i2c_smbus_read_byte_data(bq->client, reg);
+ if (ret < 0) {
+ bq_err("i2c read fail: can't read from reg 0x%02X\n", reg);
+ return ret;
+ }
+
+ *data = (u8) ret;
+
+ return 0;
+}
+
+static int __bq2597x_write_byte(struct bq2597x *bq, int reg, u8 val)
+{
+ s32 ret;
+
+ ret = i2c_smbus_write_byte_data(bq->client, reg, val);
+ if (ret < 0) {
+ bq_err("i2c write fail: can't write 0x%02X to reg 0x%02X: %d\n",
+ val, reg, ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int bq2597x_read_byte(struct bq2597x *bq, u8 reg, u8 *data)
+{
+ int ret;
+
+ if (bq->skip_reads) {
+ *data = 0;
+ return 0;
+ }
+
+ mutex_lock(&bq->i2c_rw_lock);
+ ret = __bq2597x_read_byte(bq, reg, data);
+ mutex_unlock(&bq->i2c_rw_lock);
+
+ return ret;
+}
+
+static int bq2597x_write_byte(struct bq2597x *bq, u8 reg, u8 data)
+{
+ int ret;
+
+ if (bq->skip_writes)
+ return 0;
+
+ mutex_lock(&bq->i2c_rw_lock);
+ ret = __bq2597x_write_byte(bq, reg, data);
+ mutex_unlock(&bq->i2c_rw_lock);
+
+ return ret;
+}
+
+static int bq2597x_update_bits(struct bq2597x *bq, u8 reg,
+ u8 mask, u8 data)
+{
+ int ret;
+ u8 tmp;
+
+ if (bq->skip_reads || bq->skip_writes)
+ return 0;
+
+ mutex_lock(&bq->i2c_rw_lock);
+ ret = __bq2597x_read_byte(bq, reg, &tmp);
+ if (ret) {
+ bq_err("Failed: reg=%02X, ret=%d\n", reg, ret);
+ goto out;
+ }
+
+ tmp &= ~mask;
+ tmp |= data & mask;
+
+ ret = __bq2597x_write_byte(bq, reg, tmp);
+ if (ret)
+ bq_err("Failed: reg=%02X, ret=%d\n", reg, ret);
+
+out:
+ mutex_unlock(&bq->i2c_rw_lock);
+ return ret;
+}
+
+static int bq2597x_enable_charge(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_CHG_ENABLE;
+ else
+ val = BQ2597X_CHG_DISABLE;
+
+ val <<= BQ2597X_CHG_EN_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_0C,
+ BQ2597X_CHG_EN_MASK, val);
+
+ return ret;
+}
+
+static int bq2597x_check_charge_enabled(struct bq2597x *bq, bool *enabled)
+{
+ int ret;
+ u8 val;
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_0C, &val);
+ if (!ret)
+ *enabled = !!(val & BQ2597X_CHG_EN_MASK);
+ return ret;
+}
+
+static int bq2597x_enable_wdt(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_WATCHDOG_ENABLE;
+ else
+ val = BQ2597X_WATCHDOG_DISABLE;
+
+ val <<= BQ2597X_WATCHDOG_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_0B,
+ BQ2597X_WATCHDOG_DIS_MASK, val);
+ return ret;
+}
+
+static int bq2597x_enable_batovp(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_BAT_OVP_ENABLE;
+ else
+ val = BQ2597X_BAT_OVP_DISABLE;
+
+ val <<= BQ2597X_BAT_OVP_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_00,
+ BQ2597X_BAT_OVP_DIS_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_batovp_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_BAT_OVP_BASE)
+ threshold = BQ2597X_BAT_OVP_BASE;
+
+ val = (threshold - BQ2597X_BAT_OVP_BASE) / BQ2597X_BAT_OVP_LSB;
+
+ val <<= BQ2597X_BAT_OVP_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_00,
+ BQ2597X_BAT_OVP_MASK, val);
+ return ret;
+}
+
+static int bq2597x_enable_batovp_alarm(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_BAT_OVP_ALM_ENABLE;
+ else
+ val = BQ2597X_BAT_OVP_ALM_DISABLE;
+
+ val <<= BQ2597X_BAT_OVP_ALM_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_01,
+ BQ2597X_BAT_OVP_ALM_DIS_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_batovp_alarm_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_BAT_OVP_ALM_BASE)
+ threshold = BQ2597X_BAT_OVP_ALM_BASE;
+
+ val = (threshold - BQ2597X_BAT_OVP_ALM_BASE) / BQ2597X_BAT_OVP_ALM_LSB;
+
+ val <<= BQ2597X_BAT_OVP_ALM_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_01,
+ BQ2597X_BAT_OVP_ALM_MASK, val);
+ return ret;
+}
+
+static int bq2597x_enable_batocp(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_BAT_OCP_ENABLE;
+ else
+ val = BQ2597X_BAT_OCP_DISABLE;
+
+ val <<= BQ2597X_BAT_OCP_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_02,
+ BQ2597X_BAT_OCP_DIS_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_batocp_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_BAT_OCP_BASE)
+ threshold = BQ2597X_BAT_OCP_BASE;
+
+ val = (threshold - BQ2597X_BAT_OCP_BASE) / BQ2597X_BAT_OCP_LSB;
+
+ val <<= BQ2597X_BAT_OCP_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_02,
+ BQ2597X_BAT_OCP_MASK, val);
+ return ret;
+}
+
+static int bq2597x_enable_batocp_alarm(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_BAT_OCP_ALM_ENABLE;
+ else
+ val = BQ2597X_BAT_OCP_ALM_DISABLE;
+
+ val <<= BQ2597X_BAT_OCP_ALM_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_03,
+ BQ2597X_BAT_OCP_ALM_DIS_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_batocp_alarm_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_BAT_OCP_ALM_BASE)
+ threshold = BQ2597X_BAT_OCP_ALM_BASE;
+
+ val = (threshold - BQ2597X_BAT_OCP_ALM_BASE) / BQ2597X_BAT_OCP_ALM_LSB;
+
+ val <<= BQ2597X_BAT_OCP_ALM_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_03,
+ BQ2597X_BAT_OCP_ALM_MASK, val);
+ return ret;
+}
+
+
+static int bq2597x_set_busovp_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_BUS_OVP_BASE)
+ threshold = BQ2597X_BUS_OVP_BASE;
+
+ val = (threshold - BQ2597X_BUS_OVP_BASE) / BQ2597X_BUS_OVP_LSB;
+
+ val <<= BQ2597X_BUS_OVP_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_06,
+ BQ2597X_BUS_OVP_MASK, val);
+ return ret;
+}
+
+static int bq2597x_enable_busovp_alarm(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_BUS_OVP_ALM_ENABLE;
+ else
+ val = BQ2597X_BUS_OVP_ALM_DISABLE;
+
+ val <<= BQ2597X_BUS_OVP_ALM_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_07,
+ BQ2597X_BUS_OVP_ALM_DIS_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_busovp_alarm_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_BUS_OVP_ALM_BASE)
+ threshold = BQ2597X_BUS_OVP_ALM_BASE;
+
+ val = (threshold - BQ2597X_BUS_OVP_ALM_BASE) / BQ2597X_BUS_OVP_ALM_LSB;
+
+ val <<= BQ2597X_BUS_OVP_ALM_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_07,
+ BQ2597X_BUS_OVP_ALM_MASK, val);
+ return ret;
+}
+
+static int bq2597x_enable_busocp(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_BUS_OCP_ENABLE;
+ else
+ val = BQ2597X_BUS_OCP_DISABLE;
+
+ val <<= BQ2597X_BUS_OCP_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_08,
+ BQ2597X_BUS_OCP_DIS_MASK, val);
+ return ret;
+}
+
+
+static int bq2597x_set_busocp_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_BUS_OCP_BASE)
+ threshold = BQ2597X_BUS_OCP_BASE;
+
+ val = (threshold - BQ2597X_BUS_OCP_BASE) / BQ2597X_BUS_OCP_LSB;
+
+ val <<= BQ2597X_BUS_OCP_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_08,
+ BQ2597X_BUS_OCP_MASK, val);
+ return ret;
+}
+
+static int bq2597x_enable_busocp_alarm(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_BUS_OCP_ALM_ENABLE;
+ else
+ val = BQ2597X_BUS_OCP_ALM_DISABLE;
+
+ val <<= BQ2597X_BUS_OCP_ALM_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_09,
+ BQ2597X_BUS_OCP_ALM_DIS_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_busocp_alarm_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_BUS_OCP_ALM_BASE)
+ threshold = BQ2597X_BUS_OCP_ALM_BASE;
+
+ val = (threshold - BQ2597X_BUS_OCP_ALM_BASE) / BQ2597X_BUS_OCP_ALM_LSB;
+
+ val <<= BQ2597X_BUS_OCP_ALM_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_09,
+ BQ2597X_BUS_OCP_ALM_MASK, val);
+ return ret;
+}
+
+static int bq2597x_enable_batucp_alarm(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_BAT_UCP_ALM_ENABLE;
+ else
+ val = BQ2597X_BAT_UCP_ALM_DISABLE;
+
+ val <<= BQ2597X_BAT_UCP_ALM_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_04,
+ BQ2597X_BAT_UCP_ALM_DIS_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_batucp_alarm_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_BAT_UCP_ALM_BASE)
+ threshold = BQ2597X_BAT_UCP_ALM_BASE;
+
+ val = (threshold - BQ2597X_BAT_UCP_ALM_BASE) / BQ2597X_BAT_UCP_ALM_LSB;
+
+ val <<= BQ2597X_BAT_UCP_ALM_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_04,
+ BQ2597X_BAT_UCP_ALM_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_acovp_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold < BQ2597X_AC_OVP_BASE)
+ threshold = BQ2597X_AC_OVP_BASE;
+
+ if (threshold == BQ2597X_AC_OVP_6P5V)
+ val = 0x07;
+ else
+ val = (threshold - BQ2597X_AC_OVP_BASE) / BQ2597X_AC_OVP_LSB;
+
+ val <<= BQ2597X_AC_OVP_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_05,
+ BQ2597X_AC_OVP_MASK, val);
+
+ return ret;
+
+}
+
+static int bq2597x_set_vdrop_th(struct bq2597x *bq, int threshold)
+{
+ int ret;
+ u8 val;
+
+ if (threshold == 300)
+ val = BQ2597X_VDROP_THRESHOLD_300MV;
+ else
+ val = BQ2597X_VDROP_THRESHOLD_400MV;
+
+ val <<= BQ2597X_VDROP_THRESHOLD_SET_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_05,
+ BQ2597X_VDROP_THRESHOLD_SET_MASK,
+ val);
+
+ return ret;
+}
+
+static int bq2597x_set_vdrop_deglitch(struct bq2597x *bq, int us)
+{
+ int ret;
+ u8 val;
+
+ if (us == 8)
+ val = BQ2597X_VDROP_DEGLITCH_8US;
+ else
+ val = BQ2597X_VDROP_DEGLITCH_5MS;
+
+ val <<= BQ2597X_VDROP_DEGLITCH_SET_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_05,
+ BQ2597X_VDROP_DEGLITCH_SET_MASK,
+ val);
+ return ret;
+}
+
+static int bq2597x_enable_bat_therm(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_TSBAT_ENABLE;
+ else
+ val = BQ2597X_TSBAT_DISABLE;
+
+ val <<= BQ2597X_TSBAT_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_0C,
+ BQ2597X_TSBAT_DIS_MASK, val);
+ return ret;
+}
+
+/*
+ * the input threshold is the raw value that would write to register directly.
+ */
+static int bq2597x_set_bat_therm_th(struct bq2597x *bq, u8 threshold)
+{
+ int ret;
+
+ ret = bq2597x_write_byte(bq, BQ2597X_REG_29, threshold);
+ return ret;
+}
+
+static int bq2597x_enable_bus_therm(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_TSBUS_ENABLE;
+ else
+ val = BQ2597X_TSBUS_DISABLE;
+
+ val <<= BQ2597X_TSBUS_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_0C,
+ BQ2597X_TSBUS_DIS_MASK, val);
+ return ret;
+}
+
+/*
+ * the input threshold is the raw value that would write to register directly.
+ */
+static int bq2597x_set_bus_therm_th(struct bq2597x *bq, u8 threshold)
+{
+ int ret;
+
+ ret = bq2597x_write_byte(bq, BQ2597X_REG_28, threshold);
+ return ret;
+}
+
+
+static int bq2597x_enable_die_therm(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_TDIE_ENABLE;
+ else
+ val = BQ2597X_TDIE_DISABLE;
+
+ val <<= BQ2597X_TDIE_DIS_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_0C,
+ BQ2597X_TDIE_DIS_MASK, val);
+ return ret;
+}
+
+/*
+ * please be noted that the unit here is degC
+ */
+static int bq2597x_set_die_therm_th(struct bq2597x *bq, u8 threshold)
+{
+ int ret;
+ u8 val;
+
+ /*BE careful, LSB is here is 1/LSB, so we use multiply here*/
+ val = (threshold - BQ2597X_TDIE_ALM_BASE) * BQ2597X_TDIE_ALM_LSB;
+ val <<= BQ2597X_TDIE_ALM_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_2A,
+ BQ2597X_TDIE_ALM_MASK, val);
+ return ret;
+}
+
+static int bq2597x_enable_adc(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_ADC_ENABLE;
+ else
+ val = BQ2597X_ADC_DISABLE;
+
+ val <<= BQ2597X_ADC_EN_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_14,
+ BQ2597X_ADC_EN_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_adc_average(struct bq2597x *bq, bool avg)
+{
+ int ret;
+ u8 val;
+
+ if (avg)
+ val = BQ2597X_ADC_AVG_ENABLE;
+ else
+ val = BQ2597X_ADC_AVG_DISABLE;
+
+ val <<= BQ2597X_ADC_AVG_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_14,
+ BQ2597X_ADC_AVG_MASK, val);
+ return 0;
+}
+
+static int bq2597x_set_adc_scanrate(struct bq2597x *bq, bool oneshot)
+{
+ int ret;
+ u8 val;
+
+ if (oneshot)
+ val = BQ2597X_ADC_RATE_ONESHOT;
+ else
+ val = BQ2597X_ADC_RATE_CONTINOUS;
+
+ val <<= BQ2597X_ADC_RATE_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_14,
+ BQ2597X_ADC_EN_MASK, val);
+ return ret;
+}
+
+static int bq2597x_set_adc_bits(struct bq2597x *bq, int bits)
+{
+ int ret;
+ u8 val;
+
+ if (bits > 15)
+ bits = 15;
+ if (bits < 12)
+ bits = 12;
+ val = 15 - bits;
+
+ val <<= BQ2597X_ADC_SAMPLE_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_14,
+ BQ2597X_ADC_SAMPLE_MASK, val);
+ return ret;
+}
+
+#define ADC_REG_BASE 0x16
+static int bq2597x_set_adc_scan(struct bq2597x *bq, int channel, bool enable)
+{
+ int ret;
+ u8 reg;
+ u8 mask;
+ u8 shift;
+ u8 val;
+
+ if (channel > ADC_MAX_NUM)
+ return -EINVAL;
+
+ if (channel == ADC_IBUS) {
+ reg = BQ2597X_REG_14;
+ shift = BQ2597X_IBUS_ADC_DIS_SHIFT;
+ mask = BQ2597X_IBUS_ADC_DIS_MASK;
+ } else {
+ reg = BQ2597X_REG_15;
+ shift = 8 - channel;
+ mask = 1 << shift;
+ }
+
+ if (enable)
+ val = 0 << shift;
+ else
+ val = 1 << shift;
+
+ ret = bq2597x_update_bits(bq, reg, mask, val);
+
+ return ret;
+}
+
+static int sc8551_init_adc(struct bq2597x *bq)
+{
+ int ret;
+ /* improve adc accuracy */
+ ret = bq2597x_write_byte(bq, SC8551_REG_34, 0x01);
+ return ret;
+}
+
+static int bq2597x_set_alarm_int_mask(struct bq2597x *bq, u8 mask)
+{
+ int ret;
+ u8 val;
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_0F, &val);
+ if (ret)
+ return ret;
+
+ val |= mask;
+
+ ret = bq2597x_write_byte(bq, BQ2597X_REG_0F, val);
+
+ return ret;
+}
+
+static int bq2597x_set_fault_int_mask(struct bq2597x *bq, u8 mask)
+{
+ int ret;
+ u8 val;
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_12, &val);
+ if (ret)
+ return ret;
+
+ val |= mask;
+
+ ret = bq2597x_write_byte(bq, BQ2597X_REG_12, val);
+
+ return ret;
+}
+
+static int bq2597x_set_sense_resistor(struct bq2597x *bq, int r_mohm)
+{
+ int ret;
+ u8 val;
+
+ if (r_mohm == 2)
+ val = BQ2597X_SET_IBAT_SNS_RES_2MHM;
+ else if (r_mohm == 5)
+ val = BQ2597X_SET_IBAT_SNS_RES_5MHM;
+ else
+ return -EINVAL;
+
+ val <<= BQ2597X_SET_IBAT_SNS_RES_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_2B,
+ BQ2597X_SET_IBAT_SNS_RES_MASK,
+ val);
+ return ret;
+}
+
+static int bq2597x_set_ibus_ucp_thr(struct bq2597x *bq, int ibus_ucp_thr)
+{
+ int ret;
+ u8 val;
+
+ if (ibus_ucp_thr == 300)
+ val = BQ2597X_IBUS_UCP_RISE_300MA;
+ else if (ibus_ucp_thr == 500)
+ val = BQ2597X_IBUS_UCP_RISE_500MA;
+ else
+ return -EINVAL;
+
+ val <<= BQ2597X_IBUS_UCP_RISE_TH_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_2B,
+ BQ2597X_IBUS_UCP_RISE_TH_MASK,
+ val);
+ return ret;
+}
+
+static int bq2597x_enable_regulation(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_EN_REGULATION_ENABLE;
+ else
+ val = BQ2597X_EN_REGULATION_DISABLE;
+
+ val <<= BQ2597X_EN_REGULATION_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_2B,
+ BQ2597X_EN_REGULATION_MASK,
+ val);
+
+ return ret;
+
+}
+
+static int bq2597x_enable_ucp(struct bq2597x *bq, bool enable)
+{
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = BQ2597X_IBUS_LOW_DG_5MS;
+ else
+ val = BQ2597X_IBUS_LOW_DG_10US;
+
+ val <<= BQ2597X_IBUS_LOW_DG_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_2E,
+ BQ2597X_IBUS_LOW_DG_MASK,
+ val);
+
+ return ret;
+
+}
+
+static int bq2597x_set_ss_timeout(struct bq2597x *bq, int timeout)
+{
+ int ret;
+ u8 val;
+
+ switch (timeout) {
+ case 0:
+ val = BQ2597X_SS_TIMEOUT_DISABLE;
+ break;
+ case 12:
+ val = BQ2597X_SS_TIMEOUT_12P5MS;
+ break;
+ case 25:
+ val = BQ2597X_SS_TIMEOUT_25MS;
+ break;
+ case 50:
+ val = BQ2597X_SS_TIMEOUT_50MS;
+ break;
+ case 100:
+ val = BQ2597X_SS_TIMEOUT_100MS;
+ break;
+ case 400:
+ val = BQ2597X_SS_TIMEOUT_400MS;
+ break;
+ case 1500:
+ val = BQ2597X_SS_TIMEOUT_1500MS;
+ break;
+ case 100000:
+ val = BQ2597X_SS_TIMEOUT_100000MS;
+ break;
+ default:
+ val = BQ2597X_SS_TIMEOUT_DISABLE;
+ break;
+ }
+
+ val <<= BQ2597X_SS_TIMEOUT_SET_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_2B,
+ BQ2597X_SS_TIMEOUT_SET_MASK,
+ val);
+
+ return ret;
+}
+
+static int bq2597x_set_ibat_reg_th(struct bq2597x *bq, int th_ma)
+{
+ int ret;
+ u8 val;
+
+ if (th_ma == 200)
+ val = BQ2597X_IBAT_REG_200MA;
+ else if (th_ma == 300)
+ val = BQ2597X_IBAT_REG_300MA;
+ else if (th_ma == 400)
+ val = BQ2597X_IBAT_REG_400MA;
+ else if (th_ma == 500)
+ val = BQ2597X_IBAT_REG_500MA;
+ else
+ val = BQ2597X_IBAT_REG_500MA;
+
+ val <<= BQ2597X_IBAT_REG_SHIFT;
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_2C,
+ BQ2597X_IBAT_REG_MASK,
+ val);
+
+ return ret;
+
+}
+
+static int bq2597x_set_vbat_reg_th(struct bq2597x *bq, int th_mv)
+{
+ int ret;
+ u8 val;
+
+ if (th_mv == 50)
+ val = BQ2597X_VBAT_REG_50MV;
+ else if (th_mv == 100)
+ val = BQ2597X_VBAT_REG_100MV;
+ else if (th_mv == 150)
+ val = BQ2597X_VBAT_REG_150MV;
+ else
+ val = BQ2597X_VBAT_REG_200MV;
+
+ val <<= BQ2597X_VBAT_REG_SHIFT;
+
+ ret = bq2597x_update_bits(bq, BQ2597X_REG_2C,
+ BQ2597X_VBAT_REG_MASK,
+ val);
+
+ return ret;
+}
+
+static int bq2597x_get_work_mode(struct bq2597x *bq, int *mode)
+{
+ int ret;
+ u8 val;
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_0C, &val);
+
+ if (ret) {
+ bq_err("Failed to read operation mode register\n");
+ return ret;
+ }
+
+ val = (val & BQ2597X_MS_MASK) >> BQ2597X_MS_SHIFT;
+ if (val == BQ2597X_MS_MASTER)
+ *mode = BQ25970_ROLE_MASTER;
+ else if (val == BQ2597X_MS_SLAVE)
+ *mode = BQ25970_ROLE_SLAVE;
+ else
+ *mode = BQ25970_ROLE_STDALONE;
+
+ bq_info("work mode:%s\n", *mode == BQ25970_ROLE_STDALONE ? "Standalone" :
+ (*mode == BQ25970_ROLE_SLAVE ? "Slave" : "Master"));
+ return ret;
+}
+
+static int bq2597x_detect_device(struct bq2597x *bq)
+{
+ int ret;
+ u8 data;
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_13, &data);
+ if (ret == 0) {
+ bq->part_no = (data & BQ2597X_DEV_ID_MASK);
+ bq->part_no >>= BQ2597X_DEV_ID_SHIFT;
+
+ pr_err("detect device:%d\n", data);
+ if (data == SC8551_DEVICE_ID || data == SC8551A_DEVICE_ID)
+ bq->chip_vendor = SC8551;
+ else if (data == BQ25968_DEV_ID)
+ bq->chip_vendor = BQ25968;
+ else
+ bq->chip_vendor = BQ25970;
+ }
+
+ return ret;
+}
+
+static int bq2597x_parse_dt(struct bq2597x *bq, struct device *dev)
+{
+ int ret;
+ struct device_node *np = dev->of_node;
+
+ bq->cfg = devm_kzalloc(dev, sizeof(struct bq2597x_cfg),
+ GFP_KERNEL);
+
+ if (!bq->cfg)
+ return -ENOMEM;
+
+ bq->cfg->bat_ovp_disable = of_property_read_bool(np,
+ "ti,bq2597x,bat-ovp-disable");
+ bq->cfg->bat_ocp_disable = of_property_read_bool(np,
+ "ti,bq2597x,bat-ocp-disable");
+ bq->cfg->bat_ovp_alm_disable = of_property_read_bool(np,
+ "ti,bq2597x,bat-ovp-alarm-disable");
+ bq->cfg->bat_ocp_alm_disable = of_property_read_bool(np,
+ "ti,bq2597x,bat-ocp-alarm-disable");
+ bq->cfg->bus_ocp_disable = of_property_read_bool(np,
+ "ti,bq2597x,bus-ocp-disable");
+ bq->cfg->bus_ovp_alm_disable = of_property_read_bool(np,
+ "ti,bq2597x,bus-ovp-alarm-disable");
+ bq->cfg->bus_ocp_alm_disable = of_property_read_bool(np,
+ "ti,bq2597x,bus-ocp-alarm-disable");
+ bq->cfg->bat_ucp_alm_disable = of_property_read_bool(np,
+ "ti,bq2597x,bat-ucp-alarm-disable");
+ bq->cfg->bat_therm_disable = of_property_read_bool(np,
+ "ti,bq2597x,bat-therm-disable");
+ bq->cfg->bus_therm_disable = of_property_read_bool(np,
+ "ti,bq2597x,bus-therm-disable");
+ bq->cfg->die_therm_disable = of_property_read_bool(np,
+ "ti,bq2597x,die-therm-disable");
+
+ ret = of_property_read_u32(np, "ti,bq2597x,bat-ovp-threshold",
+ &bq->cfg->bat_ovp_th);
+ if (ret) {
+ bq_err("failed to read bat-ovp-threshold\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "ti,bq2597x,bat-ovp-alarm-threshold",
+ &bq->cfg->bat_ovp_alm_th);
+ if (ret) {
+ bq_err("failed to read bat-ovp-alarm-threshold\n");
+ return ret;
+ }
+ /*ret = of_property_read_u32(np, "ti,bq2597x,bat-ocp-threshold",
+ &bq->cfg->bat_ocp_th);
+ if (ret) {
+ bq_err("failed to read bat-ocp-threshold\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "ti,bq2597x,bat-ocp-alarm-threshold",
+ &bq->cfg->bat_ocp_alm_th);
+ if (ret) {
+ bq_err("failed to read bat-ocp-alarm-threshold\n");
+ return ret;
+ }*/
+ ret = of_property_read_u32(np, "ti,bq2597x,bus-ovp-threshold",
+ &bq->cfg->bus_ovp_th);
+ if (ret) {
+ bq_err("failed to read bus-ovp-threshold\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "ti,bq2597x,bus-ovp-alarm-threshold",
+ &bq->cfg->bus_ovp_alm_th);
+ if (ret) {
+ bq_err("failed to read bus-ovp-alarm-threshold\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "ti,bq2597x,bus-ocp-threshold",
+ &bq->cfg->bus_ocp_th);
+ if (ret) {
+ bq_err("failed to read bus-ocp-threshold\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "ti,bq2597x,bus-ocp-alarm-threshold",
+ &bq->cfg->bus_ocp_alm_th);
+ if (ret) {
+ bq_err("failed to read bus-ocp-alarm-threshold\n");
+ return ret;
+ }
+ /*ret = of_property_read_u32(np, "ti,bq2597x,bat-ucp-alarm-threshold",
+ &bq->cfg->bat_ucp_alm_th);
+ if (ret) {
+ bq_err("failed to read bat-ucp-alarm-threshold\n");
+ return ret;
+ }*/
+ ret = of_property_read_u32(np, "ti,bq2597x,bat-therm-threshold",
+ &bq->cfg->bat_therm_th);
+ if (ret) {
+ bq_err("failed to read bat-therm-threshold\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "ti,bq2597x,bus-therm-threshold",
+ &bq->cfg->bus_therm_th);
+ if (ret) {
+ bq_err("failed to read bus-therm-threshold\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "ti,bq2597x,die-therm-threshold",
+ &bq->cfg->die_therm_th);
+ if (ret) {
+ bq_err("failed to read die-therm-threshold\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "ti,bq2597x,ac-ovp-threshold",
+ &bq->cfg->ac_ovp_th);
+ if (ret) {
+ bq_err("failed to read ac-ovp-threshold\n");
+ return ret;
+ }
+
+ if (bq->chip_vendor == SC8551) {
+ ret = of_property_read_u32(np, "sc8551,ac-ovp-threshold",
+ &bq->cfg->ac_ovp_th);
+ if (ret) {
+ bq_err("failed to read sc8551 ac-ovp-threshold\n");
+ return ret;
+ }
+ }
+
+ /*ret = of_property_read_u32(np, "ti,bq2597x,sense-resistor-mohm",
+ &bq->cfg->sense_r_mohm);
+ if (ret) {
+ bq_err("failed to read sense-resistor-mohm\n");
+ return ret;
+ }*/
+
+
+ return 0;
+}
+
+static int bq2597x_init_protection(struct bq2597x *bq)
+{
+ int ret;
+
+ ret = bq2597x_enable_batovp(bq, !bq->cfg->bat_ovp_disable);
+ bq_info("%s bat ovp %s\n",
+ bq->cfg->bat_ovp_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_batocp(bq, !bq->cfg->bat_ocp_disable);
+ bq_info("%s bat ocp %s\n",
+ bq->cfg->bat_ocp_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_batovp_alarm(bq, !bq->cfg->bat_ovp_alm_disable);
+ bq_info("%s bat ovp alarm %s\n",
+ bq->cfg->bat_ovp_alm_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_batocp_alarm(bq, !bq->cfg->bat_ocp_alm_disable);
+ bq_info("%s bat ocp alarm %s\n",
+ bq->cfg->bat_ocp_alm_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_batucp_alarm(bq, !bq->cfg->bat_ucp_alm_disable);
+ bq_info("%s bat ocp alarm %s\n",
+ bq->cfg->bat_ucp_alm_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_busovp_alarm(bq, !bq->cfg->bus_ovp_alm_disable);
+ bq_info("%s bus ovp alarm %s\n",
+ bq->cfg->bus_ovp_alm_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_busocp(bq, !bq->cfg->bus_ocp_disable);
+ bq_info("%s bus ocp %s\n",
+ bq->cfg->bus_ocp_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_busocp_alarm(bq, !bq->cfg->bus_ocp_alm_disable);
+ bq_info("%s bus ocp alarm %s\n",
+ bq->cfg->bus_ocp_alm_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_bat_therm(bq, !bq->cfg->bat_therm_disable);
+ bq_info("%s bat therm %s\n",
+ bq->cfg->bat_therm_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_bus_therm(bq, !bq->cfg->bus_therm_disable);
+ bq_info("%s bus therm %s\n",
+ bq->cfg->bus_therm_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_enable_die_therm(bq, !bq->cfg->die_therm_disable);
+ bq_info("%s die therm %s\n",
+ bq->cfg->die_therm_disable ? "disable" : "enable",
+ !ret ? "successfullly" : "failed");
+
+ ret = bq2597x_set_batovp_th(bq, bq->cfg->bat_ovp_th);
+ bq_info("set bat ovp th %d %s\n", bq->cfg->bat_ovp_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_batovp_alarm_th(bq, bq->cfg->bat_ovp_alm_th);
+ bq_info("set bat ovp alarm threshold %d %s\n", bq->cfg->bat_ovp_alm_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_batocp_th(bq, bq->cfg->bat_ocp_th);
+ bq_info("set bat ocp threshold %d %s\n", bq->cfg->bat_ocp_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_batocp_alarm_th(bq, bq->cfg->bat_ocp_alm_th);
+ bq_info("set bat ocp alarm threshold %d %s\n", bq->cfg->bat_ocp_alm_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_busovp_th(bq, bq->cfg->bus_ovp_th);
+ bq_info("set bus ovp threshold %d %s\n", bq->cfg->bus_ovp_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_busovp_alarm_th(bq, bq->cfg->bus_ovp_alm_th);
+ bq_info("set bus ovp alarm threshold %d %s\n", bq->cfg->bus_ovp_alm_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_busocp_th(bq, bq->cfg->bus_ocp_th);
+ bq_info("set bus ocp threshold %d %s\n", bq->cfg->bus_ocp_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_busocp_alarm_th(bq, bq->cfg->bus_ocp_alm_th);
+ bq_info("set bus ocp alarm th %d %s\n", bq->cfg->bus_ocp_alm_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_batucp_alarm_th(bq, bq->cfg->bat_ucp_alm_th);
+ bq_info("set bat ucp threshold %d %s\n", bq->cfg->bat_ucp_alm_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_bat_therm_th(bq, bq->cfg->bat_therm_th);
+ bq_info("set die therm threshold %d %s\n", bq->cfg->bat_therm_th,
+ !ret ? "successfully" : "failed");
+ ret = bq2597x_set_bus_therm_th(bq, bq->cfg->bus_therm_th);
+ bq_info("set bus therm threshold %d %s\n", bq->cfg->bus_therm_th,
+ !ret ? "successfully" : "failed");
+ ret = bq2597x_set_die_therm_th(bq, bq->cfg->die_therm_th);
+ bq_info("set die therm threshold %d %s\n", bq->cfg->die_therm_th,
+ !ret ? "successfully" : "failed");
+
+ ret = bq2597x_set_acovp_th(bq, bq->cfg->ac_ovp_th);
+ bq_info("set ac ovp threshold %d %s\n", bq->cfg->ac_ovp_th,
+ !ret ? "successfully" : "failed");
+
+ return 0;
+}
+
+static int bq2597x_init_adc(struct bq2597x *bq)
+{
+ bq2597x_set_adc_scanrate(bq, false);
+ bq2597x_set_adc_bits(bq, 13);
+ bq2597x_set_adc_average(bq, true);
+ bq2597x_set_adc_scan(bq, ADC_IBUS, true);
+ bq2597x_set_adc_scan(bq, ADC_VBUS, true);
+ bq2597x_set_adc_scan(bq, ADC_VOUT, false);
+ bq2597x_set_adc_scan(bq, ADC_VBAT, true);
+ bq2597x_set_adc_scan(bq, ADC_IBAT, false);
+ bq2597x_set_adc_scan(bq, ADC_TBUS, false);
+ bq2597x_set_adc_scan(bq, ADC_TBAT, false);
+ bq2597x_set_adc_scan(bq, ADC_TDIE, false);
+ bq2597x_set_adc_scan(bq, ADC_VAC, true);
+
+ if (bq->chip_vendor == SC8551)
+ sc8551_init_adc(bq);
+
+ bq2597x_enable_adc(bq, true);
+
+ return 0;
+}
+
+static int bq2597x_init_int_src(struct bq2597x *bq)
+{
+ int ret;
+ /*TODO:be careful ts bus and ts bat alarm bit mask is in
+ * fault mask register, so you need call
+ * bq2597x_set_fault_int_mask for tsbus and tsbat alarm
+ */
+ ret = bq2597x_set_alarm_int_mask(bq, ADC_DONE
+ | BAT_OCP_ALARM | BAT_UCP_ALARM
+ | BAT_OVP_ALARM);
+ if (ret) {
+ bq_err("failed to set alarm mask:%d\n", ret);
+ return ret;
+ }
+//#if 0
+ ret = bq2597x_set_fault_int_mask(bq,
+ TS_BUS_FAULT | TS_DIE_FAULT | TS_BAT_FAULT | BAT_OCP_FAULT);
+ if (ret) {
+ bq_err("failed to set fault mask:%d\n", ret);
+ return ret;
+ }
+//#endif
+ return ret;
+}
+
+static int bq2597x_init_regulation(struct bq2597x *bq)
+{
+ bq2597x_set_ibat_reg_th(bq, 200);
+ bq2597x_set_vbat_reg_th(bq, 50);
+
+ bq2597x_set_vdrop_deglitch(bq, 5000);
+ bq2597x_set_vdrop_th(bq, 400);
+
+ bq2597x_enable_regulation(bq, true);
+
+ return 0;
+}
+
+static int bq2597x_init_device(struct bq2597x *bq)
+{
+ int ret;
+ u8 val;
+ bq2597x_enable_wdt(bq, false);
+
+ bq2597x_set_ss_timeout(bq, 1500);
+ bq2597x_set_ibus_ucp_thr(bq, 300);
+ bq2597x_enable_ucp(bq,1);
+ bq2597x_set_sense_resistor(bq, bq->cfg->sense_r_mohm);
+
+ bq2597x_init_protection(bq);
+ bq2597x_init_adc(bq);
+ bq2597x_init_int_src(bq);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_13, &val);
+ bq_err("Bq device ID = 0x%02X\n", val);
+ if (!ret && val == BQ25968_DEV_ID) {
+ bq_err("Bq device ID = 0x%02X\n", val);
+ return 0;
+ }
+
+ bq2597x_init_regulation(bq);
+
+ return 0;
+}
+
+static int bq2597x_set_present(struct bq2597x *bq, bool present)
+{
+ if (present != bq->usb_present) {
+ bq_info("changed usb_present [%d] -> [%d]\n", bq->usb_present, present);
+ if (present) {
+ bq2597x_init_device(bq);
+ }
+ bq->usb_present = present;
+ }
+
+ return 0;
+}
+
+static ssize_t bq2597x_show_registers(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bq2597x *bq = dev_get_drvdata(dev);
+ u8 addr;
+ u8 val;
+ u8 tmpbuf[300];
+ int len;
+ int idx = 0;
+ int ret;
+
+ idx = snprintf(buf, PAGE_SIZE, "%s:\n", "bq25970");
+ for (addr = 0x0; addr <= 0x36; addr++) {
+ ret = bq2597x_read_byte(bq, addr, &val);
+ if (ret == 0) {
+ len = snprintf(tmpbuf, PAGE_SIZE - idx,
+ "Reg[%.2X] = 0x%.2x\n", addr, val);
+ memcpy(&buf[idx], tmpbuf, len);
+ idx += len;
+ }
+ }
+
+ return idx;
+}
+
+static ssize_t bq2597x_store_register(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct bq2597x *bq = dev_get_drvdata(dev);
+ int ret;
+ unsigned int reg;
+ unsigned int val;
+
+ ret = sscanf(buf, "%x %x", &reg, &val);
+ if (ret == 2 && reg <= 0x36)
+ bq2597x_write_byte(bq, (unsigned char)reg, (unsigned char)val);
+
+ return count;
+}
+
+static DEVICE_ATTR(registers, 0660, bq2597x_show_registers, bq2597x_store_register);
+
+#ifdef CONFIG_DUAL_BQ2597X
+static ssize_t bq2597x_show_diff_ti_bus_current(struct device *dev,struct device_attribute *attr,char *buf)
+{
+ struct bq2597x *bq = dev_get_drvdata(dev);
+ static struct power_supply *bq2597x_slave = NULL;
+ int diff_ti_bus_current = -1;
+ int ti_bus_current_master = 0;
+ int ti_bus_current_slave = 0;
+ int result = 0;
+ int rc;
+ int len;
+ union power_supply_propval pval = {
+ 0,
+ };
+ if(bq->mode == BQ25970_ROLE_MASTER){
+ /*get bq2597x_slave ti_bus_current*/
+ if(!bq2597x_slave){
+ bq2597x_slave = power_supply_get_by_name("bq2597x-slave");
+ if(!bq2597x_slave){
+ bq_dbg("failed get bq2597x-slave \n");
+ return 0;
+ }
+ bq_dbg("success get bq2597x-slave \n");
+ }
+ rc = power_supply_get_property(bq2597x_slave,POWER_SUPPLY_PROP_TI_BUS_CURRENT,&pval);
+ if (rc < 0) {
+ bq_dbg("failed get bq2597x-slave ti_bus_current \n");
+ return -EINVAL;
+ }
+ ti_bus_current_slave = pval.intval;
+ /*get bq2597x_master ti_bus_current*/
+ rc = bq2597x_get_adc_data(bq, ADC_IBUS, &result);
+ if (!rc)
+ ti_bus_current_master = result;
+ else
+ ti_bus_current_master = bq->ibus_curr;
+ /* get diff_ti_bus_current = ti_bus_current_master - ti_bus_current_slave */
+ if(ti_bus_current_master > ti_bus_current_slave)
+ diff_ti_bus_current = ti_bus_current_master - ti_bus_current_slave;
+ else
+ diff_ti_bus_current = ti_bus_current_slave - ti_bus_current_master;
+ } else if (bq->mode == BQ25970_ROLE_SLAVE) {
+ diff_ti_bus_current = -1;
+ }
+ len = snprintf(buf, 1024, "%d\n", diff_ti_bus_current);
+ return len;
+}
+static DEVICE_ATTR(diff_ti_bus_current,0660,bq2597x_show_diff_ti_bus_current,NULL);
+#endif
+static struct attribute *bq2597x_attributes[] = {
+ &dev_attr_registers.attr,
+#ifdef CONFIG_DUAL_BQ2597X
+ &dev_attr_diff_ti_bus_current.attr,
+#endif
+ NULL,
+};
+
+static const struct attribute_group bq2597x_attr_group = {
+ .attrs = bq2597x_attributes,
+};
+
+static enum power_supply_property bq2597x_charger_props[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+};
+static void bq2597x_check_alarm_status(struct bq2597x *bq);
+static void bq2597x_check_fault_status(struct bq2597x *bq);
+
+static int bq2597x_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bq2597x *bq = power_supply_get_drvdata(psy);
+ bool result;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ bq2597x_check_charge_enabled(bq, &result);
+ val->intval = result;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = bq->usb_present;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ ret = bq2597x_get_work_mode(bq, &bq->mode);
+ if (ret) {
+ val->strval = "unknown";
+ } else {
+ if (bq->mode == BQ25970_ROLE_MASTER)
+ val->strval = "bq2597x-master";
+ else if (bq->mode == BQ25970_ROLE_SLAVE)
+ val->strval = "bq2597x-slave";
+ else
+ val->strval = "bq2597x-standalone";
+ }
+ break;
+ default:
+ return -EINVAL;
+
+ }
+
+ return 0;
+}
+
+static int bq2597x_charger_set_property(struct power_supply *psy,
+ enum power_supply_property prop,
+ const union power_supply_propval *val)
+{
+ struct bq2597x *bq = power_supply_get_drvdata(psy);
+
+ switch (prop) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ bq2597x_set_present(bq, !!val->intval);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int bq2597x_charger_is_writeable(struct power_supply *psy,
+ enum power_supply_property prop)
+{
+ int ret;
+
+ switch (prop) {
+ //case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+ //case POWER_SUPPLY_PROP_TI_SET_BUS_PROTECTION_FOR_QC3:
+ // ret = 1;
+ // break;
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int bq2597x_psy_register(struct bq2597x *bq)
+{
+ bq->psy_cfg.drv_data = bq;
+ bq->psy_cfg.of_node = bq->dev->of_node;
+
+ if (bq->mode == BQ25970_ROLE_MASTER)
+ bq->psy_desc.name = "bq2597x-master";
+ else if (bq->mode == BQ25970_ROLE_SLAVE)
+ bq->psy_desc.name = "bq2597x-slave";
+ else
+ bq->psy_desc.name = "bq2597x-standalone";
+
+ bq->psy_desc.type = POWER_SUPPLY_TYPE_USB;
+ bq->psy_desc.usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) |
+ BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_ACA) |
+ BIT(POWER_SUPPLY_USB_TYPE_C) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) |
+ BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID),
+ bq->psy_desc.properties = bq2597x_charger_props;
+ bq->psy_desc.num_properties = ARRAY_SIZE(bq2597x_charger_props);
+ bq->psy_desc.get_property = bq2597x_charger_get_property;
+ bq->psy_desc.set_property = bq2597x_charger_set_property;
+ bq->psy_desc.property_is_writeable = bq2597x_charger_is_writeable;
+
+ bq->fc2_psy = devm_power_supply_register(bq->dev,
+ &bq->psy_desc, &bq->psy_cfg);
+ if (IS_ERR(bq->fc2_psy)) {
+ bq_err("failed to register fc2_psy\n");
+ return PTR_ERR(bq->fc2_psy);
+ }
+
+ bq_info("%s power supply register successfully\n", bq->psy_desc.name);
+
+ return 0;
+}
+
+static void bq2597x_dump_important_regs(struct bq2597x *bq)
+{
+
+ int ret;
+ u8 val;
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_0A, &val);
+ if (!ret)
+ bq_err("dump converter state Reg [%02X] = 0x%02X\n",
+ BQ2597X_REG_0A, val);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_0D, &val);
+ if (!ret)
+ bq_err("dump int stat Reg[%02X] = 0x%02X\n",
+ BQ2597X_REG_0D, val);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_0E, &val);
+ if (!ret)
+ bq_err("dump int flag Reg[%02X] = 0x%02X\n",
+ BQ2597X_REG_0E, val);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_10, &val);
+ if (!ret)
+ bq_err("dump fault stat Reg[%02X] = 0x%02X\n",
+ BQ2597X_REG_10, val);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_11, &val);
+ if (!ret)
+ bq_err("dump fault flag Reg[%02X] = 0x%02X\n",
+ BQ2597X_REG_11, val);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_2D, &val);
+ if (!ret)
+ bq_err("dump regulation flag Reg[%02X] = 0x%02X\n",
+ BQ2597X_REG_2D, val);
+}
+
+static void bq2597x_check_alarm_status(struct bq2597x *bq)
+{
+ int ret;
+ u8 flag = 0;
+ u8 stat = 0;
+
+ mutex_lock(&bq->data_lock);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_08, &flag);
+ if (!ret && (flag & BQ2597X_IBUS_UCP_FALL_FLAG_MASK))
+ bq_info("UCP_FLAG =0x%02X\n",
+ !!(flag & BQ2597X_IBUS_UCP_FALL_FLAG_MASK));
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_2D, &flag);
+ if (!ret && (flag & BQ2597X_VDROP_OVP_FLAG_MASK))
+ bq_info("VDROP_OVP_FLAG =0x%02X\n",
+ !!(flag & BQ2597X_VDROP_OVP_FLAG_MASK));
+
+ /*read to clear alarm flag*/
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_0E, &flag);
+ if (!ret && flag)
+ bq_info("INT_FLAG =0x%02X\n", flag);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_0D, &stat);
+ if (!ret && stat != bq->prev_alarm) {
+ bq_info("INT_STAT = 0X%02x\n", stat);
+ bq->prev_alarm = stat;
+ bq->bat_ovp_alarm = !!(stat & BAT_OVP_ALARM);
+ bq->bat_ocp_alarm = !!(stat & BAT_OCP_ALARM);
+ bq->bus_ovp_alarm = !!(stat & BUS_OVP_ALARM);
+ bq->bus_ocp_alarm = !!(stat & BUS_OCP_ALARM);
+ bq->batt_present = !!(stat & VBAT_INSERT);
+ bq->vbus_present = !!(stat & VBUS_INSERT);
+ bq->bat_ucp_alarm = !!(stat & BAT_UCP_ALARM);
+ }
+
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_08, &stat);
+ if (!ret && (stat & 0x50))
+ bq_err("Reg[08]BUS_UCPOVP = 0x%02X\n", stat);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_0A, &stat);
+ if (!ret && (stat & 0x02))
+ bq_err("Reg[0A]CONV_OCP = 0x%02X\n", stat);
+
+ mutex_unlock(&bq->data_lock);
+}
+
+static void bq2597x_check_fault_status(struct bq2597x *bq)
+{
+ int ret;
+ u8 flag = 0;
+ u8 stat = 0;
+ bool changed = false;
+
+ mutex_lock(&bq->data_lock);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_10, &stat);
+ if (!ret && stat)
+ bq_err("FAULT_STAT = 0x%02X\n", stat);
+
+ ret = bq2597x_read_byte(bq, BQ2597X_REG_11, &flag);
+ if (!ret && flag)
+ bq_err("FAULT_FLAG = 0x%02X\n", flag);
+
+ if (!ret && flag != bq->prev_fault) {
+ changed = true;
+ bq->prev_fault = flag;
+ bq->bat_ovp_fault = !!(flag & BAT_OVP_FAULT);
+ bq->bat_ocp_fault = !!(flag & BAT_OCP_FAULT);
+ bq->bus_ovp_fault = !!(flag & BUS_OVP_FAULT);
+ bq->bus_ocp_fault = !!(flag & BUS_OCP_FAULT);
+ bq->bat_therm_fault = !!(flag & TS_BAT_FAULT);
+ bq->bus_therm_fault = !!(flag & TS_BUS_FAULT);
+
+ bq->bat_therm_alarm = !!(flag & TBUS_TBAT_ALARM);
+ bq->bus_therm_alarm = !!(flag & TBUS_TBAT_ALARM);
+ }
+
+ mutex_unlock(&bq->data_lock);
+}
+
+/*
+ * interrupt does nothing, just info event chagne, other module could get info
+ * through power supply interface
+ */
+static irqreturn_t bq2597x_charger_interrupt(int irq, void *dev_id)
+{
+ struct bq2597x *bq = dev_id;
+
+ bq_info("INT OCCURED\n");
+
+ mutex_lock(&bq->irq_complete);
+ bq->irq_waiting = true;
+ if (!bq->resume_completed) {
+ dev_dbg(bq->dev, "IRQ triggered before device-resume\n");
+ if (!bq->irq_disabled) {
+ disable_irq_nosync(irq);
+ bq->irq_disabled = true;
+ }
+ bq->irq_waiting = false;
+ mutex_unlock(&bq->irq_complete);
+ return IRQ_HANDLED;
+ }
+ bq->irq_waiting = false;
+ /* dump some impoartant registers and alarm fault status for debug */
+ bq2597x_dump_important_regs(bq);
+ bq2597x_check_alarm_status(bq);
+ bq2597x_check_fault_status(bq);
+ mutex_unlock(&bq->irq_complete);
+
+ /* power_supply_changed(bq->fc2_psy); */
+
+ return IRQ_HANDLED;
+}
+
+
+static void determine_initial_status(struct bq2597x *bq)
+{
+ if (bq->client->irq)
+ bq2597x_charger_interrupt(bq->client->irq, bq);
+}
+
+static int show_registers(struct seq_file *m, void *data)
+{
+ struct bq2597x *bq = m->private;
+ u8 addr;
+ int ret;
+ u8 val;
+
+ for (addr = 0x0; addr <= 0x36; addr++) {
+ ret = bq2597x_read_byte(bq, addr, &val);
+ if (!ret)
+ seq_printf(m, "Reg[%02X] = 0x%02X\n", addr, val);
+ }
+ return 0;
+}
+
+
+static int reg_debugfs_open(struct inode *inode, struct file *file)
+{
+ struct bq2597x *bq = inode->i_private;
+
+ return single_open(file, show_registers, bq);
+}
+
+
+static const struct file_operations reg_debugfs_ops = {
+ .owner = THIS_MODULE,
+ .open = reg_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void create_debugfs_entry(struct bq2597x *bq)
+{
+ if (bq->mode == BQ25970_ROLE_MASTER)
+ bq->debug_root = debugfs_create_dir("bq2597x-master", NULL);
+ else if (bq->mode == BQ25970_ROLE_SLAVE)
+ bq->debug_root = debugfs_create_dir("bq2597x-slave", NULL);
+ else
+ bq->debug_root = debugfs_create_dir("bq2597x-standalone", NULL);
+
+ if (!bq->debug_root)
+ bq_err("Failed to create debug dir\n");
+
+ if (bq->debug_root) {
+ debugfs_create_file("registers",
+ S_IFREG | S_IRUGO,
+ bq->debug_root, bq, &reg_debugfs_ops);
+
+ debugfs_create_x32("skip_reads",
+ S_IFREG | S_IWUSR | S_IRUGO,
+ bq->debug_root,
+ &(bq->skip_reads));
+ debugfs_create_x32("skip_writes",
+ S_IFREG | S_IWUSR | S_IRUGO,
+ bq->debug_root,
+ &(bq->skip_writes));
+ }
+}
+
+static struct of_device_id bq2597x_charger_match_table[] = {
+ {
+ .compatible = "ti,bq2597x-standalone",
+ .data = &bq2597x_mode_data[BQ25970_STDALONE],
+ },
+ {
+ .compatible = "ti,bq2597x-master",
+ .data = &bq2597x_mode_data[BQ25970_MASTER],
+ },
+
+ {
+ .compatible = "ti,bq2597x-slave",
+ .data = &bq2597x_mode_data[BQ25970_SLAVE],
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bq2597x_charger_match_table);
+
+static int bq2597x_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct bq2597x *chip = container_of(nb, struct bq2597x, nb);
+ struct power_supply *psy = v;
+ union power_supply_propval propval;
+
+ if (psy == chip->typec_psy) {
+ power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE, &propval);
+
+ chip->charge_state = propval.intval;
+ chip->usb_present = !!propval.intval;
+
+ power_supply_changed(chip->fc2_psy);
+
+ if (chip->usb_present) {
+ msleep(30000);
+ bq2597x_enable_charge(chip, true);
+ bq2597x_check_charge_enabled(chip, &chip->charge_enabled);
+ }
+ else {
+ bq2597x_enable_charge(chip, false);
+ bq2597x_check_charge_enabled(chip, &chip->charge_enabled);
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static int bq2597x_charger_probe(struct i2c_client *client)
+{
+ struct bq2597x *bq;
+ const struct of_device_id *match;
+ struct device_node *node = client->dev.of_node;
+ int ret;
+
+ bq = devm_kzalloc(&client->dev, sizeof(struct bq2597x), GFP_KERNEL);
+ if (!bq)
+ return -ENOMEM;
+
+ bq->dev = &client->dev;
+
+ bq->client = client;
+ i2c_set_clientdata(client, bq);
+
+ mutex_init(&bq->i2c_rw_lock);
+ mutex_init(&bq->data_lock);
+ mutex_init(&bq->charging_disable_lock);
+ mutex_init(&bq->irq_complete);
+
+ bq->resume_completed = true;
+ bq->irq_waiting = false;
+
+ ret = bq2597x_detect_device(bq);
+ if (ret) {
+ bq_err("No bq2597x device found!\n");
+ return -ENODEV;
+ }
+
+ match = of_match_node(bq2597x_charger_match_table, node);
+ if (match == NULL) {
+ bq_err("device tree match not found!\n");
+ return -ENODEV;
+ }
+
+ bq2597x_get_work_mode(bq, &bq->mode);
+
+ if (bq->mode != *(int *)match->data) {
+ bq_err("device operation mode mismatch with dts configuration\n");
+ return -EINVAL;
+ }
+
+ ret = bq2597x_parse_dt(bq, &client->dev);
+ if (ret)
+ return -EIO;
+
+ ret = bq2597x_init_device(bq);
+ if (ret) {
+ bq_err("Failed to init device\n");
+ return ret;
+ }
+
+ determine_initial_status(bq);
+
+ ret = bq2597x_psy_register(bq);
+ if (ret)
+ return ret;
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, bq2597x_charger_interrupt,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "bq2597x charger irq", bq);
+ if (ret < 0) {
+ bq_err("request irq for irq=%d failed, ret =%d\n",
+ client->irq, ret);
+ goto err_1;
+ }
+ /* no need to enable this irq as a wakeup source */
+ /* enable_irq_wake(client->irq); */
+ }
+
+ device_init_wakeup(bq->dev, 1);
+ create_debugfs_entry(bq);
+
+ ret = sysfs_create_group(&bq->dev->kobj, &bq2597x_attr_group);
+ if (ret) {
+ bq_err("failed to register sysfs. err: %d\n", ret);
+ goto err_1;
+ }
+
+ /* determine_initial_status(bq); */
+
+ bq_info("bq2597x probe successfully, Part Num:%d\n!",
+ bq->part_no);
+
+ bq->typec_psy = power_supply_get_by_name(
+ "tcpm-source-psy-c440000.spmi:pmic@2:typec@1500");
+ if (IS_ERR(bq->typec_psy)) {
+ ret = PTR_ERR(bq->typec_psy);
+ dev_warn(bq->dev, "Failed to get USB Type-C: %d\n", ret);
+ bq->typec_psy = NULL;
+ }
+
+ if (bq->typec_psy) {
+ bq->nb.notifier_call = bq2597x_notifier_call;
+ ret = power_supply_reg_notifier(&bq->nb);
+ if (ret) {
+ dev_err(bq->dev,
+ "Failed to register notifier: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+
+err_1:
+ power_supply_unregister(bq->fc2_psy);
+ return ret;
+}
+
+
+static inline bool is_device_suspended(struct bq2597x *bq)
+{
+ return !bq->resume_completed;
+}
+
+static int bq2597x_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bq2597x *bq = i2c_get_clientdata(client);
+
+ mutex_lock(&bq->irq_complete);
+ bq->resume_completed = false;
+ mutex_unlock(&bq->irq_complete);
+ bq2597x_enable_adc(bq, false);
+ bq_err("Suspend successfully!");
+
+ return 0;
+}
+
+static int bq2597x_suspend_noirq(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bq2597x *bq = i2c_get_clientdata(client);
+
+ if (bq->irq_waiting) {
+ pr_err_ratelimited("Aborting suspend, an interrupt was detected while suspending\n");
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static int bq2597x_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct bq2597x *bq = i2c_get_clientdata(client);
+
+ mutex_lock(&bq->irq_complete);
+ bq->resume_completed = true;
+ if (bq->irq_waiting) {
+ bq->irq_disabled = false;
+ enable_irq(client->irq);
+ mutex_unlock(&bq->irq_complete);
+ //bq2597x_charger_interrupt(client->irq, bq);
+ } else {
+ mutex_unlock(&bq->irq_complete);
+ }
+ bq2597x_enable_adc(bq, true);
+ power_supply_changed(bq->fc2_psy);
+ bq_err("Resume successfully!");
+
+ return 0;
+}
+static void bq2597x_charger_remove(struct i2c_client *client)
+{
+ struct bq2597x *bq = i2c_get_clientdata(client);
+
+ bq2597x_enable_adc(bq, false);
+
+ power_supply_unregister(bq->fc2_psy);
+
+ mutex_destroy(&bq->charging_disable_lock);
+ mutex_destroy(&bq->data_lock);
+ mutex_destroy(&bq->i2c_rw_lock);
+ mutex_destroy(&bq->irq_complete);
+
+ debugfs_remove_recursive(bq->debug_root);
+
+ sysfs_remove_group(&bq->dev->kobj, &bq2597x_attr_group);
+}
+
+
+static void bq2597x_charger_shutdown(struct i2c_client *client)
+{
+ struct bq2597x *bq = i2c_get_clientdata(client);
+
+ bq2597x_enable_adc(bq, false);
+}
+
+static const struct dev_pm_ops bq2597x_pm_ops = {
+ .resume = bq2597x_resume,
+ .suspend_noirq = bq2597x_suspend_noirq,
+ .suspend = bq2597x_suspend,
+};
+
+static const struct i2c_device_id bq2597x_charger_id[] = {
+ {"bq2597x-standalone", BQ25970_ROLE_STDALONE},
+ {"bq2597x-master", BQ25970_ROLE_MASTER},
+ {"bq2597x-slave", BQ25970_ROLE_SLAVE},
+ {},
+};
+
+static struct i2c_driver bq2597x_charger_driver = {
+ .driver = {
+ .name = "bq2597x-charger",
+ .owner = THIS_MODULE,
+ .of_match_table = bq2597x_charger_match_table,
+ .pm = &bq2597x_pm_ops,
+ },
+ .id_table = bq2597x_charger_id,
+
+ .probe = bq2597x_charger_probe,
+ .remove = bq2597x_charger_remove,
+ .shutdown = bq2597x_charger_shutdown,
+};
+
+module_i2c_driver(bq2597x_charger_driver);
+
+MODULE_DESCRIPTION("TI BQ2597x Charger Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/power/supply/bq25970_reg.h b/drivers/power/supply/bq25970_reg.h
new file mode 100644
index 000000000000..7f4515befc6d
--- /dev/null
+++ b/drivers/power/supply/bq25970_reg.h
@@ -0,0 +1,821 @@
+
+#ifndef __BQ2597X_HEADER__
+#define __BQ2597X_HEADER__
+
+/* Register 00h */
+#define BQ2597X_REG_00 0x00
+#define BQ2597X_BAT_OVP_DIS_MASK 0x80
+#define BQ2597X_BAT_OVP_DIS_SHIFT 7
+#define BQ2597X_BAT_OVP_ENABLE 0
+#define BQ2597X_BAT_OVP_DISABLE 1
+
+#define BQ2597X_BAT_OVP_MASK 0x3F
+#define BQ2597X_BAT_OVP_SHIFT 0
+#define BQ2597X_BAT_OVP_BASE 3475
+#define BQ2597X_BAT_OVP_LSB 25
+
+/* Register 01h */
+#define BQ2597X_REG_01 0x01
+#define BQ2597X_BAT_OVP_ALM_DIS_MASK 0x80
+#define BQ2597X_BAT_OVP_ALM_DIS_SHIFT 7
+#define BQ2597X_BAT_OVP_ALM_ENABLE 0
+#define BQ2597X_BAT_OVP_ALM_DISABLE 1
+
+#define BQ2597X_BAT_OVP_ALM_MASK 0x3F
+#define BQ2597X_BAT_OVP_ALM_SHIFT 0
+#define BQ2597X_BAT_OVP_ALM_BASE 3500
+#define BQ2597X_BAT_OVP_ALM_LSB 25
+
+/* Register 02h */
+#define BQ2597X_REG_02 0x02
+#define BQ2597X_BAT_OCP_DIS_MASK 0x80
+#define BQ2597X_BAT_OCP_DIS_SHIFT 7
+#define BQ2597X_BAT_OCP_ENABLE 0
+#define BQ2597X_BAT_OCP_DISABLE 1
+
+#define BQ2597X_BAT_OCP_MASK 0x7F
+#define BQ2597X_BAT_OCP_SHIFT 0
+#define BQ2597X_BAT_OCP_BASE 2000
+#define BQ2597X_BAT_OCP_LSB 100
+
+/* Register 03h */
+#define BQ2597X_REG_03 0x03
+#define BQ2597X_BAT_OCP_ALM_DIS_MASK 0x80
+#define BQ2597X_BAT_OCP_ALM_DIS_SHIFT 7
+#define BQ2597X_BAT_OCP_ALM_ENABLE 0
+#define BQ2597X_BAT_OCP_ALM_DISABLE 1
+
+#define BQ2597X_BAT_OCP_ALM_MASK 0x7F
+#define BQ2597X_BAT_OCP_ALM_SHIFT 0
+#define BQ2597X_BAT_OCP_ALM_BASE 2000
+#define BQ2597X_BAT_OCP_ALM_LSB 100
+
+/* Register 04h */
+#define BQ2597X_REG_04 0x04
+#define BQ2597X_BAT_UCP_ALM_DIS_MASK 0x80
+#define BQ2597X_BAT_UCP_ALM_DIS_SHIFT 7
+#define BQ2597X_BAT_UCP_ALM_ENABLE 0
+#define BQ2597X_BAT_UCP_ALM_DISABLE 1
+
+#define BQ2597X_BAT_UCP_ALM_MASK 0x7F
+#define BQ2597X_BAT_UCP_ALM_SHIFT 0
+#define BQ2597X_BAT_UCP_ALM_BASE 0
+#define BQ2597X_BAT_UCP_ALM_LSB 50
+
+/* Register 05h */
+#define BQ2597X_REG_05 0x05
+#define BQ2597X_AC_OVP_STAT_MASK 0x80
+#define BQ2597X_AC_OVP_STAT_SHIFT 7
+
+#define BQ2597X_AC_OVP_FLAG_MASK 0x40
+#define BQ2597X_AC_OVP_FLAG_SHIFT 6
+
+#define BQ2597X_AC_OVP_MASK_MASK 0x20
+#define BQ2597X_AC_OVP_MASK_SHIFT 5
+
+#define BQ2597X_VDROP_THRESHOLD_SET_MASK 0x10
+#define BQ2597X_VDROP_THRESHOLD_SET_SHIFT 4
+#define BQ2597X_VDROP_THRESHOLD_300MV 0
+#define BQ2597X_VDROP_THRESHOLD_400MV 1
+
+#define BQ2597X_VDROP_DEGLITCH_SET_MASK 0x08
+#define BQ2597X_VDROP_DEGLITCH_SET_SHIFT 3
+#define BQ2597X_VDROP_DEGLITCH_8US 0
+#define BQ2597X_VDROP_DEGLITCH_5MS 1
+
+#define BQ2597X_AC_OVP_MASK 0x07
+#define BQ2597X_AC_OVP_SHIFT 0
+#define BQ2597X_AC_OVP_BASE 11
+#define BQ2597X_AC_OVP_LSB 1
+#define BQ2597X_AC_OVP_6P5V 65
+
+/* Register 06h */
+#define BQ2597X_REG_06 0x06
+#define BQ2597X_VBUS_PD_EN_MASK 0x80
+#define BQ2597X_VBUS_PD_EN_SHIFT 7
+#define BQ2597X_VBUS_PD_ENABLE 1
+#define BQ2597X_VBUS_PD_DISABLE 0
+
+#define BQ2597X_BUS_OVP_MASK 0x7F
+#define BQ2597X_BUS_OVP_SHIFT 0
+#define BQ2597X_BUS_OVP_BASE 5950
+#define BQ2597X_BUS_OVP_LSB 50
+
+/* Register 07h */
+#define BQ2597X_REG_07 0x07
+#define BQ2597X_BUS_OVP_ALM_DIS_MASK 0x80
+#define BQ2597X_BUS_OVP_ALM_DIS_SHIFT 7
+#define BQ2597X_BUS_OVP_ALM_ENABLE 0
+#define BQ2597X_BUS_OVP_ALM_DISABLE 1
+
+#define BQ2597X_BUS_OVP_ALM_MASK 0x7F
+#define BQ2597X_BUS_OVP_ALM_SHIFT 0
+#define BQ2597X_BUS_OVP_ALM_BASE 6000
+#define BQ2597X_BUS_OVP_ALM_LSB 50
+
+/* Register 08h */
+#define BQ2597X_REG_08 0x08
+#define BQ2597X_BUS_OCP_DIS_MASK 0x80
+#define BQ2597X_BUS_OCP_DIS_SHIFT 7
+#define BQ2597X_BUS_OCP_ENABLE 0
+#define BQ2597X_BUS_OCP_DISABLE 1
+
+#define BQ2597X_IBUS_UCP_RISE_FLAG_MASK 0x40
+#define BQ2597X_IBUS_UCP_RISE_FLAG_SHIFT 6
+
+#define BQ2597X_IBUS_UCP_RISE_MASK_MASK 0x20
+#define BQ2597X_IBUS_UCP_RISE_MASK_SHIFT 5
+#define BQ2597X_IBUS_UCP_RISE_MASK_ENABLE 1
+#define BQ2597X_IBUS_UCP_RISE_MASK_DISABLE 0
+
+#define BQ2597X_IBUS_UCP_FALL_FLAG_MASK 0x10
+#define BQ2597X_IBUS_UCP_FALL_FLAG_SHIFT 4
+
+#define BQ2597X_BUS_OCP_MASK 0x0F
+#define BQ2597X_BUS_OCP_SHIFT 0
+#define BQ2597X_BUS_OCP_BASE 1000
+#define BQ2597X_BUS_OCP_LSB 250
+
+/* Register 09h */
+#define BQ2597X_REG_09 0x09
+#define BQ2597X_BUS_OCP_ALM_DIS_MASK 0x80
+#define BQ2597X_BUS_OCP_ALM_DIS_SHIFT 7
+#define BQ2597X_BUS_OCP_ALM_ENABLE 0
+#define BQ2597X_BUS_OCP_ALM_DISABLE 1
+
+#define BQ2597X_BUS_OCP_ALM_MASK 0x7F
+#define BQ2597X_BUS_OCP_ALM_SHIFT 0
+#define BQ2597X_BUS_OCP_ALM_BASE 0
+#define BQ2597X_BUS_OCP_ALM_LSB 50
+
+/* Register 0Ah */
+#define BQ2597X_REG_0A 0x0A
+#define BQ2597X_TSHUT_FLAG_MASK 0x80
+#define BQ2597X_TSHUT_FLAG_SHIFT 7
+#define VBUS_ERROR_LOW_MASK BIT(5)
+#define VBUS_ERROR_HIGH_MASK BIT(4)
+
+#define BQ2597X_TSHUT_STAT_MASK 0x40
+#define BQ2597X_TSHUT_STAT_SHIFT 6
+
+#define BQ2597X_VBUS_ERRORLO_STAT_MASK 0x20
+#define BQ2597X_VBUS_ERRORLO_STAT_SHIFT 5
+
+#define BQ2597X_VBUS_ERRORHI_STAT_MASK 0x10
+#define BQ2597X_VBUS_ERRORHI_STAT_SHIFT 4
+
+#define BQ2597X_SS_TIMEOUT_FLAG_MASK 0x08
+#define BQ2597X_SS_TIMEOUT_FLAG_SHIFT 3
+
+#define BQ2597X_CONV_SWITCHING_STAT_MASK 0x04
+#define BQ2597X_CONV_SWITCHING_STAT_SHIFT 2
+
+#define BQ2597X_CONV_OCP_FLAG_MASK 0x02
+#define BQ2597X_CONV_OCP_FLAG_SHIFT 1
+
+#define BQ2597X_PIN_DIAG_FALL_FLAG_MASK 0x01
+#define BQ2597X_PIN_DIAG_FALL_FLAG_SHIFT 0
+
+/* Register 0Bh */
+#define BQ2597X_REG_0B 0x0B
+#define BQ2597X_REG_RST_MASK 0x80
+#define BQ2597X_REG_RST_SHIFT 7
+#define BQ2597X_REG_RST_ENABLE 1
+#define BQ2597X_REG_RST_DISABLE 0
+
+#define BQ2597X_FSW_SET_MASK 0x70
+#define BQ2597X_FSW_SET_SHIFT 4
+#define BQ2597X_FSW_SET_187P5KHZ 0
+#define BQ2597X_FSW_SET_250KHZ 1
+#define BQ2597X_FSW_SET_300KHZ 2
+#define BQ2597X_FSW_SET_375KHZ 3
+#define BQ2597X_FSW_SET_500KHZ 4
+#define BQ2597X_FSW_SET_750KHZ 5
+
+#define BQ2597X_WD_TIMEOUT_FLAG_MASK 0x08
+#define BQ2597X_WD_TIMEOUT_SHIFT 3
+
+#define BQ2597X_WATCHDOG_DIS_MASK 0x04
+#define BQ2597X_WATCHDOG_DIS_SHIFT 2
+#define BQ2597X_WATCHDOG_ENABLE 0
+#define BQ2597X_WATCHDOG_DISABLE 1
+
+#define BQ2597X_WATCHDOG_MASK 0x03
+#define BQ2597X_WATCHDOG_SHIFT 0
+#define BQ2597X_WATCHDOG_0P5S 0
+#define BQ2597X_WATCHDOG_1S 1
+#define BQ2597X_WATCHDOG_5S 2
+#define BQ2597X_WATCHDOG_30S 3
+
+/* Register 0Ch */
+#define BQ2597X_REG_0C 0x0C
+#define BQ2597X_CHG_EN_MASK 0x80
+#define BQ2597X_CHG_EN_SHIFT 7
+#define BQ2597X_CHG_ENABLE 1
+#define BQ2597X_CHG_DISABLE 0
+
+#define BQ2597X_MS_MASK 0x60
+#define BQ2597X_MS_SHIFT 5
+#define BQ2597X_MS_STANDALONE 0
+#define BQ2597X_MS_SLAVE 1
+#define BQ2597X_MS_MASTER 2
+
+#define BQ2597X_FREQ_SHIFT_MASK 0x18
+#define BQ2597X_FREQ_SHIFT_SHIFT 3
+#define BQ2597X_FREQ_SHIFT_NORMINAL 0
+#define BQ2597X_FREQ_SHIFT_POSITIVE10 1
+#define BQ2597X_FREQ_SHIFT_NEGATIVE10 2
+#define BQ2597X_FREQ_SHIFT_SPREAD_SPECTRUM 3
+
+#define BQ2597X_TSBUS_DIS_MASK 0x04
+#define BQ2597X_TSBUS_DIS_SHIFT 2
+#define BQ2597X_TSBUS_ENABLE 0
+#define BQ2597X_TSBUS_DISABLE 1
+
+#define BQ2597X_TSBAT_DIS_MASK 0x02
+#define BQ2597X_TSBAT_DIS_SHIFT 1
+#define BQ2597X_TSBAT_ENABLE 0
+#define BQ2597X_TSBAT_DISABLE 1
+
+#define BQ2597X_TDIE_DIS_MASK 0x01
+#define BQ2597X_TDIE_DIS_SHIFT 0
+#define BQ2597X_TDIE_ENABLE 0
+#define BQ2597X_TDIE_DISABLE 1
+
+/* Register 0Dh */
+#define BQ2597X_REG_0D 0x0D
+#define BQ2597X_BAT_OVP_ALM_STAT_MASK 0x80
+#define BQ2597X_BAT_OVP_ALM_STAT_SHIFT 7
+
+#define BQ2597X_BAT_OCP_ALM_STAT_MASK 0x40
+#define BQ2597X_BAT_OCP_ALM_STAT_SHIFT 6
+
+#define BQ2597X_BUS_OVP_ALM_STAT_MASK 0x20
+#define BQ2597X_BUS_OVP_ALM_STAT_SHIFT 5
+
+#define BQ2597X_BUS_OCP_ALM_STAT_MASK 0x10
+#define BQ2597X_BUS_OCP_ALM_STAT_SHIFT 4
+
+#define BQ2597X_BAT_UCP_ALM_STAT_MASK 0x08
+#define BQ2597X_BAT_UCP_ALM_STAT_SHIFT 3
+
+#define BQ2597X_ADAPTER_INSERT_STAT_MASK 0x04
+#define BQ2597X_ADAPTER_INSERT_STAT_SHIFT 2
+
+#define BQ2597X_VBAT_INSERT_STAT_MASK 0x02
+#define BQ2597X_VBAT_INSERT_STAT_SHIFT 1
+
+#define BQ2597X_ADC_DONE_STAT_MASK 0x01
+#define BQ2597X_ADC_DONE_STAT_SHIFT 0
+#define BQ2597X_ADC_DONE_STAT_COMPLETE 1
+#define BQ2597X_ADC_DONE_STAT_NOTCOMPLETE 0
+
+/* Register 0Eh */
+#define BQ2597X_REG_0E 0x0E
+#define BQ2597X_BAT_OVP_ALM_FLAG_MASK 0x80
+#define BQ2597X_BAT_OVP_ALM_FLAG_SHIFT 7
+
+#define BQ2597X_BAT_OCP_ALM_FLAG_MASK 0x40
+#define BQ2597X_BAT_OCP_ALM_FLAG_SHIFT 6
+
+#define BQ2597X_BUS_OVP_ALM_FLAG_MASK 0x20
+#define BQ2597X_BUS_OVP_ALM_FLAG_SHIFT 5
+
+#define BQ2597X_BUS_OCP_ALM_FLAG_MASK 0x10
+#define BQ2597X_BUS_OCP_ALM_FLAG_SHIFT 4
+
+#define BQ2597X_BAT_UCP_ALM_FLAG_MASK 0x08
+#define BQ2597X_BAT_UCP_ALM_FLAG_SHIFT 3
+
+#define BQ2597X_ADAPTER_INSERT_FLAG_MASK 0x04
+#define BQ2597X_ADAPTER_INSERT_FLAG_SHIFT 2
+
+#define BQ2597X_VBAT_INSERT_FLAG_MASK 0x02
+#define BQ2597X_VBAT_INSERT_FLAG_SHIFT 1
+
+#define BQ2597X_ADC_DONE_FLAG_MASK 0x01
+#define BQ2597X_ADC_DONE_FLAG_SHIFT 0
+#define BQ2597X_ADC_DONE_FLAG_COMPLETE 1
+#define BQ2597X_ADC_DONE_FLAG_NOTCOMPLETE 0
+
+/* Register 0Fh */
+#define BQ2597X_REG_0F 0x0F
+#define BQ2597X_BAT_OVP_ALM_MASK_MASK 0x80
+#define BQ2597X_BAT_OVP_ALM_MASK_SHIFT 7
+#define BQ2597X_BAT_OVP_ALM_MASK_ENABLE 1
+#define BQ2597X_BAT_OVP_ALM_MASK_DISABLE 0
+
+#define BQ2597X_BAT_OCP_ALM_MASK_MASK 0x40
+#define BQ2597X_BAT_OCP_ALM_MASK_SHIFT 6
+#define BQ2597X_BAT_OCP_ALM_MASK_ENABLE 1
+#define BQ2597X_BAT_OCP_ALM_MASK_DISABLE 0
+
+#define BQ2597X_BUS_OVP_ALM_MASK_MASK 0x20
+#define BQ2597X_BUS_OVP_ALM_MASK_SHIFT 5
+#define BQ2597X_BUS_OVP_ALM_MASK_ENABLE 1
+#define BQ2597X_BUS_OVP_ALM_MASK_DISABLE 0
+
+#define BQ2597X_BUS_OCP_ALM_MASK_MASK 0x10
+#define BQ2597X_BUS_OCP_ALM_MASK_SHIFT 4
+#define BQ2597X_BUS_OCP_ALM_MASK_ENABLE 1
+#define BQ2597X_BUS_OCP_ALM_MASK_DISABLE 0
+
+#define BQ2597X_BAT_UCP_ALM_MASK_MASK 0x08
+#define BQ2597X_BAT_UCP_ALM_MASK_SHIFT 3
+#define BQ2597X_BAT_UCP_ALM_MASK_ENABLE 1
+#define BQ2597X_BAT_UCP_ALM_MASK_DISABLE 0
+
+#define BQ2597X_ADAPTER_INSERT_MASK_MASK 0x04
+#define BQ2597X_ADAPTER_INSERT_MASK_SHIFT 2
+#define BQ2597X_ADAPTER_INSERT_MASK_ENABLE 1
+#define BQ2597X_ADAPTER_INSERT_MASK_DISABLE 0
+
+#define BQ2597X_VBAT_INSERT_MASK_MASK 0x02
+#define BQ2597X_VBAT_INSERT_MASK_SHIFT 1
+#define BQ2597X_VBAT_INSERT_MASK_ENABLE 1
+#define BQ2597X_VBAT_INSERT_MASK_DISABLE 0
+
+#define BQ2597X_ADC_DONE_MASK_MASK 0x01
+#define BQ2597X_ADC_DONE_MASK_SHIFT 0
+#define BQ2597X_ADC_DONE_MASK_ENABLE 1
+#define BQ2597X_ADC_DONE_MASK_DISABLE 0
+
+/* Register 10h */
+#define BQ2597X_REG_10 0x10
+#define BQ2597X_BAT_OVP_FLT_STAT_MASK 0x80
+#define BQ2597X_BAT_OVP_FLT_STAT_SHIFT 7
+
+#define BQ2597X_BAT_OCP_FLT_STAT_MASK 0x40
+#define BQ2597X_BAT_OCP_FLT_STAT_SHIFT 6
+
+#define BQ2597X_BUS_OVP_FLT_STAT_MASK 0x20
+#define BQ2597X_BUS_OVP_FLT_STAT_SHIFT 5
+
+#define BQ2597X_BUS_OCP_FLT_STAT_MASK 0x10
+#define BQ2597X_BUS_OCP_FLT_STAT_SHIFT 4
+
+#define BQ2597X_TSBUS_TSBAT_ALM_STAT_MASK 0x08
+#define BQ2597X_TSBUS_TSBAT_ALM_STAT_SHIFT 3
+
+#define BQ2597X_TSBAT_FLT_STAT_MASK 0x04
+#define BQ2597X_TSBAT_FLT_STAT_SHIFT 2
+
+#define BQ2597X_TSBUS_FLT_STAT_MASK 0x02
+#define BQ2597X_TSBUS_FLT_STAT_SHIFT 1
+
+#define BQ2597X_TDIE_ALM_STAT_MASK 0x01
+#define BQ2597X_TDIE_ALM_STAT_SHIFT 0
+
+/* Register 11h */
+#define BQ2597X_REG_11 0x11
+#define BQ2597X_BAT_OVP_FLT_FLAG_MASK 0x80
+#define BQ2597X_BAT_OVP_FLT_FLAG_SHIFT 7
+
+#define BQ2597X_BAT_OCP_FLT_FLAG_MASK 0x40
+#define BQ2597X_BAT_OCP_FLT_FLAG_SHIFT 6
+
+#define BQ2597X_BUS_OVP_FLT_FLAG_MASK 0x20
+#define BQ2597X_BUS_OVP_FLT_FLAG_SHIFT 5
+
+#define BQ2597X_BUS_OCP_FLT_FLAG_MASK 0x10
+#define BQ2597X_BUS_OCP_FLT_FLAG_SHIFT 4
+
+#define BQ2597X_TSBUS_TSBAT_ALM_FLAG_MASK 0x08
+#define BQ2597X_TSBUS_TSBAT_ALM_FLAG_SHIFT 3
+
+#define BQ2597X_TSBAT_FLT_FLAG_MASK 0x04
+#define BQ2597X_TSBAT_FLT_FLAG_SHIFT 2
+
+#define BQ2597X_TSBUS_FLT_FLAG_MASK 0x02
+#define BQ2597X_TSBUS_FLT_FLAG_SHIFT 1
+
+#define BQ2597X_TDIE_ALM_FLAG_MASK 0x01
+#define BQ2597X_TDIE_ALM_FLAG_SHIFT 0
+
+/* Register 12h */
+#define BQ2597X_REG_12 0x12
+#define BQ2597X_BAT_OVP_FLT_MASK_MASK 0x80
+#define BQ2597X_BAT_OVP_FLT_MASK_SHIFT 7
+#define BQ2597X_BAT_OVP_FLT_MASK_ENABLE 1
+#define BQ2597X_BAT_OVP_FLT_MASK_DISABLE 0
+
+#define BQ2597X_BAT_OCP_FLT_MASK_MASK 0x40
+#define BQ2597X_BAT_OCP_FLT_MASK_SHIFT 6
+#define BQ2597X_BAT_OCP_FLT_MASK_ENABLE 1
+#define BQ2597X_BAT_OCP_FLT_MASK_DISABLE 0
+
+#define BQ2597X_BUS_OVP_FLT_MASK_MASK 0x20
+#define BQ2597X_BUS_OVP_FLT_MASK_SHIFT 5
+#define BQ2597X_BUS_OVP_FLT_MASK_ENABLE 1
+#define BQ2597X_BUS_OVP_FLT_MASK_DISABLE 0
+
+#define BQ2597X_BUS_OCP_FLT_MASK_MASK 0x10
+#define BQ2597X_BUS_OCP_FLT_MASK_SHIFT 4
+#define BQ2597X_BUS_OCP_FLT_MASK_ENABLE 1
+#define BQ2597X_BUS_OCP_FLT_MASK_DISABLE 0
+
+#define BQ2597X_TSBUS_TSBAT_ALM_MASK_MASK 0x08
+#define BQ2597X_TSBUS_TSBAT_ALM_MASK_SHIFT 3
+#define BQ2597X_TSBUS_TSBAT_ALM_MASK_ENABLE 1
+#define BQ2597X_TSBUS_TSBAT_ALM_MASK_DISABLE 0
+
+#define BQ2597X_TSBAT_FLT_MASK_MASK 0x04
+#define BQ2597X_TSBAT_FLT_MASK_SHIFT 2
+#define BQ2597X_TSBAT_FLT_MASK_ENABLE 1
+#define BQ2597X_TSBAT_FLT_MASK_DISABLE 0
+
+#define BQ2597X_TSBUS_FLT_MASK_MASK 0x02
+#define BQ2597X_TSBUS_FLT_MASK_SHIFT 1
+#define BQ2597X_TSBUS_FLT_MASK_ENABLE 1
+#define BQ2597X_TSBUS_FLT_MASK_DISABLE 0
+
+#define BQ2597X_TDIE_ALM_MASK_MASK 0x01
+#define BQ2597X_TDIE_ALM_MASK_SHIFT 0
+#define BQ2597X_TDIE_ALM_MASK_ENABLE 1
+#define BQ2597X_TDIE_ALM_MASK_DISABLE 0
+
+/* Register 13h */
+#define BQ2597X_REG_13 0x13
+#define BQ2597X_DEV_ID_MASK 0x0F
+#define BQ2597X_DEV_ID_SHIFT 0
+#define BQ25968_DEV_ID 0x16
+
+#define BQ25970_DEVICE_ID 0x10
+#define SC8551_DEVICE_ID 0x00
+#define SC8551A_DEVICE_ID 0x51
+
+
+/* Register 14h */
+#define BQ2597X_REG_14 0x14
+#define BQ2597X_ADC_EN_MASK 0x80
+#define BQ2597X_ADC_EN_SHIFT 7
+#define BQ2597X_ADC_ENABLE 1
+#define BQ2597X_ADC_DISABLE 0
+
+#define BQ2597X_ADC_RATE_MASK 0x40
+#define BQ2597X_ADC_RATE_SHIFT 6
+#define BQ2597X_ADC_RATE_CONTINOUS 0
+#define BQ2597X_ADC_RATE_ONESHOT 1
+
+#define BQ2597X_ADC_AVG_MASK 0x20
+#define BQ2597X_ADC_AVG_SHIFT 5
+#define BQ2597X_ADC_AVG_DISABLE 0
+#define BQ2597X_ADC_AVG_ENABLE 1
+
+#define BQ2597X_ADC_AVG_INIT_MASK 0x10
+#define BQ2597X_ADC_AVG_INIT_SHIFT 4
+#define BQ2597X_ADC_AVG_INIT_EXIST_REG_VAL 0
+#define BQ2597X_ADC_AVG_INIT_NEW_CONVERSION 1
+
+#define BQ2597X_ADC_SAMPLE_MASK 0x0C
+#define BQ2597X_ADC_SAMPLE_SHIFT 2
+#define BQ2597X_ADC_SAMPLE_15BITS 0
+#define BQ2597X_ADC_SAMPLE_14BITS 1
+#define BQ2597X_ADC_SAMPLE_13BITS 2
+#define BQ2597X_ADC_SAMPLE_12BITS 3
+
+#define BQ2597X_IBUS_ADC_DIS_MASK 0x01
+#define BQ2597X_IBUS_ADC_DIS_SHIFT 0
+#define BQ2597X_IBUS_ADC_ENABLE 0
+#define BQ2597X_IBUS_ADC_DISABLE 1
+
+/* Register 15h */
+#define BQ2597X_REG_15 0x15
+#define BQ2597X_VBUS_ADC_DIS_MASK 0x80
+#define BQ2597X_VBUS_ADC_DIS_SHIFT 7
+#define BQ2597X_VBUS_ADC_ENABLE 0
+#define BQ2597X_VBUS_ADC_DISABLE 1
+
+#define BQ2597X_VAC_ADC_DIS_MASK 0x40
+#define BQ2597X_VAC_ADC_DIS_SHIFT 6
+#define BQ2597X_VAC_ADC_ENABLE 0
+#define BQ2597X_VAC_ADC_DISABLE 1
+
+#define BQ2597X_VOUT_ADC_DIS_MASK 0x20
+#define BQ2597X_VOUT_ADC_DIS_SHIFT 5
+#define BQ2597X_VOUT_ADC_ENABLE 0
+#define BQ2597X_VOUT_ADC_DISABLE 1
+
+#define BQ2597X_VBAT_ADC_DIS_MASK 0x10
+#define BQ2597X_VBAT_ADC_DIS_SHIFT 4
+#define BQ2597X_VBAT_ADC_ENABLE 0
+#define BQ2597X_VBAT_ADC_DISABLE 1
+
+#define BQ2597X_IBAT_ADC_DIS_MASK 0x08
+#define BQ2597X_IBAT_ADC_DIS_SHIFT 3
+#define BQ2597X_IBAT_ADC_ENABLE 0
+#define BQ2597X_IBAT_ADC_DISABLE 1
+
+#define BQ2597X_TSBUS_ADC_DIS_MASK 0x04
+#define BQ2597X_TSBUS_ADC_DIS_SHIFT 2
+#define BQ2597X_TSBUS_ADC_ENABLE 0
+#define BQ2597X_TSBUS_ADC_DISABLE 1
+
+#define BQ2597X_TSBAT_ADC_DIS_MASK 0x02
+#define BQ2597X_TSBAT_ADC_DIS_SHIFT 1
+#define BQ2597X_TSBAT_ADC_ENABLE 0
+#define BQ2597X_TSBAT_ADC_DISABLE 1
+
+#define BQ2597X_TDIE_ADC_DIS_MASK 0x01
+#define BQ2597X_TDIE_ADC_DIS_SHIFT 0
+#define BQ2597X_TDIE_ADC_ENABLE 0
+#define BQ2597X_TDIE_ADC_DISABLE 1
+
+/* Register 16h */
+#define BQ2597X_REG_16 0x16
+#define BQ2597X_IBUS_POL_MASK 0x80
+#define BQ2597X_IBUS_POL_SHIFT 7
+#define BQ2597X_IBUS_POL_POSITIVE 0
+#define BQ2597X_IBUS_POL_NAGETIVE 1
+
+#define BQ2597X_IBUS_ADC1_MASK 0x7F
+#define BQ2597X_IBUS_ADC1_SHIFT 0
+#define BQ2597X_IBUS_ADC1_BASE 0
+#define BQ2597X_IBUS_ADC1_LSB 256
+
+/* Register 17h */
+#define BQ2597X_REG_17 0x17
+#define BQ2597X_IBUS_ADC0_MASK 0xFF
+#define BQ2597X_IBUS_ADC0_SHIFT 0
+#define BQ2597X_IBUS_ADC0_BASE 0
+#define BQ2597X_IBUS_ADC0_LSB 1
+
+/* Register 18h */
+#define BQ2597X_REG_18 0x18
+#define BQ2597X_VBUS_POL_MASK 0x80
+#define BQ2597X_VBUS_POL_SHIFT 7
+#define BQ2597X_VBUS_POL_POSITIVE 0
+#define BQ2597X_VBUS_POL_NEGATIVE 1
+
+#define BQ2597X_VBUS_ADC1_MASK 0x7F
+#define BQ2597X_VBUS_ADC1_SHIFT 0
+#define BQ2597X_VBUS_ADC1_BASE 0
+#define BQ2597X_VBUS_ADC1_LSB 256
+
+/* Register 19h */
+#define BQ2597X_REG_19 0x19
+#define BQ2597X_VBUS_ADC0_MASK 0xFF
+#define BQ2597X_VBUS_ADC0_SHIFT 0
+#define BQ2597X_VBUS_ADC0_BASE 0
+#define BQ2597X_VBUS_ADC0_LSB 1
+
+/* Register 1Ah */
+#define BQ2597X_REG_1A 0x1A
+#define BQ2597X_VAC_POL_MASK 0x80
+#define BQ2597X_VAC_POL_SHIFT 7
+#define BQ2597X_VAC_POL_POSITIVE 0
+#define BQ2597X_VAC_POL_NEGATIVE 1
+
+#define BQ2597X_VAC_ADC1_MASK 0x7F
+#define BQ2597X_VAC_ADC1_SHIFT 0
+#define BQ2597X_VAC_ADC1_BASE 0
+#define BQ2597X_VAC_ADC1_LSB 256
+
+/* Register 1Bh */
+#define BQ2597X_REG_1B 0x1B
+#define BQ2597X_VAC_ADC0_MASK 0xFF
+#define BQ2597X_VAC_ADC0_SHIFT 0
+#define BQ2597X_VAC_ADC0_BASE 0
+#define BQ2597X_VAC_ADC0_LSB 1
+
+/* Register 1Ch */
+#define BQ2597X_REG_1C 0x1C
+#define BQ2597X_VOUT_POL_MASK 0x80
+#define BQ2597X_VOUT_POL_SHIFT 7
+#define BQ2597X_VOUT_POL_POSITIVE 0
+#define BQ2597X_VOUT_POL_NEGATIVE 1
+
+#define BQ2597X_VOUT_ADC1_MASK 0x7F
+#define BQ2597X_VOUT_ADC1_SHIFT 0
+#define BQ2597X_VOUT_ADC1_BASE 0
+#define BQ2597X_VOUT_ADC1_LSB 256
+
+/* Register 1Dh */
+#define BQ2597X_REG_1D 0x1D
+#define BQ2597X_VOUT_ADC0_MASK 0xFF
+#define BQ2597X_VOUT_ADC0_SHIFT 0
+#define BQ2597X_VOUT_ADC0_BASE 0
+#define BQ2597X_VOUT_ADC0_LSB 1
+
+/* Register 1Eh */
+#define BQ2597X_REG_1E 0x1E
+#define BQ2597X_VBAT_POL_MASK 0x80
+#define BQ2597X_VBAT_POL_SHIFT 7
+#define BQ2597X_VBAT_POL_POSITIVE 0
+#define BQ2597X_VBAT_POL_NEGATIVE 1
+
+#define BQ2597X_VBAT_ADC1_MASK 0x7F
+#define BQ2597X_VBAT_ADC1_SHIFT 0
+#define BQ2597X_VBAT_ADC1_BASE 0
+#define BQ2597X_VBAT_ADC1_LSB 256
+
+/* Register 1Fh */
+#define BQ2597X_REG_1F 0x1F
+#define BQ2597X_VBAT_ADC0_MASK 0xFF
+#define BQ2597X_VBAT_ADC0_SHIFT 0
+#define BQ2597X_VBAT_ADC0_BASE 0
+#define BQ2597X_VBAT_ADC0_LSB 1
+
+/* Register 20h */
+#define BQ2597X_REG_20 0x20
+#define BQ2597X_IBAT_POL_MASK 0x80
+#define BQ2597X_IBAT_POL_SHIFT 7
+#define BQ2597X_IBAT_POL_POSITIVE 0
+#define BQ2597X_IBAT_POL_NEGATIVE 1
+
+#define BQ2597X_IBAT_ADC1_MASK 0x7F
+#define BQ2597X_IBAT_ADC1_SHIFT 0
+#define BQ2597X_IBAT_ADC1_BASE 0
+#define BQ2597X_IBAT_ADC1_LSB 256
+
+/* Register 21h */
+#define BQ2597X_REG_21 0x21
+#define BQ2597X_IBAT_ADC0_MASK 0xFF
+#define BQ2597X_IBAT_ADC0_SHIFT 0
+#define BQ2597X_IBAT_ADC0_BASE 0
+#define BQ2597X_IBAT_ADC0_LSB 1
+
+/* Register 22h */
+#define BQ2597X_REG_22 0x22
+#define BQ2597X_TSBUS_POL_MASK 0x80
+#define BQ2597X_TSBUS_POL_SHIFT 7
+#define BQ2597X_TSBUS_POL_POSITIVE 0
+#define BQ2597X_TSBUS_POL_NEGATIVE 1
+
+#define BQ2597X_TSBUS_ADC1_MASK 0x7F
+#define BQ2597X_TSBUS_ADC1_SHIFT 0
+#define BQ2597X_TSBUS_ADC1_BASE 0
+#define BQ2597X_TSBUS_ADC1_LSB 25
+
+/* Register 23h */
+#define BQ2597X_REG_23 0x23
+#define BQ2597X_TSBUS_ADC0_MASK 0xFF
+#define BQ2597X_TSBUS_ADC0_SHIFT 0
+#define BQ2597X_TSBUS_ADC0_BASE 0
+#define BQ2597X_TSBUS_ADC0_LSB 0.09766
+
+/* Register 24h */
+#define BQ2597X_REG_24 0x24
+#define BQ2597X_TSBAT_POL_MASK 0x80
+#define BQ2597X_TSBAT_POL_SHIFT 7
+#define BQ2597X_TSBAT_POL_POSITIVE 0
+#define BQ2597X_TSBAT_POL_NEGATIVE 1
+
+#define BQ2597X_TSBAT_ADC1_MASK 0x7F
+#define BQ2597X_TSBAT_ADC1_SHIFT 0
+#define BQ2597X_TSBAT_ADC1_BASE 0
+#define BQ2597X_TSBAT_ADC1_LSB 25
+
+/* Register 25h */
+#define BQ2597X_REG_25 0x25
+#define BQ2597X_TSBAT_ADC0_MASK 0xFF
+#define BQ2597X_TSBAT_ADC0_SHIFT 0
+#define BQ2597X_TSBAT_ADC0_BASE 0
+#define BQ2597X_TSBAT_ADC0_LSB 0.09766
+
+/* Register 26h */
+#define BQ2597X_REG_26 0x26
+#define BQ2597X_TDIE_POL_MASK 0x80
+#define BQ2597X_TDIE_POL_SHIFT 7
+#define BQ2597X_TDIE_POL_POSITIVE 0
+#define BQ2597X_TDIE_POL_NEGATIVE 1
+
+#define BQ2597X_TDIE_ADC1_MASK 0x7F
+#define BQ2597X_TDIE_ADC1_SHIFT 0
+#define BQ2597X_TDIE_ADC1_BASE 0
+#define BQ2597X_TDIE_ADC1_LSB 128
+
+/* Register 27h */
+#define BQ2597X_REG_27 0x27
+#define BQ2597X_TDIE_ADC0_MASK 0xFF
+#define BQ2597X_TDIE_ADC0_SHIFT 0
+#define BQ2597X_TDIE_ADC0_BASE 0
+#define BQ2597X_TDIE_ADC0_LSB 0.5
+
+/* Register 28h */
+#define BQ2597X_REG_28 0x28
+#define BQ2597X_TSBUS_FLT1_MASK 0xFF
+#define BQ2597X_TSBUS_FLT1_SHIFT 0
+#define BQ2597X_TSBUS_FLT1_BASE 0
+#define BQ2597X_TSBUS_FLT1_LSB 0.19531
+
+/* Register 29h */
+#define BQ2597X_REG_29 0x29
+#define BQ2597X_TSBAT_FLT0_MASK 0xFF
+#define BQ2597X_TSBAT_FLT0_SHIFT 0
+#define BQ2597X_TSBAT_FLT0_BASE 0
+#define BQ2597X_TSBAT_FLT0_LSB 0.19531
+
+/* Register 2Ah */
+#define BQ2597X_REG_2A 0x2A
+#define BQ2597X_TDIE_ALM_MASK 0xFF
+#define BQ2597X_TDIE_ALM_SHIFT 0
+#define BQ2597X_TDIE_ALM_BASE 30
+
+#define BQ2597X_TDIE_ALM_LSB 2 /*careful
+ multiply is used for calc*/
+
+/* Register 2Bh */
+#define BQ2597X_REG_2B 0x2B
+#define BQ2597X_SS_TIMEOUT_SET_MASK 0xE0
+#define BQ2597X_SS_TIMEOUT_SET_SHIFT 5
+#define BQ2597X_SS_TIMEOUT_DISABLE 0
+#define BQ2597X_SS_TIMEOUT_12P5MS 1
+#define BQ2597X_SS_TIMEOUT_25MS 2
+#define BQ2597X_SS_TIMEOUT_50MS 3
+#define BQ2597X_SS_TIMEOUT_100MS 4
+#define BQ2597X_SS_TIMEOUT_400MS 5
+#define BQ2597X_SS_TIMEOUT_1500MS 6
+#define BQ2597X_SS_TIMEOUT_100000MS 7
+
+#define BQ2597X_EN_REGULATION_MASK 0x10
+#define BQ2597X_EN_REGULATION_SHIFT 4
+#define BQ2597X_EN_REGULATION_ENABLE 1
+#define BQ2597X_EN_REGULATION_DISABLE 0
+
+#define BQ2597X_VOUT_OVP_DIS_MASK 0x08
+#define BQ2597X_VOUT_OVP_DIS_SHIFT 3
+#define BQ2597X_VOUT_OVP_ENABLE 1
+#define BQ2597X_VOUT_OVP_DISABLE 0
+
+#define BQ2597X_IBUS_UCP_RISE_TH_MASK 0x04
+#define BQ2597X_IBUS_UCP_RISE_TH_SHIFT 2
+#define BQ2597X_IBUS_UCP_RISE_300MA 0
+#define BQ2597X_IBUS_UCP_RISE_500MA 1
+
+#define BQ2597X_SET_IBAT_SNS_RES_MASK 0x02
+#define BQ2597X_SET_IBAT_SNS_RES_SHIFT 1
+#define BQ2597X_SET_IBAT_SNS_RES_2MHM 0
+#define BQ2597X_SET_IBAT_SNS_RES_5MHM 1
+
+
+#define BQ2597X_VAC_PD_EN_MASK 0x01
+#define BQ2597X_VAC_PD_EN_SHIFT 0
+#define BQ2597X_VAC_PD_ENABLE 1
+#define BQ2597X_VAC_PD_DISABLE 0
+
+/* Register 2Ch */
+#define BQ2597X_REG_2C 0x2C
+#define BQ2597X_IBAT_REG_MASK 0xC0
+#define BQ2597X_IBAT_REG_SHIFT 6
+#define BQ2597X_IBAT_REG_200MA 0
+#define BQ2597X_IBAT_REG_300MA 1
+#define BQ2597X_IBAT_REG_400MA 2
+#define BQ2597X_IBAT_REG_500MA 3
+#define BQ2597X_VBAT_REG_MASK 0x30
+#define BQ2597X_VBAT_REG_SHIFT 4
+#define BQ2597X_VBAT_REG_50MV 0
+#define BQ2597X_VBAT_REG_100MV 1
+#define BQ2597X_VBAT_REG_150MV 2
+#define BQ2597X_VBAT_REG_200MV 3
+
+#define BQ2597X_VBAT_REG_ACTIVE_STAT_MASK 0x08
+#define BQ2597X_IBAT_REG_ACTIVE_STAT_MASK 0x04
+#define BQ2597X_VDROP_OVP_ACTIVE_STAT_MASK 0x02
+#define BQ2597X_VOUT_OVP_ACTIVE_STAT_MASK 0x01
+
+
+#define BQ2597X_REG_2D 0x2D
+#define BQ2597X_VBAT_REG_ACTIVE_FLAG_MASK 0x80
+#define BQ2597X_IBAT_REG_ACTIVE_FLAG_MASK 0x40
+#define BQ2597X_VDROP_OVP_FLAG_MASK 0x20
+#define BQ2597X_VOUT_OVP_FLAG_MASK 0x10
+#define BQ2597X_VBAT_REG_ACTIVE_MASK_MASK 0x08
+#define BQ2597X_IBAT_REG_ACTIVE_MASK_MASK 0x04
+#define BQ2597X_VDROP_OVP_MASK_MASK 0x02
+#define BQ2597X_VOUT_OVP_MASK_MASK 0x01
+
+
+#define BQ2597X_REG_2E 0x2E
+#define BQ2597X_VBUS_ERR_LOW_DG_MASK 0x10
+#define BQ2597X_VBUS_ERR_LOW_DG_SHIFT 4
+#define BQ2597X_VBUS_ERR_LOW_DG_10US 0
+#define BQ2597X_VBUS_ERR_LOW_DG_10MS 1
+#define BQ2597X_IBUS_LOW_DG_MASK 0x08
+#define BQ2597X_IBUS_LOW_DG_SHIFT 3
+#define BQ2597X_IBUS_LOW_DG_10US 0
+#define BQ2597X_IBUS_LOW_DG_5MS 1
+
+#define SC8551_IBUS_ADC_LSB 1.5625
+#define SC8551_VBUS_ADC_LSB 3.75
+#define SC8551_VAC_ADC_LSB 5
+#define SC8551_VOUT_ADC_LSB 1.25
+#define SC8551_VBAT_ADC_LSB 1.2575
+#define SC8551_IBAT_ADC_LSB 3.125
+#define SC8551_TSBUS_ADC_LSB 0.0009766
+#define SC8551_TSBAT_ADC_LSB 0.0009766
+#define SC8551_TDIE_ADC_LSB 0.5
+/* Register 00h */
+#define SC8551_BAT_OVP_BASE 3500
+#define SC8551_REG_2F 0x2F
+#define SC8551_CHIP_VENDOR_MASK GENMASK(7, 4)
+#define SC8551_REG_30 0x30
+#define SC8551_REG_31 0x31
+#define SC8551_CHARGE_MODE_MASK 0x01
+#define SC8551_CHARGE_MODE_SHIFT 0
+#define SC8551_CHARGE_MODE_DIV2 0
+#define SC8551_CHARGE_MODE_BYPASS 1
+#define SC8551_REG_34 0x34
+#define SC8551_REG_36 0x36
+
+#endif
--
2.47.3