Beispiel #1
0
static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	struct omap_rtc *rtc = dev_get_drvdata(dev);
	u8 reg, irqwake_reg = 0;

	local_irq_disable();
	rtc_wait_not_busy(rtc);
	reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
	if (rtc->type->has_irqwakeen)
		irqwake_reg = rtc_read(rtc, OMAP_RTC_IRQWAKEEN);

	if (enabled) {
		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
		irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
	} else {
		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
		irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
	}
	rtc_wait_not_busy(rtc);
	rtc->type->unlock(rtc);
	rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg);
	if (rtc->type->has_irqwakeen)
		rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg);
	rtc->type->lock(rtc);
	local_irq_enable();

	return 0;
}
Beispiel #2
0
static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	u8 reg;

	if (tm2bcd(&alm->time) < 0)
		return -EINVAL;

	local_irq_disable();
	rtc_wait_not_busy();

	rtc_write(alm->time.tm_year, OMAP_RTC_ALARM_YEARS_REG);
	rtc_write(alm->time.tm_mon, OMAP_RTC_ALARM_MONTHS_REG);
	rtc_write(alm->time.tm_mday, OMAP_RTC_ALARM_DAYS_REG);
	rtc_write(alm->time.tm_hour, OMAP_RTC_ALARM_HOURS_REG);
	rtc_write(alm->time.tm_min, OMAP_RTC_ALARM_MINUTES_REG);
	rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);

	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
	if (alm->enabled)
		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
	else
		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);

	local_irq_enable();

	return 0;
}
Beispiel #3
0
/*
 * spear_rtc_set_alarm - set the alarm time
 * @dev: rtc device in use
 * @alm: holds alarm date and time
 *
 * This function set alarm time and date. On success it will return 0
 * otherwise -ve error is returned.
 */
static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	struct spear_rtc_config *config = dev_get_drvdata(dev);
	unsigned int time, date;
	int err;

	if (tm2bcd(&alm->time) < 0)
		return -EINVAL;

	rtc_wait_not_busy(config);

	time = (alm->time.tm_sec << SECOND_SHIFT) | (alm->time.tm_min <<
			MINUTE_SHIFT) |	(alm->time.tm_hour << HOUR_SHIFT);
	date = (alm->time.tm_mday << MDAY_SHIFT) | (alm->time.tm_mon <<
			MONTH_SHIFT) | (alm->time.tm_year << YEAR_SHIFT);

	writel(time, config->ioaddr + ALARM_TIME_REG);
	writel(date, config->ioaddr + ALARM_DATE_REG);
	err = is_write_complete(config);
	if (err < 0)
		return err;

	if (alm->enabled)
		spear_rtc_enable_interrupt(config);
	else
		spear_rtc_disable_interrupt(config);

	return 0;
}
Beispiel #4
0
static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	u8 reg;

	local_irq_disable();
	rtc_wait_not_busy();
	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
	if (enabled)
		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
	else
		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
	rtc_wait_not_busy();
	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
	local_irq_enable();

	return 0;
}
Beispiel #5
0
static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	u8 reg;

	/* Much userspace code uses RTC_ALM_SET, thus "don't care" for
	 * day/month/year specifies alarms up to 24 hours in the future.
	 * So we need to handle that ... but let's ignore the "don't care"
	 * values for hours/minutes/seconds.
	 */
	if (alm->time.tm_mday <= 0
			&& alm->time.tm_mon < 0
			&& alm->time.tm_year < 0) {
		struct rtc_time tm;
		unsigned long now, then;

		omap_rtc_read_time(dev, &tm);
		rtc_tm_to_time(&tm, &now);

		alm->time.tm_mday = tm.tm_mday;
		alm->time.tm_mon = tm.tm_mon;
		alm->time.tm_year = tm.tm_year;
		rtc_tm_to_time(&alm->time, &then);

		/* sometimes the alarm wraps into tomorrow */
		if (then < now) {
			rtc_time_to_tm(now + 24 * 60 * 60, &tm);
			alm->time.tm_mday = tm.tm_mday;
			alm->time.tm_mon = tm.tm_mon;
			alm->time.tm_year = tm.tm_year;
		}
	}

	if (tm2bcd(&alm->time) < 0)
		return -EINVAL;

	local_irq_disable();
	rtc_wait_not_busy();

	rtc_write(alm->time.tm_year, OMAP_RTC_ALARM_YEARS_REG);
	rtc_write(alm->time.tm_mon, OMAP_RTC_ALARM_MONTHS_REG);
	rtc_write(alm->time.tm_mday, OMAP_RTC_ALARM_DAYS_REG);
	rtc_write(alm->time.tm_hour, OMAP_RTC_ALARM_HOURS_REG);
	rtc_write(alm->time.tm_min, OMAP_RTC_ALARM_MINUTES_REG);
	rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);

	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
	if (alm->enabled)
		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
	else
		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);

	local_irq_enable();

	return 0;
}
Beispiel #6
0
static int
omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
	u8 reg;

	switch (cmd) {
	case RTC_AIE_OFF:
	case RTC_AIE_ON:
	case RTC_UIE_OFF:
	case RTC_UIE_ON:
		break;
	default:
		return -ENOIOCTLCMD;
	}

	local_irq_disable();
	rtc_wait_not_busy();
	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
	switch (cmd) {
	/* AIE = Alarm Interrupt Enable */
	case RTC_AIE_OFF:
		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
		break;
	case RTC_AIE_ON:
		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
		break;
	/* UIE = Update Interrupt Enable (1/second) */
	case RTC_UIE_OFF:
		reg &= ~OMAP_RTC_INTERRUPTS_IT_TIMER;
		break;
	case RTC_UIE_ON:
		reg |= OMAP_RTC_INTERRUPTS_IT_TIMER;
		break;
	}
	rtc_wait_not_busy();
	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
	local_irq_enable();

	return 0;
}
Beispiel #7
0
static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct omap_rtc *rtc = dev_get_drvdata(dev);

	/* we don't report wday/yday/isdst ... */
	local_irq_disable();
	rtc_wait_not_busy(rtc);
	omap_rtc_read_time_raw(rtc, tm);
	local_irq_enable();

	bcd2tm(tm);

	return 0;
}
Beispiel #8
0
/*
 * omap_rtc_poweroff: RTC-controlled power off
 *
 * The RTC can be used to control an external PMIC via the pmic_power_en pin,
 * which can be configured to transition to OFF on ALARM2 events.
 *
 * Notes:
 * The two-second alarm offset is the shortest offset possible as the alarm
 * registers must be set before the next timer update and the offset
 * calculation is too heavy for everything to be done within a single access
 * period (~15 us).
 *
 * Called with local interrupts disabled.
 */
