Adds serial support for sun3/3x machines.  This patch has basically
been around for years, but my own laziness has kept me from committing
upstream.

Signed-off-by: Sam Creasey <[EMAIL PROTECTED]>

Index: linux-2.6.20/drivers/serial/Kconfig
===================================================================
RCS file: /home/linux-m68k/cvsroot/linux/drivers/serial/Kconfig,v
retrieving revision 1.1.1.34
diff -u -r1.1.1.34 Kconfig
--- linux-2.6.20/drivers/serial/Kconfig 8 Feb 2007 00:37:10 -0000       1.1.1.34
+++ linux-2.6.20/drivers/serial/Kconfig 3 Apr 2007 14:38:22 -0000
@@ -542,14 +542,14 @@
 
 config SERIAL_SUNCORE
        bool
-       depends on SPARC
+       depends on SPARC || SUN3 || SUN3X
        select SERIAL_CORE
        select SERIAL_CORE_CONSOLE
        default y
 
 config SERIAL_SUNZILOG
        tristate "Sun Zilog8530 serial support"
-       depends on SPARC
+       depends on SPARC || SUN3 || SUN3X
        help
          This driver supports the Zilog8530 serial ports found on many Sparc
          systems.  Say Y or M if you want to be able to these serial ports.
Index: linux-2.6.20/drivers/serial/suncore.c
===================================================================
RCS file: /home/linux-m68k/cvsroot/linux/drivers/serial/suncore.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 suncore.c
--- linux-2.6.20/drivers/serial/suncore.c       23 Sep 2006 16:58:46 -0000      
1.1.1.4
+++ linux-2.6.20/drivers/serial/suncore.c       3 Apr 2007 14:38:22 -0000
@@ -29,6 +29,7 @@
 void
 sunserial_console_termios(struct console *con)
 {
+#if !defined(CONFIG_SUN3) && !defined (CONFIG_SUN3X)
        char mode[16], buf[16], *s;
        char *mode_prop = "ttyX-mode";
        char *cd_prop = "ttyX-ignore-cd";
@@ -162,6 +163,10 @@
        }
 
        con->cflag = cflag;
+#else /* CONFIG_SUN3(X) */
+       con->cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8;
+#endif
+       
 }
 
 EXPORT_SYMBOL(sunserial_console_termios);
Index: linux-2.6.20/drivers/serial/sunzilog.c
===================================================================
RCS file: /home/linux-m68k/cvsroot/linux/drivers/serial/sunzilog.c,v
retrieving revision 1.1.1.31
diff -u -r1.1.1.31 sunzilog.c
--- linux-2.6.20/drivers/serial/sunzilog.c      8 Feb 2007 00:37:26 -0000       
1.1.1.31
+++ linux-2.6.20/drivers/serial/sunzilog.c      3 Apr 2007 14:38:22 -0000
@@ -36,13 +36,30 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/prom.h>
-#include <asm/of_device.h>
 
 #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
 
+#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+#include <asm/oplib.h>
+#include <asm/sbus.h>
+#define readb sbus_readb
+#define writeb sbus_writeb
+
+#else
+#include <asm/prom.h>
+#include <asm/of_device.h>
+#endif
+
+#ifdef CONFIG_SUN3
+#include <asm/sun3mmu.h>
+#endif
+
+#ifdef CONFIG_SUN3X
+#include <asm/sun3xprom.h>
+#endif
+
 #include <linux/serial_core.h>
 
 #include "suncore.h"
@@ -416,7 +433,15 @@
                                if (!(status & BRK_ABRT))
                                        break;
                        }
-                       sun_do_break();
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+                       sun_do_break();
+#else
+#ifdef CONFIG_SUN3
+                       prom_reboot("");
+#else
+                       sun3x_reboot();
+#endif
+#endif
                        return;
                }
        }
@@ -524,6 +549,13 @@
                struct tty_struct *tty;
                unsigned char r3;
 
+#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+               if(!channel) {
+                       up = up->next;
+                       continue;
+               }
+#endif
+
                spin_lock(&up->port.lock);
                r3 = read_zsreg(channel, R3);
 
@@ -1194,6 +1226,7 @@
 
 static inline struct console *SUNZILOG_CONSOLE(void)
 {
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
        int i;
 
        if (con_is_present())
@@ -1210,6 +1243,10 @@
 
        sunzilog_console_ops.index = i;
        sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
+#else
+       sunzilog_console_ops.index = 0;
+       sunzilog_port_table[0].flags |= SUNZILOG_FLAG_IS_CONS;
+#endif
 
        return &sunzilog_console_ops;
 }
