Esempio n. 1
0
/*
 * Provide RTC information in /proc/driver/rtc
 */
static int at91_rtc_read_proc(char *page, char **start, off_t off,
			      int count, int *eof, void *data)
{
	char *p = page;
	int len;
	struct rtc_time tm;

	at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
	p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
			"rtc_date\t: %04d-%02d-%02d\n"
			"rtc_epoch\t: %04d\n",
			tm.tm_hour, tm.tm_min, tm.tm_sec,
			tm.tm_year, tm.tm_mon + 1, tm.tm_mday, EPOCH);
	at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
	p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
			"alrm_date\t: %04d-%02d-%02d\n",
			tm.tm_hour, tm.tm_min, tm.tm_sec,
			at91_alarm_year, tm.tm_mon + 1, tm.tm_mday);
	p += sprintf(p, "alarm_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ALARM) ? "yes" : "no");
	p += sprintf(p, "update_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ACKUPD) ? "yes" : "no");
	p += sprintf(p, "periodic_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_SECEV) ? "yes" : "no");
	p += sprintf(p, "periodic_freq\t: %ld\n", (unsigned long) AT91_RTC_FREQ);

	len = (p - page) - off;
	if (len < 0)
		len = 0;

	*eof = (len <= count) ? 1 : 0;
	*start = page + off;

	return len;
}
Esempio n. 2
0
/*
 * Set alarm time and date in RTC
 */
static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_time tm;

	at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm);

	at91_alarm_year = tm.tm_year;

	tm.tm_hour = alrm->time.tm_hour;
	tm.tm_min = alrm->time.tm_min;
	tm.tm_sec = alrm->time.tm_sec;

	at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
	at91_sys_write(AT91_RTC_TIMALR,
		  bin2bcd(tm.tm_sec) << 0
		| bin2bcd(tm.tm_min) << 8
		| bin2bcd(tm.tm_hour) << 16
		| AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
	at91_sys_write(AT91_RTC_CALALR,
		  bin2bcd(tm.tm_mon + 1) << 16		/* tm_mon starts at zero */
		| bin2bcd(tm.tm_mday) << 24
		| AT91_RTC_DATEEN | AT91_RTC_MTHEN);

	if (alrm->enabled) {
		at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
		at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
	}

	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
		at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
		tm.tm_min, tm.tm_sec);

	return 0;
}
Esempio n. 3
0
/*
 * Set alarm time and date in RTC
 */
static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_time tm;

	at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm);

	tm.tm_mon = alrm->time.tm_mon;
	tm.tm_mday = alrm->time.tm_mday;
	tm.tm_hour = alrm->time.tm_hour;
	tm.tm_min = alrm->time.tm_min;
	tm.tm_sec = alrm->time.tm_sec;

	at91_rtc_write_idr(AT91_RTC_ALARM);
	at91_rtc_write(AT91_RTC_TIMALR,
		  bin2bcd(tm.tm_sec) << 0
		| bin2bcd(tm.tm_min) << 8
		| bin2bcd(tm.tm_hour) << 16
		| AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
	at91_rtc_write(AT91_RTC_CALALR,
		  bin2bcd(tm.tm_mon + 1) << 16		/* tm_mon starts at zero */
		| bin2bcd(tm.tm_mday) << 24
		| AT91_RTC_DATEEN | AT91_RTC_MTHEN);

	if (alrm->enabled) {
		at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
		at91_rtc_write_ier(AT91_RTC_ALARM);
	}

	dev_dbg(dev, "%s(): %ptR\n", __func__, &tm);

	return 0;
}
Esempio n. 4
0
/*
 * Read current time and date in RTC
 */
static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
{
	at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, tm);
	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
	tm->tm_year = tm->tm_year - 1900;

	dev_dbg(dev, "%s(): %ptR\n", __func__, tm);

	return 0;
}
Esempio n. 5
0
/*
 * Read current time and date in RTC
 */
static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
{
	at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, tm);
	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
	tm->tm_year = tm->tm_year - 1900;

	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
		tm->tm_hour, tm->tm_min, tm->tm_sec);

	return 0;
}
Esempio n. 6
0
/*
 * Read alarm time and date in RTC
 */
static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_time *tm = &alrm->time;

	at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm);
	tm->tm_year = -1;

	alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM)
			? 1 : 0;

	dev_dbg(dev, "%s(): %ptR %sabled\n", __func__, tm,
		alrm->enabled ? "en" : "dis");

	return 0;
}
Esempio n. 7
0
/*
 * Read alarm time and date in RTC
 */
