aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/power/ab8500_charger.c81
-rw-r--r--drivers/power/abx500_chargalg.c62
-rw-r--r--include/linux/mfd/abx500.h1
-rw-r--r--include/linux/mfd/abx500/ab8500-bm.h12
-rw-r--r--include/linux/mfd/abx500/ux500_chargalg.h4
5 files changed, 160 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 &&
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 188aedc322c2..cd71d8eadf50 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -267,6 +267,7 @@ struct abx500_bm_data {
267 bool autopower_cfg; 267 bool autopower_cfg;
268 bool ac_enabled; 268 bool ac_enabled;
269 bool usb_enabled; 269 bool usb_enabled;
270 bool usb_power_path;
270 bool no_maintenance; 271 bool no_maintenance;
271 bool capacity_scaling; 272 bool capacity_scaling;
272 bool chg_unknown_bat; 273 bool chg_unknown_bat;
diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h
index a73e05a0441b..0ebf0c5d1f88 100644
--- a/include/linux/mfd/abx500/ab8500-bm.h
+++ b/include/linux/mfd/abx500/ab8500-bm.h
@@ -69,6 +69,8 @@
69#define AB8500_USBCH_CTRL1_REG 0xC0 69#define AB8500_USBCH_CTRL1_REG 0xC0
70#define AB8500_USBCH_CTRL2_REG 0xC1 70#define AB8500_USBCH_CTRL2_REG 0xC1
71#define AB8500_USBCH_IPT_CRNTLVL_REG 0xC2 71#define AB8500_USBCH_IPT_CRNTLVL_REG 0xC2
72#define AB8540_USB_PP_MODE_REG 0xC5
73#define AB8540_USB_PP_CHR_REG 0xC6
72 74
73/* 75/*
74 * Gas Gauge register offsets 76 * Gas Gauge register offsets
@@ -259,6 +261,16 @@ enum bup_vch_sel {
259#define AB8505_RTC_PCUT_RESTART_REG 0x16 261#define AB8505_RTC_PCUT_RESTART_REG 0x16
260#define AB8505_RTC_PCUT_DEBOUNCE_REG 0x17 262#define AB8505_RTC_PCUT_DEBOUNCE_REG 0x17
261 263
264/* USB Power Path constants for ab8540 */
265#define BUS_VSYS_VOL_SELECT_MASK 0x06
266#define BUS_VSYS_VOL_SELECT_3P6V 0x00
267#define BUS_VSYS_VOL_SELECT_3P325V 0x02
268#define BUS_VSYS_VOL_SELECT_3P9V 0x04
269#define BUS_VSYS_VOL_SELECT_4P3V 0x06
270#define BUS_POWER_PATH_MODE_ENA 0x01
271#define BUS_PP_PRECHG_CURRENT_MASK 0x0E
272#define BUS_POWER_PATH_PRECHG_ENA 0x01
273
262/** 274/**
263 * struct res_to_temp - defines one point in a temp to res curve. To 275 * struct res_to_temp - defines one point in a temp to res curve. To
264 * be used in battery packs that combines the identification resistor with a 276 * be used in battery packs that combines the identification resistor with a
diff --git a/include/linux/mfd/abx500/ux500_chargalg.h b/include/linux/mfd/abx500/ux500_chargalg.h
index fa831f1e8cf8..234c99143bf7 100644
--- a/include/linux/mfd/abx500/ux500_chargalg.h
+++ b/include/linux/mfd/abx500/ux500_chargalg.h
@@ -20,6 +20,8 @@ struct ux500_charger_ops {
20 int (*check_enable) (struct ux500_charger *, int, int); 20 int (*check_enable) (struct ux500_charger *, int, int);
21 int (*kick_wd) (struct ux500_charger *); 21 int (*kick_wd) (struct ux500_charger *);
22 int (*update_curr) (struct ux500_charger *, int); 22 int (*update_curr) (struct ux500_charger *, int);
23 int (*pp_enable) (struct ux500_charger *, bool);
24 int (*pre_chg_enable) (struct ux500_charger *, bool);
23}; 25};
24 26
25/** 27/**
@@ -30,6 +32,7 @@ struct ux500_charger_ops {
30 * @max_out_curr maximum output charger current in mA 32 * @max_out_curr maximum output charger current in mA
31 * @enabled indicates if this charger is used or not 33 * @enabled indicates if this charger is used or not
32 * @external external charger unit (pm2xxx) 34 * @external external charger unit (pm2xxx)
35 * @power_path USB power path support
33 */ 36 */
34struct ux500_charger { 37struct ux500_charger {
35 struct power_supply psy; 38 struct power_supply psy;
@@ -39,6 +42,7 @@ struct ux500_charger {
39 int wdt_refresh; 42 int wdt_refresh;
40 bool enabled; 43 bool enabled;
41 bool external; 44 bool external;
45 bool power_path;
42}; 46};
43 47
44extern struct blocking_notifier_head charger_notifier_list; 48extern struct blocking_notifier_head charger_notifier_list;