static void omap_rtc_power_off(void)
{
	struct omap_rtc *rtc = omap_rtc_power_off_rtc;
	struct rtc_time tm;
	unsigned long now;
	u32 val;

	rtc->type->unlock(rtc);
	/* enable pmic_power_en control */
	val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
	rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN);

	/* set alarm two seconds from now */
	omap_rtc_read_time_raw(rtc, &tm);
	bcd2tm(&tm);
	rtc_tm_to_time(&tm, &now);
	rtc_time_to_tm(now + 2, &tm);

	if (tm2bcd(&tm) < 0) {
		dev_err(&rtc->rtc->dev, "power off failed\n");
		return;
	}

	rtc_wait_not_busy(rtc);

	rtc_write(rtc, OMAP_RTC_ALARM2_SECONDS_REG, tm.tm_sec);
	rtc_write(rtc, OMAP_RTC_ALARM2_MINUTES_REG, tm.tm_min);
	rtc_write(rtc, OMAP_RTC_ALARM2_HOURS_REG, tm.tm_hour);
	rtc_write(rtc, OMAP_RTC_ALARM2_DAYS_REG, tm.tm_mday);
	rtc_write(rtc, OMAP_RTC_ALARM2_MONTHS_REG, tm.tm_mon);
	rtc_write(rtc, OMAP_RTC_ALARM2_YEARS_REG, tm.tm_year);

	/*
	 * enable ALARM2 interrupt
	 *
	 * NOTE: this fails on AM3352 if rtc_write (writeb) is used
	 */
	val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
	rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG,
			val | OMAP_RTC_INTERRUPTS_IT_ALARM2);
	rtc->type->lock(rtc);

	/*
	 * Wait for alarm to trigger (within two seconds) and external PMIC to
	 * power off the system. Add a 500 ms margin for external latencies
	 * (e.g. debounce circuits).
	 */
	mdelay(2500);
}
Beispiel #9
0
/*
 * spear_rtc_set_time - set the time
 * @dev: rtc device in use
 * @tm: holds date and time
 *
 * This function set time and date. On success it will return 0
 * otherwise -ve error is returned.
 */
