コード例 #1
0
static bool bln_timeout_expired(void)
{
	if (bln_notification_timeout && _ktime_compare(alarm_get_elapsed_realtime(), bln_end_time) >= 0) {
		printk("bln: ending by timeout\n");
		bln_on = false;
		return true;
	}
  DEBUG_LOG("remain: %lldns", ktime_sub(bln_end_time, alarm_get_elapsed_realtime()).tv64);
	return false;
}
コード例 #2
0
static ssize_t pm8xxx_led_off_timer_store(struct device *dev,
				   struct device_attribute *attr,
				   const char *buf, size_t count)
{
	struct led_classdev *led_cdev;
	struct pm8xxx_led_data *ldata;
	int min, sec;
	uint16_t off_timer;
	ktime_t interval;
	ktime_t next_alarm;

	min = -1;
	sec = -1;
	sscanf(buf, "%d %d", &min, &sec);

	if (min < 0 || min > 255)
		return -EINVAL;
	if (sec < 0 || sec > 255)
		return -EINVAL;
	led_cdev = (struct led_classdev *) dev_get_drvdata(dev);
	ldata = container_of(led_cdev, struct pm8xxx_led_data, cdev);

	LED_INFO("Setting %s off_timer to %d min %d sec \n", led_cdev->name, min, sec);
	off_timer = min * 60 + sec;

	alarm_cancel(&ldata->led_alarm);
	cancel_work_sync(&ldata->led_work);
	if (off_timer) {
		interval = ktime_set(off_timer, 0);
		next_alarm = ktime_add(alarm_get_elapsed_realtime(), interval);
		alarm_start_range(&ldata->led_alarm, next_alarm, next_alarm);
	}
	return count;
}
コード例 #3
0
static void s3c_bat_work(struct work_struct *work)
{
	struct chg_data *chg =
		container_of(work, struct chg_data, bat_work);
	int ret;
	struct timespec ts;
	unsigned long flags;
	mutex_lock(&chg->mutex);

	s3c_bat_discharge_reason(chg);

	ret = s3c_cable_status_update(chg);
	if (ret < 0)
		goto err;

	mutex_unlock(&chg->mutex);

	power_supply_changed(&chg->psy_bat);

	chg->last_poll = alarm_get_elapsed_realtime();
	ts = ktime_to_timespec(chg->last_poll);
	chg->timestamp = ts.tv_sec;

	/* prevent suspend before starting the alarm */
	local_irq_save(flags);
	wake_unlock(&chg->work_wake_lock);
	s3c_program_alarm(chg, FAST_POLL);
	local_irq_restore(flags);
	return;
err:
	mutex_unlock(&chg->mutex);
	wake_unlock(&chg->work_wake_lock);
	pr_err("battery workqueue fail\n");
}
コード例 #4
0
static void bln_init_timeout(void)
{
	if (bln_enabled && bln_notification_timeout && !bln_ongoing) {
		DEBUG_LOG("seconds: %u, bln_on: %d", bln_notification_timeout, bln_on);
		bln_end_time = ktime_add(alarm_get_elapsed_realtime(), ktime_set(bln_notification_timeout * 60, 0));
	} else
    DEBUG_LOG("bailing: enabled: %d, timeout: %d, ongoing: %d", bln_enabled, bln_notification_timeout, bln_ongoing);
}
コード例 #5
0
ファイル: msm_thermal.c プロジェクト: sparkmbox/singh-kernel
static void thermal_rtc_callback(struct alarm *al)
{
	struct timeval ts;
	ts = ktime_to_timeval(alarm_get_elapsed_realtime());
	schedule_work(&timer_work);
	pr_debug("%s: Time on alarm expiry: %ld %ld\n", KBUILD_MODNAME,
			ts.tv_sec, ts.tv_usec);
}
コード例 #6
0
static void set_alarm(struct max77665_charger *chg, int seconds)
{
	ktime_t interval = ktime_set(seconds, 0);
	ktime_t now = alarm_get_elapsed_realtime();
	ktime_t next = ktime_add(now, interval);

	pr_info("set alarm after %d seconds\n", seconds);
	alarm_start_range(&chg->alarm, next, next);
}
コード例 #7
0
static void tps65200_set_check_alarm(void)
{
	ktime_t interval;
	ktime_t next_alarm;

	interval = ktime_set(TPS65200_CHECK_INTERVAL, 0);
	next_alarm = ktime_add(alarm_get_elapsed_realtime(), interval);
	alarm_start_range(&tps65200_check_alarm, next_alarm, next_alarm);
}
コード例 #8
0
ファイル: wake_timeout.c プロジェクト: talnoah/N5-kernel
static void wakefunc_rtc_callback(struct alarm *al)
{
	struct timeval ts;
	ts = ktime_to_timeval(alarm_get_elapsed_realtime());

	wake_pwrtrigger();
	
	pr_debug("%s: Time of alarm expiry: %ld\n", WAKEFUNC,
			ts.tv_sec);
}
コード例 #9
0
static void s3c_bat_discharge_reason(struct chg_data *chg)
{
	int discharge_reason;
	ktime_t ktime;
	struct timespec cur_time;

	discharge_reason = chg->bat_info.dis_reason & 0xf;
	if(chg->bat_info.batt_percentage >= 100)
	{
		chg->set_batt_full = 1;
		chg->bat_info.batt_is_full = true;
	}
	if (discharge_reason & DISCONNECT_BAT_FULL &&
			/*chg->bat_info.batt_vcell < RECHARGE_COND_VOLTAGE*/			
			chg->bat_info.batt_percentage < 100)
		chg->bat_info.dis_reason &= ~DISCONNECT_BAT_FULL;

	if (discharge_reason & DISCONNECT_TEMP_OVERHEAT &&
			chg->bat_info.batt_temp <=
			HIGH_RECOVER_TEMP)
		chg->bat_info.dis_reason &= ~DISCONNECT_TEMP_OVERHEAT;

	if (discharge_reason & DISCONNECT_TEMP_FREEZE &&
			chg->bat_info.batt_temp >=
			LOW_RECOVER_TEMP)
		chg->bat_info.dis_reason &= ~DISCONNECT_TEMP_FREEZE;

	if (discharge_reason & DISCONNECT_OVER_TIME &&
			/*chg->bat_info.batt_vcell < RECHARGE_COND_VOLTAGE*/
			chg->bat_info.batt_percentage < 100)
		chg->bat_info.dis_reason &= ~DISCONNECT_OVER_TIME;

	if (chg->set_batt_full)
		chg->bat_info.dis_reason |= DISCONNECT_BAT_FULL;

	if (chg->bat_info.batt_health != POWER_SUPPLY_HEALTH_GOOD)
		chg->bat_info.dis_reason |= chg->bat_info.batt_health ==
			POWER_SUPPLY_HEALTH_OVERHEAT ?
			DISCONNECT_TEMP_OVERHEAT : DISCONNECT_TEMP_FREEZE;

	ktime = alarm_get_elapsed_realtime();
	cur_time = ktime_to_timespec(ktime);

	if (chg->discharging_time &&
			cur_time.tv_sec > chg->discharging_time) {
		chg->set_charge_timeout = true;
		chg->bat_info.dis_reason |= DISCONNECT_OVER_TIME;
	}

	pr_debug("%s : Current charge level : %d%%\n\
Current time : %ld  discharging_time : %ld\n\
discharging reason : %d\n",\
		__func__, chg->bat_info.batt_percentage, cur_time.tv_sec,
		chg->discharging_time, chg->bat_info.dis_reason);
}
コード例 #10
0
static int instinctq_battery_prepare(struct device *dev)
{
	struct instinctq_battery *bat = dev_get_drvdata(dev);
	ktime_t now, start, end;
#ifdef CONFIG_RTC_INTF_ALARM
	now = alarm_get_elapsed_realtime();
	start = ktime_set(SUSPEND_INTERVAL - 10, 0);
	start = ktime_add(now, start);
	end = ktime_set(SUSPEND_INTERVAL + 10, 0);
	end = ktime_add(now, end);
	alarm_start_range(&bat->alarm, start, end);
#endif
	return 0;
}
コード例 #11
0
static void sec_set_time_for_charging(struct sec_bat_info *info, int mode)
{
	if (mode) {
		ktime_t ktime;
		struct timespec cur_time;

		ktime = alarm_get_elapsed_realtime();
		cur_time = ktime_to_timespec(ktime);

		/* record start time for abs timer */
		info->charging_start_time = cur_time.tv_sec;
	} else {
		/* initialize start time for abs timer */
		info->charging_start_time = 0;
	}
}
コード例 #12
0
static void p3_set_time_for_charging(struct battery_data *battery, int mode)
{
	if (mode) {
		ktime_t ktime;
		struct timespec cur_time;

		ktime = alarm_get_elapsed_realtime();
		cur_time = ktime_to_timespec(ktime);

		/* record start time for abs timer */
		battery->charging_start_time = cur_time.tv_sec;
	} else {
		/* initialize start time for abs timer */
		battery->charging_start_time = 0;
	}
}
コード例 #13
0
static void p3_bat_work(struct work_struct *work)
{
	struct battery_data *battery =
		container_of(work, struct battery_data, battery_work);
	unsigned long flags;

	pr_debug("bat work ");
	p3_bat_status_update(&battery->psy_battery);
	battery->last_poll = alarm_get_elapsed_realtime();

	/* prevent suspend before starting the alarm */
	local_irq_save(flags);
	wake_unlock(&battery->work_wake_lock);
	p3_program_alarm(battery, FAST_POLL);
	local_irq_restore(flags);
}
コード例 #14
0
static int sec_is_over_abs_time(struct sec_bat_info *info, unsigned int abs_time)
{
	ktime_t ktime;
	struct timespec cur_time;

	if (!info->charging_start_time)
		return 0;

	ktime = alarm_get_elapsed_realtime();
	cur_time = ktime_to_timespec(ktime);

	if (info->charging_start_time + abs_time < cur_time.tv_sec) {
		pr_info("Charging time out");
		return 1;
	} else
		return 0;
}
コード例 #15
0
static irqreturn_t sensordata_irq_thread_fn(int iIrq, void *dev_id)
{
	struct ssp_data *data = dev_id;
	struct timespec ts;

	ts = ktime_to_timespec(alarm_get_elapsed_realtime());
	data->timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec;

	if(gpio_get_value(data->mcu_int1)) {
		pr_info("[SSP] MCU int HIGH");
		return IRQ_HANDLED;
	}

	select_irq_msg(data);
	data->uIrqCnt++;

	return IRQ_HANDLED;
}
コード例 #16
0
ファイル: msm_thermal.c プロジェクト: sparkmbox/singh-kernel
static void thermal_rtc_setup(void)
{
	ktime_t wakeup_time;
	ktime_t curr_time;

	curr_time = alarm_get_elapsed_realtime();
	wakeup_time = ktime_add_us(curr_time,
			(wakeup_ms * USEC_PER_MSEC));
	alarm_start_range(&thermal_rtc, wakeup_time,
			wakeup_time);
	pr_debug("%s: Current Time: %ld %ld, Alarm set to: %ld %ld\n",
			KBUILD_MODNAME,
			ktime_to_timeval(curr_time).tv_sec,
			ktime_to_timeval(curr_time).tv_usec,
			ktime_to_timeval(wakeup_time).tv_sec,
			ktime_to_timeval(wakeup_time).tv_usec);

}
コード例 #17
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->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);
}
コード例 #18
0
static bool bln_start_blinking_ex(bool start, unsigned int timeout_ms)
{
	DEBUG_LOG("start: %d, bln_enabled: %d, bln_on: %d", start, bln_enabled, bln_on);

	if (start) {
		ktime_t delay;
		if (!bln_enabled || !bln_on) return false;
		bln_blink_on = true;
		delay = ktime_add(alarm_get_elapsed_realtime(), ktime_set(timeout_ms/1000, 0));
		alarm_start_range(&bln_blink_alarm, delay, delay);
		return true;
	} else {
		bln_blink_on = false;
		alarm_try_to_cancel(&bln_blink_alarm);
		cancel_delayed_work(&bln_blink_work);
		if (wake_lock_active(&bln_blink_wakelock)) wake_unlock(&bln_blink_wakelock);
		return false;
	}
}
コード例 #19
0
static void battery_monitor_interval(struct battery_info *info)
{
	ktime_t interval, next, slack;
	unsigned long flags;
	pr_debug("%s\n", __func__);

	local_irq_save(flags);

	info->last_poll = alarm_get_elapsed_realtime();

	switch (info->monitor_mode) {
	case MONITOR_CHNG:
		info->monitor_interval = info->pdata->chng_interval;
		break;
	case MONITOR_CHNG_SUSP:
		info->monitor_interval = info->pdata->chng_susp_interval;
		break;
	case MONITOR_NORM:
		info->monitor_interval = info->pdata->norm_interval;
		break;
	case MONITOR_NORM_SUSP:
		info->monitor_interval = info->pdata->norm_susp_interval;
		break;
	case MONITOR_EMER:
		info->monitor_interval = info->pdata->emer_interval;
		break;
	default:
		info->monitor_interval = info->pdata->norm_interval;
		break;
	}

	pr_debug("%s: monitor mode(%d), interval(%d)\n", __func__,
		info->monitor_mode, info->monitor_interval);

	interval = ktime_set(info->monitor_interval, 0);
	next = ktime_add(info->last_poll, interval);
	slack = ktime_set(20, 0);

	alarm_start_range(&info->alarm, next, ktime_add(next, slack));

	local_irq_restore(flags);
}
コード例 #20
0
static void ds2746_battery_work(struct work_struct *work)
{
	struct ds2746_device_info *di = container_of(work,
				struct ds2746_device_info, monitor_work);
	unsigned long flags;

	do_power_alg(0);
	get_state_check_interval_min_sec();
	di->last_poll = alarm_get_elapsed_realtime();

	/* prevent suspend before starting the alarm */
	local_irq_save(flags);

	wake_unlock(&di->work_wake_lock);
	if (poweralg.battery.is_prediction)
		ds2746_program_alarm(di, PREDIC_POLL);
	else
		ds2746_program_alarm(di, FAST_POLL);

	local_irq_restore(flags);
}
コード例 #21
0
ファイル: wake_timeout.c プロジェクト: talnoah/N5-kernel
static void wakefunc_rtc_start(void)
{
	ktime_t wakeup_time;
	ktime_t curr_time;

	if (!dt2w_switch && !s2w_switch)
		return;

	wakefunc_triggered = false;
	curr_time = alarm_get_elapsed_realtime();
	wakeup_time = ktime_add_us(curr_time,
			(wake_timeout * 1000LL * 60000LL));
	alarm_start_range(&wakefunc_rtc, wakeup_time,
			wakeup_time);
	pr_info("%s: Current Time: %ld, Alarm set to: %ld\n",
			WAKEFUNC,
			ktime_to_timeval(curr_time).tv_sec,
			ktime_to_timeval(wakeup_time).tv_sec);
		
	pr_info("%s: Timeout started for %llu minutes\n", WAKEFUNC,
			wake_timeout);
}
コード例 #22
0
static void p3_cable_changed(struct battery_data *battery)
{
	pr_debug("charger changed ");

	if (!battery->p3_battery_initial)
		return;

	if (!battery->charging_mode_booting)
		battery->info.batt_is_full = 0;

	battery->info.batt_health = POWER_SUPPLY_HEALTH_GOOD;

	schedule_work(&battery->cable_work);

	/*
	 * Wait a bit before reading ac/usb line status and setting charger,
	 * because ac/usb status readings may lag from irq.
	 */

	battery->last_poll = alarm_get_elapsed_realtime();
	p3_program_alarm(battery, FAST_POLL);
}
コード例 #23
0
static int is_over_abs_time(struct battery_data *battery)
{
	unsigned int total_time;
	ktime_t ktime;
	struct timespec cur_time;

	if (!battery->charging_start_time)
		return 0;

	ktime = alarm_get_elapsed_realtime();
	cur_time = ktime_to_timespec(ktime);

	if (battery->info.batt_is_recharging)
		total_time = battery->pdata->recharge_duration;
	else
		total_time = battery->pdata->charge_duration;

	if (battery->charging_start_time + total_time < cur_time.tv_sec) {
		pr_info("Charging time out");
		return 1;
	} else
		return 0;
}
コード例 #24
0
int battery_info_proc(char *buf, char **start,
			off_t offset, int count, int *eof, void *data)
{
	struct battery_info *info = data;
	struct timespec cur_time;
	ktime_t ktime;
	int len = 0;
	/* Guess we need no more than 100 bytes. */
	int size = 100;

	ktime = alarm_get_elapsed_realtime();
	cur_time = ktime_to_timespec(ktime);

	len = snprintf(buf, size,
		"%lu\t%u\t%u\t%u\t%u\t%d\t%u\t%d\t%d\t%u\t"
		"%u\t%u\t%u\t%u\t%u\t%u\t%d\t%u\t%u\n",
		cur_time.tv_sec,
		info->battery_raw_soc,
		info->battery_soc,
		info->battery_vcell / 1000,
		info->battery_vfocv / 1000,
		info->battery_full_soc,
		info->battery_present,
		info->battery_temper,
		info->battery_temper_adc,
		info->battery_health,
		info->charge_real_state,
		info->charge_virt_state,
		info->cable_type,
		info->charge_current,
		info->full_charged_state,
		info->recharge_phase,
		info->abstimer_state,
		info->monitor_interval,
		info->charge_start_time);
	return len;
}
コード例 #25
0
static bool battery_abstimer_cond(struct battery_info *info)
{
	unsigned int abstimer_duration;
	ktime_t ktime;
	struct timespec current_time;
	pr_debug("%s\n", __func__);

	if ((info->cable_type != POWER_SUPPLY_TYPE_MAINS) ||
		(info->full_charged_state == true) ||
		(info->charge_start_time == 0)) {
		info->abstimer_state = false;
		return false;
	}

	ktime = alarm_get_elapsed_realtime();
	current_time = ktime_to_timespec(ktime);

	if (info->recharge_phase)
		abstimer_duration = info->pdata->abstimer_recharge_duration;
	else
		abstimer_duration = info->pdata->abstimer_charge_duration;

	if ((current_time.tv_sec - info->charge_start_time) >
	    abstimer_duration) {
		pr_info("%s: charge time out(%d - %d ?? %d)\n", __func__,
			(int)current_time.tv_sec,
			info->charge_start_time,
			abstimer_duration);
		info->abstimer_state = true;
	} else {
		pr_debug("%s: not abstimer condition\n", __func__);
		info->abstimer_state = false;
	}

	return info->abstimer_state;
}
コード例 #26
0
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rv = 0;
	unsigned long flags;
	struct timespec new_alarm_time;
	struct timespec new_rtc_time;
	struct timespec tmp_time;
	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
	uint32_t alarm_type_mask = 1U << alarm_type;

	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
		return -EINVAL;

