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 667b4b8fd074..f0658d2c45b2 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) |