| // SPDX-License-Identifier: GPL-2.0+ | |
| #include <command.h> | |
| #include <display_options.h> | |
| #include <dm.h> | |
| #include <hexdump.h> | |
| #include <i2c.h> | |
| #include <mapmem.h> | |
| #include <rtc.h> | |
| #define MAX_RTC_BYTES 32 | |
| static int do_rtc_read(struct udevice *dev, int argc, char * const argv[]) | |
| { | |
| u8 buf[MAX_RTC_BYTES]; | |
| int reg, len, ret, r; | |
| if (argc < 2 || argc > 3) | |
| return CMD_RET_USAGE; | |
| reg = hextoul(argv[0], NULL); | |
| len = hextoul(argv[1], NULL); | |
| if (argc == 3) { | |
| u8 *addr; | |
| addr = map_sysmem(hextoul(argv[2], NULL), len); | |
| ret = dm_rtc_read(dev, reg, addr, len); | |
| unmap_sysmem(addr); | |
| if (ret) { | |
| printf("dm_rtc_read() failed: %d\n", ret); | |
| return CMD_RET_FAILURE; | |
| } | |
| return CMD_RET_SUCCESS; | |
| } | |
| while (len) { | |
| r = min_t(int, len, sizeof(buf)); | |
| ret = dm_rtc_read(dev, reg, buf, r); | |
| if (ret) { | |
| printf("dm_rtc_read() failed: %d\n", ret); | |
| return CMD_RET_FAILURE; | |
| } | |
| print_buffer(reg, buf, 1, r, 0); | |
| len -= r; | |
| reg += r; | |
| } | |
| return CMD_RET_SUCCESS; | |
| } | |
| static int do_rtc_write(struct udevice *dev, int argc, char * const argv[]) | |
| { | |
| u8 buf[MAX_RTC_BYTES]; | |
| int reg, len, ret; | |
| const char *s; | |
| int slen; | |
| if (argc < 2 || argc > 3) | |
| return CMD_RET_USAGE; | |
| reg = hextoul(argv[0], NULL); | |
| if (argc == 3) { | |
| u8 *addr; | |
| len = hextoul(argv[1], NULL); | |
| addr = map_sysmem(hextoul(argv[2], NULL), len); | |
| ret = dm_rtc_write(dev, reg, addr, len); | |
| unmap_sysmem(addr); | |
| if (ret) { | |
| printf("dm_rtc_write() failed: %d\n", ret); | |
| return CMD_RET_FAILURE; | |
| } | |
| return CMD_RET_SUCCESS; | |
| } | |
| s = argv[1]; | |
| slen = strlen(s); | |
| if (slen % 2) { | |
| printf("invalid hex string\n"); | |
| return CMD_RET_FAILURE; | |
| } | |
| while (slen) { | |
| len = min_t(int, slen / 2, sizeof(buf)); | |
| if (hex2bin(buf, s, len)) { | |
| printf("invalid hex string\n"); | |
| return CMD_RET_FAILURE; | |
| } | |
| ret = dm_rtc_write(dev, reg, buf, len); | |
| if (ret) { | |
| printf("dm_rtc_write() failed: %d\n", ret); | |
| return CMD_RET_FAILURE; | |
| } | |
| s += 2 * len; | |
| slen -= 2 * len; | |
| } | |
| return CMD_RET_SUCCESS; | |
| } | |
| int do_rtc(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) | |
| { | |
| static int curr_rtc; | |
| struct udevice *dev; | |
| int ret, idx; | |
| if (argc < 2) | |
| return CMD_RET_USAGE; | |
| argc--; | |
| argv++; | |
| if (!strcmp(argv[0], "list")) { | |
| struct uclass *uc; | |
| idx = 0; | |
| uclass_id_foreach_dev(UCLASS_RTC, dev, uc) { | |
| printf("RTC #%d - %s\n", idx++, dev->name); | |
| } | |
| if (!idx) { | |
| printf("*** no RTC devices available ***\n"); | |
| return CMD_RET_FAILURE; | |
| } | |
| return CMD_RET_SUCCESS; | |
| } | |
| idx = curr_rtc; | |
| if (!strcmp(argv[0], "dev") && argc >= 2) | |
| idx = dectoul(argv[1], NULL); | |
| ret = uclass_get_device(UCLASS_RTC, idx, &dev); | |
| if (ret) { | |
| printf("Cannot find RTC #%d: err=%d\n", idx, ret); | |
| return CMD_RET_FAILURE; | |
| } | |
| if (!strcmp(argv[0], "dev")) { | |
| /* Show the existing or newly selected RTC */ | |
| if (argc >= 2) | |
| curr_rtc = idx; | |
| printf("RTC #%d - %s\n", idx, dev->name); | |
| return CMD_RET_SUCCESS; | |
| } | |
| if (!strcmp(argv[0], "read")) | |
| return do_rtc_read(dev, argc - 1, argv + 1); | |
| if (!strcmp(argv[0], "write")) | |
| return do_rtc_write(dev, argc - 1, argv + 1); | |
| return CMD_RET_USAGE; | |
| } | |
| U_BOOT_CMD( | |
| rtc, 5, 0, do_rtc, | |
| "RTC subsystem", | |
| "list - show available rtc devices\n" | |
| "rtc dev [n] - show or set current rtc device\n" | |
| "rtc read <reg> <count> - read and display 8-bit registers starting at <reg>\n" | |
| "rtc read <reg> <count> <addr> - read 8-bit registers starting at <reg> to memory <addr>\n" | |
| "rtc write <reg> <hexstring> - write 8-bit registers starting at <reg>\n" | |
| "rtc write <reg> <count> <addr> - write from memory <addr> to 8-bit registers starting at <reg>\n" | |
| ); |