Exemplo n.º 1
0
/**
 * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue
 * @rtc rtc device
 * @timer timer being removed.
 *
 * Removes a timer onto the rtc devices timerqueue and sets
 * the next alarm event appropriately.
 *
 * Clears the enabled bit on the removed timer.
 *
 * Must hold ops_lock for proper serialization of timerqueue
 */
static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
{
	struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);

	timerqueue_del(&rtc->timerqueue, &timer->node);
	trace_rtc_timer_dequeue(timer);
	timer->enabled = 0;
	if (next == &timer->node) {
		struct rtc_wkalrm alarm;
		int err;

		next = timerqueue_getnext(&rtc->timerqueue);
		if (!next) {
			rtc_alarm_disable(rtc);
			return;
		}
		alarm.time = rtc_ktime_to_tm(next->expires);
		alarm.enabled = 1;
		err = __rtc_set_alarm(rtc, &alarm);
		if (err == -ETIME) {
			pm_stay_awake(rtc->dev.parent);
			schedule_work(&rtc->irqwork);
		}
	}
}
Exemplo n.º 2
0
static int lastlog_m_show(struct seq_file *s, void *v)
{
	const char priority_chars[] = {'?', '?', 'V', 'D', 'I','W','E', 'F', 'S'};
	struct logger_entry *entry = v;
	struct logger_entry tmp;
	char* tagaddr;
	char *msgaddr;
	struct rtc_time rtctime;
	int priority;

	memcpy (&tmp, entry, sizeof(tmp));

	rtctime = rtc_ktime_to_tm(ktime_set (tmp.sec, tmp.nsec));
	priority = entry->msg[0];
	tagaddr = &(entry->msg[1]);
	msgaddr = tagaddr + strlen(tagaddr) + 1;

	seq_printf (s, "%02d-%02d %02d:%02d:%02d.%03d %c/%-8s(%5d:%d): ",
						rtctime.tm_mon + 1, rtctime.tm_mday, rtctime.tm_hour,
						rtctime.tm_min, rtctime.tm_sec + 1,
						tmp.nsec / 1000000, priority_chars[priority],
						tagaddr, tmp.pid, tmp.tid);
	if (entry->msg[tmp.len-1] == '\0') {
		seq_printf (s, "%s", msgaddr);
	} else {
		seq_write (s, msgaddr, tmp.len - (msgaddr - entry->msg));
	}

	if (s->buf[s->count-1] != '\n')
		seq_putc(s, '\n');

	return 0;
}
Exemplo n.º 3
0
int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
	int err;

	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
		return err;
	if (rtc->ops == NULL)
		err = -ENODEV;
	else if (!rtc->ops->read_alarm)
		err = -EINVAL;
	else {
		memset(alarm, 0, sizeof(struct rtc_wkalrm));
		alarm->enabled = rtc->aie_timer.enabled;
		alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires);
	}
	mutex_unlock(&rtc->ops_lock);

	return err;
}
Exemplo n.º 4
0
/**
 * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue
 * @rtc rtc device
 * @timer timer being added.
 *
 * Enqueues a timer onto the rtc devices timerqueue and sets
 * the next alarm event appropriately.
 *
 * Sets the enabled bit on the added timer.
 *
 * Must hold ops_lock for proper serialization of timerqueue
 */
