"Das U-Boot" Source Tree
at master 215 lines 4.3 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2001 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 */ 6 7/* 8 * RTC, Date & Time support: get and set date & time 9 */ 10#include <command.h> 11#include <dm.h> 12#include <rtc.h> 13#include <i2c.h> 14#include <asm/global_data.h> 15 16DECLARE_GLOBAL_DATA_PTR; 17 18static const char * const weekdays[] = { 19 "Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur", 20}; 21 22int mk_date (const char *, struct rtc_time *); 23 24static struct rtc_time default_tm = { 0, 0, 0, 1, 1, 2000, 6, 0, 0 }; 25 26static int do_date(struct cmd_tbl *cmdtp, int flag, int argc, 27 char *const argv[]) 28{ 29 struct rtc_time tm; 30 int rcode = 0; 31 int old_bus __maybe_unused; 32 33 /* switch to correct I2C bus */ 34 struct udevice *dev; 35 36 rcode = uclass_get_device_by_seq(UCLASS_RTC, 0, &dev); 37 if (rcode) { 38 rcode = uclass_get_device(UCLASS_RTC, 0, &dev); 39 if (rcode) { 40 printf("Cannot find RTC: err=%d\n", rcode); 41 return CMD_RET_FAILURE; 42 } 43 } 44 45 switch (argc) { 46 case 2: /* set date & time */ 47 if (strcmp(argv[1],"reset") == 0) { 48 puts ("Reset RTC...\n"); 49 rcode = dm_rtc_reset(dev); 50 if (!rcode) 51 rcode = dm_rtc_set(dev, &default_tm); 52 if (rcode) 53 puts("## Failed to set date after RTC reset\n"); 54 } else { 55 /* initialize tm with current time */ 56 rcode = dm_rtc_get(dev, &tm); 57 if (!rcode) { 58 /* insert new date & time */ 59 if (mk_date(argv[1], &tm) != 0) { 60 puts ("## Bad date format\n"); 61 break; 62 } 63 /* and write to RTC */ 64 rcode = dm_rtc_set(dev, &tm); 65 if (rcode) { 66 printf("## Set date failed: err=%d\n", 67 rcode); 68 } 69 } else { 70 puts("## Get date failed\n"); 71 } 72 } 73 fallthrough; 74 case 1: /* get date & time */ 75 rcode = dm_rtc_get(dev, &tm); 76 if (rcode) { 77 puts("## Get date failed\n"); 78 break; 79 } 80 81 printf ("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n", 82 tm.tm_year, tm.tm_mon, tm.tm_mday, 83 (tm.tm_wday<0 || tm.tm_wday>6) ? 84 "unknown " : weekdays[tm.tm_wday], 85 tm.tm_hour, tm.tm_min, tm.tm_sec); 86 87 break; 88 default: 89 rcode = CMD_RET_USAGE; 90 } 91 92 return rcode ? CMD_RET_FAILURE : 0; 93} 94 95/* 96 * simple conversion of two-digit string with error checking 97 */ 98static int cnvrt2 (const char *str, int *valp) 99{ 100 int val; 101 102 if ((*str < '0') || (*str > '9')) 103 return (-1); 104 105 val = *str - '0'; 106 107 ++str; 108 109 if ((*str < '0') || (*str > '9')) 110 return (-1); 111 112 *valp = 10 * val + (*str - '0'); 113 114 return (0); 115} 116 117/* 118 * Convert date string: MMDDhhmm[[CC]YY][.ss] 119 * 120 * Some basic checking for valid values is done, but this will not catch 121 * all possible error conditions. 122 */ 123int mk_date (const char *datestr, struct rtc_time *tmp) 124{ 125 int len, val; 126 char *ptr; 127 128 ptr = strchr(datestr, '.'); 129 len = strlen(datestr); 130 131 /* Set seconds */ 132 if (ptr) { 133 int sec; 134 135 ptr++; 136 if ((len - (ptr - datestr)) != 2) 137 return (-1); 138 139 len -= 3; 140 141 if (cnvrt2 (ptr, &sec)) 142 return (-1); 143 144 tmp->tm_sec = sec; 145 } else { 146 tmp->tm_sec = 0; 147 } 148 149 if (len == 12) { /* MMDDhhmmCCYY */ 150 int year, century; 151 152 if (cnvrt2 (datestr+ 8, &century) || 153 cnvrt2 (datestr+10, &year) ) { 154 return (-1); 155 } 156 tmp->tm_year = 100 * century + year; 157 } else if (len == 10) { /* MMDDhhmmYY */ 158 int year, century; 159 160 century = tmp->tm_year / 100; 161 if (cnvrt2 (datestr+ 8, &year)) 162 return (-1); 163 tmp->tm_year = 100 * century + year; 164 } 165 166 switch (len) { 167 case 8: /* MMDDhhmm */ 168 /* fall thru */ 169 case 10: /* MMDDhhmmYY */ 170 /* fall thru */ 171 case 12: /* MMDDhhmmCCYY */ 172 if (cnvrt2 (datestr+0, &val) || 173 val > 12) { 174 break; 175 } 176 tmp->tm_mon = val; 177 if (cnvrt2 (datestr+2, &val) || 178 val > ((tmp->tm_mon==2) ? 29 : 31)) { 179 break; 180 } 181 tmp->tm_mday = val; 182 183 if (cnvrt2 (datestr+4, &val) || 184 val > 23) { 185 break; 186 } 187 tmp->tm_hour = val; 188 189 if (cnvrt2 (datestr+6, &val) || 190 val > 59) { 191 break; 192 } 193 tmp->tm_min = val; 194 195 /* calculate day of week */ 196 rtc_calc_weekday(tmp); 197 198 return (0); 199 default: 200 break; 201 } 202 203 return (-1); 204} 205 206/***************************************************/ 207 208U_BOOT_CMD( 209 date, 2, 1, do_date, 210 "get/set/reset date & time", 211 "[MMDDhhmm[[CC]YY][.ss]]\ndate reset\n" 212 " - without arguments: print date & time\n" 213 " - with numeric argument: set the system date & time\n" 214 " - with 'reset' argument: reset the RTC" 215);