diff options
Diffstat (limited to 'drivers/serial/sh-sci.c')
-rw-r--r-- | drivers/serial/sh-sci.c | 113 |
1 files changed, 80 insertions, 33 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 46c40bbc4bc6..1f89496d530e 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | 48 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) |
49 | #include <linux/ctype.h> | ||
49 | #include <asm/clock.h> | 50 | #include <asm/clock.h> |
50 | #include <asm/sh_bios.h> | 51 | #include <asm/sh_bios.h> |
51 | #include <asm/kgdb.h> | 52 | #include <asm/kgdb.h> |
@@ -61,7 +62,7 @@ struct sci_port { | |||
61 | unsigned int type; | 62 | unsigned int type; |
62 | 63 | ||
63 | /* Port IRQs: ERI, RXI, TXI, BRI (optional) */ | 64 | /* Port IRQs: ERI, RXI, TXI, BRI (optional) */ |
64 | unsigned int irqs[SCIx_NR_IRQS]; | 65 | unsigned int irqs[SCIx_NR_IRQS]; |
65 | 66 | ||
66 | /* Port pin configuration */ | 67 | /* Port pin configuration */ |
67 | void (*init_pins)(struct uart_port *port, | 68 | void (*init_pins)(struct uart_port *port, |
@@ -76,6 +77,11 @@ struct sci_port { | |||
76 | /* Break timer */ | 77 | /* Break timer */ |
77 | struct timer_list break_timer; | 78 | struct timer_list break_timer; |
78 | int break_flag; | 79 | int break_flag; |
80 | |||
81 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | ||
82 | /* Port clock */ | ||
83 | struct clk *clk; | ||
84 | #endif | ||
79 | }; | 85 | }; |
80 | 86 | ||
81 | #ifdef CONFIG_SH_KGDB | 87 | #ifdef CONFIG_SH_KGDB |
@@ -163,7 +169,7 @@ static void put_string(struct sci_port *sci_port, const char *buffer, int count) | |||
163 | usegdb |= sh_bios_in_gdb_mode(); | 169 | usegdb |= sh_bios_in_gdb_mode(); |
164 | #endif | 170 | #endif |
165 | #ifdef CONFIG_SH_KGDB | 171 | #ifdef CONFIG_SH_KGDB |
166 | usegdb |= (kgdb_in_gdb_mode && (port == kgdb_sci_port)); | 172 | usegdb |= (kgdb_in_gdb_mode && (sci_port == kgdb_sci_port)); |
167 | #endif | 173 | #endif |
168 | 174 | ||
169 | if (usegdb) { | 175 | if (usegdb) { |
@@ -204,7 +210,7 @@ static int kgdb_sci_getchar(void) | |||
204 | int c; | 210 | int c; |
205 | 211 | ||
206 | /* Keep trying to read a character, this could be neater */ | 212 | /* Keep trying to read a character, this could be neater */ |
207 | while ((c = get_char(kgdb_sci_port)) < 0) | 213 | while ((c = get_char(&kgdb_sci_port->port)) < 0) |
208 | cpu_relax(); | 214 | cpu_relax(); |
209 | 215 | ||
210 | return c; | 216 | return c; |
@@ -212,7 +218,7 @@ static int kgdb_sci_getchar(void) | |||
212 | 218 | ||
213 | static inline void kgdb_sci_putchar(int c) | 219 | static inline void kgdb_sci_putchar(int c) |
214 | { | 220 | { |
215 | put_char(kgdb_sci_port, c); | 221 | put_char(&kgdb_sci_port->port, c); |
216 | } | 222 | } |
217 | #endif /* CONFIG_SH_KGDB */ | 223 | #endif /* CONFIG_SH_KGDB */ |
218 | 224 | ||
@@ -283,12 +289,23 @@ static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag) | |||
283 | #endif | 289 | #endif |
284 | 290 | ||
285 | #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF) | 291 | #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF) |
286 | #if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710) | 292 | #if defined(CONFIG_CPU_SUBTYPE_SH7300) |
287 | /* SH7300 doesn't use RTS/CTS */ | 293 | /* SH7300 doesn't use RTS/CTS */ |
288 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | 294 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) |
289 | { | 295 | { |
290 | sci_out(port, SCFCR, 0); | 296 | sci_out(port, SCFCR, 0); |
291 | } | 297 | } |
298 | #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) | ||
299 | static void sci_init_pins_scif(struct uart_port* port, unsigned int cflag) | ||
300 | { | ||
301 | unsigned int fcr_val = 0; | ||
302 | |||
303 | set_sh771x_scif_pfc(port); | ||
304 | if (cflag & CRTSCTS) { | ||
305 | fcr_val |= SCFCR_MCE; | ||
306 | } | ||
307 | sci_out(port, SCFCR, fcr_val); | ||
308 | } | ||
292 | #elif defined(CONFIG_CPU_SH3) | 309 | #elif defined(CONFIG_CPU_SH3) |
293 | /* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */ | 310 | /* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */ |
294 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | 311 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) |
@@ -350,7 +367,7 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | |||
350 | } else { | 367 | } else { |
351 | #ifdef CONFIG_CPU_SUBTYPE_SH7343 | 368 | #ifdef CONFIG_CPU_SUBTYPE_SH7343 |
352 | /* Nothing */ | 369 | /* Nothing */ |
353 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) | 370 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785) |
354 | ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */ | 371 | ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */ |
355 | #else | 372 | #else |
356 | ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */ | 373 | ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */ |
@@ -360,7 +377,9 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | |||
360 | } | 377 | } |
361 | #endif | 378 | #endif |
362 | 379 | ||
363 | #if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780) | 380 | #if defined(CONFIG_CPU_SUBTYPE_SH7760) || \ |
381 | defined(CONFIG_CPU_SUBTYPE_SH7780) || \ | ||
382 | defined(CONFIG_CPU_SUBTYPE_SH7785) | ||
364 | static inline int scif_txroom(struct uart_port *port) | 383 | static inline int scif_txroom(struct uart_port *port) |
365 | { | 384 | { |
366 | return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f); | 385 | return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f); |
@@ -735,12 +754,6 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) | |||
735 | 754 | ||
736 | /* Handle BREAKs */ | 755 | /* Handle BREAKs */ |
737 | sci_handle_breaks(port); | 756 | sci_handle_breaks(port); |
738 | |||
739 | #ifdef CONFIG_SH_KGDB | ||
740 | /* Break into the debugger if a break is detected */ | ||
741 | BREAKPOINT(); | ||
742 | #endif | ||
743 | |||
744 | sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port)); | 757 | sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port)); |
745 | 758 | ||
746 | return IRQ_HANDLED; | 759 | return IRQ_HANDLED; |
@@ -947,6 +960,10 @@ static int sci_startup(struct uart_port *port) | |||
947 | if (s->enable) | 960 | if (s->enable) |
948 | s->enable(port); | 961 | s->enable(port); |
949 | 962 | ||
963 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | ||
964 | s->clk = clk_get(NULL, "module_clk"); | ||
965 | #endif | ||
966 | |||
950 | sci_request_irq(s); | 967 | sci_request_irq(s); |
951 | sci_start_tx(port); | 968 | sci_start_tx(port); |
952 | sci_start_rx(port, 1); | 969 | sci_start_rx(port, 1); |
@@ -964,6 +981,11 @@ static void sci_shutdown(struct uart_port *port) | |||
964 | 981 | ||
965 | if (s->disable) | 982 | if (s->disable) |
966 | s->disable(port); | 983 | s->disable(port); |
984 | |||
985 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | ||
986 | clk_put(s->clk); | ||
987 | s->clk = NULL; | ||
988 | #endif | ||
967 | } | 989 | } |
968 | 990 | ||
969 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | 991 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
@@ -971,7 +993,6 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
971 | { | 993 | { |
972 | struct sci_port *s = &sci_ports[port->line]; | 994 | struct sci_port *s = &sci_ports[port->line]; |
973 | unsigned int status, baud, smr_val; | 995 | unsigned int status, baud, smr_val; |
974 | unsigned long flags; | ||
975 | int t; | 996 | int t; |
976 | 997 | ||
977 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | 998 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); |
@@ -983,18 +1004,14 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
983 | default: | 1004 | default: |
984 | { | 1005 | { |
985 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | 1006 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) |
986 | struct clk *clk = clk_get(NULL, "module_clk"); | 1007 | t = SCBRR_VALUE(baud, clk_get_rate(s->clk)); |
987 | t = SCBRR_VALUE(baud, clk_get_rate(clk)); | ||
988 | clk_put(clk); | ||
989 | #else | 1008 | #else |
990 | t = SCBRR_VALUE(baud); | 1009 | t = SCBRR_VALUE(baud); |
991 | #endif | 1010 | #endif |
992 | } | ||
993 | break; | 1011 | break; |
1012 | } | ||
994 | } | 1013 | } |
995 | 1014 | ||
996 | spin_lock_irqsave(&port->lock, flags); | ||
997 | |||
998 | do { | 1015 | do { |
999 | status = sci_in(port, SCxSR); | 1016 | status = sci_in(port, SCxSR); |
1000 | } while (!(status & SCxSR_TEND(port))); | 1017 | } while (!(status & SCxSR_TEND(port))); |
@@ -1038,8 +1055,6 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1038 | 1055 | ||
1039 | if ((termios->c_cflag & CREAD) != 0) | 1056 | if ((termios->c_cflag & CREAD) != 0) |
1040 | sci_start_rx(port,0); | 1057 | sci_start_rx(port,0); |
1041 | |||
1042 | spin_unlock_irqrestore(&port->lock, flags); | ||
1043 | } | 1058 | } |
1044 | 1059 | ||
1045 | static const char *sci_type(struct uart_port *port) | 1060 | static const char *sci_type(struct uart_port *port) |
@@ -1220,10 +1235,13 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
1220 | if (!port->membase || !port->mapbase) | 1235 | if (!port->membase || !port->mapbase) |
1221 | return -ENODEV; | 1236 | return -ENODEV; |
1222 | 1237 | ||
1223 | spin_lock_init(&port->lock); | ||
1224 | |||
1225 | port->type = serial_console_port->type; | 1238 | port->type = serial_console_port->type; |
1226 | 1239 | ||
1240 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | ||
1241 | if (!serial_console_port->clk) | ||
1242 | serial_console_port->clk = clk_get(NULL, "module_clk"); | ||
1243 | #endif | ||
1244 | |||
1227 | if (port->flags & UPF_IOREMAP) | 1245 | if (port->flags & UPF_IOREMAP) |
1228 | sci_config_port(port, 0); | 1246 | sci_config_port(port, 0); |
1229 | 1247 | ||
@@ -1247,7 +1265,7 @@ static struct console serial_console = { | |||
1247 | .device = uart_console_device, | 1265 | .device = uart_console_device, |
1248 | .write = serial_console_write, | 1266 | .write = serial_console_write, |
1249 | .setup = serial_console_setup, | 1267 | .setup = serial_console_setup, |
1250 | .flags = CON_PRINTBUFFER, | 1268 | .flags = CON_PRINTBUFFER, |
1251 | .index = -1, | 1269 | .index = -1, |
1252 | .data = &sci_uart_driver, | 1270 | .data = &sci_uart_driver, |
1253 | }; | 1271 | }; |
@@ -1292,11 +1310,23 @@ int __init kgdb_console_setup(struct console *co, char *options) | |||
1292 | int parity = 'n'; | 1310 | int parity = 'n'; |
1293 | int flow = 'n'; | 1311 | int flow = 'n'; |
1294 | 1312 | ||
1295 | spin_lock_init(&port->lock); | ||
1296 | |||
1297 | if (co->index != kgdb_portnum) | 1313 | if (co->index != kgdb_portnum) |
1298 | co->index = kgdb_portnum; | 1314 | co->index = kgdb_portnum; |
1299 | 1315 | ||
1316 | kgdb_sci_port = &sci_ports[co->index]; | ||
1317 | port = &kgdb_sci_port->port; | ||
1318 | |||
1319 | /* | ||
1320 | * Also need to check port->type, we don't actually have any | ||
1321 | * UPIO_PORT ports, but uart_report_port() handily misreports | ||
1322 | * it anyways if we don't have a port available by the time this is | ||
1323 | * called. | ||
1324 | */ | ||
1325 | if (!port->type) | ||
1326 | return -ENODEV; | ||
1327 | if (!port->membase || !port->mapbase) | ||
1328 | return -ENODEV; | ||
1329 | |||
1300 | if (options) | 1330 | if (options) |
1301 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 1331 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
1302 | else | 1332 | else |
@@ -1311,11 +1341,12 @@ int __init kgdb_console_setup(struct console *co, char *options) | |||
1311 | 1341 | ||
1312 | #ifdef CONFIG_SH_KGDB_CONSOLE | 1342 | #ifdef CONFIG_SH_KGDB_CONSOLE |
1313 | static struct console kgdb_console = { | 1343 | static struct console kgdb_console = { |
1314 | .name = "ttySC", | 1344 | .name = "ttySC", |
1315 | .write = kgdb_console_write, | 1345 | .device = uart_console_device, |
1316 | .setup = kgdb_console_setup, | 1346 | .write = kgdb_console_write, |
1317 | .flags = CON_PRINTBUFFER | CON_ENABLED, | 1347 | .setup = kgdb_console_setup, |
1318 | .index = -1, | 1348 | .flags = CON_PRINTBUFFER, |
1349 | .index = -1, | ||
1319 | .data = &sci_uart_driver, | 1350 | .data = &sci_uart_driver, |
1320 | }; | 1351 | }; |
1321 | 1352 | ||
@@ -1361,9 +1392,19 @@ static int __devinit sci_probe(struct platform_device *dev) | |||
1361 | struct plat_sci_port *p = dev->dev.platform_data; | 1392 | struct plat_sci_port *p = dev->dev.platform_data; |
1362 | int i; | 1393 | int i; |
1363 | 1394 | ||
1364 | for (i = 0; p && p->flags != 0 && i < SCI_NPORTS; p++, i++) { | 1395 | for (i = 0; p && p->flags != 0; p++, i++) { |
1365 | struct sci_port *sciport = &sci_ports[i]; | 1396 | struct sci_port *sciport = &sci_ports[i]; |
1366 | 1397 | ||
1398 | /* Sanity check */ | ||
1399 | if (unlikely(i == SCI_NPORTS)) { | ||
1400 | dev_notice(&dev->dev, "Attempting to register port " | ||
1401 | "%d when only %d are available.\n", | ||
1402 | i+1, SCI_NPORTS); | ||
1403 | dev_notice(&dev->dev, "Consider bumping " | ||
1404 | "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); | ||
1405 | break; | ||
1406 | } | ||
1407 | |||
1367 | sciport->port.mapbase = p->mapbase; | 1408 | sciport->port.mapbase = p->mapbase; |
1368 | 1409 | ||
1369 | /* | 1410 | /* |
@@ -1386,6 +1427,12 @@ static int __devinit sci_probe(struct platform_device *dev) | |||
1386 | uart_add_one_port(&sci_uart_driver, &sciport->port); | 1427 | uart_add_one_port(&sci_uart_driver, &sciport->port); |
1387 | } | 1428 | } |
1388 | 1429 | ||
1430 | #if defined(CONFIG_SH_KGDB) && !defined(CONFIG_SH_KGDB_CONSOLE) | ||
1431 | kgdb_sci_port = &sci_ports[kgdb_portnum]; | ||
1432 | kgdb_getchar = kgdb_sci_getchar; | ||
1433 | kgdb_putchar = kgdb_sci_putchar; | ||
1434 | #endif | ||
1435 | |||
1389 | #ifdef CONFIG_CPU_FREQ | 1436 | #ifdef CONFIG_CPU_FREQ |
1390 | cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); | 1437 | cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); |
1391 | dev_info(&dev->dev, "sci: CPU frequency notifier registered\n"); | 1438 | dev_info(&dev->dev, "sci: CPU frequency notifier registered\n"); |