2021-01-04 20:28:13

by Ricardo Rivera-Matos

[permalink] [raw]
Subject: [PATCH v8 2/2] power: supply: bq256xx: Introduce the BQ256XX charger driver

The BQ256XX family of devices are highly integrated buck chargers
for single cell batteries.

Signed-off-by: Ricardo Rivera-Matos <[email protected]>
---
drivers/power/supply/Kconfig | 11 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/bq256xx_charger.c | 1745 ++++++++++++++++++++++++
3 files changed, 1757 insertions(+)
create mode 100644 drivers/power/supply/bq256xx_charger.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index eec646c568b7..cedef501e683 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -645,6 +645,17 @@ config CHARGER_BQ25980
Say Y to enable support for the TI BQ25980, BQ25975 and BQ25960
series of fast battery chargers.

+config CHARGER_BQ256XX
+ tristate "TI BQ256XX battery charger driver"
+ depends on I2C
+ depends on GPIOLIB || COMPILE_TEST
+ select REGMAP_I2C
+ help
+ Say Y to enable support for the TI BQ256XX battery chargers. The
+ BQ256XX family of devices are highly-integrated, switch-mode battery
+ charge management and system power path management devices for single
+ cell Li-ion and Li-polymer batteries.
+
config CHARGER_SMB347
tristate "Summit Microelectronics SMB3XX Battery Charger"
depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index dd4b86318cd9..ae322b1da1ed 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_CHARGER_BQ24735) += bq24735-charger.o
obj-$(CONFIG_CHARGER_BQ2515X) += bq2515x_charger.o
obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o
obj-$(CONFIG_CHARGER_BQ25980) += bq25980_charger.o
+obj-$(CONFIG_CHARGER_BQ256XX) += bq256xx_charger.o
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c
new file mode 100644
index 000000000000..a6aa0ab2315f
--- /dev/null
+++ b/drivers/power/supply/bq256xx_charger.c
@@ -0,0 +1,1745 @@
+// SPDX-License-Identifier: GPL-2.0
+// BQ256XX Battery Charger Driver
+// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio/consumer.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/usb/phy.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+
+#define BQ256XX_MANUFACTURER "Texas Instruments"
+
+#define BQ256XX_INPUT_CURRENT_LIMIT 0x00
+#define BQ256XX_CHARGER_CONTROL_0 0x01
+#define BQ256XX_CHARGE_CURRENT_LIMIT 0x02
+#define BQ256XX_PRECHG_AND_TERM_CURR_LIM 0x03
+#define BQ256XX_BATTERY_VOLTAGE_LIMIT 0x04
+#define BQ256XX_CHARGER_CONTROL_1 0x05
+#define BQ256XX_CHARGER_CONTROL_2 0x06
+#define BQ256XX_CHARGER_CONTROL_3 0x07
+#define BQ256XX_CHARGER_STATUS_0 0x08
+#define BQ256XX_CHARGER_STATUS_1 0x09
+#define BQ256XX_CHARGER_STATUS_2 0x0a
+#define BQ256XX_PART_INFORMATION 0x0b
+#define BQ256XX_CHARGER_CONTROL_4 0x0c
+
+#define BQ256XX_IINDPM_MASK GENMASK(4, 0)
+#define BQ256XX_IINDPM_STEP_uA 100000
+#define BQ256XX_IINDPM_OFFSET_uA 100000
+#define BQ256XX_IINDPM_MIN_uA 100000
+#define BQ256XX_IINDPM_MAX_uA 3200000
+#define BQ256XX_IINDPM_DEF_uA 2400000
+
+#define BQ256XX_VINDPM_MASK GENMASK(3, 0)
+#define BQ256XX_VINDPM_STEP_uV 100000
+#define BQ256XX_VINDPM_OFFSET_uV 3900000
+#define BQ256XX_VINDPM_MIN_uV 3900000
+#define BQ256XX_VINDPM_MAX_uV 5400000
+#define BQ256XX_VINDPM_DEF_uV 4500000
+
+#define BQ256XX_VBATREG_MASK GENMASK(7, 3)
+#define BQ2560X_VBATREG_STEP_uV 32000
+#define BQ2560X_VBATREG_OFFSET_uV 3856000
+#define BQ2560X_VBATREG_MIN_uV 3856000
+#define BQ2560X_VBATREG_MAX_uV 4624000
+#define BQ2560X_VBATREG_DEF_uV 4208000
+#define BQ25601D_VBATREG_OFFSET_uV 3847000
+#define BQ25601D_VBATREG_MIN_uV 3847000
+#define BQ25601D_VBATREG_MAX_uV 4615000
+#define BQ25601D_VBATREG_DEF_uV 4199000
+#define BQ2561X_VBATREG_STEP_uV 10000
+#define BQ25611D_VBATREG_MIN_uV 3494000
+#define BQ25611D_VBATREG_MAX_uV 4510000
+#define BQ25611D_VBATREG_DEF_uV 4190000
+#define BQ25618_VBATREG_MIN_uV 3504000
+#define BQ25618_VBATREG_MAX_uV 4500000
+#define BQ25618_VBATREG_DEF_uV 4200000
+#define BQ256XX_VBATREG_BIT_SHIFT 3
+#define BQ2561X_VBATREG_THRESH 0x8
+#define BQ25611D_VBATREG_THRESH_uV 4290000
+#define BQ25618_VBATREG_THRESH_uV 4300000
+
+#define BQ256XX_ITERM_MASK GENMASK(3, 0)
+#define BQ256XX_ITERM_STEP_uA 60000
+#define BQ256XX_ITERM_OFFSET_uA 60000
+#define BQ256XX_ITERM_MIN_uA 60000
+#define BQ256XX_ITERM_MAX_uA 780000
+#define BQ256XX_ITERM_DEF_uA 180000
+#define BQ25618_ITERM_STEP_uA 20000
+#define BQ25618_ITERM_OFFSET_uA 20000
+#define BQ25618_ITERM_MIN_uA 20000
+#define BQ25618_ITERM_MAX_uA 260000
+#define BQ25618_ITERM_DEF_uA 60000
+
+#define BQ256XX_IPRECHG_MASK GENMASK(7, 4)
+#define BQ256XX_IPRECHG_STEP_uA 60000
+#define BQ256XX_IPRECHG_OFFSET_uA 60000
+#define BQ256XX_IPRECHG_MIN_uA 60000
+#define BQ256XX_IPRECHG_MAX_uA 780000
+#define BQ256XX_IPRECHG_DEF_uA 180000
+#define BQ25618_IPRECHG_STEP_uA 20000
+#define BQ25618_IPRECHG_OFFSET_uA 20000
+#define BQ25618_IPRECHG_MIN_uA 20000
+#define BQ25618_IPRECHG_MAX_uA 260000
+#define BQ25618_IPRECHG_DEF_uA 40000
+#define BQ256XX_IPRECHG_BIT_SHIFT 4
+
+#define BQ256XX_ICHG_MASK GENMASK(5, 0)
+#define BQ256XX_ICHG_STEP_uA 60000
+#define BQ256XX_ICHG_MIN_uA 0
+#define BQ256XX_ICHG_MAX_uA 3000000
+#define BQ2560X_ICHG_DEF_uA 2040000
+#define BQ25611D_ICHG_DEF_uA 1020000
+#define BQ25618_ICHG_STEP_uA 20000
+#define BQ25618_ICHG_MIN_uA 0
+#define BQ25618_ICHG_MAX_uA 1500000
+#define BQ25618_ICHG_DEF_uA 340000
+#define BQ25618_ICHG_THRESH 0x3c
+#define BQ25618_ICHG_THRESH_uA 1180000
+
+#define BQ256XX_VBUS_STAT_MASK GENMASK(7, 5)
+#define BQ256XX_VBUS_STAT_NO_INPUT 0
+#define BQ256XX_VBUS_STAT_USB_SDP BIT(5)
+#define BQ256XX_VBUS_STAT_USB_CDP BIT(6)
+#define BQ256XX_VBUS_STAT_USB_DCP (BIT(6) | BIT(5))
+#define BQ256XX_VBUS_STAT_USB_OTG (BIT(7) | BIT(6) | BIT(5))
+
+#define BQ256XX_CHRG_STAT_MASK GENMASK(4, 3)
+#define BQ256XX_CHRG_STAT_NOT_CHRGING 0
+#define BQ256XX_CHRG_STAT_PRECHRGING BIT(3)
+#define BQ256XX_CHRG_STAT_FAST_CHRGING BIT(4)
+#define BQ256XX_CHRG_STAT_CHRG_TERM (BIT(4) | BIT(3))
+
+#define BQ256XX_PG_STAT_MASK BIT(2)
+#define BQ256XX_WDT_FAULT_MASK BIT(7)
+#define BQ256XX_CHRG_FAULT_MASK GENMASK(5, 4)
+#define BQ256XX_CHRG_FAULT_NORMAL 0
+#define BQ256XX_CHRG_FAULT_INPUT BIT(4)
+#define BQ256XX_CHRG_FAULT_THERM BIT(5)
+#define BQ256XX_CHRG_FAULT_CST_EXPIRE (BIT(5) | BIT(4))
+#define BQ256XX_BAT_FAULT_MASK BIT(3)
+#define BQ256XX_NTC_FAULT_MASK GENMASK(2, 0)
+#define BQ256XX_NTC_FAULT_WARM BIT(1)
+#define BQ256XX_NTC_FAULT_COOL (BIT(1) | BIT(0))
+#define BQ256XX_NTC_FAULT_COLD (BIT(2) | BIT(0))
+#define BQ256XX_NTC_FAULT_HOT (BIT(2) | BIT(1))
+
+#define BQ256XX_NUM_WD_VAL 8
+#define BQ256XX_WATCHDOG_MASK GENMASK(5, 4)
+#define BQ256XX_WATCHDOG_MAX 1600000
+#define BQ256XX_WATCHDOG_DIS 0
+#define BQ256XX_WDT_BIT_SHIFT 4
+
+#define BQ256XX_REG_RST BIT(7)
+
+/**
+ * struct bq256xx_init_data -
+ * @ichg: fast charge current
+ * @iindpm: input current limit
+ * @vbatreg: charge voltage
+ * @iterm: termination current
+ * @iprechg: precharge current
+ * @vindpm: input voltage limit
+ * @ichg_max: maximum fast charge current
+ * @vbatreg_max: maximum charge voltage
+ */
+struct bq256xx_init_data {
+ u32 ichg;
+ u32 iindpm;
+ u32 vbatreg;
+ u32 iterm;
+ u32 iprechg;
+ u32 vindpm;
+ u32 ichg_max;
+ u32 vbatreg_max;
+};
+
+/**
+ * struct bq256xx_state -
+ * @vbus_stat: VBUS status according to BQ256XX_CHARGER_STATUS_0
+ * @chrg_stat: charging status according to BQ256XX_CHARGER_STATUS_0
+ * @online: PG status according to BQ256XX_CHARGER_STATUS_0
+ *
+ * @wdt_fault: watchdog fault according to BQ256XX_CHARGER_STATUS_1
+ * @bat_fault: battery fault according to BQ256XX_CHARGER_STATUS_1
+ * @chrg_fault: charging fault according to BQ256XX_CHARGER_STATUS_1
+ * @ntc_fault: TS fault according to BQ256XX_CHARGER_STATUS_1
+ */
+struct bq256xx_state {
+ u8 vbus_stat;
+ u8 chrg_stat;
+ bool online;
+
+ u8 wdt_fault;
+ u8 bat_fault;
+ u8 chrg_fault;
+ u8 ntc_fault;
+};
+
+enum bq256xx_id {
+ BQ25600,
+ BQ25600D,
+ BQ25601,
+ BQ25601D,
+ BQ25618,
+ BQ25619,
+ BQ25611D,
+};
+
+/**
+ * struct bq256xx_device -
+ * @client: i2c client structure
+ * @regmap: register map structure
+ * @dev: device structure
+ * @lock: mutex lock structure
+ *
+ * @usb2_phy: usb_phy identifier
+ * @usb3_phy: usb_phy identifier
+ * @usb_nb: notifier block
+ * @usb_work: usb work queue
+ * @usb_event: usb_event code
+ *
+ * @model_name: i2c name string
+ *
+ * @init_data: initialization data
+ * @chip_info: device variant information
+ * @state: device status and faults
+ * @watchdog_timer: watchdog timer value in milliseconds
+ */
+struct bq256xx_device {
+ struct i2c_client *client;
+ struct device *dev;
+ struct power_supply *charger;
+ struct power_supply *battery;
+ struct mutex lock;
+ struct regmap *regmap;
+
+ struct usb_phy *usb2_phy;
+ struct usb_phy *usb3_phy;
+ struct notifier_block usb_nb;
+ struct work_struct usb_work;
+ unsigned long usb_event;
+
+ char model_name[I2C_NAME_SIZE];
+
+ struct bq256xx_init_data init_data;
+ const struct bq256xx_chip_info *chip_info;
+ struct bq256xx_state state;
+ int watchdog_timer;
+};
+
+/**
+ * struct bq256xx_chip_info -
+ * @model_id: device instance
+ *
+ * @bq256xx_regmap_config: regmap configuration struct
+ * @bq256xx_get_ichg: pointer to instance specific get_ichg function
+ * @bq256xx_get_iindpm: pointer to instance specific get_iindpm function
+ * @bq256xx_get_vbatreg: pointer to instance specific get_vbatreg function
+ * @bq256xx_get_iterm: pointer to instance specific get_iterm function
+ * @bq256xx_get_iprechg: pointer to instance specific get_iprechg function
+ * @bq256xx_get_vindpm: pointer to instance specific get_vindpm function
+ *
+ * @bq256xx_set_ichg: pointer to instance specific set_ichg function
+ * @bq256xx_set_iindpm: pointer to instance specific set_iindpm function
+ * @bq256xx_set_vbatreg: pointer to instance specific set_vbatreg function
+ * @bq256xx_set_iterm: pointer to instance specific set_iterm function
+ * @bq256xx_set_iprechg: pointer to instance specific set_iprechg function
+ * @bq256xx_set_vindpm: pointer to instance specific set_vindpm function
+ *
+ * @bq256xx_def_ichg: default ichg value in microamps
+ * @bq256xx_def_iindpm: default iindpm value in microamps
+ * @bq256xx_def_vbatreg: default vbatreg value in microvolts
+ * @bq256xx_def_iterm: default iterm value in microamps
+ * @bq256xx_def_iprechg: default iprechg value in microamps
+ * @bq256xx_def_vindpm: default vindpm value in microvolts
+ *
+ * @bq256xx_max_ichg: maximum charge current in microamps
+ * @bq256xx_max_vbatreg: maximum battery regulation voltage in microvolts
+ *
+ * @has_usb_detect: indicates whether device has BC1.2 detection
+ */
+struct bq256xx_chip_info {
+ int model_id;
+
+ const struct regmap_config *bq256xx_regmap_config;
+
+ int (*bq256xx_get_ichg)(struct bq256xx_device *bq);
+ int (*bq256xx_get_iindpm)(struct bq256xx_device *bq);
+ int (*bq256xx_get_vbatreg)(struct bq256xx_device *bq);
+ int (*bq256xx_get_iterm)(struct bq256xx_device *bq);
+ int (*bq256xx_get_iprechg)(struct bq256xx_device *bq);
+ int (*bq256xx_get_vindpm)(struct bq256xx_device *bq);
+
+ int (*bq256xx_set_ichg)(struct bq256xx_device *bq, int ichg);
+ int (*bq256xx_set_iindpm)(struct bq256xx_device *bq, int iindpm);
+ int (*bq256xx_set_vbatreg)(struct bq256xx_device *bq, int vbatreg);
+ int (*bq256xx_set_iterm)(struct bq256xx_device *bq, int iterm);
+ int (*bq256xx_set_iprechg)(struct bq256xx_device *bq, int iprechg);
+ int (*bq256xx_set_vindpm)(struct bq256xx_device *bq, int vindpm);
+
+ int bq256xx_def_ichg;
+ int bq256xx_def_iindpm;
+ int bq256xx_def_vbatreg;
+ int bq256xx_def_iterm;
+ int bq256xx_def_iprechg;
+ int bq256xx_def_vindpm;
+
+ int bq256xx_max_ichg;
+ int bq256xx_max_vbatreg;
+
+ bool has_usb_detect;
+};
+
+static int bq256xx_watchdog_time[BQ256XX_NUM_WD_VAL] = {
+ 0, 40000, 80000, 1600000
+};
+
+static const int bq25611d_vbatreg_values[] = {
+ 3494000, 3590000, 3686000, 3790000, 3894000, 3990000, 4090000, 4140000,
+ 4190000
+};
+
+static const int bq25618_619_vbatreg_values[] = {
+ 3504000, 3600000, 3696000, 3800000, 3904000, 4000000, 4100000, 4150000,
+ 4200000
+};
+
+static const int bq25618_619_ichg_values[] = {
+ 1290000, 1360000, 1430000, 1500000
+};
+
+static enum power_supply_usb_type bq256xx_usb_type[] = {
+ POWER_SUPPLY_USB_TYPE_SDP,
+ POWER_SUPPLY_USB_TYPE_CDP,
+ POWER_SUPPLY_USB_TYPE_DCP,
+ POWER_SUPPLY_USB_TYPE_UNKNOWN,
+ POWER_SUPPLY_USB_TYPE_ACA,
+};
+
+static int bq256xx_array_parse(int array_size, int val, const int array[])
+{
+ int i = 0;
+
+ if (val < array[i])
+ return i - 1;
+
+ if (val >= array[array_size - 1])
+ return array_size - 1;
+
+ for (i = 1; i < array_size; i++) {
+ if (val == array[i])
+ return i;
+
+ if (val > array[i - 1] && val < array[i]) {
+ if (val < array[i])
+ return i - 1;
+ else
+ return i;
+ }
+ }
+ return -EINVAL;
+}
+
+static int bq256xx_usb_notifier(struct notifier_block *nb, unsigned long val,
+ void *priv)
+{
+ struct bq256xx_device *bq =
+ container_of(nb, struct bq256xx_device, usb_nb);
+
+ bq->usb_event = val;
+ queue_work(system_power_efficient_wq, &bq->usb_work);
+
+ return NOTIFY_OK;
+}
+
+static void bq256xx_usb_work(struct work_struct *data)
+{
+ struct bq256xx_device *bq =
+ container_of(data, struct bq256xx_device, usb_work);
+
+ switch (bq->usb_event) {
+ case USB_EVENT_ID:
+ break;
+ case USB_EVENT_NONE:
+ power_supply_changed(bq->charger);
+ break;
+ default:
+ dev_err(bq->dev, "Error switching to charger mode.\n");
+ break;
+ }
+}
+
+static struct reg_default bq2560x_reg_defs[] = {
+ {BQ256XX_INPUT_CURRENT_LIMIT, 0x17},
+ {BQ256XX_CHARGER_CONTROL_0, 0x1a},
+ {BQ256XX_CHARGE_CURRENT_LIMIT, 0xa2},
+ {BQ256XX_PRECHG_AND_TERM_CURR_LIM, 0x22},
+ {BQ256XX_BATTERY_VOLTAGE_LIMIT, 0x58},
+ {BQ256XX_CHARGER_CONTROL_1, 0x9f},
+ {BQ256XX_CHARGER_CONTROL_2, 0x66},
+ {BQ256XX_CHARGER_CONTROL_3, 0x4c},
+};
+
+static struct reg_default bq25611d_reg_defs[] = {
+ {BQ256XX_INPUT_CURRENT_LIMIT, 0x17},
+ {BQ256XX_CHARGER_CONTROL_0, 0x1a},
+ {BQ256XX_CHARGE_CURRENT_LIMIT, 0x91},
+ {BQ256XX_PRECHG_AND_TERM_CURR_LIM, 0x12},
+ {BQ256XX_BATTERY_VOLTAGE_LIMIT, 0x40},
+ {BQ256XX_CHARGER_CONTROL_1, 0x9e},
+ {BQ256XX_CHARGER_CONTROL_2, 0xe6},
+ {BQ256XX_CHARGER_CONTROL_3, 0x4c},
+ {BQ256XX_PART_INFORMATION, 0x54},
+ {BQ256XX_CHARGER_CONTROL_4, 0x75},
+};
+
+static struct reg_default bq25618_619_reg_defs[] = {
+ {BQ256XX_INPUT_CURRENT_LIMIT, 0x17},
+ {BQ256XX_CHARGER_CONTROL_0, 0x1a},
+ {BQ256XX_CHARGE_CURRENT_LIMIT, 0x91},
+ {BQ256XX_PRECHG_AND_TERM_CURR_LIM, 0x12},
+ {BQ256XX_BATTERY_VOLTAGE_LIMIT, 0x40},
+ {BQ256XX_CHARGER_CONTROL_1, 0x9e},
+ {BQ256XX_CHARGER_CONTROL_2, 0xe6},
+ {BQ256XX_CHARGER_CONTROL_3, 0x4c},
+ {BQ256XX_PART_INFORMATION, 0x2c},
+ {BQ256XX_CHARGER_CONTROL_4, 0x75},
+};
+
+static int bq256xx_get_state(struct bq256xx_device *bq,
+ struct bq256xx_state *state)
+{
+ unsigned int charger_status_0;
+ unsigned int charger_status_1;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_CHARGER_STATUS_0,
+ &charger_status_0);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_CHARGER_STATUS_1,
+ &charger_status_1);
+ if (ret)
+ return ret;
+
+ state->vbus_stat = charger_status_0 & BQ256XX_VBUS_STAT_MASK;
+ state->chrg_stat = charger_status_0 & BQ256XX_CHRG_STAT_MASK;
+ state->online = charger_status_0 & BQ256XX_PG_STAT_MASK;
+
+ state->wdt_fault = charger_status_1 & BQ256XX_WDT_FAULT_MASK;
+ state->bat_fault = charger_status_1 & BQ256XX_BAT_FAULT_MASK;
+ state->chrg_fault = charger_status_1 & BQ256XX_CHRG_FAULT_MASK;
+ state->ntc_fault = charger_status_1 & BQ256XX_NTC_FAULT_MASK;
+
+ return 0;
+}
+
+static int bq256xx_get_ichg_curr(struct bq256xx_device *bq)
+{
+ unsigned int charge_current_limit;
+ unsigned int ichg_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_CHARGE_CURRENT_LIMIT,
+ &charge_current_limit);
+ if (ret)
+ return ret;
+
+ ichg_reg_code = charge_current_limit & BQ256XX_ICHG_MASK;
+
+ return ichg_reg_code * BQ256XX_ICHG_STEP_uA;
+}
+
+static int bq25618_619_get_ichg_curr(struct bq256xx_device *bq)
+{
+ unsigned int charge_current_limit;
+ unsigned int ichg_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_CHARGE_CURRENT_LIMIT,
+ &charge_current_limit);
+ if (ret)
+ return ret;
+
+ ichg_reg_code = charge_current_limit & BQ256XX_ICHG_MASK;
+
+ if (ichg_reg_code < BQ25618_ICHG_THRESH)
+ return ichg_reg_code * BQ25618_ICHG_STEP_uA;
+
+ return bq25618_619_ichg_values[ichg_reg_code - BQ25618_ICHG_THRESH];
+}
+
+static int bq256xx_set_ichg_curr(struct bq256xx_device *bq, int ichg)
+{
+ unsigned int ichg_reg_code;
+ int ichg_max = bq->init_data.ichg_max;
+
+ ichg = clamp(ichg, BQ256XX_ICHG_MIN_uA, ichg_max);
+ ichg_reg_code = ichg / BQ256XX_ICHG_STEP_uA;
+
+ return regmap_update_bits(bq->regmap, BQ256XX_CHARGE_CURRENT_LIMIT,
+ BQ256XX_ICHG_MASK, ichg_reg_code);
+}
+
+static int bq25618_619_set_ichg_curr(struct bq256xx_device *bq, int ichg)
+{
+ int array_size = ARRAY_SIZE(bq25618_619_ichg_values);
+ unsigned int ichg_reg_code;
+ int ichg_max = bq->init_data.ichg_max;
+
+ ichg = clamp(ichg, BQ25618_ICHG_MIN_uA, ichg_max);
+
+ if (ichg <= BQ25618_ICHG_THRESH_uA) {
+ ichg_reg_code = ichg / BQ25618_ICHG_STEP_uA;
+ } else {
+ ichg_reg_code = bq256xx_array_parse(array_size, ichg,
+ bq25618_619_ichg_values) + BQ25618_ICHG_THRESH;
+ }
+
+ return regmap_update_bits(bq->regmap, BQ256XX_CHARGE_CURRENT_LIMIT,
+ BQ256XX_ICHG_MASK, ichg_reg_code);
+}
+
+static int bq25618_619_get_chrg_volt(struct bq256xx_device *bq)
+{
+ unsigned int battery_volt_lim;
+ unsigned int vbatreg_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_BATTERY_VOLTAGE_LIMIT,
+ &battery_volt_lim);
+
+ if (ret)
+ return ret;
+
+ vbatreg_reg_code = (battery_volt_lim & BQ256XX_VBATREG_MASK) >>
+ BQ256XX_VBATREG_BIT_SHIFT;
+
+ if (vbatreg_reg_code > BQ2561X_VBATREG_THRESH)
+ return ((vbatreg_reg_code - BQ2561X_VBATREG_THRESH) *
+ BQ2561X_VBATREG_STEP_uV) +
+ BQ25618_VBATREG_THRESH_uV;
+
+ return bq25618_619_vbatreg_values[vbatreg_reg_code];
+}
+
+static int bq25611d_get_chrg_volt(struct bq256xx_device *bq)
+{
+ unsigned int battery_volt_lim;
+ unsigned int vbatreg_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_BATTERY_VOLTAGE_LIMIT,
+ &battery_volt_lim);
+ if (ret)
+ return ret;
+
+ vbatreg_reg_code = (battery_volt_lim & BQ256XX_VBATREG_MASK) >>
+ BQ256XX_VBATREG_BIT_SHIFT;
+
+ if (vbatreg_reg_code > BQ2561X_VBATREG_THRESH)
+ return ((vbatreg_reg_code - BQ2561X_VBATREG_THRESH) *
+ BQ2561X_VBATREG_STEP_uV) +
+ BQ25611D_VBATREG_THRESH_uV;
+
+ return bq25611d_vbatreg_values[vbatreg_reg_code];
+}
+
+static int bq2560x_get_chrg_volt(struct bq256xx_device *bq)
+{
+ unsigned int battery_volt_lim;
+ unsigned int vbatreg_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_BATTERY_VOLTAGE_LIMIT,
+ &battery_volt_lim);
+ if (ret)
+ return ret;
+
+ vbatreg_reg_code = (battery_volt_lim & BQ256XX_VBATREG_MASK) >>
+ BQ256XX_VBATREG_BIT_SHIFT;
+
+ return (vbatreg_reg_code * BQ2560X_VBATREG_STEP_uV)
+ + BQ2560X_VBATREG_OFFSET_uV;
+}
+
+static int bq25601d_get_chrg_volt(struct bq256xx_device *bq)
+{
+ unsigned int battery_volt_lim;
+ unsigned int vbatreg_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_BATTERY_VOLTAGE_LIMIT,
+ &battery_volt_lim);
+ if (ret)
+ return ret;
+
+ vbatreg_reg_code = (battery_volt_lim & BQ256XX_VBATREG_MASK) >>
+ BQ256XX_VBATREG_BIT_SHIFT;
+
+ return (vbatreg_reg_code * BQ2560X_VBATREG_STEP_uV)
+ + BQ25601D_VBATREG_OFFSET_uV;
+}
+
+static int bq25618_619_set_chrg_volt(struct bq256xx_device *bq, int vbatreg)
+{
+ int array_size = ARRAY_SIZE(bq25618_619_vbatreg_values);
+ unsigned int vbatreg_reg_code;
+ int vbatreg_max = bq->init_data.vbatreg_max;
+
+ vbatreg = clamp(vbatreg, BQ25618_VBATREG_MIN_uV, vbatreg_max);
+
+ if (vbatreg > BQ25618_VBATREG_THRESH_uV)
+ vbatreg_reg_code = ((vbatreg -
+ BQ25618_VBATREG_THRESH_uV) /
+ (BQ2561X_VBATREG_STEP_uV)) + BQ2561X_VBATREG_THRESH;
+ else {
+ vbatreg_reg_code = bq256xx_array_parse(array_size, vbatreg,
+ bq25618_619_vbatreg_values);
+ }
+
+ return regmap_update_bits(bq->regmap, BQ256XX_BATTERY_VOLTAGE_LIMIT,
+ BQ256XX_VBATREG_MASK, vbatreg_reg_code <<
+ BQ256XX_VBATREG_BIT_SHIFT);
+}
+
+static int bq25611d_set_chrg_volt(struct bq256xx_device *bq, int vbatreg)
+{
+ int array_size = ARRAY_SIZE(bq25611d_vbatreg_values);
+ unsigned int vbatreg_reg_code;
+ int vbatreg_max = bq->init_data.vbatreg_max;
+
+ vbatreg = clamp(vbatreg, BQ25611D_VBATREG_MIN_uV, vbatreg_max);
+
+ if (vbatreg > BQ25611D_VBATREG_THRESH_uV)
+ vbatreg_reg_code = ((vbatreg -
+ BQ25611D_VBATREG_THRESH_uV) /
+ (BQ2561X_VBATREG_STEP_uV)) + BQ2561X_VBATREG_THRESH;
+ else {
+ vbatreg_reg_code = bq256xx_array_parse(array_size, vbatreg,
+ bq25611d_vbatreg_values);
+ }
+
+ return regmap_update_bits(bq->regmap, BQ256XX_BATTERY_VOLTAGE_LIMIT,
+ BQ256XX_VBATREG_MASK, vbatreg_reg_code <<
+ BQ256XX_VBATREG_BIT_SHIFT);
+}
+
+static int bq2560x_set_chrg_volt(struct bq256xx_device *bq, int vbatreg)
+{
+ unsigned int vbatreg_reg_code;
+ int vbatreg_max = bq->init_data.vbatreg_max;
+
+ vbatreg = clamp(vbatreg, BQ2560X_VBATREG_MIN_uV, vbatreg_max);
+
+ vbatreg_reg_code = (vbatreg - BQ2560X_VBATREG_OFFSET_uV) /
+ BQ2560X_VBATREG_STEP_uV;
+
+ return regmap_update_bits(bq->regmap, BQ256XX_BATTERY_VOLTAGE_LIMIT,
+ BQ256XX_VBATREG_MASK, vbatreg_reg_code <<
+ BQ256XX_VBATREG_BIT_SHIFT);
+}
+
+static int bq25601d_set_chrg_volt(struct bq256xx_device *bq, int vbatreg)
+{
+ unsigned int vbatreg_reg_code;
+ int vbatreg_max = bq->init_data.vbatreg_max;
+
+ vbatreg = clamp(vbatreg, BQ25601D_VBATREG_MIN_uV, vbatreg_max);
+
+ vbatreg_reg_code = (vbatreg - BQ25601D_VBATREG_OFFSET_uV) /
+ BQ2560X_VBATREG_STEP_uV;
+
+ return regmap_update_bits(bq->regmap, BQ256XX_BATTERY_VOLTAGE_LIMIT,
+ BQ256XX_VBATREG_MASK, vbatreg_reg_code <<
+ BQ256XX_VBATREG_BIT_SHIFT);
+}
+
+static int bq256xx_get_prechrg_curr(struct bq256xx_device *bq)
+{
+ unsigned int prechg_and_term_curr_lim;
+ unsigned int iprechg_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_PRECHG_AND_TERM_CURR_LIM,
+ &prechg_and_term_curr_lim);
+ if (ret)
+ return ret;
+
+ iprechg_reg_code = (prechg_and_term_curr_lim & BQ256XX_IPRECHG_MASK)
+ >> BQ256XX_IPRECHG_BIT_SHIFT;
+
+ return (iprechg_reg_code * BQ256XX_IPRECHG_STEP_uA) +
+ BQ256XX_IPRECHG_OFFSET_uA;
+}
+
+static int bq256xx_set_prechrg_curr(struct bq256xx_device *bq, int iprechg)
+{
+ unsigned int iprechg_reg_code;
+
+ iprechg = clamp(iprechg, BQ256XX_IPRECHG_MIN_uA,
+ BQ256XX_IPRECHG_MAX_uA);
+
+ iprechg_reg_code = ((iprechg - BQ256XX_IPRECHG_OFFSET_uA) /
+ BQ256XX_IPRECHG_STEP_uA) << BQ256XX_IPRECHG_BIT_SHIFT;
+
+ return regmap_update_bits(bq->regmap, BQ256XX_PRECHG_AND_TERM_CURR_LIM,
+ BQ256XX_IPRECHG_MASK, iprechg_reg_code);
+}
+
+static int bq25618_619_get_prechrg_curr(struct bq256xx_device *bq)
+{
+ unsigned int prechg_and_term_curr_lim;
+ unsigned int iprechg_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_PRECHG_AND_TERM_CURR_LIM,
+ &prechg_and_term_curr_lim);
+ if (ret)
+ return ret;
+
+ iprechg_reg_code = (prechg_and_term_curr_lim & BQ256XX_IPRECHG_MASK)
+ >> BQ256XX_IPRECHG_BIT_SHIFT;
+
+ return (iprechg_reg_code * BQ25618_IPRECHG_STEP_uA) +
+ BQ25618_IPRECHG_OFFSET_uA;
+}
+
+static int bq25618_619_set_prechrg_curr(struct bq256xx_device *bq, int iprechg)
+{
+ unsigned int iprechg_reg_code;
+
+ iprechg = clamp(iprechg, BQ25618_IPRECHG_MIN_uA,
+ BQ25618_IPRECHG_MAX_uA);
+
+ iprechg_reg_code = ((iprechg - BQ25618_IPRECHG_OFFSET_uA) /
+ BQ25618_IPRECHG_STEP_uA) << BQ256XX_IPRECHG_BIT_SHIFT;
+
+ return regmap_update_bits(bq->regmap, BQ256XX_PRECHG_AND_TERM_CURR_LIM,
+ BQ256XX_IPRECHG_MASK, iprechg_reg_code);
+}
+
+static int bq256xx_get_term_curr(struct bq256xx_device *bq)
+{
+ unsigned int prechg_and_term_curr_lim;
+ unsigned int iterm_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_PRECHG_AND_TERM_CURR_LIM,
+ &prechg_and_term_curr_lim);
+ if (ret)
+ return ret;
+
+ iterm_reg_code = prechg_and_term_curr_lim & BQ256XX_ITERM_MASK;
+
+ return (iterm_reg_code * BQ256XX_ITERM_STEP_uA) +
+ BQ256XX_ITERM_OFFSET_uA;
+}
+
+static int bq256xx_set_term_curr(struct bq256xx_device *bq, int iterm)
+{
+ unsigned int iterm_reg_code;
+
+ iterm = clamp(iterm, BQ256XX_ITERM_MIN_uA, BQ256XX_ITERM_MAX_uA);
+
+ iterm_reg_code = (iterm - BQ256XX_ITERM_OFFSET_uA) /
+ BQ256XX_ITERM_STEP_uA;
+
+ return regmap_update_bits(bq->regmap, BQ256XX_PRECHG_AND_TERM_CURR_LIM,
+ BQ256XX_ITERM_MASK, iterm_reg_code);
+}
+
+static int bq25618_619_get_term_curr(struct bq256xx_device *bq)
+{
+ unsigned int prechg_and_term_curr_lim;
+ unsigned int iterm_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_PRECHG_AND_TERM_CURR_LIM,
+ &prechg_and_term_curr_lim);
+ if (ret)
+ return ret;
+
+ iterm_reg_code = prechg_and_term_curr_lim & BQ256XX_ITERM_MASK;
+
+ return (iterm_reg_code * BQ25618_ITERM_STEP_uA) +
+ BQ25618_ITERM_OFFSET_uA;
+}
+
+static int bq25618_619_set_term_curr(struct bq256xx_device *bq, int iterm)
+{
+ unsigned int iterm_reg_code;
+
+ iterm = clamp(iterm, BQ25618_ITERM_MIN_uA, BQ25618_ITERM_MAX_uA);
+
+ iterm_reg_code = (iterm - BQ25618_ITERM_OFFSET_uA) /
+ BQ25618_ITERM_STEP_uA;
+
+ return regmap_update_bits(bq->regmap, BQ256XX_PRECHG_AND_TERM_CURR_LIM,
+ BQ256XX_ITERM_MASK, iterm_reg_code);
+}
+
+static int bq256xx_get_input_volt_lim(struct bq256xx_device *bq)
+{
+ unsigned int charger_control_2;
+ unsigned int vindpm_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_CHARGER_CONTROL_2,
+ &charger_control_2);
+ if (ret)
+ return ret;
+
+ vindpm_reg_code = charger_control_2 & BQ256XX_VINDPM_MASK;
+
+ return (vindpm_reg_code * BQ256XX_VINDPM_STEP_uV) +
+ BQ256XX_VINDPM_OFFSET_uV;
+}
+
+static int bq256xx_set_input_volt_lim(struct bq256xx_device *bq, int vindpm)
+{
+ unsigned int vindpm_reg_code;
+
+ vindpm = clamp(vindpm, BQ256XX_VINDPM_MIN_uV, BQ256XX_VINDPM_MAX_uV);
+
+ vindpm_reg_code = (vindpm - BQ256XX_VINDPM_OFFSET_uV) /
+ BQ256XX_VINDPM_STEP_uV;
+
+ return regmap_update_bits(bq->regmap, BQ256XX_CHARGER_CONTROL_2,
+ BQ256XX_VINDPM_MASK, vindpm_reg_code);
+}
+
+static int bq256xx_get_input_curr_lim(struct bq256xx_device *bq)
+{
+ unsigned int input_current_limit;
+ unsigned int iindpm_reg_code;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ256XX_INPUT_CURRENT_LIMIT,
+ &input_current_limit);
+ if (ret)
+ return ret;
+
+ iindpm_reg_code = input_current_limit & BQ256XX_IINDPM_MASK;
+
+ return (iindpm_reg_code * BQ256XX_IINDPM_STEP_uA) +
+ BQ256XX_IINDPM_OFFSET_uA;
+}
+
+static int bq256xx_set_input_curr_lim(struct bq256xx_device *bq, int iindpm)
+{
+ unsigned int iindpm_reg_code;
+
+ iindpm = clamp(iindpm, BQ256XX_IINDPM_MIN_uA, BQ256XX_IINDPM_MAX_uA);
+
+ iindpm_reg_code = (iindpm - BQ256XX_IINDPM_OFFSET_uA) /
+ BQ256XX_IINDPM_STEP_uA;
+
+ return regmap_update_bits(bq->regmap, BQ256XX_INPUT_CURRENT_LIMIT,
+ BQ256XX_IINDPM_MASK, iindpm_reg_code);
+}
+
+static void bq256xx_charger_reset(void *data)
+{
+ struct bq256xx_device *bq = data;
+
+ regmap_update_bits(bq->regmap, BQ256XX_PART_INFORMATION,
+ BQ256XX_REG_RST, BQ256XX_REG_RST);
+
+ if (!IS_ERR_OR_NULL(bq->usb2_phy))
+ usb_unregister_notifier(bq->usb2_phy, &bq->usb_nb);
+
+ if (!IS_ERR_OR_NULL(bq->usb3_phy))
+ usb_unregister_notifier(bq->usb3_phy, &bq->usb_nb);
+}
+
+static int bq256xx_set_charger_property(struct power_supply *psy,
+ enum power_supply_property prop,
+ const union power_supply_propval *val)
+{
+ struct bq256xx_device *bq = power_supply_get_drvdata(psy);
+ int ret = -EINVAL;
+
+ switch (prop) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ ret = bq->chip_info->bq256xx_set_iindpm(bq, val->intval);
+ if (ret)
+ return ret;
+ break;
+
+ case POWER_SUPPLY_PROP_STATUS:
+ break;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ ret = bq->chip_info->bq256xx_set_vbatreg(bq, val->intval);
+ if (ret)
+ return ret;
+ break;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ ret = bq->chip_info->bq256xx_set_ichg(bq, val->intval);
+ if (ret)
+ return ret;
+ break;
+
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ ret = bq->chip_info->bq256xx_set_iprechg(bq, val->intval);
+ if (ret)
+ return ret;
+ break;
+
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ ret = bq->chip_info->bq256xx_set_iterm(bq, val->intval);
+ if (ret)
+ return ret;
+ break;
+
+ case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
+ ret = bq->chip_info->bq256xx_set_vindpm(bq, val->intval);
+ if (ret)
+ return ret;
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
+static int bq256xx_get_battery_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bq256xx_device *bq = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+ val->intval = bq->init_data.ichg_max;
+ break;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+ val->intval = bq->init_data.vbatreg_max;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int bq256xx_get_charger_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bq256xx_device *bq = power_supply_get_drvdata(psy);
+ struct bq256xx_state state;
+ int ret = 0;
+
+ mutex_lock(&bq->lock);
+ ret = bq256xx_get_state(bq, &state);
+ mutex_unlock(&bq->lock);
+ if (ret)
+ return ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (state.vbus_stat == BQ256XX_VBUS_STAT_NO_INPUT ||
+ state.vbus_stat == BQ256XX_VBUS_STAT_USB_OTG)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (state.chrg_stat == BQ256XX_CHRG_STAT_NOT_CHRGING)
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else if (state.chrg_stat == BQ256XX_CHRG_STAT_CHRG_TERM)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+ if (state.wdt_fault) {
+ val->intval =
+ POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE;
+ } else if (state.bat_fault) {
+ val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ } else {
+ switch (state.chrg_stat) {
+ case BQ256XX_CHRG_FAULT_INPUT:
+ val->intval =
+ POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ break;
+ case BQ256XX_CHRG_FAULT_THERM:
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ break;
+ case BQ256XX_CHRG_FAULT_CST_EXPIRE:
+ val->intval =
+ POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
+ break;
+ default:
+ break;
+ }
+
+ switch (state.ntc_fault) {
+ case BQ256XX_NTC_FAULT_WARM:
+ val->intval = POWER_SUPPLY_HEALTH_WARM;
+ break;
+ case BQ256XX_NTC_FAULT_COOL:
+ val->intval = POWER_SUPPLY_HEALTH_COOL;
+ break;
+ case BQ256XX_NTC_FAULT_COLD:
+ val->intval = POWER_SUPPLY_HEALTH_COLD;
+ break;
+ case BQ256XX_NTC_FAULT_HOT:
+ val->intval = POWER_SUPPLY_HEALTH_HOT;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ }
+ }
+ break;
+
+ case POWER_SUPPLY_PROP_USB_TYPE:
+ if (bq->chip_info->has_usb_detect) {
+ switch (state.vbus_stat) {
+ case BQ256XX_VBUS_STAT_USB_SDP:
+ val->intval = POWER_SUPPLY_USB_TYPE_SDP;
+ break;
+ case BQ256XX_VBUS_STAT_USB_CDP:
+ val->intval = POWER_SUPPLY_USB_TYPE_CDP;
+ break;
+ case BQ256XX_VBUS_STAT_USB_DCP:
+ val->intval = POWER_SUPPLY_USB_TYPE_DCP;
+ break;
+ case BQ256XX_VBUS_STAT_USB_OTG:
+ val->intval = POWER_SUPPLY_USB_TYPE_ACA;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+ break;
+ }
+ } else {
+ switch (state.vbus_stat) {
+ case BQ256XX_VBUS_STAT_USB_SDP:
+ val->intval = POWER_SUPPLY_USB_TYPE_SDP;
+ break;
+ case BQ256XX_VBUS_STAT_USB_OTG:
+ val->intval = POWER_SUPPLY_USB_TYPE_ACA;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+ break;
+ }
+ }
+ break;
+
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ switch (state.chrg_stat) {
+ case BQ256XX_CHRG_STAT_NOT_CHRGING:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ break;
+ case BQ256XX_CHRG_STAT_PRECHRGING:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ case BQ256XX_CHRG_STAT_FAST_CHRGING:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+ break;
+ case BQ256XX_CHRG_STAT_CHRG_TERM:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+ }
+ break;
+
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = BQ256XX_MANUFACTURER;
+ break;
+
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = bq->model_name;
+ break;
+
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = state.online;
+ break;
+
+ case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
+ ret = bq->chip_info->bq256xx_get_vindpm(bq);
+ if (ret < 0)
+ return ret;
+ val->intval = ret;
+ break;
+
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ ret = bq->chip_info->bq256xx_get_iindpm(bq);
+ if (ret < 0)
+ return ret;
+ val->intval = ret;
+ break;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ ret = bq->chip_info->bq256xx_get_vbatreg(bq);
+ if (ret < 0)
+ return ret;
+ val->intval = ret;
+ break;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ ret = bq->chip_info->bq256xx_get_ichg(bq);
+ if (ret < 0)
+ return ret;
+ val->intval = ret;
+ break;
+
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ ret = bq->chip_info->bq256xx_get_iprechg(bq);
+ if (ret < 0)
+ return ret;
+ val->intval = ret;
+ break;
+
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ ret = bq->chip_info->bq256xx_get_iterm(bq);
+ if (ret < 0)
+ return ret;
+ val->intval = ret;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static bool bq256xx_state_changed(struct bq256xx_device *bq,
+ struct bq256xx_state *new_state)
+{
+ struct bq256xx_state old_state;
+
+ mutex_lock(&bq->lock);
+ old_state = bq->state;
+ mutex_unlock(&bq->lock);
+
+ return memcmp(&old_state, &new_state, sizeof(struct bq256xx_state)) != 0;
+}
+
+static irqreturn_t bq256xx_irq_handler_thread(int irq, void *private)
+{
+ struct bq256xx_device *bq = private;
+ struct bq256xx_state state;
+ int ret;
+
+ ret = bq256xx_get_state(bq, &state);
+ if (ret < 0)
+ goto irq_out;
+
+ if (!bq256xx_state_changed(bq, &state))
+ goto irq_out;
+
+ mutex_lock(&bq->lock);
+ bq->state = state;
+ mutex_unlock(&bq->lock);
+
+ power_supply_changed(bq->charger);
+
+irq_out:
+ return IRQ_HANDLED;
+}
+
+static enum power_supply_property bq256xx_power_supply_props[] = {
+ POWER_SUPPLY_PROP_MANUFACTURER,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_USB_TYPE,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
+ POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
+ POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
+};
+
+static enum power_supply_property bq256xx_battery_props[] = {
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+};
+
+static int bq256xx_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property prop)
+{
+ switch (prop) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ case POWER_SUPPLY_PROP_STATUS:
+ case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct power_supply_desc bq256xx_power_supply_desc = {
+ .name = "bq256xx-charger",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .usb_types = bq256xx_usb_type,
+ .num_usb_types = ARRAY_SIZE(bq256xx_usb_type),
+ .properties = bq256xx_power_supply_props,
+ .num_properties = ARRAY_SIZE(bq256xx_power_supply_props),
+ .get_property = bq256xx_get_charger_property,
+ .set_property = bq256xx_set_charger_property,
+ .property_is_writeable = bq256xx_property_is_writeable,
+};
+
+static struct power_supply_desc bq256xx_battery_desc = {
+ .name = "bq256xx-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .get_property = bq256xx_get_battery_property,
+ .properties = bq256xx_battery_props,
+ .num_properties = ARRAY_SIZE(bq256xx_battery_props),
+ .property_is_writeable = bq256xx_property_is_writeable,
+};
+
+
+static bool bq256xx_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case BQ256XX_INPUT_CURRENT_LIMIT:
+ case BQ256XX_CHARGER_STATUS_0...BQ256XX_CHARGER_STATUS_2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config bq25600_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = BQ256XX_PART_INFORMATION,
+ .reg_defaults = bq2560x_reg_defs,
+ .num_reg_defaults = ARRAY_SIZE(bq2560x_reg_defs),
+ .cache_type = REGCACHE_FLAT,
+ .volatile_reg = bq256xx_is_volatile_reg,
+};
+
+static const struct regmap_config bq25611d_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = BQ256XX_CHARGER_CONTROL_4,
+ .reg_defaults = bq25611d_reg_defs,
+ .num_reg_defaults = ARRAY_SIZE(bq25611d_reg_defs),
+ .cache_type = REGCACHE_FLAT,
+ .volatile_reg = bq256xx_is_volatile_reg,
+};
+
+static const struct regmap_config bq25618_619_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = BQ256XX_CHARGER_CONTROL_4,
+ .reg_defaults = bq25618_619_reg_defs,
+ .num_reg_defaults = ARRAY_SIZE(bq25618_619_reg_defs),
+ .cache_type = REGCACHE_FLAT,
+ .volatile_reg = bq256xx_is_volatile_reg,
+};
+
+static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
+ [BQ25600] = {
+ .model_id = BQ25600,
+ .bq256xx_regmap_config = &bq25600_regmap_config,
+ .bq256xx_get_ichg = bq256xx_get_ichg_curr,
+ .bq256xx_get_iindpm = bq256xx_get_input_curr_lim,
+ .bq256xx_get_vbatreg = bq2560x_get_chrg_volt,
+ .bq256xx_get_iterm = bq256xx_get_term_curr,
+ .bq256xx_get_iprechg = bq256xx_get_prechrg_curr,
+ .bq256xx_get_vindpm = bq256xx_get_input_volt_lim,
+
+ .bq256xx_set_ichg = bq256xx_set_ichg_curr,
+ .bq256xx_set_iindpm = bq256xx_set_input_curr_lim,
+ .bq256xx_set_vbatreg = bq2560x_set_chrg_volt,
+ .bq256xx_set_iterm = bq256xx_set_term_curr,
+ .bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
+ .bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+
+ .bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
+ .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
+ .bq256xx_def_vbatreg = BQ2560X_VBATREG_DEF_uV,
+ .bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA,
+ .bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA,
+ .bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV,
+
+ .bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA,
+ .bq256xx_max_vbatreg = BQ2560X_VBATREG_MAX_uV,
+
+ .has_usb_detect = false,
+ },
+
+ [BQ25600D] = {
+ .model_id = BQ25600D,
+ .bq256xx_regmap_config = &bq25600_regmap_config,
+ .bq256xx_get_ichg = bq256xx_get_ichg_curr,
+ .bq256xx_get_iindpm = bq256xx_get_input_curr_lim,
+ .bq256xx_get_vbatreg = bq2560x_get_chrg_volt,
+ .bq256xx_get_iterm = bq256xx_get_term_curr,
+ .bq256xx_get_iprechg = bq256xx_get_prechrg_curr,
+ .bq256xx_get_vindpm = bq256xx_get_input_volt_lim,
+
+ .bq256xx_set_ichg = bq256xx_set_ichg_curr,
+ .bq256xx_set_iindpm = bq256xx_set_input_curr_lim,
+ .bq256xx_set_vbatreg = bq2560x_set_chrg_volt,
+ .bq256xx_set_iterm = bq256xx_set_term_curr,
+ .bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
+ .bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+
+ .bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
+ .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
+ .bq256xx_def_vbatreg = BQ2560X_VBATREG_DEF_uV,
+ .bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA,
+ .bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA,
+ .bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV,
+
+ .bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA,
+ .bq256xx_max_vbatreg = BQ2560X_VBATREG_MAX_uV,
+
+ .has_usb_detect = true,
+ },
+
+ [BQ25601] = {
+ .model_id = BQ25601,
+ .bq256xx_regmap_config = &bq25600_regmap_config,
+ .bq256xx_get_ichg = bq256xx_get_ichg_curr,
+ .bq256xx_get_iindpm = bq256xx_get_input_curr_lim,
+ .bq256xx_get_vbatreg = bq2560x_get_chrg_volt,
+ .bq256xx_get_iterm = bq256xx_get_term_curr,
+ .bq256xx_get_iprechg = bq256xx_get_prechrg_curr,
+ .bq256xx_get_vindpm = bq256xx_get_input_volt_lim,
+
+ .bq256xx_set_ichg = bq256xx_set_ichg_curr,
+ .bq256xx_set_iindpm = bq256xx_set_input_curr_lim,
+ .bq256xx_set_vbatreg = bq2560x_set_chrg_volt,
+ .bq256xx_set_iterm = bq256xx_set_term_curr,
+ .bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
+ .bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+
+ .bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
+ .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
+ .bq256xx_def_vbatreg = BQ2560X_VBATREG_DEF_uV,
+ .bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA,
+ .bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA,
+ .bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV,
+
+ .bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA,
+ .bq256xx_max_vbatreg = BQ2560X_VBATREG_MAX_uV,
+
+ .has_usb_detect = false,
+ },
+
+ [BQ25601D] = {
+ .model_id = BQ25601D,
+ .bq256xx_regmap_config = &bq25600_regmap_config,
+ .bq256xx_get_ichg = bq256xx_get_ichg_curr,
+ .bq256xx_get_iindpm = bq256xx_get_input_curr_lim,
+ .bq256xx_get_vbatreg = bq25601d_get_chrg_volt,
+ .bq256xx_get_iterm = bq256xx_get_term_curr,
+ .bq256xx_get_iprechg = bq256xx_get_prechrg_curr,
+ .bq256xx_get_vindpm = bq256xx_get_input_volt_lim,
+
+ .bq256xx_set_ichg = bq256xx_set_ichg_curr,
+ .bq256xx_set_iindpm = bq256xx_set_input_curr_lim,
+ .bq256xx_set_vbatreg = bq25601d_set_chrg_volt,
+ .bq256xx_set_iterm = bq256xx_set_term_curr,
+ .bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
+ .bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+
+ .bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
+ .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
+ .bq256xx_def_vbatreg = BQ2560X_VBATREG_DEF_uV,
+ .bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA,
+ .bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA,
+ .bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV,
+
+ .bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA,
+ .bq256xx_max_vbatreg = BQ2560X_VBATREG_MAX_uV,
+
+ .has_usb_detect = true,
+ },
+
+ [BQ25611D] = {
+ .model_id = BQ25611D,
+ .bq256xx_regmap_config = &bq25611d_regmap_config,
+ .bq256xx_get_ichg = bq256xx_get_ichg_curr,
+ .bq256xx_get_iindpm = bq256xx_get_input_curr_lim,
+ .bq256xx_get_vbatreg = bq25611d_get_chrg_volt,
+ .bq256xx_get_iterm = bq256xx_get_term_curr,
+ .bq256xx_get_iprechg = bq256xx_get_prechrg_curr,
+ .bq256xx_get_vindpm = bq256xx_get_input_volt_lim,
+
+ .bq256xx_set_ichg = bq256xx_set_ichg_curr,
+ .bq256xx_set_iindpm = bq256xx_set_input_curr_lim,
+ .bq256xx_set_vbatreg = bq25611d_set_chrg_volt,
+ .bq256xx_set_iterm = bq256xx_set_term_curr,
+ .bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
+ .bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+
+ .bq256xx_def_ichg = BQ25611D_ICHG_DEF_uA,
+ .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
+ .bq256xx_def_vbatreg = BQ25611D_VBATREG_DEF_uV,
+ .bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA,
+ .bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA,
+ .bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV,
+
+ .bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA,
+ .bq256xx_max_vbatreg = BQ25611D_VBATREG_MAX_uV,
+
+ .has_usb_detect = true,
+ },
+
+ [BQ25618] = {
+ .model_id = BQ25618,
+ .bq256xx_regmap_config = &bq25618_619_regmap_config,
+ .bq256xx_get_ichg = bq25618_619_get_ichg_curr,
+ .bq256xx_get_iindpm = bq256xx_get_input_curr_lim,
+ .bq256xx_get_vbatreg = bq25618_619_get_chrg_volt,
+ .bq256xx_get_iterm = bq25618_619_get_term_curr,
+ .bq256xx_get_iprechg = bq25618_619_get_prechrg_curr,
+ .bq256xx_get_vindpm = bq256xx_get_input_volt_lim,
+
+ .bq256xx_set_ichg = bq25618_619_set_ichg_curr,
+ .bq256xx_set_iindpm = bq256xx_set_input_curr_lim,
+ .bq256xx_set_vbatreg = bq25618_619_set_chrg_volt,
+ .bq256xx_set_iterm = bq25618_619_set_term_curr,
+ .bq256xx_set_iprechg = bq25618_619_set_prechrg_curr,
+ .bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+
+ .bq256xx_def_ichg = BQ25618_ICHG_DEF_uA,
+ .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
+ .bq256xx_def_vbatreg = BQ25618_VBATREG_DEF_uV,
+ .bq256xx_def_iterm = BQ25618_ITERM_DEF_uA,
+ .bq256xx_def_iprechg = BQ25618_IPRECHG_DEF_uA,
+ .bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV,
+
+ .bq256xx_max_ichg = BQ25618_ICHG_MAX_uA,
+ .bq256xx_max_vbatreg = BQ25618_VBATREG_MAX_uV,
+
+ .has_usb_detect = false,
+ },
+
+ [BQ25619] = {
+ .model_id = BQ25619,
+ .bq256xx_regmap_config = &bq25618_619_regmap_config,
+ .bq256xx_get_ichg = bq25618_619_get_ichg_curr,
+ .bq256xx_get_iindpm = bq256xx_get_input_curr_lim,
+ .bq256xx_get_vbatreg = bq25618_619_get_chrg_volt,
+ .bq256xx_get_iterm = bq25618_619_get_term_curr,
+ .bq256xx_get_iprechg = bq25618_619_get_prechrg_curr,
+ .bq256xx_get_vindpm = bq256xx_get_input_volt_lim,
+
+ .bq256xx_set_ichg = bq25618_619_set_ichg_curr,
+ .bq256xx_set_iindpm = bq256xx_set_input_curr_lim,
+ .bq256xx_set_vbatreg = bq25618_619_set_chrg_volt,
+ .bq256xx_set_iterm = bq25618_619_set_term_curr,
+ .bq256xx_set_iprechg = bq25618_619_set_prechrg_curr,
+ .bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+
+ .bq256xx_def_ichg = BQ25618_ICHG_DEF_uA,
+ .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
+ .bq256xx_def_vbatreg = BQ25618_VBATREG_DEF_uV,
+ .bq256xx_def_iterm = BQ25618_ITERM_DEF_uA,
+ .bq256xx_def_iprechg = BQ25618_IPRECHG_DEF_uA,
+ .bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV,
+
+ .bq256xx_max_ichg = BQ25618_ICHG_MAX_uA,
+ .bq256xx_max_vbatreg = BQ25618_VBATREG_MAX_uV,
+
+ .has_usb_detect = false,
+ },
+};
+
+static int bq256xx_power_supply_init(struct bq256xx_device *bq,
+ struct power_supply_config *psy_cfg, struct device *dev)
+{
+ bq->charger = devm_power_supply_register(bq->dev,
+ &bq256xx_power_supply_desc,
+ psy_cfg);
+ if (IS_ERR(bq->charger)) {
+ dev_err(dev, "power supply register charger failed\n");
+ return PTR_ERR(bq->charger);
+ }
+
+ bq->battery = devm_power_supply_register(bq->dev,
+ &bq256xx_battery_desc,
+ psy_cfg);
+ if (IS_ERR(bq->battery)) {
+ dev_err(dev, "power supply register battery failed\n");
+ return PTR_ERR(bq->battery);
+ }
+ return 0;
+}
+
+static int bq256xx_hw_init(struct bq256xx_device *bq)
+{
+ struct power_supply_battery_info bat_info = { };
+ int wd_reg_val = BQ256XX_WATCHDOG_DIS;
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < BQ256XX_NUM_WD_VAL; i++) {
+ if (bq->watchdog_timer > bq256xx_watchdog_time[i] &&
+ bq->watchdog_timer < bq256xx_watchdog_time[i + 1])
+ wd_reg_val = i;
+ }
+ ret = regmap_update_bits(bq->regmap, BQ256XX_CHARGER_CONTROL_1,
+ BQ256XX_WATCHDOG_MASK, wd_reg_val <<
+ BQ256XX_WDT_BIT_SHIFT);
+
+ ret = power_supply_get_battery_info(bq->charger, &bat_info);
+ if (ret) {
+ dev_warn(bq->dev, "battery info missing, default values will be applied\n");
+
+ bat_info.constant_charge_current_max_ua =
+ bq->chip_info->bq256xx_def_ichg;
+
+ bat_info.constant_charge_voltage_max_uv =
+ bq->chip_info->bq256xx_def_vbatreg;
+
+ bat_info.precharge_current_ua =
+ bq->chip_info->bq256xx_def_iprechg;
+
+ bat_info.charge_term_current_ua =
+ bq->chip_info->bq256xx_def_iterm;
+
+ bq->init_data.ichg_max =
+ bq->chip_info->bq256xx_max_ichg;
+
+ bq->init_data.vbatreg_max =
+ bq->chip_info->bq256xx_max_vbatreg;
+ } else {
+ bq->init_data.ichg_max =
+ bat_info.constant_charge_current_max_ua;
+
+ bq->init_data.vbatreg_max =
+ bat_info.constant_charge_voltage_max_uv;
+ }
+
+ ret = bq->chip_info->bq256xx_set_vindpm(bq, bq->init_data.vindpm);
+ if (ret)
+ return ret;
+
+ ret = bq->chip_info->bq256xx_set_iindpm(bq, bq->init_data.iindpm);
+ if (ret)
+ return ret;
+
+ ret = bq->chip_info->bq256xx_set_ichg(bq,
+ bat_info.constant_charge_current_max_ua);
+ if (ret)
+ return ret;
+
+ ret = bq->chip_info->bq256xx_set_iprechg(bq,
+ bat_info.precharge_current_ua);
+ if (ret)
+ return ret;
+
+ ret = bq->chip_info->bq256xx_set_vbatreg(bq,
+ bat_info.constant_charge_voltage_max_uv);
+ if (ret)
+ return ret;
+
+ ret = bq->chip_info->bq256xx_set_iterm(bq,
+ bat_info.charge_term_current_ua);
+ if (ret)
+ return ret;
+
+ power_supply_put_battery_info(bq->charger, &bat_info);
+
+ return 0;
+}
+
+static int bq256xx_parse_dt(struct bq256xx_device *bq,
+ struct power_supply_config *psy_cfg, struct device *dev)
+{
+ int ret = 0;
+
+ psy_cfg->drv_data = bq;
+ psy_cfg->of_node = dev->of_node;
+
+ ret = device_property_read_u32(bq->dev, "ti,watchdog-timeout-ms",
+ &bq->watchdog_timer);
+ if (ret)
+ bq->watchdog_timer = BQ256XX_WATCHDOG_DIS;
+
+ if (bq->watchdog_timer > BQ256XX_WATCHDOG_MAX ||
+ bq->watchdog_timer < BQ256XX_WATCHDOG_DIS)
+ return -EINVAL;
+
+ ret = device_property_read_u32(bq->dev,
+ "input-voltage-limit-microvolt",
+ &bq->init_data.vindpm);
+ if (ret)
+ bq->init_data.vindpm = bq->chip_info->bq256xx_def_vindpm;
+
+ ret = device_property_read_u32(bq->dev,
+ "input-current-limit-microamp",
+ &bq->init_data.iindpm);
+ if (ret)
+ bq->init_data.iindpm = bq->chip_info->bq256xx_def_iindpm;
+
+ return 0;
+}
+
+static int bq256xx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct bq256xx_device *bq;
+ struct power_supply_config *psy_cfg;
+
+ int ret;
+
+ bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL);
+ if (!bq)
+ return -ENOMEM;
+
+ bq->client = client;
+ bq->dev = dev;
+ bq->chip_info = &bq256xx_chip_info_tbl[id->driver_data];
+
+ mutex_init(&bq->lock);
+
+ strncpy(bq->model_name, id->name, I2C_NAME_SIZE);
+
+ bq->regmap = devm_regmap_init_i2c(client,
+ bq->chip_info->bq256xx_regmap_config);
+
+ if (IS_ERR(bq->regmap)) {
+ dev_err(dev, "Failed to allocate register map\n");
+ return PTR_ERR(bq->regmap);
+ }
+
+ i2c_set_clientdata(client, bq);
+
+ ret = bq256xx_parse_dt(bq, psy_cfg, dev);
+ if (ret) {
+ dev_err(dev, "Failed to read device tree properties%d\n", ret);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(dev, bq256xx_charger_reset, bq);
+ if (ret)
+ return ret;
+
+ /* OTG reporting */
+ bq->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(bq->usb2_phy)) {
+ INIT_WORK(&bq->usb_work, bq256xx_usb_work);
+ bq->usb_nb.notifier_call = bq256xx_usb_notifier;
+ usb_register_notifier(bq->usb2_phy, &bq->usb_nb);
+ }
+
+ bq->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+ if (!IS_ERR_OR_NULL(bq->usb3_phy)) {
+ INIT_WORK(&bq->usb_work, bq256xx_usb_work);
+ bq->usb_nb.notifier_call = bq256xx_usb_notifier;
+ usb_register_notifier(bq->usb3_phy, &bq->usb_nb);
+ }
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(dev, client->irq, NULL,
+ bq256xx_irq_handler_thread,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ dev_name(&client->dev), bq);
+ if (ret < 0) {
+ dev_err(dev, "get irq fail: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = bq256xx_power_supply_init(bq, psy_cfg, dev);
+ if (ret) {
+ dev_err(dev, "Failed to register power supply\n");
+ return ret;
+ }
+
+ ret = bq256xx_hw_init(bq);
+ if (ret) {
+ dev_err(dev, "Cannot initialize the chip.\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static const struct i2c_device_id bq256xx_i2c_ids[] = {
+ { "bq25600", BQ25600 },
+ { "bq25600d", BQ25600D },
+ { "bq25601", BQ25601 },
+ { "bq25601d", BQ25601D },
+ { "bq25611d", BQ25611D },
+ { "bq25618", BQ25618 },
+ { "bq25619", BQ25619 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, bq256xx_i2c_ids);
+
+static const struct of_device_id bq256xx_of_match[] = {
+ { .compatible = "ti,bq25600", .data = (void *)BQ25600 },
+ { .compatible = "ti,bq25600d", .data = (void *)BQ25600D },
+ { .compatible = "ti,bq25601", .data = (void *)BQ25601 },
+ { .compatible = "ti,bq25601d", .data = (void *)BQ25601D },
+ { .compatible = "ti,bq25611d", .data = (void *)BQ25611D },
+ { .compatible = "ti,bq25618", .data = (void *)BQ25618 },
+ { .compatible = "ti,bq25619", .data = (void *)BQ25619 },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bq256xx_of_match);
+
+static const struct acpi_device_id bq256xx_acpi_match[] = {
+ { "bq25600", BQ25600 },
+ { "bq25600d", BQ25600D },
+ { "bq25601", BQ25601 },
+ { "bq25601d", BQ25601D },
+ { "bq25611d", BQ25611D },
+ { "bq25618", BQ25618 },
+ { "bq25619", BQ25619 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, bq256xx_acpi_match);
+
+static struct i2c_driver bq256xx_driver = {
+ .driver = {
+ .name = "bq256xx-charger",
+ .of_match_table = bq256xx_of_match,
+ .acpi_match_table = ACPI_PTR(bq256xx_acpi_match),
+ },
+ .probe = bq256xx_probe,
+ .id_table = bq256xx_i2c_ids,
+};
+module_i2c_driver(bq256xx_driver);
+
+MODULE_AUTHOR("Ricardo Rivera-Matos <[email protected]>");
+MODULE_DESCRIPTION("bq256xx charger driver");
+MODULE_LICENSE("GPL v2");
--
2.28.0


2021-01-05 03:27:43

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v8 2/2] power: supply: bq256xx: Introduce the BQ256XX charger driver

Hi Ricardo,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on power-supply/for-next]
[also build test WARNING on robh/for-next v5.11-rc2 next-20210104]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Ricardo-Rivera-Matos/Introduce-the-BQ256XX-family-of-chargers/20210105-043028
base: https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git for-next
config: powerpc64-randconfig-r034-20210105 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 5c951623bc8965fa1e89660f2f5f4a2944e4981a)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install powerpc64 cross compiling tool for clang build
# apt-get install binutils-powerpc64-linux-gnu
# https://github.com/0day-ci/linux/commit/82436c2c6d99c4effb187bbd09b47c4dc59a1f3d
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Ricardo-Rivera-Matos/Introduce-the-BQ256XX-family-of-chargers/20210105-043028
git checkout 82436c2c6d99c4effb187bbd09b47c4dc59a1f3d
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=powerpc64

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

drivers/power/supply/bq256xx_charger.c:1644:29: warning: variable 'psy_cfg' is uninitialized when used here [-Wuninitialized]
ret = bq256xx_parse_dt(bq, psy_cfg, dev);
^~~~~~~
drivers/power/supply/bq256xx_charger.c:1618:37: note: initialize the variable 'psy_cfg' to silence this warning
struct power_supply_config *psy_cfg;
^
= NULL
>> drivers/power/supply/bq256xx_charger.c:1720:36: warning: unused variable 'bq256xx_acpi_match' [-Wunused-const-variable]
static const struct acpi_device_id bq256xx_acpi_match[] = {
^
2 warnings generated.


vim +/bq256xx_acpi_match +1720 drivers/power/supply/bq256xx_charger.c

1719
> 1720 static const struct acpi_device_id bq256xx_acpi_match[] = {
1721 { "bq25600", BQ25600 },
1722 { "bq25600d", BQ25600D },
1723 { "bq25601", BQ25601 },
1724 { "bq25601d", BQ25601D },
1725 { "bq25611d", BQ25611D },
1726 { "bq25618", BQ25618 },
1727 { "bq25619", BQ25619 },
1728 {},
1729 };
1730 MODULE_DEVICE_TABLE(acpi, bq256xx_acpi_match);
1731

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (3.00 kB)
.config.gz (31.14 kB)
Download all attachments

2021-01-05 03:54:12

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v8 2/2] power: supply: bq256xx: Introduce the BQ256XX charger driver

Hi Ricardo,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on power-supply/for-next]
[also build test WARNING on robh/for-next v5.11-rc2 next-20210104]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Ricardo-Rivera-Matos/Introduce-the-BQ256XX-family-of-chargers/20210105-043028
base: https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git for-next
config: s390-randconfig-r005-20210105 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 5c951623bc8965fa1e89660f2f5f4a2944e4981a)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install s390 cross compiling tool for clang build
# apt-get install binutils-s390x-linux-gnu
# https://github.com/0day-ci/linux/commit/82436c2c6d99c4effb187bbd09b47c4dc59a1f3d
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Ricardo-Rivera-Matos/Introduce-the-BQ256XX-family-of-chargers/20210105-043028
git checkout 82436c2c6d99c4effb187bbd09b47c4dc59a1f3d
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=s390

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

