blob: 73d1d87d38b1aff2b1cf66a17076510969e32859 [file] [log] [blame]
wdenkb4ad9622005-04-01 00:25:43 +00001/*
2 * SNTP support driver
3 *
4 * Masami Komiya <mkomiya@sonare.it> 2005
5 *
6 */
7
wdenkb4ad9622005-04-01 00:25:43 +00008#include <command.h>
Simon Glass1aa11262015-04-20 12:37:27 -06009#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
wdenkb4ad9622005-04-01 00:25:43 +000011#include <net.h>
12#include <rtc.h>
13
Philippe Reynes2829d992020-09-18 14:13:02 +020014#include <net/sntp.h>
wdenkb4ad9622005-04-01 00:25:43 +000015
Bartlomiej Sieka56668462008-10-01 15:26:28 +020016#define SNTP_TIMEOUT 10000UL
wdenkb4ad9622005-04-01 00:25:43 +000017
Joe Hershberger4af0b772015-04-08 01:41:12 -050018static int sntp_our_port;
wdenkb4ad9622005-04-01 00:25:43 +000019
Philippe Reynes2829d992020-09-18 14:13:02 +020020/* NTP server IP address */
21struct in_addr net_ntp_server;
22/* offset time from UTC */
23int net_ntp_time_offset;
24
Joe Hershberger4af0b772015-04-08 01:41:12 -050025static void sntp_send(void)
wdenkb4ad9622005-04-01 00:25:43 +000026{
27 struct sntp_pkt_t pkt;
28 int pktlen = SNTP_PACKET_LEN;
29 int sport;
30
Robin Getz9e0a4d62009-07-23 03:01:03 -040031 debug("%s\n", __func__);
wdenkb4ad9622005-04-01 00:25:43 +000032
Joe Hershberger840fc802012-05-15 08:59:11 +000033 memset(&pkt, 0, sizeof(pkt));
wdenkb4ad9622005-04-01 00:25:43 +000034
35 pkt.li = NTP_LI_NOLEAP;
36 pkt.vn = NTP_VERSION;
37 pkt.mode = NTP_MODE_CLIENT;
38
Joe Hershbergera8ca4f62015-04-08 01:41:05 -050039 memcpy((char *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE,
40 (char *)&pkt, pktlen);
wdenkb4ad9622005-04-01 00:25:43 +000041
Joe Hershberger4af0b772015-04-08 01:41:12 -050042 sntp_our_port = 10000 + (get_timer(0) % 4096);
wdenkb4ad9622005-04-01 00:25:43 +000043 sport = NTP_SERVICE_PORT;
44
Joe Hershbergera8ca4f62015-04-08 01:41:05 -050045 net_send_udp_packet(net_server_ethaddr, net_ntp_server, sport,
Joe Hershberger4af0b772015-04-08 01:41:12 -050046 sntp_our_port, pktlen);
wdenkb4ad9622005-04-01 00:25:43 +000047}
48
Joe Hershberger4af0b772015-04-08 01:41:12 -050049static void sntp_timeout_handler(void)
wdenkb4ad9622005-04-01 00:25:43 +000050{
Joe Hershberger840fc802012-05-15 08:59:11 +000051 puts("Timeout\n");
Joe Hershbergerd4bb76a2012-05-23 07:59:14 +000052 net_set_state(NETLOOP_FAIL);
wdenkb4ad9622005-04-01 00:25:43 +000053 return;
54}
55
Joe Hershberger5874dec2015-04-08 01:41:01 -050056static void sntp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
57 unsigned src, unsigned len)
wdenkb4ad9622005-04-01 00:25:43 +000058{
wdenk8d5d28a2005-04-02 22:37:54 +000059 struct sntp_pkt_t *rpktp = (struct sntp_pkt_t *)pkt;
wdenkb4ad9622005-04-01 00:25:43 +000060 struct rtc_time tm;
wdenk8d5d28a2005-04-02 22:37:54 +000061 ulong seconds;
wdenkb4ad9622005-04-01 00:25:43 +000062
Robin Getz9e0a4d62009-07-23 03:01:03 -040063 debug("%s\n", __func__);
wdenkb4ad9622005-04-01 00:25:43 +000064
Joe Hershberger4af0b772015-04-08 01:41:12 -050065 if (dest != sntp_our_port)
Joe Hershberger840fc802012-05-15 08:59:11 +000066 return;
wdenkb4ad9622005-04-01 00:25:43 +000067
wdenk8d5d28a2005-04-02 22:37:54 +000068 /*
Joe Hershberger22498c52015-04-08 01:41:24 -050069 * As the RTC's used in U-Boot support second resolution only
wdenk8d5d28a2005-04-02 22:37:54 +000070 * we simply ignore the sub-second field.
71 */
Joe Hershberger840fc802012-05-15 08:59:11 +000072 memcpy(&seconds, &rpktp->transmit_timestamp, sizeof(ulong));
wdenkb4ad9622005-04-01 00:25:43 +000073
Simon Glass12994662015-04-20 12:37:18 -060074 rtc_to_tm(ntohl(seconds) - 2208988800UL + net_ntp_time_offset, &tm);
Heinrich Schuchardt6875dec2020-10-23 12:58:27 +020075#ifdef CONFIG_DM_RTC
Simon Glass1aa11262015-04-20 12:37:27 -060076 struct udevice *dev;
77 int ret;
78
79 ret = uclass_get_device(UCLASS_RTC, 0, &dev);
80 if (ret)
81 printf("SNTP: cannot find RTC: err=%d\n", ret);
82 else
83 dm_rtc_set(dev, &tm);
Heinrich Schuchardt6875dec2020-10-23 12:58:27 +020084#elif defined(CONFIG_CMD_DATE)
Joe Hershberger840fc802012-05-15 08:59:11 +000085 rtc_set(&tm);
wdenkb4ad9622005-04-01 00:25:43 +000086#endif
Joe Hershberger840fc802012-05-15 08:59:11 +000087 printf("Date: %4d-%02d-%02d Time: %2d:%02d:%02d\n",
Joe Hershberger4af0b772015-04-08 01:41:12 -050088 tm.tm_year, tm.tm_mon, tm.tm_mday,
89 tm.tm_hour, tm.tm_min, tm.tm_sec);
wdenkb4ad9622005-04-01 00:25:43 +000090
Joe Hershbergerd4bb76a2012-05-23 07:59:14 +000091 net_set_state(NETLOOP_SUCCESS);
wdenkb4ad9622005-04-01 00:25:43 +000092}
93
Philippe Reynes2829d992020-09-18 14:13:02 +020094/*
95 * SNTP:
96 *
97 * Prerequisites: - own ethernet address
98 * - own IP address
99 * We want: - network time
100 * Next step: none
101 */
102int sntp_prereq(void *data)
103{
104 if (net_ntp_server.s_addr == 0) {
105 puts("*** ERROR: NTP server address not given\n");
106 return 1;
107 }
108
109 return 0;
110}
111
112int sntp_start(void *data)
wdenkb4ad9622005-04-01 00:25:43 +0000113{
Robin Getz9e0a4d62009-07-23 03:01:03 -0400114 debug("%s\n", __func__);
wdenkb4ad9622005-04-01 00:25:43 +0000115
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500116 net_set_timeout_handler(SNTP_TIMEOUT, sntp_timeout_handler);
Joe Hershberger5874dec2015-04-08 01:41:01 -0500117 net_set_udp_handler(sntp_handler);
Joe Hershberger8ecdbed2015-04-08 01:41:04 -0500118 memset(net_server_ethaddr, 0, sizeof(net_server_ethaddr));
wdenkb4ad9622005-04-01 00:25:43 +0000119
Joe Hershberger4af0b772015-04-08 01:41:12 -0500120 sntp_send();
Philippe Reynes2829d992020-09-18 14:13:02 +0200121
122 return 0;
wdenkb4ad9622005-04-01 00:25:43 +0000123}