pd.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Power Domain test commands
  4. *
  5. * Copyright (C) 2020 Texas Instruments Incorporated, <www.ti.com>
  6. */
  7. #include <common.h>
  8. #include <command.h>
  9. #include <dm.h>
  10. #include <k3-dev.h>
  11. static const struct udevice_id ti_pd_of_match[] = {
  12. { .compatible = "ti,sci-pm-domain" },
  13. { /* sentinel */ }
  14. };
  15. static struct ti_k3_pd_platdata *ti_pd_find_data(void)
  16. {
  17. struct udevice *dev;
  18. int i = 0;
  19. while (1) {
  20. uclass_get_device(UCLASS_POWER_DOMAIN, i++, &dev);
  21. if (!dev)
  22. return NULL;
  23. if (device_is_compatible(dev,
  24. ti_pd_of_match[0].compatible))
  25. return dev_get_priv(dev);
  26. }
  27. return NULL;
  28. }
  29. static void dump_lpsc(struct ti_k3_pd_platdata *data, struct ti_pd *pd)
  30. {
  31. int i;
  32. struct ti_lpsc *lpsc;
  33. u8 state;
  34. static const char * const lpsc_states[] = {
  35. "swrstdis", "syncrst", "disable", "enable", "autosleep",
  36. "autowake", "unknown",
  37. };
  38. for (i = 0; i < data->num_lpsc; i++) {
  39. lpsc = &data->lpsc[i];
  40. if (lpsc->pd != pd)
  41. continue;
  42. state = lpsc_get_state(lpsc);
  43. if (state > ARRAY_SIZE(lpsc_states))
  44. state = ARRAY_SIZE(lpsc_states) - 1;
  45. printf(" LPSC%d: state=%s, usecount=%d\n",
  46. lpsc->id, lpsc_states[state], lpsc->usecount);
  47. }
  48. }
  49. static void dump_pd(struct ti_k3_pd_platdata *data, struct ti_psc *psc)
  50. {
  51. int i;
  52. struct ti_pd *pd;
  53. u8 state;
  54. static const char * const pd_states[] = {
  55. "off", "on", "unknown"
  56. };
  57. for (i = 0; i < data->num_pd; i++) {
  58. pd = &data->pd[i];
  59. if (pd->psc != psc)
  60. continue;
  61. state = ti_pd_state(pd);
  62. if (state > ARRAY_SIZE(pd_states))
  63. state = ARRAY_SIZE(pd_states) - 1;
  64. printf(" PD%d: state=%s, usecount=%d:\n",
  65. pd->id, pd_states[state], pd->usecount);
  66. dump_lpsc(data, pd);
  67. }
  68. }
  69. static void dump_psc(struct ti_k3_pd_platdata *data)
  70. {
  71. int i;
  72. struct ti_psc *psc;
  73. for (i = 0; i < data->num_psc; i++) {
  74. psc = &data->psc[i];
  75. printf("PSC%d [%p]:\n", psc->id, psc->base);
  76. dump_pd(data, psc);
  77. }
  78. }
  79. static int do_pd_dump(struct cmd_tbl *cmdtp, int flag, int argc,
  80. char *const argv[])
  81. {
  82. struct ti_k3_pd_platdata *data;
  83. data = ti_pd_find_data();
  84. if (!data)
  85. return CMD_RET_FAILURE;
  86. dump_psc(data);
  87. return 0;
  88. }
  89. static int do_pd_endis(int argc, char *const argv[], u8 state)
  90. {
  91. u32 psc_id;
  92. u32 lpsc_id;
  93. int i;
  94. struct ti_k3_pd_platdata *data;
  95. struct ti_lpsc *lpsc;
  96. int ret;
  97. if (argc < 3)
  98. return CMD_RET_FAILURE;
  99. data = ti_pd_find_data();
  100. if (!data)
  101. return CMD_RET_FAILURE;
  102. psc_id = dectoul(argv[1], NULL);
  103. lpsc_id = dectoul(argv[2], NULL);
  104. for (i = 0; i < data->num_lpsc; i++) {
  105. lpsc = &data->lpsc[i];
  106. if (lpsc->pd->psc->id != psc_id)
  107. continue;
  108. if (lpsc->id != lpsc_id)
  109. continue;
  110. printf("%s pd [PSC:%d,LPSC:%d]...\n",
  111. state == MDSTAT_STATE_ENABLE ? "Enabling" : "Disabling",
  112. psc_id, lpsc_id);
  113. ret = ti_lpsc_transition(lpsc, state);
  114. if (ret)
  115. return CMD_RET_FAILURE;
  116. else
  117. return 0;
  118. }
  119. printf("No matching psc/lpsc found.\n");
  120. return CMD_RET_FAILURE;
  121. }
  122. static int do_pd_enable(struct cmd_tbl *cmdtp, int flag, int argc,
  123. char *const argv[])
  124. {
  125. return do_pd_endis(argc, argv, MDSTAT_STATE_ENABLE);
  126. }
  127. static int do_pd_disable(struct cmd_tbl *cmdtp, int flag, int argc,
  128. char *const argv[])
  129. {
  130. return do_pd_endis(argc, argv, MDSTAT_STATE_SWRSTDISABLE);
  131. }
  132. static struct cmd_tbl cmd_pd[] = {
  133. U_BOOT_CMD_MKENT(dump, 1, 0, do_pd_dump, "", ""),
  134. U_BOOT_CMD_MKENT(enable, 3, 0, do_pd_enable, "", ""),
  135. U_BOOT_CMD_MKENT(disable, 3, 0, do_pd_disable, "", ""),
  136. };
  137. static int ti_do_pd(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
  138. {
  139. struct cmd_tbl *c;
  140. argc--;
  141. argv++;
  142. c = find_cmd_tbl(argv[0], cmd_pd, ARRAY_SIZE(cmd_pd));
  143. if (c)
  144. return c->cmd(cmdtp, flag, argc, argv);
  145. else
  146. return CMD_RET_USAGE;
  147. }
  148. U_BOOT_CMD(pd, 4, 1, ti_do_pd,
  149. "TI power domain control",
  150. #if CONFIG_IS_ENABLED(SYS_LONGHELP)
  151. "dump - show power domain status\n"
  152. "enable [psc] [lpsc] - enable power domain\n"
  153. "disable [psc] [lpsc] - disable power domain\n"
  154. #endif
  155. );