xref: /openbmc/u-boot/drivers/rtc/mxsrtc.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2aa711b11SMarek Vasut /*
3aa711b11SMarek Vasut  * Freescale i.MX28 RTC Driver
4aa711b11SMarek Vasut  *
5aa711b11SMarek Vasut  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
6aa711b11SMarek Vasut  * on behalf of DENX Software Engineering GmbH
7aa711b11SMarek Vasut  */
8aa711b11SMarek Vasut 
9aa711b11SMarek Vasut #include <common.h>
10aa711b11SMarek Vasut #include <rtc.h>
11aa711b11SMarek Vasut #include <asm/io.h>
12aa711b11SMarek Vasut #include <asm/arch/imx-regs.h>
13aa711b11SMarek Vasut #include <asm/arch/sys_proto.h>
14aa711b11SMarek Vasut 
15aa711b11SMarek Vasut #define	MXS_RTC_MAX_TIMEOUT	1000000
16aa711b11SMarek Vasut 
17aa711b11SMarek Vasut /* Set time in seconds since 1970-01-01 */
mxs_rtc_set_time(uint32_t secs)18aa711b11SMarek Vasut int mxs_rtc_set_time(uint32_t secs)
19aa711b11SMarek Vasut {
209c471142SOtavio Salvador 	struct mxs_rtc_regs *rtc_regs = (struct mxs_rtc_regs *)MXS_RTC_BASE;
21aa711b11SMarek Vasut 	int ret;
22aa711b11SMarek Vasut 
23aa711b11SMarek Vasut 	writel(secs, &rtc_regs->hw_rtc_seconds);
24aa711b11SMarek Vasut 
25aa711b11SMarek Vasut 	/*
26aa711b11SMarek Vasut 	 * The 0x80 here means seconds were copied to analog. This information
27aa711b11SMarek Vasut 	 * is taken from the linux kernel driver for the STMP37xx RTC since
28aa711b11SMarek Vasut 	 * documentation doesn't mention it.
29aa711b11SMarek Vasut 	 */
30fa7a51cbSOtavio Salvador 	ret = mxs_wait_mask_clr(&rtc_regs->hw_rtc_stat_reg,
31aa711b11SMarek Vasut 		0x80 << RTC_STAT_STALE_REGS_OFFSET, MXS_RTC_MAX_TIMEOUT);
32aa711b11SMarek Vasut 
33aa711b11SMarek Vasut 	if (ret)
34aa711b11SMarek Vasut 		printf("MXS RTC: Timeout waiting for update\n");
35aa711b11SMarek Vasut 
36aa711b11SMarek Vasut 	return ret;
37aa711b11SMarek Vasut }
38aa711b11SMarek Vasut 
rtc_get(struct rtc_time * time)39aa711b11SMarek Vasut int rtc_get(struct rtc_time *time)
40aa711b11SMarek Vasut {
419c471142SOtavio Salvador 	struct mxs_rtc_regs *rtc_regs = (struct mxs_rtc_regs *)MXS_RTC_BASE;
42aa711b11SMarek Vasut 	uint32_t secs;
43aa711b11SMarek Vasut 
44aa711b11SMarek Vasut 	secs = readl(&rtc_regs->hw_rtc_seconds);
459f9276c3SSimon Glass 	rtc_to_tm(secs, time);
46aa711b11SMarek Vasut 
47aa711b11SMarek Vasut 	return 0;
48aa711b11SMarek Vasut }
49aa711b11SMarek Vasut 
rtc_set(struct rtc_time * time)50aa711b11SMarek Vasut int rtc_set(struct rtc_time *time)
51aa711b11SMarek Vasut {
52aa711b11SMarek Vasut 	uint32_t secs;
53aa711b11SMarek Vasut 
5471420983SSimon Glass 	secs = rtc_mktime(time);
55aa711b11SMarek Vasut 
56aa711b11SMarek Vasut 	return mxs_rtc_set_time(secs);
57aa711b11SMarek Vasut }
58aa711b11SMarek Vasut 
rtc_reset(void)59aa711b11SMarek Vasut void rtc_reset(void)
60aa711b11SMarek Vasut {
619c471142SOtavio Salvador 	struct mxs_rtc_regs *rtc_regs = (struct mxs_rtc_regs *)MXS_RTC_BASE;
62aa711b11SMarek Vasut 	int ret;
63aa711b11SMarek Vasut 
64aa711b11SMarek Vasut 	/* Set time to 1970-01-01 */
65aa711b11SMarek Vasut 	mxs_rtc_set_time(0);
66aa711b11SMarek Vasut 
67aa711b11SMarek Vasut 	/* Reset the RTC block */
68fa7a51cbSOtavio Salvador 	ret = mxs_reset_block(&rtc_regs->hw_rtc_ctrl_reg);
69aa711b11SMarek Vasut 	if (ret)
70aa711b11SMarek Vasut 		printf("MXS RTC: Block reset timeout\n");
71aa711b11SMarek Vasut }
72