From d608ab9917fbe9926704c07b27df72ac78133870 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Mon, 26 Jun 2006 18:18:11 +0200 Subject: [SERIAL] dz: Fix compilation error Fix the following compilation error in the dz serial driver that got introduced with the "kernel console should send CRLF not LFCR" change. CC drivers/serial/dz.o drivers/serial/dz.c: In function 'dz_console_putchar': drivers/serial/dz.c:679: error: 'uport' undeclared (first use in this function) drivers/serial/dz.c:679: error: (Each undeclared identifier is reported only once drivers/serial/dz.c:679: error: for each function it appears in.) Signed-off-by: Martin Michlmayr Signed-off-by: Russell King --- drivers/serial/dz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index d119c8296a78..8a98aae80e22 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -673,7 +673,7 @@ static void dz_reset(struct dz_port *dport) } #ifdef CONFIG_SERIAL_DZ_CONSOLE -static void dz_console_putchar(struct uart_port *port, int ch) +static void dz_console_putchar(struct uart_port *uport, int ch) { struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; -- cgit v1.2.2 From c65b15cfd6b8b74c6f2b3635bf47ee661d351ef3 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Sun, 9 Jul 2006 20:40:17 +0200 Subject: [SERIAL] IP22: fix serial console hangs The patch below fixes serial console hangs as seen on IP22 machines. Typically, while booting, the machine hangs for ~1 minute displaying "INIT: ", then the same thing happens again when init enters in the designated runlevel and finally the getty process on ttyS0 hangs indefinitely (though strace'ing it helps). strace (-e raw=ioctl, otherwise the ioctl() translation is utterly bogus) reveals that getty hangs on ioctl() 0x540f which happens to be TCSETSW (I saw it hang on another console ioctl() but couldn't reproduce that one). A diff between ip22zilog and sunzilog revealed the following differences: 1. the channel A flag being set on up.port.flags instead of up.flags 2. the channel A flag being set on what is marked as being channel B 3. sunzilog has a call to uart_update_timeout(port, termios->c_cflag, baud); at the end of sunzilog_set_termios(), which ip22zilog lacks (on purpose ?) The patch below addresses point 1 and fixes the serial console hangs just fine. However point 2 should be investigated by someone familiar with the IP22 Zilog; it's probably OK as is but even if it is, a comment in ip22zilog.c is badly needed. Point 3 is left as an exercise for whoever feels like digging into ip22zilog :) These are the main obvious differences between ip22zilog and sunzilog. Newer versions of sunzilog (Linus's git tree as of today) are more close to ip22zilog as the sbus_{write,read}b have been changed into simple {write,read}b, which shrinks the diff by a fair amount. Resyncing both drivers should be doable in a few hours time now for someone familiar with the IP22 Zilog hardware. Signed-off-by: Julien BLACHE Signed-off-by: Russell King --- drivers/serial/ip22zilog.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 342042889f6e..5ff269fb604c 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -1143,9 +1143,8 @@ static void __init ip22zilog_prepare(void) up[(chip * 2) + 1].port.fifosize = 1; up[(chip * 2) + 1].port.ops = &ip22zilog_pops; up[(chip * 2) + 1].port.type = PORT_IP22ZILOG; - up[(chip * 2) + 1].port.flags |= IP22ZILOG_FLAG_IS_CHANNEL_A; up[(chip * 2) + 1].port.line = (chip * 2) + 1; - up[(chip * 2) + 1].flags = 0; + up[(chip * 2) + 1].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A; } } -- cgit v1.2.2 From 3be91ec7388bae3cf1bfb4febcee5ab6c65f409f Mon Sep 17 00:00:00 2001 From: Zang Roy-r61911 Date: Fri, 30 Jun 2006 02:29:58 -0700 Subject: [SERIAL] 8250: add tsi108 serial support The following patch gets rid of CONFIG_TSI108_BRIDGE. I add UPIO_TSI to handle IIR and IER register in serial_in and serial_out. (1) the reason to rewrite serial_in: TSI108 rev Z1 version ERRATA. Reading the UART's Interrupt Identification Register (IIR) clears the Transmit Holding Register Empty (THRE) and Transmit buffer Empty (TEMP) interrupts even if they are not enabled in the Interrupt Enable Register (IER). This leads to loss of the interrupts. Interrupts are not cleared when reading UART registers as 32-bit word. (2) the reason to rewrite serial_out: Check for UART_IER_UUE bit in the autoconfig routine. This section of autoconfig is excluded for Tsi108/109 because bits 7 and 6 are reserved for internal use. They are R/W bits. In addition to incorrect identification, changing these bits (from 00) will make Tsi108/109 UART non-functional. Signed-off-by: Roy Zang Signed-off-by: Andrew Morton Signed-off-by: Russell King --- drivers/serial/8250.c | 12 ++++++++++++ drivers/serial/serial_core.c | 1 + 2 files changed, 13 insertions(+) (limited to 'drivers/serial') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 0995430e4cf1..5443fcd38355 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -299,6 +299,7 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) static unsigned int serial_in(struct uart_8250_port *up, int offset) { + unsigned int tmp; offset = map_8250_in_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { @@ -317,6 +318,13 @@ static unsigned int serial_in(struct uart_8250_port *up, int offset) return __raw_readl(up->port.membase + offset); #endif + case UPIO_TSI: + if (offset == UART_IIR) { + tmp = readl((u32 *)(up->port.membase + UART_RX)); + return (cpu_to_le32(tmp) >> 8) & 0xff; + } else + return readb(up->port.membase + offset); + default: return inb(up->port.iobase + offset); } @@ -346,6 +354,10 @@ serial_out(struct uart_8250_port *up, int offset, int value) __raw_writel(value, up->port.membase + offset); break; #endif + case UPIO_TSI: + if (!((offset == UART_IER) && (value & UART_IER_UUE))) + writeb(value, up->port.membase + offset); + break; default: outb(value, up->port.iobase + offset); diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index d5f636fbf29a..80ef7d482756 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -2036,6 +2036,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) case UPIO_MEM: case UPIO_MEM32: case UPIO_AU: + case UPIO_TSI: snprintf(address, sizeof(address), "MMIO 0x%lx", port->mapbase); break; -- cgit v1.2.2 From 68aa2c0d4a36b43ea9c6d77134c94b4501fd2eb4 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jun 2006 02:29:59 -0700 Subject: [SERIAL] 8250: sysrq deadlock fix Fix http://bugzilla.kernel.org/show_bug.cgi?id=6716 Doing a sysrq over a serial line into an SMP machine presently deadlocks. Signed-off-by: Andrew Morton Signed-off-by: Russell King --- drivers/serial/8250.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 5443fcd38355..0ae9ced00ed4 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2252,10 +2252,14 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) touch_nmi_watchdog(); - if (oops_in_progress) { - locked = spin_trylock_irqsave(&up->port.lock, flags); + local_irq_save(flags); + if (up->port.sysrq) { + /* serial8250_handle_port() already took the lock */ + locked = 0; + } else if (oops_in_progress) { + locked = spin_trylock(&up->port.lock); } else - spin_lock_irqsave(&up->port.lock, flags); + spin_lock(&up->port.lock); /* * First save the IER then disable the interrupts @@ -2277,7 +2281,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) serial_out(up, UART_IER, ier); if (locked) - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock(&up->port.lock); + local_irq_restore(flags); } static int serial8250_console_setup(struct console *co, char *options) -- cgit v1.2.2 From 91d1ed1a6d225e3cf4bd8ede6235b1be65f7651a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 12 Jul 2006 21:04:21 -0700 Subject: [SERIAL] sunsu: Handle keyboard and mouse ports directly. The sunsu_ports[] array exists merely to be able to easily use an integer index to get at the proper serial console port struct. We size this only for real ports, not for the keyboard and mouse, and thus keyboard and mouse port registration would fail. Fix this by dynamically allocating the port struct for the keyboard and mouse, instead of using the sunsu_ports[] array. Signed-off-by: David S. Miller --- drivers/serial/sunsu.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index f9013baba05b..93bdaa3169fc 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1406,25 +1406,35 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m struct device_node *dp = op->node; struct uart_sunsu_port *up; struct resource *rp; + enum su_type type; int err; - if (inst >= UART_NR) - return -EINVAL; + type = su_get_type(dp); + if (type == SU_PORT_PORT) { + if (inst >= UART_NR) + return -EINVAL; + up = &sunsu_ports[inst]; + } else { + up = kzalloc(sizeof(*up), GFP_KERNEL); + if (!up) + return -ENOMEM; + } - up = &sunsu_ports[inst]; up->port.line = inst; spin_lock_init(&up->port.lock); - up->su_type = su_get_type(dp); + up->su_type = type; rp = &op->resource[0]; - up->port.mapbase = op->resource[0].start; - + up->port.mapbase = rp->start; up->reg_size = (rp->end - rp->start) + 1; up->port.membase = of_ioremap(rp, 0, up->reg_size, "su"); - if (!up->port.membase) + if (!up->port.membase) { + if (type != SU_PORT_PORT) + kfree(up); return -ENOMEM; + } up->port.irq = op->irqs[0]; @@ -1436,8 +1446,11 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m err = 0; if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) { err = sunsu_kbd_ms_init(up); - if (err) + if (err) { + kfree(up); goto out_unmap; + } + dev_set_drvdata(&op->dev, up); return 0; } @@ -1476,8 +1489,12 @@ static int __devexit su_remove(struct of_device *dev) #ifdef CONFIG_SERIO serio_unregister_port(&up->serio); #endif - } else if (up->port.type != PORT_UNKNOWN) + kfree(up); + } else if (up->port.type != PORT_UNKNOWN) { uart_remove_one_port(&sunsu_reg, &up->port); + } + + dev_set_drvdata(&dev->dev, NULL); return 0; } -- cgit v1.2.2 From 66151bbd20c6c62dbe5b131484c885086e3a8d29 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Thu, 13 Jul 2006 17:33:03 +0900 Subject: [MIPS] vr41xx: Move IRQ numbers to asm-mips/vr41xx/irq.h Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle --- drivers/serial/vr41xx_siu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/serial') diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index e93d0edc2e08..6c8b0ea83c3c 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -38,6 +38,7 @@ #include #include +#include #include #include -- cgit v1.2.2 From c964521c54304f51705764334f7b27a9518ed65a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 13 Jul 2006 16:05:57 -0700 Subject: [SERIAL] sunsu: Report keyboard and mouse ports in kernel log. Otherwise there is no explicit mention of these devices. Signed-off-by: David S. Miller --- drivers/serial/sunsu.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/serial') diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 93bdaa3169fc..d3a5aeee73a3 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1200,6 +1200,11 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up) if (up->port.type == PORT_UNKNOWN) return -ENODEV; + printk("%s: %s port at %lx, irq %u\n", + to_of_device(up->port.dev)->node->full_name, + (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", + up->port.mapbase, up->port.irq); + #ifdef CONFIG_SERIO serio = &up->serio; serio->port_data = up; -- cgit v1.2.2 From 5b4bbb3d78285ab735941365c17f1c55a228c659 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 13 Jul 2006 16:07:25 -0700 Subject: [SERIAL] sunsab: Fix significant typo in sab_probe() Instead of initializing both ports of a SAB device properly, we were setting up the first port structure twice and ending up only with the second port, oops. Signed-off-by: David S. Miller --- drivers/serial/sunsab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 0dbd4df44c05..979497f108c8 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -1052,7 +1052,7 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id * if (err) return err; - err = sunsab_init_one(&up[0], op, 0, + err = sunsab_init_one(&up[1], op, 0, (inst * 2) + 1); if (err) { of_iounmap(up[0].port.membase, -- cgit v1.2.2 From 44f2650b134b423128063ded29a11454b924390e Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 17 Jul 2006 15:53:32 -0700 Subject: [SPARC64] Fix sunsab ports ordering Register second SAB port before the first one, as serial A is wired to it, and expected to appear as ttyS0. Signed-off-by: Marc Zyngier Signed-off-by: David S. Miller --- drivers/serial/sunsab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 979497f108c8..cb55d81c27d9 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -1061,8 +1061,8 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id * return err; } - uart_add_one_port(&sunsab_reg, &up[0].port); uart_add_one_port(&sunsab_reg, &up[1].port); + uart_add_one_port(&sunsab_reg, &up[0].port); dev_set_drvdata(&op->dev, &up[0]); -- cgit v1.2.2 From bda2f7b4801964351253706d1a87e4d2110829a5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 17 Jul 2006 16:40:26 -0700 Subject: [SERIAL] sunsab: Get line numbers and table sizing correct. Table sizing code should look for "se" not "su" nodes. The chip at the lower address should get the first index. Signed-off-by: David S. Miller --- drivers/serial/sunsab.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index cb55d81c27d9..dc673e1b6fd9 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -1047,12 +1047,13 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id * up = &sunsab_ports[inst * 2]; err = sunsab_init_one(&up[0], op, - sizeof(union sab82532_async_regs), + 0, (inst * 2) + 0); if (err) return err; - err = sunsab_init_one(&up[1], op, 0, + err = sunsab_init_one(&up[1], op, + sizeof(union sab82532_async_regs), (inst * 2) + 1); if (err) { of_iounmap(up[0].port.membase, @@ -1061,8 +1062,8 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id * return err; } - uart_add_one_port(&sunsab_reg, &up[1].port); uart_add_one_port(&sunsab_reg, &up[0].port); + uart_add_one_port(&sunsab_reg, &up[1].port); dev_set_drvdata(&op->dev, &up[0]); @@ -1117,7 +1118,7 @@ static int __init sunsab_init(void) int err; num_channels = 0; - for_each_node_by_name(dp, "su") + for_each_node_by_name(dp, "se") num_channels += 2; for_each_node_by_name(dp, "serial") { if (of_device_is_compatible(dp, "sab82532")) -- cgit v1.2.2 From 67e23a1e60b6bc0a090407d0fc060166ab558b72 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 17 Jul 2006 21:07:17 -0700 Subject: [SERIAL] sunzilog: Register IRQ after all devices have been probed. Otherwise we will deref half-initialized channel pointers and crash in the interrupt handler. Signed-off-by: David S. Miller --- drivers/serial/sunzilog.c | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index a1456d9352cb..496810c50947 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1336,12 +1336,11 @@ static int __devinit zs_get_instance(struct device_node *dp) static int zilog_irq = -1; -static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match) +static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match) { - struct of_device *op = to_of_device(&dev->dev); struct uart_sunzilog_port *up; struct zilog_layout __iomem *rp; - int inst = zs_get_instance(dev->node); + int inst = zs_get_instance(op->node); int err; sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0, @@ -1413,7 +1412,7 @@ static int __devinit zs_probe(struct of_device *dev, const struct of_device_id * } } - dev_set_drvdata(&dev->dev, &up[0]); + dev_set_drvdata(&op->dev, &up[0]); return 0; } @@ -1462,18 +1461,19 @@ static struct of_platform_driver zs_driver = { static int __init sunzilog_init(void) { struct device_node *dp; - int err; + int err, uart_count; NUM_SUNZILOG = 0; for_each_node_by_name(dp, "zs") NUM_SUNZILOG++; + uart_count = 0; if (NUM_SUNZILOG) { int uart_count; err = sunzilog_alloc_tables(); if (err) - return err; + goto out; /* Subtract 1 for keyboard, 1 for mouse. */ uart_count = (NUM_SUNZILOG * 2) - 2; @@ -1481,17 +1481,41 @@ static int __init sunzilog_init(void) sunzilog_reg.nr = uart_count; sunzilog_reg.minor = sunserial_current_minor; err = uart_register_driver(&sunzilog_reg); - if (err) { - sunzilog_free_tables(); - return err; - } + if (err) + goto out_free_tables; + sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64; sunzilog_reg.cons = SUNZILOG_CONSOLE(); sunserial_current_minor += uart_count; } - return of_register_driver(&zs_driver, &of_bus_type); + err = of_register_driver(&zs_driver, &of_bus_type); + if (err) + goto out_unregister_uart; + + if (zilog_irq != -1) { + err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, + "zs", sunzilog_irq_chain); + if (err) + goto out_unregister_driver; + } + +out: + return err; + +out_unregister_driver: + of_unregister_driver(&zs_driver); + +out_unregister_uart: + if (NUM_SUNZILOG) { + uart_unregister_driver(&sunzilog_reg); + sunzilog_reg.cons = NULL; + } + +out_free_tables: + sunzilog_free_tables(); + goto out; } static void __exit sunzilog_exit(void) -- cgit v1.2.2 From b77d35b7229164304d6fb8f047b9bcd3da2c9592 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 19 Jul 2006 21:04:04 -0700 Subject: [SERIAL] sunzilog: Remove duplicate IRQ registry in zs_probe(). We do it now in sunzilog_init() after all devices have been probed. Signed-off-by: David S. Miller --- drivers/serial/sunzilog.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 496810c50947..18df10f49aff 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1351,16 +1351,8 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m rp = sunzilog_chip_regs[inst]; - if (zilog_irq == -1) { + if (zilog_irq == -1) zilog_irq = op->irqs[0]; - err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, - "zs", sunzilog_irq_chain); - if (err) { - of_iounmap(rp, sizeof(struct zilog_layout)); - - return err; - } - } up = &sunzilog_port_table[inst * 2]; -- cgit v1.2.2 From 8a84eb164cc44a7604a27f8118473a82b45472a8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 19 Jul 2006 22:55:08 -0700 Subject: [SERIAL] sunzilog: Fix instance enumeration. Just do a linear enumeration so that we handle sun4d systems correctly. As a consequence, eliminate the hard coded keyboard and mouse channel line values, use the CONS_{KEYB,MS} flags instead. Also, report the keyboard/mouse Zilog channels just like the uart ones do. Signed-off-by: David S. Miller --- drivers/serial/sunzilog.c | 71 +++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 36 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 18df10f49aff..47bc3d57e019 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -68,9 +68,6 @@ static int num_sunzilog; #define NUM_SUNZILOG num_sunzilog #define NUM_CHANNELS (NUM_SUNZILOG * 2) -#define KEYBOARD_LINE 0x2 -#define MOUSE_LINE 0x3 - #define ZS_CLOCK 4915200 /* Zilog input clock rate. */ #define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */ @@ -1225,12 +1222,10 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe { int baud, brg; - if (channel == KEYBOARD_LINE) { - up->flags |= SUNZILOG_FLAG_CONS_KEYB; + if (up->flags & SUNZILOG_FLAG_CONS_KEYB) { up->cflag = B1200 | CS8 | CLOCAL | CREAD; baud = 1200; } else { - up->flags |= SUNZILOG_FLAG_CONS_MOUSE; up->cflag = B4800 | CS8 | CLOCAL | CREAD; baud = 4800; } @@ -1243,14 +1238,14 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe } #ifdef CONFIG_SERIO -static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int channel) +static void __init sunzilog_register_serio(struct uart_sunzilog_port *up) { struct serio *serio = &up->serio; serio->port_data = up; serio->id.type = SERIO_RS232; - if (channel == KEYBOARD_LINE) { + if (up->flags & SUNZILOG_FLAG_CONS_KEYB) { serio->id.proto = SERIO_SUNKBD; strlcpy(serio->name, "zskbd", sizeof(serio->name)); } else { @@ -1259,7 +1254,8 @@ static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int ch strlcpy(serio->name, "zsms", sizeof(serio->name)); } strlcpy(serio->phys, - (channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"), + ((up->flags & SUNZILOG_FLAG_CONS_KEYB) ? + "zs/serio0" : "zs/serio1"), sizeof(serio->phys)); serio->write = sunzilog_serio_write; @@ -1286,8 +1282,8 @@ static void __init sunzilog_init_hw(struct uart_sunzilog_port *up) (void) read_zsreg(channel, R0); } - if (up->port.line == KEYBOARD_LINE || - up->port.line == MOUSE_LINE) { + if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | + SUNZILOG_FLAG_CONS_MOUSE)) { sunzilog_init_kbdms(up, up->port.line); up->curregs[R9] |= (NV | MIE); write_zsreg(channel, R9, up->curregs[R9]); @@ -1313,36 +1309,26 @@ static void __init sunzilog_init_hw(struct uart_sunzilog_port *up) spin_unlock_irqrestore(&up->port.lock, flags); #ifdef CONFIG_SERIO - if (up->port.line == KEYBOARD_LINE || up->port.line == MOUSE_LINE) - sunzilog_register_serio(up, up->port.line); + if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | + SUNZILOG_FLAG_CONS_MOUSE)) + sunzilog_register_serio(up); #endif } -static int __devinit zs_get_instance(struct device_node *dp) -{ - int ret; - - ret = of_getintprop_default(dp, "slave", -1); - if (ret != -1) - return ret; - - if (of_find_property(dp, "keyboard", NULL)) - ret = 1; - else - ret = 0; - - return ret; -} - static int zilog_irq = -1; static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match) { + static int inst; struct uart_sunzilog_port *up; struct zilog_layout __iomem *rp; - int inst = zs_get_instance(op->node); + int keyboard_mouse; int err; + keyboard_mouse = 0; + if (of_find_property(op->node, "keyboard", NULL)) + keyboard_mouse = 1; + sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0, sizeof(struct zilog_layout), "zs"); @@ -1369,7 +1355,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m up[0].port.line = (inst * 2) + 0; up[0].port.dev = &op->dev; up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A; - if (inst == 1) + if (keyboard_mouse) up[0].flags |= SUNZILOG_FLAG_CONS_KEYB; sunzilog_init_hw(&up[0]); @@ -1386,11 +1372,11 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m up[1].port.line = (inst * 2) + 1; up[1].port.dev = &op->dev; up[1].flags |= 0; - if (inst == 1) + if (keyboard_mouse) up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE; sunzilog_init_hw(&up[1]); - if (inst != 1) { + if (!keyboard_mouse) { err = uart_add_one_port(&sunzilog_reg, &up[0].port); if (err) { of_iounmap(rp, sizeof(struct zilog_layout)); @@ -1402,10 +1388,19 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m of_iounmap(rp, sizeof(struct zilog_layout)); return err; } + } else { + printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) " + "is a zs\n", + op->dev.bus_id, up[0].port.mapbase, op->irqs[0]); + printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) " + "is a zs\n", + op->dev.bus_id, up[1].port.mapbase, op->irqs[0]); } dev_set_drvdata(&op->dev, &up[0]); + inst++; + return 0; } @@ -1454,10 +1449,15 @@ static int __init sunzilog_init(void) { struct device_node *dp; int err, uart_count; + int num_keybms; NUM_SUNZILOG = 0; - for_each_node_by_name(dp, "zs") + num_keybms = 0; + for_each_node_by_name(dp, "zs") { NUM_SUNZILOG++; + if (of_find_property(dp, "keyboard", NULL)) + num_keybms++; + } uart_count = 0; if (NUM_SUNZILOG) { @@ -1467,8 +1467,7 @@ static int __init sunzilog_init(void) if (err) goto out; - /* Subtract 1 for keyboard, 1 for mouse. */ - uart_count = (NUM_SUNZILOG * 2) - 2; + uart_count = (NUM_SUNZILOG * 2) - (2 * num_keybms); sunzilog_reg.nr = uart_count; sunzilog_reg.minor = sunserial_current_minor; -- cgit v1.2.2