diff options
Diffstat (limited to 'debian/patches/bugfix/m68k/sun3-3x-serial.diff')
-rw-r--r-- | debian/patches/bugfix/m68k/sun3-3x-serial.diff | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/debian/patches/bugfix/m68k/sun3-3x-serial.diff b/debian/patches/bugfix/m68k/sun3-3x-serial.diff new file mode 100644 index 000000000000..d49c94941d19 --- /dev/null +++ b/debian/patches/bugfix/m68k/sun3-3x-serial.diff @@ -0,0 +1,486 @@ +From: David Miller <davem@davemloft.net> +To: sammy@sammy.net +Cc: linux-m68k@vger.kernel.org +Subject: Re: [PATCH] Sun3/3x Serial driver support + +From: Sam Creasey <sammy@sammy.net> +Date: Tue, 3 Apr 2007 10:43:42 -0400 + +> 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@sammy.net> + +Same thing here, please build a proper openprom device tree in +the sun3 port and then you'll need to make few, if any, +changes to the sparc drivers. + +I've made these drivers as portable as possible, frankly, and +if you cook up proper in-kernel device objects, you'll need +to do no porting at all. + +--------------------------------------------------------------------------- + +From sammy@sammy.net Tue Apr 3 16:47:31 2007 +Date: Tue, 3 Apr 2007 10:43:42 -0400 +From: Sam Creasey <sammy@sammy.net> +To: linux-m68k@vger.kernel.org, David S. Miller <davem@davemloft.net> +Subject: [PATCH] Sun3/3x Serial driver support + +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@sammy.net> + +--- + drivers/serial/Kconfig | 4 + drivers/serial/suncore.c | 4 + drivers/serial/sunzilog.c | 200 +++++++++++++++++++++++++++++++++++++++++++--- + 3 files changed, 195 insertions(+), 13 deletions(-) + +--- linux-m68k-2.6.21.orig/drivers/serial/Kconfig ++++ linux-m68k-2.6.21/drivers/serial/Kconfig +@@ -543,14 +543,14 @@ config SERIAL_UARTLITE_CONSOLE + + 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. +--- linux-m68k-2.6.21.orig/drivers/serial/suncore.c ++++ linux-m68k-2.6.21/drivers/serial/suncore.c +@@ -29,6 +29,7 @@ EXPORT_SYMBOL(sunserial_current_minor); + 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,9 @@ no_options: + } + + con->cflag = cflag; ++#else /* CONFIG_SUN3(X) */ ++ con->cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8; ++#endif + } + + EXPORT_SYMBOL(sunserial_console_termios); +--- linux-m68k-2.6.21.orig/drivers/serial/sunzilog.c ++++ linux-m68k-2.6.21/drivers/serial/sunzilog.c +@@ -35,13 +35,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" +@@ -415,7 +432,15 @@ static void sunzilog_status_handle(struc + 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; + } + } +@@ -523,6 +548,13 @@ static irqreturn_t sunzilog_interrupt(in + 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); + +@@ -1193,6 +1225,7 @@ static struct console sunzilog_console_o + + static inline struct console *SUNZILOG_CONSOLE(void) + { ++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X) + int i; + + if (con_is_present()) +@@ -1209,6 +1242,10 @@ static inline struct console *SUNZILOG_C + + 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; + } +@@ -1266,6 +1303,8 @@ static void __init sunzilog_register_ser + } + #endif + ++static int zilog_irq = -1; ++ + static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) + { + struct zilog_channel __iomem *channel; +@@ -1276,9 +1315,16 @@ static void __devinit sunzilog_init_hw(s + + 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 | +@@ -1293,7 +1339,11 @@ static void __devinit sunzilog_init_hw(s + 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; +@@ -1314,9 +1364,75 @@ static void __devinit sunzilog_init_hw(s + #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; +@@ -1325,51 +1441,70 @@ static int __devinit zs_probe(struct of_ + 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; +@@ -1378,33 +1513,50 @@ static int __devinit zs_probe(struct of_ + 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)) { +@@ -1445,13 +1597,17 @@ static struct of_platform_driver zs_driv + .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") { +@@ -1459,6 +1615,10 @@ static int __init sunzilog_init(void) + if (of_find_property(dp, "keyboard", NULL)) + num_keybms++; + } ++#else ++ NUM_SUNZILOG = 2; ++ num_keybms = 1; ++#endif + + uart_count = 0; + if (NUM_SUNZILOG) { +@@ -1481,6 +1641,7 @@ static int __init sunzilog_init(void) + + sunserial_current_minor += uart_count; + } ++#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X) + + err = of_register_driver(&zs_driver, &of_bus_type); + if (err) +@@ -1492,12 +1653,28 @@ static int __init sunzilog_init(void) + 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) { +@@ -1512,8 +1689,9 @@ out_free_tables: + + 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; |