summaryrefslogtreecommitdiffstats
path: root/drivers/serial/sunsu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/sunsu.c')
-rw-r--r--drivers/serial/sunsu.c79
1 files changed, 55 insertions, 24 deletions
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 47c6837850b..551ebfe3ccb 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -29,6 +29,7 @@
#include <linux/serial.h>
#include <linux/sysrq.h>
#include <linux/console.h>
+#include <linux/slab.h>
#ifdef CONFIG_SERIO
#include <linux/serio.h>
#endif
@@ -311,7 +312,7 @@ static void sunsu_enable_ms(struct uart_port *port)
static struct tty_struct *
receive_chars(struct uart_sunsu_port *up, unsigned char *status)
{
- struct tty_struct *tty = up->port.info->port.tty;
+ struct tty_struct *tty = up->port.state->port.tty;
unsigned char ch, flag;
int max_count = 256;
int saw_console_brk = 0;
@@ -389,7 +390,7 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status)
static void transmit_chars(struct uart_sunsu_port *up)
{
- struct circ_buf *xmit = &up->port.info->xmit;
+ struct circ_buf *xmit = &up->port.state->xmit;
int count;
if (up->port.x_char) {
@@ -441,7 +442,7 @@ static void check_modem_status(struct uart_sunsu_port *up)
if (status & UART_MSR_DCTS)
uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
- wake_up_interruptible(&up->port.info->delta_msr_wait);
+ wake_up_interruptible(&up->port.state->port.delta_msr_wait);
}
static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id)
@@ -1199,7 +1200,7 @@ static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up)
return -ENODEV;
printk("%s: %s port at %llx, irq %u\n",
- to_of_device(up->port.dev)->node->full_name,
+ up->port.dev->of_node->full_name,
(up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse",
(unsigned long long) up->port.mapbase,
up->port.irq);
@@ -1329,11 +1330,9 @@ static void sunsu_console_write(struct console *co, const char *s,
*/
static int __init sunsu_console_setup(struct console *co, char *options)
{
+ static struct ktermios dummy;
+ struct ktermios termios;
struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
printk("Console: ttyS%d (SU)\n",
(sunsu_reg.minor - 64) + co->index);
@@ -1352,10 +1351,15 @@ static int __init sunsu_console_setup(struct console *co, char *options)
*/
spin_lock_init(&port->lock);
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
+ /* Get firmware console settings. */
+ sunserial_console_termios(co, port->dev->of_node);
- return uart_set_options(port, co, baud, parity, bits, flow);
+ memset(&termios, 0, sizeof(struct ktermios));
+ termios.c_cflag = co->cflag;
+ port->mctrl |= TIOCM_DTR;
+ port->ops->set_termios(port, &termios, &dummy);
+
+ return 0;
}
static struct console sunsu_console = {
@@ -1402,13 +1406,14 @@ static enum su_type __devinit su_get_type(struct device_node *dp)
return SU_PORT_PORT;
}
-static int __devinit su_probe(struct of_device *op, const struct of_device_id *match)
+static int __devinit su_probe(struct platform_device *op, const struct of_device_id *match)
{
static int inst;
- struct device_node *dp = op->node;
+ struct device_node *dp = op->dev.of_node;
struct uart_sunsu_port *up;
struct resource *rp;
enum su_type type;
+ bool ignore_line;
int err;
type = su_get_type(dp);
@@ -1438,7 +1443,7 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
return -ENOMEM;
}
- up->port.irq = op->irqs[0];
+ up->port.irq = op->archdata.irqs[0];
up->port.dev = &op->dev;
@@ -1449,8 +1454,10 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) {
err = sunsu_kbd_ms_init(up);
if (err) {
+ of_iounmap(&op->resource[0],
+ up->port.membase, up->reg_size);
kfree(up);
- goto out_unmap;
+ return err;
}
dev_set_drvdata(&op->dev, up);
@@ -1467,8 +1474,14 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
up->port.ops = &sunsu_pops;
+ ignore_line = false;
+ if (!strcmp(dp->name, "rsc-console") ||
+ !strcmp(dp->name, "lom-console"))
+ ignore_line = true;
+
sunserial_console_match(SUNSU_CONSOLE(), dp,
- &sunsu_reg, up->port.line);
+ &sunsu_reg, up->port.line,
+ ignore_line);
err = uart_add_one_port(&sunsu_reg, &up->port);
if (err)
goto out_unmap;
@@ -1484,23 +1497,28 @@ out_unmap:
return err;
}
-static int __devexit su_remove(struct of_device *op)
+static int __devexit su_remove(struct platform_device *op)
{
struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
+ bool kbdms = false;
if (up->su_type == SU_PORT_MS ||
- up->su_type == SU_PORT_KBD) {
+ up->su_type == SU_PORT_KBD)
+ kbdms = true;
+
+ if (kbdms) {
#ifdef CONFIG_SERIO
serio_unregister_port(&up->serio);
#endif
- kfree(up);
- } else if (up->port.type != PORT_UNKNOWN) {
+ } else if (up->port.type != PORT_UNKNOWN)
uart_remove_one_port(&sunsu_reg, &up->port);
- }
if (up->port.membase)
of_iounmap(&op->resource[0], up->port.membase, up->reg_size);
+ if (kbdms)
+ kfree(up);
+
dev_set_drvdata(&op->dev, NULL);
return 0;
@@ -1517,13 +1535,20 @@ static const struct of_device_id su_match[] = {
.name = "serial",
.compatible = "su",
},
+ {
+ .type = "serial",
+ .compatible = "su",
+ },
{},
};
MODULE_DEVICE_TABLE(of, su_match);
static struct of_platform_driver su_driver = {
- .name = "su",
- .match_table = su_match,
+ .driver = {
+ .name = "su",
+ .owner = THIS_MODULE,
+ .of_match_table = su_match,
+ },
.probe = su_probe,
.remove = __devexit_p(su_remove),
};
@@ -1548,6 +1573,12 @@ static int __init sunsu_init(void)
num_uart++;
}
}
+ for_each_node_by_type(dp, "serial") {
+ if (of_device_is_compatible(dp, "su")) {
+ if (su_get_type(dp) == SU_PORT_PORT)
+ num_uart++;
+ }
+ }
if (num_uart) {
err = sunserial_register_minors(&sunsu_reg, num_uart);
@@ -1555,7 +1586,7 @@ static int __init sunsu_init(void)
return err;
}
- err = of_register_driver(&su_driver, &of_bus_type);
+ err = of_register_platform_driver(&su_driver);
if (err && num_uart)
sunserial_unregister_minors(&sunsu_reg, num_uart);