blob: b3826e950d0b7e0cc0d7f8b2766108f4c6f23df0 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Matthias Fuchs95c6bc72007-12-27 16:55:17 +01002/*
3 * (C) Copyright 2007
4 * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.com.
Matthias Fuchs95c6bc72007-12-27 16:55:17 +01005 */
6
7/*
8 * Epson RX8025 RTC driver.
9 */
10
11#include <common.h>
12#include <command.h>
13#include <rtc.h>
14#include <i2c.h>
15
Matthias Fuchs95c6bc72007-12-27 16:55:17 +010016/*---------------------------------------------------------------------*/
17#undef DEBUG_RTC
18
19#ifdef DEBUG_RTC
20#define DEBUGR(fmt,args...) printf(fmt ,##args)
21#else
22#define DEBUGR(fmt,args...)
23#endif
24/*---------------------------------------------------------------------*/
25
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020026#ifndef CONFIG_SYS_I2C_RTC_ADDR
27# define CONFIG_SYS_I2C_RTC_ADDR 0x32
Matthias Fuchs95c6bc72007-12-27 16:55:17 +010028#endif
29
30/*
31 * RTC register addresses
32 */
33#define RTC_SEC_REG_ADDR 0x00
34#define RTC_MIN_REG_ADDR 0x01
35#define RTC_HR_REG_ADDR 0x02
36#define RTC_DAY_REG_ADDR 0x03
37#define RTC_DATE_REG_ADDR 0x04
38#define RTC_MON_REG_ADDR 0x05
39#define RTC_YR_REG_ADDR 0x06
40
41#define RTC_CTL1_REG_ADDR 0x0e
42#define RTC_CTL2_REG_ADDR 0x0f
43
44/*
45 * Control register 1 bits
46 */
47#define RTC_CTL1_BIT_2412 0x20
48
49/*
50 * Control register 2 bits
51 */
52#define RTC_CTL2_BIT_PON 0x10
53#define RTC_CTL2_BIT_VDET 0x40
54#define RTC_CTL2_BIT_XST 0x20
55#define RTC_CTL2_BIT_VDSL 0x80
56
57/*
58 * Note: the RX8025 I2C RTC requires register
59 * reads and write to consist of a single bus
60 * cycle. It is not allowed to write the register
61 * address in a first cycle that is terminated by
62 * a STOP condition. The chips needs a 'restart'
63 * sequence (start sequence without a prior stop).
64 * This driver has been written for a 4xx board.
65 * U-Boot's 4xx i2c driver is currently not capable
66 * to generate such cycles to some work arounds
67 * are used.
68 */
69
70/* static uchar rtc_read (uchar reg); */
71#define rtc_read(reg) buf[((reg) + 1) & 0xf]
72
Heiko Schocherf91fb722019-07-16 05:31:34 +020073static void rtc_write(uchar reg, uchar val);
Matthias Fuchs95c6bc72007-12-27 16:55:17 +010074
75/*
76 * Get the current time from the RTC
77 */
Heiko Schocherf91fb722019-07-16 05:31:34 +020078int rtc_get(struct rtc_time *tmp)
Matthias Fuchs95c6bc72007-12-27 16:55:17 +010079{
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +030080 int rel = 0;
Matthias Fuchs95c6bc72007-12-27 16:55:17 +010081 uchar sec, min, hour, mday, wday, mon, year, ctl2;
82 uchar buf[16];
83
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020084 if (i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 0, buf, 16))
Matthias Fuchs95c6bc72007-12-27 16:55:17 +010085 printf("Error reading from RTC\n");
86
87 sec = rtc_read(RTC_SEC_REG_ADDR);
88 min = rtc_read(RTC_MIN_REG_ADDR);
89 hour = rtc_read(RTC_HR_REG_ADDR);
90 wday = rtc_read(RTC_DAY_REG_ADDR);
91 mday = rtc_read(RTC_DATE_REG_ADDR);
92 mon = rtc_read(RTC_MON_REG_ADDR);
93 year = rtc_read(RTC_YR_REG_ADDR);
94
Heiko Schocherf91fb722019-07-16 05:31:34 +020095 DEBUGR("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
96 "hr: %02x min: %02x sec: %02x\n",
97 year, mon, mday, wday, hour, min, sec);
Matthias Fuchs95c6bc72007-12-27 16:55:17 +010098
99 /* dump status */
100 ctl2 = rtc_read(RTC_CTL2_REG_ADDR);
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +0300101 if (ctl2 & RTC_CTL2_BIT_PON) {
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100102 printf("RTC: power-on detected\n");
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +0300103 rel = -1;
104 }
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100105
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +0300106 if (ctl2 & RTC_CTL2_BIT_VDET) {
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100107 printf("RTC: voltage drop detected\n");
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +0300108 rel = -1;
109 }
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100110
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +0300111 if (!(ctl2 & RTC_CTL2_BIT_XST)) {
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100112 printf("RTC: oscillator stop detected\n");
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +0300113 rel = -1;
114 }
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100115
Heiko Schocherf91fb722019-07-16 05:31:34 +0200116 tmp->tm_sec = bcd2bin(sec & 0x7F);
117 tmp->tm_min = bcd2bin(min & 0x7F);
Yuri Tikhonov5875d352008-08-15 15:42:09 +0200118 if (rtc_read(RTC_CTL1_REG_ADDR) & RTC_CTL1_BIT_2412)
Heiko Schocherf91fb722019-07-16 05:31:34 +0200119 tmp->tm_hour = bcd2bin(hour & 0x3F);
Yuri Tikhonov5875d352008-08-15 15:42:09 +0200120 else
Heiko Schocherf91fb722019-07-16 05:31:34 +0200121 tmp->tm_hour = bcd2bin(hour & 0x1F) % 12 +
Yuri Tikhonov5875d352008-08-15 15:42:09 +0200122 ((hour & 0x20) ? 12 : 0);
Heiko Schocherf91fb722019-07-16 05:31:34 +0200123
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100124 tmp->tm_mday = bcd2bin (mday & 0x3F);
125 tmp->tm_mon = bcd2bin (mon & 0x1F);
126 tmp->tm_year = bcd2bin (year) + ( bcd2bin (year) >= 70 ? 1900 : 2000);
127 tmp->tm_wday = bcd2bin (wday & 0x07);
128 tmp->tm_yday = 0;
129 tmp->tm_isdst= 0;
130
Heiko Schocherf91fb722019-07-16 05:31:34 +0200131 DEBUGR("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
132 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
133 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +0300134
135 return rel;
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100136}
137
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100138/*
139 * Set the RTC
140 */
Heiko Schocherf91fb722019-07-16 05:31:34 +0200141int rtc_set(struct rtc_time *tmp)
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100142{
Heiko Schocherf91fb722019-07-16 05:31:34 +0200143 DEBUGR("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
144 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
145 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100146
147 if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
148 printf("WARNING: year should be between 1970 and 2069!\n");
149
Heiko Schocherf91fb722019-07-16 05:31:34 +0200150 rtc_write(RTC_YR_REG_ADDR, bin2bcd(tmp->tm_year % 100));
151 rtc_write(RTC_MON_REG_ADDR, bin2bcd(tmp->tm_mon));
152 rtc_write(RTC_DAY_REG_ADDR, bin2bcd(tmp->tm_wday));
153 rtc_write(RTC_DATE_REG_ADDR, bin2bcd(tmp->tm_mday));
154 rtc_write(RTC_HR_REG_ADDR, bin2bcd(tmp->tm_hour));
155 rtc_write(RTC_MIN_REG_ADDR, bin2bcd(tmp->tm_min));
156 rtc_write(RTC_SEC_REG_ADDR, bin2bcd(tmp->tm_sec));
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100157
Heiko Schocherf91fb722019-07-16 05:31:34 +0200158 rtc_write(RTC_CTL1_REG_ADDR, RTC_CTL1_BIT_2412);
Jean-Christophe PLAGNIOL-VILLARDd1e23192008-09-01 23:06:23 +0200159
160 return 0;
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100161}
162
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100163/*
Chris Packham402c8fd2018-03-21 15:40:37 +1300164 * Reset the RTC
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100165 */
Heiko Schocherf91fb722019-07-16 05:31:34 +0200166void rtc_reset(void)
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100167{
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100168 uchar buf[16];
169 uchar ctl2;
170
Heiko Schocherf91fb722019-07-16 05:31:34 +0200171 if (i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 0, buf, 16))
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100172 printf("Error reading from RTC\n");
173
174 ctl2 = rtc_read(RTC_CTL2_REG_ADDR);
175 ctl2 &= ~(RTC_CTL2_BIT_PON | RTC_CTL2_BIT_VDET);
176 ctl2 |= RTC_CTL2_BIT_XST | RTC_CTL2_BIT_VDSL;
Heiko Schocherf91fb722019-07-16 05:31:34 +0200177 rtc_write(RTC_CTL2_REG_ADDR, ctl2);
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100178}
179
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100180/*
181 * Helper functions
182 */
Heiko Schocherf91fb722019-07-16 05:31:34 +0200183static void rtc_write(uchar reg, uchar val)
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100184{
185 uchar buf[2];
186 buf[0] = reg << 4;
187 buf[1] = val;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200188 if (i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 0, buf, 2) != 0)
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100189 printf("Error writing to RTC\n");
Matthias Fuchs95c6bc72007-12-27 16:55:17 +0100190}