aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2013-02-14 07:39:15 -0500
committerLee Jones <lee.jones@linaro.org>2013-03-06 23:35:46 -0500
commitdb43e6c473b57d4e7a55c4bd6edef71f40f13eae (patch)
tree0fbe4762c914ba15898cf8bcb9bd8e531fe8fc31 /drivers
parent405fea1c6691eb8259f2ca879c9348a4cf5d898d (diff)
ab8500-bm: Add usb power path support
AB8540 supports power path function in USB charging mode for fast power up with dead and weak battery, and it could extend the battery age. When USB charging starts, if the Vbattrue is below than SW cut off voltage, power path and pre-charge should be enabled. If Vbattrue is higher than SW cut off voltage, power path and pre-charge should be disabled. This is to make sure full current to battery charge. At the end of charge, power path should be enable again to reduce charging the battery again. Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/power/ab8500_charger.c81
-rw-r--r--drivers/power/abx500_chargalg.c62
2 files changed, 143 insertions, 0 deletions
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 6fea4fdf8701..f249a65b02e1 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -1925,6 +1925,67 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
1925 return ret; 1925 return ret;
1926} 1926}
1927 1927
1928/**
1929 * ab8540_charger_power_path_enable() - enable usb power path mode
1930 * @charger: pointer to the ux500_charger structure
1931 * @enable: enable/disable flag
1932 *
1933 * Enable or disable the power path for usb mode
1934 * Returns error code in case of failure else 0(on success)
1935 */
1936static int ab8540_charger_power_path_enable(struct ux500_charger *charger,
1937 bool enable)
1938{
1939 int ret;
1940 struct ab8500_charger *di;
1941
1942 if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
1943 di = to_ab8500_charger_usb_device_info(charger);
1944 else
1945 return -ENXIO;
1946
1947 ret = abx500_mask_and_set_register_interruptible(di->dev,
1948 AB8500_CHARGER, AB8540_USB_PP_MODE_REG,
1949 BUS_POWER_PATH_MODE_ENA, enable);
1950 if (ret) {
1951 dev_err(di->dev, "%s write failed\n", __func__);
1952 return ret;
1953 }
1954
1955 return ret;
1956}
1957
1958
1959/**
1960 * ab8540_charger_usb_pre_chg_enable() - enable usb pre change
1961 * @charger: pointer to the ux500_charger structure
1962 * @enable: enable/disable flag
1963 *
1964 * Enable or disable the pre-chage for usb mode
1965 * Returns error code in case of failure else 0(on success)
1966 */
1967static int ab8540_charger_usb_pre_chg_enable(struct ux500_charger *charger,
1968 bool enable)
1969{
1970 int ret;
1971 struct ab8500_charger *di;
1972
1973 if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
1974 di = to_ab8500_charger_usb_device_info(charger);
1975 else
1976 return -ENXIO;
1977
1978 ret = abx500_mask_and_set_register_interruptible(di->dev,
1979 AB8500_CHARGER, AB8540_USB_PP_CHR_REG,
1980 BUS_POWER_PATH_PRECHG_ENA, enable);
1981 if (ret) {
1982 dev_err(di->dev, "%s write failed\n", __func__);
1983 return ret;
1984 }
1985
1986 return ret;
1987}
1988
1928static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data) 1989static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
1929{ 1990{
1930 struct power_supply *psy; 1991 struct power_supply *psy;
@@ -3201,6 +3262,23 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
3201 if (ret < 0) 3262 if (ret < 0)
3202 dev_err(di->dev, "%s mask and set failed\n", __func__); 3263 dev_err(di->dev, "%s mask and set failed\n", __func__);
3203 3264
3265 if (is_ab8540(di->parent)) {
3266 ret = abx500_mask_and_set_register_interruptible(di->dev,
3267 AB8500_CHARGER, AB8540_USB_PP_MODE_REG,
3268 BUS_VSYS_VOL_SELECT_MASK, BUS_VSYS_VOL_SELECT_3P6V);
3269 if (ret) {
3270 dev_err(di->dev, "failed to setup usb power path vsys voltage\n");
3271 goto out;
3272 }
3273 ret = abx500_mask_and_set_register_interruptible(di->dev,
3274 AB8500_CHARGER, AB8540_USB_PP_CHR_REG,
3275 BUS_PP_PRECHG_CURRENT_MASK, 0);
3276 if (ret) {
3277 dev_err(di->dev, "failed to setup usb power path prechage current\n");
3278 goto out;
3279 }
3280 }
3281
3204out: 3282out:
3205 return ret; 3283 return ret;
3206} 3284}
@@ -3484,6 +3562,8 @@ static int ab8500_charger_probe(struct platform_device *pdev)
3484 di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable; 3562 di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable;
3485 di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; 3563 di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
3486 di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current; 3564 di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current;
3565 di->usb_chg.ops.pp_enable = &ab8540_charger_power_path_enable;
3566 di->usb_chg.ops.pre_chg_enable = &ab8540_charger_usb_pre_chg_enable;
3487 di->usb_chg.max_out_volt = ab8500_charger_voltage_map[ 3567 di->usb_chg.max_out_volt = ab8500_charger_voltage_map[
3488 ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; 3568 ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
3489 di->usb_chg.max_out_curr = ab8500_charger_current_map[ 3569 di->usb_chg.max_out_curr = ab8500_charger_current_map[
@@ -3491,6 +3571,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
3491 di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; 3571 di->usb_chg.wdt_refresh = CHG_WD_INTERVAL;
3492 di->usb_chg.enabled = di->bm->usb_enabled; 3572 di->usb_chg.enabled = di->bm->usb_enabled;
3493 di->usb_chg.external = false; 3573 di->usb_chg.external = false;
3574 di->usb_chg.power_path = di->bm->usb_power_path;
3494 di->usb_state.usb_current = -1; 3575 di->usb_state.usb_current = -1;
3495 3576
3496 /* Create a work queue for the charger */ 3577 /* Create a work queue for the charger */
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index a876976678ab..a9b8efdafb8f 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -34,6 +34,9 @@
34/* End-of-charge criteria counter */ 34/* End-of-charge criteria counter */
35#define EOC_COND_CNT 10 35#define EOC_COND_CNT 10
36 36
37/* Plus margin for the low battery threshold */
38#define BAT_PLUS_MARGIN (100)
39
37#define to_abx500_chargalg_device_info(x) container_of((x), \ 40#define to_abx500_chargalg_device_info(x) container_of((x), \
38 struct abx500_chargalg, chargalg_psy); 41 struct abx500_chargalg, chargalg_psy);
39 42
@@ -83,6 +86,7 @@ enum abx500_chargalg_states {
83 STATE_HW_TEMP_PROTECT_INIT, 86 STATE_HW_TEMP_PROTECT_INIT,
84 STATE_HW_TEMP_PROTECT, 87 STATE_HW_TEMP_PROTECT,
85 STATE_NORMAL_INIT, 88 STATE_NORMAL_INIT,
89 STATE_USB_PP_PRE_CHARGE,
86 STATE_NORMAL, 90 STATE_NORMAL,
87 STATE_WAIT_FOR_RECHARGE_INIT, 91 STATE_WAIT_FOR_RECHARGE_INIT,
88 STATE_WAIT_FOR_RECHARGE, 92 STATE_WAIT_FOR_RECHARGE,
@@ -114,6 +118,7 @@ static const char *states[] = {
114 "HW_TEMP_PROTECT_INIT", 118 "HW_TEMP_PROTECT_INIT",
115 "HW_TEMP_PROTECT", 119 "HW_TEMP_PROTECT",
116 "NORMAL_INIT", 120 "NORMAL_INIT",
121 "USB_PP_PRE_CHARGE",
117 "NORMAL", 122 "NORMAL",
118 "WAIT_FOR_RECHARGE_INIT", 123 "WAIT_FOR_RECHARGE_INIT",
119 "WAIT_FOR_RECHARGE", 124 "WAIT_FOR_RECHARGE",
@@ -560,6 +565,37 @@ static int abx500_chargalg_usb_en(struct abx500_chargalg *di, int enable,
560 return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset); 565 return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset);
561} 566}
562 567
568 /**
569 * ab8540_chargalg_usb_pp_en() - Enable/ disable USB power path
570 * @di: pointer to the abx500_chargalg structure
571 * @enable: power path enable/disable
572 *
573 * The USB power path will be enable/ disable
574 */
575static int ab8540_chargalg_usb_pp_en(struct abx500_chargalg *di, bool enable)
576{
577 if (!di->usb_chg || !di->usb_chg->ops.pp_enable)
578 return -ENXIO;
579
580 return di->usb_chg->ops.pp_enable(di->usb_chg, enable);
581}
582
583/**
584 * ab8540_chargalg_usb_pre_chg_en() - Enable/ disable USB pre-charge
585 * @di: pointer to the abx500_chargalg structure
586 * @enable: USB pre-charge enable/disable
587 *
588 * The USB USB pre-charge will be enable/ disable
589 */
590static int ab8540_chargalg_usb_pre_chg_en(struct abx500_chargalg *di,
591 bool enable)
592{
593 if (!di->usb_chg || !di->usb_chg->ops.pre_chg_enable)
594 return -ENXIO;
595
596 return di->usb_chg->ops.pre_chg_enable(di->usb_chg, enable);
597}
598
563/** 599/**
564 * abx500_chargalg_update_chg_curr() - Update charger current 600 * abx500_chargalg_update_chg_curr() - Update charger current
565 * @di: pointer to the abx500_chargalg structure 601 * @di: pointer to the abx500_chargalg structure
@@ -765,6 +801,9 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
765 di->batt_data.avg_curr > 0) { 801 di->batt_data.avg_curr > 0) {
766 if (++di->eoc_cnt >= EOC_COND_CNT) { 802 if (++di->eoc_cnt >= EOC_COND_CNT) {
767 di->eoc_cnt = 0; 803 di->eoc_cnt = 0;
804 if ((di->chg_info.charger_type & USB_CHG) &&
805 (di->usb_chg->power_path))
806 ab8540_chargalg_usb_pp_en(di, true);
768 di->charge_status = POWER_SUPPLY_STATUS_FULL; 807 di->charge_status = POWER_SUPPLY_STATUS_FULL;
769 di->maintenance_chg = true; 808 di->maintenance_chg = true;
770 dev_dbg(di->dev, "EOC reached!\n"); 809 dev_dbg(di->dev, "EOC reached!\n");
@@ -1465,6 +1504,22 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
1465 break; 1504 break;
1466 1505
1467 case STATE_NORMAL_INIT: 1506 case STATE_NORMAL_INIT:
1507 if ((di->chg_info.charger_type & USB_CHG) &&
1508 di->usb_chg->power_path) {
1509 if (di->batt_data.volt >
1510 (di->bm->fg_params->lowbat_threshold +
1511 BAT_PLUS_MARGIN)) {
1512 ab8540_chargalg_usb_pre_chg_en(di, false);
1513 ab8540_chargalg_usb_pp_en(di, false);
1514 } else {
1515 ab8540_chargalg_usb_pp_en(di, true);
1516 ab8540_chargalg_usb_pre_chg_en(di, true);
1517 abx500_chargalg_state_to(di,
1518 STATE_USB_PP_PRE_CHARGE);
1519 break;
1520 }
1521 }
1522
1468 abx500_chargalg_start_charging(di, 1523 abx500_chargalg_start_charging(di,
1469 di->bm->bat_type[di->bm->batt_id].normal_vol_lvl, 1524 di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
1470 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl); 1525 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
@@ -1479,6 +1534,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
1479 1534
1480 break; 1535 break;
1481 1536
1537 case STATE_USB_PP_PRE_CHARGE:
1538 if (di->batt_data.volt >
1539 (di->bm->fg_params->lowbat_threshold +
1540 BAT_PLUS_MARGIN))
1541 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1542 break;
1543
1482 case STATE_NORMAL: 1544 case STATE_NORMAL:
1483 handle_maxim_chg_curr(di); 1545 handle_maxim_chg_curr(di);
1484 if (di->charge_status == POWER_SUPPLY_STATUS_FULL && 1546 if (di->charge_status == POWER_SUPPLY_STATUS_FULL &&