#define CFG_FAULT_IRQ_DCIN_UV BIT(2)
#define CFG_FAULT_IRQ_OTG_UV BIT(5)
#define CFG_STATUS_IRQ 0x0d
+#define CFG_STATUS_IRQ_CHARGE_TIMEOUT BIT(7)
#define CFG_STATUS_IRQ_TERMINATION_OR_TAPER BIT(4)
#define CFG_ADDRESS 0x0e
#define IRQSTAT_C_TERMINATION_STAT BIT(0)
#define IRQSTAT_C_TERMINATION_IRQ BIT(1)
#define IRQSTAT_C_TAPER_IRQ BIT(3)
+#define IRQSTAT_D 0x38
+#define IRQSTAT_D_CHARGE_TIMEOUT_STAT BIT(2)
+#define IRQSTAT_D_CHARGE_TIMEOUT_IRQ BIT(3)
#define IRQSTAT_E 0x39
#define IRQSTAT_E_USBIN_UV_STAT BIT(0)
#define IRQSTAT_E_USBIN_UV_IRQ BIT(1)
#define STAT_B 0x3c
#define STAT_C 0x3d
#define STAT_C_CHG_ENABLED BIT(0)
+#define STAT_C_HOLDOFF_STAT BIT(3)
#define STAT_C_CHG_MASK 0x06
#define STAT_C_CHG_SHIFT 1
+#define STAT_C_CHG_TERM BIT(5)
#define STAT_C_CHARGER_ERROR BIT(6)
#define STAT_E 0x3f
static irqreturn_t smb347_interrupt(int irq, void *data)
{
struct smb347_charger *smb = data;
- int stat_c, irqstat_e, irqstat_c, irqstat_f;
+ int stat_c, irqstat_c, irqstat_d, irqstat_e, irqstat_f;
irqreturn_t ret = IRQ_NONE;
stat_c = smb347_read(smb, STAT_C);
return IRQ_NONE;
}
+ irqstat_d = smb347_read(smb, IRQSTAT_D);
+ if (irqstat_d < 0) {
+ dev_warn(&smb->client->dev, "reading IRQSTAT_D failed\n");
+ return IRQ_NONE;
+ }
+
irqstat_e = smb347_read(smb, IRQSTAT_E);
if (irqstat_e < 0) {
dev_warn(&smb->client->dev, "reading IRQSTAT_E failed\n");
}
/*
- * If we get charger error we report the error back to user and
- * disable charging.
+ * If we get charger error we report the error back to user.
+ * If the error is recovered charging will resume again.
*/
if (stat_c & STAT_C_CHARGER_ERROR) {
dev_err(&smb->client->dev,
- "error in charger, disabling charging\n");
+ "charging stopped due to charger error\n");
- smb347_charging_disable(smb);
if (smb->pdata->show_battery)
power_supply_changed(&smb->battery);
}
/*
+ * If we got a complete charger timeout int that means the charge
+ * full is not detected with in charge timeout value.
+ */
+ if (irqstat_d & IRQSTAT_D_CHARGE_TIMEOUT_IRQ) {
+ dev_info(&smb->client->dev,
+ "[Charge Timeout]:Total Charge Timeout INT recieved\n");
+ if (irqstat_d & IRQSTAT_D_CHARGE_TIMEOUT_STAT)
+ dev_info(&smb->client->dev,
+ "[Charge Timeout]:charging stopped\n");
+ if (smb->pdata->show_battery)
+ power_supply_changed(&smb->battery);
+ ret = IRQ_HANDLED;
+ }
+
+ /*
* If we got an under voltage interrupt it means that AC/USB input
* was connected or disconnected.
*/
if (ret < 0)
goto fail;
- ret = smb347_write(smb, CFG_STATUS_IRQ,
- CFG_STATUS_IRQ_TERMINATION_OR_TAPER);
+ val = CFG_STATUS_IRQ_CHARGE_TIMEOUT |
+ CFG_STATUS_IRQ_TERMINATION_OR_TAPER;
+ ret = smb347_write(smb, CFG_STATUS_IRQ, val);
if (ret < 0)
goto fail;
int smb347_get_charging_status(void)
{
+ int ret, status;
+
if (!smb347_dev)
return -EINVAL;
if (!smb347_is_online(smb347_dev))
return POWER_SUPPLY_STATUS_DISCHARGING;
- if (smb347_charging_status(smb347_dev))
- return POWER_SUPPLY_STATUS_CHARGING;
- else
- return POWER_SUPPLY_STATUS_FULL;
+ ret = smb347_read(smb347_dev, STAT_C);
+ if (ret < 0)
+ return ret;
+
+ dev_info(&smb347_dev->client->dev,
+ "Charging Status: STAT_C:0x%x\n", ret);
+
+ if ((ret & STAT_C_CHARGER_ERROR) ||
+ (ret & STAT_C_HOLDOFF_STAT)) {
+ /* set to NOT CHARGING upon charger error
+ * or charging has stopped.
+ */
+ status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ if ((ret & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT) {
+ /* set to charging if battery is in pre-charge,
+ * fast charge or taper charging mode.
+ */
+ status = POWER_SUPPLY_STATUS_CHARGING;
+ } else if (ret & STAT_C_CHG_TERM) {
+ /* set the status to FULL if battery is not in pre
+ * charge, fast charge or taper charging mode AND
+ * charging is terminated at least once.
+ */
+ status = POWER_SUPPLY_STATUS_FULL;
+ } else {
+ /* in this case no charger error or termination
+ * occured but charging is not in progress!!!
+ */
+ status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ }
+ }
+ return status;
}
-EXPORT_SYMBOL_GPL(smb347_usb_get_property);
+EXPORT_SYMBOL_GPL(smb347_get_charging_status);
static enum power_supply_property smb347_usb_properties[] = {
POWER_SUPPLY_PROP_ONLINE,
switch (prop) {
case POWER_SUPPLY_PROP_STATUS:
- if (!smb347_is_online(smb)) {
- val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
- break;
- }
- if (smb347_charging_status(smb))
- val->intval = POWER_SUPPLY_STATUS_CHARGING;
- else
- val->intval = POWER_SUPPLY_STATUS_FULL;
+ ret = smb347_get_charging_status();
+ if (ret < 0)
+ return ret;
+ val->intval = ret;
break;
case POWER_SUPPLY_PROP_CHARGE_TYPE: