Exemple #1
0
static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
    u32 status;
    unsigned long read_time;
    struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);

    status = readl(xrtcdev->reg_base + RTC_INT_STS);

    if (status & RTC_INT_SEC) {
        /*
         * RTC has updated the CURRENT_TIME with the time written into
         * SET_TIME_WRITE register.
         */
        rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_CUR_TM), tm);
    } else {
        /*
         * Time written in SET_TIME_WRITE has not yet updated into
         * the seconds read register, so read the time from the
         * SET_TIME_WRITE instead of CURRENT_TIME register.
         * Since we add +1 sec while writing, we need to -1 sec while
         * reading.
         */
        read_time = readl(xrtcdev->reg_base + RTC_SET_TM_RD) - 1;
        rtc_time64_to_tm(read_time, tm);
    }

    return rtc_valid_tm(tm);
}
Exemple #2
0
static void gregorian_to_rockchip(struct rtc_time *tm)
{
	time64_t extra_days = nov2dec_transitions(tm);
	time64_t time = rtc_tm_to_time64(tm);
	rtc_time64_to_tm(time - extra_days * 86400, tm);

	/* Compensate if we went back over Nov 31st (will work up to 2381) */
	if (nov2dec_transitions(tm) < extra_days) {
		if (tm->tm_mon + 1 == 11)
			tm->tm_mday++;	/* This may result in 31! */
		else
			rtc_time64_to_tm(time - (extra_days - 1) * 86400, tm);
	}
}
Exemple #3
0
/*
 * Read alarm time and date in RTC
 */
static int wm831x_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev);
	int ret;
	u16 data[2];
	u32 time;

	ret = wm831x_bulk_read(wm831x_rtc->wm831x, WM831X_RTC_ALARM_1,
			       2, data);
	if (ret != 0) {
		dev_err(dev, "Failed to read alarm time: %d\n", ret);
		return ret;
	}

	time = (data[0] << 16) | data[1];

	rtc_time64_to_tm(time, &alrm->time);

	ret = wm831x_reg_read(wm831x_rtc->wm831x, WM831X_RTC_CONTROL);
	if (ret < 0) {
		dev_err(dev, "Failed to read RTC control: %d\n", ret);
		return ret;
	}

	if (ret & WM831X_RTC_ALM_ENA)
		alrm->enabled = 1;
	else
		alrm->enabled = 0;

	return 0;
}
Exemple #4
0
static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);

	rtc_time64_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time);
	return 0;
}
Exemple #5
0
/* Read alarm time from RTC. */
static int cros_ec_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
	struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
	int ret;
	u32 current_time, alarm_offset;

	/*
	 * The EC host command for getting the alarm is relative (i.e. 5
	 * seconds from now) whereas rtc_wkalrm is absolute. Get the current
	 * RTC time first so we can calculate the relative time.
	 */
	ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
	if (ret < 0) {
		dev_err(dev, "error getting time: %d\n", ret);
		return ret;
	}

	ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_ALARM, &alarm_offset);
	if (ret < 0) {
		dev_err(dev, "error getting alarm: %d\n", ret);
		return ret;
	}

	rtc_time64_to_tm(current_time + alarm_offset, &alrm->time);

	return 0;
}
Exemple #6
0
static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
	unsigned int seconds, days1, days2;

	if (!priv->valid)
		return -ENODATA;

	do {
		int ret;

		ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1);
		if (ret)
			return ret;

		ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds);
		if (ret)
			return ret;

		ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2);
		if (ret)
			return ret;
	} while (days1 != days2);

	rtc_time64_to_tm((time64_t)days1 * SEC_PER_DAY + seconds, tm);

	return 0;
}
Exemple #7
0
static int test_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct rtc_test_data *rtd = dev_get_drvdata(dev);

	rtc_time64_to_tm(ktime_get_real_seconds() + rtd->offset, tm);

	return 0;
}
Exemple #8
0
static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
    struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);

    rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_ALRM), &alrm->time);
    alrm->enabled = readl(xrtcdev->reg_base + RTC_INT_MASK) & RTC_INT_ALRM;

    return 0;
}
Exemple #9
0
static int ds2404_read_time(struct device *dev, struct rtc_time *dt)
{
	unsigned long time = 0;

	ds2404_read_memory(dev, 0x203, 4, (u8 *)&time);
	time = le32_to_cpu(time);

	rtc_time64_to_tm(time, dt);
	return 0;
}
Exemple #10
0
void mpc8xx_get_rtc_time(struct rtc_time *tm)
{
	unsigned long data;
	sit8xx_t __iomem *sys_tmr = immr_map(im_sit);

	/* Get time from the RTC. */
	data = in_be32(&sys_tmr->sit_rtc);
	rtc_time64_to_tm(data, tm);
	immr_unmap(sys_tmr);
	return;
}
Exemple #11
0
/* Time read/write */
static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
	int ret;
	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);

	ret = stmp3xxx_wait_time(rtc_data);
	if (ret)
		return ret;

	rtc_time64_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);
	return 0;
}
Exemple #12
0
/*
 * Convert ktime to rtc_time
 */
