162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/init.h>
362306a36Sopenharmony_ci#include <linux/errno.h>
462306a36Sopenharmony_ci#include <linux/console.h>
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <asm/sibyte/board.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <asm/fw/cfe/cfe_api.h>
962306a36Sopenharmony_ci#include <asm/fw/cfe/cfe_error.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ciextern int cfe_cons_handle;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic void cfe_console_write(struct console *cons, const char *str,
1462306a36Sopenharmony_ci		       unsigned int count)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	int i, last, written;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	for (i=0, last=0; i<count; i++) {
1962306a36Sopenharmony_ci		if (!str[i])
2062306a36Sopenharmony_ci			/* XXXKW can/should this ever happen? */
2162306a36Sopenharmony_ci			return;
2262306a36Sopenharmony_ci		if (str[i] == '\n') {
2362306a36Sopenharmony_ci			do {
2462306a36Sopenharmony_ci				written = cfe_write(cfe_cons_handle, &str[last], i-last);
2562306a36Sopenharmony_ci				if (written < 0)
2662306a36Sopenharmony_ci					;
2762306a36Sopenharmony_ci				last += written;
2862306a36Sopenharmony_ci			} while (last < i);
2962306a36Sopenharmony_ci			while (cfe_write(cfe_cons_handle, "\r", 1) <= 0)
3062306a36Sopenharmony_ci				;
3162306a36Sopenharmony_ci		}
3262306a36Sopenharmony_ci	}
3362306a36Sopenharmony_ci	if (last != count) {
3462306a36Sopenharmony_ci		do {
3562306a36Sopenharmony_ci			written = cfe_write(cfe_cons_handle, &str[last], count-last);
3662306a36Sopenharmony_ci			if (written < 0)
3762306a36Sopenharmony_ci				;
3862306a36Sopenharmony_ci			last += written;
3962306a36Sopenharmony_ci		} while (last < count);
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic int cfe_console_setup(struct console *cons, char *str)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	char consdev[32];
4762306a36Sopenharmony_ci	/* XXXKW think about interaction with 'console=' cmdline arg */
4862306a36Sopenharmony_ci	/* If none of the console options are configured, the build will break. */
4962306a36Sopenharmony_ci	if (cfe_getenv("BOOT_CONSOLE", consdev, 32) >= 0) {
5062306a36Sopenharmony_ci#ifdef CONFIG_SERIAL_SB1250_DUART
5162306a36Sopenharmony_ci		if (!strcmp(consdev, "uart0")) {
5262306a36Sopenharmony_ci			setleds("u0cn");
5362306a36Sopenharmony_ci		} else if (!strcmp(consdev, "uart1")) {
5462306a36Sopenharmony_ci			setleds("u1cn");
5562306a36Sopenharmony_ci		} else
5662306a36Sopenharmony_ci#endif
5762306a36Sopenharmony_ci#ifdef CONFIG_VGA_CONSOLE
5862306a36Sopenharmony_ci		       if (!strcmp(consdev, "pcconsole0")) {
5962306a36Sopenharmony_ci				setleds("pccn");
6062306a36Sopenharmony_ci		} else
6162306a36Sopenharmony_ci#endif
6262306a36Sopenharmony_ci			return -ENODEV;
6362306a36Sopenharmony_ci	}
6462306a36Sopenharmony_ci	return 0;
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic struct console sb1250_cfe_cons = {
6862306a36Sopenharmony_ci	.name		= "cfe",
6962306a36Sopenharmony_ci	.write		= cfe_console_write,
7062306a36Sopenharmony_ci	.setup		= cfe_console_setup,
7162306a36Sopenharmony_ci	.flags		= CON_PRINTBUFFER,
7262306a36Sopenharmony_ci	.index		= -1,
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic int __init sb1250_cfe_console_init(void)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	register_console(&sb1250_cfe_cons);
7862306a36Sopenharmony_ci	return 0;
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciconsole_initcall(sb1250_cfe_console_init);
82