Newer
Older
/*
* (C) Copyright 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* RTC, Date & Time support: get and set date & time
*/
#include <common.h>
#include <command.h>
#include <i2c.h>
DECLARE_GLOBAL_DATA_PTR;
"Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
};
#ifdef CONFIG_NEEDS_MANUAL_RELOC
#define RELOC(a) ((typeof(a))((unsigned long)(a) + gd->reloc_off))
#else
#define RELOC(a) a
static struct rtc_time default_tm = { 0, 0, 0, 1, 1, 2000, 6, 0, 0 };
static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
int old_bus __maybe_unused;
/* switch to correct I2C bus */
#ifdef CONFIG_DM_RTC
struct udevice *dev;
rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
if (rcode) {
printf("Cannot find RTC: err=%d\n", rcode);
return CMD_RET_FAILURE;
}
#elif defined(CONFIG_SYS_I2C)
old_bus = i2c_get_bus_num();
i2c_set_bus_num(CONFIG_SYS_RTC_BUS_NUM);
#else
old_bus = I2C_GET_BUS();
I2C_SET_BUS(CONFIG_SYS_RTC_BUS_NUM);
switch (argc) {
case 2: /* set date & time */
if (strcmp(argv[1],"reset") == 0) {
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_reset(dev);
if (!rcode)
rcode = dm_rtc_set(dev, &default_tm);
#else
rtc_reset();
if (rcode)
puts("## Failed to set date after RTC reset\n");
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_get(dev, &tm);
#else
rcode = rtc_get(&tm);
#endif
if (!rcode) {
Jean-Christophe PLAGNIOL-VILLARD
committed
/* insert new date & time */
if (mk_date(argv[1], &tm) != 0) {
Jean-Christophe PLAGNIOL-VILLARD
committed
puts ("## Bad date format\n");
break;
}
/* and write to RTC */
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_set(dev, &tm);
#else
rcode = rtc_set(&tm);
#endif
if (rcode) {
printf("## Set date failed: err=%d\n",
rcode);
}
Jean-Christophe PLAGNIOL-VILLARD
committed
} else {
}
}
/* FALL TROUGH */
case 1: /* get date & time */
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_get(dev, &tm);
#else
rcode = rtc_get(&tm);
#endif
Jean-Christophe PLAGNIOL-VILLARD
committed
if (rcode) {
Jean-Christophe PLAGNIOL-VILLARD
committed
break;
}
printf ("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n",
tm.tm_year, tm.tm_mon, tm.tm_mday,
(tm.tm_wday<0 || tm.tm_wday>6) ?
"unknown " : RELOC(weekdays[tm.tm_wday]),
rcode = CMD_RET_USAGE;
/* switch back to original I2C bus */
#ifdef CONFIG_SYS_I2C
i2c_set_bus_num(old_bus);
#elif !defined(CONFIG_DM_RTC)
I2C_SET_BUS(old_bus);
return rcode ? CMD_RET_FAILURE : 0;
}
/*
* simple conversion of two-digit string with error checking
*/
{
int val;
if ((*str < '0') || (*str > '9'))
return (-1);
val = *str - '0';
++str;
if ((*str < '0') || (*str > '9'))
return (-1);
*valp = 10 * val + (*str - '0');
return (0);
}
/*
* Convert date string: MMDDhhmm[[CC]YY][.ss]
*
* Some basic checking for valid values is done, but this will not catch
* all possible error conditions.
*/
int mk_date (const char *datestr, struct rtc_time *tmp)
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
{
int len, val;
char *ptr;
ptr = strchr (datestr,'.');
len = strlen (datestr);
/* Set seconds */
if (ptr) {
int sec;
*ptr++ = '\0';
if ((len - (ptr - datestr)) != 2)
return (-1);
len = strlen (datestr);
if (cnvrt2 (ptr, &sec))
return (-1);
tmp->tm_sec = sec;
} else {
tmp->tm_sec = 0;
}
if (len == 12) { /* MMDDhhmmCCYY */
int year, century;
if (cnvrt2 (datestr+ 8, ¢ury) ||
cnvrt2 (datestr+10, &year) ) {
return (-1);
}
tmp->tm_year = 100 * century + year;
} else if (len == 10) { /* MMDDhhmmYY */
int year, century;
century = tmp->tm_year / 100;
if (cnvrt2 (datestr+ 8, &year))
return (-1);
tmp->tm_year = 100 * century + year;
}
switch (len) {
case 8: /* MMDDhhmm */
/* fall thru */
case 10: /* MMDDhhmmYY */
/* fall thru */
case 12: /* MMDDhhmmCCYY */
if (cnvrt2 (datestr+0, &val) ||
val > 12) {
break;
}
tmp->tm_mon = val;
if (cnvrt2 (datestr+2, &val) ||
val > ((tmp->tm_mon==2) ? 29 : 31)) {
break;
}
tmp->tm_mday = val;
if (cnvrt2 (datestr+4, &val) ||
val > 23) {
break;
}
tmp->tm_hour = val;
if (cnvrt2 (datestr+6, &val) ||
val > 59) {
break;
}
tmp->tm_min = val;
/* calculate day of week */
return (0);
default:
break;
}
return (-1);
}
/***************************************************/
U_BOOT_CMD(
date, 2, 1, do_date,
"[MMDDhhmm[[CC]YY][.ss]]\ndate reset\n"
" - without arguments: print date & time\n"
" - with numeric argument: set the system date & time\n"