@@ -1267,6 +1304,8 @@
 }
 #endif
 
+static int zilog_irq = -1;
+
 static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
 {
        struct zilog_channel __iomem *channel;
@@ -1277,9 +1316,16 @@
 
        spin_lock_irqsave(&up->port.lock, flags);
        if (ZS_IS_CHANNEL_A(up)) {
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
                write_zsreg(channel, R9, FHWRES);
                ZSDELAY_LONG();
+#endif
                (void) read_zsreg(channel, R0);
+#ifdef CONFIG_SUN3
+                       /* should sun3x run here? */
+                       /* program the int vector */
+                       write_zsreg(channel, R2, 0x18+zilog_irq);
+#endif
        }
 
        if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
@@ -1294,7 +1340,11 @@
                up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
                up->curregs[R3] = RxENAB | Rx8;
                up->curregs[R5] = TxENAB | Tx8;
+#ifdef CONFIG_SUN3
+               up->curregs[R9] = MIE;
+#else
                up->curregs[R9] = NV | MIE;
+#endif
                up->curregs[R10] = NRZ;
                up->curregs[R11] = TCBR | RCBR;
                baud = 9600;
@@ -1315,9 +1365,75 @@
 #endif
 }
 
-static int zilog_irq = -1;
+#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+static struct zilog_layout * __init get_zs(int chip)
+{
+       unsigned int vaddr = 0;
 
+       if (chip < 0 || chip >= NUM_SUNZILOG) {
+               prom_printf("SunZilog: Illegal chip number %d in get_zs.\n", 
chip);
+               prom_halt();
+       }
+       
+#ifndef CONFIG_SUN3X
+       /* sun3 OBIO version */
+       /* Grrr, these have to be hardcoded aieee */
+       switch(chip) {
+       case 0:
+               for(vaddr = 0xfe00000; vaddr < (0xfe00000 +
+                                               SUN3_PMEG_SIZE); vaddr += 
SUN3_PTE_SIZE) {
+                       unsigned long iopte;
+                       
+                       iopte = sun3_get_pte(vaddr);
+                       if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */
+                               continue;
+                       
+                       if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) ==
+                          0x20000) {
+                               break;
+                       }
+               }
+               break;
+       case 1:
+               for(vaddr = 0xfe00000; vaddr < (0xfe00000 +
+                                               SUN3_PMEG_SIZE); vaddr += 
SUN3_PTE_SIZE) {
+                       
+                       unsigned long iopte;
+
+                       iopte = sun3_get_pte(vaddr);
+                       if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */
+                               continue;
+                       
+                       if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) ==
+                          0) {
+                               break;
+                       }
+               }
+               break;
+       };
+#else
+       /* sun3x is a wee bit cleaner. :) */
+       switch(chip) {
+       case 0:
+               vaddr = SUN3X_ZS2;
+               break;
+
+       case 1:
+               vaddr = SUN3X_ZS1;
+               break;
+       }
+#endif
+
+       if(!vaddr)
+               panic("get_zs whee no serial chip mappable");
+       
+       return (struct zilog_layout *)(unsigned long) vaddr;
+}
+
+static int __devinit zs_probe(void)
+#else
 static int __devinit zs_probe(struct of_device *op, const struct of_device_id 
*match)
+#endif
 {
        static int inst;
        struct uart_sunzilog_port *up;
@@ -1326,51 +1442,70 @@
        int err;
 
        keyboard_mouse = 0;
+#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+       sunzilog_chip_regs[inst] = get_zs(inst);
+       if(inst)
+               keyboard_mouse = 1;
+#else
        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");
+#endif /* CONFIG_SUN3 || CONFIG_SUN3X */
+
        if (!sunzilog_chip_regs[inst])
                return -ENOMEM;
 
        rp = sunzilog_chip_regs[inst];
 
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
        if (zilog_irq == -1)
                zilog_irq = op->irqs[0];
+#endif
 
        up = &sunzilog_port_table[inst * 2];
 
        /* Channel A */
-       up[0].port.mapbase = op->resource[0].start + 0x00;
        up[0].port.membase = (void __iomem *) &rp->channelA;
-       up[0].port.iotype = UPIO_MEM;
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+       up[0].port.mapbase = op->resource[0].start + 0x00;
        up[0].port.irq = op->irqs[0];
+       up[0].port.dev = &op->dev;
+#else
+       up[0].port.mapbase = (unsigned long)up[0].port.membase;
+       up[0].port.irq = zilog_irq;
+#endif
+       up[0].port.iotype = UPIO_MEM;
        up[0].port.uartclk = ZS_CLOCK;
        up[0].port.fifosize = 1;
        up[0].port.ops = &sunzilog_pops;
        up[0].port.type = PORT_SUNZILOG;
        up[0].port.flags = 0;
        up[0].port.line = (inst * 2) + 0;
-       up[0].port.dev = &op->dev;
        up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
        if (keyboard_mouse)
                up[0].flags |= SUNZILOG_FLAG_CONS_KEYB;
        sunzilog_init_hw(&up[0]);
 
        /* Channel B */
-       up[1].port.mapbase = op->resource[0].start + 0x04;
        up[1].port.membase = (void __iomem *) &rp->channelB;
-       up[1].port.iotype = UPIO_MEM;
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
+       up[1].port.mapbase = op->resource[0].start + 0x04;
        up[1].port.irq = op->irqs[0];
+       up[1].port.dev = &op->dev;
+#else
+       up[1].port.mapbase = (unsigned long)up[1].port.membase;
+       up[1].port.irq = zilog_irq;
+#endif
+       up[1].port.iotype = UPIO_MEM;
        up[1].port.uartclk = ZS_CLOCK;
        up[1].port.fifosize = 1;
        up[1].port.ops = &sunzilog_pops;
        up[1].port.type = PORT_SUNZILOG;
        up[1].port.flags = 0;
        up[1].port.line = (inst * 2) + 1;
-       up[1].port.dev = &op->dev;
        up[1].flags |= 0;
        if (keyboard_mouse)
                up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE;
@@ -1379,33 +1514,50 @@
        if (!keyboard_mouse) {
                err = uart_add_one_port(&sunzilog_reg, &up[0].port);
                if (err) {
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
                        of_iounmap(&op->resource[0],
                                   rp, sizeof(struct zilog_layout));
+#endif
                        return err;
                }
                err = uart_add_one_port(&sunzilog_reg, &up[1].port);
                if (err) {
                        uart_remove_one_port(&sunzilog_reg, &up[0].port);
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
                        of_iounmap(&op->resource[0],
                                   rp, sizeof(struct zilog_layout));
+#endif
                        return err;
                }
        } else {
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
                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]);
+#else
+               printk(KERN_INFO "zs%d: Keyboard at MMIO %lx (irq = %d) "
+                      "is a zs\n",
+                      inst, up[0].port.mapbase, zilog_irq);
+               printk(KERN_INFO "zs%d: Mouse at MMIO %lx (irq = %d) "
+                      "is a zs\n",
+                      inst, up[1].port.mapbase, zilog_irq);
+#endif
        }
 
+
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
        dev_set_drvdata(&op->dev, &up[0]);
+#endif
 
        inst++;
 
        return 0;
 }
 
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
 static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
 {
        if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
@@ -1446,13 +1598,17 @@
        .probe          = zs_probe,
        .remove         = __devexit_p(zs_remove),
 };
+#endif /* !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X) */
 
 static int __init sunzilog_init(void)
 {
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
        struct device_node *dp;
+#endif
        int err, uart_count;
        int num_keybms;
 
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
        NUM_SUNZILOG = 0;
        num_keybms = 0;
        for_each_node_by_name(dp, "zs") {
@@ -1460,6 +1616,10 @@
                if (of_find_property(dp, "keyboard", NULL))
                        num_keybms++;
        }
+#else
+       NUM_SUNZILOG = 2;
+       num_keybms = 1;
+#endif
 
        uart_count = 0;
        if (NUM_SUNZILOG) {
@@ -1482,6 +1642,7 @@
 
                sunserial_current_minor += uart_count;
        }
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
 
        err = of_register_driver(&zs_driver, &of_bus_type);
        if (err)
@@ -1493,12 +1654,28 @@
                if (err)
                        goto out_unregister_driver;
        }
+#else
+       
+       zilog_irq = 6;
+       err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_DISABLED,
+                         "zs", sunzilog_irq_chain);
+       if (err)
+               goto out_unregister_uart;
+
+       /* probe for two zs instances on sun3/3x */
+       zs_probe();
+       zs_probe();
+
+
+#endif
 
 out:
        return err;
 
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
 out_unregister_driver:
        of_unregister_driver(&zs_driver);
+#endif
 
 out_unregister_uart:
        if (NUM_SUNZILOG) {
@@ -1513,8 +1690,9 @@
 
 static void __exit sunzilog_exit(void)
 {
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X)
        of_unregister_driver(&zs_driver);
-
+#endif
        if (zilog_irq != -1) {
                free_irq(zilog_irq, sunzilog_irq_chain);
                zilog_irq = -1;
-
To unsubscribe from this list: send the line "unsubscribe linux-m68k" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to