aboutsummaryrefslogtreecommitdiffstats
path: root/debian/patches/bugfix/m68k/sun3-3x-serial.diff
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/bugfix/m68k/sun3-3x-serial.diff')
-rw-r--r--debian/patches/bugfix/m68k/sun3-3x-serial.diff486
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;