diff options
author | Magnus Damm <damm@opensource.se> | 2009-12-14 05:24:42 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-12-14 22:06:29 -0500 |
commit | 7b6fd3bf82c4901f6ba0101ba71a5c507c24f9cf (patch) | |
tree | 088bfc0216c0a0db902d3df1f8f6cd9695381f3b | |
parent | 0eb37e26ed332b2a96630cf7f7ebe9fddb41cc3c (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>
-rw-r--r-- | arch/sh/kernel/early_printk.c | 10 | ||||
-rw-r--r-- | arch/sh/kernel/setup.c | 3 | ||||
-rw-r--r-- | drivers/serial/sh-sci.c | 54 |
3 files changed, 49 insertions, 18 deletions
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c index 81a46145ffa5..fe7dc3fe1db1 100644 --- a/arch/sh/kernel/early_printk.c +++ b/arch/sh/kernel/early_printk.c | |||
@@ -191,15 +191,7 @@ static void scif_sercon_init(char *s) | |||
191 | * Setup a default console, if more than one is compiled in, rely on the | 191 | * Setup a default console, if more than one is compiled in, rely on the |
192 | * earlyprintk= parsing to give priority. | 192 | * earlyprintk= parsing to give priority. |
193 | */ | 193 | */ |
194 | static struct console *early_console = | 194 | static struct console *early_console; |
195 | #ifdef CONFIG_SH_STANDARD_BIOS | ||
196 | &bios_console | ||
197 | #elif defined(CONFIG_EARLY_SCIF_CONSOLE) | ||
198 | &scif_console | ||
199 | #else | ||
200 | NULL | ||
201 | #endif | ||
202 | ; | ||
203 | 195 | ||
204 | static int __init setup_early_printk(char *buf) | 196 | static int __init setup_early_printk(char *buf) |
205 | { | 197 | { |
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 5a947a2567e4..8b0e69792cf4 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -423,6 +423,9 @@ void __init setup_arch(char **cmdline_p) | |||
423 | 423 | ||
424 | plat_early_device_setup(); | 424 | plat_early_device_setup(); |
425 | 425 | ||
426 | /* Let earlyprintk output early console messages */ | ||
427 | early_platform_driver_probe("earlyprintk", 1, 1); | ||
428 | |||
426 | sh_mv_setup(); | 429 | sh_mv_setup(); |
427 | 430 | ||
428 | /* | 431 | /* |
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 | ||
1104 | static int __init serial_console_setup(struct console *co, char *options) | 1107 | static 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 | } |
1167 | console_initcall(sci_console_init); | 1175 | console_initcall(sci_console_init); |
1176 | |||
1177 | static struct sci_port early_serial_port; | ||
1178 | static struct console early_serial_console = { | ||
1179 | .name = "early_ttySC", | ||
1180 | .write = serial_console_write, | ||
1181 | .flags = CON_PRINTBUFFER, | ||
1182 | }; | ||
1183 | static 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 | ||
1385 | early_platform_init_buffer("earlyprintk", &sci_driver, | ||
1386 | early_serial_buf, ARRAY_SIZE(early_serial_buf)); | ||
1387 | #endif | ||
1352 | module_init(sci_init); | 1388 | module_init(sci_init); |
1353 | module_exit(sci_exit); | 1389 | module_exit(sci_exit); |
1354 | 1390 | ||