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 *
71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
839ba774fSPo-Yu Chuang */
939ba774fSPo-Yu Chuang
1039ba774fSPo-Yu Chuang #include <config.h>
1139ba774fSPo-Yu Chuang #include <common.h>
1239ba774fSPo-Yu Chuang #include <rtc.h>
1339ba774fSPo-Yu Chuang #include <asm/io.h>
1439ba774fSPo-Yu Chuang
1539ba774fSPo-Yu Chuang struct ftrtc010 {
1639ba774fSPo-Yu Chuang unsigned int sec; /* 0x00 */
1739ba774fSPo-Yu Chuang unsigned int min; /* 0x04 */
1839ba774fSPo-Yu Chuang unsigned int hour; /* 0x08 */
1939ba774fSPo-Yu Chuang unsigned int day; /* 0x0c */
2039ba774fSPo-Yu Chuang unsigned int alarm_sec; /* 0x10 */
2139ba774fSPo-Yu Chuang unsigned int alarm_min; /* 0x14 */
2239ba774fSPo-Yu Chuang unsigned int alarm_hour; /* 0x18 */
2339ba774fSPo-Yu Chuang unsigned int record; /* 0x1c */
2439ba774fSPo-Yu Chuang unsigned int cr; /* 0x20 */
250284816eSMacpaul Lin unsigned int wsec; /* 0x24 */
260284816eSMacpaul Lin unsigned int wmin; /* 0x28 */
270284816eSMacpaul Lin unsigned int whour; /* 0x2c */
280284816eSMacpaul Lin unsigned int wday; /* 0x30 */
290284816eSMacpaul Lin unsigned int intr; /* 0x34 */
300284816eSMacpaul Lin unsigned int div; /* 0x38 */
310284816eSMacpaul Lin unsigned int rev; /* 0x3c */
3239ba774fSPo-Yu Chuang };
3339ba774fSPo-Yu Chuang
3439ba774fSPo-Yu Chuang /*
3539ba774fSPo-Yu Chuang * RTC Control Register
3639ba774fSPo-Yu Chuang */
3739ba774fSPo-Yu Chuang #define FTRTC010_CR_ENABLE (1 << 0)
3839ba774fSPo-Yu Chuang #define FTRTC010_CR_INTERRUPT_SEC (1 << 1) /* per second irq */
3939ba774fSPo-Yu Chuang #define FTRTC010_CR_INTERRUPT_MIN (1 << 2) /* per minute irq */
4039ba774fSPo-Yu Chuang #define FTRTC010_CR_INTERRUPT_HR (1 << 3) /* per hour irq */
4139ba774fSPo-Yu Chuang #define FTRTC010_CR_INTERRUPT_DAY (1 << 4) /* per day irq */
4239ba774fSPo-Yu Chuang
4339ba774fSPo-Yu Chuang static struct ftrtc010 *rtc = (struct ftrtc010 *)CONFIG_FTRTC010_BASE;
4439ba774fSPo-Yu Chuang
ftrtc010_enable(void)4539ba774fSPo-Yu Chuang static void ftrtc010_enable(void)
4639ba774fSPo-Yu Chuang {
4739ba774fSPo-Yu Chuang writel(FTRTC010_CR_ENABLE, &rtc->cr);
4839ba774fSPo-Yu Chuang }
4939ba774fSPo-Yu Chuang
5039ba774fSPo-Yu Chuang /*
5139ba774fSPo-Yu Chuang * return current time in seconds
5239ba774fSPo-Yu Chuang */
ftrtc010_time(void)5339ba774fSPo-Yu Chuang static unsigned long ftrtc010_time(void)
5439ba774fSPo-Yu Chuang {
5539ba774fSPo-Yu Chuang unsigned long day;
5639ba774fSPo-Yu Chuang unsigned long hour;
5739ba774fSPo-Yu Chuang unsigned long minute;
5839ba774fSPo-Yu Chuang unsigned long second;
5939ba774fSPo-Yu Chuang unsigned long second2;
6039ba774fSPo-Yu Chuang
6139ba774fSPo-Yu Chuang do {
6239ba774fSPo-Yu Chuang second = readl(&rtc->sec);
6339ba774fSPo-Yu Chuang day = readl(&rtc->day);
6439ba774fSPo-Yu Chuang hour = readl(&rtc->hour);
6539ba774fSPo-Yu Chuang minute = readl(&rtc->min);
6639ba774fSPo-Yu Chuang second2 = readl(&rtc->sec);
6739ba774fSPo-Yu Chuang } while (second != second2);
6839ba774fSPo-Yu Chuang
6939ba774fSPo-Yu Chuang return day * 24 * 60 * 60 + hour * 60 * 60 + minute * 60 + second;
7039ba774fSPo-Yu Chuang }
7139ba774fSPo-Yu Chuang
7239ba774fSPo-Yu Chuang /*
7339ba774fSPo-Yu Chuang * Get the current time from the RTC
7439ba774fSPo-Yu Chuang */
7539ba774fSPo-Yu Chuang
rtc_get(struct rtc_time * tmp)7639ba774fSPo-Yu Chuang int rtc_get(struct rtc_time *tmp)
7739ba774fSPo-Yu Chuang {
7839ba774fSPo-Yu Chuang unsigned long now;
7939ba774fSPo-Yu Chuang
8039ba774fSPo-Yu Chuang debug("%s(): record register: %x\n",
8139ba774fSPo-Yu Chuang __func__, readl(&rtc->record));
8239ba774fSPo-Yu Chuang
830284816eSMacpaul Lin #ifdef CONFIG_FTRTC010_PCLK
840284816eSMacpaul Lin now = (ftrtc010_time() + readl(&rtc->record)) / RTC_DIV_COUNT;
850284816eSMacpaul Lin #else /* CONFIG_FTRTC010_EXTCLK */
8639ba774fSPo-Yu Chuang now = ftrtc010_time() + readl(&rtc->record);
870284816eSMacpaul Lin #endif
8839ba774fSPo-Yu Chuang
899f9276c3SSimon Glass rtc_to_tm(now, tmp);
9039ba774fSPo-Yu Chuang
9139ba774fSPo-Yu Chuang return 0;
9239ba774fSPo-Yu Chuang }
9339ba774fSPo-Yu Chuang
9439ba774fSPo-Yu Chuang /*
9539ba774fSPo-Yu Chuang * Set the RTC
9639ba774fSPo-Yu Chuang */
rtc_set(struct rtc_time * tmp)9739ba774fSPo-Yu Chuang int rtc_set(struct rtc_time *tmp)
9839ba774fSPo-Yu Chuang {
9939ba774fSPo-Yu Chuang unsigned long new;
10039ba774fSPo-Yu Chuang unsigned long now;
10139ba774fSPo-Yu Chuang
10239ba774fSPo-Yu Chuang debug("%s(): DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
10339ba774fSPo-Yu Chuang __func__,
10439ba774fSPo-Yu Chuang tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
10539ba774fSPo-Yu Chuang tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
10639ba774fSPo-Yu Chuang
107*71420983SSimon Glass new = rtc_mktime(tmp);
10839ba774fSPo-Yu Chuang
10939ba774fSPo-Yu Chuang now = ftrtc010_time();
11039ba774fSPo-Yu Chuang
11139ba774fSPo-Yu Chuang debug("%s(): write %lx to record register\n", __func__, new - now);
11239ba774fSPo-Yu Chuang
11339ba774fSPo-Yu Chuang writel(new - now, &rtc->record);
11439ba774fSPo-Yu Chuang
11539ba774fSPo-Yu Chuang return 0;
11639ba774fSPo-Yu Chuang }
11739ba774fSPo-Yu Chuang
rtc_reset(void)11839ba774fSPo-Yu Chuang void rtc_reset(void)
11939ba774fSPo-Yu Chuang {
12039ba774fSPo-Yu Chuang debug("%s()\n", __func__);
12139ba774fSPo-Yu Chuang ftrtc010_enable();
12239ba774fSPo-Yu Chuang }
123