static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct spear_rtc_config *config = dev_get_drvdata(dev);
	unsigned int time, date;

	if (tm2bcd(tm) < 0)
		return -EINVAL;

	rtc_wait_not_busy(config);
	time = (tm->tm_sec << SECOND_SHIFT) | (tm->tm_min << MINUTE_SHIFT) |
		(tm->tm_hour << HOUR_SHIFT);
	date = (tm->tm_mday << MDAY_SHIFT) | (tm->tm_mon << MONTH_SHIFT) |
		(tm->tm_year << YEAR_SHIFT);
	writel(time, config->ioaddr + TIME_REG);
	writel(date, config->ioaddr + DATE_REG);

	return is_write_complete(config);
}
Beispiel #10
0
static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	/* we don't report wday/yday/isdst ... */
	local_irq_disable();
	rtc_wait_not_busy();

	tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
	tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
	tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
	tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
	tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
	tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);

	local_irq_enable();

	bcd2tm(tm);
	return 0;
}
Beispiel #11
0
static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	if (tm2bcd(tm) < 0)
		return -EINVAL;
	local_irq_disable();
	rtc_wait_not_busy();

	rtc_write(tm->tm_year, OMAP_RTC_YEARS_REG);
	rtc_write(tm->tm_mon, OMAP_RTC_MONTHS_REG);
	rtc_write(tm->tm_mday, OMAP_RTC_DAYS_REG);
	rtc_write(tm->tm_hour, OMAP_RTC_HOURS_REG);
	rtc_write(tm->tm_min, OMAP_RTC_MINUTES_REG);
	rtc_write(tm->tm_sec, OMAP_RTC_SECONDS_REG);

	local_irq_enable();

	return 0;
}
Beispiel #12
0
/*
 * spear_rtc_read_time - set the time
 * @dev: rtc device in use
 * @tm: holds date and time
 *
 * This function read time and date. On success it will return 0
 * otherwise -ve error is returned.
 */
static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct spear_rtc_config *config = dev_get_drvdata(dev);
	unsigned int time, date;

	/* we don't report wday/yday/isdst ... */
	rtc_wait_not_busy(config);

	time = readl(config->ioaddr + TIME_REG);
	date = readl(config->ioaddr + DATE_REG);
	tm->tm_sec = (time >> SECOND_SHIFT) & SECOND_MASK;
	tm->tm_min = (time >> MINUTE_SHIFT) & MIN_MASK;
	tm->tm_hour = (time >> HOUR_SHIFT) & HOUR_MASK;
	tm->tm_mday = (date >> MDAY_SHIFT) & DAY_MASK;
	tm->tm_mon = (date >> MONTH_SHIFT) & MONTH_MASK;
	tm->tm_year = (date >> YEAR_SHIFT) & YEAR_MASK;

	bcd2tm(tm);
	return 0;
}
Beispiel #13
0
static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	local_irq_disable();
	rtc_wait_not_busy();

	alm->time.tm_sec = rtc_read(OMAP_RTC_ALARM_SECONDS_REG);
	alm->time.tm_min = rtc_read(OMAP_RTC_ALARM_MINUTES_REG);
	alm->time.tm_hour = rtc_read(OMAP_RTC_ALARM_HOURS_REG);
	alm->time.tm_mday = rtc_read(OMAP_RTC_ALARM_DAYS_REG);
	alm->time.tm_mon = rtc_read(OMAP_RTC_ALARM_MONTHS_REG);
	alm->time.tm_year = rtc_read(OMAP_RTC_ALARM_YEARS_REG);

	local_irq_enable();

	bcd2tm(&alm->time);
	alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
			& OMAP_RTC_INTERRUPTS_IT_ALARM);

	return 0;
}
Beispiel #14
0
/*
 * spear_rtc_read_alarm - read the alarm time
 * @dev: rtc device in use
 * @alm: holds alarm date and time
 *
 * This function read alarm time and date. On success it will return 0
 * otherwise -ve error is returned.
 */
