aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/ab8500_charger.c
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/power/ab8500_charger.c
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/power/ab8500_charger.c')
-rw-r--r--drivers/power/ab8500_charger.c81
1 files changed, 81 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 */