static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
{
	struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
	struct rtc_time tm;
	ktime_t now;

	timer->enabled = 1;
	__rtc_read_time(rtc, &tm);
	now = rtc_tm_to_ktime(tm);

	/* Skip over expired timers */
	while (next) {
		if (next->expires >= now)
			break;
		next = timerqueue_iterate_next(next);
	}

	timerqueue_add(&rtc->timerqueue, &timer->node);
	trace_rtc_timer_enqueue(timer);
	if (!next || ktime_before(timer->node.expires, next->expires)) {
		struct rtc_wkalrm alarm;
		int err;

		alarm.time = rtc_ktime_to_tm(timer->node.expires);
		alarm.enabled = 1;
		err = __rtc_set_alarm(rtc, &alarm);
		if (err == -ETIME) {
			pm_stay_awake(rtc->dev.parent);
			schedule_work(&rtc->irqwork);
		} else if (err) {
			timerqueue_del(&rtc->timerqueue, &timer->node);
			trace_rtc_timer_dequeue(timer);
			timer->enabled = 0;
			return err;
		}
	}
	return 0;
}
Exemplo n.º 5
0
int alarm_set_alarm(char* alarm_data)
{
	struct rtc_wkalrm alm;
	int ret;
	char buf_ptr[BOOTALM_BIT_TOTAL+1];
	struct rtc_time rtc_tm;
	unsigned long rtc_sec;
	unsigned long rtc_alarm_time;
	struct timespec rtc_delta;
	struct timespec wall_time;
	ktime_t wall_ktm;
	struct rtc_time wall_tm;
	struct rtc_device *rtc_dev = alarmtimer_get_rtcdev();

	if (!rtc_dev) {
		pr_err("%s: no RTC, time will be lost on reboot\n", __func__);
		return -ENXIO;
	}

	strlcpy(buf_ptr, alarm_data, BOOTALM_BIT_TOTAL+1);

	alm.time.tm_sec = 0;
	alm.time.tm_min = (buf_ptr[BOOTALM_BIT_MIN] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_MIN+1]  - '0');
	alm.time.tm_hour = (buf_ptr[BOOTALM_BIT_HOUR] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_HOUR+1] - '0');
	alm.time.tm_mday = (buf_ptr[BOOTALM_BIT_DAY] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_DAY+1] - '0');
	alm.time.tm_mon = (buf_ptr[BOOTALM_BIT_MONTH] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_MONTH+1] - '0');
	alm.time.tm_year = (buf_ptr[BOOTALM_BIT_YEAR] - '0') * 1000
				+ (buf_ptr[BOOTALM_BIT_YEAR+1] - '0') * 100
				+ (buf_ptr[BOOTALM_BIT_YEAR+2] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_YEAR+3] - '0');

	alm.enabled = (*buf_ptr == '1');

	pr_info("[SAPA] %s : %s => tm(%d %04d-%02d-%02d %02d:%02d:%02d)\n",
			__func__, buf_ptr, alm.enabled,
			alm.time.tm_year, alm.time.tm_mon, alm.time.tm_mday,
			alm.time.tm_hour, alm.time.tm_min, alm.time.tm_sec);

	if (alm.enabled) {
		/* If time daemon is exist */

		alm.time.tm_mon -= 1;
		alm.time.tm_year -= 1900;

		/* read current time */
		rtc_read_time(rtc_dev, &rtc_tm);
		rtc_tm_to_time(&rtc_tm, &rtc_sec);
		pr_info("[SAPA] rtc  %4d-%02d-%02d %02d:%02d:%02d -> %lu\n",
			rtc_tm.tm_year, rtc_tm.tm_mon, rtc_tm.tm_mday,
			rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec, rtc_sec);

		/* read kernel time */
		getnstimeofday(&wall_time);
		wall_ktm = timespec_to_ktime(wall_time);
		wall_tm = rtc_ktime_to_tm(wall_ktm);
		pr_info("[SAPA] wall %4d-%02d-%02d %02d:%02d:%02d -> %lu\n",
			wall_tm.tm_year, wall_tm.tm_mon, wall_tm.tm_mday,
			wall_tm.tm_hour, wall_tm.tm_min, wall_tm.tm_sec, wall_time.tv_sec);

		/* calculate offset */
		set_normalized_timespec(&rtc_delta,
					wall_time.tv_sec - rtc_sec,
					wall_time.tv_nsec);

		/* convert user requested SAPA time to second type */
		rtc_tm_to_time(&alm.time, &rtc_alarm_time);

		/* convert to RTC time with user requested SAPA time and offset */
		rtc_alarm_time -= rtc_delta.tv_sec;
		rtc_time_to_tm(rtc_alarm_time, &alm.time);
		pr_info("[SAPA] arlm %4d-%02d-%02d %02d:%02d:%02d -> %lu\n",
			alm.time.tm_year, alm.time.tm_mon, alm.time.tm_mday,
			alm.time.tm_hour, alm.time.tm_min, alm.time.tm_sec, rtc_alarm_time);

	}
	ret = rtc_set_bootalarm(rtc_dev, &alm);
	if (ret < 0) {
		pr_err("%s: Failed to set ALARM, time will be lost on reboot\n", __func__);
		return ret;
	}

	return 0;
}
Exemplo n.º 6
0
/**
 * rtc_timer_do_work - Expires rtc timers
 * @rtc rtc device
 * @timer timer being removed.
 *
 * Expires rtc timers. Reprograms next alarm event if needed.
 * Called via worktask.
 *
 * Serializes access to timerqueue via ops_lock mutex
 */
