summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2014-02-05 18:33:12 +0530
committerLaxman Dewangan <ldewangan@nvidia.com>2014-02-11 22:00:47 -0800
commit97ac89362494defda398449708d971d1609bf300 (patch)
treeb7f050cdcd269b2fa1f46094b351d1bfa802c3e4
parentc4b84d35d022129816ff17a01555c14d01681d1c (diff)
power: bq2419x: add support for thermal profiling configuration
BQ2419x support thermal charging based on JEITA. This is default on HW and can not disable by SW. Provide mechanims to add more thermal profiling based on platform along with HW support to match the paltform specific requirements. bug 1435980 Change-Id: I6b6bed8639924e698c953d965248c752d08ad46d Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/363841 (cherry picked from commit cbc4d5e75a7a41af4dc0609c58a045e401ae9cde) Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Change-Id: I4400ca4cd557dddc3b2f9610d0fc0c10a05cd038 Reviewed-on: http://git-master/r/365861
-rw-r--r--Documentation/devicetree/bindings/power/bq2419x-charger.txt16
-rw-r--r--drivers/power/bq2419x-charger.c198
-rw-r--r--include/linux/power/bq2419x-charger.h6
3 files changed, 108 insertions, 112 deletions
diff --git a/Documentation/devicetree/bindings/power/bq2419x-charger.txt b/Documentation/devicetree/bindings/power/bq2419x-charger.txt
index 52cfaa124dcd..b47812c66097 100644
--- a/Documentation/devicetree/bindings/power/bq2419x-charger.txt
+++ b/Documentation/devicetree/bindings/power/bq2419x-charger.txt
@@ -27,6 +27,22 @@ Optional properties:
will be disabled.
- rtc-alarm-time : Time setting in seconds for the rtc alarm timer
which wakes the board up for charging after shutdown.
+- ti,temp-range: List of temperatures in degC for thermal profiling.
+- ti,charge-current-limit: List of fast charging current limit in mA for
+ thermal profiling.
+ The value is provided as
+ ti,temp-range = <15 60>;
+ ti,charge-current-limit = <2048 5200>;
+
+ This will set chargign current limit to
+ 2048 for <= 15 degC and
+ 5200 for 16 to 60 degC
+ This will result:
+ < 0 -> Charger disable. (As by HW)
+ 0 to 10 -> 1048mA charging current limit (as by 50% HW)
+ 11 to 15 -> 2048mA
+ 16 to 60 -> 5200 mA
+ > 60 : Charging will be disabled by HW.
Subnode properties:
==================
diff --git a/drivers/power/bq2419x-charger.c b/drivers/power/bq2419x-charger.c
index c8fe2446bc63..0e66a4e9558e 100644
--- a/drivers/power/bq2419x-charger.c
+++ b/drivers/power/bq2419x-charger.c
@@ -50,23 +50,6 @@
#define bq_chg_err(bq, fmt, ...) \
dev_err(bq->dev, "Charging Fault: " fmt, ##__VA_ARGS__)
-enum charging_states {
- ENABLED_HALF_IBAT = 1,
- ENABLED_FULL_IBAT,
- DISABLED,
-};
-
-static const unsigned int bq2419x_maxcharge_voltage_lookup[] = {
- 3504, 3520, 3536, 3552, 3568, 3584, 3600, 3616,
- 3632, 3648, 3664, 3680, 3696, 3712, 3728, 3744,
- 3760, 3776, 3792, 3808, 3824, 3840, 3856, 3872,
- 3888, 3904, 3920, 3936, 3952, 3968, 3984, 4000,
- 4016, 4032, 4048, 4064, 4080, 4096, 4112, 4128,
- 4144, 4160, 4176, 4192, 4208, 4224, 4240, 4256,
- 4272, 4288, 4304, 4320, 4336, 4352, 4368, 4384,
- 4400, 4416, 4432, 4448, 4464, 4480, 4496, 4512,
-};
-
#define BQ2419X_INPUT_VINDPM_OFFSET 3880
#define BQ2419X_CHARGE_ICHG_OFFSET 512
#define BQ2419X_PRE_CHG_IPRECHG_OFFSET 128
@@ -118,25 +101,15 @@ struct bq2419x_chip {
bool cable_connected;
int last_charging_current;
bool disable_suspend_during_charging;
- int charging_state;
struct bq2419x_reg_info input_src;
struct bq2419x_reg_info chg_current_control;
struct bq2419x_reg_info prechg_term_control;
struct bq2419x_reg_info ir_comp_therm;
struct bq2419x_reg_info chg_voltage_control;
+ struct bq2419x_vbus_platform_data *vbus_pdata;
+ struct bq2419x_charger_platform_data *charger_pdata;
};
-static inline int convert_to_reg(int x)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bq2419x_maxcharge_voltage_lookup); i++) {
- if (x < bq2419x_maxcharge_voltage_lookup[i])
- break;
- }
- return i > 0 ? i - 1 : -EINVAL;
-}
-
static int current_to_reg(const unsigned int *tbl,
size_t size, unsigned int val)
{
@@ -361,6 +334,11 @@ static int bq2419x_charger_init(struct bq2419x_chip *bq2419x)
if (ret < 0)
dev_err(bq2419x->dev, "VOLT_CTRL update failed: %d\n", ret);
+ ret = regmap_update_bits(bq2419x->regmap, BQ2419X_TIME_CTRL_REG,
+ BQ2419X_TIME_JEITA_ISET, 0);
+ if (ret < 0)
+ dev_err(bq2419x->dev, "TIME_CTRL update failed: %d\n", ret);
+
return ret;
}
@@ -397,41 +375,6 @@ static int bq2419x_configure_charging_current(struct bq2419x_chip *bq2419x,
return ret;
}
-int bq2419x_full_current_enable(struct bq2419x_chip *bq2419x)
-{
- int ret;
- int in_current_limit;
-
- in_current_limit = bq2419x->last_charging_current/1000;
- ret = bq2419x_configure_charging_current(bq2419x, in_current_limit);
- if (ret < 0) {
- dev_err(bq2419x->dev,
- "Failed to initialise full current charging\n");
- return ret;
- }
-
- bq2419x->charging_state = ENABLED_FULL_IBAT;
-
- return 0;
-}
-
-int bq2419x_half_current_enable(struct bq2419x_chip *bq2419x)
-{
- int ret;
- int in_current_limit;
-
- in_current_limit = bq2419x->last_charging_current/2000;
- ret = bq2419x_configure_charging_current(bq2419x, in_current_limit);
- if (ret < 0) {
- dev_err(bq2419x->dev,
- "Failed to initialise half current charging\n");
- return ret;
- }
- bq2419x->charging_state = ENABLED_HALF_IBAT;
-
- return 0;
-}
-
static int bq2419x_set_charging_current(struct regulator_dev *rdev,
int min_uA, int max_uA)
{
@@ -469,7 +412,6 @@ static int bq2419x_set_charging_current(struct regulator_dev *rdev,
in_current_limit = max_uA/1000;
bq2419x->cable_connected = 1;
bq2419x->chg_status = BATTERY_CHARGING;
- bq2419x->charging_state = ENABLED_FULL_IBAT;
battery_charger_thermal_start_monitoring(
bq2419x->bc_dev);
}
@@ -1114,57 +1056,47 @@ static int bq2419x_charger_thermal_configure(
int battery_voltage)
{
struct bq2419x_chip *bq2419x = battery_charger_get_drvdata(bc_dev);
- int temperature;
- int battery_threshold_voltage;
- int in_current_limit;
+ struct bq2419x_charger_platform_data *chg_pdata;
+ int fast_charge_current = 0;
+ int ichg;
int ret;
+ int i;
+ int curr_ichg;
- if (!bq2419x->cable_connected)
+ chg_pdata = bq2419x->charger_pdata;
+ if (!bq2419x->cable_connected || !chg_pdata->n_temp_profile)
return 0;
- temperature = temp;
- dev_info(bq2419x->dev, "Battery temp %d\n", temperature);
- if (enable_charger) {
- if (!enable_charg_half_current &&
- bq2419x->charging_state != ENABLED_FULL_IBAT) {
- ret = regmap_update_bits(bq2419x->regmap,
- BQ2419X_VOLT_CTRL_REG,
- bq2419x->chg_voltage_control.mask,
- bq2419x->chg_voltage_control.val);
- if (ret < 0) {
- dev_err(bq2419x->dev,
- "VOLT_CTRL update failed %d\n", ret);
- return ret;
- }
- bq2419x_full_current_enable(bq2419x);
- battery_charging_status_update(bq2419x->bc_dev,
- BATTERY_CHARGING);
- } else if (enable_charg_half_current &&
- bq2419x->charging_state != ENABLED_HALF_IBAT) {
- bq2419x_half_current_enable(bq2419x);
- /*Set charge voltage */
- battery_threshold_voltage =
- convert_to_reg(battery_voltage);
- ret = regmap_update_bits(bq2419x->regmap,
- BQ2419X_VOLT_CTRL_REG, BQ2419x_VOLTAGE_CTRL_MASK,
- battery_threshold_voltage << 2);
- if (ret < 0)
- return ret;
- battery_charging_status_update(bq2419x->bc_dev,
- BATTERY_CHARGING);
- }
- } else {
- if (bq2419x->charging_state != DISABLED) {
- in_current_limit = 500;
- ret = bq2419x_configure_charging_current(bq2419x,
- in_current_limit);
- if (ret < 0)
- return ret;
- bq2419x->charging_state = DISABLED;
- battery_charging_status_update(bq2419x->bc_dev,
- BATTERY_DISCHARGING);
+ dev_info(bq2419x->dev, "Battery temp %d\n", temp);
+
+ for (i = 0; i < chg_pdata->n_temp_profile; ++i) {
+ if (temp <= chg_pdata->temp_range[i]) {
+ fast_charge_current = chg_pdata->chg_current_limit[i];
+ break;
}
}
+ if (!fast_charge_current || !temp) {
+ dev_info(bq2419x->dev, "Disable charging done by HW\n");
+ return 0;
+ }
+
+ /* Fast charger become 50% when temp is at < 10 degC */
+ if (temp <= 10)
+ fast_charge_current *= 2;
+
+ curr_ichg = bq2419x->chg_current_control.val >> 2;
+ ichg = bq2419x_val_to_reg(fast_charge_current,
+ BQ2419X_CHARGE_ICHG_OFFSET, 64, 6, 0);
+ if (curr_ichg == ichg)
+ return 0;
+
+ bq2419x->chg_current_control.val = ichg << 2;
+ ret = regmap_update_bits(bq2419x->regmap, BQ2419X_CHRG_CTRL_REG,
+ BQ2419X_CHRG_CTRL_ICHG_MASK, ichg << 2);
+ if (ret < 0) {
+ dev_err(bq2419x->dev, "CHRG_CTRL_REG update failed %d\n", ret);
+ return ret;
+ }
return 0;
}
@@ -1215,10 +1147,12 @@ static struct bq2419x_platform_data *bq2419x_dt_parse(struct i2c_client *client)
batt_reg_node = of_find_node_by_name(np, "charger");
if (batt_reg_node) {
+ int temp_range_len, chg_current_lim_len;
int wdt_timeout;
int chg_restart_time;
int temp_polling_time;
struct regulator_init_data *batt_init_data;
+ struct bq2419x_charger_platform_data *chg_pdata;
const char *status_str;
struct bq2419x_charger_platform_data *bcharger_pdata;
u32 pval;
@@ -1236,6 +1170,7 @@ static struct bq2419x_platform_data *bq2419x_dt_parse(struct i2c_client *client)
return ERR_PTR(-ENOMEM);
bcharger_pdata = pdata->bcharger_pdata;
+ chg_pdata = pdata->bcharger_pdata;
batt_init_data = of_get_regulator_init_data(&client->dev,
batt_reg_node);
if (!batt_init_data)
@@ -1304,8 +1239,47 @@ static struct bq2419x_platform_data *bq2419x_dt_parse(struct i2c_client *client)
bcharger_pdata->temp_polling_time_sec =
temp_polling_time;
- pdata->bcharger_pdata->tz_name = of_get_property(batt_reg_node,
+ chg_pdata->tz_name = of_get_property(batt_reg_node,
"ti,thermal-zone", NULL);
+
+ temp_range_len = of_property_count_u32(batt_reg_node,
+ "ti,temp-range");
+ chg_current_lim_len = of_property_count_u32(batt_reg_node,
+ "ti,charge-current-limit");
+ if (temp_range_len < 0)
+ goto skip_therm_profile;
+
+ if (temp_range_len != chg_current_lim_len) {
+ dev_info(&client->dev,
+ "thermal profile data is not correct\n");
+ goto skip_therm_profile;
+ }
+
+ chg_pdata->temp_range = devm_kzalloc(&client->dev,
+ sizeof(u32) * temp_range_len, GFP_KERNEL);
+ if (!chg_pdata->temp_range)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_u32_array(batt_reg_node, "ti,temp-range",
+ chg_pdata->temp_range, temp_range_len);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ chg_pdata->chg_current_limit = devm_kzalloc(&client->dev,
+ sizeof(u32) * temp_range_len, GFP_KERNEL);
+ if (!chg_pdata->chg_current_limit)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_u32_array(batt_reg_node,
+ "ti,charge-current-limit",
+ chg_pdata->chg_current_limit,
+ temp_range_len);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ chg_pdata->n_temp_profile = temp_range_len;
+
+skip_therm_profile:
pdata->bcharger_pdata->consumer_supplies =
batt_init_data->consumer_supplies;
pdata->bcharger_pdata->num_consumer_supplies =
@@ -1371,6 +1345,8 @@ static int bq2419x_probe(struct i2c_client *client,
dev_err(&client->dev, "Memory allocation failed\n");
return -ENOMEM;
}
+ bq2419x->charger_pdata = pdata->bcharger_pdata;
+ bq2419x->vbus_pdata = pdata->vbus_pdata;
bq2419x->regmap = devm_regmap_init_i2c(client, &bq2419x_regmap_config);
if (IS_ERR(bq2419x->regmap)) {
diff --git a/include/linux/power/bq2419x-charger.h b/include/linux/power/bq2419x-charger.h
index b55ccbcdc895..c4ea43139c17 100644
--- a/include/linux/power/bq2419x-charger.h
+++ b/include/linux/power/bq2419x-charger.h
@@ -51,13 +51,14 @@
#define BQ2419X_THERM_VCLAMP_MASK 0x1C
#define BQ2419X_THERM_TREG_MASK 0x03
+#define BQ2419X_TIME_JEITA_ISET 0x01
+
#define BQ2419X_CHG_VOLT_LIMIT_MASK 0xFC
#define BQ24190_IC_VER 0x40
#define BQ24192_IC_VER 0x28
#define BQ24192i_IC_VER 0x18
-#define BQ2419X_CHARGE_CURRENT_MASK ~(0x03)
#define BQ2419X_ENABLE_CHARGE_MASK 0x30
#define BQ2419X_ENABLE_VBUS 0x20
#define BQ2419X_ENABLE_CHARGE 0x10
@@ -144,6 +145,9 @@ struct bq2419x_charger_platform_data {
bool disable_suspend_during_charging;
bool enable_thermal_monitor; /* TRUE if FuelGauge provides temp */
int temp_polling_time_sec;
+ int n_temp_profile;
+ u32 *temp_range;
+ u32 *chg_current_limit;
};
/*