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