18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/init.h>
38c2ecf20Sopenharmony_ci#include <linux/errno.h>
48c2ecf20Sopenharmony_ci#include <linux/console.h>
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <asm/sibyte/board.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <asm/fw/cfe/cfe_api.h>
98c2ecf20Sopenharmony_ci#include <asm/fw/cfe/cfe_error.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ciextern int cfe_cons_handle;
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic void cfe_console_write(struct console *cons, const char *str,
148c2ecf20Sopenharmony_ci		       unsigned int count)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	int i, last, written;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	for (i=0, last=0; i<count; i++) {
198c2ecf20Sopenharmony_ci		if (!str[i])
208c2ecf20Sopenharmony_ci			/* XXXKW can/should this ever happen? */
218c2ecf20Sopenharmony_ci			return;
228c2ecf20Sopenharmony_ci		if (str[i] == '\n') {
238c2ecf20Sopenharmony_ci			do {
248c2ecf20Sopenharmony_ci				written = cfe_write(cfe_cons_handle, &str[last], i-last);
258c2ecf20Sopenharmony_ci				if (written < 0)
268c2ecf20Sopenharmony_ci					;
278c2ecf20Sopenharmony_ci				last += written;
288c2ecf20Sopenharmony_ci			} while (last < i);
298c2ecf20Sopenharmony_ci			while (cfe_write(cfe_cons_handle, "\r", 1) <= 0)
308c2ecf20Sopenharmony_ci				;
318c2ecf20Sopenharmony_ci		}
328c2ecf20Sopenharmony_ci	}
338c2ecf20Sopenharmony_ci	if (last != count) {
348c2ecf20Sopenharmony_ci		do {
358c2ecf20Sopenharmony_ci			written = cfe_write(cfe_cons_handle, &str[last], count-last);
368c2ecf20Sopenharmony_ci			if (written < 0)
378c2ecf20Sopenharmony_ci				;
388c2ecf20Sopenharmony_ci			last += written;
398c2ecf20Sopenharmony_ci		} while (last < count);
408c2ecf20Sopenharmony_ci	}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic int cfe_console_setup(struct console *cons, char *str)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	char consdev[32];
478c2ecf20Sopenharmony_ci	/* XXXKW think about interaction with 'console=' cmdline arg */
488c2ecf20Sopenharmony_ci	/* If none of the console options are configured, the build will break. */
498c2ecf20Sopenharmony_ci	if (cfe_getenv("BOOT_CONSOLE", consdev, 32) >= 0) {
508c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_SB1250_DUART
518c2ecf20Sopenharmony_ci		if (!strcmp(consdev, "uart0")) {
528c2ecf20Sopenharmony_ci			setleds("u0cn");
538c2ecf20Sopenharmony_ci		} else if (!strcmp(consdev, "uart1")) {
548c2ecf20Sopenharmony_ci			setleds("u1cn");
558c2ecf20Sopenharmony_ci		} else
568c2ecf20Sopenharmony_ci#endif
578c2ecf20Sopenharmony_ci#ifdef CONFIG_VGA_CONSOLE
588c2ecf20Sopenharmony_ci		       if (!strcmp(consdev, "pcconsole0")) {
598c2ecf20Sopenharmony_ci				setleds("pccn");
608c2ecf20Sopenharmony_ci		} else
618c2ecf20Sopenharmony_ci#endif
628c2ecf20Sopenharmony_ci			return -ENODEV;
638c2ecf20Sopenharmony_ci	}
648c2ecf20Sopenharmony_ci	return 0;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic struct console sb1250_cfe_cons = {
688c2ecf20Sopenharmony_ci	.name		= "cfe",
698c2ecf20Sopenharmony_ci	.write		= cfe_console_write,
708c2ecf20Sopenharmony_ci	.setup		= cfe_console_setup,
718c2ecf20Sopenharmony_ci	.flags		= CON_PRINTBUFFER,
728c2ecf20Sopenharmony_ci	.index		= -1,
738c2ecf20Sopenharmony_ci};
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic int __init sb1250_cfe_console_init(void)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	register_console(&sb1250_cfe_cons);
788c2ecf20Sopenharmony_ci	return 0;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ciconsole_initcall(sb1250_cfe_console_init);
82