include/uapi/linux/swab.h:19:12: note: expanded from macro '___constant_swab32'
(((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
^
In file included from drivers/power/supply/bq256xx_charger.c:13:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/s390/include/asm/io.h:80:
include/asm-generic/io.h:490:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
~~~~~~~~~~ ^
include/uapi/linux/byteorder/big_endian.h:34:59: note: expanded from macro '__le32_to_cpu'
#define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x))
^
include/uapi/linux/swab.h:119:21: note: expanded from macro '__swab32'
___constant_swab32(x) : \
^
include/uapi/linux/swab.h:20:12: note: expanded from macro '___constant_swab32'
(((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
^
In file included from drivers/power/supply/bq256xx_charger.c:13:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/s390/include/asm/io.h:80:
include/asm-generic/io.h:490:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
~~~~~~~~~~ ^
include/uapi/linux/byteorder/big_endian.h:34:59: note: expanded from macro '__le32_to_cpu'
#define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x))
^
include/uapi/linux/swab.h:119:21: note: expanded from macro '__swab32'
___constant_swab32(x) : \
^
include/uapi/linux/swab.h:21:12: note: expanded from macro '___constant_swab32'
(((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
^
In file included from drivers/power/supply/bq256xx_charger.c:13:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/s390/include/asm/io.h:80:
include/asm-generic/io.h:490:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
~~~~~~~~~~ ^
include/uapi/linux/byteorder/big_endian.h:34:59: note: expanded from macro '__le32_to_cpu'
#define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x))
^
include/uapi/linux/swab.h:119:21: note: expanded from macro '__swab32'
___constant_swab32(x) : \
^
include/uapi/linux/swab.h:22:12: note: expanded from macro '___constant_swab32'
(((__u32)(x) & (__u32)0xff000000UL) >> 24)))
^
In file included from drivers/power/supply/bq256xx_charger.c:13:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/s390/include/asm/io.h:80:
include/asm-generic/io.h:490:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
~~~~~~~~~~ ^
include/uapi/linux/byteorder/big_endian.h:34:59: note: expanded from macro '__le32_to_cpu'
#define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x))
^
include/uapi/linux/swab.h:120:12: note: expanded from macro '__swab32'
__fswab32(x))
^
In file included from drivers/power/supply/bq256xx_charger.c:13:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/s390/include/asm/io.h:80:
include/asm-generic/io.h:501:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writeb(value, PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:511:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:521:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:609:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
readsb(PCI_IOBASE + addr, buffer, count);
~~~~~~~~~~ ^
include/asm-generic/io.h:617:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
readsw(PCI_IOBASE + addr, buffer, count);
~~~~~~~~~~ ^
include/asm-generic/io.h:625:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
readsl(PCI_IOBASE + addr, buffer, count);
~~~~~~~~~~ ^
include/asm-generic/io.h:634:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
writesb(PCI_IOBASE + addr, buffer, count);
~~~~~~~~~~ ^
include/asm-generic/io.h:643:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
writesw(PCI_IOBASE + addr, buffer, count);
~~~~~~~~~~ ^
include/asm-generic/io.h:652:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
writesl(PCI_IOBASE + addr, buffer, count);
~~~~~~~~~~ ^
>> drivers/power/supply/bq256xx_charger.c:1644:29: warning: variable 'psy_cfg' is uninitialized when used here [-Wuninitialized]
ret = bq256xx_parse_dt(bq, psy_cfg, dev);
^~~~~~~
drivers/power/supply/bq256xx_charger.c:1618:37: note: initialize the variable 'psy_cfg' to silence this warning
struct power_supply_config *psy_cfg;
^
= NULL
>> drivers/power/supply/bq256xx_charger.c:1720:36: warning: unused variable 'bq256xx_acpi_match' [-Wunused-const-variable]
static const struct acpi_device_id bq256xx_acpi_match[] = {
^
22 warnings generated.


vim +/psy_cfg +1644 drivers/power/supply/bq256xx_charger.c

1612
1613 static int bq256xx_probe(struct i2c_client *client,
1614 const struct i2c_device_id *id)
1615 {
1616 struct device *dev = &client->dev;
1617 struct bq256xx_device *bq;
1618 struct power_supply_config *psy_cfg;
1619
1620 int ret;
1621
1622 bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL);
1623 if (!bq)
1624 return -ENOMEM;
1625
1626 bq->client = client;
1627 bq->dev = dev;
1628 bq->chip_info = &bq256xx_chip_info_tbl[id->driver_data];
1629
1630 mutex_init(&bq->lock);
1631
1632 strncpy(bq->model_name, id->name, I2C_NAME_SIZE);
1633
1634 bq->regmap = devm_regmap_init_i2c(client,
1635 bq->chip_info->bq256xx_regmap_config);
1636
1637 if (IS_ERR(bq->regmap)) {
1638 dev_err(dev, "Failed to allocate register map\n");
1639 return PTR_ERR(bq->regmap);
1640 }
1641
1642 i2c_set_clientdata(client, bq);
1643
> 1644 ret = bq256xx_parse_dt(bq, psy_cfg, dev);
1645 if (ret) {
1646 dev_err(dev, "Failed to read device tree properties%d\n", ret);
1647 return ret;
1648 }
1649
1650 ret = devm_add_action_or_reset(dev, bq256xx_charger_reset, bq);
1651 if (ret)
1652 return ret;
1653
1654 /* OTG reporting */
1655 bq->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
1656 if (!IS_ERR_OR_NULL(bq->usb2_phy)) {
1657 INIT_WORK(&bq->usb_work, bq256xx_usb_work);
1658 bq->usb_nb.notifier_call = bq256xx_usb_notifier;
1659 usb_register_notifier(bq->usb2_phy, &bq->usb_nb);
1660 }
1661
1662 bq->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
1663 if (!IS_ERR_OR_NULL(bq->usb3_phy)) {
1664 INIT_WORK(&bq->usb_work, bq256xx_usb_work);
1665 bq->usb_nb.notifier_call = bq256xx_usb_notifier;
1666 usb_register_notifier(bq->usb3_phy, &bq->usb_nb);
1667 }
1668
1669 if (client->irq) {
1670 ret = devm_request_threaded_irq(dev, client->irq, NULL,
1671 bq256xx_irq_handler_thread,
1672 IRQF_TRIGGER_FALLING |
1673 IRQF_ONESHOT,
1674 dev_name(&client->dev), bq);
1675 if (ret < 0) {
1676 dev_err(dev, "get irq fail: %d\n", ret);
1677 return ret;
1678 }
1679 }
1680
1681 ret = bq256xx_power_supply_init(bq, psy_cfg, dev);
1682 if (ret) {
1683 dev_err(dev, "Failed to register power supply\n");
1684 return ret;
1685 }
1686
1687 ret = bq256xx_hw_init(bq);
1688 if (ret) {
1689 dev_err(dev, "Cannot initialize the chip.\n");
1690 return ret;
1691 }
1692
1693 return ret;
1694 }
1695
1696 static const struct i2c_device_id bq256xx_i2c_ids[] = {
1697 { "bq25600", BQ25600 },
1698 { "bq25600d", BQ25600D },
1699 { "bq25601", BQ25601 },
1700 { "bq25601d", BQ25601D },
1701 { "bq25611d", BQ25611D },
1702 { "bq25618", BQ25618 },
1703 { "bq25619", BQ25619 },
1704 {},
1705 };
1706 MODULE_DEVICE_TABLE(i2c, bq256xx_i2c_ids);
1707
1708 static const struct of_device_id bq256xx_of_match[] = {
1709 { .compatible = "ti,bq25600", .data = (void *)BQ25600 },
1710 { .compatible = "ti,bq25600d", .data = (void *)BQ25600D },
1711 { .compatible = "ti,bq25601", .data = (void *)BQ25601 },
1712 { .compatible = "ti,bq25601d", .data = (void *)BQ25601D },
1713 { .compatible = "ti,bq25611d", .data = (void *)BQ25611D },
1714 { .compatible = "ti,bq25618", .data = (void *)BQ25618 },
1715 { .compatible = "ti,bq25619", .data = (void *)BQ25619 },
1716 { },
1717 };
1718 MODULE_DEVICE_TABLE(of, bq256xx_of_match);
1719
> 1720 static const struct acpi_device_id bq256xx_acpi_match[] = {
1721 { "bq25600", BQ25600 },
1722 { "bq25600d", BQ25600D },
1723 { "bq25601", BQ25601 },
1724 { "bq25601d", BQ25601D },
1725 { "bq25611d", BQ25611D },
1726 { "bq25618", BQ25618 },
1727 { "bq25619", BQ25619 },
1728 {},
1729 };
1730 MODULE_DEVICE_TABLE(acpi, bq256xx_acpi_match);
1731

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (13.40 kB)
.config.gz (13.32 kB)
Download all attachments

2021-01-05 14:20:54

by Sebastian Reichel

[permalink] [raw]
Subject: Re: [PATCH v8 2/2] power: supply: bq256xx: Introduce the BQ256XX charger driver

Hi Ricardo,

On Tue, Jan 05, 2021 at 11:24:18AM +0800, kernel test robot wrote:
> Hi Ricardo,
>
> Thank you for the patch! Perhaps something to improve:
>
> [auto build test WARNING on power-supply/for-next]
> [also build test WARNING on robh/for-next v5.11-rc2 next-20210104]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch]
>
> url: https://github.com/0day-ci/linux/commits/Ricardo-Rivera-Matos/Introduce-the-BQ256XX-family-of-chargers/20210105-043028
> base: https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git for-next
> config: powerpc64-randconfig-r034-20210105 (attached as .config)
> compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 5c951623bc8965fa1e89660f2f5f4a2944e4981a)
> reproduce (this is a W=1 build):
> wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # install powerpc64 cross compiling tool for clang build
> # apt-get install binutils-powerpc64-linux-gnu
> # https://github.com/0day-ci/linux/commit/82436c2c6d99c4effb187bbd09b47c4dc59a1f3d
> git remote add linux-review https://github.com/0day-ci/linux
> git fetch --no-tags linux-review Ricardo-Rivera-Matos/Introduce-the-BQ256XX-family-of-chargers/20210105-043028
> git checkout 82436c2c6d99c4effb187bbd09b47c4dc59a1f3d
> # save the attached .config to linux build tree
> COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=powerpc64
>
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot <[email protected]>
>
> All warnings (new ones prefixed by >>):
>
> drivers/power/supply/bq256xx_charger.c:1644:29: warning: variable 'psy_cfg' is uninitialized when used here [-Wuninitialized]
> ret = bq256xx_parse_dt(bq, psy_cfg, dev);
> ^~~~~~~
> drivers/power/supply/bq256xx_charger.c:1618:37: note: initialize the variable 'psy_cfg' to silence this warning
> struct power_supply_config *psy_cfg;
> ^
> = NULL

bah, I missed this serious issue during review :(

FWIW the compiler provided wrong solution. It would result in
dereferencing a NULL pointer afterwards since you never allocate
any memory for psy_cfg. You could of course allocate memory for
it, but power_supply_config is only needed during device
registration.

Proper solution is to initialize it as variable instead of pointer,
so that it ends up on the stack. Also you should initialize it with
{} to make sure any fields not explicitly configured are 0.

> >> drivers/power/supply/bq256xx_charger.c:1720:36: warning: unused variable 'bq256xx_acpi_match' [-Wunused-const-variable]
> static const struct acpi_device_id bq256xx_acpi_match[] = {

For this one just change

.acpi_match_table = ACPI_PTR(bq256xx_acpi_match),

into

.acpi_match_table = bq256xx_acpi_match,

> 2 warnings generated.
>
>
> vim +/bq256xx_acpi_match +1720 drivers/power/supply/bq256xx_charger.c
>
> 1719
> > 1720 static const struct acpi_device_id bq256xx_acpi_match[] = {
> 1721 { "bq25600", BQ25600 },
> 1722 { "bq25600d", BQ25600D },
> 1723 { "bq25601", BQ25601 },
> 1724 { "bq25601d", BQ25601D },
> 1725 { "bq25611d", BQ25611D },
> 1726 { "bq25618", BQ25618 },
> 1727 { "bq25619", BQ25619 },
> 1728 {},
> 1729 };
> 1730 MODULE_DEVICE_TABLE(acpi, bq256xx_acpi_match);
> 1731
>
> ---
> 0-DAY CI Kernel Test Service, Intel Corporation
> https://lists.01.org/hyperkitty/list/[email protected]

Thanks,

-- Sebastian


Attachments:
(No filename) (3.84 kB)
signature.asc (849.00 B)
Download all attachments

2021-01-05 22:58:18

by Ricardo Rivera-Matos

[permalink] [raw]
Subject: Re: [EXTERNAL] Re: [PATCH v8 2/2] power: supply: bq256xx: Introduce the BQ256XX charger driver

Sebastian,

On 1/5/21 8:18 AM, Sebastian Reichel wrote:
> Hi Ricardo,
>
> On Tue, Jan 05, 2021 at 11:24:18AM +0800, kernel test robot wrote:
>> Hi Ricardo,
>>
>> Thank you for the patch! Perhaps something to improve:
>>
>> [auto build test WARNING on power-supply/for-next]
>> [also build test WARNING on robh/for-next v5.11-rc2 next-20210104]
>> [If your patch is applied to the wrong git tree, kindly drop us a note.
>> And when submitting patch, we suggest to use '--base' as documented in
>> https://git-scm.com/docs/git-format-patch]
>>
>> url: https://github.com/0day-ci/linux/commits/Ricardo-Rivera-Matos/Introduce-the-BQ256XX-family-of-chargers/20210105-043028
>> base: https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git for-next
>> config: powerpc64-randconfig-r034-20210105 (attached as .config)
>> compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 5c951623bc8965fa1e89660f2f5f4a2944e4981a)
>> reproduce (this is a W=1 build):
>> wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>> chmod +x ~/bin/make.cross
>> # install powerpc64 cross compiling tool for clang build
>> # apt-get install binutils-powerpc64-linux-gnu
>> # https://github.com/0day-ci/linux/commit/82436c2c6d99c4effb187bbd09b47c4dc59a1f3d
>> git remote add linux-review https://github.com/0day-ci/linux
>> git fetch --no-tags linux-review Ricardo-Rivera-Matos/Introduce-the-BQ256XX-family-of-chargers/20210105-043028
>> git checkout 82436c2c6d99c4effb187bbd09b47c4dc59a1f3d
>> # save the attached .config to linux build tree
>> COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=powerpc64
>>
>> If you fix the issue, kindly add following tag as appropriate
>> Reported-by: kernel test robot <[email protected]>
>>
>> All warnings (new ones prefixed by >>):
>>
>> drivers/power/supply/bq256xx_charger.c:1644:29: warning: variable 'psy_cfg' is uninitialized when used here [-Wuninitialized]
>> ret = bq256xx_parse_dt(bq, psy_cfg, dev);
>> ^~~~~~~
>> drivers/power/supply/bq256xx_charger.c:1618:37: note: initialize the variable 'psy_cfg' to silence this warning
>> struct power_supply_config *psy_cfg;
>> ^
>> = NULL
> bah, I missed this serious issue during review :(
>
> FWIW the compiler provided wrong solution. It would result in
> dereferencing a NULL pointer afterwards since you never allocate
> any memory for psy_cfg. You could of course allocate memory for
> it, but power_supply_config is only needed during device
> registration.
>
> Proper solution is to initialize it as variable instead of pointer,
> so that it ends up on the stack. Also you should initialize it with
> {} to make sure any fields not explicitly configured are 0.
ACK
>
>>>> drivers/power/supply/bq256xx_charger.c:1720:36: warning: unused variable 'bq256xx_acpi_match' [-Wunused-const-variable]
>> static const struct acpi_device_id bq256xx_acpi_match[] = {
> For this one just change
>
> .acpi_match_table = ACPI_PTR(bq256xx_acpi_match),
>
> into
>
> .acpi_match_table = bq256xx_acpi_match,
ACK
>
>> 2 warnings generated.
>>
>>
>> vim +/bq256xx_acpi_match +1720 drivers/power/supply/bq256xx_charger.c
>>
>> 1719
>>> 1720 static const struct acpi_device_id bq256xx_acpi_match[] = {
>> 1721 { "bq25600", BQ25600 },
>> 1722 { "bq25600d", BQ25600D },
>> 1723 { "bq25601", BQ25601 },
>> 1724 { "bq25601d", BQ25601D },
>> 1725 { "bq25611d", BQ25611D },
>> 1726 { "bq25618", BQ25618 },
>> 1727 { "bq25619", BQ25619 },
>> 1728 {},
>> 1729 };
>> 1730 MODULE_DEVICE_TABLE(acpi, bq256xx_acpi_match);
>> 1731
>>
>> ---
>> 0-DAY CI Kernel Test Service, Intel Corporation
>> https://lists.01.org/hyperkitty/list/[email protected]
> Thanks,
>
> -- Sebastian
Thanks for the feedback on this!

Ricardo