Loading drivers/power/smb135x-charger.c +112 −51 Original line number Diff line number Diff line Loading @@ -200,6 +200,11 @@ #define IRQ_D_TIMEOUT_BIT BIT(2) #define IRQ_E_REG 0x54 #define IRQ_E_DC_OV_BIT BIT(6) #define IRQ_E_DC_UV_BIT BIT(4) #define IRQ_E_USB_OV_BIT BIT(2) #define IRQ_E_USB_UV_BIT BIT(0) #define IRQ_F_REG 0x55 #define IRQ_F_POWER_OK_BIT BIT(0) Loading Loading @@ -237,6 +242,7 @@ struct smb135x_chg { bool usb_present; bool dc_present; bool dc_ov; bool bmd_algo_disabled; bool iterm_disabled; Loading Loading @@ -375,34 +381,6 @@ static bool is_usb100_broken(struct smb135x_chg *chip) return !!(reg & CHECK_USB100_GOOD_BIT); } static bool is_dc_present(struct smb135x_chg *chip) { int rc; u8 reg; rc = smb135x_read(chip, STATUS_8_REG, ®); if (rc < 0) { dev_err(chip->dev, "Couldn't read status 5 rc = %d\n", rc); return false; } return !!(reg & (DCIN_9V | DCIN_UNREG | DCIN_LV)); } static bool is_usb_present(struct smb135x_chg *chip) { int rc; u8 reg; rc = smb135x_read(chip, STATUS_8_REG, ®); if (rc < 0) { dev_err(chip->dev, "Couldn't read status 5 rc = %d\n", rc); return false; } return !!(reg & (USBIN_9V | USBIN_UNREG | USBIN_LV)); } static char *usb_type_str[] = { "ACA_DOCK", /* bit 0 */ "ACA_C", /* bit 1 */ Loading Loading @@ -925,6 +903,7 @@ static int smb135x_battery_get_property(struct power_supply *psy, static enum power_supply_property smb135x_dc_properties[] = { POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_HEALTH, }; static int smb135x_dc_get_property(struct power_supply *psy, Loading @@ -936,8 +915,10 @@ static int smb135x_dc_get_property(struct power_supply *psy, switch (prop) { case POWER_SUPPLY_PROP_ONLINE: /* return if dc is charging the battery */ val->intval = is_dc_present(chip); val->intval = chip->dc_present; break; case POWER_SUPPLY_PROP_HEALTH: val->intval = chip->dc_present; break; default: return -EINVAL; Loading Loading @@ -1210,15 +1191,42 @@ static int power_ok_handler(struct smb135x_chg *chip, u8 rt_stat) return 0; } static int handle_dc_removal(struct smb135x_chg *chip) { if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIRELESS) { cancel_delayed_work_sync(&chip->wireless_insertion_work); smb135x_dc_suspend(chip, true); } if (chip->dc_psy_type != -EINVAL) power_supply_set_online(&chip->dc_psy, chip->dc_present); return 0; } #define DCIN_UNSUSPEND_DELAY_MS 1000 static int handle_dc_insertion(struct smb135x_chg *chip) { if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIRELESS) schedule_delayed_work(&chip->wireless_insertion_work, msecs_to_jiffies(DCIN_UNSUSPEND_DELAY_MS)); if (chip->dc_psy_type != -EINVAL) power_supply_set_online(&chip->dc_psy, chip->dc_present); return 0; } /** * dcin_uv_handler() - called when the dc voltage crosses the uv threshold * @chip: pointer to smb135x_chg chip * @rt_stat: the status bit indicating whether dc voltage is uv */ #define DCIN_UNSUSPEND_DELAY_MS 1000 static int dcin_uv_handler(struct smb135x_chg *chip, u8 rt_stat) { bool dc_present = is_dc_present(chip); /* * rt_stat indicates if dc is undervolted. If so dc_present * should be marked removed */ bool dc_present = !rt_stat; pr_debug("chip->dc_present = %d dc_present = %d\n", chip->dc_present, dc_present); Loading @@ -1226,30 +1234,45 @@ static int dcin_uv_handler(struct smb135x_chg *chip, u8 rt_stat) if (chip->dc_present && !dc_present) { /* dc removed */ chip->dc_present = dc_present; if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIRELESS) { cancel_delayed_work_sync( &chip->wireless_insertion_work); smb135x_dc_suspend(chip, true); } if (chip->dc_psy_type != -EINVAL) power_supply_set_online(&chip->dc_psy, chip->dc_present); handle_dc_removal(chip); } if (!chip->dc_present && dc_present) { /* dc inserted */ chip->dc_present = dc_present; if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIRELESS) schedule_delayed_work(&chip->wireless_insertion_work, msecs_to_jiffies(DCIN_UNSUSPEND_DELAY_MS)); if (chip->dc_psy_type != -EINVAL) power_supply_set_online(&chip->dc_psy, chip->dc_present); handle_dc_insertion(chip); } return 0; } static int dcin_ov_handler(struct smb135x_chg *chip, u8 rt_stat) { /* * rt_stat indicates if dc is overvolted. If so dc_present * should be marked removed */ bool dc_present = !rt_stat; pr_debug("chip->dc_present = %d dc_present = %d\n", chip->dc_present, dc_present); chip->dc_ov = !!rt_stat; if (chip->dc_present && !dc_present) { /* dc removed */ chip->dc_present = dc_present; handle_dc_removal(chip); } if (!chip->dc_present && dc_present) { /* dc inserted */ chip->dc_present = dc_present; handle_dc_insertion(chip); } return 0; } static int handle_usb_removal(struct smb135x_chg *chip) { if (chip->usb_psy) { Loading Loading @@ -1304,7 +1327,11 @@ static int handle_usb_insertion(struct smb135x_chg *chip) */ static int usbin_uv_handler(struct smb135x_chg *chip, u8 rt_stat) { bool usb_present = is_usb_present(chip); /* * rt_stat indicates if usb is undervolted. If so usb_present * should be marked removed */ bool usb_present = !rt_stat; pr_debug("chip->usb_present = %d usb_present = %d\n", chip->usb_present, usb_present); Loading @@ -1316,15 +1343,41 @@ static int usbin_uv_handler(struct smb135x_chg *chip, u8 rt_stat) return 0; } static int usbin_ov_handler(struct smb135x_chg *chip, u8 rt_stat) { /* * rt_stat indicates if usb is overvolted. If so usb_present * should be marked removed */ bool usb_present = !rt_stat; int health; pr_debug("chip->usb_present = %d usb_present = %d\n", chip->usb_present, usb_present); if (chip->usb_present && !usb_present) { /* USB removed */ chip->usb_present = usb_present; handle_usb_removal(chip); } if (chip->usb_psy) { health = rt_stat ? POWER_SUPPLY_HEALTH_OVERVOLTAGE : POWER_SUPPLY_HEALTH_GOOD; power_supply_set_health_state(chip->usb_psy, health); } return 0; } /** * src_detect_handler() - this is called when USB charger type is detected, use * it for handling USB charger insertion * it for handling USB charger insertion/removal * @chip: pointer to smb135x_chg chip * @rt_stat: the status bit indicating chg insertion/removal */ static int src_detect_handler(struct smb135x_chg *chip, u8 rt_stat) { bool usb_present = is_usb_present(chip); bool usb_present = !!rt_stat; pr_debug("chip->usb_present = %d usb_present = %d\n", chip->usb_present, usb_present); Loading Loading @@ -1455,6 +1508,7 @@ static struct irq_handler_info handlers[] = { }, { .name = "usbin_ov", .smb_irq = usbin_ov_handler, }, { .name = "dcin_uv", Loading @@ -1462,6 +1516,7 @@ static struct irq_handler_info handlers[] = { }, { .name = "dcin_ov", .smb_irq = dcin_ov_handler, }, }, }, Loading Loading @@ -1877,8 +1932,14 @@ static int determine_initial_status(struct smb135x_chg *chip) if (reg & IRQ_C_TERM_BIT) chip->chg_done_batt_full = true; chip->usb_present = is_usb_present(chip); chip->dc_present = is_dc_present(chip); rc = smb135x_read(chip, IRQ_E_REG, ®); if (rc < 0) { dev_err(chip->dev, "Couldn't read irq E rc = %d\n", rc); return rc; } chip->usb_present = !(reg & IRQ_E_USB_OV_BIT) && !(reg & IRQ_E_USB_UV_BIT); chip->dc_present = !(reg & IRQ_E_DC_OV_BIT) && !(reg & IRQ_E_DC_UV_BIT); if (chip->usb_present) handle_usb_insertion(chip); Loading Loading
drivers/power/smb135x-charger.c +112 −51 Original line number Diff line number Diff line Loading @@ -200,6 +200,11 @@ #define IRQ_D_TIMEOUT_BIT BIT(2) #define IRQ_E_REG 0x54 #define IRQ_E_DC_OV_BIT BIT(6) #define IRQ_E_DC_UV_BIT BIT(4) #define IRQ_E_USB_OV_BIT BIT(2) #define IRQ_E_USB_UV_BIT BIT(0) #define IRQ_F_REG 0x55 #define IRQ_F_POWER_OK_BIT BIT(0) Loading Loading @@ -237,6 +242,7 @@ struct smb135x_chg { bool usb_present; bool dc_present; bool dc_ov; bool bmd_algo_disabled; bool iterm_disabled; Loading Loading @@ -375,34 +381,6 @@ static bool is_usb100_broken(struct smb135x_chg *chip) return !!(reg & CHECK_USB100_GOOD_BIT); } static bool is_dc_present(struct smb135x_chg *chip) { int rc; u8 reg; rc = smb135x_read(chip, STATUS_8_REG, ®); if (rc < 0) { dev_err(chip->dev, "Couldn't read status 5 rc = %d\n", rc); return false; } return !!(reg & (DCIN_9V | DCIN_UNREG | DCIN_LV)); } static bool is_usb_present(struct smb135x_chg *chip) { int rc; u8 reg; rc = smb135x_read(chip, STATUS_8_REG, ®); if (rc < 0) { dev_err(chip->dev, "Couldn't read status 5 rc = %d\n", rc); return false; } return !!(reg & (USBIN_9V | USBIN_UNREG | USBIN_LV)); } static char *usb_type_str[] = { "ACA_DOCK", /* bit 0 */ "ACA_C", /* bit 1 */ Loading Loading @@ -925,6 +903,7 @@ static int smb135x_battery_get_property(struct power_supply *psy, static enum power_supply_property smb135x_dc_properties[] = { POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_HEALTH, }; static int smb135x_dc_get_property(struct power_supply *psy, Loading @@ -936,8 +915,10 @@ static int smb135x_dc_get_property(struct power_supply *psy, switch (prop) { case POWER_SUPPLY_PROP_ONLINE: /* return if dc is charging the battery */ val->intval = is_dc_present(chip); val->intval = chip->dc_present; break; case POWER_SUPPLY_PROP_HEALTH: val->intval = chip->dc_present; break; default: return -EINVAL; Loading Loading @@ -1210,15 +1191,42 @@ static int power_ok_handler(struct smb135x_chg *chip, u8 rt_stat) return 0; } static int handle_dc_removal(struct smb135x_chg *chip) { if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIRELESS) { cancel_delayed_work_sync(&chip->wireless_insertion_work); smb135x_dc_suspend(chip, true); } if (chip->dc_psy_type != -EINVAL) power_supply_set_online(&chip->dc_psy, chip->dc_present); return 0; } #define DCIN_UNSUSPEND_DELAY_MS 1000 static int handle_dc_insertion(struct smb135x_chg *chip) { if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIRELESS) schedule_delayed_work(&chip->wireless_insertion_work, msecs_to_jiffies(DCIN_UNSUSPEND_DELAY_MS)); if (chip->dc_psy_type != -EINVAL) power_supply_set_online(&chip->dc_psy, chip->dc_present); return 0; } /** * dcin_uv_handler() - called when the dc voltage crosses the uv threshold * @chip: pointer to smb135x_chg chip * @rt_stat: the status bit indicating whether dc voltage is uv */ #define DCIN_UNSUSPEND_DELAY_MS 1000 static int dcin_uv_handler(struct smb135x_chg *chip, u8 rt_stat) { bool dc_present = is_dc_present(chip); /* * rt_stat indicates if dc is undervolted. If so dc_present * should be marked removed */ bool dc_present = !rt_stat; pr_debug("chip->dc_present = %d dc_present = %d\n", chip->dc_present, dc_present); Loading @@ -1226,30 +1234,45 @@ static int dcin_uv_handler(struct smb135x_chg *chip, u8 rt_stat) if (chip->dc_present && !dc_present) { /* dc removed */ chip->dc_present = dc_present; if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIRELESS) { cancel_delayed_work_sync( &chip->wireless_insertion_work); smb135x_dc_suspend(chip, true); } if (chip->dc_psy_type != -EINVAL) power_supply_set_online(&chip->dc_psy, chip->dc_present); handle_dc_removal(chip); } if (!chip->dc_present && dc_present) { /* dc inserted */ chip->dc_present = dc_present; if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIRELESS) schedule_delayed_work(&chip->wireless_insertion_work, msecs_to_jiffies(DCIN_UNSUSPEND_DELAY_MS)); if (chip->dc_psy_type != -EINVAL) power_supply_set_online(&chip->dc_psy, chip->dc_present); handle_dc_insertion(chip); } return 0; } static int dcin_ov_handler(struct smb135x_chg *chip, u8 rt_stat) { /* * rt_stat indicates if dc is overvolted. If so dc_present * should be marked removed */ bool dc_present = !rt_stat; pr_debug("chip->dc_present = %d dc_present = %d\n", chip->dc_present, dc_present); chip->dc_ov = !!rt_stat; if (chip->dc_present && !dc_present) { /* dc removed */ chip->dc_present = dc_present; handle_dc_removal(chip); } if (!chip->dc_present && dc_present) { /* dc inserted */ chip->dc_present = dc_present; handle_dc_insertion(chip); } return 0; } static int handle_usb_removal(struct smb135x_chg *chip) { if (chip->usb_psy) { Loading Loading @@ -1304,7 +1327,11 @@ static int handle_usb_insertion(struct smb135x_chg *chip) */ static int usbin_uv_handler(struct smb135x_chg *chip, u8 rt_stat) { bool usb_present = is_usb_present(chip); /* * rt_stat indicates if usb is undervolted. If so usb_present * should be marked removed */ bool usb_present = !rt_stat; pr_debug("chip->usb_present = %d usb_present = %d\n", chip->usb_present, usb_present); Loading @@ -1316,15 +1343,41 @@ static int usbin_uv_handler(struct smb135x_chg *chip, u8 rt_stat) return 0; } static int usbin_ov_handler(struct smb135x_chg *chip, u8 rt_stat) { /* * rt_stat indicates if usb is overvolted. If so usb_present * should be marked removed */ bool usb_present = !rt_stat; int health; pr_debug("chip->usb_present = %d usb_present = %d\n", chip->usb_present, usb_present); if (chip->usb_present && !usb_present) { /* USB removed */ chip->usb_present = usb_present; handle_usb_removal(chip); } if (chip->usb_psy) { health = rt_stat ? POWER_SUPPLY_HEALTH_OVERVOLTAGE : POWER_SUPPLY_HEALTH_GOOD; power_supply_set_health_state(chip->usb_psy, health); } return 0; } /** * src_detect_handler() - this is called when USB charger type is detected, use * it for handling USB charger insertion * it for handling USB charger insertion/removal * @chip: pointer to smb135x_chg chip * @rt_stat: the status bit indicating chg insertion/removal */ static int src_detect_handler(struct smb135x_chg *chip, u8 rt_stat) { bool usb_present = is_usb_present(chip); bool usb_present = !!rt_stat; pr_debug("chip->usb_present = %d usb_present = %d\n", chip->usb_present, usb_present); Loading Loading @@ -1455,6 +1508,7 @@ static struct irq_handler_info handlers[] = { }, { .name = "usbin_ov", .smb_irq = usbin_ov_handler, }, { .name = "dcin_uv", Loading @@ -1462,6 +1516,7 @@ static struct irq_handler_info handlers[] = { }, { .name = "dcin_ov", .smb_irq = dcin_ov_handler, }, }, }, Loading Loading @@ -1877,8 +1932,14 @@ static int determine_initial_status(struct smb135x_chg *chip) if (reg & IRQ_C_TERM_BIT) chip->chg_done_batt_full = true; chip->usb_present = is_usb_present(chip); chip->dc_present = is_dc_present(chip); rc = smb135x_read(chip, IRQ_E_REG, ®); if (rc < 0) { dev_err(chip->dev, "Couldn't read irq E rc = %d\n", rc); return rc; } chip->usb_present = !(reg & IRQ_E_USB_OV_BIT) && !(reg & IRQ_E_USB_UV_BIT); chip->dc_present = !(reg & IRQ_E_DC_OV_BIT) && !(reg & IRQ_E_DC_UV_BIT); if (chip->usb_present) handle_usb_insertion(chip); Loading