misc.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2020 Wind River Systems, Inc.
  4. *
  5. * Author:
  6. * Bin Meng <bin.meng@windriver.com>
  7. *
  8. * A command interface to access misc devices with MISC uclass driver APIs.
  9. */
  10. #include <common.h>
  11. #include <command.h>
  12. #include <dm.h>
  13. #include <errno.h>
  14. #include <misc.h>
  15. enum misc_op {
  16. MISC_OP_READ,
  17. MISC_OP_WRITE
  18. };
  19. static char *misc_op_str[] = {
  20. "read",
  21. "write"
  22. };
  23. static int do_misc_list(struct cmd_tbl *cmdtp, int flag,
  24. int argc, char *const argv[])
  25. {
  26. struct udevice *dev;
  27. printf("Device Index Driver\n");
  28. printf("-------------------------------------\n");
  29. for (uclass_first_device(UCLASS_MISC, &dev);
  30. dev;
  31. uclass_next_device(&dev)) {
  32. printf("%-20s %5d %10s\n", dev->name, dev_seq(dev),
  33. dev->driver->name);
  34. }
  35. return 0;
  36. }
  37. static int do_misc_op(struct cmd_tbl *cmdtp, int flag,
  38. int argc, char *const argv[], enum misc_op op)
  39. {
  40. int (*misc_op)(struct udevice *, int, void *, int);
  41. struct udevice *dev;
  42. int offset;
  43. void *buf;
  44. int size;
  45. int ret;
  46. ret = uclass_get_device_by_name(UCLASS_MISC, argv[0], &dev);
  47. if (ret) {
  48. printf("Unable to find device %s\n", argv[0]);
  49. return ret;
  50. }
  51. offset = hextoul(argv[1], NULL);
  52. buf = (void *)hextoul(argv[2], NULL);
  53. size = hextoul(argv[3], NULL);
  54. if (op == MISC_OP_READ)
  55. misc_op = misc_read;
  56. else
  57. misc_op = misc_write;
  58. ret = misc_op(dev, offset, buf, size);
  59. if (ret < 0) {
  60. if (ret == -ENOSYS) {
  61. printf("The device does not support %s\n",
  62. misc_op_str[op]);
  63. ret = 0;
  64. }
  65. } else {
  66. if (ret == size)
  67. ret = 0;
  68. else
  69. printf("Partially %s %d bytes\n", misc_op_str[op], ret);
  70. }
  71. return ret;
  72. }
  73. static int do_misc_read(struct cmd_tbl *cmdtp, int flag,
  74. int argc, char *const argv[])
  75. {
  76. return do_misc_op(cmdtp, flag, argc, argv, MISC_OP_READ);
  77. }
  78. static int do_misc_write(struct cmd_tbl *cmdtp, int flag,
  79. int argc, char *const argv[])
  80. {
  81. return do_misc_op(cmdtp, flag, argc, argv, MISC_OP_WRITE);
  82. }
  83. static struct cmd_tbl misc_commands[] = {
  84. U_BOOT_CMD_MKENT(list, 0, 1, do_misc_list, "", ""),
  85. U_BOOT_CMD_MKENT(read, 4, 1, do_misc_read, "", ""),
  86. U_BOOT_CMD_MKENT(write, 4, 1, do_misc_write, "", ""),
  87. };
  88. static int do_misc(struct cmd_tbl *cmdtp, int flag,
  89. int argc, char *const argv[])
  90. {
  91. struct cmd_tbl *misc_cmd;
  92. int ret;
  93. if (argc < 2)
  94. return CMD_RET_USAGE;
  95. misc_cmd = find_cmd_tbl(argv[1], misc_commands,
  96. ARRAY_SIZE(misc_commands));
  97. argc -= 2;
  98. argv += 2;
  99. if (!misc_cmd || argc != misc_cmd->maxargs)
  100. return CMD_RET_USAGE;
  101. ret = misc_cmd->cmd(misc_cmd, flag, argc, argv);
  102. return cmd_process_error(misc_cmd, ret);
  103. }
  104. U_BOOT_CMD(
  105. misc, 6, 1, do_misc,
  106. "Access miscellaneous devices with MISC uclass driver APIs",
  107. "list - list all miscellaneous devices\n"
  108. "misc read name offset addr len - read `len' bytes starting at\n"
  109. " `offset' of device `name'\n"
  110. " to memory at `addr'\n"
  111. "misc write name offset addr len - write `len' bytes starting at\n"
  112. " `offset' of device `name'\n"
  113. " from memory at `addr'"
  114. );