Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 367472
b: refs/heads/master
c: db43e6c
h: refs/heads/master
v: v3
  • Loading branch information
Lee Jones committed Mar 7, 2013
1 parent a0e2535 commit ff74a40
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 405fea1c6691eb8259f2ca879c9348a4cf5d898d
refs/heads/master: db43e6c473b57d4e7a55c4bd6edef71f40f13eae
81 changes: 81 additions & 0 deletions trunk/drivers/power/ab8500_charger.c
Original file line number Diff line number Diff line change
Expand Up @@ -1925,6 +1925,67 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
return ret;
}

/**
* ab8540_charger_power_path_enable() - enable usb power path mode
* @charger: pointer to the ux500_charger structure
* @enable: enable/disable flag
*
* Enable or disable the power path for usb mode
* Returns error code in case of failure else 0(on success)
*/
static int ab8540_charger_power_path_enable(struct ux500_charger *charger,
bool enable)
{
int ret;
struct ab8500_charger *di;

if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
di = to_ab8500_charger_usb_device_info(charger);
else
return -ENXIO;

ret = abx500_mask_and_set_register_interruptible(di->dev,
AB8500_CHARGER, AB8540_USB_PP_MODE_REG,
BUS_POWER_PATH_MODE_ENA, enable);
if (ret) {
dev_err(di->dev, "%s write failed\n", __func__);
return ret;
}

return ret;
}


/**
* ab8540_charger_usb_pre_chg_enable() - enable usb pre change
* @charger: pointer to the ux500_charger structure
* @enable: enable/disable flag
*
* Enable or disable the pre-chage for usb mode
* Returns error code in case of failure else 0(on success)
*/
static int ab8540_charger_usb_pre_chg_enable(struct ux500_charger *charger,
bool enable)
{
int ret;
struct ab8500_charger *di;

if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
di = to_ab8500_charger_usb_device_info(charger);
else
return -ENXIO;

ret = abx500_mask_and_set_register_interruptible(di->dev,
AB8500_CHARGER, AB8540_USB_PP_CHR_REG,
BUS_POWER_PATH_PRECHG_ENA, enable);
if (ret) {
dev_err(di->dev, "%s write failed\n", __func__);
return ret;
}

return ret;
}

static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
{
struct power_supply *psy;
Expand Down Expand Up @@ -3201,6 +3262,23 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
if (ret < 0)
dev_err(di->dev, "%s mask and set failed\n", __func__);

if (is_ab8540(di->parent)) {
ret = abx500_mask_and_set_register_interruptible(di->dev,
AB8500_CHARGER, AB8540_USB_PP_MODE_REG,
BUS_VSYS_VOL_SELECT_MASK, BUS_VSYS_VOL_SELECT_3P6V);
if (ret) {
dev_err(di->dev, "failed to setup usb power path vsys voltage\n");
goto out;
}
ret = abx500_mask_and_set_register_interruptible(di->dev,
AB8500_CHARGER, AB8540_USB_PP_CHR_REG,
BUS_PP_PRECHG_CURRENT_MASK, 0);
if (ret) {
dev_err(di->dev, "failed to setup usb power path prechage current\n");
goto out;
}
}

out:
return ret;
}
Expand Down Expand Up @@ -3484,13 +3562,16 @@ static int ab8500_charger_probe(struct platform_device *pdev)
di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable;
di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
di->usb_chg.ops.update_curr = &ab8500_charger_update_charger_current;
di->usb_chg.ops.pp_enable = &ab8540_charger_power_path_enable;
di->usb_chg.ops.pre_chg_enable = &ab8540_charger_usb_pre_chg_enable;
di->usb_chg.max_out_volt = ab8500_charger_voltage_map[
ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
di->usb_chg.max_out_curr = ab8500_charger_current_map[
ARRAY_SIZE(ab8500_charger_current_map) - 1];
di->usb_chg.wdt_refresh = CHG_WD_INTERVAL;
di->usb_chg.enabled = di->bm->usb_enabled;
di->usb_chg.external = false;
di->usb_chg.power_path = di->bm->usb_power_path;
di->usb_state.usb_current = -1;

/* Create a work queue for the charger */
Expand Down
62 changes: 62 additions & 0 deletions trunk/drivers/power/abx500_chargalg.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
/* End-of-charge criteria counter */
#define EOC_COND_CNT 10

/* Plus margin for the low battery threshold */
#define BAT_PLUS_MARGIN (100)

#define to_abx500_chargalg_device_info(x) container_of((x), \
struct abx500_chargalg, chargalg_psy);

