* [PATCH 1/2] dt-bindings: power: Add the bq25790 dt bindings
@ 2020-07-30 14:58 Dan Murphy
2020-07-30 14:58 ` [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver Dan Murphy
2020-07-31 22:40 ` [PATCH 1/2] dt-bindings: power: Add the bq25790 dt bindings Rob Herring
0 siblings, 2 replies; 7+ messages in thread
From: Dan Murphy @ 2020-07-30 14:58 UTC (permalink / raw)
To: sre, robh; +Cc: devicetree, r-rivera-matos, linux-pm, linux-kernel, Dan Murphy
Add the bindings for the bq25790.
Signed-off-by: Ricardo Rivera-Matos <r-rivera-matos@ti.com>
Signed-off-by: Dan Murphy <dmurphy@ti.com>
---
.../bindings/power/supply/bq25790.yaml | 87 +++++++++++++++++++
1 file changed, 87 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/bq25790.yaml
diff --git a/Documentation/devicetree/bindings/power/supply/bq25790.yaml b/Documentation/devicetree/bindings/power/supply/bq25790.yaml
new file mode 100644
index 000000000000..97dd539c1625
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/bq25790.yaml
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2020 Texas Instruments Incorporated
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/power/supply/bq25790.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: TI BQ25790 Switch Mode Buck-Boost Charger
+
+maintainers:
+ - Dan Murphy <dmurphy@ti.com>
+
+description: |
+ BQ25790 is a highly integrated switch-mode buck-boost charger for 1-4 cell
+ Li-ion batteries and Li-polymer batteries. The device charges a battery from a
+ wide range of input sources including legacy USB adapters to high voltage USB
+ PD adapters and traditional barrel adapters.
+
+allOf:
+ - $ref: power-supply.yaml#
+
+properties:
+ compatible:
+ enum:
+ - ti,bq25790
+ - ti,bq25792
+
+ reg:
+ maxItems: 1
+
+ ti,watchdog-timer:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ Watchdog timer in milli seconds. 0 (default) disables the watchdog.
+ minimum: 0
+ maximum: 160000
+ enum: [ 0, 500, 1000, 2000, 20000, 40000, 80000, 160000]
+
+ input-voltage-limit-microvolt:
+ description: |
+ Minimum input voltage limit in micro volts with a 100000 micro volt step.
+ minimum: 3600000
+ maximum: 22000000
+
+ input-current-limit-microamp:
+ description: |
+ Maximum input current limit in micro amps with a 100000 micro amp step.
+ minimum: 100000
+ maximum: 3300000
+
+ monitored-battery:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to the battery node being monitored
+
+required:
+ - compatible
+ - reg
+ - monitored-battery
+
+examples:
+ - |
+ bat: battery {
+ compatible = "simple-battery";
+ constant-charge-current-max-microamp = <2000000>;
+ constant-charge-voltage-max-microvolt = <4200000>;
+ precharge-current-microamp = <160000>;
+ charge-term-current-microamp = <160000>;
+ };
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ bq25790: charger@6b {
+ compatible = "ti,bq25790";
+ reg = <0x6b>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+ ti,watchdog-timer = <2000>;
+ input-current-limit = <3000000>;
+ input-voltage-limit = <4500000>;
+ monitored-battery = <&bat>;
+ };
+ };
+
+...
--
2.28.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver
2020-07-30 14:58 [PATCH 1/2] dt-bindings: power: Add the bq25790 dt bindings Dan Murphy
@ 2020-07-30 14:58 ` Dan Murphy
2020-07-30 15:14 ` Ricardo Rivera-Matos
2020-08-05 11:59 ` Dan Carpenter
2020-07-31 22:40 ` [PATCH 1/2] dt-bindings: power: Add the bq25790 dt bindings Rob Herring
1 sibling, 2 replies; 7+ messages in thread
From: Dan Murphy @ 2020-07-30 14:58 UTC (permalink / raw)
To: sre, robh; +Cc: devicetree, r-rivera-matos, linux-pm, linux-kernel, Dan Murphy
BQ25790 is a highly integrated switch-mode buck-boost charger
for 1-4 cell Li-ion battery and Li-polymer battery.
Signed-off-by: Dan Murphy <dmurphy@ti.com>
---
drivers/power/supply/Kconfig | 8 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/bq25790_charger.c | 1117 ++++++++++++++++++++++++
drivers/power/supply/bq25790_charger.h | 150 ++++
4 files changed, 1276 insertions(+)
create mode 100644 drivers/power/supply/bq25790_charger.c
create mode 100644 drivers/power/supply/bq25790_charger.h
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index faf2830aa152..802c644d92be 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -623,6 +623,14 @@ config CHARGER_BQ2515X
rail, ADC for battery and system monitoring, and push-button
controller.
+config CHARGER_BQ25790
+ tristate "TI BQ25790 battery charger driver"
+ depends on I2C
+ depends on GPIOLIB || COMPILE_TEST
+ select REGMAP_I2C
+ help
+ Say Y to enable support for the TI BQ25790 battery charger.
+
config CHARGER_BQ25890
tristate "TI BQ25890 battery charger driver"
depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index b3c694a65114..ae269b9f624b 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -84,6 +84,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_BQ25790) += bq25790_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/bq25790_charger.c b/drivers/power/supply/bq25790_charger.c
new file mode 100644
index 000000000000..92fa859ef55c
--- /dev/null
+++ b/drivers/power/supply/bq25790_charger.c
@@ -0,0 +1,1117 @@
+// SPDX-License-Identifier: GPL-2.0
+// BQ25790 driver
+// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/usb/phy.h>
+
+#include <linux/acpi.h>
+#include <linux/of.h>
+
+#include "bq25790_charger.h"
+
+#define BQ25790_NUM_WD_VAL 8
+
+struct bq25790_init_data {
+ u32 ichg;
+ u32 ilim;
+ u32 vreg;
+ u32 iterm;
+ u32 iprechg;
+ u32 vlim;
+ u32 ichg_max;
+ u32 vreg_max;
+};
+
+struct bq25790_state {
+ bool online;
+ u8 chrg_status;
+ u8 chrg_type;
+ u8 health;
+ u8 chrg_fault;
+ u8 vsys_status;
+ u8 vbus_status;
+ u8 fault_0;
+ u8 fault_1;
+ u32 vbat_adc;
+ u32 vbus_adc;
+ u32 ibat_adc;
+};
+
+struct bq25790_device {
+ struct i2c_client *client;
+ struct device *dev;
+ struct power_supply *charger;
+ struct power_supply *battery;
+ struct mutex lock;
+
+ struct usb_phy *usb2_phy;
+ struct usb_phy *usb3_phy;
+ struct notifier_block usb_nb;
+ struct work_struct usb_work;
+ unsigned long usb_event;
+ struct regmap *regmap;
+
+ char model_name[I2C_NAME_SIZE];
+ int device_id;
+
+ struct bq25790_init_data init_data;
+ struct bq25790_state state;
+ int watchdog_timer;
+};
+
+static struct reg_default bq25790_reg_defs[] = {
+ {BQ25790_INPUT_V_LIM, 0x24},
+ {BQ25790_INPUT_I_LIM_MSB, 0x01},
+ {BQ25790_INPUT_I_LIM_LSB, 0x2c},
+ {BQ25790_PRECHRG_CTRL, 0xc3},
+ {BQ25790_TERM_CTRL, 0x5},
+ {BQ25790_VOTG_REG, 0xdc},
+ {BQ25790_IOTG_REG, 0x4b},
+ {BQ25790_TIMER_CTRL, 0x3d},
+ {BQ25790_CHRG_CTRL_0, 0xa2},
+ {BQ25790_CHRG_CTRL_1, 0x85},
+ {BQ25790_CHRG_CTRL_2, 0x40},
+ {BQ25790_CHRG_CTRL_3, 0x12},
+ {BQ25790_CHRG_CTRL_5, 0x16},
+ {BQ25790_MPPT_CTRL, 0xaa},
+ {BQ25790_TEMP_CTRL, 0xc0},
+ {BQ25790_NTC_CTRL_0, 0x7a},
+ {BQ25790_NTC_CTRL_1, 0x54},
+ {BQ25790_ICO_I_LIM, 0x0},
+ {BQ25790_CHRG_STAT_0, 0x0},
+ {BQ25790_CHRG_STAT_1, 0x0},
+ {BQ25790_CHRG_STAT_2, 0x0},
+ {BQ25790_CHRG_STAT_3, 0x0},
+ {BQ25790_CHRG_STAT_4, 0x0},
+ {BQ25790_FAULT_STAT_0, 0x0},
+ {BQ25790_FAULT_STAT_1, 0x0},
+ {BQ25790_CHRG_FLAG_0, 0x0},
+ {BQ25790_CHRG_FLAG_1, 0x0},
+ {BQ25790_CHRG_FLAG_2, 0x0},
+ {BQ25790_CHRG_FLAG_3, 0x0},
+ {BQ25790_FAULT_FLAG_0, 0x0},
+ {BQ25790_FAULT_FLAG_1, 0x0},
+ {BQ25790_CHRG_MSK_0, 0x0},
+ {BQ25790_CHRG_MSK_1, 0x0},
+ {BQ25790_CHRG_MSK_2, 0x0},
+ {BQ25790_CHRG_MSK_3, 0x0},
+ {BQ25790_FAULT_MSK_0, 0x0},
+ {BQ25790_FAULT_MSK_1, 0x0},
+ {BQ25790_ADC_CTRL, 0x30},
+ {BQ25790_FN_DISABE_0, 0x0},
+ {BQ25790_FN_DISABE_1, 0x0},
+ {BQ25790_ADC_IBUS, 0x0},
+ {BQ25790_ADC_IBAT_MSB, 0x0},
+ {BQ25790_ADC_IBAT_LSB, 0x0},
+ {BQ25790_ADC_VBUS_MSB, 0x0},
+ {BQ25790_ADC_VBUS_LSB, 0x0},
+ {BQ25790_ADC_VAC1, 0x0},
+ {BQ25790_ADC_VAC2, 0x0},
+ {BQ25790_ADC_VBAT_MSB, 0x0},
+ {BQ25790_ADC_VBAT_LSB, 0x0},
+ {BQ25790_ADC_VBUS_MSB, 0x0},
+ {BQ25790_ADC_VBUS_LSB, 0x0},
+ {BQ25790_ADC_TS, 0x0},
+ {BQ25790_ADC_TDIE, 0x0},
+ {BQ25790_ADC_DP, 0x0},
+ {BQ25790_ADC_DM, 0x0},
+ {BQ25790_DPDM_DRV, 0x0},
+ {BQ25790_PART_INFO, 0x0},
+};
+
+static int bq25790_watchdog_time[BQ25790_NUM_WD_VAL] = {0, 500, 1000, 2000,
+ 20000, 40000, 80000,
+ 160000};
+
+static enum power_supply_usb_type bq25790_usb_type[] = {
+ POWER_SUPPLY_USB_TYPE_PD_DRP,
+ POWER_SUPPLY_USB_TYPE_SDP,
+ POWER_SUPPLY_USB_TYPE_CDP,
+ POWER_SUPPLY_USB_TYPE_DCP,
+ POWER_SUPPLY_USB_TYPE_UNKNOWN,
+};
+
+static int bq25790_usb_notifier(struct notifier_block *nb, unsigned long val,
+ void *priv)
+{
+ struct bq25790_device *bq =
+ container_of(nb, struct bq25790_device, usb_nb);
+
+ bq->usb_event = val;
+ queue_work(system_power_efficient_wq, &bq->usb_work);
+
+ return NOTIFY_OK;
+}
+
+static void bq25790_usb_work(struct work_struct *data)
+{
+ struct bq25790_device *bq =
+ container_of(data, struct bq25790_device, usb_work);
+
+ switch (bq->usb_event) {
+ case USB_EVENT_ID:
+ break;
+
+ case USB_EVENT_NONE:
+ power_supply_changed(bq->charger);
+ break;
+ }
+
+ return;
+
+ dev_err(bq->dev, "Error switching to charger mode.\n");
+}
+
+static int bq25790_get_vbat_adc(struct bq25790_device *bq)
+{
+ int ret;
+ int vbat_adc_lsb, vbat_adc_msb;
+ u16 vbat_adc;
+
+ ret = regmap_read(bq->regmap, BQ25790_ADC_VBAT_MSB, &vbat_adc_msb);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(bq->regmap, BQ25790_ADC_VBAT_LSB, &vbat_adc_lsb);
+ if (ret)
+ return ret;
+
+ vbat_adc = (vbat_adc_msb << 8) | vbat_adc_lsb;
+
+ return vbat_adc * BQ25790_ADC_VOLT_STEP_uV;
+}
+
+static int bq25790_get_vbus_adc(struct bq25790_device *bq)
+{
+ int ret;
+ int vbus_adc_lsb, vbus_adc_msb;
+ u16 vbus_adc;
+
+ ret = regmap_update_bits(bq->regmap, BQ25790_ADC_CTRL,
+ BQ25790_ADC_EN, BQ25790_ADC_EN);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(bq->regmap, BQ25790_ADC_VBUS_MSB, &vbus_adc_msb);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(bq->regmap, BQ25790_ADC_VBUS_LSB, &vbus_adc_lsb);
+ if (ret)
+ return ret;
+
+ vbus_adc = (vbus_adc_msb << 8) | vbus_adc_lsb;
+
+ return vbus_adc * BQ25790_ADC_VOLT_STEP_uV;
+}
+
+static int bq25790_get_ibat_adc(struct bq25790_device *bq)
+{
+ int ret;
+ int ibat_adc_lsb, ibat_adc_msb;
+ u16 ibat_adc;
+
+ ret = regmap_read(bq->regmap, BQ25790_ADC_IBAT_MSB, &ibat_adc_msb);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(bq->regmap, BQ25790_ADC_IBAT_LSB, &ibat_adc_lsb);
+ if (ret)
+ return ret;
+
+ ibat_adc = (ibat_adc_msb << 8) | ibat_adc_lsb;
+
+ return ibat_adc * BQ25790_ADC_CURR_STEP_uA;
+}
+
+static int bq25790_get_term_curr(struct bq25790_device *bq)
+{
+ int ret;
+ int reg_val;
+
+ ret = regmap_read(bq->regmap, BQ25790_TERM_CTRL, ®_val);
+ if (ret)
+ return ret;
+
+ reg_val &= BQ25790_TERMCHRG_CUR_MASK;
+
+ return reg_val * BQ25790_TERMCHRG_CURRENT_STEP_uA;
+}
+
+static int bq25790_get_prechrg_curr(struct bq25790_device *bq)
+{
+ int ret;
+ int reg_val;
+
+ ret = regmap_read(bq->regmap, BQ25790_PRECHRG_CTRL, ®_val);
+ if (ret)
+ return ret;
+
+ reg_val &= BQ25790_PRECHRG_CUR_MASK;
+
+ return reg_val * BQ25790_PRECHRG_CURRENT_STEP_uA;
+}
+
+static int bq25790_get_ichg_curr(struct bq25790_device *bq)
+{
+ int ret;
+ int ichg, ichg_lsb, ichg_msb;
+
+ ret = regmap_read(bq->regmap, BQ25790_CHRG_I_LIM_LSB, &ichg_lsb);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(bq->regmap, BQ25790_CHRG_I_LIM_MSB, &ichg_msb);
+ if (ret)
+ return ret;
+
+ ichg = (ichg_msb << 8) | ichg_lsb;
+
+ return ichg * BQ25790_ICHRG_CURRENT_STEP_uA;
+}
+
+static int bq25790_set_term_curr(struct bq25790_device *bq, int term_current)
+{
+ int reg_val;
+
+ if (term_current < BQ25790_TERMCHRG_I_MIN_uA ||
+ term_current > BQ25790_TERMCHRG_I_MAX_uA)
+ return -EINVAL;
+
+ reg_val = term_current / BQ25790_TERMCHRG_CURRENT_STEP_uA;
+
+ return regmap_update_bits(bq->regmap, BQ25790_TERM_CTRL,
+ BQ25790_TERMCHRG_CUR_MASK, reg_val);
+}
+
+static int bq25790_set_prechrg_curr(struct bq25790_device *bq, int pre_current)
+{
+ int reg_val;
+
+ if (pre_current < BQ25790_PRECHRG_I_MIN_uA ||
+ pre_current > BQ25790_PRECHRG_I_MAX_uA)
+ return -EINVAL;
+
+ reg_val = pre_current / BQ25790_PRECHRG_CURRENT_STEP_uA;
+
+ return regmap_update_bits(bq->regmap, BQ25790_PRECHRG_CTRL,
+ BQ25790_PRECHRG_CUR_MASK, reg_val);
+}
+
+static int bq25790_set_ichrg_curr(struct bq25790_device *bq, int chrg_curr)
+{
+ int ret;
+ int ichg, ichg_msb, ichg_lsb;
+
+ if (chrg_curr < BQ25790_ICHRG_I_MIN_uA ||
+ chrg_curr > BQ25790_ICHRG_I_MAX_uA)
+ return -EINVAL;
+
+ ichg = chrg_curr / BQ25790_ICHRG_CURRENT_STEP_uA;
+ ichg_msb = (ichg >> 8) & 0xff;
+ ret = regmap_write(bq->regmap, BQ25790_CHRG_I_LIM_MSB, ichg_msb);
+ if (ret)
+ return ret;
+
+ ichg_lsb = ichg & 0xff;
+
+ return regmap_write(bq->regmap, BQ25790_CHRG_I_LIM_LSB, ichg_lsb);
+}
+
+static int bq25790_set_chrg_volt(struct bq25790_device *bq, int chrg_volt)
+{
+ int vlim_lsb, vlim_msb, vlim;
+ int ret;
+
+ if (chrg_volt < BQ25790_VREG_V_MIN_uV ||
+ chrg_volt > BQ25790_VREG_V_MAX_uV)
+ return -EINVAL;
+
+ vlim = chrg_volt / BQ25790_VREG_V_STEP_uV;
+ vlim_msb = (vlim >> 8) & 0xff;
+ ret = regmap_write(bq->regmap, BQ25790_CHRG_V_LIM_MSB, vlim_msb);
+ if (ret)
+ return ret;
+
+ vlim_lsb = vlim & 0xff;
+
+ return regmap_write(bq->regmap, BQ25790_CHRG_V_LIM_LSB, vlim_lsb);
+}
+
+static int bq25790_get_chrg_volt(struct bq25790_device *bq)
+{
+ int ret;
+ int vlim_lsb, vlim_msb, chrg_volt;
+
+ ret = regmap_read(bq->regmap, BQ25790_CHRG_V_LIM_MSB, &vlim_msb);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(bq->regmap, BQ25790_CHRG_V_LIM_LSB, &vlim_lsb);
+ if (ret)
+ return ret;
+
+ chrg_volt = (vlim_msb << 8) | vlim_lsb;
+
+ return chrg_volt * BQ25790_VREG_V_STEP_uV;
+}
+
+static int bq25790_set_input_volt_lim(struct bq25790_device *bq, int vindpm)
+{
+ int ret;
+ int vlim_lsb, vlim_msb;
+ int vlim;
+
+ if (vindpm < BQ25790_VINDPM_V_MIN_uV ||
+ vindpm > BQ25790_VINDPM_V_MAX_uV)
+ return -EINVAL;
+
+ vlim = vindpm / BQ25790_VINDPM_STEP_uV;
+
+ vlim_msb = (vlim >> 8) & 0xff;
+
+ ret = regmap_write(bq->regmap, BQ25790_CHRG_V_LIM_MSB, vlim_msb);
+ if (ret)
+ return ret;
+
+ vlim_lsb = vlim & 0xff;
+
+ return regmap_write(bq->regmap, BQ25790_CHRG_V_LIM_LSB, vlim_lsb);
+}
+
+static int bq25790_get_input_volt_lim(struct bq25790_device *bq)
+{
+ int ret;
+ int vlim;
+
+ ret = regmap_read(bq->regmap, BQ25790_INPUT_V_LIM, &vlim);
+ if (ret)
+ return ret;
+
+ return vlim * BQ25790_VINDPM_STEP_uV;
+}
+
+static int bq25790_set_input_curr_lim(struct bq25790_device *bq, int iindpm)
+{
+ int ret;
+ int ilim, ilim_lsb, ilim_msb;
+
+ if (iindpm < BQ25790_IINDPM_I_MIN_uA ||
+ iindpm > BQ25790_IINDPM_I_MAX_uA)
+ return -EINVAL;
+
+ ilim = iindpm / BQ25790_IINDPM_STEP_uA;
+ ilim_msb = (ilim >> 8) & 0xff;
+
+ ret = regmap_write(bq->regmap, BQ25790_INPUT_I_LIM_MSB, ilim_msb);
+ if (ret)
+ return ret;
+
+ ilim_lsb = ilim & 0xff;
+
+ return regmap_write(bq->regmap, BQ25790_INPUT_I_LIM_LSB, ilim_lsb);
+}
+
+static int bq25790_get_input_curr_lim(struct bq25790_device *bq)
+{
+ int ret;
+ int ilim_msb, ilim_lsb;
+ u16 ilim;
+
+ ret = regmap_read(bq->regmap, BQ25790_INPUT_I_LIM_MSB, &ilim_msb);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(bq->regmap, BQ25790_INPUT_I_LIM_LSB, &ilim_lsb);
+ if (ret)
+ return ret;
+
+ ilim = (ilim_msb << 8) | ilim_lsb;
+
+ return ilim * BQ25790_IINDPM_STEP_uA;
+}
+
+static int bq25790_get_state(struct bq25790_device *bq,
+ struct bq25790_state *state)
+{
+ int chrg_stat_0, chrg_stat_1, chrg_stat_3, chrg_stat_4;
+ int chrg_ctrl_0, fault_0, fault_1;
+ int ret;
+
+ ret = regmap_read(bq->regmap, BQ25790_CHRG_STAT_0, &chrg_stat_0);
+ if (ret)
+ return ret;
+
+ state->vbus_status = chrg_stat_0 & BQ25790_VBUS_PRESENT;
+
+ ret = regmap_read(bq->regmap, BQ25790_CHRG_STAT_1, &chrg_stat_1);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(bq->regmap, BQ25790_CHRG_CTRL_0, &chrg_ctrl_0);
+ if (ret)
+ return ret;
+
+ if (chrg_ctrl_0 & BQ25790_CHRG_EN)
+ state->chrg_status = chrg_stat_1 & BQ25790_CHG_STAT_MSK;
+ else
+ state->chrg_status = BQ25790_NOT_CHRGING;
+
+ state->chrg_type = chrg_stat_1 & BQ25790_VBUS_STAT_MSK;
+
+ ret = regmap_read(bq->regmap, BQ25790_CHRG_STAT_4, &chrg_stat_4);
+ if (ret)
+ return ret;
+
+ state->health = chrg_stat_4 & BQ25790_TEMP_MASK;
+
+ ret = regmap_read(bq->regmap, BQ25790_FAULT_STAT_0, &fault_0);
+ if (ret)
+ return ret;
+
+ state->fault_0 = fault_0;
+
+ ret = regmap_read(bq->regmap, BQ25790_FAULT_STAT_1, &fault_1);
+ if (ret)
+ return ret;
+
+ state->fault_1 = fault_1;
+
+ ret = regmap_read(bq->regmap, BQ25790_CHRG_STAT_3, &chrg_stat_3);
+ if (ret)
+ return ret;
+
+ state->online = chrg_stat_3 & BQ25790_VSYS_STAT;
+
+ state->vbat_adc = bq25790_get_vbat_adc(bq);
+
+ state->vbus_adc = bq25790_get_vbus_adc(bq);
+
+ state->ibat_adc = bq25790_get_ibat_adc(bq);
+
+ return 0;
+}
+
+static int bq25790_set_property(struct power_supply *psy,
+ enum power_supply_property prop,
+ const union power_supply_propval *val)
+{
+ struct bq25790_device *bq = power_supply_get_drvdata(psy);
+ int ret = -EINVAL;
+
+ switch (prop) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ ret = bq25790_set_input_curr_lim(bq, val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ ret = bq25790_set_chrg_volt(bq, val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ ret = bq25790_set_ichrg_curr(bq, val->intval);
+ break;
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ ret = bq25790_set_prechrg_curr(bq, val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ ret = bq25790_set_term_curr(bq, val->intval);
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ break;
+ case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
+ ret = bq25790_set_input_volt_lim(bq, val->intval);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int bq25790_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bq25790_device *bq = power_supply_get_drvdata(psy);
+ struct bq25790_state state;
+ int ret = 0;
+
+ mutex_lock(&bq->lock);
+ ret = bq25790_get_state(bq, &state);
+ mutex_unlock(&bq->lock);
+ if (ret)
+ return ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (!state.chrg_type || (state.chrg_type == BQ25790_OTG_MODE))
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (!state.chrg_status)
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else if (state.chrg_status == BQ25790_TERM_CHRG)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ switch (state.chrg_status) {
+ case BQ25790_TRICKLE_CHRG:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ case BQ25790_PRECHRG:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ case BQ25790_FAST_CHRG:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+ break;
+ case BQ25790_TAPER_CHRG:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
+ break;
+ case BQ25790_TOP_OFF_CHRG:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ case BQ25790_NOT_CHRGING:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+ }
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = BQ25790_MANUFACTURER;
+ break;
+
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = BQ25790_NAME;
+ break;
+
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = state.online;
+ break;
+ case POWER_SUPPLY_PROP_USB_TYPE:
+ if (!state.chrg_type) {
+ val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+ break;
+ }
+ switch (state.chrg_type) {
+ case BQ25790_USB_SDP:
+ val->intval = POWER_SUPPLY_USB_TYPE_SDP;
+ break;
+ case BQ25790_USB_CDP:
+ val->intval = POWER_SUPPLY_USB_TYPE_CDP;
+ break;
+ case BQ25790_USB_DCP:
+ val->intval = POWER_SUPPLY_USB_TYPE_DCP;
+ break;
+ case BQ25790_OTG_MODE:
+ val->intval = POWER_SUPPLY_USB_TYPE_PD_DRP;
+ break;
+
+ default:
+ val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+ break;
+ }
+ break;
+
+ case POWER_SUPPLY_PROP_HEALTH:
+ if (state.fault_1 && (BQ25790_OTG_OVP | BQ25790_VSYS_OVP))
+ val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ else
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+
+ switch (state.health) {
+ case BQ25790_TEMP_HOT:
+ val->intval = POWER_SUPPLY_HEALTH_HOT;
+ break;
+ case BQ25790_TEMP_WARM:
+ val->intval = POWER_SUPPLY_HEALTH_WARM;
+ break;
+ case BQ25790_TEMP_COOL:
+ val->intval = POWER_SUPPLY_HEALTH_COOL;
+ break;
+ case BQ25790_TEMP_COLD:
+ val->intval = POWER_SUPPLY_HEALTH_COLD;
+ break;
+ }
+ break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ ret = bq25790_get_ichg_curr(bq);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
+ break;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ ret = bq25790_get_chrg_volt(bq);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
+ break;
+
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ ret = bq25790_get_prechrg_curr(bq);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ ret = bq25790_get_term_curr(bq);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = state.vbus_adc;
+ break;
+ case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
+ ret = bq25790_get_input_volt_lim(bq);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
+ break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ ret = bq25790_get_input_curr_lim(bq);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int bq25790_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bq25790_device *bq = power_supply_get_drvdata(psy);
+ struct bq25790_state state;
+ int ret = 0;
+
+ mutex_lock(&bq->lock);
+ ret = bq25790_get_state(bq, &state);
+ mutex_unlock(&bq->lock);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(bq->regmap, BQ25790_ADC_CTRL,
+ BQ25790_ADC_EN, BQ25790_ADC_EN);
+ if (ret)
+ return ret;
+
+ 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.vreg_max;
+ break;
+
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = state.vbat_adc;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = state.ibat_adc;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static bool bq25790_state_changed(struct bq25790_device *bq,
+ struct bq25790_state *new_state)
+{
+ struct bq25790_state old_state;
+
+ mutex_lock(&bq->lock);
+ old_state = bq->state;
+ mutex_unlock(&bq->lock);
+
+ return (old_state.chrg_status != new_state->chrg_status ||
+ old_state.chrg_fault != new_state->chrg_fault ||
+ old_state.online != new_state->online ||
+ old_state.health != new_state->health ||
+ old_state.fault_0 != new_state->fault_0 ||
+ old_state.fault_1 != new_state->fault_1 ||
+ old_state.chrg_type != new_state->chrg_type ||
+ old_state.vsys_status != new_state->vsys_status ||
+ old_state.vbat_adc != new_state->vbat_adc ||
+ old_state.vbus_adc != new_state->vbus_adc ||
+ old_state.ibat_adc != new_state->ibat_adc);
+}
+
+static irqreturn_t bq25790_irq_handler_thread(int irq, void *private)
+{
+ struct bq25790_device *bq = private;
+ struct bq25790_state state;
+ int ret;
+
+ ret = bq25790_get_state(bq, &state);
+ if (ret < 0)
+ goto irq_out;
+
+ if (!bq25790_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 bq25790_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_CONSTANT_CHARGE_CURRENT,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
+ POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
+ POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_USB_TYPE,
+};
+
+static enum power_supply_property bq25790_battery_props[] = {
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+static char *bq25790_charger_supplied_to[] = {
+ "main-battery",
+};
+
+static int bq25790_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 bq25790_power_supply_desc = {
+ .name = "bq25790-charger",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .usb_types = bq25790_usb_type,
+ .num_usb_types = ARRAY_SIZE(bq25790_usb_type),
+ .properties = bq25790_power_supply_props,
+ .num_properties = ARRAY_SIZE(bq25790_power_supply_props),
+ .get_property = bq25790_get_property,
+ .set_property = bq25790_set_property,
+ .property_is_writeable = bq25790_property_is_writeable,
+};
+
+static const struct power_supply_desc bq25790_battery_desc = {
+ .name = "bq25790-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .get_property = bq25790_battery_get_property,
+ .properties = bq25790_battery_props,
+ .num_properties = ARRAY_SIZE(bq25790_battery_props),
+};
+
+static bool bq25790_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case BQ25790_ICO_I_LIM...BQ25790_FAULT_FLAG_1:
+ case BQ25790_ADC_IBUS...BQ25790_ADC_DM:
+ case BQ25790_CHRG_CTRL_0:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config bq25790_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = BQ25790_PART_INFO,
+ .reg_defaults = bq25790_reg_defs,
+ .num_reg_defaults = ARRAY_SIZE(bq25790_reg_defs),
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = bq25790_is_volatile_reg,
+};
+
+static int bq25790_power_supply_init(struct bq25790_device *bq,
+ struct device *dev)
+{
+ struct power_supply_config psy_cfg = { .drv_data = bq,
+ .of_node = dev->of_node, };
+
+ psy_cfg.supplied_to = bq25790_charger_supplied_to;
+ psy_cfg.num_supplicants = ARRAY_SIZE(bq25790_charger_supplied_to);
+
+ bq->charger = devm_power_supply_register(bq->dev,
+ &bq25790_power_supply_desc,
+ &psy_cfg);
+ if (IS_ERR(bq->charger))
+ return -EINVAL;
+
+ bq->battery = devm_power_supply_register(bq->dev,
+ &bq25790_battery_desc,
+ &psy_cfg);
+ if (IS_ERR(bq->battery))
+ return -EINVAL;
+ return 0;
+}
+
+static int bq25790_hw_init(struct bq25790_device *bq)
+{
+ struct power_supply_battery_info bat_info = { };
+ int wd_reg_val;
+ int ret = 0;
+ int i;
+
+ if (bq->watchdog_timer) {
+ for (i = 0; i < BQ25790_NUM_WD_VAL; i++) {
+ if (bq->watchdog_timer > bq25790_watchdog_time[i] &&
+ bq->watchdog_timer < bq25790_watchdog_time[i + 1]) {
+ wd_reg_val = i;
+ break;
+ }
+ }
+ } else
+ wd_reg_val = BQ25790_WATCHDOG_DIS;
+
+ ret = regmap_update_bits(bq->regmap, BQ25790_CHRG_CTRL_1,
+ BQ25790_WATCHDOG_MASK, wd_reg_val);
+
+ 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 =
+ BQ25790_ICHRG_I_DEF_uA;
+
+ bat_info.constant_charge_voltage_max_uv =
+ BQ25790_VREG_V_DEF_uV;
+
+ bat_info.precharge_current_ua = BQ25790_PRECHRG_I_DEF_uA;
+ bat_info.charge_term_current_ua = BQ25790_TERMCHRG_I_DEF_uA;
+ bq->init_data.ichg_max = BQ25790_ICHRG_I_MAX_uA;
+ bq->init_data.vreg_max = BQ25790_VREG_V_MAX_uV;
+ } else {
+ bq->init_data.ichg_max =
+ bat_info.constant_charge_current_max_ua;
+
+ bq->init_data.vreg_max =
+ bat_info.constant_charge_voltage_max_uv;
+ }
+
+ ret = bq25790_set_ichrg_curr(bq,
+ bat_info.constant_charge_current_max_ua);
+ if (ret)
+ goto err_out;
+
+ ret = bq25790_set_prechrg_curr(bq, bat_info.precharge_current_ua);
+ if (ret)
+ goto err_out;
+
+ ret = bq25790_set_chrg_volt(bq,
+ bat_info.constant_charge_voltage_max_uv);
+ if (ret)
+ goto err_out;
+
+ ret = bq25790_set_term_curr(bq, bat_info.charge_term_current_ua);
+ if (ret)
+ goto err_out;
+
+ ret = bq25790_set_input_volt_lim(bq, bq->init_data.vlim);
+ if (ret)
+ goto err_out;
+
+ ret = bq25790_set_input_curr_lim(bq, bq->init_data.ilim);
+ if (ret)
+ goto err_out;
+
+err_out:
+ return ret;
+}
+
+static int bq25790_parse_dt(struct bq25790_device *bq)
+{
+ int ret;
+
+ ret = device_property_read_u32(bq->dev, "ti,watchdog-timer",
+ &bq->watchdog_timer);
+ if (ret)
+ bq->watchdog_timer = BQ25790_WATCHDOG_DIS;
+
+ if (bq->watchdog_timer > BQ25790_WATCHDOG_MAX ||
+ bq->watchdog_timer < BQ25790_WATCHDOG_DIS)
+ return -EINVAL;
+
+ ret = device_property_read_u32(bq->dev,
+ "input-voltage-limit-microvolt",
+ &bq->init_data.vlim);
+ if (ret)
+ bq->init_data.vlim = BQ25790_VINDPM_DEF_uV;
+
+ if (bq->init_data.vlim > BQ25790_VINDPM_V_MAX_uV ||
+ bq->init_data.vlim < BQ25790_VINDPM_V_MIN_uV)
+ return -EINVAL;
+
+ ret = device_property_read_u32(bq->dev,
+ "input-current-limit-microamp",
+ &bq->init_data.ilim);
+ if (ret)
+ bq->init_data.ilim = BQ25790_IINDPM_DEF_uA;
+
+ if (bq->init_data.ilim > BQ25790_IINDPM_I_MAX_uA ||
+ bq->init_data.ilim < BQ25790_IINDPM_I_MIN_uA)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int bq25790_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct bq25790_device *bq;
+ int ret;
+
+ bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL);
+ if (!bq)
+ return -ENOMEM;
+
+ bq->client = client;
+ bq->dev = dev;
+
+ mutex_init(&bq->lock);
+
+ strncpy(bq->model_name, id->name, I2C_NAME_SIZE);
+
+ bq->regmap = devm_regmap_init_i2c(client, &bq25790_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 = bq25790_parse_dt(bq);
+ if (ret) {
+ dev_err(dev, "Failed to read device tree properties%d\n", 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, bq25790_usb_work);
+ bq->usb_nb.notifier_call = bq25790_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, bq25790_usb_work);
+ bq->usb_nb.notifier_call = bq25790_usb_notifier;
+ usb_register_notifier(bq->usb3_phy, &bq->usb_nb);
+ }
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(dev, client->irq, NULL,
+ bq25790_irq_handler_thread,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ dev_name(&client->dev), bq);
+ if (ret)
+ goto error_out;
+ }
+
+ ret = bq25790_power_supply_init(bq, dev);
+ if (ret) {
+ dev_err(dev, "Failed to register power supply\n");
+ goto error_out;
+ }
+
+ ret = bq25790_hw_init(bq);
+ if (ret) {
+ dev_err(dev, "Cannot initialize the chip.\n");
+ goto error_out;
+ }
+
+ return ret;
+error_out:
+ 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);
+ return ret;
+}
+
+static const struct i2c_device_id bq25790_i2c_ids[] = {
+ { BQ25790_NAME, 0 },
+ { BQ25792_NAME, 1 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, bq25790_i2c_ids);
+
+static const struct of_device_id bq25790_of_match[] = {
+ { .compatible = "ti,bq25790", },
+ { .compatible = "ti,bq25792", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bq25790_of_match);
+
+static const struct acpi_device_id bq25790_acpi_match[] = {
+ {BQ25790_NAME, 0},
+ {BQ25792_NAME, 0},
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, bq25790_acpi_match);
+
+static struct i2c_driver bq25790_driver = {
+ .driver = {
+ .name = "bq25790-charger",
+ .of_match_table = bq25790_of_match,
+ .acpi_match_table = ACPI_PTR(bq25790_acpi_match),
+ },
+ .probe = bq25790_probe,
+ .id_table = bq25790_i2c_ids,
+};
+module_i2c_driver(bq25790_driver);
+
+MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
+MODULE_AUTHOR("Ricardo Rivera-Matos <r-rivera-matos@ti.com>");
+MODULE_DESCRIPTION("bq25790 charger driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/supply/bq25790_charger.h b/drivers/power/supply/bq25790_charger.h
new file mode 100644
index 000000000000..77234e116a6b
--- /dev/null
+++ b/drivers/power/supply/bq25790_charger.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+// BQ25790 Charger Driver
+// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+
+#ifndef _BQ25790_CHARGER_H
+#define _BQ25790_CHARGER_H
+
+#define BQ25790_MANUFACTURER "Texas Instruments"
+#define BQ25790_NAME "bq25790"
+#define BQ25792_NAME "bq25792"
+
+#define BQ25790_MIN_SYS_V 0x00
+#define BQ25790_CHRG_V_LIM_MSB 0x01
+#define BQ25790_CHRG_V_LIM_LSB 0x02
+#define BQ25790_CHRG_I_LIM_MSB 0x03
+#define BQ25790_CHRG_I_LIM_LSB 0x04
+#define BQ25790_INPUT_V_LIM 0x05
+#define BQ25790_INPUT_I_LIM_MSB 0x06
+#define BQ25790_INPUT_I_LIM_LSB 0x07
+#define BQ25790_PRECHRG_CTRL 0x08
+#define BQ25790_TERM_CTRL 0x09
+#define BQ25790_RECHRG_CTRL 0x0a
+#define BQ25790_VOTG_REG 0x0b
+#define BQ25790_IOTG_REG 0x0d
+#define BQ25790_TIMER_CTRL 0x0e
+#define BQ25790_CHRG_CTRL_0 0x0f
+#define BQ25790_CHRG_CTRL_1 0x10
+#define BQ25790_CHRG_CTRL_2 0x11
+#define BQ25790_CHRG_CTRL_3 0x12
+#define BQ25790_CHRG_CTRL_4 0x13
+#define BQ25790_CHRG_CTRL_5 0x14
+#define BQ25790_MPPT_CTRL 0x15
+#define BQ25790_TEMP_CTRL 0x16
+#define BQ25790_NTC_CTRL_0 0x17
+#define BQ25790_NTC_CTRL_1 0x18
+#define BQ25790_ICO_I_LIM 0x19
+#define BQ25790_CHRG_STAT_0 0x1b
+#define BQ25790_CHRG_STAT_1 0x1c
+#define BQ25790_CHRG_STAT_2 0x1d
+#define BQ25790_CHRG_STAT_3 0x1e
+#define BQ25790_CHRG_STAT_4 0x1f
+#define BQ25790_FAULT_STAT_0 0x20
+#define BQ25790_FAULT_STAT_1 0x21
+#define BQ25790_CHRG_FLAG_0 0x22
+#define BQ25790_CHRG_FLAG_1 0x23
+#define BQ25790_CHRG_FLAG_2 0x24
+#define BQ25790_CHRG_FLAG_3 0x25
+#define BQ25790_FAULT_FLAG_0 0x26
+#define BQ25790_FAULT_FLAG_1 0x27
+#define BQ25790_CHRG_MSK_0 0x28
+#define BQ25790_CHRG_MSK_1 0x29
+#define BQ25790_CHRG_MSK_2 0x2a
+#define BQ25790_CHRG_MSK_3 0x2b
+#define BQ25790_FAULT_MSK_0 0x2c
+#define BQ25790_FAULT_MSK_1 0x2d
+#define BQ25790_ADC_CTRL 0x2e
+#define BQ25790_FN_DISABE_0 0x2f
+#define BQ25790_FN_DISABE_1 0x30
+#define BQ25790_ADC_IBUS 0x31
+#define BQ25790_ADC_IBAT_MSB 0x33
+#define BQ25790_ADC_IBAT_LSB 0x34
+#define BQ25790_ADC_VBUS_MSB 0x35
+#define BQ25790_ADC_VBUS_LSB 0x36
+#define BQ25790_ADC_VAC1 0x37
+#define BQ25790_ADC_VAC2 0x39
+#define BQ25790_ADC_VBAT_MSB 0x3b
+#define BQ25790_ADC_VBAT_LSB 0x3c
+#define BQ25790_ADC_VSYS_MSB 0x3d
+#define BQ25790_ADC_VSYS_LSB 0x3e
+#define BQ25790_ADC_TS 0x3f
+#define BQ25790_ADC_TDIE 0x41
+#define BQ25790_ADC_DP 0x43
+#define BQ25790_ADC_DM 0x45
+#define BQ25790_DPDM_DRV 0x47
+#define BQ25790_PART_INFO 0x48
+
+#define BQ25790_CHRG_EN BIT(5)
+#define BQ25790_ADC_EN BIT(7)
+
+/* Charger Status 1 */
+#define BQ25790_CHG_STAT_MSK GENMASK(7, 5)
+#define BQ25790_NOT_CHRGING 0
+#define BQ25790_TRICKLE_CHRG BIT(5)
+#define BQ25790_PRECHRG BIT(6)
+#define BQ25790_FAST_CHRG (BIT(5) | BIT(6))
+#define BQ25790_TAPER_CHRG BIT(7)
+#define BQ25790_TOP_OFF_CHRG (BIT(6) | BIT(7))
+#define BQ25790_TERM_CHRG (BIT(5) | BIT(6) | BIT(7))
+#define BQ25790_VBUS_PRESENT BIT(0)
+
+#define BQ25790_VBUS_STAT_MSK GENMASK(4, 1)
+#define BQ25790_USB_SDP BIT(1)
+#define BQ25790_USB_CDP BIT(2)
+#define BQ25790_USB_DCP (BIT(1) | BIT(2))
+#define BQ25790_HVDCP BIT(3)
+#define BQ25790_UNKNOWN_3A (BIT(3) | BIT(1))
+#define BQ25790_NON_STANDARD (BIT(3) | BIT(2))
+#define BQ25790_OTG_MODE (BIT(3) | BIT(2) | BIT(1))
+#define BQ25790_UNQUAL_ADAPT BIT(4)
+#define BQ25790_DIRECT_PWR (BIT(4) | BIT(2) | BIT(1))
+
+/* Charger Status 4 */
+#define BQ25790_TEMP_HOT BIT(0)
+#define BQ25790_TEMP_WARM BIT(1)
+#define BQ25790_TEMP_COOL BIT(2)
+#define BQ25790_TEMP_COLD BIT(3)
+#define BQ25790_TEMP_MASK GENMASK(3, 0)
+
+#define BQ25790_OTG_OVP BIT(5)
+#define BQ25790_VSYS_OVP BIT(6)
+#define BQ25790_VSYS_STAT BIT(4)
+
+#define BQ25790_PRECHRG_CUR_MASK GENMASK(5, 0)
+#define BQ25790_PRECHRG_CURRENT_STEP_uA 40000
+#define BQ25790_PRECHRG_I_MIN_uA 40000
+#define BQ25790_PRECHRG_I_MAX_uA 2000000
+#define BQ25790_PRECHRG_I_DEF_uA 120000
+#define BQ25790_TERMCHRG_CUR_MASK GENMASK(4, 0)
+#define BQ25790_TERMCHRG_CURRENT_STEP_uA 40000
+#define BQ25790_TERMCHRG_I_MIN_uA 40000
+#define BQ25790_TERMCHRG_I_MAX_uA 1000000
+#define BQ25790_TERMCHRG_I_DEF_uA 200000
+#define BQ25790_ICHRG_CURRENT_STEP_uA 10000
+#define BQ25790_ICHRG_I_MIN_uA 50000
+#define BQ25790_ICHRG_I_MAX_uA 5000000
+#define BQ25790_ICHRG_I_DEF_uA 1000000
+
+#define BQ25790_VREG_V_MAX_uV 18800000
+#define BQ25790_VREG_V_MIN_uV 3000000
+#define BQ25790_VREG_V_DEF_uV 3600000
+#define BQ25790_VREG_V_STEP_uV 10000
+
+#define BQ25790_IINDPM_I_MIN_uA 100000
+#define BQ25790_IINDPM_I_MAX_uA 3300000
+#define BQ25790_IINDPM_STEP_uA 10000
+#define BQ25790_IINDPM_DEF_uA 1000000
+
+#define BQ25790_VINDPM_V_MIN_uV 3600000
+#define BQ25790_VINDPM_V_MAX_uV 22000000
+#define BQ25790_VINDPM_STEP_uV 100000
+#define BQ25790_VINDPM_DEF_uV 3600000
+
+#define BQ25790_ADC_VOLT_STEP_uV 1000
+#define BQ25790_ADC_CURR_STEP_uA 1000
+
+#define BQ25790_WATCHDOG_MASK GENMASK(2, 0)
+#define BQ25790_WATCHDOG_DIS 0
+#define BQ25790_WATCHDOG_MAX 160000
+
+#endif /* _BQ25790_CHARGER_H */
--
2.28.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver
2020-07-30 14:58 ` [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver Dan Murphy
@ 2020-07-30 15:14 ` Ricardo Rivera-Matos
2020-08-05 11:59 ` Dan Carpenter
1 sibling, 0 replies; 7+ messages in thread
From: Ricardo Rivera-Matos @ 2020-07-30 15:14 UTC (permalink / raw)
To: Dan Murphy, sre, robh; +Cc: devicetree, linux-pm, linux-kernel
Signed-off-by: Ricardo Rivera-Matos <r-rivera-matos@ti.com>
On 7/30/20 9:58 AM, Dan Murphy wrote:
> BQ25790 is a highly integrated switch-mode buck-boost charger
> for 1-4 cell Li-ion battery and Li-polymer battery.
>
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
> drivers/power/supply/Kconfig | 8 +
> drivers/power/supply/Makefile | 1 +
> drivers/power/supply/bq25790_charger.c | 1117 ++++++++++++++++++++++++
> drivers/power/supply/bq25790_charger.h | 150 ++++
> 4 files changed, 1276 insertions(+)
> create mode 100644 drivers/power/supply/bq25790_charger.c
> create mode 100644 drivers/power/supply/bq25790_charger.h
>
> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> index faf2830aa152..802c644d92be 100644
> --- a/drivers/power/supply/Kconfig
> +++ b/drivers/power/supply/Kconfig
> @@ -623,6 +623,14 @@ config CHARGER_BQ2515X
> rail, ADC for battery and system monitoring, and push-button
> controller.
>
> +config CHARGER_BQ25790
> + tristate "TI BQ25790 battery charger driver"
> + depends on I2C
> + depends on GPIOLIB || COMPILE_TEST
> + select REGMAP_I2C
> + help
> + Say Y to enable support for the TI BQ25790 battery charger.
> +
> config CHARGER_BQ25890
> tristate "TI BQ25890 battery charger driver"
> depends on I2C
> diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
> index b3c694a65114..ae269b9f624b 100644
> --- a/drivers/power/supply/Makefile
> +++ b/drivers/power/supply/Makefile
> @@ -84,6 +84,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_BQ25790) += bq25790_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/bq25790_charger.c b/drivers/power/supply/bq25790_charger.c
> new file mode 100644
> index 000000000000..92fa859ef55c
> --- /dev/null
> +++ b/drivers/power/supply/bq25790_charger.c
> @@ -0,0 +1,1117 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// BQ25790 driver
> +// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
> +
> +#include <linux/module.h>
> +#include <linux/i2c.h>
> +#include <linux/power_supply.h>
> +#include <linux/regmap.h>
> +#include <linux/types.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/usb/phy.h>
> +
> +#include <linux/acpi.h>
> +#include <linux/of.h>
> +
> +#include "bq25790_charger.h"
> +
> +#define BQ25790_NUM_WD_VAL 8
> +
> +struct bq25790_init_data {
> + u32 ichg;
> + u32 ilim;
> + u32 vreg;
> + u32 iterm;
> + u32 iprechg;
> + u32 vlim;
> + u32 ichg_max;
> + u32 vreg_max;
> +};
> +
> +struct bq25790_state {
> + bool online;
> + u8 chrg_status;
> + u8 chrg_type;
> + u8 health;
> + u8 chrg_fault;
> + u8 vsys_status;
> + u8 vbus_status;
> + u8 fault_0;
> + u8 fault_1;
> + u32 vbat_adc;
> + u32 vbus_adc;
> + u32 ibat_adc;
> +};
> +
> +struct bq25790_device {
> + struct i2c_client *client;
> + struct device *dev;
> + struct power_supply *charger;
> + struct power_supply *battery;
> + struct mutex lock;
> +
> + struct usb_phy *usb2_phy;
> + struct usb_phy *usb3_phy;
> + struct notifier_block usb_nb;
> + struct work_struct usb_work;
> + unsigned long usb_event;
> + struct regmap *regmap;
> +
> + char model_name[I2C_NAME_SIZE];
> + int device_id;
> +
> + struct bq25790_init_data init_data;
> + struct bq25790_state state;
> + int watchdog_timer;
> +};
> +
> +static struct reg_default bq25790_reg_defs[] = {
> + {BQ25790_INPUT_V_LIM, 0x24},
> + {BQ25790_INPUT_I_LIM_MSB, 0x01},
> + {BQ25790_INPUT_I_LIM_LSB, 0x2c},
> + {BQ25790_PRECHRG_CTRL, 0xc3},
> + {BQ25790_TERM_CTRL, 0x5},
> + {BQ25790_VOTG_REG, 0xdc},
> + {BQ25790_IOTG_REG, 0x4b},
> + {BQ25790_TIMER_CTRL, 0x3d},
> + {BQ25790_CHRG_CTRL_0, 0xa2},
> + {BQ25790_CHRG_CTRL_1, 0x85},
> + {BQ25790_CHRG_CTRL_2, 0x40},
> + {BQ25790_CHRG_CTRL_3, 0x12},
> + {BQ25790_CHRG_CTRL_5, 0x16},
> + {BQ25790_MPPT_CTRL, 0xaa},
> + {BQ25790_TEMP_CTRL, 0xc0},
> + {BQ25790_NTC_CTRL_0, 0x7a},
> + {BQ25790_NTC_CTRL_1, 0x54},
> + {BQ25790_ICO_I_LIM, 0x0},
> + {BQ25790_CHRG_STAT_0, 0x0},
> + {BQ25790_CHRG_STAT_1, 0x0},
> + {BQ25790_CHRG_STAT_2, 0x0},
> + {BQ25790_CHRG_STAT_3, 0x0},
> + {BQ25790_CHRG_STAT_4, 0x0},
> + {BQ25790_FAULT_STAT_0, 0x0},
> + {BQ25790_FAULT_STAT_1, 0x0},
> + {BQ25790_CHRG_FLAG_0, 0x0},
> + {BQ25790_CHRG_FLAG_1, 0x0},
> + {BQ25790_CHRG_FLAG_2, 0x0},
> + {BQ25790_CHRG_FLAG_3, 0x0},
> + {BQ25790_FAULT_FLAG_0, 0x0},
> + {BQ25790_FAULT_FLAG_1, 0x0},
> + {BQ25790_CHRG_MSK_0, 0x0},
> + {BQ25790_CHRG_MSK_1, 0x0},
> + {BQ25790_CHRG_MSK_2, 0x0},
> + {BQ25790_CHRG_MSK_3, 0x0},
> + {BQ25790_FAULT_MSK_0, 0x0},
> + {BQ25790_FAULT_MSK_1, 0x0},
> + {BQ25790_ADC_CTRL, 0x30},
> + {BQ25790_FN_DISABE_0, 0x0},
> + {BQ25790_FN_DISABE_1, 0x0},
> + {BQ25790_ADC_IBUS, 0x0},
> + {BQ25790_ADC_IBAT_MSB, 0x0},
> + {BQ25790_ADC_IBAT_LSB, 0x0},
> + {BQ25790_ADC_VBUS_MSB, 0x0},
> + {BQ25790_ADC_VBUS_LSB, 0x0},
> + {BQ25790_ADC_VAC1, 0x0},
> + {BQ25790_ADC_VAC2, 0x0},
> + {BQ25790_ADC_VBAT_MSB, 0x0},
> + {BQ25790_ADC_VBAT_LSB, 0x0},
> + {BQ25790_ADC_VBUS_MSB, 0x0},
> + {BQ25790_ADC_VBUS_LSB, 0x0},
> + {BQ25790_ADC_TS, 0x0},
> + {BQ25790_ADC_TDIE, 0x0},
> + {BQ25790_ADC_DP, 0x0},
> + {BQ25790_ADC_DM, 0x0},
> + {BQ25790_DPDM_DRV, 0x0},
> + {BQ25790_PART_INFO, 0x0},
> +};
> +
> +static int bq25790_watchdog_time[BQ25790_NUM_WD_VAL] = {0, 500, 1000, 2000,
> + 20000, 40000, 80000,
> + 160000};
> +
> +static enum power_supply_usb_type bq25790_usb_type[] = {
> + POWER_SUPPLY_USB_TYPE_PD_DRP,
> + POWER_SUPPLY_USB_TYPE_SDP,
> + POWER_SUPPLY_USB_TYPE_CDP,
> + POWER_SUPPLY_USB_TYPE_DCP,
> + POWER_SUPPLY_USB_TYPE_UNKNOWN,
> +};
> +
> +static int bq25790_usb_notifier(struct notifier_block *nb, unsigned long val,
> + void *priv)
> +{
> + struct bq25790_device *bq =
> + container_of(nb, struct bq25790_device, usb_nb);
> +
> + bq->usb_event = val;
> + queue_work(system_power_efficient_wq, &bq->usb_work);
> +
> + return NOTIFY_OK;
> +}
> +
> +static void bq25790_usb_work(struct work_struct *data)
> +{
> + struct bq25790_device *bq =
> + container_of(data, struct bq25790_device, usb_work);
> +
> + switch (bq->usb_event) {
> + case USB_EVENT_ID:
> + break;
> +
> + case USB_EVENT_NONE:
> + power_supply_changed(bq->charger);
> + break;
> + }
> +
> + return;
> +
> + dev_err(bq->dev, "Error switching to charger mode.\n");
> +}
> +
> +static int bq25790_get_vbat_adc(struct bq25790_device *bq)
> +{
> + int ret;
> + int vbat_adc_lsb, vbat_adc_msb;
> + u16 vbat_adc;
> +
> + ret = regmap_read(bq->regmap, BQ25790_ADC_VBAT_MSB, &vbat_adc_msb);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(bq->regmap, BQ25790_ADC_VBAT_LSB, &vbat_adc_lsb);
> + if (ret)
> + return ret;
> +
> + vbat_adc = (vbat_adc_msb << 8) | vbat_adc_lsb;
> +
> + return vbat_adc * BQ25790_ADC_VOLT_STEP_uV;
> +}
> +
> +static int bq25790_get_vbus_adc(struct bq25790_device *bq)
> +{
> + int ret;
> + int vbus_adc_lsb, vbus_adc_msb;
> + u16 vbus_adc;
> +
> + ret = regmap_update_bits(bq->regmap, BQ25790_ADC_CTRL,
> + BQ25790_ADC_EN, BQ25790_ADC_EN);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(bq->regmap, BQ25790_ADC_VBUS_MSB, &vbus_adc_msb);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(bq->regmap, BQ25790_ADC_VBUS_LSB, &vbus_adc_lsb);
> + if (ret)
> + return ret;
> +
> + vbus_adc = (vbus_adc_msb << 8) | vbus_adc_lsb;
> +
> + return vbus_adc * BQ25790_ADC_VOLT_STEP_uV;
> +}
> +
> +static int bq25790_get_ibat_adc(struct bq25790_device *bq)
> +{
> + int ret;
> + int ibat_adc_lsb, ibat_adc_msb;
> + u16 ibat_adc;
> +
> + ret = regmap_read(bq->regmap, BQ25790_ADC_IBAT_MSB, &ibat_adc_msb);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(bq->regmap, BQ25790_ADC_IBAT_LSB, &ibat_adc_lsb);
> + if (ret)
> + return ret;
> +
> + ibat_adc = (ibat_adc_msb << 8) | ibat_adc_lsb;
> +
> + return ibat_adc * BQ25790_ADC_CURR_STEP_uA;
> +}
> +
> +static int bq25790_get_term_curr(struct bq25790_device *bq)
> +{
> + int ret;
> + int reg_val;
> +
> + ret = regmap_read(bq->regmap, BQ25790_TERM_CTRL, ®_val);
> + if (ret)
> + return ret;
> +
> + reg_val &= BQ25790_TERMCHRG_CUR_MASK;
> +
> + return reg_val * BQ25790_TERMCHRG_CURRENT_STEP_uA;
> +}
> +
> +static int bq25790_get_prechrg_curr(struct bq25790_device *bq)
> +{
> + int ret;
> + int reg_val;
> +
> + ret = regmap_read(bq->regmap, BQ25790_PRECHRG_CTRL, ®_val);
> + if (ret)
> + return ret;
> +
> + reg_val &= BQ25790_PRECHRG_CUR_MASK;
> +
> + return reg_val * BQ25790_PRECHRG_CURRENT_STEP_uA;
> +}
> +
> +static int bq25790_get_ichg_curr(struct bq25790_device *bq)
> +{
> + int ret;
> + int ichg, ichg_lsb, ichg_msb;
> +
> + ret = regmap_read(bq->regmap, BQ25790_CHRG_I_LIM_LSB, &ichg_lsb);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(bq->regmap, BQ25790_CHRG_I_LIM_MSB, &ichg_msb);
> + if (ret)
> + return ret;
> +
> + ichg = (ichg_msb << 8) | ichg_lsb;
> +
> + return ichg * BQ25790_ICHRG_CURRENT_STEP_uA;
> +}
> +
> +static int bq25790_set_term_curr(struct bq25790_device *bq, int term_current)
> +{
> + int reg_val;
> +
> + if (term_current < BQ25790_TERMCHRG_I_MIN_uA ||
> + term_current > BQ25790_TERMCHRG_I_MAX_uA)
> + return -EINVAL;
> +
> + reg_val = term_current / BQ25790_TERMCHRG_CURRENT_STEP_uA;
> +
> + return regmap_update_bits(bq->regmap, BQ25790_TERM_CTRL,
> + BQ25790_TERMCHRG_CUR_MASK, reg_val);
> +}
> +
> +static int bq25790_set_prechrg_curr(struct bq25790_device *bq, int pre_current)
> +{
> + int reg_val;
> +
> + if (pre_current < BQ25790_PRECHRG_I_MIN_uA ||
> + pre_current > BQ25790_PRECHRG_I_MAX_uA)
> + return -EINVAL;
> +
> + reg_val = pre_current / BQ25790_PRECHRG_CURRENT_STEP_uA;
> +
> + return regmap_update_bits(bq->regmap, BQ25790_PRECHRG_CTRL,
> + BQ25790_PRECHRG_CUR_MASK, reg_val);
> +}
> +
> +static int bq25790_set_ichrg_curr(struct bq25790_device *bq, int chrg_curr)
> +{
> + int ret;
> + int ichg, ichg_msb, ichg_lsb;
> +
> + if (chrg_curr < BQ25790_ICHRG_I_MIN_uA ||
> + chrg_curr > BQ25790_ICHRG_I_MAX_uA)
> + return -EINVAL;
> +
> + ichg = chrg_curr / BQ25790_ICHRG_CURRENT_STEP_uA;
> + ichg_msb = (ichg >> 8) & 0xff;
> + ret = regmap_write(bq->regmap, BQ25790_CHRG_I_LIM_MSB, ichg_msb);
> + if (ret)
> + return ret;
> +
> + ichg_lsb = ichg & 0xff;
> +
> + return regmap_write(bq->regmap, BQ25790_CHRG_I_LIM_LSB, ichg_lsb);
> +}
> +
> +static int bq25790_set_chrg_volt(struct bq25790_device *bq, int chrg_volt)
> +{
> + int vlim_lsb, vlim_msb, vlim;
> + int ret;
> +
> + if (chrg_volt < BQ25790_VREG_V_MIN_uV ||
> + chrg_volt > BQ25790_VREG_V_MAX_uV)
> + return -EINVAL;
> +
> + vlim = chrg_volt / BQ25790_VREG_V_STEP_uV;
> + vlim_msb = (vlim >> 8) & 0xff;
> + ret = regmap_write(bq->regmap, BQ25790_CHRG_V_LIM_MSB, vlim_msb);
> + if (ret)
> + return ret;
> +
> + vlim_lsb = vlim & 0xff;
> +
> + return regmap_write(bq->regmap, BQ25790_CHRG_V_LIM_LSB, vlim_lsb);
> +}
> +
> +static int bq25790_get_chrg_volt(struct bq25790_device *bq)
> +{
> + int ret;
> + int vlim_lsb, vlim_msb, chrg_volt;
> +
> + ret = regmap_read(bq->regmap, BQ25790_CHRG_V_LIM_MSB, &vlim_msb);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(bq->regmap, BQ25790_CHRG_V_LIM_LSB, &vlim_lsb);
> + if (ret)
> + return ret;
> +
> + chrg_volt = (vlim_msb << 8) | vlim_lsb;
> +
> + return chrg_volt * BQ25790_VREG_V_STEP_uV;
> +}
> +
> +static int bq25790_set_input_volt_lim(struct bq25790_device *bq, int vindpm)
> +{
> + int ret;
> + int vlim_lsb, vlim_msb;
> + int vlim;
> +
> + if (vindpm < BQ25790_VINDPM_V_MIN_uV ||
> + vindpm > BQ25790_VINDPM_V_MAX_uV)
> + return -EINVAL;
> +
> + vlim = vindpm / BQ25790_VINDPM_STEP_uV;
> +
> + vlim_msb = (vlim >> 8) & 0xff;
> +
> + ret = regmap_write(bq->regmap, BQ25790_CHRG_V_LIM_MSB, vlim_msb);
> + if (ret)
> + return ret;
> +
> + vlim_lsb = vlim & 0xff;
> +
> + return regmap_write(bq->regmap, BQ25790_CHRG_V_LIM_LSB, vlim_lsb);
> +}
> +
> +static int bq25790_get_input_volt_lim(struct bq25790_device *bq)
> +{
> + int ret;
> + int vlim;
> +
> + ret = regmap_read(bq->regmap, BQ25790_INPUT_V_LIM, &vlim);
> + if (ret)
> + return ret;
> +
> + return vlim * BQ25790_VINDPM_STEP_uV;
> +}
> +
> +static int bq25790_set_input_curr_lim(struct bq25790_device *bq, int iindpm)
> +{
> + int ret;
> + int ilim, ilim_lsb, ilim_msb;
> +
> + if (iindpm < BQ25790_IINDPM_I_MIN_uA ||
> + iindpm > BQ25790_IINDPM_I_MAX_uA)
> + return -EINVAL;
> +
> + ilim = iindpm / BQ25790_IINDPM_STEP_uA;
> + ilim_msb = (ilim >> 8) & 0xff;
> +
> + ret = regmap_write(bq->regmap, BQ25790_INPUT_I_LIM_MSB, ilim_msb);
> + if (ret)
> + return ret;
> +
> + ilim_lsb = ilim & 0xff;
> +
> + return regmap_write(bq->regmap, BQ25790_INPUT_I_LIM_LSB, ilim_lsb);
> +}
> +
> +static int bq25790_get_input_curr_lim(struct bq25790_device *bq)
> +{
> + int ret;
> + int ilim_msb, ilim_lsb;
> + u16 ilim;
> +
> + ret = regmap_read(bq->regmap, BQ25790_INPUT_I_LIM_MSB, &ilim_msb);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(bq->regmap, BQ25790_INPUT_I_LIM_LSB, &ilim_lsb);
> + if (ret)
> + return ret;
> +
> + ilim = (ilim_msb << 8) | ilim_lsb;
> +
> + return ilim * BQ25790_IINDPM_STEP_uA;
> +}
> +
> +static int bq25790_get_state(struct bq25790_device *bq,
> + struct bq25790_state *state)
> +{
> + int chrg_stat_0, chrg_stat_1, chrg_stat_3, chrg_stat_4;
> + int chrg_ctrl_0, fault_0, fault_1;
> + int ret;
> +
> + ret = regmap_read(bq->regmap, BQ25790_CHRG_STAT_0, &chrg_stat_0);
> + if (ret)
> + return ret;
> +
> + state->vbus_status = chrg_stat_0 & BQ25790_VBUS_PRESENT;
> +
> + ret = regmap_read(bq->regmap, BQ25790_CHRG_STAT_1, &chrg_stat_1);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(bq->regmap, BQ25790_CHRG_CTRL_0, &chrg_ctrl_0);
> + if (ret)
> + return ret;
> +
> + if (chrg_ctrl_0 & BQ25790_CHRG_EN)
> + state->chrg_status = chrg_stat_1 & BQ25790_CHG_STAT_MSK;
> + else
> + state->chrg_status = BQ25790_NOT_CHRGING;
> +
> + state->chrg_type = chrg_stat_1 & BQ25790_VBUS_STAT_MSK;
> +
> + ret = regmap_read(bq->regmap, BQ25790_CHRG_STAT_4, &chrg_stat_4);
> + if (ret)
> + return ret;
> +
> + state->health = chrg_stat_4 & BQ25790_TEMP_MASK;
> +
> + ret = regmap_read(bq->regmap, BQ25790_FAULT_STAT_0, &fault_0);
> + if (ret)
> + return ret;
> +
> + state->fault_0 = fault_0;
> +
> + ret = regmap_read(bq->regmap, BQ25790_FAULT_STAT_1, &fault_1);
> + if (ret)
> + return ret;
> +
> + state->fault_1 = fault_1;
> +
> + ret = regmap_read(bq->regmap, BQ25790_CHRG_STAT_3, &chrg_stat_3);
> + if (ret)
> + return ret;
> +
> + state->online = chrg_stat_3 & BQ25790_VSYS_STAT;
> +
> + state->vbat_adc = bq25790_get_vbat_adc(bq);
> +
> + state->vbus_adc = bq25790_get_vbus_adc(bq);
> +
> + state->ibat_adc = bq25790_get_ibat_adc(bq);
> +
> + return 0;
> +}
> +
> +static int bq25790_set_property(struct power_supply *psy,
> + enum power_supply_property prop,
> + const union power_supply_propval *val)
> +{
> + struct bq25790_device *bq = power_supply_get_drvdata(psy);
> + int ret = -EINVAL;
> +
> + switch (prop) {
> + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
> + ret = bq25790_set_input_curr_lim(bq, val->intval);
> + break;
> + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
> + ret = bq25790_set_chrg_volt(bq, val->intval);
> + break;
> + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
> + ret = bq25790_set_ichrg_curr(bq, val->intval);
> + break;
> + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
> + ret = bq25790_set_prechrg_curr(bq, val->intval);
> + break;
> + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
> + ret = bq25790_set_term_curr(bq, val->intval);
> + break;
> + case POWER_SUPPLY_PROP_STATUS:
> + break;
> + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
> + ret = bq25790_set_input_volt_lim(bq, val->intval);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return ret;
> +}
> +
> +static int bq25790_get_property(struct power_supply *psy,
> + enum power_supply_property psp,
> + union power_supply_propval *val)
> +{
> + struct bq25790_device *bq = power_supply_get_drvdata(psy);
> + struct bq25790_state state;
> + int ret = 0;
> +
> + mutex_lock(&bq->lock);
> + ret = bq25790_get_state(bq, &state);
> + mutex_unlock(&bq->lock);
> + if (ret)
> + return ret;
> +
> + switch (psp) {
> + case POWER_SUPPLY_PROP_STATUS:
> + if (!state.chrg_type || (state.chrg_type == BQ25790_OTG_MODE))
> + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
> + else if (!state.chrg_status)
> + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
> + else if (state.chrg_status == BQ25790_TERM_CHRG)
> + val->intval = POWER_SUPPLY_STATUS_FULL;
> + else
> + val->intval = POWER_SUPPLY_STATUS_CHARGING;
> + break;
> + case POWER_SUPPLY_PROP_CHARGE_TYPE:
> + switch (state.chrg_status) {
> + case BQ25790_TRICKLE_CHRG:
> + val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
> + break;
> + case BQ25790_PRECHRG:
> + val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
> + break;
> + case BQ25790_FAST_CHRG:
> + val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
> + break;
> + case BQ25790_TAPER_CHRG:
> + val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
> + break;
> + case BQ25790_TOP_OFF_CHRG:
> + val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
> + break;
> + case BQ25790_NOT_CHRGING:
> + val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
> + break;
> + default:
> + val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
> + }
> + break;
> + case POWER_SUPPLY_PROP_MANUFACTURER:
> + val->strval = BQ25790_MANUFACTURER;
> + break;
> +
> + case POWER_SUPPLY_PROP_MODEL_NAME:
> + val->strval = BQ25790_NAME;
> + break;
> +
> + case POWER_SUPPLY_PROP_ONLINE:
> + val->intval = state.online;
> + break;
> + case POWER_SUPPLY_PROP_USB_TYPE:
> + if (!state.chrg_type) {
> + val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
> + break;
> + }
> + switch (state.chrg_type) {
> + case BQ25790_USB_SDP:
> + val->intval = POWER_SUPPLY_USB_TYPE_SDP;
> + break;
> + case BQ25790_USB_CDP:
> + val->intval = POWER_SUPPLY_USB_TYPE_CDP;
> + break;
> + case BQ25790_USB_DCP:
> + val->intval = POWER_SUPPLY_USB_TYPE_DCP;
> + break;
> + case BQ25790_OTG_MODE:
> + val->intval = POWER_SUPPLY_USB_TYPE_PD_DRP;
> + break;
> +
> + default:
> + val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
> + break;
> + }
> + break;
> +
> + case POWER_SUPPLY_PROP_HEALTH:
> + if (state.fault_1 && (BQ25790_OTG_OVP | BQ25790_VSYS_OVP))
> + val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
> + else
> + val->intval = POWER_SUPPLY_HEALTH_GOOD;
> +
> + switch (state.health) {
> + case BQ25790_TEMP_HOT:
> + val->intval = POWER_SUPPLY_HEALTH_HOT;
> + break;
> + case BQ25790_TEMP_WARM:
> + val->intval = POWER_SUPPLY_HEALTH_WARM;
> + break;
> + case BQ25790_TEMP_COOL:
> + val->intval = POWER_SUPPLY_HEALTH_COOL;
> + break;
> + case BQ25790_TEMP_COLD:
> + val->intval = POWER_SUPPLY_HEALTH_COLD;
> + break;
> + }
> + break;
> + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
> + ret = bq25790_get_ichg_curr(bq);
> + if (ret < 0)
> + return ret;
> +
> + val->intval = ret;
> + break;
> +
> + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
> + ret = bq25790_get_chrg_volt(bq);
> + if (ret < 0)
> + return ret;
> +
> + val->intval = ret;
> + break;
> +
> + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
> + ret = bq25790_get_prechrg_curr(bq);
> + if (ret < 0)
> + return ret;
> +
> + val->intval = ret;
> + break;
> + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
> + ret = bq25790_get_term_curr(bq);
> + if (ret < 0)
> + return ret;
> +
> + val->intval = ret;
> + break;
> + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
> + val->intval = state.vbus_adc;
> + break;
> + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
> + ret = bq25790_get_input_volt_lim(bq);
> + if (ret < 0)
> + return ret;
> +
> + val->intval = ret;
> + break;
> + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
> + ret = bq25790_get_input_curr_lim(bq);
> + if (ret < 0)
> + return ret;
> +
> + val->intval = ret;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return ret;
> +}
> +
> +static int bq25790_battery_get_property(struct power_supply *psy,
> + enum power_supply_property psp,
> + union power_supply_propval *val)
> +{
> + struct bq25790_device *bq = power_supply_get_drvdata(psy);
> + struct bq25790_state state;
> + int ret = 0;
> +
> + mutex_lock(&bq->lock);
> + ret = bq25790_get_state(bq, &state);
> + mutex_unlock(&bq->lock);
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(bq->regmap, BQ25790_ADC_CTRL,
> + BQ25790_ADC_EN, BQ25790_ADC_EN);
> + if (ret)
> + return ret;
> +
> + 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.vreg_max;
> + break;
> +
> + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
> + val->intval = state.vbat_adc;
> + break;
> + case POWER_SUPPLY_PROP_CURRENT_NOW:
> + val->intval = state.ibat_adc;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return ret;
> +}
> +
> +static bool bq25790_state_changed(struct bq25790_device *bq,
> + struct bq25790_state *new_state)
> +{
> + struct bq25790_state old_state;
> +
> + mutex_lock(&bq->lock);
> + old_state = bq->state;
> + mutex_unlock(&bq->lock);
> +
> + return (old_state.chrg_status != new_state->chrg_status ||
> + old_state.chrg_fault != new_state->chrg_fault ||
> + old_state.online != new_state->online ||
> + old_state.health != new_state->health ||
> + old_state.fault_0 != new_state->fault_0 ||
> + old_state.fault_1 != new_state->fault_1 ||
> + old_state.chrg_type != new_state->chrg_type ||
> + old_state.vsys_status != new_state->vsys_status ||
> + old_state.vbat_adc != new_state->vbat_adc ||
> + old_state.vbus_adc != new_state->vbus_adc ||
> + old_state.ibat_adc != new_state->ibat_adc);
> +}
> +
> +static irqreturn_t bq25790_irq_handler_thread(int irq, void *private)
> +{
> + struct bq25790_device *bq = private;
> + struct bq25790_state state;
> + int ret;
> +
> + ret = bq25790_get_state(bq, &state);
> + if (ret < 0)
> + goto irq_out;
> +
> + if (!bq25790_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 bq25790_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_CONSTANT_CHARGE_CURRENT,
> + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
> + POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
> + POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
> + POWER_SUPPLY_PROP_VOLTAGE_NOW,
> + POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT,
> + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
> + POWER_SUPPLY_PROP_CHARGE_TYPE,
> + POWER_SUPPLY_PROP_USB_TYPE,
> +};
> +
> +static enum power_supply_property bq25790_battery_props[] = {
> + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
> + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
> + POWER_SUPPLY_PROP_VOLTAGE_NOW,
> + POWER_SUPPLY_PROP_CURRENT_NOW,
> +};
> +
> +static char *bq25790_charger_supplied_to[] = {
> + "main-battery",
> +};
> +
> +static int bq25790_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 bq25790_power_supply_desc = {
> + .name = "bq25790-charger",
> + .type = POWER_SUPPLY_TYPE_USB,
> + .usb_types = bq25790_usb_type,
> + .num_usb_types = ARRAY_SIZE(bq25790_usb_type),
> + .properties = bq25790_power_supply_props,
> + .num_properties = ARRAY_SIZE(bq25790_power_supply_props),
> + .get_property = bq25790_get_property,
> + .set_property = bq25790_set_property,
> + .property_is_writeable = bq25790_property_is_writeable,
> +};
> +
> +static const struct power_supply_desc bq25790_battery_desc = {
> + .name = "bq25790-battery",
> + .type = POWER_SUPPLY_TYPE_BATTERY,
> + .get_property = bq25790_battery_get_property,
> + .properties = bq25790_battery_props,
> + .num_properties = ARRAY_SIZE(bq25790_battery_props),
> +};
> +
> +static bool bq25790_is_volatile_reg(struct device *dev, unsigned int reg)
> +{
> + switch (reg) {
> + case BQ25790_ICO_I_LIM...BQ25790_FAULT_FLAG_1:
> + case BQ25790_ADC_IBUS...BQ25790_ADC_DM:
> + case BQ25790_CHRG_CTRL_0:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
> +static const struct regmap_config bq25790_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> +
> + .max_register = BQ25790_PART_INFO,
> + .reg_defaults = bq25790_reg_defs,
> + .num_reg_defaults = ARRAY_SIZE(bq25790_reg_defs),
> + .cache_type = REGCACHE_RBTREE,
> + .volatile_reg = bq25790_is_volatile_reg,
> +};
> +
> +static int bq25790_power_supply_init(struct bq25790_device *bq,
> + struct device *dev)
> +{
> + struct power_supply_config psy_cfg = { .drv_data = bq,
> + .of_node = dev->of_node, };
> +
> + psy_cfg.supplied_to = bq25790_charger_supplied_to;
> + psy_cfg.num_supplicants = ARRAY_SIZE(bq25790_charger_supplied_to);
> +
> + bq->charger = devm_power_supply_register(bq->dev,
> + &bq25790_power_supply_desc,
> + &psy_cfg);
> + if (IS_ERR(bq->charger))
> + return -EINVAL;
> +
> + bq->battery = devm_power_supply_register(bq->dev,
> + &bq25790_battery_desc,
> + &psy_cfg);
> + if (IS_ERR(bq->battery))
> + return -EINVAL;
> + return 0;
> +}
> +
> +static int bq25790_hw_init(struct bq25790_device *bq)
> +{
> + struct power_supply_battery_info bat_info = { };
> + int wd_reg_val;
> + int ret = 0;
> + int i;
> +
> + if (bq->watchdog_timer) {
> + for (i = 0; i < BQ25790_NUM_WD_VAL; i++) {
> + if (bq->watchdog_timer > bq25790_watchdog_time[i] &&
> + bq->watchdog_timer < bq25790_watchdog_time[i + 1]) {
> + wd_reg_val = i;
> + break;
> + }
> + }
> + } else
> + wd_reg_val = BQ25790_WATCHDOG_DIS;
> +
> + ret = regmap_update_bits(bq->regmap, BQ25790_CHRG_CTRL_1,
> + BQ25790_WATCHDOG_MASK, wd_reg_val);
> +
> + 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 =
> + BQ25790_ICHRG_I_DEF_uA;
> +
> + bat_info.constant_charge_voltage_max_uv =
> + BQ25790_VREG_V_DEF_uV;
> +
> + bat_info.precharge_current_ua = BQ25790_PRECHRG_I_DEF_uA;
> + bat_info.charge_term_current_ua = BQ25790_TERMCHRG_I_DEF_uA;
> + bq->init_data.ichg_max = BQ25790_ICHRG_I_MAX_uA;
> + bq->init_data.vreg_max = BQ25790_VREG_V_MAX_uV;
> + } else {
> + bq->init_data.ichg_max =
> + bat_info.constant_charge_current_max_ua;
> +
> + bq->init_data.vreg_max =
> + bat_info.constant_charge_voltage_max_uv;
> + }
> +
> + ret = bq25790_set_ichrg_curr(bq,
> + bat_info.constant_charge_current_max_ua);
> + if (ret)
> + goto err_out;
> +
> + ret = bq25790_set_prechrg_curr(bq, bat_info.precharge_current_ua);
> + if (ret)
> + goto err_out;
> +
> + ret = bq25790_set_chrg_volt(bq,
> + bat_info.constant_charge_voltage_max_uv);
> + if (ret)
> + goto err_out;
> +
> + ret = bq25790_set_term_curr(bq, bat_info.charge_term_current_ua);
> + if (ret)
> + goto err_out;
> +
> + ret = bq25790_set_input_volt_lim(bq, bq->init_data.vlim);
> + if (ret)
> + goto err_out;
> +
> + ret = bq25790_set_input_curr_lim(bq, bq->init_data.ilim);
> + if (ret)
> + goto err_out;
> +
> +err_out:
> + return ret;
> +}
> +
> +static int bq25790_parse_dt(struct bq25790_device *bq)
> +{
> + int ret;
> +
> + ret = device_property_read_u32(bq->dev, "ti,watchdog-timer",
> + &bq->watchdog_timer);
> + if (ret)
> + bq->watchdog_timer = BQ25790_WATCHDOG_DIS;
> +
> + if (bq->watchdog_timer > BQ25790_WATCHDOG_MAX ||
> + bq->watchdog_timer < BQ25790_WATCHDOG_DIS)
> + return -EINVAL;
> +
> + ret = device_property_read_u32(bq->dev,
> + "input-voltage-limit-microvolt",
> + &bq->init_data.vlim);
> + if (ret)
> + bq->init_data.vlim = BQ25790_VINDPM_DEF_uV;
> +
> + if (bq->init_data.vlim > BQ25790_VINDPM_V_MAX_uV ||
> + bq->init_data.vlim < BQ25790_VINDPM_V_MIN_uV)
> + return -EINVAL;
> +
> + ret = device_property_read_u32(bq->dev,
> + "input-current-limit-microamp",
> + &bq->init_data.ilim);
> + if (ret)
> + bq->init_data.ilim = BQ25790_IINDPM_DEF_uA;
> +
> + if (bq->init_data.ilim > BQ25790_IINDPM_I_MAX_uA ||
> + bq->init_data.ilim < BQ25790_IINDPM_I_MIN_uA)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static int bq25790_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct device *dev = &client->dev;
> + struct bq25790_device *bq;
> + int ret;
> +
> + bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL);
> + if (!bq)
> + return -ENOMEM;
> +
> + bq->client = client;
> + bq->dev = dev;
> +
> + mutex_init(&bq->lock);
> +
> + strncpy(bq->model_name, id->name, I2C_NAME_SIZE);
> +
> + bq->regmap = devm_regmap_init_i2c(client, &bq25790_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 = bq25790_parse_dt(bq);
> + if (ret) {
> + dev_err(dev, "Failed to read device tree properties%d\n", 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, bq25790_usb_work);
> + bq->usb_nb.notifier_call = bq25790_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, bq25790_usb_work);
> + bq->usb_nb.notifier_call = bq25790_usb_notifier;
> + usb_register_notifier(bq->usb3_phy, &bq->usb_nb);
> + }
> +
> + if (client->irq) {
> + ret = devm_request_threaded_irq(dev, client->irq, NULL,
> + bq25790_irq_handler_thread,
> + IRQF_TRIGGER_FALLING |
> + IRQF_ONESHOT,
> + dev_name(&client->dev), bq);
> + if (ret)
> + goto error_out;
> + }
> +
> + ret = bq25790_power_supply_init(bq, dev);
> + if (ret) {
> + dev_err(dev, "Failed to register power supply\n");
> + goto error_out;
> + }
> +
> + ret = bq25790_hw_init(bq);
> + if (ret) {
> + dev_err(dev, "Cannot initialize the chip.\n");
> + goto error_out;
> + }
> +
> + return ret;
> +error_out:
> + 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);
> + return ret;
> +}
> +
> +static const struct i2c_device_id bq25790_i2c_ids[] = {
> + { BQ25790_NAME, 0 },
> + { BQ25792_NAME, 1 },
> + {},
> +};
> +MODULE_DEVICE_TABLE(i2c, bq25790_i2c_ids);
> +
> +static const struct of_device_id bq25790_of_match[] = {
> + { .compatible = "ti,bq25790", },
> + { .compatible = "ti,bq25792", },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, bq25790_of_match);
> +
> +static const struct acpi_device_id bq25790_acpi_match[] = {
> + {BQ25790_NAME, 0},
> + {BQ25792_NAME, 0},
> + {},
> +};
> +MODULE_DEVICE_TABLE(acpi, bq25790_acpi_match);
> +
> +static struct i2c_driver bq25790_driver = {
> + .driver = {
> + .name = "bq25790-charger",
> + .of_match_table = bq25790_of_match,
> + .acpi_match_table = ACPI_PTR(bq25790_acpi_match),
> + },
> + .probe = bq25790_probe,
> + .id_table = bq25790_i2c_ids,
> +};
> +module_i2c_driver(bq25790_driver);
> +
> +MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
> +MODULE_AUTHOR("Ricardo Rivera-Matos <r-rivera-matos@ti.com>");
> +MODULE_DESCRIPTION("bq25790 charger driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/power/supply/bq25790_charger.h b/drivers/power/supply/bq25790_charger.h
> new file mode 100644
> index 000000000000..77234e116a6b
> --- /dev/null
> +++ b/drivers/power/supply/bq25790_charger.h
> @@ -0,0 +1,150 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +// BQ25790 Charger Driver
> +// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
> +
> +#ifndef _BQ25790_CHARGER_H
> +#define _BQ25790_CHARGER_H
> +
> +#define BQ25790_MANUFACTURER "Texas Instruments"
> +#define BQ25790_NAME "bq25790"
> +#define BQ25792_NAME "bq25792"
> +
> +#define BQ25790_MIN_SYS_V 0x00
> +#define BQ25790_CHRG_V_LIM_MSB 0x01
> +#define BQ25790_CHRG_V_LIM_LSB 0x02
> +#define BQ25790_CHRG_I_LIM_MSB 0x03
> +#define BQ25790_CHRG_I_LIM_LSB 0x04
> +#define BQ25790_INPUT_V_LIM 0x05
> +#define BQ25790_INPUT_I_LIM_MSB 0x06
> +#define BQ25790_INPUT_I_LIM_LSB 0x07
> +#define BQ25790_PRECHRG_CTRL 0x08
> +#define BQ25790_TERM_CTRL 0x09
> +#define BQ25790_RECHRG_CTRL 0x0a
> +#define BQ25790_VOTG_REG 0x0b
> +#define BQ25790_IOTG_REG 0x0d
> +#define BQ25790_TIMER_CTRL 0x0e
> +#define BQ25790_CHRG_CTRL_0 0x0f
> +#define BQ25790_CHRG_CTRL_1 0x10
> +#define BQ25790_CHRG_CTRL_2 0x11
> +#define BQ25790_CHRG_CTRL_3 0x12
> +#define BQ25790_CHRG_CTRL_4 0x13
> +#define BQ25790_CHRG_CTRL_5 0x14
> +#define BQ25790_MPPT_CTRL 0x15
> +#define BQ25790_TEMP_CTRL 0x16
> +#define BQ25790_NTC_CTRL_0 0x17
> +#define BQ25790_NTC_CTRL_1 0x18
> +#define BQ25790_ICO_I_LIM 0x19
> +#define BQ25790_CHRG_STAT_0 0x1b
> +#define BQ25790_CHRG_STAT_1 0x1c
> +#define BQ25790_CHRG_STAT_2 0x1d
> +#define BQ25790_CHRG_STAT_3 0x1e
> +#define BQ25790_CHRG_STAT_4 0x1f
> +#define BQ25790_FAULT_STAT_0 0x20
> +#define BQ25790_FAULT_STAT_1 0x21
> +#define BQ25790_CHRG_FLAG_0 0x22
> +#define BQ25790_CHRG_FLAG_1 0x23
> +#define BQ25790_CHRG_FLAG_2 0x24
> +#define BQ25790_CHRG_FLAG_3 0x25
> +#define BQ25790_FAULT_FLAG_0 0x26
> +#define BQ25790_FAULT_FLAG_1 0x27
> +#define BQ25790_CHRG_MSK_0 0x28
> +#define BQ25790_CHRG_MSK_1 0x29
> +#define BQ25790_CHRG_MSK_2 0x2a
> +#define BQ25790_CHRG_MSK_3 0x2b
> +#define BQ25790_FAULT_MSK_0 0x2c
> +#define BQ25790_FAULT_MSK_1 0x2d
> +#define BQ25790_ADC_CTRL 0x2e
> +#define BQ25790_FN_DISABE_0 0x2f
> +#define BQ25790_FN_DISABE_1 0x30
> +#define BQ25790_ADC_IBUS 0x31
> +#define BQ25790_ADC_IBAT_MSB 0x33
> +#define BQ25790_ADC_IBAT_LSB 0x34
> +#define BQ25790_ADC_VBUS_MSB 0x35
> +#define BQ25790_ADC_VBUS_LSB 0x36
> +#define BQ25790_ADC_VAC1 0x37
> +#define BQ25790_ADC_VAC2 0x39
> +#define BQ25790_ADC_VBAT_MSB 0x3b
> +#define BQ25790_ADC_VBAT_LSB 0x3c
> +#define BQ25790_ADC_VSYS_MSB 0x3d
> +#define BQ25790_ADC_VSYS_LSB 0x3e
> +#define BQ25790_ADC_TS 0x3f
> +#define BQ25790_ADC_TDIE 0x41
> +#define BQ25790_ADC_DP 0x43
> +#define BQ25790_ADC_DM 0x45
> +#define BQ25790_DPDM_DRV 0x47
> +#define BQ25790_PART_INFO 0x48
> +
> +#define BQ25790_CHRG_EN BIT(5)
> +#define BQ25790_ADC_EN BIT(7)
> +
> +/* Charger Status 1 */
> +#define BQ25790_CHG_STAT_MSK GENMASK(7, 5)
> +#define BQ25790_NOT_CHRGING 0
> +#define BQ25790_TRICKLE_CHRG BIT(5)
> +#define BQ25790_PRECHRG BIT(6)
> +#define BQ25790_FAST_CHRG (BIT(5) | BIT(6))
> +#define BQ25790_TAPER_CHRG BIT(7)
> +#define BQ25790_TOP_OFF_CHRG (BIT(6) | BIT(7))
> +#define BQ25790_TERM_CHRG (BIT(5) | BIT(6) | BIT(7))
> +#define BQ25790_VBUS_PRESENT BIT(0)
> +
> +#define BQ25790_VBUS_STAT_MSK GENMASK(4, 1)
> +#define BQ25790_USB_SDP BIT(1)
> +#define BQ25790_USB_CDP BIT(2)
> +#define BQ25790_USB_DCP (BIT(1) | BIT(2))
> +#define BQ25790_HVDCP BIT(3)
> +#define BQ25790_UNKNOWN_3A (BIT(3) | BIT(1))
> +#define BQ25790_NON_STANDARD (BIT(3) | BIT(2))
> +#define BQ25790_OTG_MODE (BIT(3) | BIT(2) | BIT(1))
> +#define BQ25790_UNQUAL_ADAPT BIT(4)
> +#define BQ25790_DIRECT_PWR (BIT(4) | BIT(2) | BIT(1))
> +
> +/* Charger Status 4 */
> +#define BQ25790_TEMP_HOT BIT(0)
> +#define BQ25790_TEMP_WARM BIT(1)
> +#define BQ25790_TEMP_COOL BIT(2)
> +#define BQ25790_TEMP_COLD BIT(3)
> +#define BQ25790_TEMP_MASK GENMASK(3, 0)
> +
> +#define BQ25790_OTG_OVP BIT(5)
> +#define BQ25790_VSYS_OVP BIT(6)
> +#define BQ25790_VSYS_STAT BIT(4)
> +
> +#define BQ25790_PRECHRG_CUR_MASK GENMASK(5, 0)
> +#define BQ25790_PRECHRG_CURRENT_STEP_uA 40000
> +#define BQ25790_PRECHRG_I_MIN_uA 40000
> +#define BQ25790_PRECHRG_I_MAX_uA 2000000
> +#define BQ25790_PRECHRG_I_DEF_uA 120000
> +#define BQ25790_TERMCHRG_CUR_MASK GENMASK(4, 0)
> +#define BQ25790_TERMCHRG_CURRENT_STEP_uA 40000
> +#define BQ25790_TERMCHRG_I_MIN_uA 40000
> +#define BQ25790_TERMCHRG_I_MAX_uA 1000000
> +#define BQ25790_TERMCHRG_I_DEF_uA 200000
> +#define BQ25790_ICHRG_CURRENT_STEP_uA 10000
> +#define BQ25790_ICHRG_I_MIN_uA 50000
> +#define BQ25790_ICHRG_I_MAX_uA 5000000
> +#define BQ25790_ICHRG_I_DEF_uA 1000000
> +
> +#define BQ25790_VREG_V_MAX_uV 18800000
> +#define BQ25790_VREG_V_MIN_uV 3000000
> +#define BQ25790_VREG_V_DEF_uV 3600000
> +#define BQ25790_VREG_V_STEP_uV 10000
> +
> +#define BQ25790_IINDPM_I_MIN_uA 100000
> +#define BQ25790_IINDPM_I_MAX_uA 3300000
> +#define BQ25790_IINDPM_STEP_uA 10000
> +#define BQ25790_IINDPM_DEF_uA 1000000
> +
> +#define BQ25790_VINDPM_V_MIN_uV 3600000
> +#define BQ25790_VINDPM_V_MAX_uV 22000000
> +#define BQ25790_VINDPM_STEP_uV 100000
> +#define BQ25790_VINDPM_DEF_uV 3600000
> +
> +#define BQ25790_ADC_VOLT_STEP_uV 1000
> +#define BQ25790_ADC_CURR_STEP_uA 1000
> +
> +#define BQ25790_WATCHDOG_MASK GENMASK(2, 0)
> +#define BQ25790_WATCHDOG_DIS 0
> +#define BQ25790_WATCHDOG_MAX 160000
> +
> +#endif /* _BQ25790_CHARGER_H */
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] dt-bindings: power: Add the bq25790 dt bindings
2020-07-30 14:58 [PATCH 1/2] dt-bindings: power: Add the bq25790 dt bindings Dan Murphy
2020-07-30 14:58 ` [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver Dan Murphy
@ 2020-07-31 22:40 ` Rob Herring
1 sibling, 0 replies; 7+ messages in thread
From: Rob Herring @ 2020-07-31 22:40 UTC (permalink / raw)
To: Dan Murphy; +Cc: sre, devicetree, r-rivera-matos, linux-pm, linux-kernel
On Thu, Jul 30, 2020 at 09:58:33AM -0500, Dan Murphy wrote:
> Add the bindings for the bq25790.
>
> Signed-off-by: Ricardo Rivera-Matos <r-rivera-matos@ti.com>
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
> .../bindings/power/supply/bq25790.yaml | 87 +++++++++++++++++++
> 1 file changed, 87 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/bq25790.yaml
>
> diff --git a/Documentation/devicetree/bindings/power/supply/bq25790.yaml b/Documentation/devicetree/bindings/power/supply/bq25790.yaml
> new file mode 100644
> index 000000000000..97dd539c1625
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/supply/bq25790.yaml
> @@ -0,0 +1,87 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +# Copyright (C) 2020 Texas Instruments Incorporated
> +%YAML 1.2
> +---
> +$id: "http://devicetree.org/schemas/power/supply/bq25790.yaml#"
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#"
> +
> +title: TI BQ25790 Switch Mode Buck-Boost Charger
> +
> +maintainers:
> + - Dan Murphy <dmurphy@ti.com>
> +
> +description: |
> + BQ25790 is a highly integrated switch-mode buck-boost charger for 1-4 cell
> + Li-ion batteries and Li-polymer batteries. The device charges a battery from a
> + wide range of input sources including legacy USB adapters to high voltage USB
> + PD adapters and traditional barrel adapters.
> +
> +allOf:
> + - $ref: power-supply.yaml#
> +
> +properties:
> + compatible:
> + enum:
> + - ti,bq25790
> + - ti,bq25792
> +
> + reg:
> + maxItems: 1
> +
> + ti,watchdog-timer:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description: |
> + Watchdog timer in milli seconds. 0 (default) disables the watchdog.
Add a standard unit suffix and you can drop the type. And maybe
s/timer/timeout/ would be a bit clearer.
Also:
default: 0
> + minimum: 0
> + maximum: 160000
> + enum: [ 0, 500, 1000, 2000, 20000, 40000, 80000, 160000]
> +
> + input-voltage-limit-microvolt:
> + description: |
> + Minimum input voltage limit in micro volts with a 100000 micro volt step.
> + minimum: 3600000
> + maximum: 22000000
> +
> + input-current-limit-microamp:
> + description: |
> + Maximum input current limit in micro amps with a 100000 micro amp step.
> + minimum: 100000
> + maximum: 3300000
> +
> + monitored-battery:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description: phandle to the battery node being monitored
> +
> +required:
> + - compatible
> + - reg
> + - monitored-battery
Add:
unevaluatedProperties: false
> +
> +examples:
> + - |
> + bat: battery {
> + compatible = "simple-battery";
> + constant-charge-current-max-microamp = <2000000>;
> + constant-charge-voltage-max-microvolt = <4200000>;
> + precharge-current-microamp = <160000>;
> + charge-term-current-microamp = <160000>;
> + };
> + #include <dt-bindings/gpio/gpio.h>
> + #include <dt-bindings/interrupt-controller/irq.h>
> + i2c0 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + bq25790: charger@6b {
> + compatible = "ti,bq25790";
> + reg = <0x6b>;
> + interrupt-parent = <&gpio1>;
> + interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
Not documented.
> + ti,watchdog-timer = <2000>;
> + input-current-limit = <3000000>;
> + input-voltage-limit = <4500000>;
Doesn't match the schema.
> + monitored-battery = <&bat>;
> + };
> + };
> +
> +...
> --
> 2.28.0
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver
2020-07-30 14:58 ` [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver Dan Murphy
2020-07-30 15:14 ` Ricardo Rivera-Matos
@ 2020-08-05 11:59 ` Dan Carpenter
1 sibling, 0 replies; 7+ messages in thread
From: Dan Carpenter @ 2020-08-05 11:59 UTC (permalink / raw)
To: kbuild, Dan Murphy, sre, robh
Cc: lkp, kbuild-all, devicetree, r-rivera-matos, linux-pm,
linux-kernel, Dan Murphy
[-- Attachment #1: Type: text/plain, Size: 2498 bytes --]
Hi Dan,
url: https://github.com/0day-ci/linux/commits/Dan-Murphy/dt-bindings-power-Add-the-bq25790-dt-bindings/20200730-225910
base: https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git for-next
config: x86_64-randconfig-m001-20200731 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-14) 9.3.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch warnings:
drivers/power/supply/bq25790_charger.c:170 bq25790_usb_work() warn: ignoring unreachable code.
drivers/power/supply/bq25790_charger.c:624 bq25790_get_property() warn: should this be a bitwise op?
drivers/power/supply/bq25790_charger.c:904 bq25790_hw_init() error: buffer overflow 'bq25790_watchdog_time' 8 <= 8
# https://github.com/0day-ci/linux/commit/e5cf0f04730928b191aff54ab64bdd2167b2ecd4
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout e5cf0f04730928b191aff54ab64bdd2167b2ecd4
vim +170 drivers/power/supply/bq25790_charger.c
e5cf0f04730928 Dan Murphy 2020-07-30 154 static void bq25790_usb_work(struct work_struct *data)
e5cf0f04730928 Dan Murphy 2020-07-30 155 {
e5cf0f04730928 Dan Murphy 2020-07-30 156 struct bq25790_device *bq =
e5cf0f04730928 Dan Murphy 2020-07-30 157 container_of(data, struct bq25790_device, usb_work);
e5cf0f04730928 Dan Murphy 2020-07-30 158
e5cf0f04730928 Dan Murphy 2020-07-30 159 switch (bq->usb_event) {
e5cf0f04730928 Dan Murphy 2020-07-30 160 case USB_EVENT_ID:
e5cf0f04730928 Dan Murphy 2020-07-30 161 break;
e5cf0f04730928 Dan Murphy 2020-07-30 162
e5cf0f04730928 Dan Murphy 2020-07-30 163 case USB_EVENT_NONE:
e5cf0f04730928 Dan Murphy 2020-07-30 164 power_supply_changed(bq->charger);
e5cf0f04730928 Dan Murphy 2020-07-30 165 break;
e5cf0f04730928 Dan Murphy 2020-07-30 166 }
e5cf0f04730928 Dan Murphy 2020-07-30 167
e5cf0f04730928 Dan Murphy 2020-07-30 168 return;
^^^^^^
e5cf0f04730928 Dan Murphy 2020-07-30 169
e5cf0f04730928 Dan Murphy 2020-07-30 @170 dev_err(bq->dev, "Error switching to charger mode.\n");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Unreachable.
e5cf0f04730928 Dan Murphy 2020-07-30 171 }
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36721 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver
@ 2020-08-05 11:59 ` Dan Carpenter
0 siblings, 0 replies; 7+ messages in thread
From: Dan Carpenter @ 2020-08-05 11:59 UTC (permalink / raw)
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 2548 bytes --]
Hi Dan,
url: https://github.com/0day-ci/linux/commits/Dan-Murphy/dt-bindings-power-Add-the-bq25790-dt-bindings/20200730-225910
base: https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git for-next
config: x86_64-randconfig-m001-20200731 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-14) 9.3.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch warnings:
drivers/power/supply/bq25790_charger.c:170 bq25790_usb_work() warn: ignoring unreachable code.
drivers/power/supply/bq25790_charger.c:624 bq25790_get_property() warn: should this be a bitwise op?
drivers/power/supply/bq25790_charger.c:904 bq25790_hw_init() error: buffer overflow 'bq25790_watchdog_time' 8 <= 8
# https://github.com/0day-ci/linux/commit/e5cf0f04730928b191aff54ab64bdd2167b2ecd4
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout e5cf0f04730928b191aff54ab64bdd2167b2ecd4
vim +170 drivers/power/supply/bq25790_charger.c
e5cf0f04730928 Dan Murphy 2020-07-30 154 static void bq25790_usb_work(struct work_struct *data)
e5cf0f04730928 Dan Murphy 2020-07-30 155 {
e5cf0f04730928 Dan Murphy 2020-07-30 156 struct bq25790_device *bq =
e5cf0f04730928 Dan Murphy 2020-07-30 157 container_of(data, struct bq25790_device, usb_work);
e5cf0f04730928 Dan Murphy 2020-07-30 158
e5cf0f04730928 Dan Murphy 2020-07-30 159 switch (bq->usb_event) {
e5cf0f04730928 Dan Murphy 2020-07-30 160 case USB_EVENT_ID:
e5cf0f04730928 Dan Murphy 2020-07-30 161 break;
e5cf0f04730928 Dan Murphy 2020-07-30 162
e5cf0f04730928 Dan Murphy 2020-07-30 163 case USB_EVENT_NONE:
e5cf0f04730928 Dan Murphy 2020-07-30 164 power_supply_changed(bq->charger);
e5cf0f04730928 Dan Murphy 2020-07-30 165 break;
e5cf0f04730928 Dan Murphy 2020-07-30 166 }
e5cf0f04730928 Dan Murphy 2020-07-30 167
e5cf0f04730928 Dan Murphy 2020-07-30 168 return;
^^^^^^
e5cf0f04730928 Dan Murphy 2020-07-30 169
e5cf0f04730928 Dan Murphy 2020-07-30 @170 dev_err(bq->dev, "Error switching to charger mode.\n");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Unreachable.
e5cf0f04730928 Dan Murphy 2020-07-30 171 }
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 36721 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver
@ 2020-08-05 11:59 ` Dan Carpenter
0 siblings, 0 replies; 7+ messages in thread
From: Dan Carpenter @ 2020-08-05 11:59 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 2548 bytes --]
Hi Dan,
url: https://github.com/0day-ci/linux/commits/Dan-Murphy/dt-bindings-power-Add-the-bq25790-dt-bindings/20200730-225910
base: https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git for-next
config: x86_64-randconfig-m001-20200731 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-14) 9.3.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch warnings:
drivers/power/supply/bq25790_charger.c:170 bq25790_usb_work() warn: ignoring unreachable code.
drivers/power/supply/bq25790_charger.c:624 bq25790_get_property() warn: should this be a bitwise op?
drivers/power/supply/bq25790_charger.c:904 bq25790_hw_init() error: buffer overflow 'bq25790_watchdog_time' 8 <= 8
# https://github.com/0day-ci/linux/commit/e5cf0f04730928b191aff54ab64bdd2167b2ecd4
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout e5cf0f04730928b191aff54ab64bdd2167b2ecd4
vim +170 drivers/power/supply/bq25790_charger.c
e5cf0f04730928 Dan Murphy 2020-07-30 154 static void bq25790_usb_work(struct work_struct *data)
e5cf0f04730928 Dan Murphy 2020-07-30 155 {
e5cf0f04730928 Dan Murphy 2020-07-30 156 struct bq25790_device *bq =
e5cf0f04730928 Dan Murphy 2020-07-30 157 container_of(data, struct bq25790_device, usb_work);
e5cf0f04730928 Dan Murphy 2020-07-30 158
e5cf0f04730928 Dan Murphy 2020-07-30 159 switch (bq->usb_event) {
e5cf0f04730928 Dan Murphy 2020-07-30 160 case USB_EVENT_ID:
e5cf0f04730928 Dan Murphy 2020-07-30 161 break;
e5cf0f04730928 Dan Murphy 2020-07-30 162
e5cf0f04730928 Dan Murphy 2020-07-30 163 case USB_EVENT_NONE:
e5cf0f04730928 Dan Murphy 2020-07-30 164 power_supply_changed(bq->charger);
e5cf0f04730928 Dan Murphy 2020-07-30 165 break;
e5cf0f04730928 Dan Murphy 2020-07-30 166 }
e5cf0f04730928 Dan Murphy 2020-07-30 167
e5cf0f04730928 Dan Murphy 2020-07-30 168 return;
^^^^^^
e5cf0f04730928 Dan Murphy 2020-07-30 169
e5cf0f04730928 Dan Murphy 2020-07-30 @170 dev_err(bq->dev, "Error switching to charger mode.\n");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Unreachable.
e5cf0f04730928 Dan Murphy 2020-07-30 171 }
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 36721 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-08-05 20:05 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-30 14:58 [PATCH 1/2] dt-bindings: power: Add the bq25790 dt bindings Dan Murphy
2020-07-30 14:58 ` [PATCH 2/2] power: supply: bq25790: Introduce the BQ25790 charger driver Dan Murphy
2020-07-30 15:14 ` Ricardo Rivera-Matos
2020-08-05 11:59 ` Dan Carpenter
2020-08-05 11:59 ` Dan Carpenter
2020-08-05 11:59 ` Dan Carpenter
2020-07-31 22:40 ` [PATCH 1/2] dt-bindings: power: Add the bq25790 dt bindings Rob Herring
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.