struct rtc_time rtc_ktime_to_tm(ktime_t kt)
{
	struct timespec64 ts;
	struct rtc_time ret;

	ts = ktime_to_timespec64(kt);
	/* Round up any ns */
	if (ts.tv_nsec)
		ts.tv_sec++;
	rtc_time64_to_tm(ts.tv_sec, &ret);
	return ret;
}
Exemple #13
0
static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
{
	struct pdc_tod tod_data;

	memset(tm, 0, sizeof(*tm));
	if (pdc_tod_read(&tod_data) < 0)
		return -EOPNOTSUPP;

	/* we treat tod_sec as unsigned, so this can work until year 2106 */
	rtc_time64_to_tm(tod_data.tod_sec, tm);
	return rtc_valid_tm(tm);
}
Exemple #14
0
static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_test_data *rtd = dev_get_drvdata(dev);
	time64_t alarm;

	alarm = (rtd->alarm.expires - jiffies) / HZ;
	alarm += ktime_get_real_seconds() + rtd->offset;

	rtc_time64_to_tm(alarm, &alrm->time);
	alrm->enabled = rtd->alarm_en;

	return 0;
}
Exemple #15
0
static int dm355evm_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	union evm_time	time;
	int		status;
	int		tries = 0;

	do {
		/*
		 * Read LSB(0) to MSB(3) bytes.  Defend against the counter
		 * rolling over by re-reading until the value is stable,
		 * and assuming the four reads take at most a few seconds.
		 */
		status = dm355evm_msp_read(DM355EVM_MSP_RTC_0);
		if (status < 0)
			return status;
		if (tries && time.bytes[0] == status)
			break;
		time.bytes[0] = status;

		status = dm355evm_msp_read(DM355EVM_MSP_RTC_1);
		if (status < 0)
			return status;
		if (tries && time.bytes[1] == status)
			break;
		time.bytes[1] = status;

		status = dm355evm_msp_read(DM355EVM_MSP_RTC_2);
		if (status < 0)
			return status;
		if (tries && time.bytes[2] == status)
			break;
		time.bytes[2] = status;

		status = dm355evm_msp_read(DM355EVM_MSP_RTC_3);
		if (status < 0)
			return status;
		if (tries && time.bytes[3] == status)
			break;
		time.bytes[3] = status;

	} while (++tries < 5);

	dev_dbg(dev, "read timestamp %08x\n", time.value);

	rtc_time64_to_tm(le32_to_cpu(time.value), tm);
	return 0;
}
Exemple #16
0
/*
 * Read current time and date in RTC
 */
