@@ -90,6 +90,8 @@
#define CHARGER_STATUS_POLL 10 /* in ms */
+#define CHG_WD_INTERVAL (60 * HZ)
+
/* UsbLineStatus register - usb types */
enum ab8500_charger_link_status {
USB_STAT_NOT_CONFIGURED,
@@ -2945,7 +2947,9 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
ARRAY_SIZE(ab8500_charger_voltage_map) - 1];
di->ac_chg.max_out_curr = ab8500_charger_current_map[
ARRAY_SIZE(ab8500_charger_current_map) - 1];
+ di->ac_chg.wdt_refresh = CHG_WD_INTERVAL;
di->ac_chg.enabled = di->pdata->ac_enabled;
+ di->ac_chg.external = false;
/* USB supply */
/* power_supply base class */
@@ -2964,7 +2968,9 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
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->pdata->usb_enabled;
+ di->usb_chg.external = false;
/* Create a work queue for the charger */
di->charger_wq =
@@ -453,8 +453,18 @@ static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di)
{
/* Check if charger exists and kick watchdog if charging */
if (di->ac_chg && di->ac_chg->ops.kick_wd &&
- di->chg_info.online_chg & AC_CHG)
+ di->chg_info.online_chg & AC_CHG) {
+ /*
+ * If AB charger watchdog expired, pm2xxx charging
+ * gets disabled. To be safe, kick both AB charger watchdog
+ * and pm2xxx watchdog.
+ */
+ if (di->ac_chg->external &&
+ di->usb_chg && di->usb_chg->ops.kick_wd)
+ di->usb_chg->ops.kick_wd(di->usb_chg);
+
return di->ac_chg->ops.kick_wd(di->ac_chg);
+ }
else if (di->usb_chg && di->usb_chg->ops.kick_wd &&
di->chg_info.online_chg & USB_CHG)
return di->usb_chg->ops.kick_wd(di->usb_chg);
@@ -1591,6 +1601,8 @@ static void abx500_chargalg_periodic_work(struct work_struct *work)
static void abx500_chargalg_wd_work(struct work_struct *work)
{
int ret;
+ int refresh_time;
+
struct abx500_chargalg *di = container_of(work,
struct abx500_chargalg, chargalg_wd_work.work);
@@ -1600,8 +1612,15 @@ static void abx500_chargalg_wd_work(struct work_struct *work)
if (ret < 0)
dev_err(di->dev, "failed to kick watchdog\n");
+ if (di->chg_info.online_chg & AC_CHG)
+ refresh_time = di->ac_chg->wdt_refresh;
+ else if (di->chg_info.online_chg & USB_CHG)
+ refresh_time = di->usb_chg->wdt_refresh;
+ else
+ refresh_time = CHG_WD_INTERVAL;
+
queue_delayed_work(di->chargalg_wq,
- &di->chargalg_wd_work, CHG_WD_INTERVAL);
+ &di->chargalg_wd_work, refresh_time);
}
/**
@@ -28,13 +28,16 @@ struct ux500_charger_ops {
* @max_out_volt maximum output charger voltage in mV
* @max_out_curr maximum output charger current in mA
* @enabled indicates if this charger is used or not
+ * @external external charger unit (pm2xxx)
*/
struct ux500_charger {
struct power_supply psy;
struct ux500_charger_ops ops;
int max_out_volt;
int max_out_curr;
+ int wdt_refresh;
bool enabled;
+ bool external;
};
#endif