Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Generic serial console support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Author: Mark A. Greer <mgreer@mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * and was written by Matt Porter <mporter@kernel.crashing.org>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * 2001,2006 (c) MontaVista Software, Inc.  This file is licensed under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * the terms of the GNU General Public License version 2.  This program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * is licensed "as is" without any warranty of any kind, whether express
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "types.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "string.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include "stdio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "io.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) static int serial_open(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	struct serial_console_data *scdp = console_ops.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	return scdp->open();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static void serial_write(const char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	struct serial_console_data *scdp = console_ops.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	while (*buf != '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		scdp->putc(*buf++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static void serial_edit_cmdline(char *buf, int len, unsigned int timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	int timer = 0, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	char ch, *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct serial_console_data *scdp = console_ops.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	cp = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	count = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	cp = &buf[count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		if (scdp->tstc()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			while (((ch = scdp->getc()) != '\n') && (ch != '\r')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 				/* Test for backspace/delete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 				if ((ch == '\b') || (ch == '\177')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 					if (cp != buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 						cp--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 						count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 						printf("\b \b");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 				/* Test for ^x/^u (and wipe the line) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 				} else if ((ch == '\030') || (ch == '\025')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 					while (cp != buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 						cp--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 						count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 						printf("\b \b");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 				} else if (count < len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 						*cp++ = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 						count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 						scdp->putc(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			break;  /* Exit 'timer' loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		udelay(1000);  /* 1 msec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	} while (timer++ < timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	*cp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static void serial_close(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	struct serial_console_data *scdp = console_ops.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (scdp->close)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		scdp->close();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) static void *serial_get_stdout_devp(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	void *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	char devtype[MAX_PROP_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	char path[MAX_PATH_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	devp = finddevice("/chosen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	if (devp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		getprop(devp, "stdout-path", path, MAX_PATH_LEN) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		devp = finddevice(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		if (devp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 			goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 				&& !strcmp(devtype, "serial"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			return devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static struct serial_console_data serial_cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Node's "compatible" property determines which serial driver to use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int serial_console_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	void *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	int rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	devp = serial_get_stdout_devp();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	if (devp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (dt_is_compatible(devp, "ns16550") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	    dt_is_compatible(devp, "pnpPNP,501"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		rc = ns16550_console_init(devp, &serial_cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #ifdef CONFIG_CPM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	else if (dt_is_compatible(devp, "fsl,cpm1-scc-uart") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	         dt_is_compatible(devp, "fsl,cpm1-smc-uart") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	         dt_is_compatible(devp, "fsl,cpm2-scc-uart") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	         dt_is_compatible(devp, "fsl,cpm2-smc-uart"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		rc = cpm_console_init(devp, &serial_cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #ifdef CONFIG_PPC_MPC52xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	else if (dt_is_compatible(devp, "fsl,mpc5200-psc-uart"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		rc = mpc5200_psc_console_init(devp, &serial_cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #ifdef CONFIG_PPC64_BOOT_WRAPPER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	else if (dt_is_compatible(devp, "ibm,opal-console-raw"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		rc = opal_console_init(devp, &serial_cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	/* Add other serial console driver calls here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		console_ops.open = serial_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		console_ops.write = serial_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		console_ops.close = serial_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		console_ops.data = &serial_cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		if (serial_cd.getc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			console_ops.edit_cmdline = serial_edit_cmdline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }