plat_console.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <common/debug.h>
  11. #include <common/fdt_fixup.h>
  12. #include <common/fdt_wrappers.h>
  13. #include <drivers/arm/dcc.h>
  14. #include <drivers/arm/pl011.h>
  15. #include <drivers/cadence/cdns_uart.h>
  16. #include <drivers/console.h>
  17. #include <libfdt.h>
  18. #include <plat_console.h>
  19. #include <plat_fdt.h>
  20. #include <platform_def.h>
  21. #include <plat_private.h>
  22. #if !(CONSOLE_IS(none))
  23. static console_t boot_console;
  24. static console_holder boot_hd_console;
  25. #if defined(CONSOLE_RUNTIME)
  26. static console_t runtime_console;
  27. static console_holder rt_hd_console;
  28. #endif
  29. #if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
  30. (!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
  31. !IS_TFA_IN_OCM(BL31_BASE)))
  32. static dt_uart_info_t dt_uart_info;
  33. #endif
  34. /**
  35. * register_console() - Registers the uart with console list.
  36. * @consoleh: Console holder structure with UART base address,
  37. * UART clock, UART buad rate, flags & console type
  38. * @console: Pointer to the console information structure.
  39. */
  40. static void register_console(const console_holder *consoleh, console_t *console)
  41. {
  42. int32_t rc = 0;
  43. switch (consoleh->console_type) {
  44. #if defined(PLAT_zynqmp)
  45. case CONSOLE_CDNS:
  46. rc = console_cdns_register(consoleh->base,
  47. consoleh->clk,
  48. consoleh->baud_rate,
  49. console);
  50. break;
  51. #else
  52. case CONSOLE_PL011:
  53. rc = console_pl011_register(consoleh->base,
  54. consoleh->clk,
  55. consoleh->baud_rate,
  56. console);
  57. break;
  58. #endif
  59. case CONSOLE_DCC:
  60. rc = console_dcc_register(console);
  61. break;
  62. default:
  63. INFO("Invalid console type\n");
  64. break;
  65. }
  66. if (rc == 0) {
  67. panic();
  68. }
  69. console_set_scope(console, consoleh->console_scope);
  70. }
  71. #if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
  72. (!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
  73. !IS_TFA_IN_OCM(BL31_BASE)))
  74. /**
  75. * get_baudrate() - Get the baudrate form DTB.
  76. * @dtb: Address of the Device Tree Blob (DTB).
  77. *
  78. * Return: On success returns the baudrate; on failure returns an error.
  79. */
  80. static int32_t get_baudrate(void *dtb)
  81. {
  82. int node;
  83. int32_t ret = 0;
  84. const char *prop, *path;
  85. char *end;
  86. int32_t baud_rate = 0;
  87. node = fdt_path_offset(dtb, "/secure-chosen");
  88. if (node < 0) {
  89. node = fdt_path_offset(dtb, "/chosen");
  90. if (node < 0) {
  91. ret = -FDT_ERR_NOTFOUND;
  92. goto error;
  93. }
  94. }
  95. prop = fdt_getprop(dtb, node, "stdout-path", NULL);
  96. if (prop == NULL) {
  97. ret = -FDT_ERR_NOTFOUND;
  98. goto error;
  99. }
  100. /* Parse string serial0:115200n8 */
  101. path = strchr(prop, ':');
  102. if (!path) {
  103. ret = -FDT_ERR_NOTFOUND;
  104. goto error;
  105. } else {
  106. baud_rate = strtoul(path + 1, &end, 10);
  107. if (baud_rate == 0 && end == path) {
  108. ERROR("Conversion error occurred: %d\n", baud_rate);
  109. ret = -FDT_ERR_NOTFOUND;
  110. goto error;
  111. }
  112. ret = baud_rate;
  113. }
  114. error:
  115. return ret;
  116. }
  117. /**
  118. * get_node_status() - Get the DTB node status.
  119. * @dtb: Address of the Device Tree Blob (DTB).
  120. * @node: Node address in the device tree.
  121. *
  122. * Return: On success, it returns 1; on failure, it returns an 0.
  123. */
  124. static uint32_t get_node_status(void *dtb, int node)
  125. {
  126. const char *status_cell;
  127. uint32_t status = 0;
  128. status_cell = fdt_getprop(dtb, node, "status", NULL);
  129. if (!status_cell || strcmp(status_cell, "okay") == 0) {
  130. status = 1;
  131. } else {
  132. status = 0;
  133. }
  134. return status;
  135. }
  136. /**
  137. * fdt_add_uart_info() - Add DTB information to a UART structure.
  138. * @info: Pointer to the UART information structure.
  139. * @node: Node address in the device tree.
  140. * @dtb: Address of the Device Tree Blob(DTB).
  141. *
  142. * Return: On success, it returns 0; on failure, it returns -1 or -FDT_ERR_NOTFOUND.
  143. */
  144. static int32_t fdt_add_uart_info(dt_uart_info_t *info, int node, void *dtb)
  145. {
  146. uintptr_t base_addr;
  147. const char *com;
  148. int32_t ret = 0;
  149. uint32_t status;
  150. com = fdt_getprop(dtb, node, "compatible", NULL);
  151. if (com != NULL) {
  152. strlcpy(info->compatible, com, sizeof(info->compatible));
  153. } else {
  154. ERROR("Compatible property not found in DTB node\n");
  155. ret = -FDT_ERR_NOTFOUND;
  156. goto error;
  157. }
  158. status = get_node_status(dtb, node);
  159. if (status == 0) {
  160. ERROR("Uart node is disabled in DTB\n");
  161. ret = -FDT_ERR_NOTFOUND;
  162. goto error;
  163. }
  164. if (strncmp(info->compatible, DT_UART_DCC_COMPAT, strlen(DT_UART_DCC_COMPAT)) != 0) {
  165. ret = fdt_get_reg_props_by_index(dtb, node, 0, &base_addr, NULL);
  166. if (ret >= 0) {
  167. info->base = base_addr;
  168. } else {
  169. ERROR("Failed to retrieve base address. Error code: %d\n", ret);
  170. ret = -FDT_ERR_NOTFOUND;
  171. goto error;
  172. }
  173. info->baud_rate = get_baudrate(dtb);
  174. if (strncmp(info->compatible, DT_UART_CAD_COMPAT,
  175. strlen(DT_UART_CAD_COMPAT)) == 0) {
  176. info->console_type = CONSOLE_CDNS;
  177. } else if (strncmp(info->compatible, DT_UART_PL011_COMPAT,
  178. strlen(DT_UART_PL011_COMPAT)) == 0) {
  179. info->console_type = CONSOLE_PL011;
  180. } else {
  181. ERROR("Incompatible uart node in DTB\n");
  182. ret = -FDT_ERR_NOTFOUND;
  183. }
  184. } else {
  185. info->console_type = CONSOLE_DCC;
  186. }
  187. error:
  188. return ret;
  189. }
  190. /**
  191. * fdt_get_uart_info() - Get the uart information form DTB.
  192. * @info: Pointer to the UART information structure.
  193. *
  194. * Return: On success, it returns 0; on failure, it returns an error+reason.
  195. */
  196. static int fdt_get_uart_info(dt_uart_info_t *info)
  197. {
  198. int node = 0, ret = 0;
  199. void *dtb = (void *)XILINX_OF_BOARD_DTB_ADDR;
  200. ret = is_valid_dtb(dtb);
  201. if (ret < 0) {
  202. ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret);
  203. goto error;
  204. }
  205. node = fdt_get_stdout_node_offset(dtb);
  206. if (node < 0) {
  207. ERROR("DT get stdout node failed : %d\n", node);
  208. goto error;
  209. }
  210. ret = fdt_add_uart_info(info, node, dtb);
  211. if (ret < 0) {
  212. ERROR("Failed to add DT UART info: %d\n", ret);
  213. goto error;
  214. }
  215. error:
  216. return ret;
  217. }
  218. #endif
  219. void setup_console(void)
  220. {
  221. /* This is hardcoded console setup just in case that DTB console fails */
  222. boot_hd_console.base = (uintptr_t)UART_BASE;
  223. boot_hd_console.baud_rate = (uint32_t)UART_BAUDRATE;
  224. boot_hd_console.clk = get_uart_clk();
  225. boot_hd_console.console_scope = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH;
  226. boot_hd_console.console_type = UART_TYPE;
  227. /* For DT code decoding uncomment console registration below */
  228. /* register_console(&boot_hd_console, &boot_console); */
  229. #if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
  230. (!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
  231. !IS_TFA_IN_OCM(BL31_BASE)))
  232. /* Parse DTB console for UART information */
  233. if (fdt_get_uart_info(&dt_uart_info) == 0) {
  234. if (CONSOLE_IS(dtb)) {
  235. boot_hd_console.base = dt_uart_info.base;
  236. boot_hd_console.baud_rate = dt_uart_info.baud_rate;
  237. boot_hd_console.console_type = dt_uart_info.console_type;
  238. }
  239. } else {
  240. ERROR("Failed to initialize DT console or console node is disabled\n");
  241. }
  242. #endif
  243. /* Initialize the boot console */
  244. register_console(&boot_hd_console, &boot_console);
  245. INFO("BL31: Early console setup\n");
  246. #ifdef CONSOLE_RUNTIME
  247. #if (RT_CONSOLE_IS(dtb) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
  248. (!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
  249. !IS_TFA_IN_OCM(BL31_BASE)))
  250. rt_hd_console.base = dt_uart_info.base;
  251. rt_hd_console.baud_rate = dt_uart_info.baud_rate;
  252. rt_hd_console.console_type = dt_uart_info.console_type;
  253. #else
  254. rt_hd_console.base = (uintptr_t)RT_UART_BASE;
  255. rt_hd_console.baud_rate = (uint32_t)UART_BAUDRATE;
  256. rt_hd_console.console_type = RT_UART_TYPE;
  257. #endif
  258. if ((rt_hd_console.console_type == boot_hd_console.console_type) &&
  259. (rt_hd_console.base == boot_hd_console.base)) {
  260. console_set_scope(&boot_console,
  261. CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH | CONSOLE_FLAG_RUNTIME);
  262. INFO("Successfully initialized runtime console\n");
  263. } else {
  264. rt_hd_console.clk = get_uart_clk();
  265. rt_hd_console.console_scope = CONSOLE_FLAG_RUNTIME;
  266. register_console(&rt_hd_console, &runtime_console);
  267. INFO("Successfully initialized new runtime console\n");
  268. }
  269. #endif
  270. }
  271. #else
  272. void setup_console(void)
  273. {
  274. }
  275. #endif