#ifdef CONFIG_ANDROID_RTC_CHANGE_WAIT
	if( ANDROID_ALARM_BASE_CMD(cmd)!=ANDROID_ALARM_GET_TIME(0) &&
		ANDROID_ALARM_BASE_CMD(cmd)!=ANDROID_RTC_CHANGE_WAIT ){
#else
	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
#endif
		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
			return -EPERM;
		if (file->private_data == NULL &&
		    cmd != ANDROID_ALARM_SET_RTC) {
			spin_lock_irqsave(&alarm_slock, flags);
			if (alarm_opened) {
				spin_unlock_irqrestore(&alarm_slock, flags);
				return -EBUSY;
			}
			alarm_opened = 1;
			file->private_data = (void *)1;
			spin_unlock_irqrestore(&alarm_slock, flags);
		}
	}

	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
	case ANDROID_ALARM_CLEAR(0):
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		alarm_try_to_cancel(&alarms[alarm_type]);
		if (alarm_pending) {
			alarm_pending &= ~alarm_type_mask;
			if (!alarm_pending && !wait_pending)
				wake_unlock(&alarm_wake_lock);
		}
		alarm_enabled &= ~alarm_type_mask;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;

	case ANDROID_ALARM_SET_OLD:
	case ANDROID_ALARM_SET_AND_WAIT_OLD:
		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
			rv = -EFAULT;
			goto err1;
		}
		new_alarm_time.tv_nsec = 0;
		goto from_old_alarm_set;

	case ANDROID_ALARM_SET_AND_WAIT(0):
	case ANDROID_ALARM_SET(0):
		if (copy_from_user(&new_alarm_time, (void __user *)arg,
		    sizeof(new_alarm_time))) {
			rv = -EFAULT;
			goto err1;
		}
