xref: /rk3399_rockchip-uboot/drivers/rtc/ftrtc010.c (revision 0284816e985ab8509371170f39501da0cdee75e4)
139ba774fSPo-Yu Chuang /*
239ba774fSPo-Yu Chuang  * Faraday FTRTC010 Real Time Clock
339ba774fSPo-Yu Chuang  *
439ba774fSPo-Yu Chuang  * (C) Copyright 2009 Faraday Technology
539ba774fSPo-Yu Chuang  * Po-Yu Chuang <ratbert@faraday-tech.com>
639ba774fSPo-Yu Chuang  *
739ba774fSPo-Yu Chuang  * This program is free software; you can redistribute it and/or modify
839ba774fSPo-Yu Chuang  * it under the terms of the GNU General Public License as published by
939ba774fSPo-Yu Chuang  * the Free Software Foundation; either version 2 of the License, or
1039ba774fSPo-Yu Chuang  * (at your option) any later version.
1139ba774fSPo-Yu Chuang  *
1239ba774fSPo-Yu Chuang  * This program is distributed in the hope that it will be useful,
1339ba774fSPo-Yu Chuang  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1439ba774fSPo-Yu Chuang  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1539ba774fSPo-Yu Chuang  * GNU General Public License for more details.
1639ba774fSPo-Yu Chuang  *
1739ba774fSPo-Yu Chuang  * You should have received a copy of the GNU General Public License
1839ba774fSPo-Yu Chuang  * along with this program; if not, write to the Free Software
1939ba774fSPo-Yu Chuang  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2039ba774fSPo-Yu Chuang  */
2139ba774fSPo-Yu Chuang 
2239ba774fSPo-Yu Chuang #include <config.h>
2339ba774fSPo-Yu Chuang #include <common.h>
2439ba774fSPo-Yu Chuang #include <rtc.h>
2539ba774fSPo-Yu Chuang #include <asm/io.h>
2639ba774fSPo-Yu Chuang 
2739ba774fSPo-Yu Chuang struct ftrtc010 {
2839ba774fSPo-Yu Chuang 	unsigned int sec;		/* 0x00 */
2939ba774fSPo-Yu Chuang 	unsigned int min;		/* 0x04 */
3039ba774fSPo-Yu Chuang 	unsigned int hour;		/* 0x08 */
3139ba774fSPo-Yu Chuang 	unsigned int day;		/* 0x0c */
3239ba774fSPo-Yu Chuang 	unsigned int alarm_sec;		/* 0x10 */
3339ba774fSPo-Yu Chuang 	unsigned int alarm_min;		/* 0x14 */
3439ba774fSPo-Yu Chuang 	unsigned int alarm_hour;	/* 0x18 */
3539ba774fSPo-Yu Chuang 	unsigned int record;		/* 0x1c */
3639ba774fSPo-Yu Chuang 	unsigned int cr;		/* 0x20 */
37*0284816eSMacpaul Lin 	unsigned int wsec;		/* 0x24 */
38*0284816eSMacpaul Lin 	unsigned int wmin;		/* 0x28 */
39*0284816eSMacpaul Lin 	unsigned int whour;		/* 0x2c */
40*0284816eSMacpaul Lin 	unsigned int wday;		/* 0x30 */
41*0284816eSMacpaul Lin 	unsigned int intr;		/* 0x34 */
42*0284816eSMacpaul Lin 	unsigned int div;		/* 0x38 */
43*0284816eSMacpaul Lin 	unsigned int rev;		/* 0x3c */
4439ba774fSPo-Yu Chuang };
4539ba774fSPo-Yu Chuang 
4639ba774fSPo-Yu Chuang /*
4739ba774fSPo-Yu Chuang  * RTC Control Register
4839ba774fSPo-Yu Chuang  */
4939ba774fSPo-Yu Chuang #define FTRTC010_CR_ENABLE		(1 << 0)
5039ba774fSPo-Yu Chuang #define FTRTC010_CR_INTERRUPT_SEC	(1 << 1)	/* per second irq */
5139ba774fSPo-Yu Chuang #define FTRTC010_CR_INTERRUPT_MIN	(1 << 2)	/* per minute irq */
5239ba774fSPo-Yu Chuang #define FTRTC010_CR_INTERRUPT_HR	(1 << 3)	/* per hour   irq */
5339ba774fSPo-Yu Chuang #define FTRTC010_CR_INTERRUPT_DAY	(1 << 4)	/* per day    irq */
5439ba774fSPo-Yu Chuang 
5539ba774fSPo-Yu Chuang static struct ftrtc010 *rtc = (struct ftrtc010 *)CONFIG_FTRTC010_BASE;
5639ba774fSPo-Yu Chuang 
5739ba774fSPo-Yu Chuang static void ftrtc010_enable(void)
5839ba774fSPo-Yu Chuang {
5939ba774fSPo-Yu Chuang 	writel(FTRTC010_CR_ENABLE, &rtc->cr);
6039ba774fSPo-Yu Chuang }
6139ba774fSPo-Yu Chuang 
6239ba774fSPo-Yu Chuang /*
6339ba774fSPo-Yu Chuang  * return current time in seconds
6439ba774fSPo-Yu Chuang  */
6539ba774fSPo-Yu Chuang static unsigned long ftrtc010_time(void)
6639ba774fSPo-Yu Chuang {
6739ba774fSPo-Yu Chuang 	unsigned long day;
6839ba774fSPo-Yu Chuang 	unsigned long hour;
6939ba774fSPo-Yu Chuang 	unsigned long minute;
7039ba774fSPo-Yu Chuang 	unsigned long second;
7139ba774fSPo-Yu Chuang 	unsigned long second2;
7239ba774fSPo-Yu Chuang 
7339ba774fSPo-Yu Chuang 	do {
7439ba774fSPo-Yu Chuang 		second	= readl(&rtc->sec);
7539ba774fSPo-Yu Chuang 		day	= readl(&rtc->day);
7639ba774fSPo-Yu Chuang 		hour	= readl(&rtc->hour);
7739ba774fSPo-Yu Chuang 		minute	= readl(&rtc->min);
7839ba774fSPo-Yu Chuang 		second2	= readl(&rtc->sec);
7939ba774fSPo-Yu Chuang 	} while (second != second2);
8039ba774fSPo-Yu Chuang 
8139ba774fSPo-Yu Chuang 	return day * 24 * 60 * 60 + hour * 60 * 60 + minute * 60 + second;
8239ba774fSPo-Yu Chuang }
8339ba774fSPo-Yu Chuang 
8439ba774fSPo-Yu Chuang /*
8539ba774fSPo-Yu Chuang  * Get the current time from the RTC
8639ba774fSPo-Yu Chuang  */
8739ba774fSPo-Yu Chuang 
8839ba774fSPo-Yu Chuang int rtc_get(struct rtc_time *tmp)
8939ba774fSPo-Yu Chuang {
9039ba774fSPo-Yu Chuang 	unsigned long now;
9139ba774fSPo-Yu Chuang 
9239ba774fSPo-Yu Chuang 	debug("%s(): record register: %x\n",
9339ba774fSPo-Yu Chuang 	      __func__, readl(&rtc->record));
9439ba774fSPo-Yu Chuang 
95*0284816eSMacpaul Lin #ifdef CONFIG_FTRTC010_PCLK
96*0284816eSMacpaul Lin 	now = (ftrtc010_time() + readl(&rtc->record)) / RTC_DIV_COUNT;
97*0284816eSMacpaul Lin #else /* CONFIG_FTRTC010_EXTCLK */
9839ba774fSPo-Yu Chuang 	now = ftrtc010_time() + readl(&rtc->record);
99*0284816eSMacpaul Lin #endif
10039ba774fSPo-Yu Chuang 
10139ba774fSPo-Yu Chuang 	to_tm(now, tmp);
10239ba774fSPo-Yu Chuang 
10339ba774fSPo-Yu Chuang 	return 0;
10439ba774fSPo-Yu Chuang }
10539ba774fSPo-Yu Chuang 
10639ba774fSPo-Yu Chuang /*
10739ba774fSPo-Yu Chuang  * Set the RTC
10839ba774fSPo-Yu Chuang  */
10939ba774fSPo-Yu Chuang int rtc_set(struct rtc_time *tmp)
11039ba774fSPo-Yu Chuang {
11139ba774fSPo-Yu Chuang 	unsigned long new;
11239ba774fSPo-Yu Chuang 	unsigned long now;
11339ba774fSPo-Yu Chuang 
11439ba774fSPo-Yu Chuang 	debug("%s(): DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
11539ba774fSPo-Yu Chuang 	      __func__,
11639ba774fSPo-Yu Chuang 	      tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
11739ba774fSPo-Yu Chuang 	      tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
11839ba774fSPo-Yu Chuang 
11939ba774fSPo-Yu Chuang 	new = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_hour,
12039ba774fSPo-Yu Chuang 		     tmp->tm_min, tmp->tm_sec);
12139ba774fSPo-Yu Chuang 
12239ba774fSPo-Yu Chuang 	now = ftrtc010_time();
12339ba774fSPo-Yu Chuang 
12439ba774fSPo-Yu Chuang 	debug("%s(): write %lx to record register\n", __func__, new - now);
12539ba774fSPo-Yu Chuang 
12639ba774fSPo-Yu Chuang 	writel(new - now, &rtc->record);
12739ba774fSPo-Yu Chuang 
12839ba774fSPo-Yu Chuang 	return 0;
12939ba774fSPo-Yu Chuang }
13039ba774fSPo-Yu Chuang 
13139ba774fSPo-Yu Chuang void rtc_reset(void)
13239ba774fSPo-Yu Chuang {
13339ba774fSPo-Yu Chuang 	debug("%s()\n", __func__);
13439ba774fSPo-Yu Chuang 	ftrtc010_enable();
13539ba774fSPo-Yu Chuang }
136