Expand Down Expand Up @@ -83,6 +86,7 @@ enum abx500_chargalg_states {
STATE_HW_TEMP_PROTECT_INIT,
STATE_HW_TEMP_PROTECT,
STATE_NORMAL_INIT,
STATE_USB_PP_PRE_CHARGE,
STATE_NORMAL,
STATE_WAIT_FOR_RECHARGE_INIT,
STATE_WAIT_FOR_RECHARGE,
Expand Down Expand Up @@ -114,6 +118,7 @@ static const char *states[] = {
"HW_TEMP_PROTECT_INIT",
"HW_TEMP_PROTECT",
"NORMAL_INIT",
"USB_PP_PRE_CHARGE",
"NORMAL",
"WAIT_FOR_RECHARGE_INIT",
"WAIT_FOR_RECHARGE",
Expand Down Expand Up @@ -560,6 +565,37 @@ static int abx500_chargalg_usb_en(struct abx500_chargalg *di, int enable,
return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset);
}

/**
* ab8540_chargalg_usb_pp_en() - Enable/ disable USB power path
* @di: pointer to the abx500_chargalg structure
* @enable: power path enable/disable
*
* The USB power path will be enable/ disable
*/
static int ab8540_chargalg_usb_pp_en(struct abx500_chargalg *di, bool enable)
{
if (!di->usb_chg || !di->usb_chg->ops.pp_enable)
return -ENXIO;

return di->usb_chg->ops.pp_enable(di->usb_chg, enable);
}

/**
* ab8540_chargalg_usb_pre_chg_en() - Enable/ disable USB pre-charge
* @di: pointer to the abx500_chargalg structure
* @enable: USB pre-charge enable/disable
*
* The USB USB pre-charge will be enable/ disable
*/
static int ab8540_chargalg_usb_pre_chg_en(struct abx500_chargalg *di,
bool enable)
{
if (!di->usb_chg || !di->usb_chg->ops.pre_chg_enable)
return -ENXIO;

return di->usb_chg->ops.pre_chg_enable(di->usb_chg, enable);
}

/**
* abx500_chargalg_update_chg_curr() - Update charger current
* @di: pointer to the abx500_chargalg structure
Expand Down Expand Up @@ -765,6 +801,9 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
di->batt_data.avg_curr > 0) {
if (++di->eoc_cnt >= EOC_COND_CNT) {
di->eoc_cnt = 0;
if ((di->chg_info.charger_type & USB_CHG) &&
(di->usb_chg->power_path))
ab8540_chargalg_usb_pp_en(di, true);
di->charge_status = POWER_SUPPLY_STATUS_FULL;
di->maintenance_chg = true;
dev_dbg(di->dev, "EOC reached!\n");
Expand Down Expand Up @@ -1465,6 +1504,22 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
break;

case STATE_NORMAL_INIT:
if ((di->chg_info.charger_type & USB_CHG) &&
di->usb_chg->power_path) {
if (di->batt_data.volt >
(di->bm->fg_params->lowbat_threshold +
BAT_PLUS_MARGIN)) {
ab8540_chargalg_usb_pre_chg_en(di, false);
ab8540_chargalg_usb_pp_en(di, false);
} else {
ab8540_chargalg_usb_pp_en(di, true);
ab8540_chargalg_usb_pre_chg_en(di, true);
abx500_chargalg_state_to(di,
STATE_USB_PP_PRE_CHARGE);
break;
}
}

abx500_chargalg_start_charging(di,
di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
Expand All @@ -1479,6 +1534,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)

break;

case STATE_USB_PP_PRE_CHARGE:
if (di->batt_data.volt >
(di->bm->fg_params->lowbat_threshold +
BAT_PLUS_MARGIN))
abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
break;

case STATE_NORMAL:
handle_maxim_chg_curr(di);
if (di->charge_status == POWER_SUPPLY_STATUS_FULL &&
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/mfd/abx500.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ struct abx500_bm_data {
bool autopower_cfg;
bool ac_enabled;
bool usb_enabled;
bool usb_power_path;
bool no_maintenance;
bool capacity_scaling;
bool chg_unknown_bat;
Expand Down
12 changes: 12 additions & 0 deletions trunk/include/linux/mfd/abx500/ab8500-bm.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
#define AB8500_USBCH_CTRL1_REG 0xC0
#define AB8500_USBCH_CTRL2_REG 0xC1
#define AB8500_USBCH_IPT_CRNTLVL_REG 0xC2
#define AB8540_USB_PP_MODE_REG 0xC5
#define AB8540_USB_PP_CHR_REG 0xC6

/*
* Gas Gauge register offsets
Expand Down Expand Up @@ -259,6 +261,16 @@ enum bup_vch_sel {
#define AB8505_RTC_PCUT_RESTART_REG 0x16
#define AB8505_RTC_PCUT_DEBOUNCE_REG 0x17

/* USB Power Path constants for ab8540 */
#define BUS_VSYS_VOL_SELECT_MASK 0x06
#define BUS_VSYS_VOL_SELECT_3P6V 0x00
#define BUS_VSYS_VOL_SELECT_3P325V 0x02
#define BUS_VSYS_VOL_SELECT_3P9V 0x04
#define BUS_VSYS_VOL_SELECT_4P3V 0x06
#define BUS_POWER_PATH_MODE_ENA 0x01
#define BUS_PP_PRECHG_CURRENT_MASK 0x0E
#define BUS_POWER_PATH_PRECHG_ENA 0x01

/**
* struct res_to_temp - defines one point in a temp to res curve. To
* be used in battery packs that combines the identification resistor with a
Expand Down
4 changes: 4 additions & 0 deletions trunk/include/linux/mfd/abx500/ux500_chargalg.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ struct ux500_charger_ops {
int (*check_enable) (struct ux500_charger *, int, int);
int (*kick_wd) (struct ux500_charger *);
int (*update_curr) (struct ux500_charger *, int);
int (*pp_enable) (struct ux500_charger *, bool);
int (*pre_chg_enable) (struct ux500_charger *, bool);
};

/**
Expand All @@ -30,6 +32,7 @@ struct ux500_charger_ops {
* @max_out_curr maximum output charger current in mA
* @enabled indicates if this charger is used or not
* @external external charger unit (pm2xxx)
* @power_path USB power path support
*/
struct ux500_charger {
struct power_supply psy;
Expand All @@ -39,6 +42,7 @@ struct ux500_charger {
int wdt_refresh;
bool enabled;
bool external;
bool power_path;
};

extern struct blocking_notifier_head charger_notifier_list;
Expand Down

0 comments on commit ff74a40

Please sign in to comment.