from_old_alarm_set:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
			new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
		alarm_enabled |= alarm_type_mask;
		alarm_start_range(&alarms[alarm_type],
			timespec_to_ktime(new_alarm_time),
			timespec_to_ktime(new_alarm_time));
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
			break;
		/* fall though */
	case ANDROID_ALARM_WAIT:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm wait\n");
		if (!alarm_pending && wait_pending) {
			wake_unlock(&alarm_wake_lock);
			wait_pending = 0;
		}
		spin_unlock_irqrestore(&alarm_slock, flags);
		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
		if (rv)
			goto err1;
		spin_lock_irqsave(&alarm_slock, flags);
		rv = alarm_pending;
		wait_pending = 1;
		alarm_pending = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;
#ifdef CONFIG_ANDROID_RTC_CHANGE_WAIT
	case ANDROID_RTC_CHANGE_WAIT:
		rv = wait_event_interruptible(rtc_change_wait_queue, rtc_changed);
		spin_lock_irqsave(&alarm_slock, flags);
		rtc_changed = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (rv)
			goto err1;
		break;
#endif
	case ANDROID_ALARM_SET_RTC:
		if (copy_from_user(&new_rtc_time, (void __user *)arg,
		    sizeof(new_rtc_time))) {
			rv = -EFAULT;
			goto err1;
		}
		rv = alarm_set_rtc(new_rtc_time);
		spin_lock_irqsave(&alarm_slock, flags);
		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
		wake_up(&alarm_wait_queue);
