aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/sh-sci.c
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2009-12-14 05:24:42 -0500
committerPaul Mundt <lethal@linux-sh.org>2009-12-14 22:06:29 -0500
commit7b6fd3bf82c4901f6ba0101ba71a5c507c24f9cf (patch)
tree088bfc0216c0a0db902d3df1f8f6cd9695381f3b /drivers/serial/sh-sci.c
parent0eb37e26ed332b2a96630cf7f7ebe9fddb41cc3c (diff)
sh-sci: Extend sh-sci driver with early console V2
This is V2 of early serial console support for the sh-sci driver. The early serial console is using early platform devices and "earlyprintk". To use this feature the early platform devices must be broken out to one device per port and the desired port should be selected on the kernel command line like: "earlyprintk=sh-sci.N[,baudrate][,keep]" Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/serial/sh-sci.c')
-rw-r--r--drivers/serial/sh-sci.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index ff38dbdb5c6e..d96c7c7f1b22 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -1043,10 +1043,14 @@ static void __devinit sci_init_single(struct platform_device *dev,
1043 sci_port->port.iotype = UPIO_MEM; 1043 sci_port->port.iotype = UPIO_MEM;
1044 sci_port->port.line = index; 1044 sci_port->port.line = index;
1045 sci_port->port.fifosize = 1; 1045 sci_port->port.fifosize = 1;
1046 sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; 1046
1047 sci_port->dclk = clk_get(&dev->dev, "peripheral_clk"); 1047 if (dev) {
1048 sci_port->enable = sci_clk_enable; 1048 sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL;
1049 sci_port->disable = sci_clk_disable; 1049 sci_port->dclk = clk_get(&dev->dev, "peripheral_clk");
1050 sci_port->enable = sci_clk_enable;
1051 sci_port->disable = sci_clk_disable;
1052 sci_port->port.dev = &dev->dev;
1053 }
1050 1054
1051 sci_port->break_timer.data = (unsigned long)sci_port; 1055 sci_port->break_timer.data = (unsigned long)sci_port;
1052 sci_port->break_timer.function = sci_break_timer; 1056 sci_port->break_timer.function = sci_break_timer;
@@ -1057,7 +1061,6 @@ static void __devinit sci_init_single(struct platform_device *dev,
1057 1061
1058 sci_port->port.irq = p->irqs[SCIx_TXI_IRQ]; 1062 sci_port->port.irq = p->irqs[SCIx_TXI_IRQ];
1059 sci_port->port.flags = p->flags; 1063 sci_port->port.flags = p->flags;
1060 sci_port->port.dev = &dev->dev;
1061 sci_port->type = sci_port->port.type = p->type; 1064 sci_port->type = sci_port->port.type = p->type;
1062 1065
1063 memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); 1066 memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
@@ -1101,7 +1104,7 @@ static void serial_console_write(struct console *co, const char *s,
1101 sci_port->disable(port); 1104 sci_port->disable(port);
1102} 1105}
1103 1106
1104static int __init serial_console_setup(struct console *co, char *options) 1107static int __devinit serial_console_setup(struct console *co, char *options)
1105{ 1108{
1106 struct sci_port *sci_port; 1109 struct sci_port *sci_port;
1107 struct uart_port *port; 1110 struct uart_port *port;
@@ -1119,9 +1122,14 @@ static int __init serial_console_setup(struct console *co, char *options)
1119 if (co->index >= SCI_NPORTS) 1122 if (co->index >= SCI_NPORTS)
1120 co->index = 0; 1123 co->index = 0;
1121 1124
1122 sci_port = &sci_ports[co->index]; 1125 if (co->data) {
1123 port = &sci_port->port; 1126 port = co->data;
1124 co->data = port; 1127 sci_port = to_sci_port(port);
1128 } else {
1129 sci_port = &sci_ports[co->index];
1130 port = &sci_port->port;
1131 co->data = port;
1132 }
1125 1133
1126 /* 1134 /*
1127 * Also need to check port->type, we don't actually have any 1135 * Also need to check port->type, we don't actually have any
@@ -1165,6 +1173,15 @@ static int __init sci_console_init(void)
1165 return 0; 1173 return 0;
1166} 1174}
1167console_initcall(sci_console_init); 1175console_initcall(sci_console_init);
1176
1177static struct sci_port early_serial_port;
1178static struct console early_serial_console = {
1179 .name = "early_ttySC",
1180 .write = serial_console_write,
1181 .flags = CON_PRINTBUFFER,
1182};
1183static char early_serial_buf[32];
1184
1168#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ 1185#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
1169 1186
1170#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) 1187#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
@@ -1250,6 +1267,21 @@ static int __devinit sci_probe(struct platform_device *dev)
1250 struct sh_sci_priv *priv; 1267 struct sh_sci_priv *priv;
1251 int i, ret = -EINVAL; 1268 int i, ret = -EINVAL;
1252 1269
1270#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
1271 if (is_early_platform_device(dev)) {
1272 if (dev->id == -1)
1273 return -ENOTSUPP;
1274 early_serial_console.index = dev->id;
1275 early_serial_console.data = &early_serial_port.port;
1276 sci_init_single(NULL, &early_serial_port, dev->id, p);
1277 serial_console_setup(&early_serial_console, early_serial_buf);
1278 if (!strstr(early_serial_buf, "keep"))
1279 early_serial_console.flags |= CON_BOOT;
1280 register_console(&early_serial_console);
1281 return 0;
1282 }
1283#endif
1284
1253 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 1285 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1254 if (!priv) 1286 if (!priv)
1255 return -ENOMEM; 1287 return -ENOMEM;
@@ -1349,6 +1381,10 @@ static void __exit sci_exit(void)
1349 uart_unregister_driver(&sci_uart_driver); 1381 uart_unregister_driver(&sci_uart_driver);
1350} 1382}
1351 1383
1384#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
1385early_platform_init_buffer("earlyprintk", &sci_driver,
1386 early_serial_buf, ARRAY_SIZE(early_serial_buf));
1387#endif
1352module_init(sci_init); 1388module_init(sci_init);
1353module_exit(sci_exit); 1389module_exit(sci_exit);
1354 1390