Beispiel #1
0
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);
}
Beispiel #3
0
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;
}