-diff -Nur linux-2.6.17/drivers/char/Kconfig linux-2.6.17-owrt/drivers/char/Kconfig
---- linux-2.6.17/drivers/char/Kconfig 2006-06-18 03:49:35.000000000 +0200
-+++ linux-2.6.17-owrt/drivers/char/Kconfig 2006-06-18 12:41:36.000000000 +0200
-@@ -340,6 +340,14 @@
- To compile this driver as a module, choose M here: the
- module will be called istallion.
+diff -Nur linux-2.6.21.1/drivers/char/Kconfig linux-2.6.21.1-owrt/drivers/char/Kconfig
+--- linux-2.6.21.1/drivers/char/Kconfig 2007-04-27 23:49:26.000000000 +0200
++++ linux-2.6.21.1-owrt/drivers/char/Kconfig 2007-05-24 22:28:54.000000000 +0200
+@@ -386,6 +386,14 @@
+ If you have an Alchemy AU1000 processor (MIPS based) and you want
+ to use a console on a serial port, say Y. Otherwise, say N.
+config SIBYTE_SB1250_DUART
+ bool "Support for BCM1xxx onchip DUART"
+ bool "Console on BCM1xxx DUART"
+ depends on SIBYTE_SB1250_DUART
+
- config AU1000_UART
- bool "Enable Au1000 UART Support"
- depends on SERIAL_NONSTANDARD && MIPS
-diff -Nur linux-2.6.17/drivers/char/Makefile linux-2.6.17-owrt/drivers/char/Makefile
---- linux-2.6.17/drivers/char/Makefile 2006-06-18 03:49:35.000000000 +0200
-+++ linux-2.6.17-owrt/drivers/char/Makefile 2006-06-18 12:42:57.000000000 +0200
-@@ -31,6 +31,7 @@
- obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o
+ config SERIAL_DEC
+ bool "DECstation serial support"
+ depends on MACH_DECSTATION
+diff -Nur linux-2.6.21.1/drivers/char/Makefile linux-2.6.21.1-owrt/drivers/char/Makefile
+--- linux-2.6.21.1/drivers/char/Makefile 2007-04-27 23:49:26.000000000 +0200
++++ linux-2.6.21.1-owrt/drivers/char/Makefile 2007-05-24 22:32:31.000000000 +0200
+@@ -32,6 +32,7 @@
obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
+ obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o
+obj-$(CONFIG_SIBYTE_SB1250_DUART) += sb1250_duart.o
obj-$(CONFIG_COMPUTONE) += ip2/
obj-$(CONFIG_RISCOM8) += riscom8.o
obj-$(CONFIG_ISI) += isicom.o
-diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/char/sb1250_duart.c
---- linux-2.6.17/drivers/char/sb1250_duart.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.17-owrt/drivers/char/sb1250_duart.c 2006-06-18 12:41:36.000000000 +0200
-@@ -0,0 +1,911 @@
+diff -Nur linux-2.6.21.1/drivers/char/sb1250_duart.c linux-2.6.21.1-owrt/drivers/char/sb1250_duart.c
+--- linux-2.6.21.1/drivers/char/sb1250_duart.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.1-owrt/drivers/char/sb1250_duart.c 2007-05-24 22:10:12.000000000 +0200
+@@ -0,0 +1,979 @@
+/*
+ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
+ *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
-+ *
++ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
-+/*
++/*
+ * Driver support for the on-chip sb1250 dual-channel serial port,
+ * running in asynchronous mode. Also, support for doing a serial console
-+ * on one of those ports
++ * on one of those ports
+ */
-+#include <linux/autoconf.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/serial.h>
+EXPORT_SYMBOL(sb1250_duart_present);
+
+/*
-+ * Still not sure what the termios structures set up here are for,
++ * In bug 1956, we get glitches that can mess up uart registers. This
++ * "read-mode-reg after any register access" is an accepted workaround.
++ */
++#if SIBYTE_1956_WAR
++# define SB1_SER1956_WAR { \
++ u32 ignore; \
++ ignore = csr_in32(uart_states[line].mode_1); \
++ ignore = csr_in32(uart_states[line].mode_2); \
++ }
++#else
++# define SB1_SER1956_WAR
++#endif
++
++/*
++ * Still not sure what the termios structures set up here are for,
+ * but we have to supply pointers to them to register the tty driver
+ */
+static struct tty_driver *sb1250_duart_driver; //, sb1250_duart_callout_driver;
+
+/*
-+ * This lock protects both the open flags for all the uart states as
++ * This lock protects both the open flags for all the uart states as
+ * well as the reference count for the module
+ */
+static DEFINE_SPINLOCK(open_lock);
+
-+typedef struct {
-+ unsigned char outp_buf[SERIAL_XMIT_SIZE];
-+ unsigned int outp_head;
-+ unsigned int outp_tail;
-+ unsigned int outp_count;
-+ spinlock_t outp_lock;
-+ unsigned int open;
-+ unsigned int line;
-+ unsigned int last_cflags;
-+ unsigned long flags;
-+ struct tty_struct *tty;
++typedef struct {
++ unsigned char outp_buf[SERIAL_XMIT_SIZE];
++ unsigned int outp_head;
++ unsigned int outp_tail;
++ unsigned int outp_count;
++ spinlock_t outp_lock;
++ unsigned int open;
++ unsigned int line;
++ unsigned int last_cflags;
++ unsigned long flags;
++ struct tty_struct *tty;
++
+ /* CSR addresses */
-+ volatile u32 *status;
-+ volatile u32 *imr;
-+ volatile u32 *tx_hold;
-+ volatile u32 *rx_hold;
-+ volatile u32 *mode_1;
-+ volatile u32 *mode_2;
-+ volatile u32 *clk_sel;
-+ volatile u32 *cmd;
++ unsigned int *status;
++ unsigned int *imr;
++ unsigned int *tx_hold;
++ unsigned int *rx_hold;
++ unsigned int *mode_1;
++ unsigned int *mode_2;
++ unsigned int *clk_sel;
++ unsigned int *cmd;
+} uart_state_t;
+
+static uart_state_t uart_states[DUART_MAX_LINE];
+
+/*
-+ * Inline functions local to this module
++ * Inline functions local to this module
+ */
+
-+/*
-+ * In bug 1956, we get glitches that can mess up uart registers. This
-+ * "write-mode-1 after any register access" is the accepted
-+ * workaround.
-+ */
-+#if SIBYTE_1956_WAR
-+static unsigned int last_mode1[DUART_MAX_LINE];
-+#endif
-+
+static inline u32 READ_SERCSR(volatile u32 *addr, int line)
+{
+ u32 val = csr_in32(addr);
-+#if SIBYTE_1956_WAR
-+ csr_out32(last_mode1[line], uart_states[line].mode_1);
-+#endif
++ SB1_SER1956_WAR;
+ return val;
+}
+
+static inline void WRITE_SERCSR(u32 val, volatile u32 *addr, int line)
+{
+ csr_out32(val, addr);
-+#if SIBYTE_1956_WAR
-+ csr_out32(last_mode1[line], uart_states[line].mode_1);
-+#endif
++ SB1_SER1956_WAR;
+}
+
+static void init_duart_port(uart_state_t *port, int line)
+ port->mode_2 = IOADDR(UNIT_CHANREG(line, R_DUART_MODE_REG_2));
+ port->clk_sel = IOADDR(UNIT_CHANREG(line, R_DUART_CLK_SEL));
+ port->cmd = IOADDR(UNIT_CHANREG(line, R_DUART_CMD));
++ port->last_cflags = DEFAULT_CFLAGS;
++ spin_lock_init(&port->outp_lock);
+ port->flags |= DUART_INITIALIZED;
+ }
+}
+ WRITE_SERCSR(tmp & ~mask, port->imr, line);
+}
+
-+
++
+/* Unmask the passed interrupt lines at the duart level */
+static inline void duart_unmask_ints(unsigned int line, unsigned int mask)
+{
+ duart_mask_ints(us->line, M_DUART_IMR_TX);
+ }
+
-+ if (us->open &&
++ if (us->open &&
+ (us->outp_count < (SERIAL_XMIT_SIZE/2))) {
+ /*
+ * We told the discipline at one point that we had no
+ }
+}
+
-+/*
++/*
+ * Generic interrupt handler for both channels. dev_id is a pointer
-+ * to the proper uart_states structure, so from that we can derive
-+ * which port interrupted
++ * to the proper uart_states structure, so from that we can derive
++ * which port interrupted
+ */
+
+static irqreturn_t duart_int(int irq, void *dev_id)
+
+/* memcpy the data from src to destination, but take extra care if the
+ data is coming from user space */
-+static inline int copy_buf(char *dest, const char *src, int size, int from_user)
++static inline int copy_buf(char *dest, const char *src, int size, int from_user)
+{
+ if (from_user) {
-+ (void) copy_from_user(dest, src, size);
++ (void) copy_from_user(dest, src, size);
+ } else {
+ memcpy(dest, src, size);
+ }
+ us = tty->driver_data;
+ if (!us) return 0;
+
-+ pr_debug("duart_write called for %i chars by %i (%s)\n", count, current->pid, current->comm);
++ pr_debug("duart_write called for %i chars by %i (%s)\n", count,
++ current->pid, current->comm);
+
+ spin_lock_irqsave(&us->outp_lock, flags);
+
+
+ spin_unlock_irqrestore(&us->outp_lock, flags);
+
-+ if (us->outp_count && !tty->stopped &&
++ if (us->outp_count && !tty->stopped &&
+ !tty->hw_stopped && !(us->flags & TX_INTEN)) {
+ us->flags |= TX_INTEN;
+ duart_unmask_ints(us->line, M_DUART_IMR_TX);
+{
+ uart_state_t *port;
+
-+ if (!tty) return;
++ if (!tty)
++ return;
+
+ port = tty->driver_data;
+
-+ if (!port) return;
++ if (!port)
++ return;
+
+ if (port->outp_count <= 0 || tty->stopped || tty->hw_stopped) {
+ return;
+ duart_unmask_ints(port->line, M_DUART_IMR_TX);
+}
+
-+/* Return the number of characters in the output buffer that have yet to be
++/* Return the number of characters in the output buffer that have yet to be
+ written */
+static int duart_chars_in_buffer(struct tty_struct *tty)
+{
+ switch (cflag & CSIZE) {
+ case CS7:
+ mode_reg1 |= V_DUART_BITS_PER_CHAR_7;
-+
++
+ default:
-+ /* We don't handle CS5 or CS6...is there a way we're supposed to flag this?
-+ right now we just force them to CS8 */
++ /* We don't handle CS5 or CS6...is there a way we're supposed to
++ * flag this? right now we just force them to CS8 */
+ mode_reg1 |= 0x0;
+ break;
+ }
+ if (cflag & PARODD) {
+ mode_reg1 |= M_DUART_PARITY_TYPE_ODD;
+ }
-+
++
+ /* Formula for this is (5000000/baud)-1, but we saturate
+ at 12 bits, which means we can't actually do anything less
+ that 1200 baud */
+ switch (cflag & CBAUD) {
-+ case B200:
-+ case B300:
++ case B200:
++ case B300:
+ case B1200: clk_divisor = 4095; break;
+ case B1800: clk_divisor = 2776; break;
+ case B2400: clk_divisor = 2082; break;
+ case B4800: clk_divisor = 1040; break;
-+ default:
+ case B9600: clk_divisor = 519; break;
+ case B19200: clk_divisor = 259; break;
+ case B38400: clk_divisor = 129; break;
++ default:
+ case B57600: clk_divisor = 85; break;
+ case B115200: clk_divisor = 42; break;
+ }
+{
+ uart_state_t *us = (uart_state_t *) tty->driver_data;
+
-+ pr_debug("duart_set_termios called by %i (%s)\n", current->pid, current->comm);
++ pr_debug("duart_set_termios called by %i (%s)\n", current->pid,
++ current->comm);
+ if (old && tty->termios->c_cflag == old->c_cflag)
+ return;
+ duart_set_cflag(us->line, tty->termios->c_cflag);
+}
+
-+static int get_serial_info(uart_state_t *us, struct serial_struct * retinfo) {
-+
++static int get_serial_info(uart_state_t *us, struct serial_struct * retinfo)
++{
+ struct serial_struct tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
+
-+ tmp.type=PORT_SB1250;
-+ tmp.line=us->line;
-+ tmp.port=UNIT_CHANREG(tmp.line,0);
-+ tmp.irq=UNIT_INT(tmp.line);
-+ tmp.xmit_fifo_size=16; /* fixed by hw */
-+ tmp.baud_base=5000000;
-+ tmp.io_type=SERIAL_IO_MEM;
++ tmp.type = PORT_SB1250;
++ tmp.line = us->line;
++ tmp.port = UNIT_CHANREG(tmp.line,0);
++ tmp.irq = UNIT_INT(tmp.line);
++ tmp.xmit_fifo_size = 16; /* fixed by hw */
++ tmp.baud_base = 5000000;
++ tmp.io_type = SERIAL_IO_MEM;
+
+ if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+ return -EFAULT;
+}
+
+/* Not sure on the semantics of this; are we supposed to wait until the stuff
-+ already in the hardware FIFO drains, or are we supposed to wait until
-+ we've drained the output buffer, too? I'm assuming the former, 'cause thats
-+ what the other drivers seem to assume
-+*/
++ * already in the hardware FIFO drains, or are we supposed to wait until
++ * we've drained the output buffer, too? I'm assuming the former, 'cause thats
++ * what the other drivers seem to assume
++ */
+
+static void duart_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ pr_debug("duart_wait_until_sent(%d)+\n", timeout);
+ while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT)) {
+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
++ schedule_timeout(1);
+ if (signal_pending(current))
+ break;
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ return -ENODEV;
+
+ pr_debug("duart_open called by %i (%s), tty is %p, rw is %p, ww is %p\n",
-+ current->pid, current->comm, tty, tty->read_wait,
-+ tty->write_wait);
++ current->pid, current->comm, tty, (void *)&tty->read_wait,
++ (void *)&tty->write_wait);
+
+ us = uart_states + line;
+ tty->driver_data = us;
+
+/* Set up the driver and register it, register the UART interrupts. This
+ is called from tty_init, or as a part of the module init */
-+static int __init sb1250_duart_init(void)
++static int __init sb1250_duart_init(void)
+{
+ int i;
+
+
+ sb1250_duart_driver->owner = THIS_MODULE;
+ sb1250_duart_driver->name = "duart";
-+ sb1250_duart_driver->devfs_name = "duart/";
+ sb1250_duart_driver->major = TTY_MAJOR;
+ sb1250_duart_driver->minor_start = SB1250_DUART_MINOR_BASE;
+ sb1250_duart_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ sb1250_duart_driver->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(sb1250_duart_driver, &duart_ops);
+
-+ for (i=0; i<DUART_MAX_LINE; i++) {
++ for (i = 0; i < DUART_MAX_LINE; i++) {
+ uart_state_t *port = uart_states + i;
+
+ if (!sb1250_duart_present[i])
+ continue;
+
+ init_duart_port(port, i);
-+ spin_lock_init(&port->outp_lock);
+ duart_mask_ints(i, M_DUART_IMR_ALL);
+ if (request_irq(UNIT_INT(i), duart_int, 0, "uart", port)) {
+ panic("Couldn't get uart0 interrupt line");
+ }
-+ __raw_writeq(M_DUART_RX_EN|M_DUART_TX_EN,
-+ IOADDR(UNIT_CHANREG(i, R_DUART_CMD)));
-+ duart_set_cflag(i, DEFAULT_CFLAGS);
++ /*
++ * this generic write to a register does not implement the 1956
++ * WAR and sometimes output gets corrupted afterwards,
++ * especially if the port was in use as a console.
++ */
++ __raw_writel(M_DUART_RX_EN|M_DUART_TX_EN, port->cmd);
++
++ /*
++ * we should really check to see if it's registered as a console
++ * before trashing those settings
++ */
++ duart_set_cflag(i, port->last_cflags);
+ }
+
+ /* Interrupts are now active, our ISR can be called. */
+ tty_unregister_driver(sb1250_duart_driver);
+ put_tty_driver(sb1250_duart_driver);
+
-+ for (i=0; i<DUART_MAX_LINE; i++) {
++ for (i = 0; i < DUART_MAX_LINE; i++) {
+ if (!sb1250_duart_present[i])
+ continue;
+ free_irq(UNIT_INT(i), &uart_states[i]);
+ if (*s == '\n')
+ serial_outc('\r', line);
+ serial_outc(*s++, line);
-+ }
++ }
+ WRITE_SERCSR(imr, port->imr, line);
+}
+
+
+ sb1250_duart_init_present_lines();
+
-+ for (i=0; i<DUART_MAX_LINE; i++) {
++ for (i = 0; i < DUART_MAX_LINE; i++) {
+ uart_state_t *port = uart_states + i;
++ u32 cflags = DEFAULT_CFLAGS;
+
+ if (!sb1250_duart_present[i])
+ continue;
+
+ init_duart_port(port, i);
-+#if SIBYTE_1956_WAR
-+ last_mode1[i] = V_DUART_PARITY_MODE_NONE|V_DUART_BITS_PER_CHAR_8;
-+#endif
-+ WRITE_SERCSR(V_DUART_PARITY_MODE_NONE|V_DUART_BITS_PER_CHAR_8,
-+ port->mode_1, i);
-+ WRITE_SERCSR(M_DUART_STOP_BIT_LEN_1,
-+ port->mode_2, i);
-+ WRITE_SERCSR(V_DUART_BAUD_RATE(115200),
-+ port->clk_sel, i);
-+ WRITE_SERCSR(M_DUART_RX_EN|M_DUART_TX_EN,
-+ port->cmd, i);
++ if (str) {
++ int speed;
++ char par = 'n';
++ int cbits = 8;
++
++ cflags = 0;
++
++ /*
++ * format is in Documentation/serial_console.txt
++ */
++ sscanf(str, "%d%c%d", &speed, &par, &cbits);
++
++ switch (speed) {
++ case 200:
++ case 300:
++ case 1200:
++ cflags |= B1200;
++ break;
++ case 1800:
++ cflags |= B1800;
++ break;
++ case 2400:
++ cflags |= B2400;
++ break;
++ case 4800:
++ cflags |= B4800;
++ break;
++ default:
++ case 9600:
++ cflags |= B9600;
++ break;
++ case 19200:
++ cflags |= B19200;
++ break;
++ case 38400:
++ cflags |= B38400;
++ break;
++ case 57600:
++ cflags |= B57600;
++ break;
++ case 115200:
++ cflags |= B115200;
++ break;
++ }
++ switch (par) {
++ case 'o':
++ cflags |= PARODD;
++ case 'e':
++ cflags |= PARENB;
++ }
++ switch (cbits) {
++ default: // we only do 7 or 8
++ case 8:
++ cflags |= CS8;
++ break;
++ case 7:
++ cflags |= CS7;
++ break;
++ }
++ }
++ duart_set_cflag(i, cflags);
++ WRITE_SERCSR(M_DUART_RX_EN | M_DUART_TX_EN, port->cmd, i);
+ }
++
+ return 0;
+}
+
+
+static int __init sb1250_serial_console_init(void)
+{
++ //add_preferred_console("duart", 0, "57600n8");
+ register_console(&sb1250_ser_cons);
+ return 0;
+}
+console_initcall(sb1250_serial_console_init);
+
+#endif /* CONFIG_SIBYTE_SB1250_DUART_CONSOLE */
-diff -Nur linux-2.6.17/include/linux/serial.h linux-2.6.17-owrt/include/linux/serial.h
---- linux-2.6.17/include/linux/serial.h 2006-06-18 03:49:35.000000000 +0200
-+++ linux-2.6.17-owrt/include/linux/serial.h 2006-06-18 12:41:36.000000000 +0200
+diff -Nur linux-2.6.21.1/include/linux/serial.h linux-2.6.21.1-owrt/include/linux/serial.h
+--- linux-2.6.21.1/include/linux/serial.h 2007-04-27 23:49:26.000000000 +0200
++++ linux-2.6.21.1-owrt/include/linux/serial.h 2007-05-24 22:10:29.000000000 +0200
@@ -76,7 +76,8 @@
#define PORT_16654 11
#define PORT_16850 12