diff --git a/Documentation/devicetree/bindings/power/supply/bq25750.yaml b/Documentation/devicetree/bindings/power/supply/bq25750.yaml new file mode 100755 index 0000000..2bdb41c --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/bq25750.yaml @@ -0,0 +1,94 @@ +# 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 + +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,bq25750 + + reg: + maxItems: 1 + + ti,watchdog-timeout-ms: + default: 0 + description: | + Watchdog timer in milli seconds. 0 (default) disables the watchdog. + minimum: 0 + maximum: 160000 + enum: [ 0, 40000, 80000, 160000] + + input-voltage-limit-microvolt: + description: | + Minimum input voltage limit in micro volts with a 100000 micro volt step. + minimum: 4200000 + maximum: 65000000 + + input-current-limit-microamp: + description: | + Maximum input current limit in micro amps with a 100000 micro amp step. + minimum: 1000000 + maximum: 50000000 + + monitored-battery: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle to the battery node being monitored + + interrupts: + maxItems: 1 + description: | + Interrupt sends an active low, 256 μs pulse to host to report the charger + device status and faults. + +required: + - compatible + - reg + - monitored-battery + +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 + #include + 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-timeout-ms = <40000>; + input-current-limit-microamp = <50000>; + input-voltage-limit-microvolt = <20000>; + monitored-battery = <&bat>; + }; + }; + +... diff --git a/drivers/power/supply/bq25750_charger.c b/drivers/power/supply/bq25750_charger.c new file mode 100755 index 0000000..f87f6f4 --- /dev/null +++ b/drivers/power/supply/bq25750_charger.c @@ -0,0 +1,1103 @@ +// SPDX-License-Identifier: GPL-2.0 +// BQ25750 driver +// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bq25750_charger.h" + +#define BQ25750_NUM_WD_VAL 8 + +struct bq25750_init_data { + u32 ichg; + u32 ilim; + u32 vreg; + u32 iterm; + u32 iprechg; + u32 vlim; + u32 ichg_max; + u32 vreg_max; +}; + +struct bq25750_state { + bool online; + u8 chrg_status; + u8 chrg_type; + u8 health; + u8 chrg_fault; + u8 vsys_status; + //u8 vac_status; + u8 fault_0; + u8 fault_1; + u32 vbat_adc; + u32 vac_adc; + u32 ibat_adc; +}; + +enum bq25750_id { + BQ25750, + BQ25792, +}; + +struct bq25750_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 bq25750_init_data init_data; + struct bq25750_state state; + int watchdog_timer; +}; + +static struct reg_default bq25750_reg_defs[] = { + {BQ25750_INPUT_V_LIM, 0x24}, + {BQ25750_INPUT_I_LIM_MSB, 0x01}, + {BQ25750_INPUT_I_LIM_LSB, 0x2c}, + {BQ25750_PRECHRG_CTRL, 0xc3}, + {BQ25750_TERM_CTRL, 0x5}, + {BQ25750_VOTG_REG, 0xdc}, + {BQ25750_IOTG_REG, 0x4b}, + {BQ25750_TIMER_CTRL, 0x3d}, + {BQ25750_CHRG_CTRL_0, 0xa2}, + {BQ25750_CHRG_CTRL_1, 0x85}, + {BQ25750_CHRG_CTRL_2, 0x40}, + {BQ25750_CHRG_CTRL_3, 0x12}, + {BQ25750_CHRG_CTRL_5, 0x16}, + {BQ25750_MPPT_CTRL, 0xaa}, + {BQ25750_TEMP_CTRL, 0xc0}, + {BQ25750_NTC_CTRL_0, 0x7a}, + {BQ25750_NTC_CTRL_1, 0x54}, + {BQ25750_ICO_I_LIM, 0x0}, + {BQ25750_CHRG_STAT_0, 0x0}, + {BQ25750_CHRG_STAT_1, 0x0}, + {BQ25750_CHRG_STAT_2, 0x0}, + {BQ25750_CHRG_STAT_3, 0x0}, + {BQ25750_CHRG_STAT_4, 0x0}, + {BQ25750_FAULT_STAT_0, 0x0}, + {BQ25750_FAULT_STAT_1, 0x0}, + {BQ25750_CHRG_FLAG_0, 0x0}, + {BQ25750_CHRG_FLAG_1, 0x0}, + {BQ25750_CHRG_FLAG_2, 0x0}, + {BQ25750_CHRG_FLAG_3, 0x0}, + {BQ25750_FAULT_FLAG_0, 0x0}, + {BQ25750_FAULT_FLAG_1, 0x0}, + {BQ25750_CHRG_MSK_0, 0x0}, + {BQ25750_CHRG_MSK_1, 0x0}, + {BQ25750_CHRG_MSK_2, 0x0}, + {BQ25750_CHRG_MSK_3, 0x0}, + {BQ25750_FAULT_MSK_0, 0x0}, + {BQ25750_FAULT_MSK_1, 0x0}, + {BQ25750_ADC_CTRL, 0x30}, + {BQ25750_FN_DISABE_0, 0x0}, + {BQ25750_FN_DISABE_1, 0x0}, + {BQ25750_ADC_IBUS, 0x0}, + {BQ25750_ADC_IBAT_MSB, 0x0}, + {BQ25750_ADC_IBAT_LSB, 0x0}, + {BQ25750_ADC_VBUS_MSB, 0x0}, + {BQ25750_ADC_VBUS_LSB, 0x0}, + {BQ25750_ADC_VAC1, 0x0}, + {BQ25750_ADC_VAC2, 0x0}, + {BQ25750_ADC_VBAT_MSB, 0x0}, + {BQ25750_ADC_VBAT_LSB, 0x0}, + {BQ25750_ADC_VBUS_MSB, 0x0}, + {BQ25750_ADC_VBUS_LSB, 0x0}, + {BQ25750_ADC_TS, 0x0}, + {BQ25750_ADC_TDIE, 0x0}, + {BQ25750_ADC_DP, 0x0}, + {BQ25750_ADC_DM, 0x0}, + {BQ25750_DPDM_DRV, 0x0}, + {BQ25750_PART_INFO, 0x0}, +}; + +static int bq25750_watchdog_time[BQ25750_NUM_WD_VAL] = {0, 40000, 80000, 160000}; + +static enum power_supply_usb_type bq25750_usb_type[] = { + POWER_SUPPLY_USB_TYPE_ACA, + POWER_SUPPLY_USB_TYPE_SDP, + POWER_SUPPLY_USB_TYPE_CDP, + POWER_SUPPLY_USB_TYPE_DCP, + POWER_SUPPLY_USB_TYPE_UNKNOWN, +}; + +static int bq25750_usb_notifier(struct notifier_block *nb, unsigned long val, + void *priv) +{ + struct bq25750_device *bq = + container_of(nb, struct bq25750_device, usb_nb); + + bq->usb_event = val; + queue_work(system_power_efficient_wq, &bq->usb_work); + + return NOTIFY_OK; +} + +static void bq25750_usb_work(struct work_struct *data) +{ + struct bq25750_device *bq = + container_of(data, struct bq25750_device, usb_work); + + switch (bq->usb_event) { + case USB_EVENT_ID: + break; + + case USB_EVENT_NONE: + power_supply_changed(bq->charger); + break; + } +} + +static int bq25750_get_vbat_adc(struct bq25750_device *bq) +{ + int ret; + int vbat_adc_lsb, vbat_adc_msb; + u16 vbat_adc; + + ret = regmap_read(bq->regmap, BQ25750_ADC_VBAT_MSB, &vbat_adc_msb); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_ADC_VBAT_LSB, &vbat_adc_lsb); + if (ret) + return ret; + + vbat_adc = (vbat_adc_msb << 8) | vbat_adc_lsb; + + return vbat_adc * BQ25750_ADC_VOLT_STEP_uV; +} + +static int bq25750_get_vac_adc(struct bq25750_device *bq) +{ + int ret; + int vac_adc_lsb, vac_adc_msb; + u16 vac_adc; + + ret = regmap_read(bq->regmap, BQ25750_ADC_VAC_MSB, &vac_adc_msb); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_ADC_VAC_LSB, &vac_adc_lsb); + if (ret) + return ret; + + vac_adc = (vac_adc_msb << 8) | vac_adc_lsb; + + return vac_adc * BQ25750_ADC_VOLT_STEP_uV; +} + +static int bq25750_get_ibat_adc(struct bq25750_device *bq) +{ + int ret; + int ibat_adc_lsb, ibat_adc_msb; + u16 ibat_adc; + + ret = regmap_read(bq->regmap, BQ25750_ADC_IBAT_MSB, &ibat_adc_msb); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_ADC_IBAT_LSB, &ibat_adc_lsb); + if (ret) + return ret; + + ibat_adc = (ibat_adc_msb << 8) | ibat_adc_lsb; + + return ibat_adc * BQ25750_ADC_CURR_STEP_uA; +} + +static int bq25750_set_term_curr(struct bq25750_device *bq, int term_current) +{ + int ret; + int iterm, iterm_lsb, iterm_msb; + + term_current = clamp(term_current, BQ25750_TERMCHRG_I_MIN_uA, + BQ25750_TERMCHRG_I_MAX_uA); + + iterm = (term_current / BQ25750_TERMCHRG_CURRENT_STEP_uA) << BQ25750_TERM_I_LIM_MOVE_STEP; + iterm_msb = (iterm >> 8) & 0xff; + ret = regmap_write(bq->regmap, BQ25750_TERM_I_LIM_MSB, iterm_msb); + if (ret) + return ret; + + iterm_lsb = iterm & 0xff; + + return regmap_write(bq->regmap, BQ25750_TERM_I_LIM_LSB, iterm_lsb); +} + +static int bq25750_get_term_curr(struct bq25750_device *bq) +{ + int ret; + int iterm, iterm_lsb, iterm_msb; + + ret = regmap_read(bq->regmap, BQ25750_TERM_I_LIM_LSB, &iterm_lsb); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_TERM_I_LIM_MSB, &iterm_msb); + if (ret) + return ret; + + iterm = ((iterm_msb << 8) | iterm_lsb) >> BQ25750_TERM_I_LIM_MOVE_STEP; + + return iterm * BQ25750_TERMCHRG_CURRENT_STEP_uA; +} + +static int bq25750_set_prechrg_curr(struct bq25750_device *bq, int pre_current) +{ + int reg_val; + int iprechg, iprechg_lsb, iprechg_msb; + + pre_current = clamp(pre_current, BQ25750_PRECHRG_I_MIN_uA, + BQ25750_PRECHRG_I_MAX_uA); + + iprechg = (pre_current / BQ25750_PRECHRG_CURRENT_STEP_uA) << BQ25750_PRECHRG_I_LIM_MOVE_STEP; + iprechg_msb = (iprechg >> 8) & 0xff; + ret = regmap_write(bq->regmap, BQ25750_CHRG_I_LIM_MSB, iprechg_msb); + if (ret) + return ret; + + iprechg_lsb = iprechg & 0xff; + + return regmap_write(bq->regmap, BQ25750_CHRG_I_LIM_LSB, iprechg_lsb); +} + +static int bq25750_get_prechrg_curr(struct bq25750_device *bq) +{ + int ret; + int iprechg, iprechg_lsb, iprechg_msb; + + ret = regmap_read(bq->regmap, BQ25750_PRECHRG_I_LIM_LSB, &iprechg_lsb); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_PRECHRG_I_LIM_MSB, &iprechg_msb); + if (ret) + return ret; + + iprechg = ((iprechg_msb << 8) | iprechg_lsb) >> BQ25750_PRECHRG_I_LIM_MOVE_STEP; + + return iprechg * BQ25750_PRECHRG_CURRENT_STEP_uA; +} + +static int bq25750_set_ichrg_curr(struct bq25750_device *bq, int chrg_curr) +{ + int chrg_curr_max = bq->init_data.ichg_max; + int ichg, ichg_msb, ichg_lsb; + int ret; + + chrg_curr = clamp(chrg_curr, BQ25750_ICHRG_I_MIN_uA, + chrg_curr_max); + + ichg = (chrg_curr / BQ25750_ICHRG_CURRENT_STEP_uA) << BQ25750_CHRG_I_LIM_MOVE_STEP; + ichg_msb = (ichg >> 8) & 0xff; + ret = regmap_write(bq->regmap, BQ25750_CHRG_I_LIM_MSB, ichg_msb); + if (ret) + return ret; + + ichg_lsb = ichg & 0xff; + + return regmap_write(bq->regmap, BQ25750_CHRG_I_LIM_LSB, ichg_lsb); +} + +static int bq25750_get_ichg_curr(struct bq25750_device *bq) +{ + int ret; + int ichg, ichg_lsb, ichg_msb; + + ret = regmap_read(bq->regmap, BQ25750_CHRG_I_LIM_LSB, &ichg_lsb); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_CHRG_I_LIM_MSB, &ichg_msb); + if (ret) + return ret; + + ichg = ((ichg_msb << 8) | ichg_lsb) >> BQ25750_CHRG_I_LIM_MOVE_STEP; + + return ichg * BQ25750_ICHRG_CURRENT_STEP_uA; +} + +static int bq25750_set_chrg_volt(struct bq25750_device *bq, int chrg_volt) +{ + int chrg_volt_max = bq->init_data.vreg_max; + int vlim_lsb, vlim_msb, vlim; + int ret; + + chrg_volt = clamp(chrg_volt, BQ25750_VREG_V_MIN_uV, chrg_volt_max); + + vlim = chrg_volt / BQ25750_VREG_V_STEP_uV; + vlim_msb = (vlim >> 8) & 0xff; + ret = regmap_write(bq->regmap, BQ25750_CHRG_V_LIM_MSB, vlim_msb); + if (ret) + return ret; + + vlim_lsb = vlim & 0xff; + + return regmap_write(bq->regmap, BQ25750_CHRG_V_LIM_LSB, vlim_lsb); +} + +static int bq25750_get_chrg_volt(struct bq25750_device *bq) +{ + int ret; + int vlim_lsb, vlim_msb, chrg_volt; + + ret = regmap_read(bq->regmap, BQ25750_CHRG_V_LIM_MSB, &vlim_msb); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_CHRG_V_LIM_LSB, &vlim_lsb); + if (ret) + return ret; + + chrg_volt = (vlim_msb << 8) | vlim_lsb; + + return chrg_volt * BQ25750_VREG_V_STEP_uV; +} + +static int bq25750_set_input_volt_lim(struct bq25750_device *bq, int vindpm) +{ + int ret; + int vlim_lsb, vlim_msb; + int vlim; + + vindpm = clamp(vindpm, BQ25750_VINDPM_V_MIN_uV, + BQ25750_VINDPM_V_MAX_uV); + + vlim = (vindpm / BQ25750_VINDPM_STEP_uV) << BQ25750_INPUT_V_DPM_LIM_MOVE_STEP; + + vlim_msb = (vlim >> 8) & 0xff; + + ret = regmap_write(bq->regmap, BQ25750_INPUT_V_DPM_LIM_MSB, vlim_msb); + if (ret) + return ret; + + vlim_lsb = vlim & 0xff; + + return regmap_write(bq->regmap, BQ25750_INPUT_V_DPM_LIM_LSB, vlim_lsb); +} + +static int bq25750_get_input_volt_lim(struct bq25750_device *bq) +{ + int ret; + int vlim_msb, vlim_lsb; + u16 ilim; + + ret = regmap_read(bq->regmap, BQ25750_INPUT_V_DPM_LIM_MSB, &vlim_msb); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_INPUT_V_DPM_LIM_LSB, &vlim_lsb); + if (ret) + return ret; + + ilim = ((vlim_msb << 8) | vlim_lsb) >> BQ25750_INPUT_V_DPM_LIM_MOVE_STEP; + + return ilim * BQ25750_VINDPM_STEP_uV; +} + +static int bq25750_set_input_curr_lim(struct bq25750_device *bq, int iindpm) +{ + int ret; + int ilim, ilim_lsb, ilim_msb; + + iindpm = clamp(iindpm, BQ25750_IINDPM_I_MIN_uA, + BQ25750_IINDPM_I_MAX_uA); + + ilim = (iindpm / BQ25750_IINDPM_STEP_uA) << BQ25750_IINDPM_STEP_uA; + ilim_msb = (ilim >> 8) & 0xff; + + ret = regmap_write(bq->regmap, BQ25750_INPUT_I_DPM_LIM_MSB, ilim_msb); + if (ret) + return ret; + + ilim_lsb = ilim & 0xff; + + return regmap_write(bq->regmap, BQ25750_INPUT_I_DPM_LIM_LSB, ilim_lsb); +} + +static int bq25750_get_input_curr_lim(struct bq25750_device *bq) +{ + int ret; + int ilim_msb, ilim_lsb; + u16 ilim; + + ret = regmap_read(bq->regmap, BQ25750_INPUT_I_DPM_LIM_MSB, &ilim_msb); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_INPUT_I_DPM_LIM_LSB, &ilim_lsb); + if (ret) + return ret; + + ilim = ((ilim_msb << 8) | ilim_lsb) >> BQ25750_INPUT_I_DPM_LIM_MOVE_STEP; + + return ilim * BQ25750_IINDPM_STEP_uA; +} + +static int bq25750_get_state(struct bq25750_device *bq, + struct bq25750_state *state) +{ + int chrg_stat_0, chrg_stat_1, chrg_stat_3, chrg_stat_4; + int chrg_ctrl, fault; + int ret; + + ret = regmap_update_bits(bq->regmap, BQ25750_ADC_CTRL, + BQ25750_ADC_EN, BQ25750_ADC_EN); + if (ret) + return ret; + + //ret = regmap_read(bq->regmap, BQ25750_CHRG_STAT_0, &chrg_stat_0); + //if (ret) + // return ret; + + //state->vac_status = chrg_stat_0 & BQ25750_VBUS_PRESENT; + + + ret = regmap_read(bq->regmap, BQ25750_CHRG_STAT_2, &chrg_stat_2); + if (ret) + return ret; + + ret = regmap_read(bq->regmap, BQ25750_CHRG_CTRL, &chrg_ctrl); + if (ret) + return ret; + + if (chrg_ctrl & BQ25750_CHRG_EN) + state->chrg_status = chrg_stat_2 & BQ25750_CHG_STAT_MSK; + else + state->chrg_status = BQ25750_NOT_CHRGING; + + //state->chrg_type = chrg_stat_2 & BQ25750_VBUS_STAT_MSK; + + ret = regmap_read(bq->regmap, BQ25750_CHRG_STAT_1, &chrg_stat_1); + if (ret) + return ret; + + state->health = (chrg_stat_1 & BQ25750_TEMP_MASK) >> BQ25750_TEMP_MOVE_STEP; + + ret = regmap_read(bq->regmap, BQ25750_FAULT_STAT, &fault); + if (ret) + return ret; + + state->fault = fault; + + + + state->online = chrg_stat_2 & BQ25750_PG_STAT_STAT; + + state->vbat_adc = bq25750_get_vbat_adc(bq); + + state->vac_adc = bq25750_get_vac_adc(bq); + + state->ibat_adc = bq25750_get_ibat_adc(bq); + + return 0; +} + +static void bq25750_charger_reset(void *data) +{ + struct bq25750_device *bq = data; + + 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 bq25750_set_property(struct power_supply *psy, + enum power_supply_property prop, + const union power_supply_propval *val) +{ + struct bq25750_device *bq = power_supply_get_drvdata(psy); + int ret = -EINVAL; + + switch (prop) { + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + ret = bq25750_set_input_curr_lim(bq, val->intval); + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + ret = bq25750_set_chrg_volt(bq, val->intval); + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + ret = bq25750_set_ichrg_curr(bq, val->intval); + break; + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: + ret = bq25750_set_prechrg_curr(bq, val->intval); + break; + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: + ret = bq25750_set_term_curr(bq, val->intval); + break; + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: + ret = bq25750_set_input_volt_lim(bq, val->intval); + break; + default: + return -EINVAL; + } + + return ret; +} + +static int bq25750_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct bq25750_device *bq = power_supply_get_drvdata(psy); + struct bq25750_state state; + int ret = 0; + + ret = bq25750_get_state(bq, &state); + if (ret) + return ret; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + if (!state.chrg_status) + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + else if (state.chrg_status == BQ25750_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 BQ25750_TRICKLE_CHRG: + val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + break; + case BQ25750_PRECHRG: + val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + break; + case BQ25750_FAST_CHRG: + val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; + break; + case BQ25750_TAPER_CHRG: + val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD; + break; + case BQ25750_FLOAT_CHRG: + val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; + break; + case BQ25750_TOP_OFF_CHRG: + val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + break; + case BQ25750_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 = BQ25750_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_USB_TYPE: + if (!state.chrg_type) { + val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN; + break; + } + + + case POWER_SUPPLY_PROP_HEALTH: + if (state.fault & (BQ25750_VBAT_OV_STAT | BQ25750_VAC_OV_STAT)) + val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; + else + val->intval = POWER_SUPPLY_HEALTH_GOOD; + + switch (state.health) { + case BQ25750_TEMP_HOT: + val->intval = POWER_SUPPLY_HEALTH_HOT; + break; + case BQ25750_TEMP_WARM: + val->intval = POWER_SUPPLY_HEALTH_WARM; + break; + case BQ25750_TEMP_COOL: + val->intval = POWER_SUPPLY_HEALTH_COOL; + break; + case BQ25750_TEMP_COLD: + val->intval = POWER_SUPPLY_HEALTH_COLD; + break; + } + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + ret = bq25750_get_ichg_curr(bq); + if (ret < 0) + return ret; + + val->intval = ret; + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + ret = bq25750_get_chrg_volt(bq); + if (ret < 0) + return ret; + + val->intval = ret; + break; + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: + ret = bq25750_get_prechrg_curr(bq); + if (ret < 0) + return ret; + + val->intval = ret; + break; + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: + ret = bq25750_get_term_curr(bq); + if (ret < 0) + return ret; + + val->intval = ret; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = state.vac_adc; + break; + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: + ret = bq25750_get_input_volt_lim(bq); + if (ret < 0) + return ret; + + val->intval = ret; + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + ret = bq25750_get_input_curr_lim(bq); + if (ret < 0) + return ret; + + val->intval = ret; + break; + default: + return -EINVAL; + } + + return ret; +} + +static int bq25750_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct bq25750_device *bq = power_supply_get_drvdata(psy); + struct bq25750_state state; + int ret = 0; + + ret = bq25750_get_state(bq, &state); + 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 bq25750_state_changed(struct bq25750_device *bq, + struct bq25750_state *new_state) +{ + struct bq25750_state old_state; + + mutex_lock(&bq->lock); + old_state = bq->state; + mutex_unlock(&bq->lock); + + return memcmp(&old_state, new_state, + sizeof(struct bq25750_state)) != 0; +} + +static irqreturn_t bq25750_irq_handler_thread(int irq, void *private) +{ + struct bq25750_device *bq = private; + struct bq25750_state state; + int ret; + + ret = bq25750_get_state(bq, &state); + if (ret < 0) + goto irq_out; + + if (!bq25750_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 bq25750_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 bq25750_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 int bq25750_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_INPUT_VOLTAGE_LIMIT: + return true; + default: + return false; + } +} + +static const struct power_supply_desc bq25750_power_supply_desc = { + .name = "bq25750-charger", + .type = POWER_SUPPLY_TYPE_USB, + .usb_types = bq25750_usb_type, + .num_usb_types = ARRAY_SIZE(bq25750_usb_type), + .properties = bq25750_power_supply_props, + .num_properties = ARRAY_SIZE(bq25750_power_supply_props), + .get_property = bq25750_get_property, + .set_property = bq25750_set_property, + .property_is_writeable = bq25750_property_is_writeable, +}; + +static const struct power_supply_desc bq25750_battery_desc = { + .name = "bq25750-battery", + .type = POWER_SUPPLY_TYPE_BATTERY, + .get_property = bq25750_battery_get_property, + .properties = bq25750_battery_props, + .num_properties = ARRAY_SIZE(bq25750_battery_props), +}; + +static bool bq25750_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BQ25750_CHRG_V_LIM_MSB...BQ25750_TERM_I_LIM_LSB: + case BQ25750_ADC_IAC_MSB...BQ25750_ADC_VFB_LSB: + case BQ25750_CHRG_CTRL: + return true; + default: + return false; + } +} + +static const struct regmap_config bq25750_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = BQ25750_PART_INFO, + .reg_defaults = bq25750_reg_defs, + .num_reg_defaults = ARRAY_SIZE(bq25750_reg_defs), + .cache_type = REGCACHE_FLAT, + .volatile_reg = bq25750_is_volatile_reg, +}; + +static int bq25750_power_supply_init(struct bq25750_device *bq, + struct power_supply_config *psy_cfg, struct device *dev) +{ + bq->charger = devm_power_supply_register(bq->dev, + &bq25750_power_supply_desc, + psy_cfg); + if (IS_ERR(bq->charger)) + return -EINVAL; + + bq->battery = devm_power_supply_register(bq->dev, + &bq25750_battery_desc, + psy_cfg); + if (IS_ERR(bq->battery)) + return -EINVAL; + return 0; +} + +static int bq25750_hw_init(struct bq25750_device *bq) +{ + struct power_supply_battery_info bat_info = { }; + int wd_reg_val = BQ25750_WATCHDOG_DIS; + int wd_max_val = BQ25750_NUM_WD_VAL - 1; + int ret = 0; + int i; + + if (bq->watchdog_timer) { + if (bq->watchdog_timer >= bq25750_watchdog_time[wd_max_val]) + wd_reg_val = wd_max_val; + else { + for (i = 0; i < wd_max_val; i++) { + if (bq->watchdog_timer > bq25750_watchdog_time[i] && + bq->watchdog_timer < bq25750_watchdog_time[i + 1]) { + wd_reg_val = i; + break; + } + } + } + } + dev_warn(bq->dev, "222222222\n"); + ret = regmap_update_bits(bq->regmap, BQ25750_TIMER_CTRL, + BQ25750_WATCHDOG_MASK, wd_reg_val); + if (ret) + return ret; + dev_warn(bq->dev, "33333333333\n"); + 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 = + BQ25750_ICHRG_I_DEF_uA; + + bat_info.constant_charge_voltage_max_uv = + BQ25750_VREG_V_DEF_uV; + + bat_info.precharge_current_ua = BQ25750_PRECHRG_I_DEF_uA; + bat_info.charge_term_current_ua = BQ25750_TERMCHRG_I_DEF_uA; + bq->init_data.ichg_max = BQ25750_ICHRG_I_MAX_uA; + bq->init_data.vreg_max = BQ25750_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 = bq25750_set_ichrg_curr(bq, + bat_info.constant_charge_current_max_ua); + if (ret) + return ret; + + ret = bq25750_set_prechrg_curr(bq, bat_info.precharge_current_ua); + if (ret) + return ret; + + ret = bq25750_set_chrg_volt(bq, + bat_info.constant_charge_voltage_max_uv); + if (ret) + return ret; + + ret = bq25750_set_term_curr(bq, bat_info.charge_term_current_ua); + if (ret) + return ret; + + ret = bq25750_set_input_volt_lim(bq, bq->init_data.vlim); + if (ret) + return ret; + + ret = bq25750_set_input_curr_lim(bq, bq->init_data.ilim); + if (ret) + return ret; + + power_supply_put_battery_info(bq->charger, &bat_info); + + return 0; +} + +static int bq25750_parse_dt(struct bq25750_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 = BQ25750_WATCHDOG_DIS; + + if (bq->watchdog_timer > BQ25750_WATCHDOG_MAX || + bq->watchdog_timer < BQ25750_WATCHDOG_DIS) + return -EINVALx + + ret = device_property_read_u32(bq->dev, + "input-voltage-limit-microvolt", + &bq->init_data.vlim); + if (ret) + bq->init_data.vlim = BQ25750_VINDPM_DEF_uV; + + if (bq->init_data.vlim > BQ25750_VINDPM_V_MAX_uV || + bq->init_data.vlim < BQ25750_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 = BQ25750_IINDPM_DEF_uA; + + if (bq->init_data.ilim > BQ25750_IINDPM_I_MAX_uA || + bq->init_data.ilim < BQ25750_IINDPM_I_MIN_uA) + return -EINVAL; + + return 0; +} + +static int bq25750_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct bq25750_device *bq; + struct power_supply_config psy_cfg = { }; + + int ret; + dev_err(dev, "\r\n------------------------->>>>>>>>>>>>>>>aaaaaaaa\r\n"); + 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, &bq25750_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 = bq25750_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, bq25750_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, bq25750_usb_work); + bq->usb_nb.notifier_call = bq25750_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, bq25750_usb_work); + bq->usb_nb.notifier_call = bq25750_usb_notifier; + usb_register_notifier(bq->usb3_phy, &bq->usb_nb); + } + + if (client->irq) { + ret = devm_request_threaded_irq(dev, client->irq, NULL, + bq25750_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 = bq25750_power_supply_init(bq, &psy_cfg, dev); + if (ret) { + dev_err(dev, "Failed to register power supply\n"); + return ret; + } + + ret = bq25750_hw_init(bq); + if (ret) { + dev_err(dev, "Cannot initialize the chip.\n"); + return ret; + } + + return ret; +} + +static const struct i2c_device_id bq25750_i2c_ids[] = { + { "bq25750", BQ25750 }, + { "bq25792", BQ25792 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, bq25750_i2c_ids); + +static const struct of_device_id bq25750_of_match[] = { + { .compatible = "ti,bq25750", }, + { .compatible = "ti,bq25792", }, + { }, +}; +MODULE_DEVICE_TABLE(of, bq25750_of_match); + +static const struct acpi_device_id bq25750_acpi_match[] = { + { "bq25750", BQ25750 }, + { "bq25792", BQ25792 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, bq25750_acpi_match); + +static struct i2c_driver bq25750_driver = { + .driver = { + .name = "bq25750-charger", + .of_match_table = bq25750_of_match, + .acpi_match_table = bq25750_acpi_match, + }, + .probe = bq25750_probe, + .id_table = bq25750_i2c_ids, +}; +module_i2c_driver(bq25750_driver); + +MODULE_AUTHOR("Dan Murphy "); +MODULE_AUTHOR("Ricardo Rivera-Matos "); +MODULE_DESCRIPTION("bq25750 charger driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/supply/bq25750_charger.h b/drivers/power/supply/bq25750_charger.h new file mode 100755 index 0000000..57aa396 --- /dev/null +++ b/drivers/power/supply/bq25750_charger.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +// BQ25750 Charger Driver +// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + +#ifndef _BQ25750_CHARGER_H +#define _BQ25750_CHARGER_H + +#define BQ25750_MANUFACTURER "Texas Instruments" + + +#define BQ25750_CHRG_V_LIM_MSB 0x00 +#define BQ25750_CHRG_V_LIM_LSB 0x01 +#define BQ25750_CHRG_I_LIM_MSB 0x02 +#define BQ25750_CHRG_I_LIM_LSB 0x03 +#define BQ25750_INPUT_I_DPM_LIM_MSB 0x06 +#define BQ25750_INPUT_I_DPM_LIM_LSB 0x07 +#define BQ25750_INPUT_V_DPM_LIM_MSB 0x08 +#define BQ25750_INPUT_V_DPM_LIM_LSB 0x09 +#define BQ25750_REV_INPUT_I_LIM_MSB 0x0A +#define BQ25750_REV_INPUT_I_LIM_LSB 0x0B +#define BQ25750_REV_INPUT_V_LIM_MSB 0x0C +#define BQ25750_REV_INPUT_V_LIM_LSB 0x0D +#define BQ25750_PRECHRG_I_LIM_MSB 0x10 +#define BQ25750_RRECHRG_I_LIM_LSB 0x11 +#define BQ25750_TERM_I_LIM_MSB 0x12 +#define BQ25750_TERM_I_LIM_LSB 0x13 +#define BQ25750_RECHRG_AND_TERM_CTRL 0x014 +#define BQ25750_TIMER_CTRL 0x15 +#define BQ25750_THREE_STAGE_CHRG_CTRL 0x16 +#define BQ25750_CHRG_CTRL 0x17 +#define BQ25750_PIN_CTRL 0x18 +#define BQ25750_POW_AND_REV_CTRL 0x19 +#define BQ25750_MPPT_CTRL 0x1A +#define BQ25750_TS_CHAG_THRESHOLD_CTRL 0x1B +#define BQ25750_TS_CHAG_BEHAVIOR_CTRL 0x1C +#define BQ25750_REV_THRESHOLD_CTRL 0x1D +#define BQ25750_REV_UNDER_V_CONTROL 0x1E +#define BQ25750_VAC_MAX_POWER_POINT_DETECTED_MSB 0x1F +#define BQ25750_VAC_MAX_POWER_POINT_DETECTED_LSB 0x20 +#define BQ25750_CHRG_STAT_1 0x21 +#define BQ25750_CHRG_STAT_2 0x22 +#define BQ25750_CHRG_STAT_3 0x23 +#define BQ25750_FAULT_STAT 0x24 +#define BQ25750_CHRG_FLAG_1 0x25 +#define BQ25750_CHRG_FLAG_2 0x26 +#define BQ25750_FAULT_FLAG 0x27 +#define BQ25750_CHRG_MSK_1 0x28 +#define BQ25750_CHRG_MSK_2 0x29 +#define BQ25750_FAULT_MSK_0 0x2A +#define BQ25750_ADC_CTRL 0x2B +#define BQ25750_ADC_CHANNEL_CTRL 0x2C +#define BQ25750_ADC_IAC_MSB 0x2D +#define BQ25750_ADC_IAC_LSB 0x2E +#define BQ25750_ADC_IBAT_MSB 0x2F +#define BQ25750_ADC_IBAT_LSB 0x30 +#define BQ25750_ADC_VAC_MSB 0x31 +#define BQ25750_ADC_VAC_LSB 0x32 +#define BQ25750_ADC_VBAT_MSB 0x33 +#define BQ25750_ADC_VBAT_LSB 0x34 +#define BQ25750_ADC_VSYS_MSB 0x35 +#define BQ25750_ADC_VSYS_LSB 0x36 +#define BQ25750_ADC_TS_MSB 0x37 +#define BQ25750_ADC_TS_LSB 0x38 +#define BQ25750_ADC_VFB_MSB 0x39 +#define BQ25750_ADC_VFB_LSB 0x3A +#define BQ25750_GATE_DRV_STRENGTH_CTRL 0x3B +#define BQ25750_GATE_DEAD_TIME_CTRL 0x3C +#define BQ25750_PART_INFO 0x3D +#define BQ25750_REV_DISCHAG_CURRENT 0x62 + + +#define BQ25750_CHRG_EN BIT(0) +#define BQ25750_ADC_EN BIT(7) + +#define BQ25750_CHRG_I_LIM_MOVE_STEP 2 +#define BQ25750_INPUT_I_DPM_LIM_MOVE_STEP 2 +#define BQ25750_INPUT_V_DPM_LIM_MOVE_STEP 2 +#define BQ25750_PRECHRG_I_LIM_MOVE_STEP 2 +#define BQ25750_TERM_I_LIM_MOVE_STEP 2 + +/* Charger Status 1 */ +#define BQ25750_CHG_STAT_MSK GENMASK(2, 0) +#define BQ25750_NOT_CHRGING 0 +#define BQ25750_TRICKLE_CHRG BIT(0) +#define BQ25750_PRECHRG BIT(1) +#define BQ25750_FAST_CHRG (BIT(0) | BIT(1)) +#define BQ25750_TAPER_CHRG BIT(2) +#define BQ25750_FLOAT_CHRG (BIT(2) | BIT(0)) +#define BQ25750_TOP_OFF_CHRG (BIT(1) | BIT(2)) +#define BQ25750_TERM_CHRG (BIT(0) | BIT(1) | BIT(2)) +#define BQ25750_VBUS_PRESENT BIT(0) + + + +/* Charger Status 4 */ + +#define BQ25750_TEMP_WARM BIT(0) +#define BQ25750_TEMP_COOL BIT(1) +#define BQ25750_TEMP_COLD (BIT(0) | BIT(1)) +#define BQ25750_TEMP_HOT BIT(2) +#define BQ25750_TEMP_MASK GENMASK(6, 4) +#define BQ25750_TEMP_MOVE_STEP 4 + + +#define BQ25750_VBAT_OV_STAT BIT(4) +#define BQ25750_VAC_OV_STAT BIT(6) + +#define BQ25750_PG_STAT_STAT BIT(7) + + +#define BQ25750_PRECHRG_CUR_MASK GENMASK(9, 2) +#define BQ25750_PRECHRG_CURRENT_STEP_uA 50000 +#define BQ25750_PRECHRG_I_MIN_uA 250000 +#define BQ25750_PRECHRG_I_MAX_uA 10000000 +#define BQ25750_PRECHRG_I_DEF_uA 4000000 + +#define BQ25750_TERMCHRG_CUR_MASK GENMASK(9, 2) +#define BQ25750_TERMCHRG_CURRENT_STEP_uA 50000 +#define BQ25750_TERMCHRG_I_MIN_uA 250000 +#define BQ25750_TERMCHRG_I_MAX_uA 10000000 +#define BQ25750_TERMCHRG_I_DEF_uA 2000000 + +#define BQ25750_ICHRG_CURRENT_STEP_uA 50000 +#define BQ25750_ICHRG_I_MIN_uA 400000 +#define BQ25750_ICHRG_I_MAX_uA 20000000 +#define BQ25750_ICHRG_I_DEF_uA 20000000 + +#define BQ25750_VREG_V_MAX_uV 1566000 +#define BQ25750_VREG_V_MIN_uV 1504000 +#define BQ25750_VREG_V_DEF_uV 1536000 +#define BQ25750_VREG_V_STEP_uV 2000 + +#define BQ25750_IINDPM_I_MIN_uA 1000000 +#define BQ25750_IINDPM_I_MAX_uA 50000000 +#define BQ25750_IINDPM_STEP_uA 125000 +#define BQ25750_IINDPM_DEF_uA 50000000 + +#define BQ25750_VINDPM_V_MIN_uV 4200000 +#define BQ25750_VINDPM_V_MAX_uV 65000000 +#define BQ25750_VINDPM_STEP_uV 20000 +#define BQ25750_VINDPM_DEF_uV 4200000 + +#define BQ25750_ADC_VOLT_STEP_uV 2000 +#define BQ25750_ADC_CURR_STEP_uA 2000 + +#define BQ25750_WATCHDOG_MASK GENMASK(5, 4) +#define BQ25750_WATCHDOG_DIS 0 +#define BQ25750_WATCHDOG_MAX 160000 + +#endif /* _BQ25750_CHARGER_H */