xref: /rk3399_ARM-atf/plat/xilinx/common/plat_console.c (revision a542b9c1deef0d2a69dd712dc26fb92763b8ec36)
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 
26*a542b9c1SPrasad 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 
190*a542b9c1SPrasad 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 /**
201*a542b9c1SPrasad Kummari  * console_end() - Unregister the console_t instance form the console list.
202*a542b9c1SPrasad Kummari  * @console: Pointer to the console information structure.
20339234622SPrasad Kummari  */
204*a542b9c1SPrasad Kummari static void console_end(console_t *console)
20539234622SPrasad Kummari {
20639234622SPrasad Kummari 	if (CONSOLE_IS(dcc)) {
20739234622SPrasad Kummari 		console_dcc_unregister();
20839234622SPrasad Kummari 	} else {
209*a542b9c1SPrasad Kummari 		if (console != NULL) {
21039234622SPrasad Kummari 			console_flush();
211*a542b9c1SPrasad Kummari 			(void)console_unregister(console);
212*a542b9c1SPrasad Kummari 		}
21339234622SPrasad Kummari 	}
21439234622SPrasad Kummari }
21539234622SPrasad Kummari 
21639234622SPrasad Kummari /**
21739234622SPrasad Kummari  * setup_runtime_console() - Registers the runtime uart with console list.
21839234622SPrasad Kummari  * @clock: UART clock.
21939234622SPrasad Kummari  * @info: Pointer to the UART information structure.
22039234622SPrasad Kummari  */
22139234622SPrasad Kummari static void setup_runtime_console(uint32_t clock, dt_uart_info_t *info)
22239234622SPrasad Kummari {
22339234622SPrasad Kummari 	static console_t bl31_runtime_console;
2248eb6a1daSPrasad Kummari 	int32_t rc;
22539234622SPrasad Kummari 
22639234622SPrasad Kummari #if defined(PLAT_zynqmp)
22739234622SPrasad Kummari 	rc = console_cdns_register(info->base,
22839234622SPrasad Kummari 				   clock,
22939234622SPrasad Kummari 				   info->baud_rate,
23039234622SPrasad Kummari 				   &bl31_runtime_console);
23139234622SPrasad Kummari #else
23239234622SPrasad Kummari 	rc = console_pl011_register(info->base,
23339234622SPrasad Kummari 				    clock,
23439234622SPrasad Kummari 				    info->baud_rate,
23539234622SPrasad Kummari 				    &bl31_runtime_console);
23639234622SPrasad Kummari #endif
23739234622SPrasad Kummari 	if (rc == 0) {
23839234622SPrasad Kummari 		panic();
23939234622SPrasad Kummari 	}
24039234622SPrasad Kummari 
24139234622SPrasad Kummari 	console_set_scope(&bl31_runtime_console,
24239234622SPrasad Kummari 			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME |
24339234622SPrasad Kummari 			  CONSOLE_FLAG_CRASH);
24439234622SPrasad Kummari }
24539234622SPrasad Kummari 
24639234622SPrasad Kummari 
24739234622SPrasad Kummari /**
24800a68427SPrasad Kummari  * dt_console_init() - Initializes the DT console information.
24939234622SPrasad Kummari  * @uart_info: Pointer to the UART information structure.
250*a542b9c1SPrasad Kummari  * @console: Pointer to the console information structure.
25139234622SPrasad Kummari  * @clock: UART clock.
25239234622SPrasad Kummari  *
25339234622SPrasad Kummari  * Return: On success, it returns 0; on failure, it returns an error+reason;
25439234622SPrasad Kummari  */
25500a68427SPrasad Kummari static int32_t dt_console_init(dt_uart_info_t *uart_info,
256*a542b9c1SPrasad Kummari 			  console_t *console,
25739234622SPrasad Kummari 			  uint32_t clock)
25839234622SPrasad Kummari {
25939234622SPrasad Kummari 	int32_t rc = 0;
26039234622SPrasad Kummari 
26139234622SPrasad Kummari 	/* Parse UART information from Device Tree Blob (DTB) */
26239234622SPrasad Kummari 	rc = fdt_get_uart_info(uart_info);
26339234622SPrasad Kummari 	if (rc < 0) {
26439234622SPrasad Kummari 		rc = -FDT_ERR_NOTFOUND;
2658eb6a1daSPrasad Kummari 		goto error;
26639234622SPrasad Kummari 	}
26739234622SPrasad Kummari 
26839234622SPrasad Kummari 	if (strncmp(uart_info->compatible, DT_UART_COMPAT,
26939234622SPrasad Kummari 		   strlen(DT_UART_COMPAT)) == 0) {
27039234622SPrasad Kummari 
27139234622SPrasad Kummari 		if (check_fdt_uart_info(uart_info) == 0) {
27239234622SPrasad Kummari 			setup_runtime_console(clock, uart_info);
273*a542b9c1SPrasad Kummari 			console_end(console);
27439234622SPrasad Kummari 			INFO("Runtime console setup\n");
27539234622SPrasad Kummari 		} else {
27639234622SPrasad Kummari 			INFO("Early console and DTB console are same\n");
27739234622SPrasad Kummari 		}
27839234622SPrasad Kummari 	} else if (strncmp(uart_info->compatible, DT_UART_DCC_COMPAT,
27939234622SPrasad Kummari 			  strlen(DT_UART_DCC_COMPAT)) == 0) {
28039234622SPrasad Kummari 		rc = console_dcc_register();
28139234622SPrasad Kummari 		if (rc == 0) {
28239234622SPrasad Kummari 			panic();
28339234622SPrasad Kummari 		}
284*a542b9c1SPrasad Kummari 		console_end(console);
28539234622SPrasad Kummari 	} else {
28639234622SPrasad Kummari 		WARN("BL31: No console device found in DT.\n");
28739234622SPrasad Kummari 	}
28839234622SPrasad Kummari 
2898eb6a1daSPrasad Kummari error:
29039234622SPrasad Kummari 	return rc;
29139234622SPrasad Kummari }
29239234622SPrasad Kummari #endif
29339234622SPrasad Kummari 
29439234622SPrasad Kummari void setup_console(void)
29539234622SPrasad Kummari {
2968eb6a1daSPrasad Kummari 	int32_t rc;
29739234622SPrasad Kummari 	uint32_t uart_clk = get_uart_clk();
29839234622SPrasad Kummari 
29939234622SPrasad Kummari #if defined(PLAT_zynqmp)
30039234622SPrasad Kummari 	if (CONSOLE_IS(cadence) || (CONSOLE_IS(cadence1))) {
30139234622SPrasad Kummari 		rc = console_cdns_register(UART_BASE,
30239234622SPrasad Kummari 					   uart_clk,
30339234622SPrasad Kummari 					   UART_BAUDRATE,
304*a542b9c1SPrasad Kummari 					   &boot_console);
30539234622SPrasad Kummari 		if (rc == 0) {
30639234622SPrasad Kummari 			panic();
30739234622SPrasad Kummari 		}
30839234622SPrasad Kummari 
309*a542b9c1SPrasad Kummari 		console_set_scope(&boot_console, CONSOLE_FLAG_BOOT |
31039234622SPrasad Kummari 				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
31139234622SPrasad Kummari 	}
31239234622SPrasad Kummari #else
31339234622SPrasad Kummari 	if (CONSOLE_IS(pl011) || (CONSOLE_IS(pl011_1))) {
31439234622SPrasad Kummari 		/* Initialize the console to provide early debug support */
31539234622SPrasad Kummari 		rc = console_pl011_register((uint32_t)UART_BASE,
31639234622SPrasad Kummari 					   uart_clk,
31739234622SPrasad Kummari 					   (uint32_t)UART_BAUDRATE,
318*a542b9c1SPrasad Kummari 					   &boot_console);
31939234622SPrasad Kummari 		if (rc == 0) {
32039234622SPrasad Kummari 			panic();
32139234622SPrasad Kummari 		}
32239234622SPrasad Kummari 
323*a542b9c1SPrasad Kummari 		console_set_scope(&boot_console, CONSOLE_FLAG_BOOT |
32439234622SPrasad Kummari 				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
32539234622SPrasad Kummari 	}
32639234622SPrasad Kummari #endif
32739234622SPrasad Kummari 	if (CONSOLE_IS(dcc)) {
32839234622SPrasad Kummari 		/* Initialize the dcc console for debug */
32939234622SPrasad Kummari 		rc = console_dcc_register();
33039234622SPrasad Kummari 		if (rc == 0) {
33139234622SPrasad Kummari 			panic();
33239234622SPrasad Kummari 		}
33339234622SPrasad Kummari 	}
33439234622SPrasad Kummari 	INFO("BL31: Early console setup\n");
33539234622SPrasad Kummari 
33639234622SPrasad Kummari #if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
33739234622SPrasad Kummari 	static dt_uart_info_t uart_info = {0};
33839234622SPrasad Kummari 
33900a68427SPrasad Kummari 	/* Initialize the DTB console using UART information from the DTB */
340*a542b9c1SPrasad Kummari 	rc = dt_console_init(&uart_info, &boot_console, uart_clk);
34139234622SPrasad Kummari 	if (rc < 0) {
34200a68427SPrasad Kummari 		ERROR("Failed to initialize DT console: %d\n", rc);
34339234622SPrasad Kummari 	}
34439234622SPrasad Kummari #endif
34539234622SPrasad Kummari }
346