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