static int wm831x_rtc_readtime(struct device *dev, struct rtc_time *tm)
{
	struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev);
	struct wm831x *wm831x = wm831x_rtc->wm831x;
	u16 time1[2], time2[2];
	int ret;
	int count = 0;

	/* Has the RTC been programmed? */
	ret = wm831x_reg_read(wm831x, WM831X_RTC_CONTROL);
	if (ret < 0) {
		dev_err(dev, "Failed to read RTC control: %d\n", ret);
		return ret;
	}
	if (!(ret & WM831X_RTC_VALID)) {
		dev_dbg(dev, "RTC not yet configured\n");
		return -EINVAL;
	}

	/* Read twice to make sure we don't read a corrupt, partially
	 * incremented, value.
	 */
	do {
		ret = wm831x_bulk_read(wm831x, WM831X_RTC_TIME_1,
				       2, time1);
		if (ret != 0)
			continue;

		ret = wm831x_bulk_read(wm831x, WM831X_RTC_TIME_1,
				       2, time2);
		if (ret != 0)
			continue;

		if (memcmp(time1, time2, sizeof(time1)) == 0) {
			u32 time = (time1[0] << 16) | time1[1];

			rtc_time64_to_tm(time, tm);
			return 0;
		}

	} while (++count < WM831X_GET_TIME_RETRIES);

	dev_err(dev, "Timed out reading current time\n");

	return -EIO;
}
Exemple #17
0
/* Read the current time from the EC. */
static int cros_ec_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
	struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
	int ret;
	u32 time;

	ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &time);
	if (ret) {
		dev_err(dev, "error getting time: %d\n", ret);
		return ret;
	}

	rtc_time64_to_tm(time, tm);

	return 0;
}
Exemple #18
0
static int cmos_aie_poweroff(struct device *dev)
{
	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
	struct rtc_time now;
	time64_t t_now;
	int retval = 0;
	unsigned char rtc_control;

	if (!cmos->alarm_expires)
		return -EINVAL;

	spin_lock_irq(&rtc_lock);
	rtc_control = CMOS_READ(RTC_CONTROL);
	spin_unlock_irq(&rtc_lock);

	/* We only care about the situation where AIE is disabled. */
	if (rtc_control & RTC_AIE)
		return -EBUSY;

	cmos_read_time(dev, &now);
	t_now = rtc_tm_to_time64(&now);

	/*
	 * When enabling "RTC wake-up" in BIOS setup, the machine reboots
	 * automatically right after shutdown on some buggy boxes.
	 * This automatic rebooting issue won't happen when the alarm
	 * time is larger than now+1 seconds.
	 *
	 * If the alarm time is equal to now+1 seconds, the issue can be
	 * prevented by cancelling the alarm.
	 */
	if (cmos->alarm_expires == t_now + 1) {
		struct rtc_wkalrm alarm;

		/* Cancel the AIE timer by configuring the past time. */
		rtc_time64_to_tm(t_now - 1, &alarm.time);
		alarm.enabled = 0;
		retval = cmos_set_alarm(dev, &alarm);
	} else if (cmos->alarm_expires > t_now + 1) {
		retval = -EBUSY;
	}

	return retval;
}
Exemple #19
0
static void rtc_subtract_offset(struct rtc_device *rtc, struct rtc_time *tm)
{
	time64_t secs;

	if (!rtc->offset_secs)
		return;

	secs = rtc_tm_to_time64(tm);

	/*
	 * If the setting time values are in the valid range of RTC hardware
	 * device, then no need to subtract the offset when setting time to RTC
	 * device. Otherwise we need to subtract the offset to make the time
	 * values are valid for RTC hardware device.
	 */
	if (secs >= rtc->range_min && secs <= rtc->range_max)
		return;

	rtc_time64_to_tm(secs - rtc->offset_secs, tm);
}
Exemple #20
0
static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
	struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
	unsigned seconds, days;
	time64_t s1970;
	int enabled, pending;
	int ret;

	mc13xxx_lock(priv->mc13xxx);

	ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds);
	if (unlikely(ret))
		goto out;
	if (seconds >= SEC_PER_DAY) {
		ret = -ENODATA;
		goto out;
	}

	ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days);
	if (unlikely(ret))
		goto out;

	ret = mc13xxx_irq_status(priv->mc13xxx, MC13XXX_IRQ_TODA,
			&enabled, &pending);

