blob: 929783e15f094c84c7eb7e8f3943535cbd59dc2e [file] [log] [blame]
wdenk1c437712004-01-16 00:30:56 +00001/*
2 * (C) Copyright 2004
3 * Reinhard Meyer, EMK Elektronik GmbH
4 * r.meyer@emk-elektronik.de
5 * www.emk-elektronik.de
6 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
wdenk1c437712004-01-16 00:30:56 +00008 */
9
10/*****************************************************************************
11 * Date & Time support for internal RTC of MPC52xx
12 *****************************************************************************/
13/*#define DEBUG*/
14
15#include <common.h>
16#include <command.h>
17#include <rtc.h>
18
Michal Simek871c18d2008-07-14 19:45:37 +020019#if defined(CONFIG_CMD_DATE)
wdenk1c437712004-01-16 00:30:56 +000020
21/*****************************************************************************
22 * this structure should be defined in mpc5200.h ...
23 *****************************************************************************/
24typedef struct rtc5200 {
25 volatile ulong tsr; /* MBAR+0x800: time set register */
26 volatile ulong dsr; /* MBAR+0x804: data set register */
27 volatile ulong nysr; /* MBAR+0x808: new year and stopwatch register */
28 volatile ulong aier; /* MBAR+0x80C: alarm and interrupt enable register */
29 volatile ulong ctr; /* MBAR+0x810: current time register */
30 volatile ulong cdr; /* MBAR+0x814: current data register */
Mike Williams16263082011-07-22 04:01:30 +000031 volatile ulong asir; /* MBAR+0x818: alarm and stopwatch interrupt register */
wdenk1c437712004-01-16 00:30:56 +000032 volatile ulong piber; /* MBAR+0x81C: periodic interrupt and bus error register */
33 volatile ulong trdr; /* MBAR+0x820: test register/divides register */
34} RTC5200;
35
36#define RTC_SET 0x02000000
37#define RTC_PAUSE 0x01000000
38
39/*****************************************************************************
40 * get time
41 *****************************************************************************/
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +030042int rtc_get (struct rtc_time *tmp)
wdenk1c437712004-01-16 00:30:56 +000043{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020044 RTC5200 *rtc = (RTC5200 *) (CONFIG_SYS_MBAR+0x800);
wdenk1c437712004-01-16 00:30:56 +000045 ulong time, date, time2;
46
47 /* read twice to avoid getting a funny time when the second is just changing */
48 do {
49 time = rtc->ctr;
50 date = rtc->cdr;
51 time2 = rtc->ctr;
52 } while (time != time2);
53
54 tmp->tm_year = date & 0xfff;
55 tmp->tm_mon = (date >> 24) & 0xf;
56 tmp->tm_mday = (date >> 16) & 0x1f;
57 tmp->tm_wday = (date >> 21) & 7;
58 /* sunday is 7 in 5200 but 0 in rtc_time */
59 if (tmp->tm_wday == 7)
60 tmp->tm_wday = 0;
61 tmp->tm_hour = (time >> 16) & 0x1f;
62 tmp->tm_min = (time >> 8) & 0x3f;
63 tmp->tm_sec = time & 0x3f;
64
65 debug ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
66 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
67 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
Yuri Tikhonovb73a19e2008-03-20 17:56:04 +030068
69 return 0;
wdenk1c437712004-01-16 00:30:56 +000070}
71
72/*****************************************************************************
73 * set time
74 *****************************************************************************/
Jean-Christophe PLAGNIOL-VILLARDd1e23192008-09-01 23:06:23 +020075int rtc_set (struct rtc_time *tmp)
wdenk1c437712004-01-16 00:30:56 +000076{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020077 RTC5200 *rtc = (RTC5200 *) (CONFIG_SYS_MBAR+0x800);
wdenk1c437712004-01-16 00:30:56 +000078 ulong time, date, year;
79
80 debug ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
81 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
82 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
83
84 time = (tmp->tm_hour << 16) | (tmp->tm_min << 8) | tmp->tm_sec;
85 date = (tmp->tm_mon << 16) | tmp->tm_mday;
86 if (tmp->tm_wday == 0)
87 date |= (7 << 8);
88 else
89 date |= (tmp->tm_wday << 8);
90 year = tmp->tm_year;
91
92 /* mask unwanted bits that might show up when rtc_time is corrupt */
93 time &= 0x001f3f3f;
94 date &= 0x001f071f;
95 year &= 0x00000fff;
96
97 /* pause and set the RTC */
98 rtc->nysr = year;
99 rtc->dsr = date | RTC_PAUSE;
100 udelay (1000);
101 rtc->dsr = date | RTC_PAUSE | RTC_SET;
102 udelay (1000);
103 rtc->dsr = date | RTC_PAUSE;
104 udelay (1000);
105 rtc->dsr = date;
106 udelay (1000);
107
108 rtc->tsr = time | RTC_PAUSE;
109 udelay (1000);
110 rtc->tsr = time | RTC_PAUSE | RTC_SET;
111 udelay (1000);
112 rtc->tsr = time | RTC_PAUSE;
113 udelay (1000);
114 rtc->tsr = time;
115 udelay (1000);
Jean-Christophe PLAGNIOL-VILLARDd1e23192008-09-01 23:06:23 +0200116
117 return 0;
wdenk1c437712004-01-16 00:30:56 +0000118}
119
120/*****************************************************************************
121 * reset rtc circuit
122 *****************************************************************************/
123void rtc_reset (void)
124{
125 return; /* nothing to do */
126}
127
Jon Loeliger068b60a2007-07-10 10:27:39 -0500128#endif