static void sec_bat_cable_work(struct work_struct *work) { struct sec_bat_info *info = container_of(work, struct sec_bat_info, cable_work); switch (info->cable_type) { case CABLE_TYPE_NONE: info->batt_full_status = BATT_NOT_FULL; info->recharging_status = false; info->charging_start_time = 0; info->charging_status = POWER_SUPPLY_STATUS_DISCHARGING; sec_bat_enable_charging(info, false); wake_lock_timeout(&info->vbus_wake_lock, HZ * 5); break; case CABLE_TYPE_USB: case CABLE_TYPE_AC: case CABLE_TYPE_DOCK: sec_bat_enable_charging(info, true); info->charging_status = POWER_SUPPLY_STATUS_CHARGING; wake_lock(&info->vbus_wake_lock); break; default: dev_err(info->dev, "%s: Invalid cable type\n", __func__); break;; } power_supply_changed(&info->psy_ac); power_supply_changed(&info->psy_usb); wake_unlock(&info->cable_wake_lock); }
static void sec_bat_cable_work(struct work_struct *work) { struct sec_bat_info *info = container_of(work, struct sec_bat_info, cable_work); switch (info->cable_type) { case CABLE_TYPE_NONE: info->batt_full_status = BATT_NOT_FULL; info->recharging_status = false; info->charging_start_time = 0; info->batt_temp_high_cnt = 0; info->batt_temp_low_cnt = 0; info->batt_temp_recover_cnt = 0; info->charging_status = POWER_SUPPLY_STATUS_DISCHARGING; sec_bat_enable_charging(info, false); if (info->batt_health == POWER_SUPPLY_HEALTH_OVERVOLTAGE) info->batt_health = POWER_SUPPLY_HEALTH_GOOD; wake_lock_timeout(&info->vbus_wake_lock, HZ * 2); break; case CABLE_TYPE_USB: info->charging_status = POWER_SUPPLY_STATUS_CHARGING; sec_bat_enable_charging(info, true); wake_lock(&info->vbus_wake_lock); break; case CABLE_TYPE_AC: case CABLE_TYPE_DOCK: info->charging_status = POWER_SUPPLY_STATUS_CHARGING; sec_bat_enable_charging(info, true); break; default: dev_err(info->dev, "%s: Invalid cable type\n", __func__); break;; } power_supply_changed(&info->psy_ac); power_supply_changed(&info->psy_usb); info->last_poll = alarm_get_elapsed_realtime(); sec_program_alarm(info, FAST_POLL); /* To notify framework layer, remaning 2 sec */ wake_lock_timeout(&info->cable_wake_lock, HZ * 2); }
static void sec_bat_handle_charger_topoff(struct sec_bat_info *info) { if (!sec_bat_enable_charging(info, false)) { info->charging_status = POWER_SUPPLY_STATUS_FULL; info->batt_full_status = BATT_FULL; info->recharging_status = false; dev_info(info->dev, "%s: Charging Top-off\n", __func__); } }
static int sec_bat_set_property(struct power_supply *ps, enum power_supply_property psp, const union power_supply_propval *val) { struct sec_bat_info *info = container_of(ps, struct sec_bat_info, psy_bat); struct power_supply *psy = power_supply_get_by_name(info->charger_name); union power_supply_propval value; if (!psy) { dev_err(info->dev, "%s: fail to get charger ps\n", __func__); return -ENODEV; } switch (psp) { case POWER_SUPPLY_PROP_STATUS: /* TODO: topoff interrupt: called by charger IC */ dev_info(info->dev, "%s: topoff intr\n", __func__); if (val->intval != POWER_SUPPLY_STATUS_FULL) return -EINVAL; if(info->charging_status != POWER_SUPPLY_STATUS_CHARGING && info->charging_status != POWER_SUPPLY_STATUS_FULL) { dev_info(info->dev, "%s: battery is not charging status(%d)\n", __func__, info->charging_status); return -EINVAL; } if(info->batt_soc < 90) { dev_info(info->dev, "%s: battery level(%d) is low! not full charged\n", __func__, info->batt_soc); return -EINVAL; } if (info->use_sub_charger) { info->batt_full_status = BATT_2ND_FULL; info->charging_status = POWER_SUPPLY_STATUS_FULL; info->recharging_status = false; /* disable charging */ sec_bat_enable_charging(info, 0); } else { if (info->batt_full_status == BATT_NOT_FULL) { info->batt_full_status = BATT_1ST_FULL; info->charging_status = POWER_SUPPLY_STATUS_FULL; /*set topoff current : 600mA *15%* = 90mA */ value.intval = MAX8907C_TOPOFF_10PERCENT; psy->set_property(psy, POWER_SUPPLY_PROP_CHARGE_FULL, &value); /* re-enable charging */ sec_bat_re_enable_charging_main(info); } else { info->batt_full_status = BATT_2ND_FULL; info->recharging_status = false; /* disable charging */ sec_bat_enable_charging(info, 0); } } dev_info(info->dev, "%s: battery is full charged\n", __func__); break; case POWER_SUPPLY_PROP_CAPACITY_LEVEL: /* TODO: lowbatt interrupt: called by fuel gauge */ dev_info(info->dev, "%s: lowbatt intr\n", __func__); if (val->intval != POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL) return -EINVAL; wake_lock(&info->monitor_wake_lock); queue_work(info->monitor_wqueue, &info->monitor_work); break; case POWER_SUPPLY_PROP_ONLINE: /* cable is attached or detached. called by USB switch(MUIC) */ dev_info(info->dev, "%s: cable was changed(%d)\n", __func__, val->intval); switch (val->intval) { case POWER_SUPPLY_TYPE_BATTERY: info->cable_type = CABLE_TYPE_NONE; break; case POWER_SUPPLY_TYPE_MAINS: info->cable_type = CABLE_TYPE_AC; break; case POWER_SUPPLY_TYPE_USB: info->cable_type = CABLE_TYPE_USB; break; case POWER_SUPPLY_TYPE_DOCK: info->cable_type = CABLE_TYPE_DOCK; break; default: return -EINVAL; } wake_lock(&info->cable_wake_lock); queue_work(info->monitor_wqueue, &info->cable_work); break; case POWER_SUPPLY_PROP_HEALTH: if (val->intval != POWER_SUPPLY_HEALTH_OVERVOLTAGE && val->intval != POWER_SUPPLY_HEALTH_GOOD) return -EINVAL; info->batt_health = val->intval; break; default: return -EINVAL; } return 0; }