xref: /rk3399_ARM-atf/plat/xilinx/common/plat_console.c (revision f84a4c5cd79b2bbd68197a5186d01cdceb87b177)
139234622SPrasad Kummari /*
239234622SPrasad Kummari  * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
339234622SPrasad Kummari  *
439234622SPrasad Kummari  * SPDX-License-Identifier: BSD-3-Clause
539234622SPrasad Kummari  */
639234622SPrasad Kummari 
739234622SPrasad Kummari #include <assert.h>
839234622SPrasad Kummari #include <errno.h>
939234622SPrasad Kummari #include <stdlib.h>
1039234622SPrasad Kummari #include <string.h>
1139234622SPrasad Kummari 
1239234622SPrasad Kummari #include <common/debug.h>
1339234622SPrasad Kummari #include <common/fdt_fixup.h>
1439234622SPrasad Kummari #include <common/fdt_wrappers.h>
1539234622SPrasad Kummari #include <drivers/arm/dcc.h>
1639234622SPrasad Kummari #include <drivers/arm/pl011.h>
1739234622SPrasad Kummari #include <drivers/cadence/cdns_uart.h>
1839234622SPrasad Kummari #include <drivers/console.h>
1939234622SPrasad Kummari #include <libfdt.h>
2039234622SPrasad Kummari #include <plat_console.h>
21e2d9dfe2SPrasad Kummari #include <plat_fdt.h>
2239234622SPrasad Kummari 
2339234622SPrasad Kummari #include <platform_def.h>
2439234622SPrasad Kummari #include <plat_private.h>
2539234622SPrasad Kummari 
26a542b9c1SPrasad Kummari static console_t boot_console;
2739234622SPrasad Kummari 
2839234622SPrasad Kummari #if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
2939234622SPrasad Kummari /**
3039234622SPrasad Kummari  * get_baudrate() - Get the baudrate form DTB.
3139234622SPrasad Kummari  * @dtb: Address of the Device Tree Blob (DTB).
3239234622SPrasad Kummari  *
3339234622SPrasad Kummari  * Return: On success returns the baudrate; on failure returns an error.
3439234622SPrasad Kummari  */
3539234622SPrasad Kummari static int32_t get_baudrate(void *dtb)
3639234622SPrasad Kummari {
3739234622SPrasad Kummari 	int node;
3839234622SPrasad Kummari 	int32_t ret = 0;
3939234622SPrasad Kummari 	const char *prop, *path;
4039234622SPrasad Kummari 	char *end;
4139234622SPrasad Kummari 	int32_t baud_rate = 0;
4239234622SPrasad Kummari 
4339234622SPrasad Kummari 	node = fdt_path_offset(dtb, "/secure-chosen");
4439234622SPrasad Kummari 	if (node < 0) {
4539234622SPrasad Kummari 		node = fdt_path_offset(dtb, "/chosen");
4639234622SPrasad Kummari 		if (node < 0) {
4739234622SPrasad Kummari 			ret = -FDT_ERR_NOTFOUND;
4839234622SPrasad Kummari 			goto error;
4939234622SPrasad Kummari 		}
5039234622SPrasad Kummari 	}
5139234622SPrasad Kummari 
5239234622SPrasad Kummari 	prop = fdt_getprop(dtb, node, "stdout-path", NULL);
5339234622SPrasad Kummari 	if (prop == NULL) {
5439234622SPrasad Kummari 		ret = -FDT_ERR_NOTFOUND;
5539234622SPrasad Kummari 		goto error;
5639234622SPrasad Kummari 	}
5739234622SPrasad Kummari 
5839234622SPrasad Kummari 	/* Parse string serial0:115200n8 */
5939234622SPrasad Kummari 	path = strchr(prop, ':');
6039234622SPrasad Kummari 	if (!path) {
6139234622SPrasad Kummari 		ret = -FDT_ERR_NOTFOUND;
6239234622SPrasad Kummari 		goto error;
6339234622SPrasad Kummari 	} else {
6439234622SPrasad Kummari 
6539234622SPrasad Kummari 		baud_rate = strtoul(path + 1, &end, 10);
6639234622SPrasad Kummari 		if (baud_rate == 0 && end == path) {
6739234622SPrasad Kummari 			ERROR("Conversion error occurred: %d\n", baud_rate);
6839234622SPrasad Kummari 			ret = -FDT_ERR_NOTFOUND;
6939234622SPrasad Kummari 			goto error;
7039234622SPrasad Kummari 		}
7139234622SPrasad Kummari 		ret = baud_rate;
7239234622SPrasad Kummari 	}
7339234622SPrasad Kummari 
7439234622SPrasad Kummari error:
7539234622SPrasad Kummari 	return ret;
7639234622SPrasad Kummari }
7739234622SPrasad Kummari 
7839234622SPrasad Kummari /**
7939234622SPrasad Kummari  * get_node_status() - Get the DTB node status.
8039234622SPrasad Kummari  * @dtb: Address of the Device Tree Blob (DTB).
8139234622SPrasad Kummari  * @node: Node address in the device tree.
8239234622SPrasad Kummari  *
8339234622SPrasad Kummari  * Return: On success, it returns 1; on failure, it returns an 0.
8439234622SPrasad Kummari  */
8539234622SPrasad Kummari static uint32_t get_node_status(void *dtb, int node)
8639234622SPrasad Kummari {
8739234622SPrasad Kummari 	const char *status_cell;
8839234622SPrasad Kummari 	uint32_t status = 0;
8939234622SPrasad Kummari 
9039234622SPrasad Kummari 	status_cell = fdt_getprop(dtb, node, "status", NULL);
9139234622SPrasad Kummari 	if (!status_cell || strcmp(status_cell, "okay") == 0) {
9239234622SPrasad Kummari 		status = 1;
9339234622SPrasad Kummari 	} else {
9439234622SPrasad Kummari 		status = 0;
9539234622SPrasad Kummari 	}
9639234622SPrasad Kummari 
9739234622SPrasad Kummari 	return status;
9839234622SPrasad Kummari }
9939234622SPrasad Kummari 
10039234622SPrasad Kummari /**
10139234622SPrasad Kummari  * fdt_add_uart_info() - Add DTB information to a UART structure.
10239234622SPrasad Kummari  * @info: Pointer to the UART information structure.
10339234622SPrasad Kummari  * @node: Node address in the device tree.
10439234622SPrasad Kummari  * @dtb: Address of the Device Tree Blob(DTB).
10539234622SPrasad Kummari  *
10639234622SPrasad Kummari  * Return: On success, it returns 1; on failure, it returns an 0.
10739234622SPrasad Kummari  */
10839234622SPrasad Kummari static uint32_t fdt_add_uart_info(dt_uart_info_t *info, int node, void *dtb)
10939234622SPrasad Kummari {
11039234622SPrasad Kummari 	uintptr_t base_addr;
11139234622SPrasad Kummari 	const char *com;
1128eb6a1daSPrasad Kummari 	int32_t ret = 0;
11339234622SPrasad Kummari 
11439234622SPrasad Kummari 	com = fdt_getprop(dtb, node, "compatible", NULL);
11539234622SPrasad Kummari 	if (com != NULL) {
11639234622SPrasad Kummari 		strlcpy(info->compatible, com, sizeof(info->compatible));
11739234622SPrasad Kummari 	} else {
11839234622SPrasad Kummari 		ERROR("Compatible property not found in DTB node\n");
11939234622SPrasad Kummari 		ret  = -FDT_ERR_NOTFOUND;
12039234622SPrasad Kummari 		goto error;
12139234622SPrasad Kummari 	}
12239234622SPrasad Kummari 
12339234622SPrasad Kummari 	ret = fdt_get_reg_props_by_index(dtb, node, 0, &base_addr, NULL);
12439234622SPrasad Kummari 	if (ret >= 0) {
12539234622SPrasad Kummari 		info->base = base_addr;
12639234622SPrasad Kummari 	} else {
12739234622SPrasad Kummari 		ERROR("Failed to retrieve base address. Error code: %d\n", ret);
12839234622SPrasad Kummari 		ret  = -FDT_ERR_NOTFOUND;
12939234622SPrasad Kummari 		goto error;
13039234622SPrasad Kummari 	}
13139234622SPrasad Kummari 
13239234622SPrasad Kummari 	info->status = get_node_status(dtb, node);
13339234622SPrasad Kummari 	info->baud_rate = get_baudrate(dtb);
13439234622SPrasad Kummari 
13539234622SPrasad Kummari error:
13639234622SPrasad Kummari 	return ret;
13739234622SPrasad Kummari }
13839234622SPrasad Kummari 
13939234622SPrasad Kummari /**
14039234622SPrasad Kummari  * fdt_get_uart_info() - Get the uart information form DTB.
14139234622SPrasad Kummari  * @info: Pointer to the UART information structure.
14239234622SPrasad Kummari  *
14339234622SPrasad Kummari  * Return: On success, it returns 0; on failure, it returns an error+reason.
14439234622SPrasad Kummari  */
14539234622SPrasad Kummari static int fdt_get_uart_info(dt_uart_info_t *info)
14639234622SPrasad Kummari {
1478eb6a1daSPrasad Kummari 	int node = 0, ret = 0;
14839234622SPrasad Kummari 	void *dtb = (void *)XILINX_OF_BOARD_DTB_ADDR;
14939234622SPrasad Kummari 
150e2d9dfe2SPrasad Kummari 	ret = is_valid_dtb(dtb);
15139234622SPrasad Kummari 	if (ret < 0) {
15239234622SPrasad Kummari 		ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret);
15339234622SPrasad Kummari 		ret  = -FDT_ERR_NOTFOUND;
15439234622SPrasad Kummari 		goto error;
15539234622SPrasad Kummari 	}
15639234622SPrasad Kummari 
15739234622SPrasad Kummari 	node = fdt_get_stdout_node_offset(dtb);
15839234622SPrasad Kummari 	if (node < 0) {
15939234622SPrasad Kummari 		ERROR("DT get stdout node failed : %d\n", node);
16039234622SPrasad Kummari 		ret  = -FDT_ERR_NOTFOUND;
16139234622SPrasad Kummari 		goto error;
16239234622SPrasad Kummari 	}
16339234622SPrasad Kummari 
16439234622SPrasad Kummari 	ret = fdt_add_uart_info(info, node, dtb);
16539234622SPrasad Kummari 	if (ret < 0) {
16639234622SPrasad Kummari 		ERROR("Failed to add DT UART info: %d\n", ret);
16739234622SPrasad Kummari 		ret  = -FDT_ERR_NOTFOUND;
16839234622SPrasad Kummari 		goto error;
16939234622SPrasad Kummari 	}
17039234622SPrasad Kummari 
17139234622SPrasad Kummari error:
17239234622SPrasad Kummari 	return ret;
17339234622SPrasad Kummari }
17439234622SPrasad Kummari 
17539234622SPrasad Kummari /**
17639234622SPrasad Kummari  * check_fdt_uart_info() - Check early uart info with DTB uart info.
17739234622SPrasad Kummari  * @info: Pointer to the UART information structure.
17839234622SPrasad Kummari  *
17939234622SPrasad Kummari  * Return: On success, it returns 0; on failure, it returns an error+reason.
18039234622SPrasad Kummari  */
1818eb6a1daSPrasad Kummari static int32_t check_fdt_uart_info(dt_uart_info_t *info)
18239234622SPrasad Kummari {
1838eb6a1daSPrasad Kummari 	int32_t ret = 0;
18439234622SPrasad Kummari 
18539234622SPrasad Kummari 	if (info->status == 0) {
18639234622SPrasad Kummari 		ret = -ENODEV;
18739234622SPrasad Kummari 		goto error;
18839234622SPrasad Kummari 	}
18939234622SPrasad Kummari 
190a542b9c1SPrasad Kummari 	if ((info->base == boot_console.base) &&
19139234622SPrasad Kummari 	   (info->baud_rate == UART_BAUDRATE) && !CONSOLE_IS(dcc)) {
19239234622SPrasad Kummari 		ret = -ENODEV;
19339234622SPrasad Kummari 		goto error;
19439234622SPrasad Kummari 	}
19539234622SPrasad Kummari 
19639234622SPrasad Kummari error:
19739234622SPrasad Kummari 	return ret;
19839234622SPrasad Kummari }
19939234622SPrasad Kummari 
20039234622SPrasad Kummari /**
201a542b9c1SPrasad Kummari  * console_end() - Unregister the console_t instance form the console list.
202a542b9c1SPrasad Kummari  * @console: Pointer to the console information structure.
20339234622SPrasad Kummari  */
204a542b9c1SPrasad Kummari static void console_end(console_t *console)
20539234622SPrasad Kummari {
20639234622SPrasad Kummari 	if (CONSOLE_IS(dcc)) {
20739234622SPrasad Kummari 		console_dcc_unregister();
20839234622SPrasad Kummari 	} else {
209a542b9c1SPrasad Kummari 		if (console != NULL) {
21039234622SPrasad Kummari 			console_flush();
211a542b9c1SPrasad Kummari 			(void)console_unregister(console);
212a542b9c1SPrasad Kummari 		}
21339234622SPrasad Kummari 	}
21439234622SPrasad Kummari }
21539234622SPrasad Kummari 
21639234622SPrasad Kummari /**
217*f84a4c5cSPrasad Kummari  * register_console() - Registers the runtime uart with console list.
218*f84a4c5cSPrasad Kummari  * @uart_base: UART base address
21939234622SPrasad Kummari  * @clock: UART clock.
220*f84a4c5cSPrasad Kummari  * @baud_rate: UART buad rate
221*f84a4c5cSPrasad Kummari  * @console: Pointer to the console information structure.
222*f84a4c5cSPrasad Kummari  * @flags: console flags.
22339234622SPrasad Kummari  */
224*f84a4c5cSPrasad Kummari static void register_console(uintptr_t uart_base, uint32_t clock,
225*f84a4c5cSPrasad Kummari 			     uint32_t baud_rate, console_t *console,
226*f84a4c5cSPrasad Kummari 			     uint32_t flags)
22739234622SPrasad Kummari {
2288eb6a1daSPrasad Kummari 	int32_t rc;
22939234622SPrasad Kummari 
23039234622SPrasad Kummari #if defined(PLAT_zynqmp)
231*f84a4c5cSPrasad Kummari 	rc = console_cdns_register(uart_base,
23239234622SPrasad Kummari 				   clock,
233*f84a4c5cSPrasad Kummari 				   baud_rate,
234*f84a4c5cSPrasad Kummari 				   console);
23539234622SPrasad Kummari #else
236*f84a4c5cSPrasad Kummari 	rc = console_pl011_register(uart_base,
23739234622SPrasad Kummari 				    clock,
238*f84a4c5cSPrasad Kummari 				    baud_rate,
239*f84a4c5cSPrasad Kummari 				    console);
24039234622SPrasad Kummari #endif
24139234622SPrasad Kummari 	if (rc == 0) {
24239234622SPrasad Kummari 		panic();
24339234622SPrasad Kummari 	}
24439234622SPrasad Kummari 
245*f84a4c5cSPrasad Kummari 	console_set_scope(console, flags);
24639234622SPrasad Kummari }
24739234622SPrasad Kummari 
24839234622SPrasad Kummari /**
24900a68427SPrasad Kummari  * dt_console_init() - Initializes the DT console information.
25039234622SPrasad Kummari  * @uart_info: Pointer to the UART information structure.
251a542b9c1SPrasad Kummari  * @console: Pointer to the console information structure.
25239234622SPrasad Kummari  * @clock: UART clock.
25339234622SPrasad Kummari  *
25439234622SPrasad Kummari  * Return: On success, it returns 0; on failure, it returns an error+reason;
25539234622SPrasad Kummari  */
25600a68427SPrasad Kummari static int32_t dt_console_init(dt_uart_info_t *uart_info,
257a542b9c1SPrasad Kummari 			  console_t *console,
25839234622SPrasad Kummari 			  uint32_t clock)
25939234622SPrasad Kummari {
26039234622SPrasad Kummari 	int32_t rc = 0;
261*f84a4c5cSPrasad Kummari 	static console_t dt_console;
26239234622SPrasad Kummari 
26339234622SPrasad Kummari 	/* Parse UART information from Device Tree Blob (DTB) */
26439234622SPrasad Kummari 	rc = fdt_get_uart_info(uart_info);
26539234622SPrasad Kummari 	if (rc < 0) {
26639234622SPrasad Kummari 		rc = -FDT_ERR_NOTFOUND;
2678eb6a1daSPrasad Kummari 		goto error;
26839234622SPrasad Kummari 	}
26939234622SPrasad Kummari 
27039234622SPrasad Kummari 	if (strncmp(uart_info->compatible, DT_UART_COMPAT,
27139234622SPrasad Kummari 		   strlen(DT_UART_COMPAT)) == 0) {
27239234622SPrasad Kummari 
27339234622SPrasad Kummari 		if (check_fdt_uart_info(uart_info) == 0) {
274*f84a4c5cSPrasad Kummari 			register_console(uart_info->base, clock,
275*f84a4c5cSPrasad Kummari 					 uart_info->baud_rate, &dt_console,
276*f84a4c5cSPrasad Kummari 					 CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME
277*f84a4c5cSPrasad Kummari 					 | CONSOLE_FLAG_CRASH);
278a542b9c1SPrasad Kummari 			console_end(console);
279*f84a4c5cSPrasad Kummari 			INFO("DTB console setup\n");
28039234622SPrasad Kummari 		} else {
28139234622SPrasad Kummari 			INFO("Early console and DTB console are same\n");
28239234622SPrasad Kummari 		}
28339234622SPrasad Kummari 	} else if (strncmp(uart_info->compatible, DT_UART_DCC_COMPAT,
28439234622SPrasad Kummari 			  strlen(DT_UART_DCC_COMPAT)) == 0) {
28539234622SPrasad Kummari 		rc = console_dcc_register();
28639234622SPrasad Kummari 		if (rc == 0) {
28739234622SPrasad Kummari 			panic();
28839234622SPrasad Kummari 		}
289a542b9c1SPrasad Kummari 		console_end(console);
29039234622SPrasad Kummari 	} else {
29139234622SPrasad Kummari 		WARN("BL31: No console device found in DT.\n");
29239234622SPrasad Kummari 	}
29339234622SPrasad Kummari 
2948eb6a1daSPrasad Kummari error:
29539234622SPrasad Kummari 	return rc;
29639234622SPrasad Kummari }
29739234622SPrasad Kummari #endif
29839234622SPrasad Kummari 
29939234622SPrasad Kummari void setup_console(void)
30039234622SPrasad Kummari {
3018eb6a1daSPrasad Kummari 	int32_t rc;
30239234622SPrasad Kummari 	uint32_t uart_clk = get_uart_clk();
30339234622SPrasad Kummari 
30439234622SPrasad Kummari #if defined(PLAT_zynqmp)
30539234622SPrasad Kummari 	if (CONSOLE_IS(cadence) || (CONSOLE_IS(cadence1))) {
30639234622SPrasad Kummari 		rc = console_cdns_register(UART_BASE,
30739234622SPrasad Kummari 					   uart_clk,
30839234622SPrasad Kummari 					   UART_BAUDRATE,
309a542b9c1SPrasad Kummari 					   &boot_console);
31039234622SPrasad Kummari 		if (rc == 0) {
31139234622SPrasad Kummari 			panic();
31239234622SPrasad Kummari 		}
31339234622SPrasad Kummari 
314a542b9c1SPrasad Kummari 		console_set_scope(&boot_console, CONSOLE_FLAG_BOOT |
31539234622SPrasad Kummari 				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
31639234622SPrasad Kummari 	}
31739234622SPrasad Kummari #else
31839234622SPrasad Kummari 	if (CONSOLE_IS(pl011) || (CONSOLE_IS(pl011_1))) {
31939234622SPrasad Kummari 		/* Initialize the console to provide early debug support */
32039234622SPrasad Kummari 		rc = console_pl011_register((uint32_t)UART_BASE,
32139234622SPrasad Kummari 					   uart_clk,
32239234622SPrasad Kummari 					   (uint32_t)UART_BAUDRATE,
323a542b9c1SPrasad Kummari 					   &boot_console);
32439234622SPrasad Kummari 		if (rc == 0) {
32539234622SPrasad Kummari 			panic();
32639234622SPrasad Kummari 		}
32739234622SPrasad Kummari 
328a542b9c1SPrasad Kummari 		console_set_scope(&boot_console, CONSOLE_FLAG_BOOT |
32939234622SPrasad Kummari 				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
33039234622SPrasad Kummari 	}
33139234622SPrasad Kummari #endif
33239234622SPrasad Kummari 	if (CONSOLE_IS(dcc)) {
33339234622SPrasad Kummari 		/* Initialize the dcc console for debug */
33439234622SPrasad Kummari 		rc = console_dcc_register();
33539234622SPrasad Kummari 		if (rc == 0) {
33639234622SPrasad Kummari 			panic();
33739234622SPrasad Kummari 		}
33839234622SPrasad Kummari 	}
33939234622SPrasad Kummari 	INFO("BL31: Early console setup\n");
34039234622SPrasad Kummari 
34139234622SPrasad Kummari #if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
34239234622SPrasad Kummari 	static dt_uart_info_t uart_info = {0};
34339234622SPrasad Kummari 
34400a68427SPrasad Kummari 	/* Initialize the DTB console using UART information from the DTB */
345a542b9c1SPrasad Kummari 	rc = dt_console_init(&uart_info, &boot_console, uart_clk);
34639234622SPrasad Kummari 	if (rc < 0) {
34700a68427SPrasad Kummari 		ERROR("Failed to initialize DT console: %d\n", rc);
34839234622SPrasad Kummari 	}
34939234622SPrasad Kummari #endif
35039234622SPrasad Kummari }
351