1// SPDX-License-Identifier: GPL-2.0+ 2 3#include <common.h> 4#include <command.h> 5#include <display_options.h> 6#include <dm.h> 7#include <hexdump.h> 8#include <i2c.h> 9#include <mapmem.h> 10#include <rtc.h> 11 12#define MAX_RTC_BYTES 32 13 14static int do_rtc_read(struct udevice *dev, int argc, char * const argv[]) 15{ 16 u8 buf[MAX_RTC_BYTES]; 17 int reg, len, ret, r; 18 19 if (argc < 2 || argc > 3) 20 return CMD_RET_USAGE; 21 22 reg = hextoul(argv[0], NULL); 23 len = hextoul(argv[1], NULL); 24 25 if (argc == 3) { 26 u8 *addr; 27 28 addr = map_sysmem(hextoul(argv[2], NULL), len); 29 ret = dm_rtc_read(dev, reg, addr, len); 30 unmap_sysmem(addr); 31 if (ret) { 32 printf("dm_rtc_read() failed: %d\n", ret); 33 return CMD_RET_FAILURE; 34 } 35 return CMD_RET_SUCCESS; 36 } 37 38 while (len) { 39 r = min_t(int, len, sizeof(buf)); 40 ret = dm_rtc_read(dev, reg, buf, r); 41 if (ret) { 42 printf("dm_rtc_read() failed: %d\n", ret); 43 return CMD_RET_FAILURE; 44 } 45 print_buffer(reg, buf, 1, r, 0); 46 len -= r; 47 reg += r; 48 } 49 50 return CMD_RET_SUCCESS; 51} 52 53static int do_rtc_write(struct udevice *dev, int argc, char * const argv[]) 54{ 55 u8 buf[MAX_RTC_BYTES]; 56 int reg, len, ret; 57 const char *s; 58 int slen; 59 60 if (argc < 2 || argc > 3) 61 return CMD_RET_USAGE; 62 63 reg = hextoul(argv[0], NULL); 64 65 if (argc == 3) { 66 u8 *addr; 67 68 len = hextoul(argv[1], NULL); 69 addr = map_sysmem(hextoul(argv[2], NULL), len); 70 ret = dm_rtc_write(dev, reg, addr, len); 71 unmap_sysmem(addr); 72 if (ret) { 73 printf("dm_rtc_write() failed: %d\n", ret); 74 return CMD_RET_FAILURE; 75 } 76 return CMD_RET_SUCCESS; 77 } 78 79 s = argv[1]; 80 slen = strlen(s); 81 82 if (slen % 2) { 83 printf("invalid hex string\n"); 84 return CMD_RET_FAILURE; 85 } 86 87 while (slen) { 88 len = min_t(int, slen / 2, sizeof(buf)); 89 if (hex2bin(buf, s, len)) { 90 printf("invalid hex string\n"); 91 return CMD_RET_FAILURE; 92 } 93 94 ret = dm_rtc_write(dev, reg, buf, len); 95 if (ret) { 96 printf("dm_rtc_write() failed: %d\n", ret); 97 return CMD_RET_FAILURE; 98 } 99 s += 2 * len; 100 slen -= 2 * len; 101 } 102 103 return CMD_RET_SUCCESS; 104} 105 106int do_rtc(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) 107{ 108 static int curr_rtc; 109 struct udevice *dev; 110 int ret, idx; 111 112 if (argc < 2) 113 return CMD_RET_USAGE; 114 115 argc--; 116 argv++; 117 118 if (!strcmp(argv[0], "list")) { 119 struct uclass *uc; 120 121 idx = 0; 122 uclass_id_foreach_dev(UCLASS_RTC, dev, uc) { 123 printf("RTC #%d - %s\n", idx++, dev->name); 124 } 125 if (!idx) { 126 printf("*** no RTC devices available ***\n"); 127 return CMD_RET_FAILURE; 128 } 129 return CMD_RET_SUCCESS; 130 } 131 132 idx = curr_rtc; 133 if (!strcmp(argv[0], "dev") && argc >= 2) 134 idx = dectoul(argv[1], NULL); 135 136 ret = uclass_get_device(UCLASS_RTC, idx, &dev); 137 if (ret) { 138 printf("Cannot find RTC #%d: err=%d\n", idx, ret); 139 return CMD_RET_FAILURE; 140 } 141 142 if (!strcmp(argv[0], "dev")) { 143 /* Show the existing or newly selected RTC */ 144 if (argc >= 2) 145 curr_rtc = idx; 146 printf("RTC #%d - %s\n", idx, dev->name); 147 return CMD_RET_SUCCESS; 148 } 149 150 if (!strcmp(argv[0], "read")) 151 return do_rtc_read(dev, argc - 1, argv + 1); 152 153 if (!strcmp(argv[0], "write")) 154 return do_rtc_write(dev, argc - 1, argv + 1); 155 156 return CMD_RET_USAGE; 157} 158 159U_BOOT_CMD( 160 rtc, 5, 0, do_rtc, 161 "RTC subsystem", 162 "list - show available rtc devices\n" 163 "rtc dev [n] - show or set current rtc device\n" 164 "rtc read <reg> <count> - read and display 8-bit registers starting at <reg>\n" 165 "rtc read <reg> <count> <addr> - read 8-bit registers starting at <reg> to memory <addr>\n" 166 "rtc write <reg> <hexstring> - write 8-bit registers starting at <reg>\n" 167 "rtc write <reg> <count> <addr> - write from memory <addr> to 8-bit registers starting at <reg>\n" 168); 169