diff options
Diffstat (limited to 'arch/powerpc/boot/serial.c')
-rw-r--r-- | arch/powerpc/boot/serial.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c new file mode 100644 index 000000000000..e8de4cf59be7 --- /dev/null +++ b/arch/powerpc/boot/serial.c | |||
@@ -0,0 +1,142 @@ | |||
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 | |||
22 | extern void udelay(long delay); | ||
23 | |||
24 | static int serial_open(void) | ||
25 | { | ||
26 | struct serial_console_data *scdp = console_ops.data; | ||
27 | return scdp->open(); | ||
28 | } | ||
29 | |||
30 | static void serial_write(char *buf, int len) | ||
31 | { | ||
32 | struct serial_console_data *scdp = console_ops.data; | ||
33 | |||
34 | while (*buf != '\0') | ||
35 | scdp->putc(*buf++); | ||
36 | } | ||
37 | |||
38 | static void serial_edit_cmdline(char *buf, int len) | ||
39 | { | ||
40 | int timer = 0, count; | ||
41 | char ch, *cp; | ||
42 | struct serial_console_data *scdp = console_ops.data; | ||
43 | |||
44 | cp = buf; | ||
45 | count = strlen(buf); | ||
46 | cp = &buf[count]; | ||
47 | count++; | ||
48 | |||
49 | while (timer++ < 5*1000) { | ||
50 | if (scdp->tstc()) { | ||
51 | while (((ch = scdp->getc()) != '\n') && (ch != '\r')) { | ||
52 | /* Test for backspace/delete */ | ||
53 | if ((ch == '\b') || (ch == '\177')) { | ||
54 | if (cp != buf) { | ||
55 | cp--; | ||
56 | count--; | ||
57 | printf("\b \b"); | ||
58 | } | ||
59 | /* Test for ^x/^u (and wipe the line) */ | ||
60 | } else if ((ch == '\030') || (ch == '\025')) { | ||
61 | while (cp != buf) { | ||
62 | cp--; | ||
63 | count--; | ||
64 | printf("\b \b"); | ||
65 | } | ||
66 | } else if (count < len) { | ||
67 | *cp++ = ch; | ||
68 | count++; | ||
69 | scdp->putc(ch); | ||
70 | } | ||
71 | } | ||
72 | break; /* Exit 'timer' loop */ | ||
73 | } | ||
74 | udelay(1000); /* 1 msec */ | ||
75 | } | ||
76 | *cp = 0; | ||
77 | } | ||
78 | |||
79 | static void serial_close(void) | ||
80 | { | ||
81 | struct serial_console_data *scdp = console_ops.data; | ||
82 | |||
83 | if (scdp->close) | ||
84 | scdp->close(); | ||
85 | } | ||
86 | |||
87 | static void *serial_get_stdout_devp(void) | ||
88 | { | ||
89 | void *devp; | ||
90 | char devtype[MAX_PROP_LEN]; | ||
91 | char path[MAX_PATH_LEN]; | ||
92 | |||
93 | devp = finddevice("/chosen"); | ||
94 | if (devp == NULL) | ||
95 | goto err_out; | ||
96 | |||
97 | if (getprop(devp, "linux,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 | } | ||
106 | err_out: | ||
107 | return NULL; | ||
108 | } | ||
109 | |||
110 | static struct serial_console_data serial_cd; | ||
111 | |||
112 | /* Node's "compatible" property determines which serial driver to use */ | ||
113 | int serial_console_init(void) | ||
114 | { | ||
115 | void *devp; | ||
116 | int rc = -1; | ||
117 | char compat[MAX_PROP_LEN]; | ||
118 | |||
119 | devp = serial_get_stdout_devp(); | ||
120 | if (devp == NULL) | ||
121 | goto err_out; | ||
122 | |||
123 | if (getprop(devp, "compatible", compat, sizeof(compat)) < 0) | ||
124 | goto err_out; | ||
125 | |||
126 | if (!strcmp(compat, "ns16550")) | ||
127 | rc = ns16550_console_init(devp, &serial_cd); | ||
128 | |||
129 | /* Add other serial console driver calls here */ | ||
130 | |||
131 | if (!rc) { | ||
132 | console_ops.open = serial_open; | ||
133 | console_ops.write = serial_write; | ||
134 | console_ops.edit_cmdline = serial_edit_cmdline; | ||
135 | console_ops.close = serial_close; | ||
136 | console_ops.data = &serial_cd; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | err_out: | ||
141 | return -1; | ||
142 | } | ||