blob: 7bd9f8b42af925d81cd8c075b647637dbe9912e7 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Matthias Fuchs6f60bf32007-12-27 16:55:17 +01002/*
3 * (C) Copyright 2007
4 * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.com.
Matthias Fuchs6f60bf32007-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 Fuchs6f60bf32007-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-VILLARD03836942008-10-16 15:01:15 +020026#ifndef CONFIG_SYS_I2C_RTC_ADDR
27# define CONFIG_SYS_I2C_RTC_ADDR 0x32
Matthias Fuchs6f60bf32007-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
73static void rtc_write (uchar reg, uchar val);
Matthias Fuchs6f60bf32007-12-27 16:55:17 +010074
75/*
76 * Get the current time from the RTC
77 */
Yuri Tikhonov9bacd942008-03-20 17:56:04 +030078int rtc_get (struct rtc_time *tmp)
Matthias Fuchs6f60bf32007-12-27 16:55:17 +010079{
Yuri Tikhonov9bacd942008-03-20 17:56:04 +030080 int rel = 0;
Matthias Fuchs6f60bf32007-12-27 16:55:17 +010081 uchar sec, min, hour, mday, wday, mon, year, ctl2;
82 uchar buf[16];
83
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020084 if (i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 0, buf, 16))
Matthias Fuchs6f60bf32007-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
95 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);
98
99 /* dump status */
100 ctl2 = rtc_read(RTC_CTL2_REG_ADDR);
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300101 if (ctl2 & RTC_CTL2_BIT_PON) {
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100102 printf("RTC: power-on detected\n");
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300103 rel = -1;
104 }
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100105
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300106 if (ctl2 & RTC_CTL2_BIT_VDET) {
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100107 printf("RTC: voltage drop detected\n");
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300108 rel = -1;
109 }
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100110
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300111 if (!(ctl2 & RTC_CTL2_BIT_XST)) {
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100112 printf("RTC: oscillator stop detected\n");
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300113 rel = -1;
114 }
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100115
116 tmp->tm_sec = bcd2bin (sec & 0x7F);
117 tmp->tm_min = bcd2bin (min & 0x7F);
Yuri Tikhonov62a34592008-08-15 15:42:09 +0200118 if (rtc_read(RTC_CTL1_REG_ADDR) & RTC_CTL1_BIT_2412)
119 tmp->tm_hour = bcd2bin (hour & 0x3F);
120 else
121 tmp->tm_hour = bcd2bin (hour & 0x1F) % 12 +
122 ((hour & 0x20) ? 12 : 0);
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100123 tmp->tm_mday = bcd2bin (mday & 0x3F);
124 tmp->tm_mon = bcd2bin (mon & 0x1F);
125 tmp->tm_year = bcd2bin (year) + ( bcd2bin (year) >= 70 ? 1900 : 2000);
126 tmp->tm_wday = bcd2bin (wday & 0x07);
127 tmp->tm_yday = 0;
128 tmp->tm_isdst= 0;
129
130 DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
131 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
132 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300133
134 return rel;
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100135}
136
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100137/*
138 * Set the RTC
139 */
Jean-Christophe PLAGNIOL-VILLARD97a2e102008-09-01 23:06:23 +0200140int rtc_set (struct rtc_time *tmp)
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100141{
142 DEBUGR ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
143 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
144 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
145
146 if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
147 printf("WARNING: year should be between 1970 and 2069!\n");
148
149 rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100));
150 rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon));
151 rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday));
152 rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday));
153 rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour));
154 rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min));
155 rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec));
156
157 rtc_write (RTC_CTL1_REG_ADDR, RTC_CTL1_BIT_2412);
Jean-Christophe PLAGNIOL-VILLARD97a2e102008-09-01 23:06:23 +0200158
159 return 0;
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100160}
161
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100162/*
Chris Packham7c105e42018-03-21 15:40:37 +1300163 * Reset the RTC
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100164 */
165void rtc_reset (void)
166{
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100167 uchar buf[16];
168 uchar ctl2;
169
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200170 if (i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 0, buf, 16))
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100171 printf("Error reading from RTC\n");
172
173 ctl2 = rtc_read(RTC_CTL2_REG_ADDR);
174 ctl2 &= ~(RTC_CTL2_BIT_PON | RTC_CTL2_BIT_VDET);
175 ctl2 |= RTC_CTL2_BIT_XST | RTC_CTL2_BIT_VDSL;
176 rtc_write (RTC_CTL2_REG_ADDR, ctl2);
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100177}
178
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100179/*
180 * Helper functions
181 */
182static void rtc_write (uchar reg, uchar val)
183{
184 uchar buf[2];
185 buf[0] = reg << 4;
186 buf[1] = val;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200187 if (i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 0, buf, 2) != 0)
Matthias Fuchs6f60bf32007-12-27 16:55:17 +0100188 printf("Error writing to RTC\n");
189
190}