common/cmd_[a-f]* : Augment CONFIG_COMMANDS tests with defined(CONFIG_CMD_*).
[platform/kernel/u-boot.git] / common / cmd_date.c
1 /*
2  * (C) Copyright 2001
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * RTC, Date & Time support: get and set date & time
26  */
27 #include <common.h>
28 #include <command.h>
29 #include <rtc.h>
30 #include <i2c.h>
31
32 DECLARE_GLOBAL_DATA_PTR;
33
34 #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_CMD_DATE)
35
36 const char *weekdays[] = {
37         "Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
38 };
39
40 #define RELOC(a)        ((typeof(a))((unsigned long)(a) + gd->reloc_off))
41
42 int mk_date (char *, struct rtc_time *);
43
44 int do_date (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
45 {
46         struct rtc_time tm;
47         int rcode = 0;
48         int old_bus;
49
50         /* switch to correct I2C bus */
51         old_bus = I2C_GET_BUS();
52         I2C_SET_BUS(CFG_RTC_BUS_NUM);
53
54         switch (argc) {
55         case 2:                 /* set date & time */
56                 if (strcmp(argv[1],"reset") == 0) {
57                         puts ("Reset RTC...\n");
58                         rtc_reset ();
59                 } else {
60                         /* initialize tm with current time */
61                         rtc_get (&tm);
62                         /* insert new date & time */
63                         if (mk_date (argv[1], &tm) != 0) {
64                                 puts ("## Bad date format\n");
65                                 break;
66                         }
67                         /* and write to RTC */
68                         rtc_set (&tm);
69                 }
70                 /* FALL TROUGH */
71         case 1:                 /* get date & time */
72                 rtc_get (&tm);
73
74                 printf ("Date: %4d-%02d-%02d (%sday)    Time: %2d:%02d:%02d\n",
75                         tm.tm_year, tm.tm_mon, tm.tm_mday,
76                         (tm.tm_wday<0 || tm.tm_wday>6) ?
77                                 "unknown " : RELOC(weekdays[tm.tm_wday]),
78                         tm.tm_hour, tm.tm_min, tm.tm_sec);
79
80                 break;
81         default:
82                 printf ("Usage:\n%s\n", cmdtp->usage);
83                 rcode = 1;
84         }
85
86         /* switch back to original I2C bus */
87         I2C_SET_BUS(old_bus);
88
89         return rcode;
90 }
91
92 /*
93  * simple conversion of two-digit string with error checking
94  */
95 static int cnvrt2 (char *str, int *valp)
96 {
97         int val;
98
99         if ((*str < '0') || (*str > '9'))
100                 return (-1);
101
102         val = *str - '0';
103
104         ++str;
105
106         if ((*str < '0') || (*str > '9'))
107                 return (-1);
108
109         *valp = 10 * val + (*str - '0');
110
111         return (0);
112 }
113
114 /*
115  * Convert date string: MMDDhhmm[[CC]YY][.ss]
116  *
117  * Some basic checking for valid values is done, but this will not catch
118  * all possible error conditions.
119  */
120 int mk_date (char *datestr, struct rtc_time *tmp)
121 {
122         int len, val;
123         char *ptr;
124
125         ptr = strchr (datestr,'.');
126         len = strlen (datestr);
127
128         /* Set seconds */
129         if (ptr) {
130                 int sec;
131
132                 *ptr++ = '\0';
133                 if ((len - (ptr - datestr)) != 2)
134                         return (-1);
135
136                 len = strlen (datestr);
137
138                 if (cnvrt2 (ptr, &sec))
139                         return (-1);
140
141                 tmp->tm_sec = sec;
142         } else {
143                 tmp->tm_sec = 0;
144         }
145
146         if (len == 12) {                /* MMDDhhmmCCYY */
147                 int year, century;
148
149                 if (cnvrt2 (datestr+ 8, &century) ||
150                     cnvrt2 (datestr+10, &year) ) {
151                         return (-1);
152                 }
153                 tmp->tm_year = 100 * century + year;
154         } else if (len == 10) {         /* MMDDhhmmYY   */
155                 int year, century;
156
157                 century = tmp->tm_year / 100;
158                 if (cnvrt2 (datestr+ 8, &year))
159                         return (-1);
160                 tmp->tm_year = 100 * century + year;
161         }
162
163         switch (len) {
164         case 8:                 /* MMDDhhmm     */
165                 /* fall thru */
166         case 10:                /* MMDDhhmmYY   */
167                 /* fall thru */
168         case 12:                /* MMDDhhmmCCYY */
169                 if (cnvrt2 (datestr+0, &val) ||
170                     val > 12) {
171                         break;
172                 }
173                 tmp->tm_mon  = val;
174                 if (cnvrt2 (datestr+2, &val) ||
175                     val > ((tmp->tm_mon==2) ? 29 : 31)) {
176                         break;
177                 }
178                 tmp->tm_mday = val;
179
180                 if (cnvrt2 (datestr+4, &val) ||
181                     val > 23) {
182                         break;
183                 }
184                 tmp->tm_hour = val;
185
186                 if (cnvrt2 (datestr+6, &val) ||
187                     val > 59) {
188                         break;
189                 }
190                 tmp->tm_min  = val;
191
192                 /* calculate day of week */
193                 GregorianDay (tmp);
194
195                 return (0);
196         default:
197                 break;
198         }
199
200         return (-1);
201 }
202
203 /***************************************************/
204
205 U_BOOT_CMD(
206         date,   2,      1,      do_date,
207         "date    - get/set/reset date & time\n",
208         "[MMDDhhmm[[CC]YY][.ss]]\ndate reset\n"
209         "  - without arguments: print date & time\n"
210         "  - with numeric argument: set the system date & time\n"
211         "  - with 'reset' argument: reset the RTC\n"
212 );
213
214 #endif  /* CFG_CMD_DATE */