diff options
Diffstat (limited to 'drivers/serial/sh-sci.c')
| -rw-r--r-- | drivers/serial/sh-sci.c | 90 |
1 files changed, 49 insertions, 41 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 3df2aaec829f..3b9d2d83b590 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) | 4 | * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2002 - 2006 Paul Mundt | 6 | * Copyright (C) 2002 - 2008 Paul Mundt |
| 7 | * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007). | 7 | * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007). |
| 8 | * | 8 | * |
| 9 | * based off of the old drivers/char/sh-sci.c by: | 9 | * based off of the old drivers/char/sh-sci.c by: |
| @@ -46,6 +46,7 @@ | |||
| 46 | #include <linux/cpufreq.h> | 46 | #include <linux/cpufreq.h> |
| 47 | #include <linux/clk.h> | 47 | #include <linux/clk.h> |
| 48 | #include <linux/ctype.h> | 48 | #include <linux/ctype.h> |
| 49 | #include <linux/err.h> | ||
| 49 | 50 | ||
| 50 | #ifdef CONFIG_SUPERH | 51 | #ifdef CONFIG_SUPERH |
| 51 | #include <asm/clock.h> | 52 | #include <asm/clock.h> |
| @@ -78,7 +79,7 @@ struct sci_port { | |||
| 78 | struct timer_list break_timer; | 79 | struct timer_list break_timer; |
| 79 | int break_flag; | 80 | int break_flag; |
| 80 | 81 | ||
| 81 | #ifdef CONFIG_SUPERH | 82 | #ifdef CONFIG_HAVE_CLK |
| 82 | /* Port clock */ | 83 | /* Port clock */ |
| 83 | struct clk *clk; | 84 | struct clk *clk; |
| 84 | #endif | 85 | #endif |
| @@ -831,7 +832,7 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | |||
| 831 | return IRQ_HANDLED; | 832 | return IRQ_HANDLED; |
| 832 | } | 833 | } |
| 833 | 834 | ||
| 834 | #ifdef CONFIG_CPU_FREQ | 835 | #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_HAVE_CLK) |
| 835 | /* | 836 | /* |
| 836 | * Here we define a transistion notifier so that we can update all of our | 837 | * Here we define a transistion notifier so that we can update all of our |
| 837 | * ports' baud rate when the peripheral clock changes. | 838 | * ports' baud rate when the peripheral clock changes. |
| @@ -860,7 +861,7 @@ static int sci_notifier(struct notifier_block *self, | |||
| 860 | * Clean this up later.. | 861 | * Clean this up later.. |
| 861 | */ | 862 | */ |
| 862 | clk = clk_get(NULL, "module_clk"); | 863 | clk = clk_get(NULL, "module_clk"); |
| 863 | port->uartclk = clk_get_rate(clk) * 16; | 864 | port->uartclk = clk_get_rate(clk); |
| 864 | clk_put(clk); | 865 | clk_put(clk); |
| 865 | } | 866 | } |
| 866 | 867 | ||
| @@ -873,7 +874,7 @@ static int sci_notifier(struct notifier_block *self, | |||
| 873 | } | 874 | } |
| 874 | 875 | ||
| 875 | static struct notifier_block sci_nb = { &sci_notifier, NULL, 0 }; | 876 | static struct notifier_block sci_nb = { &sci_notifier, NULL, 0 }; |
| 876 | #endif /* CONFIG_CPU_FREQ */ | 877 | #endif /* CONFIG_CPU_FREQ && CONFIG_HAVE_CLK */ |
| 877 | 878 | ||
| 878 | static int sci_request_irq(struct sci_port *port) | 879 | static int sci_request_irq(struct sci_port *port) |
| 879 | { | 880 | { |
| @@ -1008,7 +1009,7 @@ static int sci_startup(struct uart_port *port) | |||
| 1008 | if (s->enable) | 1009 | if (s->enable) |
| 1009 | s->enable(port); | 1010 | s->enable(port); |
| 1010 | 1011 | ||
| 1011 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | 1012 | #ifdef CONFIG_HAVE_CLK |
| 1012 | s->clk = clk_get(NULL, "module_clk"); | 1013 | s->clk = clk_get(NULL, "module_clk"); |
| 1013 | #endif | 1014 | #endif |
| 1014 | 1015 | ||
| @@ -1030,7 +1031,7 @@ static void sci_shutdown(struct uart_port *port) | |||
| 1030 | if (s->disable) | 1031 | if (s->disable) |
| 1031 | s->disable(port); | 1032 | s->disable(port); |
| 1032 | 1033 | ||
| 1033 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | 1034 | #ifdef CONFIG_HAVE_CLK |
| 1034 | clk_put(s->clk); | 1035 | clk_put(s->clk); |
| 1035 | s->clk = NULL; | 1036 | s->clk = NULL; |
| 1036 | #endif | 1037 | #endif |
| @@ -1041,24 +1042,11 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1041 | { | 1042 | { |
| 1042 | struct sci_port *s = &sci_ports[port->line]; | 1043 | struct sci_port *s = &sci_ports[port->line]; |
| 1043 | unsigned int status, baud, smr_val; | 1044 | unsigned int status, baud, smr_val; |
| 1044 | int t; | 1045 | int t = -1; |
| 1045 | 1046 | ||
| 1046 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | 1047 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); |
| 1047 | 1048 | if (likely(baud)) | |
| 1048 | switch (baud) { | 1049 | t = SCBRR_VALUE(baud, port->uartclk); |
| 1049 | case 0: | ||
| 1050 | t = -1; | ||
| 1051 | break; | ||
| 1052 | default: | ||
| 1053 | { | ||
| 1054 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | ||
| 1055 | t = SCBRR_VALUE(baud, clk_get_rate(s->clk)); | ||
| 1056 | #else | ||
| 1057 | t = SCBRR_VALUE(baud); | ||
| 1058 | #endif | ||
| 1059 | break; | ||
| 1060 | } | ||
| 1061 | } | ||
| 1062 | 1050 | ||
| 1063 | do { | 1051 | do { |
| 1064 | status = sci_in(port, SCxSR); | 1052 | status = sci_in(port, SCxSR); |
| @@ -1113,7 +1101,7 @@ static const char *sci_type(struct uart_port *port) | |||
| 1113 | case PORT_IRDA: return "irda"; | 1101 | case PORT_IRDA: return "irda"; |
| 1114 | } | 1102 | } |
| 1115 | 1103 | ||
| 1116 | return 0; | 1104 | return NULL; |
| 1117 | } | 1105 | } |
| 1118 | 1106 | ||
| 1119 | static void sci_release_port(struct uart_port *port) | 1107 | static void sci_release_port(struct uart_port *port) |
| @@ -1145,12 +1133,16 @@ static void sci_config_port(struct uart_port *port, int flags) | |||
| 1145 | break; | 1133 | break; |
| 1146 | } | 1134 | } |
| 1147 | 1135 | ||
| 1148 | #if defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) | 1136 | if (port->flags & UPF_IOREMAP && !port->membase) { |
| 1149 | if (port->mapbase == 0) | 1137 | #if defined(CONFIG_SUPERH64) |
| 1150 | port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF"); | 1138 | port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF"); |
| 1151 | 1139 | port->membase = (void __iomem *)port->mapbase; | |
| 1152 | port->membase = (void __iomem *)port->mapbase; | 1140 | #else |
| 1141 | port->membase = ioremap_nocache(port->mapbase, 0x40); | ||
| 1153 | #endif | 1142 | #endif |
| 1143 | |||
| 1144 | printk(KERN_ERR "sci: can't remap port#%d\n", port->line); | ||
| 1145 | } | ||
| 1154 | } | 1146 | } |
| 1155 | 1147 | ||
| 1156 | static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) | 1148 | static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) |
| @@ -1207,17 +1199,17 @@ static void __init sci_init_ports(void) | |||
| 1207 | sci_ports[i].disable = h8300_sci_disable; | 1199 | sci_ports[i].disable = h8300_sci_disable; |
| 1208 | #endif | 1200 | #endif |
| 1209 | sci_ports[i].port.uartclk = CONFIG_CPU_CLOCK; | 1201 | sci_ports[i].port.uartclk = CONFIG_CPU_CLOCK; |
| 1210 | #elif defined(CONFIG_SUPERH64) | 1202 | #elif defined(CONFIG_HAVE_CLK) |
| 1211 | sci_ports[i].port.uartclk = current_cpu_data.module_clock * 16; | ||
| 1212 | #else | ||
| 1213 | /* | 1203 | /* |
| 1214 | * XXX: We should use a proper SCI/SCIF clock | 1204 | * XXX: We should use a proper SCI/SCIF clock |
| 1215 | */ | 1205 | */ |
| 1216 | { | 1206 | { |
| 1217 | struct clk *clk = clk_get(NULL, "module_clk"); | 1207 | struct clk *clk = clk_get(NULL, "module_clk"); |
| 1218 | sci_ports[i].port.uartclk = clk_get_rate(clk) * 16; | 1208 | sci_ports[i].port.uartclk = clk_get_rate(clk); |
| 1219 | clk_put(clk); | 1209 | clk_put(clk); |
| 1220 | } | 1210 | } |
| 1211 | #else | ||
| 1212 | #error "Need a valid uartclk" | ||
| 1221 | #endif | 1213 | #endif |
| 1222 | 1214 | ||
| 1223 | sci_ports[i].break_timer.data = (unsigned long)&sci_ports[i]; | 1215 | sci_ports[i].break_timer.data = (unsigned long)&sci_ports[i]; |
| @@ -1285,7 +1277,7 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
| 1285 | 1277 | ||
| 1286 | port->type = serial_console_port->type; | 1278 | port->type = serial_console_port->type; |
| 1287 | 1279 | ||
| 1288 | #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) | 1280 | #ifdef CONFIG_HAVE_CLK |
| 1289 | if (!serial_console_port->clk) | 1281 | if (!serial_console_port->clk) |
| 1290 | serial_console_port->clk = clk_get(NULL, "module_clk"); | 1282 | serial_console_port->clk = clk_get(NULL, "module_clk"); |
| 1291 | #endif | 1283 | #endif |
| @@ -1436,7 +1428,7 @@ static struct uart_driver sci_uart_driver = { | |||
| 1436 | static int __devinit sci_probe(struct platform_device *dev) | 1428 | static int __devinit sci_probe(struct platform_device *dev) |
| 1437 | { | 1429 | { |
| 1438 | struct plat_sci_port *p = dev->dev.platform_data; | 1430 | struct plat_sci_port *p = dev->dev.platform_data; |
| 1439 | int i; | 1431 | int i, ret = -EINVAL; |
| 1440 | 1432 | ||
| 1441 | for (i = 0; p && p->flags != 0; p++, i++) { | 1433 | for (i = 0; p && p->flags != 0; p++, i++) { |
| 1442 | struct sci_port *sciport = &sci_ports[i]; | 1434 | struct sci_port *sciport = &sci_ports[i]; |
| @@ -1453,12 +1445,22 @@ static int __devinit sci_probe(struct platform_device *dev) | |||
| 1453 | 1445 | ||
| 1454 | sciport->port.mapbase = p->mapbase; | 1446 | sciport->port.mapbase = p->mapbase; |
| 1455 | 1447 | ||
| 1456 | /* | 1448 | if (p->mapbase && !p->membase) { |
| 1457 | * For the simple (and majority of) cases where we don't need | 1449 | if (p->flags & UPF_IOREMAP) { |
| 1458 | * to do any remapping, just cast the cookie directly. | 1450 | p->membase = ioremap_nocache(p->mapbase, 0x40); |
| 1459 | */ | 1451 | if (IS_ERR(p->membase)) { |
| 1460 | if (p->mapbase && !p->membase && !(p->flags & UPF_IOREMAP)) | 1452 | ret = PTR_ERR(p->membase); |
| 1461 | p->membase = (void __iomem *)p->mapbase; | 1453 | goto err_unreg; |
| 1454 | } | ||
| 1455 | } else { | ||
| 1456 | /* | ||
| 1457 | * For the simple (and majority of) cases | ||
| 1458 | * where we don't need to do any remapping, | ||
| 1459 | * just cast the cookie directly. | ||
| 1460 | */ | ||
| 1461 | p->membase = (void __iomem *)p->mapbase; | ||
| 1462 | } | ||
| 1463 | } | ||
| 1462 | 1464 | ||
| 1463 | sciport->port.membase = p->membase; | 1465 | sciport->port.membase = p->membase; |
| 1464 | 1466 | ||
| @@ -1479,7 +1481,7 @@ static int __devinit sci_probe(struct platform_device *dev) | |||
| 1479 | kgdb_putchar = kgdb_sci_putchar; | 1481 | kgdb_putchar = kgdb_sci_putchar; |
| 1480 | #endif | 1482 | #endif |
| 1481 | 1483 | ||
| 1482 | #ifdef CONFIG_CPU_FREQ | 1484 | #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_HAVE_CLK) |
| 1483 | cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); | 1485 | cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); |
| 1484 | dev_info(&dev->dev, "CPU frequency notifier registered\n"); | 1486 | dev_info(&dev->dev, "CPU frequency notifier registered\n"); |
| 1485 | #endif | 1487 | #endif |
| @@ -1489,6 +1491,12 @@ static int __devinit sci_probe(struct platform_device *dev) | |||
| 1489 | #endif | 1491 | #endif |
| 1490 | 1492 | ||
| 1491 | return 0; | 1493 | return 0; |
| 1494 | |||
| 1495 | err_unreg: | ||
| 1496 | for (i = i - 1; i >= 0; i--) | ||
| 1497 | uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port); | ||
| 1498 | |||
| 1499 | return ret; | ||
| 1492 | } | 1500 | } |
| 1493 | 1501 | ||
| 1494 | static int __devexit sci_remove(struct platform_device *dev) | 1502 | static int __devexit sci_remove(struct platform_device *dev) |