out:
	mc13xxx_unlock(priv->mc13xxx);

	if (ret)
		return ret;

	alarm->enabled = enabled;
	alarm->pending = pending;

	s1970 = (time64_t)days * SEC_PER_DAY + seconds;

	rtc_time64_to_tm(s1970, &alarm->time);
	dev_dbg(dev, "%s: %lld\n", __func__, (long long)s1970);

	return 0;
}
Exemple #21
0
static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct imx_sc_msg_timer_get_rtc_time msg;
	struct imx_sc_rpc_msg *hdr = &msg.hdr;
	int ret;

	hdr->ver = IMX_SC_RPC_VERSION;
	hdr->svc = IMX_SC_RPC_SVC_TIMER;
	hdr->func = IMX_SC_TIMER_FUNC_GET_RTC_SEC1970;
	hdr->size = 1;

	ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true);
	if (ret) {
		dev_err(dev, "read rtc time failed, ret %d\n", ret);
		return ret;
	}

	rtc_time64_to_tm(msg.time, tm);

	return 0;
}
Exemple #22
0
static void rtc_add_offset(struct rtc_device *rtc, struct rtc_time *tm)
{
	time64_t secs;

	if (!rtc->offset_secs)
		return;

	secs = rtc_tm_to_time64(tm);

	/*
	 * Since the reading time values from RTC device are always in the RTC
	 * original valid range, but we need to skip the overlapped region
	 * between expanded range and original range, which is no need to add
	 * the offset.
	 */
	if ((rtc->start_secs > rtc->range_min && secs >= rtc->start_secs) ||
	    (rtc->start_secs < rtc->range_min &&
	     secs <= (rtc->start_secs + rtc->range_max - rtc->range_min)))
		return;

	rtc_time64_to_tm(secs + rtc->offset_secs, tm);
}
Exemple #23
0
static int st_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct st_rtc *rtc = dev_get_drvdata(dev);
	unsigned long lpt_lsb, lpt_msb;
	unsigned long long lpt;
	unsigned long flags;

	spin_lock_irqsave(&rtc->lock, flags);

	do {
		lpt_msb = readl_relaxed(rtc->ioaddr + LPC_LPT_MSB_OFF);
		lpt_lsb = readl_relaxed(rtc->ioaddr + LPC_LPT_LSB_OFF);
	} while (readl_relaxed(rtc->ioaddr + LPC_LPT_MSB_OFF) != lpt_msb);

	spin_unlock_irqrestore(&rtc->lock, flags);

	lpt = ((unsigned long long)lpt_msb << 32) | lpt_lsb;
	do_div(lpt, rtc->clkrate);
	rtc_time64_to_tm(lpt, tm);

	return 0;
}
Exemple #24
0
static int test_rtc_read_time(struct device *dev,
	struct rtc_time *tm)
{
	rtc_time64_to_tm(ktime_get_real_seconds(), tm);
	return 0;
}
Exemple #25
0
static ssize_t
wakealarm_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t n)
{
	ssize_t retval;
	time64_t now, alarm;
	time64_t push = 0;
	struct rtc_wkalrm alm;
	struct rtc_device *rtc = to_rtc_device(dev);
	const char *buf_ptr;
	int adjust = 0;

	/* Only request alarms that trigger in the future.  Disable them
	 * by writing another time, e.g. 0 meaning Jan 1 1970 UTC.
	 */
	retval = rtc_read_time(rtc, &alm.time);
	if (retval < 0)
		return retval;
	now = rtc_tm_to_time64(&alm.time);

	buf_ptr = buf;
	if (*buf_ptr == '+') {
		buf_ptr++;
		if (*buf_ptr == '=') {
			buf_ptr++;
			push = 1;
		} else
			adjust = 1;
	}
	retval = kstrtos64(buf_ptr, 0, &alarm);
	if (retval)
		return retval;
	if (adjust) {
		alarm += now;
	}
	if (alarm > now || push) {
		/* Avoid accidentally clobbering active alarms; we can't
		 * entirely prevent that here, without even the minimal
		 * locking from the /dev/rtcN api.
		 */
		retval = rtc_read_alarm(rtc, &alm);
		if (retval < 0)
			return retval;
		if (alm.enabled) {
			if (push) {
				push = rtc_tm_to_time64(&alm.time);
				alarm += push;
			} else
				return -EBUSY;
		} else if (push)
			return -EINVAL;
		alm.enabled = 1;
	} else {
		alm.enabled = 0;

		/* Provide a valid future alarm time.  Linux isn't EFI,
		 * this time won't be ignored when disabling the alarm.
		 */
		alarm = now + 300;
	}
	rtc_time64_to_tm(alarm, &alm.time);

	retval = rtc_set_alarm(rtc, &alm);
	return (retval < 0) ? retval : n;
}
Exemple #26
0
int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
	int err;
	struct rtc_time before, now;
	int first_time = 1;
	time64_t t_now, t_alm;
	enum { none, day, month, year } missing = none;
	unsigned days;

	/* The lower level RTC driver may return -1 in some fields,
	 * creating invalid alarm->time values, for reasons like:
	 *
	 *   - The hardware may not be capable of filling them in;
	 *     many alarms match only on time-of-day fields, not
	 *     day/month/year calendar data.
	 *
	 *   - Some hardware uses illegal values as "wildcard" match
	 *     values, which non-Linux firmware (like a BIOS) may try
	 *     to set up as e.g. "alarm 15 minutes after each hour".
	 *     Linux uses only oneshot alarms.
	 *
	 * When we see that here, we deal with it by using values from
	 * a current RTC timestamp for any missing (-1) values.  The
	 * RTC driver prevents "periodic alarm" modes.
	 *
	 * But this can be racey, because some fields of the RTC timestamp
	 * may have wrapped in the interval since we read the RTC alarm,
	 * which would lead to us inserting inconsistent values in place
	 * of the -1 fields.
	 *
	 * Reading the alarm and timestamp in the reverse sequence
	 * would have the same race condition, and not solve the issue.
	 *
	 * So, we must first read the RTC timestamp,
	 * then read the RTC alarm value,
	 * and then read a second RTC timestamp.
	 *
	 * If any fields of the second timestamp have changed
	 * when compared with the first timestamp, then we know
	 * our timestamp may be inconsistent with that used by
	 * the low-level rtc_read_alarm_internal() function.
	 *
	 * So, when the two timestamps disagree, we just loop and do
	 * the process again to get a fully consistent set of values.
	 *
	 * This could all instead be done in the lower level driver,
	 * but since more than one lower level RTC implementation needs it,
	 * then it's probably best best to do it here instead of there..
	 */

	/* Get the "before" timestamp */
	err = rtc_read_time(rtc, &before);
	if (err < 0)
		return err;
	do {
		if (!first_time)
			memcpy(&before, &now, sizeof(struct rtc_time));
		first_time = 0;

		/* get the RTC alarm values, which may be incomplete */
		err = rtc_read_alarm_internal(rtc, alarm);
		if (err)
			return err;

		/* full-function RTCs won't have such missing fields */
		if (rtc_valid_tm(&alarm->time) == 0) {
			rtc_add_offset(rtc, &alarm->time);
			return 0;
		}

		/* get the "after" timestamp, to detect wrapped fields */
		err = rtc_read_time(rtc, &now);
		if (err < 0)
			return err;

		/* note that tm_sec is a "don't care" value here: */
	} while (   before.tm_min   != now.tm_min
		 || before.tm_hour  != now.tm_hour
		 || before.tm_mon   != now.tm_mon
		 || before.tm_year  != now.tm_year);

	/* Fill in the missing alarm fields using the timestamp; we
	 * know there's at least one since alarm->time is invalid.
	 */
	if (alarm->time.tm_sec == -1)
		alarm->time.tm_sec = now.tm_sec;
	if (alarm->time.tm_min == -1)
		alarm->time.tm_min = now.tm_min;
	if (alarm->time.tm_hour == -1)
		alarm->time.tm_hour = now.tm_hour;

	/* For simplicity, only support date rollover for now */
	if (alarm->time.tm_mday < 1 || alarm->time.tm_mday > 31) {
		alarm->time.tm_mday = now.tm_mday;
		missing = day;
	}
	if ((unsigned)alarm->time.tm_mon >= 12) {
		alarm->time.tm_mon = now.tm_mon;
		if (missing == none)
			missing = month;
	}
	if (alarm->time.tm_year == -1) {
		alarm->time.tm_year = now.tm_year;
		if (missing == none)
			missing = year;
	}

	/* Can't proceed if alarm is still invalid after replacing
	 * missing fields.
	 */
	err = rtc_valid_tm(&alarm->time);
	if (err)
		goto done;

	/* with luck, no rollover is needed */
	t_now = rtc_tm_to_time64(&now);
	t_alm = rtc_tm_to_time64(&alarm->time);
	if (t_now < t_alm)
		goto done;

	switch (missing) {

	/* 24 hour rollover ... if it's now 10am Monday, an alarm that
	 * that will trigger at 5am will do so at 5am Tuesday, which
	 * could also be in the next month or year.  This is a common
	 * case, especially for PCs.
	 */
	case day:
		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day");
		t_alm += 24 * 60 * 60;
		rtc_time64_to_tm(t_alm, &alarm->time);
		break;

	/* Month rollover ... if it's the 31th, an alarm on the 3rd will
	 * be next month.  An alarm matching on the 30th, 29th, or 28th
	 * may end up in the month after that!  Many newer PCs support
	 * this type of alarm.
	 */
	case month:
		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month");
		do {
			if (alarm->time.tm_mon < 11)
				alarm->time.tm_mon++;
			else {
				alarm->time.tm_mon = 0;
				alarm->time.tm_year++;
			}
			days = rtc_month_days(alarm->time.tm_mon,
					alarm->time.tm_year);
		} while (days < alarm->time.tm_mday);
		break;

	/* Year rollover ... easy except for leap years! */
	case year:
		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
		do {
			alarm->time.tm_year++;
		} while (!is_leap_year(alarm->time.tm_year + 1900)
			&& rtc_valid_tm(&alarm->time) != 0);
		break;

	default:
		dev_warn(&rtc->dev, "alarm rollover not handled\n");
	}

	err = rtc_valid_tm(&alarm->time);

done:
	if (err) {
		dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n",
			alarm->time.tm_year + 1900, alarm->time.tm_mon + 1,
			alarm->time.tm_mday, alarm->time.tm_hour, alarm->time.tm_min,
			alarm->time.tm_sec);
	}

	return err;
}
Exemple #27
0
static void rockchip_to_gregorian(struct rtc_time *tm)
{
	/* If it's Nov 31st, rtc_tm_to_time64() will count that like Dec 1st */
	time64_t time = rtc_tm_to_time64(tm);
	rtc_time64_to_tm(time + nov2dec_transitions(tm) * 86400, tm);
}