#ifdef CONFIG_ANDROID_RTC_CHANGE_WAIT
		rtc_changed = 1;
		wake_up(&rtc_change_wait_queue);
#endif
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (rv < 0)
			goto err1;
		break;
	case ANDROID_ALARM_GET_TIME(0):
		switch (alarm_type) {
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_RTC:
			getnstimeofday(&tmp_time);
			break;
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
			tmp_time =
				ktime_to_timespec(alarm_get_elapsed_realtime());
			break;
		case ANDROID_ALARM_TYPE_COUNT:
		case ANDROID_ALARM_SYSTEMTIME:
			ktime_get_ts(&tmp_time);
			break;
		}
		if (copy_to_user((void __user *)arg, &tmp_time,
		    sizeof(tmp_time))) {
			rv = -EFAULT;
			goto err1;
		}
		break;

	default:
		rv = -EINVAL;
		goto err1;
	}
err1:
	return rv;
}

static int alarm_open(struct inode *inode, struct file *file)
{
	file->private_data = NULL;
	return 0;
}
コード例 #27
0
static __devinit int samsung_battery_probe(struct platform_device *pdev)
{
	struct battery_info *info;
	int ret = 0;
	char *temper_src_name[] = { "fuelgauge", "ap adc",
		"ext adc", "unknown"
	};
	pr_info("%s: SAMSUNG Battery Driver Loading\n", __func__);

	info = kzalloc(sizeof(*info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	platform_set_drvdata(pdev, info);

	info->dev = &pdev->dev;
	info->pdata = pdev->dev.platform_data;

	/* Check charger name and fuelgauge name. */
	if (!info->pdata->charger_name || !info->pdata->fuelgauge_name) {
		pr_err("%s: no charger or fuel gauge name\n", __func__);
		goto err_kfree;
	}
	info->charger_name = info->pdata->charger_name;
	info->fuelgauge_name = info->pdata->fuelgauge_name;
#if defined(CONFIG_CHARGER_MAX8922_U1)
	if (system_rev >= 2)
		info->sub_charger_name = info->pdata->sub_charger_name;
#endif
	pr_info("%s: Charger name: %s\n", __func__, info->charger_name);
	pr_info("%s: Fuelgauge name: %s\n", __func__, info->fuelgauge_name);
#if defined(CONFIG_CHARGER_MAX8922_U1)
	if (system_rev >= 2)
		pr_info("%s: SubCharger name: %s\n", __func__,
			info->sub_charger_name);
#endif

	info->psy_charger = power_supply_get_by_name(info->charger_name);
	info->psy_fuelgauge = power_supply_get_by_name(info->fuelgauge_name);
#if defined(CONFIG_CHARGER_MAX8922_U1)
	if (system_rev >= 2)
		info->psy_sub_charger =
		    power_supply_get_by_name(info->sub_charger_name);
#endif
	if (!info->psy_charger || !info->psy_fuelgauge) {
		pr_err("%s: fail to get power supply\n", __func__);
		goto err_kfree;
	}

	/* WORKAROUND: set battery pdata in driver */
	if (system_rev == 3) {
		info->pdata->temper_src = TEMPER_EXT_ADC;
		info->pdata->temper_ch = 7;
	}
	pr_info("%s: Temperature source: %s\n", __func__,
		temper_src_name[info->pdata->temper_src]);

	/* recalculate recharge voltage, it depends on max voltage value */
	info->pdata->recharge_voltage = info->pdata->voltage_max - 50;
	pr_info("%s: Recharge voltage: %d\n", __func__,
				info->pdata->recharge_voltage);
#if defined(CONFIG_S3C_ADC)
#if defined(CONFIG_MACH_S2PLUS)
	if (system_rev >= 2)
#endif
		/* adc register */
		info->adc_client = s3c_adc_register(pdev, NULL, NULL, 0);
#endif

	/* init battery info */
	info->full_charged_state = false;
	info->abstimer_state = false;
	info->recharge_phase = false;
	info->siop_charge_current = CHARGER_USB_CURRENT;
	info->monitor_mode = MONITOR_NORM;
	info->led_state = BATT_LED_DISCHARGING;

	/* LPM charging state */
	info->lpm_state = lpcharge;

	wake_lock_init(&info->monitor_wake_lock, WAKE_LOCK_SUSPEND,
		       "battery-monitor");
	wake_lock_init(&info->emer_wake_lock, WAKE_LOCK_SUSPEND,
		       "battery-emergency");
	if (!info->pdata->suspend_chging)
		wake_lock_init(&info->charge_wake_lock,
			       WAKE_LOCK_SUSPEND, "battery-charging");

	/* Init wq for battery */
	INIT_WORK(&info->error_work, battery_error_work);
	INIT_WORK(&info->monitor_work, battery_monitor_work);

	/* Init Power supply class */
	info->psy_bat.name = "battery";
	info->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY;
	info->psy_bat.properties = samsung_battery_props;
	info->psy_bat.num_properties = ARRAY_SIZE(samsung_battery_props);
	info->psy_bat.get_property = samsung_battery_get_property;
	info->psy_bat.set_property = samsung_battery_set_property;

	info->psy_usb.name = "usb";
	info->psy_usb.type = POWER_SUPPLY_TYPE_USB;
	info->psy_usb.supplied_to = supply_list;
	info->psy_usb.num_supplicants = ARRAY_SIZE(supply_list);
	info->psy_usb.properties = samsung_power_props;
	info->psy_usb.num_properties = ARRAY_SIZE(samsung_power_props);
	info->psy_usb.get_property = samsung_usb_get_property;

	info->psy_ac.name = "ac";
	info->psy_ac.type = POWER_SUPPLY_TYPE_MAINS;
	info->psy_ac.supplied_to = supply_list;
	info->psy_ac.num_supplicants = ARRAY_SIZE(supply_list);
	info->psy_ac.properties = samsung_power_props;
	info->psy_ac.num_properties = ARRAY_SIZE(samsung_power_props);
	info->psy_ac.get_property = samsung_ac_get_property;

	ret = power_supply_register(&pdev->dev, &info->psy_bat);
	if (ret) {
		pr_err("%s: failed to register psy_bat\n", __func__);
		goto err_psy_reg_bat;
	}

	ret = power_supply_register(&pdev->dev, &info->psy_usb);
	if (ret) {
		pr_err("%s: failed to register psy_usb\n", __func__);
		goto err_psy_reg_usb;
	}

	ret = power_supply_register(&pdev->dev, &info->psy_ac);
	if (ret) {
		pr_err("%s: failed to register psy_ac\n", __func__);
		goto err_psy_reg_ac;
	}

	/* Using android alarm for gauging instead of workqueue */
	info->last_poll = alarm_get_elapsed_realtime();
	alarm_init(&info->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
		   samsung_battery_alarm_start);

	/* update battery init status */
	schedule_work(&info->monitor_work);

	/* Create samsung detail attributes */
	battery_create_attrs(info->psy_bat.dev);

	pr_info("%s: SAMSUNG Battery Driver Loaded\n", __func__);
	return 0;

 err_psy_reg_ac:
	power_supply_unregister(&info->psy_usb);
 err_psy_reg_usb:
	power_supply_unregister(&info->psy_bat);
 err_psy_reg_bat:
	wake_lock_destroy(&info->monitor_wake_lock);
	wake_lock_destroy(&info->emer_wake_lock);
	if (!info->pdata->suspend_chging)
		wake_lock_destroy(&info->charge_wake_lock);
 err_kfree:
	kfree(info);

	return ret;
}
コード例 #28
0
static __devinit int max8998_charger_probe(struct platform_device *pdev)
{
	struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
	struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
	struct chg_data *chg;
	struct i2c_client *i2c = iodev->i2c;
	int ret = 0;

	pr_info("%s : MAX8998 Charger Driver Loading\n", __func__);

	chg = kzalloc(sizeof(*chg), GFP_KERNEL);
	if (!chg)
		return -ENOMEM;

	chg->iodev = iodev;
	chg->pdata = pdata->charger;

	if (!chg->pdata || !chg->pdata->adc_table) {
		pr_err("%s : No platform data & adc_table supplied\n", __func__);
		ret = -EINVAL;
		goto err_bat_table;
	}

	chg->psy_bat.name = "battery",
	chg->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY,
	chg->psy_bat.properties = max8998_battery_props,
	chg->psy_bat.num_properties = ARRAY_SIZE(max8998_battery_props),
	chg->psy_bat.get_property = s3c_bat_get_property,
	chg->psy_bat.property_is_writeable = s3c_bat_property_is_writeable,
	chg->psy_bat.set_property = s3c_bat_set_property,

	chg->psy_usb.name = "usb",
	chg->psy_usb.type = POWER_SUPPLY_TYPE_USB,
	chg->psy_usb.supplied_to = supply_list,
	chg->psy_usb.num_supplicants = ARRAY_SIZE(supply_list),
	chg->psy_usb.properties = s3c_power_properties,
	chg->psy_usb.num_properties = ARRAY_SIZE(s3c_power_properties),
	chg->psy_usb.get_property = s3c_usb_get_property,

	chg->psy_ac.name = "ac",
	chg->psy_ac.type = POWER_SUPPLY_TYPE_MAINS,
	chg->psy_ac.supplied_to = supply_list,
	chg->psy_ac.num_supplicants = ARRAY_SIZE(supply_list),
	chg->psy_ac.properties = s3c_power_properties,
	chg->psy_ac.num_properties = ARRAY_SIZE(s3c_power_properties),
	chg->psy_ac.get_property = s3c_ac_get_property,

	chg->present = 1;
	chg->bat_info.batt_health = POWER_SUPPLY_HEALTH_GOOD;
	chg->bat_info.batt_is_full = false;
	chg->bat_info.batt_temp = 100; //fake
	chg->bat_info.batt_percentage = 50; //fake, modem will bootup soon and update it... hopefully
	chg->set_charge_timeout = false;

	chg->cable_status = CABLE_TYPE_NONE;

	mutex_init(&chg->mutex);

	platform_set_drvdata(pdev, chg);

	ret = max8998_update_reg(i2c, MAX8998_REG_CHGR1, /* disable */
		(0x3 << MAX8998_SHIFT_RSTR), MAX8998_MASK_RSTR);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_update_reg(i2c, MAX8998_REG_CHGR2, /* 6 Hr */
		(0x2 << MAX8998_SHIFT_FT), MAX8998_MASK_FT);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_update_reg(i2c, MAX8998_REG_CHGR2, /* 4.2V */
		(0x0 << MAX8998_SHIFT_BATTSL), MAX8998_MASK_BATTSL);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_update_reg(i2c, MAX8998_REG_CHGR2, /* 105c */
		(0x0 << MAX8998_SHIFT_TMP), MAX8998_MASK_TMP);
	if (ret < 0)
		goto err_kfree;

	pr_info("%s : pmic interrupt registered\n", __func__);
	ret = max8998_write_reg(i2c, MAX8998_REG_IRQM1,
		~(MAX8998_MASK_DCINR | MAX8998_MASK_DCINF));
	if (ret < 0)
		goto err_kfree;

	ret = max8998_write_reg(i2c, MAX8998_REG_IRQM2, 0xFF);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_write_reg(i2c, MAX8998_REG_IRQM3, ~MAX8998_IRQ_CHGRSTF_MASK);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_write_reg(i2c, MAX8998_REG_IRQM4, 0xFF);
	if (ret < 0)
		goto err_kfree;

	wake_lock_init(&chg->vbus_wake_lock, WAKE_LOCK_SUSPEND,
		"vbus_present");
	wake_lock_init(&chg->work_wake_lock, WAKE_LOCK_SUSPEND,
		"max8998-charger");

	INIT_WORK(&chg->bat_work, s3c_bat_work);

	chg->monitor_wqueue =
		create_freezable_workqueue(dev_name(&pdev->dev));
	if (!chg->monitor_wqueue) {
		pr_err("Failed to create freezeable workqueue\n");
		ret = -ENOMEM;
		goto err_wake_lock;
	}

	chg->last_poll = alarm_get_elapsed_realtime();
	alarm_init(&chg->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
		s3c_battery_alarm);

	check_lpm_charging_mode(chg);

	/* init power supplier framework */
	ret = power_supply_register(&pdev->dev, &chg->psy_bat);
	if (ret) {
		pr_err("Failed to register power supply psy_bat\n");
		goto err_wqueue;
	}

	ret = power_supply_register(&pdev->dev, &chg->psy_usb);
	if (ret) {
		pr_err("Failed to register power supply psy_usb\n");
		goto err_supply_unreg_bat;
	}

	ret = power_supply_register(&pdev->dev, &chg->psy_ac);
	if (ret) {
		pr_err("Failed to register power supply psy_ac\n");
		goto err_supply_unreg_usb;
	}

	ret = request_threaded_irq(iodev->i2c->irq, NULL,
			max8998_int_work_func,
			IRQF_TRIGGER_FALLING, "max8998-charger", chg);
	if (ret) {
		pr_err("%s : Failed to request pmic irq\n", __func__);
		goto err_supply_unreg_ac;
	}

	ret = enable_irq_wake(iodev->i2c->irq);
	if (ret) {
		pr_err("Failed to enable pmic irq wake\n");
		goto err_irq;
	}

	ret = s3c_bat_create_attrs(chg->psy_bat.dev);
	if (ret) {
		pr_err("%s : Failed to create_attrs\n", __func__);
		goto err_irq;
	}

	chg->callbacks.set_cable = max8998_set_cable;
	if (chg->pdata->register_callbacks)
		chg->pdata->register_callbacks(&chg->callbacks);

	wake_lock(&chg->work_wake_lock);
	queue_work(chg->monitor_wqueue, &chg->bat_work);

	return 0;

err_irq:
	free_irq(iodev->i2c->irq, NULL);
err_supply_unreg_ac:
	power_supply_unregister(&chg->psy_ac);
err_supply_unreg_usb:
	power_supply_unregister(&chg->psy_usb);
err_supply_unreg_bat:
	power_supply_unregister(&chg->psy_bat);
err_wqueue:
	destroy_workqueue(chg->monitor_wqueue);
	cancel_work_sync(&chg->bat_work);
	alarm_cancel(&chg->alarm);
err_wake_lock:
	wake_lock_destroy(&chg->work_wake_lock);
	wake_lock_destroy(&chg->vbus_wake_lock);
err_kfree:
	mutex_destroy(&chg->mutex);
err_bat_table:
	kfree(chg);
	return ret;
}
コード例 #29
0
static void battery_charge_control(struct battery_info *info,
				   int enable,
				   int set_current)
{
	ktime_t ktime;
	struct timespec current_time;
	pr_debug("%s\n", __func__);

	ktime = alarm_get_elapsed_realtime();
	current_time = ktime_to_timespec(ktime);

	if (set_current == CHARGER_KEEP_CURRENT)
		goto charge_state_control;

	if (info->siop_state == true) {
		pr_debug("%s: siop state, charge current is %dmA\n", __func__,
			 info->siop_charge_current);
		set_current = info->siop_charge_current;
	}

	/* check charge current before and after */
	if (info->charge_current == ((set_current * 3 / 100) * 333 / 10)) {
		/*
		 * (current * 3 / 100) is converted value
		 * for register setting.
		 * (register current * 333 / 10) is actual value
		 * for charging
		 */
		pr_debug("%s: same charge current: %dmA\n", __func__,
							set_current);
	} else {
		battery_control_info(info,
				     POWER_SUPPLY_PROP_CURRENT_NOW,
				     set_current);
		pr_info("%s: update charge current: %dmA\n", __func__,
							set_current);
	}

	info->charge_current =
		battery_get_info(info, POWER_SUPPLY_PROP_CURRENT_NOW);

charge_state_control:
	/* check charge state before and after */
	if ((enable == CHARGE_ENABLE) &&
		(info->charge_start_time == 0)) {
		battery_control_info(info,
				     POWER_SUPPLY_PROP_STATUS,
				     CHARGE_ENABLE);

		info->charge_start_time = current_time.tv_sec;
		pr_info("%s: charge enabled, current as %dmA @%d\n", __func__,
				info->charge_current, info->charge_start_time);
	} else if ((enable == CHARGE_DISABLE) &&
		(info->charge_start_time != 0)) {
		battery_control_info(info,
				     POWER_SUPPLY_PROP_STATUS,
				     CHARGE_DISABLE);

		pr_info("%s: charge disabled, current as %dmA @%d\n", __func__,
				info->charge_current, (int)current_time.tv_sec);

		info->charge_start_time = 0;
	} else {
		pr_debug("%s: same charge state(%s), current as %dmA @%d\n",
				__func__, (enable ? "enabled" : "disabled"),
				info->charge_current, info->charge_start_time);
	}

	info->charge_real_state = info->charge_virt_state =
		battery_get_info(info, POWER_SUPPLY_PROP_STATUS);
}
コード例 #30
0
static int s3c_cable_status_update(struct chg_data *chg)
{
	int ret;
	bool vdc_status;
	ktime_t ktime;
	struct timespec cur_time;

	/* if max8998 has detected vdcin */
	if (max8998_check_vdcin(chg)) {
		vdc_status = 1;
		if (chg->bat_info.dis_reason) {
			pr_info("%s : battery status discharging : %d\n",
				__func__, chg->bat_info.dis_reason);
			/* have vdcin, but cannot charge */
			chg->charging = false;
			ret = max8998_charging_control(chg);
			if (ret < 0)
				goto err;
			chg->bat_info.charging_status =
				chg->bat_info.batt_is_full ?
				POWER_SUPPLY_STATUS_FULL :
				POWER_SUPPLY_STATUS_NOT_CHARGING;
			chg->discharging_time = 0;
			chg->set_batt_full = 0;
			goto update;
		} else if (chg->discharging_time == 0) {
			ktime = alarm_get_elapsed_realtime();
			cur_time = ktime_to_timespec(ktime);
			chg->discharging_time =
				chg->bat_info.batt_is_full ||
				chg->set_charge_timeout ?
				cur_time.tv_sec + TOTAL_RECHARGING_TIME :
				cur_time.tv_sec + TOTAL_CHARGING_TIME;
		}

		/* able to charge */
		chg->charging = true;
		ret = max8998_charging_control(chg);
		if (ret < 0)
			goto err;

		chg->bat_info.charging_status = chg->bat_info.batt_is_full ?
			POWER_SUPPLY_STATUS_FULL : POWER_SUPPLY_STATUS_CHARGING;

	} else {
		/* no vdc in, not able to charge */
		vdc_status = 0;
		chg->charging = false;
		ret = max8998_charging_control(chg);
		if (ret < 0)
			goto err;

		chg->bat_info.charging_status = POWER_SUPPLY_STATUS_DISCHARGING;

		chg->bat_info.batt_is_full = false;
		chg->set_charge_timeout = false;
		chg->set_batt_full = 0;
		chg->bat_info.dis_reason = 0;
		chg->discharging_time = 0;

		if (lpm_charging_mode && pm_power_off)
			pm_power_off();
	}

update:
	if ((chg->cable_status == CABLE_TYPE_USB) && vdc_status)
		wake_lock(&chg->vbus_wake_lock);
	else
		wake_lock_timeout(&chg->vbus_wake_lock, HZ / 2);

	return 0;
err:
	return ret;
}