static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
    struct rtc_time *tm = &alrm->time;

    at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm);
    tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
    tm->tm_year = at91_alarm_year - 1900;

    alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM)
                    ? 1 : 0;

    dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
            1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
            tm->tm_hour, tm->tm_min, tm->tm_sec);

    return 0;
}
Esempio n. 8
0
/*
 * Handle commands from user-space
 */
static int at91_rtc_ioctl(struct inode *inode, struct file *file,
			  unsigned int cmd, unsigned long arg)
{
	struct rtc_time tm, tm2;
	int ret = 0;

	spin_lock_irq(&at91_rtc_lock);
	switch (cmd) {
	case RTC_AIE_OFF:	/* alarm off */
		AT91_SYS->RTC_IDR = AT91C_RTC_ALARM;
		rtc_irq_data = 0;
		break;
	case RTC_AIE_ON:	/* alarm on */
		AT91_SYS->RTC_IER = AT91C_RTC_ALARM;
		rtc_irq_data = 0;
		break;
	case RTC_UIE_OFF:	/* update off */
		AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
		rtc_irq_data = 0;
		break;
	case RTC_UIE_ON:	/* update on */
		AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
		rtc_irq_data = 0;
		break;
	case RTC_PIE_OFF:	/* periodic off */
		AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
		rtc_irq_data = 0;
		break;
	case RTC_PIE_ON:	/* periodic on */
		AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
		rtc_irq_data = 0;
		break;
	case RTC_ALM_READ:	/* read alarm */
		at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
		tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
		tm.tm_year = at91_alarm_year - 1900;
		ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
		break;
	case RTC_ALM_SET:	/* set alarm */
		if (copy_from_user(&tm2, (struct rtc_time *) arg, sizeof(tm2)))
			ret = -EFAULT;
		else {
			at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
			at91_alarm_year = tm.tm_year;
			if ((unsigned) tm2.tm_hour < 24)	/* do some range checking */
				tm.tm_hour = tm2.tm_hour;
			if ((unsigned) tm2.tm_min < 60)
				tm.tm_min = tm2.tm_min;
			if ((unsigned) tm2.tm_sec < 60)
				tm.tm_sec = tm2.tm_sec;
			AT91_SYS->RTC_TIMALR = BIN2BCD(tm.tm_sec) << 0
				| BIN2BCD(tm.tm_min) << 8
				| BIN2BCD(tm.tm_hour) << 16
				| AT91C_RTC_HOUREN | AT91C_RTC_MINEN
				| AT91C_RTC_SECEN;
			AT91_SYS->RTC_CALALR = BIN2BCD(tm.tm_mon + 1) << 16	/* tm_mon starts at zero */
				| BIN2BCD(tm.tm_mday) << 24
				| AT91C_RTC_DATEEN | AT91C_RTC_MONTHEN;
		}
		break;
	case RTC_RD_TIME:	/* read time */
		at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
		tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
		tm.tm_year = tm.tm_year - 1900;
		ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
		break;
	case RTC_SET_TIME:	/* set time */
		if (!capable(CAP_SYS_TIME))
			ret = -EACCES;
		else {
			if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(tm)))
				ret = -EFAULT;
			else {
				int tm_year = tm.tm_year + 1900;
				if (tm_year < EPOCH
				    || (unsigned) tm.tm_mon >= 12
				    || tm.tm_mday < 1
				    || tm.tm_mday > (days_in_mo[tm.tm_mon] + (tm.tm_mon == 1 && is_leap(tm_year)))
				    || (unsigned) tm.tm_hour >= 24
				    || (unsigned) tm.tm_min >= 60
				    || (unsigned) tm.tm_sec >= 60)
					ret = -EINVAL;
				else
					at91_rtc_settime(&tm);
			}
		}
		break;
	case RTC_IRQP_READ:	/* read periodic alarm frequency */
		ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
		break;
	case RTC_IRQP_SET:	/* set periodic alarm frequency */
		if (arg != AT91_RTC_FREQ)
			ret = -EINVAL;
		break;
	case RTC_EPOCH_READ:	/* read epoch */
		ret = put_user(EPOCH, (unsigned long *) arg);
		break;
	default:
		ret = -EINVAL;
		break;
	}
	spin_unlock_irq(&at91_rtc_lock);
	return ret;
}