diff options
author | Paul Mundt <lethal@linux-sh.org> | 2008-12-11 05:06:43 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-12-22 04:44:04 -0500 |
commit | 07d2a1a1cd8d609a4bc320a492670de57ec6bde1 (patch) | |
tree | c4ab45734d6b07d0250f2f874096730da08f1ae1 /drivers/serial | |
parent | ab6e570ba33dbee18c2520d386e0f367a9b573c3 (diff) |
serial: sh-sci: Implement CONSOLE_POLL support and kill off old kgdb console.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/sh-sci.c | 201 |
1 files changed, 20 insertions, 181 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 31532e97fb96..231f77b16492 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #ifdef CONFIG_SUPERH | 51 | #ifdef CONFIG_SUPERH |
52 | #include <asm/clock.h> | 52 | #include <asm/clock.h> |
53 | #include <asm/sh_bios.h> | 53 | #include <asm/sh_bios.h> |
54 | #include <asm/kgdb.h> | ||
55 | #endif | 54 | #endif |
56 | 55 | ||
57 | #include "sh-sci.h" | 56 | #include "sh-sci.h" |
@@ -85,10 +84,6 @@ struct sci_port { | |||
85 | #endif | 84 | #endif |
86 | }; | 85 | }; |
87 | 86 | ||
88 | #ifdef CONFIG_SH_KGDB | ||
89 | static struct sci_port *kgdb_sci_port; | ||
90 | #endif | ||
91 | |||
92 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | 87 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE |
93 | static struct sci_port *serial_console_port; | 88 | static struct sci_port *serial_console_port; |
94 | #endif | 89 | #endif |
@@ -107,21 +102,18 @@ to_sci_port(struct uart_port *uart) | |||
107 | return container_of(uart, struct sci_port, port); | 102 | return container_of(uart, struct sci_port, port); |
108 | } | 103 | } |
109 | 104 | ||
110 | #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && \ | 105 | #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) |
111 | defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) | ||
112 | static inline void handle_error(struct uart_port *port) | 106 | static inline void handle_error(struct uart_port *port) |
113 | { | 107 | { |
114 | /* Clear error flags */ | 108 | /* Clear error flags */ |
115 | sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); | 109 | sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); |
116 | } | 110 | } |
117 | 111 | ||
118 | static int get_char(struct uart_port *port) | 112 | static int sci_poll_get_char(struct uart_port *port) |
119 | { | 113 | { |
120 | unsigned long flags; | ||
121 | unsigned short status; | 114 | unsigned short status; |
122 | int c; | 115 | int c; |
123 | 116 | ||
124 | spin_lock_irqsave(&port->lock, flags); | ||
125 | do { | 117 | do { |
126 | status = sci_in(port, SCxSR); | 118 | status = sci_in(port, SCxSR); |
127 | if (status & SCxSR_ERRORS(port)) { | 119 | if (status & SCxSR_ERRORS(port)) { |
@@ -129,24 +121,20 @@ static int get_char(struct uart_port *port) | |||
129 | continue; | 121 | continue; |
130 | } | 122 | } |
131 | } while (!(status & SCxSR_RDxF(port))); | 123 | } while (!(status & SCxSR_RDxF(port))); |
124 | |||
132 | c = sci_in(port, SCxRDR); | 125 | c = sci_in(port, SCxRDR); |
126 | |||
133 | /* Dummy read */ | 127 | /* Dummy read */ |
134 | sci_in(port, SCxSR); | 128 | sci_in(port, SCxSR); |
135 | sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); | 129 | sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); |
136 | spin_unlock_irqrestore(&port->lock, flags); | ||
137 | 130 | ||
138 | return c; | 131 | return c; |
139 | } | 132 | } |
140 | #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ | ||
141 | 133 | ||
142 | #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || defined(CONFIG_SH_KGDB) | 134 | static void sci_poll_put_char(struct uart_port *port, unsigned char c) |
143 | static void put_char(struct uart_port *port, char c) | ||
144 | { | 135 | { |
145 | unsigned long flags; | ||
146 | unsigned short status; | 136 | unsigned short status; |
147 | 137 | ||
148 | spin_lock_irqsave(&port->lock, flags); | ||
149 | |||
150 | do { | 138 | do { |
151 | status = sci_in(port, SCxSR); | 139 | status = sci_in(port, SCxSR); |
152 | } while (!(status & SCxSR_TDxE(port))); | 140 | } while (!(status & SCxSR_TDxE(port))); |
@@ -154,82 +142,8 @@ static void put_char(struct uart_port *port, char c) | |||
154 | sci_in(port, SCxSR); /* Dummy read */ | 142 | sci_in(port, SCxSR); /* Dummy read */ |
155 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); | 143 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); |
156 | sci_out(port, SCxTDR, c); | 144 | sci_out(port, SCxTDR, c); |
157 | |||
158 | spin_unlock_irqrestore(&port->lock, flags); | ||
159 | } | 145 | } |
160 | #endif | 146 | #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */ |
161 | |||
162 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | ||
163 | static void put_string(struct sci_port *sci_port, const char *buffer, int count) | ||
164 | { | ||
165 | struct uart_port *port = &sci_port->port; | ||
166 | const unsigned char *p = buffer; | ||
167 | int i; | ||
168 | |||
169 | #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) | ||
170 | int checksum; | ||
171 | int usegdb = 0; | ||
172 | |||
173 | #ifdef CONFIG_SH_STANDARD_BIOS | ||
174 | /* This call only does a trap the first time it is | ||
175 | * called, and so is safe to do here unconditionally | ||
176 | */ | ||
177 | usegdb |= sh_bios_in_gdb_mode(); | ||
178 | #endif | ||
179 | #ifdef CONFIG_SH_KGDB | ||
180 | usegdb |= (kgdb_in_gdb_mode && (sci_port == kgdb_sci_port)); | ||
181 | #endif | ||
182 | |||
183 | if (usegdb) { | ||
184 | /* $<packet info>#<checksum>. */ | ||
185 | do { | ||
186 | unsigned char c; | ||
187 | put_char(port, '$'); | ||
188 | put_char(port, 'O'); /* 'O'utput to console */ | ||
189 | checksum = 'O'; | ||
190 | |||
191 | /* Don't use run length encoding */ | ||
192 | for (i = 0; i < count; i++) { | ||
193 | int h, l; | ||
194 | |||
195 | c = *p++; | ||
196 | h = hex_asc_hi(c); | ||
197 | l = hex_asc_lo(c); | ||
198 | put_char(port, h); | ||
199 | put_char(port, l); | ||
200 | checksum += h + l; | ||
201 | } | ||
202 | put_char(port, '#'); | ||
203 | put_char(port, hex_asc_hi(checksum)); | ||
204 | put_char(port, hex_asc_lo(checksum)); | ||
205 | } while (get_char(port) != '+'); | ||
206 | } else | ||
207 | #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ | ||
208 | for (i = 0; i < count; i++) { | ||
209 | if (*p == 10) | ||
210 | put_char(port, '\r'); | ||
211 | put_char(port, *p++); | ||
212 | } | ||
213 | } | ||
214 | #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ | ||
215 | |||
216 | #ifdef CONFIG_SH_KGDB | ||
217 | static int kgdb_sci_getchar(void) | ||
218 | { | ||
219 | int c; | ||
220 | |||
221 | /* Keep trying to read a character, this could be neater */ | ||
222 | while ((c = get_char(&kgdb_sci_port->port)) < 0) | ||
223 | cpu_relax(); | ||
224 | |||
225 | return c; | ||
226 | } | ||
227 | |||
228 | static inline void kgdb_sci_putchar(int c) | ||
229 | { | ||
230 | put_char(&kgdb_sci_port->port, c); | ||
231 | } | ||
232 | #endif /* CONFIG_SH_KGDB */ | ||
233 | 147 | ||
234 | #if defined(__H8300S__) | 148 | #if defined(__H8300S__) |
235 | enum { sci_disable, sci_enable }; | 149 | enum { sci_disable, sci_enable }; |
@@ -1181,6 +1095,10 @@ static struct uart_ops sci_uart_ops = { | |||
1181 | .request_port = sci_request_port, | 1095 | .request_port = sci_request_port, |
1182 | .config_port = sci_config_port, | 1096 | .config_port = sci_config_port, |
1183 | .verify_port = sci_verify_port, | 1097 | .verify_port = sci_verify_port, |
1098 | #ifdef CONFIG_CONSOLE_POLL | ||
1099 | .poll_get_char = sci_poll_get_char, | ||
1100 | .poll_put_char = sci_poll_put_char, | ||
1101 | #endif | ||
1184 | }; | 1102 | }; |
1185 | 1103 | ||
1186 | static void __init sci_init_ports(void) | 1104 | static void __init sci_init_ports(void) |
@@ -1247,7 +1165,15 @@ int __init early_sci_setup(struct uart_port *port) | |||
1247 | static void serial_console_write(struct console *co, const char *s, | 1165 | static void serial_console_write(struct console *co, const char *s, |
1248 | unsigned count) | 1166 | unsigned count) |
1249 | { | 1167 | { |
1250 | put_string(serial_console_port, s, count); | 1168 | struct uart_port *port = &serial_console_port->port; |
1169 | int i; | ||
1170 | |||
1171 | for (i = 0; i < count; i++) { | ||
1172 | if (*s == 10) | ||
1173 | sci_poll_put_char(port, '\r'); | ||
1174 | |||
1175 | sci_poll_put_char(port, *s++); | ||
1176 | } | ||
1251 | } | 1177 | } |
1252 | 1178 | ||
1253 | static int __init serial_console_setup(struct console *co, char *options) | 1179 | static int __init serial_console_setup(struct console *co, char *options) |
@@ -1325,88 +1251,7 @@ static int __init sci_console_init(void) | |||
1325 | console_initcall(sci_console_init); | 1251 | console_initcall(sci_console_init); |
1326 | #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ | 1252 | #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ |
1327 | 1253 | ||
1328 | #ifdef CONFIG_SH_KGDB_CONSOLE | 1254 | #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) |
1329 | /* | ||
1330 | * FIXME: Most of this can go away.. at the moment, we rely on | ||
1331 | * arch/sh/kernel/setup.c to do the command line parsing for kgdb, though | ||
1332 | * most of that can easily be done here instead. | ||
1333 | * | ||
1334 | * For the time being, just accept the values that were parsed earlier.. | ||
1335 | */ | ||
1336 | static void __init kgdb_console_get_options(struct uart_port *port, int *baud, | ||
1337 | int *parity, int *bits) | ||
1338 | { | ||
1339 | *baud = kgdb_baud; | ||
1340 | *parity = tolower(kgdb_parity); | ||
1341 | *bits = kgdb_bits - '0'; | ||
1342 | } | ||
1343 | |||
1344 | /* | ||
1345 | * The naming here is somewhat misleading, since kgdb_console_setup() takes | ||
1346 | * care of the early-on initialization for kgdb, regardless of whether we | ||
1347 | * actually use kgdb as a console or not. | ||
1348 | * | ||
1349 | * On the plus side, this lets us kill off the old kgdb_sci_setup() nonsense. | ||
1350 | */ | ||
1351 | int __init kgdb_console_setup(struct console *co, char *options) | ||
1352 | { | ||
1353 | struct uart_port *port = &sci_ports[kgdb_portnum].port; | ||
1354 | int baud = 38400; | ||
1355 | int bits = 8; | ||
1356 | int parity = 'n'; | ||
1357 | int flow = 'n'; | ||
1358 | |||
1359 | if (co->index != kgdb_portnum) | ||
1360 | co->index = kgdb_portnum; | ||
1361 | |||
1362 | kgdb_sci_port = &sci_ports[co->index]; | ||
1363 | port = &kgdb_sci_port->port; | ||
1364 | |||
1365 | /* | ||
1366 | * Also need to check port->type, we don't actually have any | ||
1367 | * UPIO_PORT ports, but uart_report_port() handily misreports | ||
1368 | * it anyways if we don't have a port available by the time this is | ||
1369 | * called. | ||
1370 | */ | ||
1371 | if (!port->type) | ||
1372 | return -ENODEV; | ||
1373 | if (!port->membase || !port->mapbase) | ||
1374 | return -ENODEV; | ||
1375 | |||
1376 | if (options) | ||
1377 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
1378 | else | ||
1379 | kgdb_console_get_options(port, &baud, &parity, &bits); | ||
1380 | |||
1381 | kgdb_getchar = kgdb_sci_getchar; | ||
1382 | kgdb_putchar = kgdb_sci_putchar; | ||
1383 | |||
1384 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
1385 | } | ||
1386 | |||
1387 | static struct console kgdb_console = { | ||
1388 | .name = "ttySC", | ||
1389 | .device = uart_console_device, | ||
1390 | .write = kgdb_console_write, | ||
1391 | .setup = kgdb_console_setup, | ||
1392 | .flags = CON_PRINTBUFFER, | ||
1393 | .index = -1, | ||
1394 | .data = &sci_uart_driver, | ||
1395 | }; | ||
1396 | |||
1397 | /* Register the KGDB console so we get messages (d'oh!) */ | ||
1398 | static int __init kgdb_console_init(void) | ||
1399 | { | ||
1400 | sci_init_ports(); | ||
1401 | register_console(&kgdb_console); | ||
1402 | return 0; | ||
1403 | } | ||
1404 | console_initcall(kgdb_console_init); | ||
1405 | #endif /* CONFIG_SH_KGDB_CONSOLE */ | ||
1406 | |||
1407 | #if defined(CONFIG_SH_KGDB_CONSOLE) | ||
1408 | #define SCI_CONSOLE (&kgdb_console) | ||
1409 | #elif defined(CONFIG_SERIAL_SH_SCI_CONSOLE) | ||
1410 | #define SCI_CONSOLE (&serial_console) | 1255 | #define SCI_CONSOLE (&serial_console) |
1411 | #else | 1256 | #else |
1412 | #define SCI_CONSOLE 0 | 1257 | #define SCI_CONSOLE 0 |
@@ -1481,12 +1326,6 @@ static int __devinit sci_probe(struct platform_device *dev) | |||
1481 | uart_add_one_port(&sci_uart_driver, &sciport->port); | 1326 | uart_add_one_port(&sci_uart_driver, &sciport->port); |
1482 | } | 1327 | } |
1483 | 1328 | ||
1484 | #if defined(CONFIG_SH_KGDB) && !defined(CONFIG_SH_KGDB_CONSOLE) | ||
1485 | kgdb_sci_port = &sci_ports[kgdb_portnum]; | ||
1486 | kgdb_getchar = kgdb_sci_getchar; | ||
1487 | kgdb_putchar = kgdb_sci_putchar; | ||
1488 | #endif | ||
1489 | |||
1490 | #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_HAVE_CLK) | 1329 | #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_HAVE_CLK) |
1491 | cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); | 1330 | cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); |
1492 | dev_info(&dev->dev, "CPU frequency notifier registered\n"); | 1331 | dev_info(&dev->dev, "CPU frequency notifier registered\n"); |