[PATCH] Sun3/3x Serial driver support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <sammy@xxxxxxxxx>

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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux