[SERIAL] sunzilog: Fix instance enumeration.
authorDavid S. Miller <davem@sunset.davemloft.net>
Thu, 20 Jul 2006 05:55:08 +0000 (22:55 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 21 Jul 2006 21:18:25 +0000 (14:18 -0700)
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 <davem@davemloft.net>
drivers/serial/sunzilog.c

index 18df10f49aff8d57a5ee8853a8e20c5b87dbd128..47bc3d57e019e225f533d0a30e7b8bdf8fa71fc2 100644 (file)
@@ -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;