static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	struct spear_rtc_config *config = dev_get_drvdata(dev);
	unsigned int time, date;

	rtc_wait_not_busy(config);

	time = readl(config->ioaddr + ALARM_TIME_REG);
	date = readl(config->ioaddr + ALARM_DATE_REG);
	alm->time.tm_sec = (time >> SECOND_SHIFT) & SECOND_MASK;
	alm->time.tm_min = (time >> MINUTE_SHIFT) & MIN_MASK;
	alm->time.tm_hour = (time >> HOUR_SHIFT) & HOUR_MASK;
	alm->time.tm_mday = (date >> MDAY_SHIFT) & DAY_MASK;
	alm->time.tm_mon = (date >> MONTH_SHIFT) & MONTH_MASK;
	alm->time.tm_year = (date >> YEAR_SHIFT) & YEAR_MASK;

	bcd2tm(&alm->time);
	alm->enabled = readl(config->ioaddr + CTRL_REG) & INT_ENABLE;

	return 0;
}
Beispiel #15
0
static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	struct omap_rtc *rtc = dev_get_drvdata(dev);
	u8 reg, irqwake_reg = 0;

	if (tm2bcd(&alm->time) < 0)
		return -EINVAL;

	local_irq_disable();
	rtc_wait_not_busy(rtc);

	rtc->type->unlock(rtc);
	rtc_write(rtc, OMAP_RTC_ALARM_YEARS_REG, alm->time.tm_year);
	rtc_write(rtc, OMAP_RTC_ALARM_MONTHS_REG, alm->time.tm_mon);
	rtc_write(rtc, OMAP_RTC_ALARM_DAYS_REG, alm->time.tm_mday);
	rtc_write(rtc, OMAP_RTC_ALARM_HOURS_REG, alm->time.tm_hour);
	rtc_write(rtc, OMAP_RTC_ALARM_MINUTES_REG, alm->time.tm_min);
	rtc_write(rtc, OMAP_RTC_ALARM_SECONDS_REG, alm->time.tm_sec);

	reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
	if (rtc->type->has_irqwakeen)
		irqwake_reg = rtc_read(rtc, OMAP_RTC_IRQWAKEEN);

	if (alm->enabled) {
		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
		irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
	} else {
		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
		irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
	}
	rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg);
	if (rtc->type->has_irqwakeen)
		rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg);
	rtc->type->lock(rtc);

	local_irq_enable();

	return 0;
}
Beispiel #16
0
static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct omap_rtc *rtc = dev_get_drvdata(dev);

	if (tm2bcd(tm) < 0)
		return -EINVAL;

	local_irq_disable();
	rtc_wait_not_busy(rtc);

	rtc->type->unlock(rtc);
	rtc_write(rtc, OMAP_RTC_YEARS_REG, tm->tm_year);
	rtc_write(rtc, OMAP_RTC_MONTHS_REG, tm->tm_mon);
	rtc_write(rtc, OMAP_RTC_DAYS_REG, tm->tm_mday);
	rtc_write(rtc, OMAP_RTC_HOURS_REG, tm->tm_hour);
	rtc_write(rtc, OMAP_RTC_MINUTES_REG, tm->tm_min);
	rtc_write(rtc, OMAP_RTC_SECONDS_REG, tm->tm_sec);
	rtc->type->lock(rtc);

	local_irq_enable();

	return 0;
}
Beispiel #17
0
static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	struct omap_rtc *rtc = dev_get_drvdata(dev);
	u8 interrupts;

	local_irq_disable();
	rtc_wait_not_busy(rtc);

	alm->time.tm_sec = rtc_read(rtc, OMAP_RTC_ALARM_SECONDS_REG);
	alm->time.tm_min = rtc_read(rtc, OMAP_RTC_ALARM_MINUTES_REG);
	alm->time.tm_hour = rtc_read(rtc, OMAP_RTC_ALARM_HOURS_REG);
	alm->time.tm_mday = rtc_read(rtc, OMAP_RTC_ALARM_DAYS_REG);
	alm->time.tm_mon = rtc_read(rtc, OMAP_RTC_ALARM_MONTHS_REG);
	alm->time.tm_year = rtc_read(rtc, OMAP_RTC_ALARM_YEARS_REG);

	local_irq_enable();

	bcd2tm(&alm->time);

	interrupts = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
	alm->enabled = !!(interrupts & OMAP_RTC_INTERRUPTS_IT_ALARM);

	return 0;
}