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