summaryrefslogtreecommitdiff
path: root/drivers/power/supply/bq256xx_charger.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/supply/bq256xx_charger.c')
-rw-r--r--drivers/power/supply/bq256xx_charger.c159
1 files changed, 114 insertions, 45 deletions
diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c
index b274942dc46a..ae14162f017a 100644
--- a/drivers/power/supply/bq256xx_charger.c
+++ b/drivers/power/supply/bq256xx_charger.c
@@ -41,6 +41,9 @@
#define BQ256XX_IINDPM_MAX_uA 3200000
#define BQ256XX_IINDPM_DEF_uA 2400000
+#define BQ256XX_TS_IGNORE BIT(6)
+#define BQ256XX_TS_IGNORE_SHIFT 6
+
#define BQ256XX_VINDPM_MASK GENMASK(3, 0)
#define BQ256XX_VINDPM_STEP_uV 100000
#define BQ256XX_VINDPM_OFFSET_uV 3900000
@@ -70,6 +73,9 @@
#define BQ25611D_VBATREG_THRESH_uV 4290000
#define BQ25618_VBATREG_THRESH_uV 4300000
+#define BQ256XX_CHG_CONFIG_MASK BIT(4)
+#define BQ256XX_CHG_CONFIG_BIT_SHIFT 4
+
#define BQ256XX_ITERM_MASK GENMASK(3, 0)
#define BQ256XX_ITERM_STEP_uA 60000
#define BQ256XX_ITERM_OFFSET_uA 60000
@@ -153,6 +159,7 @@
* @vindpm: input voltage limit
* @ichg_max: maximum fast charge current
* @vbatreg_max: maximum charge voltage
+ * @ts_ignore: TS_IGNORE flag
*/
struct bq256xx_init_data {
u32 ichg;
@@ -163,6 +170,7 @@ struct bq256xx_init_data {
u32 vindpm;
u32 ichg_max;
u32 vbatreg_max;
+ bool ts_ignore;
};
/**
@@ -259,6 +267,8 @@ struct bq256xx_device {
* @bq256xx_set_iterm: pointer to instance specific set_iterm function
* @bq256xx_set_iprechg: pointer to instance specific set_iprechg function
* @bq256xx_set_vindpm: pointer to instance specific set_vindpm function
+ * @bq256xx_set_charge_type: pointer to instance specific set_charge_type function
+ * @bq256xx_set_ts_ignore: pointer to instance specific set_ts_ignore function
*
* @bq256xx_def_ichg: default ichg value in microamps
* @bq256xx_def_iindpm: default iindpm value in microamps
@@ -290,6 +300,8 @@ struct bq256xx_chip_info {
int (*bq256xx_set_iterm)(struct bq256xx_device *bq, int iterm);
int (*bq256xx_set_iprechg)(struct bq256xx_device *bq, int iprechg);
int (*bq256xx_set_vindpm)(struct bq256xx_device *bq, int vindpm);
+ int (*bq256xx_set_charge_type)(struct bq256xx_device *bq, int type);
+ int (*bq256xx_set_ts_ignore)(struct bq256xx_device *bq, bool ts_ignore);
int bq256xx_def_ichg;
int bq256xx_def_iindpm;
@@ -322,14 +334,6 @@ static const int bq25618_619_ichg_values[] = {
1290000, 1360000, 1430000, 1500000
};
-static enum power_supply_usb_type bq256xx_usb_type[] = {
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
- POWER_SUPPLY_USB_TYPE_ACA,
-};
-
static int bq256xx_array_parse(int array_size, int val, const int array[])
{
int i = 0;
@@ -383,7 +387,7 @@ static void bq256xx_usb_work(struct work_struct *data)
}
}
-static struct reg_default bq2560x_reg_defs[] = {
+static const struct reg_default bq2560x_reg_defs[] = {
{BQ256XX_INPUT_CURRENT_LIMIT, 0x17},
{BQ256XX_CHARGER_CONTROL_0, 0x1a},
{BQ256XX_CHARGE_CURRENT_LIMIT, 0xa2},
@@ -394,7 +398,7 @@ static struct reg_default bq2560x_reg_defs[] = {
{BQ256XX_CHARGER_CONTROL_3, 0x4c},
};
-static struct reg_default bq25611d_reg_defs[] = {
+static const struct reg_default bq25611d_reg_defs[] = {
{BQ256XX_INPUT_CURRENT_LIMIT, 0x17},
{BQ256XX_CHARGER_CONTROL_0, 0x1a},
{BQ256XX_CHARGE_CURRENT_LIMIT, 0x91},
@@ -407,7 +411,7 @@ static struct reg_default bq25611d_reg_defs[] = {
{BQ256XX_CHARGER_CONTROL_4, 0x75},
};
-static struct reg_default bq25618_619_reg_defs[] = {
+static const struct reg_default bq25618_619_reg_defs[] = {
{BQ256XX_INPUT_CURRENT_LIMIT, 0x17},
{BQ256XX_CHARGER_CONTROL_0, 0x1a},
{BQ256XX_CHARGE_CURRENT_LIMIT, 0x91},
@@ -449,6 +453,27 @@ static int bq256xx_get_state(struct bq256xx_device *bq,
return 0;
}
+static int bq256xx_set_charge_type(struct bq256xx_device *bq, int type)
+{
+ int chg_config = 0;
+
+ switch (type) {
+ case POWER_SUPPLY_CHARGE_TYPE_NONE:
+ chg_config = 0x0;
+ break;
+ case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:
+ case POWER_SUPPLY_CHARGE_TYPE_FAST:
+ chg_config = 0x1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(bq->regmap, BQ256XX_CHARGER_CONTROL_0,
+ BQ256XX_CHG_CONFIG_MASK,
+ (chg_config ? 1 : 0) << BQ256XX_CHG_CONFIG_BIT_SHIFT);
+}
+
static int bq256xx_get_ichg_curr(struct bq256xx_device *bq)
{
unsigned int charge_current_limit;
@@ -670,6 +695,12 @@ static int bq25601d_set_chrg_volt(struct bq256xx_device *bq, int vbatreg)
BQ256XX_VBATREG_BIT_SHIFT);
}
+static int bq256xx_set_ts_ignore(struct bq256xx_device *bq, bool ts_ignore)
+{
+ return regmap_update_bits(bq->regmap, BQ256XX_INPUT_CURRENT_LIMIT,
+ BQ256XX_TS_IGNORE, (ts_ignore ? 1 : 0) << BQ256XX_TS_IGNORE_SHIFT);
+}
+
static int bq256xx_get_prechrg_curr(struct bq256xx_device *bq)
{
unsigned int prechg_and_term_curr_lim;
@@ -915,6 +946,12 @@ static int bq256xx_set_charger_property(struct power_supply *psy,
return ret;
break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ ret = bq->chip_info->bq256xx_set_charge_type(bq, val->intval);
+ if (ret)
+ return ret;
+ break;
+
default:
break;
}
@@ -1197,6 +1234,7 @@ static int bq256xx_property_is_writeable(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
case POWER_SUPPLY_PROP_STATUS:
case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
return true;
default:
return false;
@@ -1206,8 +1244,11 @@ static int bq256xx_property_is_writeable(struct power_supply *psy,
static const struct power_supply_desc bq256xx_power_supply_desc = {
.name = "bq256xx-charger",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = bq256xx_usb_type,
- .num_usb_types = ARRAY_SIZE(bq256xx_usb_type),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_ACA) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = bq256xx_power_supply_props,
.num_properties = ARRAY_SIZE(bq256xx_power_supply_props),
.get_property = bq256xx_get_charger_property,
@@ -1279,6 +1320,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_get_iterm = bq256xx_get_term_curr,
.bq256xx_get_iprechg = bq256xx_get_prechrg_curr,
.bq256xx_get_vindpm = bq256xx_get_input_volt_lim,
+ .bq256xx_set_ts_ignore = NULL,
.bq256xx_set_ichg = bq256xx_set_ichg_curr,
.bq256xx_set_iindpm = bq256xx_set_input_curr_lim,
@@ -1286,6 +1328,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iterm = bq256xx_set_term_curr,
.bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+ .bq256xx_set_charge_type = bq256xx_set_charge_type,
.bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1316,6 +1359,8 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iterm = bq256xx_set_term_curr,
.bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+ .bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = NULL,
.bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1346,6 +1391,8 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iterm = bq256xx_set_term_curr,
.bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+ .bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = NULL,
.bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1376,6 +1423,8 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iterm = bq256xx_set_term_curr,
.bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+ .bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = NULL,
.bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1406,6 +1455,8 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iterm = bq256xx_set_term_curr,
.bq256xx_set_iprechg = bq256xx_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+ .bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = bq256xx_set_ts_ignore,
.bq256xx_def_ichg = BQ25611D_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1436,6 +1487,8 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iterm = bq25618_619_set_term_curr,
.bq256xx_set_iprechg = bq25618_619_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+ .bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = bq256xx_set_ts_ignore,
.bq256xx_def_ichg = BQ25618_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1466,6 +1519,8 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = {
.bq256xx_set_iterm = bq25618_619_set_term_curr,
.bq256xx_set_iprechg = bq25618_619_set_prechrg_curr,
.bq256xx_set_vindpm = bq256xx_set_input_volt_lim,
+ .bq256xx_set_charge_type = bq256xx_set_charge_type,
+ .bq256xx_set_ts_ignore = bq256xx_set_ts_ignore,
.bq256xx_def_ichg = BQ25618_ICHG_DEF_uA,
.bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA,
@@ -1514,15 +1569,21 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
wd_reg_val = i;
break;
}
- if (bq->watchdog_timer > bq256xx_watchdog_time[i] &&
+ if (i + 1 < BQ256XX_NUM_WD_VAL &&
+ bq->watchdog_timer > bq256xx_watchdog_time[i] &&
bq->watchdog_timer < bq256xx_watchdog_time[i + 1])
wd_reg_val = i;
}
ret = regmap_update_bits(bq->regmap, BQ256XX_CHARGER_CONTROL_1,
BQ256XX_WATCHDOG_MASK, wd_reg_val <<
BQ256XX_WDT_BIT_SHIFT);
+ if (ret)
+ return ret;
ret = power_supply_get_battery_info(bq->charger, &bat_info);
+ if (ret == -ENOMEM)
+ return ret;
+
if (ret) {
dev_warn(bq->dev, "battery info missing, default values will be applied\n");
@@ -1560,7 +1621,7 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
return ret;
ret = bq->chip_info->bq256xx_set_ichg(bq,
- bat_info->constant_charge_current_max_ua);
+ bq->chip_info->bq256xx_def_ichg);
if (ret)
return ret;
@@ -1570,7 +1631,7 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
return ret;
ret = bq->chip_info->bq256xx_set_vbatreg(bq,
- bat_info->constant_charge_voltage_max_uv);
+ bq->chip_info->bq256xx_def_vbatreg);
if (ret)
return ret;
@@ -1579,6 +1640,12 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
if (ret)
return ret;
+ if (bq->chip_info->bq256xx_set_ts_ignore) {
+ ret = bq->chip_info->bq256xx_set_ts_ignore(bq, bq->init_data.ts_ignore);
+ if (ret)
+ return ret;
+ }
+
power_supply_put_battery_info(bq->charger, bat_info);
return 0;
@@ -1590,7 +1657,7 @@ static int bq256xx_parse_dt(struct bq256xx_device *bq,
int ret = 0;
psy_cfg->drv_data = bq;
- psy_cfg->of_node = dev->of_node;
+ psy_cfg->fwnode = dev_fwnode(dev);
ret = device_property_read_u32(bq->dev, "ti,watchdog-timeout-ms",
&bq->watchdog_timer);
@@ -1613,12 +1680,14 @@ static int bq256xx_parse_dt(struct bq256xx_device *bq,
if (ret)
bq->init_data.iindpm = bq->chip_info->bq256xx_def_iindpm;
+ bq->init_data.ts_ignore = device_property_read_bool(bq->dev, "ti,no-thermistor");
+
return 0;
}
-static int bq256xx_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bq256xx_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct device *dev = &client->dev;
struct bq256xx_device *bq;
struct power_supply_config psy_cfg = { };
@@ -1631,11 +1700,11 @@ static int bq256xx_probe(struct i2c_client *client,
bq->client = client;
bq->dev = dev;
- bq->chip_info = &bq256xx_chip_info_tbl[id->driver_data];
+ bq->chip_info = i2c_get_match_data(client);
mutex_init(&bq->lock);
- strncpy(bq->model_name, id->name, I2C_NAME_SIZE);
+ strscpy(bq->model_name, id->name, sizeof(bq->model_name));
bq->regmap = devm_regmap_init_i2c(client,
bq->chip_info->bq256xx_regmap_config);
@@ -1700,38 +1769,38 @@ static int bq256xx_probe(struct i2c_client *client,
}
static const struct i2c_device_id bq256xx_i2c_ids[] = {
- { "bq25600", BQ25600 },
- { "bq25600d", BQ25600D },
- { "bq25601", BQ25601 },
- { "bq25601d", BQ25601D },
- { "bq25611d", BQ25611D },
- { "bq25618", BQ25618 },
- { "bq25619", BQ25619 },
- {},
+ { "bq25600", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600] },
+ { "bq25600d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600D] },
+ { "bq25601", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601] },
+ { "bq25601d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601D] },
+ { "bq25611d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25611D] },
+ { "bq25618", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25618] },
+ { "bq25619", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25619] },
+ {}
};
MODULE_DEVICE_TABLE(i2c, bq256xx_i2c_ids);
static const struct of_device_id bq256xx_of_match[] = {
- { .compatible = "ti,bq25600", .data = (void *)BQ25600 },
- { .compatible = "ti,bq25600d", .data = (void *)BQ25600D },
- { .compatible = "ti,bq25601", .data = (void *)BQ25601 },
- { .compatible = "ti,bq25601d", .data = (void *)BQ25601D },
- { .compatible = "ti,bq25611d", .data = (void *)BQ25611D },
- { .compatible = "ti,bq25618", .data = (void *)BQ25618 },
- { .compatible = "ti,bq25619", .data = (void *)BQ25619 },
- { },
+ { .compatible = "ti,bq25600", .data = &bq256xx_chip_info_tbl[BQ25600] },
+ { .compatible = "ti,bq25600d", .data = &bq256xx_chip_info_tbl[BQ25600D] },
+ { .compatible = "ti,bq25601", .data = &bq256xx_chip_info_tbl[BQ25601] },
+ { .compatible = "ti,bq25601d", .data = &bq256xx_chip_info_tbl[BQ25601D] },
+ { .compatible = "ti,bq25611d", .data = &bq256xx_chip_info_tbl[BQ25611D] },
+ { .compatible = "ti,bq25618", .data = &bq256xx_chip_info_tbl[BQ25618] },
+ { .compatible = "ti,bq25619", .data = &bq256xx_chip_info_tbl[BQ25619] },
+ {}
};
MODULE_DEVICE_TABLE(of, bq256xx_of_match);
static const struct acpi_device_id bq256xx_acpi_match[] = {
- { "bq25600", BQ25600 },
- { "bq25600d", BQ25600D },
- { "bq25601", BQ25601 },
- { "bq25601d", BQ25601D },
- { "bq25611d", BQ25611D },
- { "bq25618", BQ25618 },
- { "bq25619", BQ25619 },
- {},
+ { "bq25600", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600] },
+ { "bq25600d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600D] },
+ { "bq25601", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601] },
+ { "bq25601d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601D] },
+ { "bq25611d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25611D] },
+ { "bq25618", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25618] },
+ { "bq25619", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25619] },
+ {}
};
MODULE_DEVICE_TABLE(acpi, bq256xx_acpi_match);