blob: 3be97c9d933fcc67308ccda07cb4d3923942103d [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk1fe2c702003-03-06 21:55:29 +00002/*
3 * (C) Copyright 2001, 2002, 2003
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * Keith Outwater, keith_outwater@mvis.com`
6 * Steven Scholz, steven.scholz@imc-berlin.de
wdenk1fe2c702003-03-06 21:55:29 +00007 */
8
9/*
10 * Date & Time support (no alarms) for Dallas Semiconductor (now Maxim)
Markus Niebel90491f22014-07-21 11:06:16 +020011 * DS1307 and DS1338/9 Real Time Clock (RTC).
wdenk1fe2c702003-03-06 21:55:29 +000012 *
13 * based on ds1337.c
14 */
15
16#include <common.h>
17#include <command.h>
Chris Packham97a3e912017-04-29 15:20:29 +120018#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060019#include <log.h>
wdenk1fe2c702003-03-06 21:55:29 +000020#include <rtc.h>
21#include <i2c.h>
22
Chris Packham97a3e912017-04-29 15:20:29 +120023enum ds_type {
24 ds_1307,
25 ds_1337,
Chris Packham69e8fdd2021-03-03 14:09:44 +130026 ds_1339,
Chris Packham97a3e912017-04-29 15:20:29 +120027 ds_1340,
Heiko Schocher2e819b42019-05-27 08:13:41 +020028 m41t11,
Chris Packham97a3e912017-04-29 15:20:29 +120029 mcp794xx,
30};
wdenk1fe2c702003-03-06 21:55:29 +000031
32/*
33 * RTC register addresses
34 */
35#define RTC_SEC_REG_ADDR 0x00
36#define RTC_MIN_REG_ADDR 0x01
37#define RTC_HR_REG_ADDR 0x02
38#define RTC_DAY_REG_ADDR 0x03
39#define RTC_DATE_REG_ADDR 0x04
40#define RTC_MON_REG_ADDR 0x05
41#define RTC_YR_REG_ADDR 0x06
42#define RTC_CTL_REG_ADDR 0x07
43
44#define RTC_SEC_BIT_CH 0x80 /* Clock Halt (in Register 0) */
45
Callum Sinclair85341612021-08-10 14:51:15 +120046/* DS1307-specific bits */
wdenk1fe2c702003-03-06 21:55:29 +000047#define RTC_CTL_BIT_RS0 0x01 /* Rate select 0 */
48#define RTC_CTL_BIT_RS1 0x02 /* Rate select 1 */
49#define RTC_CTL_BIT_SQWE 0x10 /* Square Wave Enable */
50#define RTC_CTL_BIT_OUT 0x80 /* Output Control */
51
Callum Sinclair85341612021-08-10 14:51:15 +120052/* DS1337-specific bits */
53#define DS1337_CTL_BIT_RS1 0x08 /* Rate select 1 */
54#define DS1337_CTL_BIT_RS2 0x10 /* Rate select 2 */
55#define DS1337_CTL_BIT_EOSC 0x80 /* Enable Oscillator */
56
57/* DS1340-specific bits */
58#define DS1340_SEC_BIT_EOSC 0x80 /* Enable Oscillator */
59#define DS1340_CTL_BIT_OUT 0x80 /* Output Control */
60
Andy Flemingb9b8c2f2015-10-21 18:59:06 -050061/* MCP7941X-specific bits */
62#define MCP7941X_BIT_ST 0x80
63#define MCP7941X_BIT_VBATEN 0x08
64
Chris Packham97a3e912017-04-29 15:20:29 +120065#ifndef CONFIG_DM_RTC
66
Chris Packham97a3e912017-04-29 15:20:29 +120067/*---------------------------------------------------------------------*/
68#undef DEBUG_RTC
69
70#ifdef DEBUG_RTC
71#define DEBUGR(fmt, args...) printf(fmt, ##args)
72#else
73#define DEBUGR(fmt, args...)
74#endif
75/*---------------------------------------------------------------------*/
76
77#ifndef CONFIG_SYS_I2C_RTC_ADDR
78# define CONFIG_SYS_I2C_RTC_ADDR 0x68
79#endif
80
81#if defined(CONFIG_RTC_DS1307) && (CONFIG_SYS_I2C_SPEED > 100000)
82# error The DS1307 is specified only up to 100kHz!
83#endif
84
wdenk1fe2c702003-03-06 21:55:29 +000085static uchar rtc_read (uchar reg);
86static void rtc_write (uchar reg, uchar val);
wdenk1fe2c702003-03-06 21:55:29 +000087
88/*
89 * Get the current time from the RTC
90 */
Yuri Tikhonov9bacd942008-03-20 17:56:04 +030091int rtc_get (struct rtc_time *tmp)
wdenk1fe2c702003-03-06 21:55:29 +000092{
Yuri Tikhonov9bacd942008-03-20 17:56:04 +030093 int rel = 0;
wdenk1fe2c702003-03-06 21:55:29 +000094 uchar sec, min, hour, mday, wday, mon, year;
95
Andy Flemingb9b8c2f2015-10-21 18:59:06 -050096#ifdef CONFIG_RTC_MCP79411
97read_rtc:
98#endif
wdenk1fe2c702003-03-06 21:55:29 +000099 sec = rtc_read (RTC_SEC_REG_ADDR);
100 min = rtc_read (RTC_MIN_REG_ADDR);
101 hour = rtc_read (RTC_HR_REG_ADDR);
102 wday = rtc_read (RTC_DAY_REG_ADDR);
103 mday = rtc_read (RTC_DATE_REG_ADDR);
104 mon = rtc_read (RTC_MON_REG_ADDR);
105 year = rtc_read (RTC_YR_REG_ADDR);
106
107 DEBUGR ("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
108 "hr: %02x min: %02x sec: %02x\n",
109 year, mon, mday, wday, hour, min, sec);
110
Andy Flemingb9b8c2f2015-10-21 18:59:06 -0500111#ifdef CONFIG_RTC_DS1307
wdenk1fe2c702003-03-06 21:55:29 +0000112 if (sec & RTC_SEC_BIT_CH) {
113 printf ("### Warning: RTC oscillator has stopped\n");
114 /* clear the CH flag */
115 rtc_write (RTC_SEC_REG_ADDR,
116 rtc_read (RTC_SEC_REG_ADDR) & ~RTC_SEC_BIT_CH);
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300117 rel = -1;
wdenk1fe2c702003-03-06 21:55:29 +0000118 }
Andy Flemingb9b8c2f2015-10-21 18:59:06 -0500119#endif
120
121#ifdef CONFIG_RTC_MCP79411
122 /* make sure that the backup battery is enabled */
123 if (!(wday & MCP7941X_BIT_VBATEN)) {
124 rtc_write(RTC_DAY_REG_ADDR,
125 wday | MCP7941X_BIT_VBATEN);
126 }
wdenk57b2d802003-06-27 21:31:46 +0000127
Andy Flemingb9b8c2f2015-10-21 18:59:06 -0500128 /* clock halted? turn it on, so clock can tick. */
129 if (!(sec & MCP7941X_BIT_ST)) {
130 rtc_write(RTC_SEC_REG_ADDR, MCP7941X_BIT_ST);
131 printf("Started RTC\n");
132 goto read_rtc;
133 }
134#endif
135
136
wdenk1fe2c702003-03-06 21:55:29 +0000137 tmp->tm_sec = bcd2bin (sec & 0x7F);
138 tmp->tm_min = bcd2bin (min & 0x7F);
139 tmp->tm_hour = bcd2bin (hour & 0x3F);
140 tmp->tm_mday = bcd2bin (mday & 0x3F);
141 tmp->tm_mon = bcd2bin (mon & 0x1F);
142 tmp->tm_year = bcd2bin (year) + ( bcd2bin (year) >= 70 ? 1900 : 2000);
143 tmp->tm_wday = bcd2bin ((wday - 1) & 0x07);
144 tmp->tm_yday = 0;
145 tmp->tm_isdst= 0;
146
147 DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
148 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
149 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
Yuri Tikhonov9bacd942008-03-20 17:56:04 +0300150
151 return rel;
wdenk1fe2c702003-03-06 21:55:29 +0000152}
153
154
155/*
156 * Set the RTC
157 */
Jean-Christophe PLAGNIOL-VILLARD97a2e102008-09-01 23:06:23 +0200158int rtc_set (struct rtc_time *tmp)
wdenk1fe2c702003-03-06 21:55:29 +0000159{
160 DEBUGR ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
161 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
162 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
163
164 if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
165 printf("WARNING: year should be between 1970 and 2069!\n");
wdenk57b2d802003-06-27 21:31:46 +0000166
wdenk1fe2c702003-03-06 21:55:29 +0000167 rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100));
168 rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon));
Andy Flemingb9b8c2f2015-10-21 18:59:06 -0500169#ifdef CONFIG_RTC_MCP79411
170 rtc_write (RTC_DAY_REG_ADDR,
171 bin2bcd (tmp->tm_wday + 1) | MCP7941X_BIT_VBATEN);
172#else
wdenk1fe2c702003-03-06 21:55:29 +0000173 rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1));
Andy Flemingb9b8c2f2015-10-21 18:59:06 -0500174#endif
wdenk1fe2c702003-03-06 21:55:29 +0000175 rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday));
176 rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour));
177 rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min));
Andy Flemingb9b8c2f2015-10-21 18:59:06 -0500178#ifdef CONFIG_RTC_MCP79411
179 rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec) | MCP7941X_BIT_ST);
180#else
wdenk1fe2c702003-03-06 21:55:29 +0000181 rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec));
Andy Flemingb9b8c2f2015-10-21 18:59:06 -0500182#endif
Jean-Christophe PLAGNIOL-VILLARD97a2e102008-09-01 23:06:23 +0200183
184 return 0;
wdenk1fe2c702003-03-06 21:55:29 +0000185}
186
187
188/*
wdenk57b2d802003-06-27 21:31:46 +0000189 * Reset the RTC. We setting the date back to 1970-01-01.
190 * We also enable the oscillator output on the SQW/OUT pin and program
wdenk1fe2c702003-03-06 21:55:29 +0000191 * it for 32,768 Hz output. Note that according to the datasheet, turning
192 * on the square wave output increases the current drain on the backup
193 * battery to something between 480nA and 800nA.
194 */
195void rtc_reset (void)
196{
wdenk1fe2c702003-03-06 21:55:29 +0000197 rtc_write (RTC_SEC_REG_ADDR, 0x00); /* clearing Clock Halt */
198 rtc_write (RTC_CTL_REG_ADDR, RTC_CTL_BIT_SQWE | RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS0);
wdenk1fe2c702003-03-06 21:55:29 +0000199}
200
201
202/*
203 * Helper functions
204 */
205
206static
207uchar rtc_read (uchar reg)
208{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200209 return (i2c_reg_read (CONFIG_SYS_I2C_RTC_ADDR, reg));
wdenk1fe2c702003-03-06 21:55:29 +0000210}
211
212
213static void rtc_write (uchar reg, uchar val)
214{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200215 i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
wdenk1fe2c702003-03-06 21:55:29 +0000216}
Chris Packham97a3e912017-04-29 15:20:29 +1200217
Chris Packham97a3e912017-04-29 15:20:29 +1200218#endif /* !CONFIG_DM_RTC */
219
220#ifdef CONFIG_DM_RTC
221static int ds1307_rtc_set(struct udevice *dev, const struct rtc_time *tm)
222{
223 int ret;
224 uchar buf[7];
225 enum ds_type type = dev_get_driver_data(dev);
226
227 debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
228 tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
229 tm->tm_hour, tm->tm_min, tm->tm_sec);
230
231 if (tm->tm_year < 1970 || tm->tm_year > 2069)
232 printf("WARNING: year should be between 1970 and 2069!\n");
233
234 buf[RTC_YR_REG_ADDR] = bin2bcd(tm->tm_year % 100);
235 buf[RTC_MON_REG_ADDR] = bin2bcd(tm->tm_mon);
236 buf[RTC_DAY_REG_ADDR] = bin2bcd(tm->tm_wday + 1);
237 buf[RTC_DATE_REG_ADDR] = bin2bcd(tm->tm_mday);
238 buf[RTC_HR_REG_ADDR] = bin2bcd(tm->tm_hour);
239 buf[RTC_MIN_REG_ADDR] = bin2bcd(tm->tm_min);
240 buf[RTC_SEC_REG_ADDR] = bin2bcd(tm->tm_sec);
241
242 if (type == mcp794xx) {
243 buf[RTC_DAY_REG_ADDR] |= MCP7941X_BIT_VBATEN;
244 buf[RTC_SEC_REG_ADDR] |= MCP7941X_BIT_ST;
245 }
246
247 ret = dm_i2c_write(dev, 0, buf, sizeof(buf));
248 if (ret < 0)
249 return ret;
250
251 return 0;
252}
253
254static int ds1307_rtc_get(struct udevice *dev, struct rtc_time *tm)
255{
256 int ret;
257 uchar buf[7];
258 enum ds_type type = dev_get_driver_data(dev);
259
260read_rtc:
261 ret = dm_i2c_read(dev, 0, buf, sizeof(buf));
262 if (ret < 0)
263 return ret;
264
265 if (type == ds_1307) {
266 if (buf[RTC_SEC_REG_ADDR] & RTC_SEC_BIT_CH) {
267 printf("### Warning: RTC oscillator has stopped\n");
268 /* clear the CH flag */
269 buf[RTC_SEC_REG_ADDR] &= ~RTC_SEC_BIT_CH;
270 dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR,
271 buf[RTC_SEC_REG_ADDR]);
272 return -1;
273 }
Callum Sinclair85341612021-08-10 14:51:15 +1200274 } else if (type == ds_1337) {
275 if (buf[RTC_CTL_REG_ADDR] & DS1337_CTL_BIT_EOSC) {
276 printf("### Warning: RTC oscillator has stopped\n");
277 /* clear the not oscillator enable (~EOSC) flag */
278 buf[RTC_CTL_REG_ADDR] &= ~DS1337_CTL_BIT_EOSC;
279 dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR,
280 buf[RTC_CTL_REG_ADDR]);
281 return -1;
282 }
283 } else if (type == ds_1340) {
284 if (buf[RTC_SEC_REG_ADDR] & DS1340_SEC_BIT_EOSC) {
285 printf("### Warning: RTC oscillator has stopped\n");
286 /* clear the not oscillator enable (~EOSC) flag */
287 buf[RTC_SEC_REG_ADDR] &= ~DS1340_SEC_BIT_EOSC;
288 dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR,
289 buf[RTC_SEC_REG_ADDR]);
290 return -1;
291 }
292 } else if (type == m41t11) {
Heiko Schocher2e819b42019-05-27 08:13:41 +0200293 /* clock halted? turn it on, so clock can tick. */
294 if (buf[RTC_SEC_REG_ADDR] & RTC_SEC_BIT_CH) {
295 buf[RTC_SEC_REG_ADDR] &= ~RTC_SEC_BIT_CH;
296 dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR,
297 MCP7941X_BIT_ST);
298 dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR,
299 buf[RTC_SEC_REG_ADDR]);
300 goto read_rtc;
301 }
Callum Sinclair85341612021-08-10 14:51:15 +1200302 } else if (type == mcp794xx) {
Chris Packham97a3e912017-04-29 15:20:29 +1200303 /* make sure that the backup battery is enabled */
304 if (!(buf[RTC_DAY_REG_ADDR] & MCP7941X_BIT_VBATEN)) {
305 dm_i2c_reg_write(dev, RTC_DAY_REG_ADDR,
306 buf[RTC_DAY_REG_ADDR] |
307 MCP7941X_BIT_VBATEN);
308 }
309
310 /* clock halted? turn it on, so clock can tick. */
311 if (!(buf[RTC_SEC_REG_ADDR] & MCP7941X_BIT_ST)) {
312 dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR,
313 MCP7941X_BIT_ST);
314 printf("Started RTC\n");
315 goto read_rtc;
316 }
317 }
318
319 tm->tm_sec = bcd2bin(buf[RTC_SEC_REG_ADDR] & 0x7F);
320 tm->tm_min = bcd2bin(buf[RTC_MIN_REG_ADDR] & 0x7F);
321 tm->tm_hour = bcd2bin(buf[RTC_HR_REG_ADDR] & 0x3F);
322 tm->tm_mday = bcd2bin(buf[RTC_DATE_REG_ADDR] & 0x3F);
323 tm->tm_mon = bcd2bin(buf[RTC_MON_REG_ADDR] & 0x1F);
324 tm->tm_year = bcd2bin(buf[RTC_YR_REG_ADDR]) +
325 (bcd2bin(buf[RTC_YR_REG_ADDR]) >= 70 ?
326 1900 : 2000);
327 tm->tm_wday = bcd2bin((buf[RTC_DAY_REG_ADDR] - 1) & 0x07);
328 tm->tm_yday = 0;
329 tm->tm_isdst = 0;
330
331 debug("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
332 tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
333 tm->tm_hour, tm->tm_min, tm->tm_sec);
334
335 return 0;
336}
337
338static int ds1307_rtc_reset(struct udevice *dev)
339{
340 int ret;
Callum Sinclair85341612021-08-10 14:51:15 +1200341 enum ds_type type = dev_get_driver_data(dev);
Chris Packham97a3e912017-04-29 15:20:29 +1200342
Callum Sinclair85341612021-08-10 14:51:15 +1200343 /*
344 * reset clock/oscillator in the seconds register:
345 * on DS1307 bit 7 enables Clock Halt (CH),
346 * on DS1340 bit 7 disables the oscillator (not EOSC)
347 * on MCP794xx bit 7 enables Start Oscillator (ST)
348 */
Chris Packham97a3e912017-04-29 15:20:29 +1200349 ret = dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR, 0x00);
350 if (ret < 0)
351 return ret;
Chris Packham97a3e912017-04-29 15:20:29 +1200352
Callum Sinclair85341612021-08-10 14:51:15 +1200353 if (type == ds_1307) {
354 /* Write control register in order to enable square-wave
355 * output (SQWE) and set a default rate of 32.768kHz (RS1|RS0).
356 */
357 ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR,
358 RTC_CTL_BIT_SQWE | RTC_CTL_BIT_RS1 |
359 RTC_CTL_BIT_RS0);
360 } else if (type == ds_1337) {
361 /* Write control register in order to enable oscillator output
362 * (not EOSC) and set a default rate of 32.768kHz (RS2|RS1).
363 */
364 ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR,
365 DS1337_CTL_BIT_RS2 | DS1337_CTL_BIT_RS1);
366 } else if (type == ds_1340 || type == mcp794xx || type == m41t11) {
367 /* Reset clock calibration, frequency test and output level. */
368 ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR, 0x00);
369 }
370
371 return ret;
Chris Packham97a3e912017-04-29 15:20:29 +1200372}
373
374static int ds1307_probe(struct udevice *dev)
375{
376 i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
377 DM_I2C_CHIP_WR_ADDRESS);
378
379 return 0;
380}
381
382static const struct rtc_ops ds1307_rtc_ops = {
383 .get = ds1307_rtc_get,
384 .set = ds1307_rtc_set,
385 .reset = ds1307_rtc_reset,
386};
387
388static const struct udevice_id ds1307_rtc_ids[] = {
389 { .compatible = "dallas,ds1307", .data = ds_1307 },
390 { .compatible = "dallas,ds1337", .data = ds_1337 },
Chris Packham69e8fdd2021-03-03 14:09:44 +1300391 { .compatible = "dallas,ds1339", .data = ds_1339 },
Chris Packham97a3e912017-04-29 15:20:29 +1200392 { .compatible = "dallas,ds1340", .data = ds_1340 },
393 { .compatible = "microchip,mcp7941x", .data = mcp794xx },
Heiko Schocher2e819b42019-05-27 08:13:41 +0200394 { .compatible = "st,m41t11", .data = m41t11 },
Chris Packham97a3e912017-04-29 15:20:29 +1200395 { }
396};
397
398U_BOOT_DRIVER(rtc_ds1307) = {
399 .name = "rtc-ds1307",
400 .id = UCLASS_RTC,
401 .probe = ds1307_probe,
402 .of_match = ds1307_rtc_ids,
403 .ops = &ds1307_rtc_ops,
404};
405#endif /* CONFIG_DM_RTC */