void rtc_timer_do_work(struct work_struct *work)
{
	struct rtc_timer *timer;
	struct timerqueue_node *next;
	ktime_t now;
	struct rtc_time tm;

	struct rtc_device *rtc =
		container_of(work, struct rtc_device, irqwork);

	mutex_lock(&rtc->ops_lock);
again:
	__rtc_read_time(rtc, &tm);
	now = rtc_tm_to_ktime(tm);
	while ((next = timerqueue_getnext(&rtc->timerqueue))) {
		if (next->expires > now)
			break;

		/* expire timer */
		timer = container_of(next, struct rtc_timer, node);
		timerqueue_del(&rtc->timerqueue, &timer->node);
		trace_rtc_timer_dequeue(timer);
		timer->enabled = 0;
		if (timer->func)
			timer->func(timer->rtc);

		trace_rtc_timer_fired(timer);
		/* Re-add/fwd periodic timers */
		if (ktime_to_ns(timer->period)) {
			timer->node.expires = ktime_add(timer->node.expires,
							timer->period);
			timer->enabled = 1;
			timerqueue_add(&rtc->timerqueue, &timer->node);
			trace_rtc_timer_enqueue(timer);
		}
	}

	/* Set next alarm */
	if (next) {
		struct rtc_wkalrm alarm;
		int err;
		int retry = 3;

		alarm.time = rtc_ktime_to_tm(next->expires);
		alarm.enabled = 1;
reprogram:
		err = __rtc_set_alarm(rtc, &alarm);
		if (err == -ETIME) {
			goto again;
		} else if (err) {
			if (retry-- > 0)
				goto reprogram;

			timer = container_of(next, struct rtc_timer, node);
			timerqueue_del(&rtc->timerqueue, &timer->node);
			trace_rtc_timer_dequeue(timer);
			timer->enabled = 0;
			dev_err(&rtc->dev, "__rtc_set_alarm: err=%d\n", err);
			goto again;
		}
	} else {
Exemplo n.º 7
0
static void cros_usbpd_print_log_entry(struct ec_response_pd_log *r,
				       ktime_t tstamp)
{
	const char *fault, *role, *chg_type;
	struct usb_chg_measures *meas;
	struct mcdp_info *minfo;
	int role_idx, type_idx;
	char buf[BUF_SIZE + 1];
	struct rtc_time rt;
	int len = 0;
	s32 rem;
	int i;

	/* The timestamp is the number of 1024th of seconds in the past */
	tstamp = ktime_sub_us(tstamp, r->timestamp << PD_LOG_TIMESTAMP_SHIFT);
	rt = rtc_ktime_to_tm(tstamp);

	switch (r->type) {
	case PD_EVENT_MCU_CHARGE:
		if (r->data & CHARGE_FLAGS_OVERRIDE)
			len += append_str(buf, len, "override ");

		if (r->data & CHARGE_FLAGS_DELAYED_OVERRIDE)
			len += append_str(buf, len, "pending_override ");

		role_idx = r->data & CHARGE_FLAGS_ROLE_MASK;
		role = role_idx < ARRAY_SIZE(role_names) ?
			role_names[role_idx] : "Unknown";

		type_idx = (r->data & CHARGE_FLAGS_TYPE_MASK)
			 >> CHARGE_FLAGS_TYPE_SHIFT;

		chg_type = type_idx < ARRAY_SIZE(chg_type_names) ?
			chg_type_names[type_idx] : "???";

		if (role_idx == USB_PD_PORT_POWER_DISCONNECTED ||
		    role_idx == USB_PD_PORT_POWER_SOURCE) {
			len += append_str(buf, len, "%s", role);
			break;
		}

		meas = (struct usb_chg_measures *)r->payload;
		len += append_str(buf, len, "%s %s %s %dmV max %dmV / %dmA",
				  role,	r->data & CHARGE_FLAGS_DUAL_ROLE ?
				  "DRP" : "Charger",
				  chg_type, meas->voltage_now,
				  meas->voltage_max, meas->current_max);
		break;
	case PD_EVENT_ACC_RW_FAIL:
		len += append_str(buf, len, "RW signature check failed");
		break;
	case PD_EVENT_PS_FAULT:
		fault = r->data < ARRAY_SIZE(fault_names) ? fault_names[r->data]
							  : "???";
		len += append_str(buf, len, "Power supply fault: %s", fault);
		break;
	case PD_EVENT_VIDEO_DP_MODE:
		len += append_str(buf, len, "DP mode %sabled", r->data == 1 ?
				  "en" : "dis");
		break;
	case PD_EVENT_VIDEO_CODEC:
		minfo = (struct mcdp_info *)r->payload;
		len += append_str(buf, len, "HDMI info: family:%04x chipid:%04x ",
				  MCDP_FAMILY(minfo->family),
				  MCDP_CHIPID(minfo->chipid));
		len += append_str(buf, len, "irom:%d.%d.%d fw:%d.%d.%d",
				  minfo->irom.major, minfo->irom.minor,
				  minfo->irom.build, minfo->fw.major,
				  minfo->fw.minor, minfo->fw.build);
		break;
	default:
		len += append_str(buf, len, "Event %02x (%04x) [", r->type,
				  r->data);

		for (i = 0; i < PD_LOG_SIZE(r->size_port); i++)
			len += append_str(buf, len, "%02x ", r->payload[i]);

		len += append_str(buf, len, "]");
		break;
	}

	div_s64_rem(ktime_to_ms(tstamp), MSEC_PER_SEC, &rem);
	pr_info("PDLOG %d/%02d/%02d %02d:%02d:%02d.%03d P%d %s\n",
		rt.tm_year + 1900, rt.tm_mon + 1, rt.tm_mday,
		rt.tm_hour, rt.tm_min, rt.tm_sec, rem,
		PD_LOG_PORT(r->size_port), buf);
}