1 diff -Nur linux-2.6.21.1/drivers/char/Kconfig linux-2.6.21.1-owrt/drivers/char/Kconfig
2 --- linux-2.6.21.1/drivers/char/Kconfig 2007-04-27 23:49:26.000000000 +0200
3 +++ linux-2.6.21.1-owrt/drivers/char/Kconfig 2007-05-24 22:28:54.000000000 +0200
5 If you have an Alchemy AU1000 processor (MIPS based) and you want
6 to use a console on a serial port, say Y. Otherwise, say N.
8 +config SIBYTE_SB1250_DUART
9 + bool "Support for BCM1xxx onchip DUART"
10 + depends on MIPS && SIBYTE_SB1xxx_SOC=y
12 +config SIBYTE_SB1250_DUART_CONSOLE
13 + bool "Console on BCM1xxx DUART"
14 + depends on SIBYTE_SB1250_DUART
17 bool "DECstation serial support"
18 depends on MACH_DECSTATION
19 diff -Nur linux-2.6.21.1/drivers/char/Makefile linux-2.6.21.1-owrt/drivers/char/Makefile
20 --- linux-2.6.21.1/drivers/char/Makefile 2007-04-27 23:49:26.000000000 +0200
21 +++ linux-2.6.21.1-owrt/drivers/char/Makefile 2007-05-24 22:32:31.000000000 +0200
23 obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
24 obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
25 obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o
26 +obj-$(CONFIG_SIBYTE_SB1250_DUART) += sb1250_duart.o
27 obj-$(CONFIG_COMPUTONE) += ip2/
28 obj-$(CONFIG_RISCOM8) += riscom8.o
29 obj-$(CONFIG_ISI) += isicom.o
30 diff -Nur linux-2.6.21.1/drivers/char/sb1250_duart.c linux-2.6.21.1-owrt/drivers/char/sb1250_duart.c
31 --- linux-2.6.21.1/drivers/char/sb1250_duart.c 1970-01-01 01:00:00.000000000 +0100
32 +++ linux-2.6.21.1-owrt/drivers/char/sb1250_duart.c 2007-05-24 22:10:12.000000000 +0200
35 + * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
37 + * This program is free software; you can redistribute it and/or
38 + * modify it under the terms of the GNU General Public License
39 + * as published by the Free Software Foundation; either version 2
40 + * of the License, or (at your option) any later version.
42 + * This program is distributed in the hope that it will be useful,
43 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
44 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 + * GNU General Public License for more details.
47 + * You should have received a copy of the GNU General Public License
48 + * along with this program; if not, write to the Free Software
49 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
53 + * Driver support for the on-chip sb1250 dual-channel serial port,
54 + * running in asynchronous mode. Also, support for doing a serial console
55 + * on one of those ports
57 +#include <linux/types.h>
58 +#include <linux/kernel.h>
59 +#include <linux/serial.h>
60 +#include <linux/interrupt.h>
61 +#include <linux/module.h>
62 +#include <linux/console.h>
63 +#include <linux/kdev_t.h>
64 +#include <linux/major.h>
65 +#include <linux/termios.h>
66 +#include <linux/spinlock.h>
67 +#include <linux/irq.h>
68 +#include <linux/errno.h>
69 +#include <linux/tty.h>
70 +#include <linux/sched.h>
71 +#include <linux/tty_flip.h>
72 +#include <linux/timer.h>
73 +#include <linux/init.h>
74 +#include <linux/mm.h>
75 +#include <asm/delay.h>
77 +#include <asm/uaccess.h>
78 +#include <asm/sibyte/swarm.h>
79 +#include <asm/sibyte/sb1250.h>
80 +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
81 +#include <asm/sibyte/bcm1480_regs.h>
82 +#include <asm/sibyte/bcm1480_int.h>
83 +#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
84 +#include <asm/sibyte/sb1250_regs.h>
85 +#include <asm/sibyte/sb1250_int.h>
87 +#error invalid SiByte UART configuation
89 +#include <asm/sibyte/sb1250_uart.h>
92 +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
93 +#define UNIT_CHANREG(n,reg) A_BCM1480_DUART_CHANREG((n),(reg))
94 +#define UNIT_IMRREG(n) A_BCM1480_DUART_IMRREG(n)
95 +#define UNIT_INT(n) (K_BCM1480_INT_UART_0 + (n))
96 +#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
97 +#define UNIT_CHANREG(n,reg) A_DUART_CHANREG((n),(reg))
98 +#define UNIT_IMRREG(n) A_DUART_IMRREG(n)
99 +#define UNIT_INT(n) (K_INT_UART_0 + (n))
101 +#error invalid SiByte UART configuation
104 +/* Toggle spewing of debugging output */
107 +#define DEFAULT_CFLAGS (CS8 | B115200)
110 +#define DUART_INITIALIZED 2
112 +#define DUART_MAX_LINE 4
113 +char sb1250_duart_present[DUART_MAX_LINE];
114 +EXPORT_SYMBOL(sb1250_duart_present);
117 + * In bug 1956, we get glitches that can mess up uart registers. This
118 + * "read-mode-reg after any register access" is an accepted workaround.
121 +# define SB1_SER1956_WAR { \
123 + ignore = csr_in32(uart_states[line].mode_1); \
124 + ignore = csr_in32(uart_states[line].mode_2); \
127 +# define SB1_SER1956_WAR
131 + * Still not sure what the termios structures set up here are for,
132 + * but we have to supply pointers to them to register the tty driver
134 +static struct tty_driver *sb1250_duart_driver; //, sb1250_duart_callout_driver;
137 + * This lock protects both the open flags for all the uart states as
138 + * well as the reference count for the module
140 +static DEFINE_SPINLOCK(open_lock);
143 + unsigned char outp_buf[SERIAL_XMIT_SIZE];
144 + unsigned int outp_head;
145 + unsigned int outp_tail;
146 + unsigned int outp_count;
147 + spinlock_t outp_lock;
150 + unsigned int last_cflags;
151 + unsigned long flags;
152 + struct tty_struct *tty;
154 + /* CSR addresses */
155 + unsigned int *status;
157 + unsigned int *tx_hold;
158 + unsigned int *rx_hold;
159 + unsigned int *mode_1;
160 + unsigned int *mode_2;
161 + unsigned int *clk_sel;
165 +static uart_state_t uart_states[DUART_MAX_LINE];
168 + * Inline functions local to this module
171 +static inline u32 READ_SERCSR(volatile u32 *addr, int line)
173 + u32 val = csr_in32(addr);
178 +static inline void WRITE_SERCSR(u32 val, volatile u32 *addr, int line)
180 + csr_out32(val, addr);
184 +static void init_duart_port(uart_state_t *port, int line)
186 + if (!(port->flags & DUART_INITIALIZED)) {
188 + port->status = IOADDR(UNIT_CHANREG(line, R_DUART_STATUS));
189 + port->imr = IOADDR(UNIT_IMRREG(line));
190 + port->tx_hold = IOADDR(UNIT_CHANREG(line, R_DUART_TX_HOLD));
191 + port->rx_hold = IOADDR(UNIT_CHANREG(line, R_DUART_RX_HOLD));
192 + port->mode_1 = IOADDR(UNIT_CHANREG(line, R_DUART_MODE_REG_1));
193 + port->mode_2 = IOADDR(UNIT_CHANREG(line, R_DUART_MODE_REG_2));
194 + port->clk_sel = IOADDR(UNIT_CHANREG(line, R_DUART_CLK_SEL));
195 + port->cmd = IOADDR(UNIT_CHANREG(line, R_DUART_CMD));
196 + port->last_cflags = DEFAULT_CFLAGS;
197 + spin_lock_init(&port->outp_lock);
198 + port->flags |= DUART_INITIALIZED;
203 + * Mask out the passed interrupt lines at the duart level. This should be
204 + * called while holding the associated outp_lock.
206 +static inline void duart_mask_ints(unsigned int line, unsigned int mask)
208 + uart_state_t *port = uart_states + line;
209 + u64 tmp = READ_SERCSR(port->imr, line);
210 + WRITE_SERCSR(tmp & ~mask, port->imr, line);
214 +/* Unmask the passed interrupt lines at the duart level */
215 +static inline void duart_unmask_ints(unsigned int line, unsigned int mask)
217 + uart_state_t *port = uart_states + line;
218 + u64 tmp = READ_SERCSR(port->imr, line);
219 + WRITE_SERCSR(tmp | mask, port->imr, line);
222 +static inline void transmit_char_pio(uart_state_t *us)
224 + struct tty_struct *tty = us->tty;
227 + if (spin_trylock(&us->outp_lock)) {
229 + if (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_RDY))
231 + if (us->outp_count <= 0 || tty->stopped || tty->hw_stopped) {
234 + WRITE_SERCSR(us->outp_buf[us->outp_head],
235 + us->tx_hold, us->line);
236 + us->outp_head = (us->outp_head + 1) & (SERIAL_XMIT_SIZE-1);
237 + if (--us->outp_count <= 0)
242 + spin_unlock(&us->outp_lock);
247 + if (!us->outp_count || tty->stopped ||
248 + tty->hw_stopped || blocked) {
249 + us->flags &= ~TX_INTEN;
250 + duart_mask_ints(us->line, M_DUART_IMR_TX);
254 + (us->outp_count < (SERIAL_XMIT_SIZE/2))) {
256 + * We told the discipline at one point that we had no
257 + * space, so it went to sleep. Wake it up when we hit
260 + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
261 + tty->ldisc.write_wakeup)
262 + tty->ldisc.write_wakeup(tty);
263 + wake_up_interruptible(&tty->write_wait);
268 + * Generic interrupt handler for both channels. dev_id is a pointer
269 + * to the proper uart_states structure, so from that we can derive
270 + * which port interrupted
273 +static irqreturn_t duart_int(int irq, void *dev_id)
275 + uart_state_t *us = (uart_state_t *)dev_id;
276 + struct tty_struct *tty = us->tty;
277 + unsigned int status = READ_SERCSR(us->status, us->line);
279 + pr_debug("DUART INT\n");
281 + if (status & M_DUART_RX_RDY) {
282 + int counter = 2048;
285 + if (status & M_DUART_OVRUN_ERR)
286 + tty_insert_flip_char(tty, 0, TTY_OVERRUN);
287 + if (status & M_DUART_PARITY_ERR) {
288 + printk("Parity error!\n");
289 + } else if (status & M_DUART_FRM_ERR) {
290 + printk("Frame error!\n");
293 + while (counter > 0) {
294 + if (!(READ_SERCSR(us->status, us->line) & M_DUART_RX_RDY))
296 + ch = READ_SERCSR(us->rx_hold, us->line);
297 + tty_insert_flip_char(tty, ch, 0);
301 + tty_flip_buffer_push(tty);
304 + if (status & M_DUART_TX_RDY) {
305 + transmit_char_pio(us);
308 + return IRQ_HANDLED;
312 + * Actual driver functions
315 +/* Return the number of characters we can accomodate in a write at this instant */
316 +static int duart_write_room(struct tty_struct *tty)
318 + uart_state_t *us = (uart_state_t *) tty->driver_data;
321 + retval = SERIAL_XMIT_SIZE - us->outp_count;
323 + pr_debug("duart_write_room called, returning %i\n", retval);
328 +/* memcpy the data from src to destination, but take extra care if the
329 + data is coming from user space */
330 +static inline int copy_buf(char *dest, const char *src, int size, int from_user)
333 + (void) copy_from_user(dest, src, size);
335 + memcpy(dest, src, size);
341 + * Buffer up to count characters from buf to be written. If we don't have
342 + * other characters buffered, enable the tx interrupt to start sending
344 +static int duart_write(struct tty_struct *tty, const unsigned char *buf,
348 + int c, t, total = 0;
349 + unsigned long flags;
351 + if (!tty) return 0;
353 + us = tty->driver_data;
356 + pr_debug("duart_write called for %i chars by %i (%s)\n", count,
357 + current->pid, current->comm);
359 + spin_lock_irqsave(&us->outp_lock, flags);
364 + t = SERIAL_XMIT_SIZE - us->outp_tail;
367 + t = SERIAL_XMIT_SIZE - 1 - us->outp_count;
372 + memcpy(us->outp_buf + us->outp_tail, buf, c);
374 + us->outp_count += c;
375 + us->outp_tail = (us->outp_tail + c) & (SERIAL_XMIT_SIZE - 1);
381 + spin_unlock_irqrestore(&us->outp_lock, flags);
383 + if (us->outp_count && !tty->stopped &&
384 + !tty->hw_stopped && !(us->flags & TX_INTEN)) {
385 + us->flags |= TX_INTEN;
386 + duart_unmask_ints(us->line, M_DUART_IMR_TX);
393 +/* Buffer one character to be written. If there's not room for it, just drop
394 + it on the floor. This is used for echo, among other things */
395 +static void duart_put_char(struct tty_struct *tty, u_char ch)
397 + uart_state_t *us = (uart_state_t *) tty->driver_data;
398 + unsigned long flags;
400 + pr_debug("duart_put_char called. Char is %x (%c)\n", (int)ch, ch);
402 + spin_lock_irqsave(&us->outp_lock, flags);
404 + if (us->outp_count == SERIAL_XMIT_SIZE) {
405 + spin_unlock_irqrestore(&us->outp_lock, flags);
409 + us->outp_buf[us->outp_tail] = ch;
410 + us->outp_tail = (us->outp_tail + 1) &(SERIAL_XMIT_SIZE-1);
413 + spin_unlock_irqrestore(&us->outp_lock, flags);
416 +static void duart_flush_chars(struct tty_struct * tty)
418 + uart_state_t *port;
423 + port = tty->driver_data;
428 + if (port->outp_count <= 0 || tty->stopped || tty->hw_stopped) {
432 + port->flags |= TX_INTEN;
433 + duart_unmask_ints(port->line, M_DUART_IMR_TX);
436 +/* Return the number of characters in the output buffer that have yet to be
438 +static int duart_chars_in_buffer(struct tty_struct *tty)
440 + uart_state_t *us = (uart_state_t *) tty->driver_data;
443 + retval = us->outp_count;
445 + pr_debug("duart_chars_in_buffer returning %i\n", retval);
450 +/* Kill everything we haven't yet shoved into the FIFO. Turn off the
451 + transmit interrupt since we've nothing more to transmit */
452 +static void duart_flush_buffer(struct tty_struct *tty)
454 + uart_state_t *us = (uart_state_t *) tty->driver_data;
455 + unsigned long flags;
457 + pr_debug("duart_flush_buffer called\n");
458 + spin_lock_irqsave(&us->outp_lock, flags);
459 + us->outp_head = us->outp_tail = us->outp_count = 0;
460 + spin_unlock_irqrestore(&us->outp_lock, flags);
462 + wake_up_interruptible(&us->tty->write_wait);
463 + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
464 + tty->ldisc.write_wakeup)
465 + tty->ldisc.write_wakeup(tty);
469 +/* See sb1250 user manual for details on these registers */
470 +static inline void duart_set_cflag(unsigned int line, unsigned int cflag)
472 + unsigned int mode_reg1 = 0, mode_reg2 = 0;
473 + unsigned int clk_divisor;
474 + uart_state_t *port = uart_states + line;
476 + switch (cflag & CSIZE) {
478 + mode_reg1 |= V_DUART_BITS_PER_CHAR_7;
481 + /* We don't handle CS5 or CS6...is there a way we're supposed to
482 + * flag this? right now we just force them to CS8 */
486 + if (cflag & CSTOPB) {
487 + mode_reg2 |= M_DUART_STOP_BIT_LEN_2;
489 + if (!(cflag & PARENB)) {
490 + mode_reg1 |= V_DUART_PARITY_MODE_NONE;
492 + if (cflag & PARODD) {
493 + mode_reg1 |= M_DUART_PARITY_TYPE_ODD;
496 + /* Formula for this is (5000000/baud)-1, but we saturate
497 + at 12 bits, which means we can't actually do anything less
499 + switch (cflag & CBAUD) {
502 + case B1200: clk_divisor = 4095; break;
503 + case B1800: clk_divisor = 2776; break;
504 + case B2400: clk_divisor = 2082; break;
505 + case B4800: clk_divisor = 1040; break;
506 + case B9600: clk_divisor = 519; break;
507 + case B19200: clk_divisor = 259; break;
508 + case B38400: clk_divisor = 129; break;
510 + case B57600: clk_divisor = 85; break;
511 + case B115200: clk_divisor = 42; break;
513 + WRITE_SERCSR(mode_reg1, port->mode_1, port->line);
514 + WRITE_SERCSR(mode_reg2, port->mode_2, port->line);
515 + WRITE_SERCSR(clk_divisor, port->clk_sel, port->line);
516 + port->last_cflags = cflag;
520 +/* Handle notification of a termios change. */
521 +static void duart_set_termios(struct tty_struct *tty, struct termios *old)
523 + uart_state_t *us = (uart_state_t *) tty->driver_data;
525 + pr_debug("duart_set_termios called by %i (%s)\n", current->pid,
527 + if (old && tty->termios->c_cflag == old->c_cflag)
529 + duart_set_cflag(us->line, tty->termios->c_cflag);
532 +static int get_serial_info(uart_state_t *us, struct serial_struct * retinfo)
534 + struct serial_struct tmp;
536 + memset(&tmp, 0, sizeof(tmp));
538 + tmp.type = PORT_SB1250;
539 + tmp.line = us->line;
540 + tmp.port = UNIT_CHANREG(tmp.line,0);
541 + tmp.irq = UNIT_INT(tmp.line);
542 + tmp.xmit_fifo_size = 16; /* fixed by hw */
543 + tmp.baud_base = 5000000;
544 + tmp.io_type = SERIAL_IO_MEM;
546 + if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
552 +static int duart_ioctl(struct tty_struct *tty, struct file * file,
553 + unsigned int cmd, unsigned long arg)
555 + uart_state_t *us = (uart_state_t *) tty->driver_data;
557 +/* if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
561 + printk("Ignoring TIOCMGET\n");
564 + printk("Ignoring TIOCMBIS\n");
567 + printk("Ignoring TIOCMBIC\n");
570 + printk("Ignoring TIOCMSET\n");
573 + return get_serial_info(us,(struct serial_struct *) arg);
575 + printk("Ignoring TIOCSSERIAL\n");
577 + case TIOCSERCONFIG:
578 + printk("Ignoring TIOCSERCONFIG\n");
580 + case TIOCSERGETLSR: /* Get line status register */
581 + printk("Ignoring TIOCSERGETLSR\n");
583 + case TIOCSERGSTRUCT:
584 + printk("Ignoring TIOCSERGSTRUCT\n");
587 + printk("Ignoring TIOCMIWAIT\n");
590 + printk("Ignoring TIOCGICOUNT\n");
593 + printk("Ignoring TIOCSERGWILD\n");
596 + printk("Ignoring TIOCSERSWILD\n");
601 +// printk("Ignoring IOCTL %x from pid %i (%s)\n", cmd, current->pid, current->comm);
602 + return -ENOIOCTLCMD;
605 +/* XXXKW locking? */
606 +static void duart_start(struct tty_struct *tty)
608 + uart_state_t *us = (uart_state_t *) tty->driver_data;
610 + pr_debug("duart_start called\n");
612 + if (us->outp_count && !(us->flags & TX_INTEN)) {
613 + us->flags |= TX_INTEN;
614 + duart_unmask_ints(us->line, M_DUART_IMR_TX);
618 +/* XXXKW locking? */
619 +static void duart_stop(struct tty_struct *tty)
621 + uart_state_t *us = (uart_state_t *) tty->driver_data;
623 + pr_debug("duart_stop called\n");
625 + if (us->outp_count && (us->flags & TX_INTEN)) {
626 + us->flags &= ~TX_INTEN;
627 + duart_mask_ints(us->line, M_DUART_IMR_TX);
631 +/* Not sure on the semantics of this; are we supposed to wait until the stuff
632 + * already in the hardware FIFO drains, or are we supposed to wait until
633 + * we've drained the output buffer, too? I'm assuming the former, 'cause thats
634 + * what the other drivers seem to assume
637 +static void duart_wait_until_sent(struct tty_struct *tty, int timeout)
639 + uart_state_t *us = (uart_state_t *) tty->driver_data;
640 + unsigned long orig_jiffies;
642 + orig_jiffies = jiffies;
643 + pr_debug("duart_wait_until_sent(%d)+\n", timeout);
644 + while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT)) {
645 + set_current_state(TASK_INTERRUPTIBLE);
646 + schedule_timeout(1);
647 + if (signal_pending(current))
649 + if (timeout && time_after(jiffies, orig_jiffies + timeout))
652 + pr_debug("duart_wait_until_sent()-\n");
656 + * duart_hangup() --- called by tty_hangup() when a hangup is signaled.
658 +static void duart_hangup(struct tty_struct *tty)
660 + uart_state_t *us = (uart_state_t *) tty->driver_data;
662 + duart_flush_buffer(tty);
668 + * Open a tty line. Note that this can be called multiple times, so ->open can
669 + * be >1. Only set up the tty struct if this is a "new" open, e.g. ->open was
672 +static int duart_open(struct tty_struct *tty, struct file *filp)
675 + unsigned int line = tty->index;
676 + unsigned long flags;
678 + if ((line >= tty->driver->num) || !sb1250_duart_present[line])
681 + pr_debug("duart_open called by %i (%s), tty is %p, rw is %p, ww is %p\n",
682 + current->pid, current->comm, tty, (void *)&tty->read_wait,
683 + (void *)&tty->write_wait);
685 + us = uart_states + line;
686 + tty->driver_data = us;
688 + spin_lock_irqsave(&open_lock, flags);
691 + us->tty->termios->c_cflag = us->last_cflags;
694 + us->flags &= ~TX_INTEN;
695 + duart_unmask_ints(line, M_DUART_IMR_RX);
696 + spin_unlock_irqrestore(&open_lock, flags);
703 + * Close a reference count out. If reference count hits zero, null the
704 + * tty, kill the interrupts. The tty_io driver is responsible for making
705 + * sure we've cleared out our internal buffers before calling close()
707 +static void duart_close(struct tty_struct *tty, struct file *filp)
709 + uart_state_t *us = (uart_state_t *) tty->driver_data;
710 + unsigned long flags;
712 + pr_debug("duart_close called by %i (%s)\n", current->pid, current->comm);
714 + if (!us || !us->open)
717 + spin_lock_irqsave(&open_lock, flags);
718 + if (tty_hung_up_p(filp)) {
719 + spin_unlock_irqrestore(&open_lock, flags);
723 + if (--us->open < 0) {
725 + printk(KERN_ERR "duart: bad open count: %d\n", us->open);
728 + spin_unlock_irqrestore(&open_lock, flags);
732 + spin_unlock_irqrestore(&open_lock, flags);
736 + /* Stop accepting input */
737 + duart_mask_ints(us->line, M_DUART_IMR_RX);
738 + /* Wait for FIFO to drain */
739 + while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT))
742 + if (tty->driver->flush_buffer)
743 + tty->driver->flush_buffer(tty);
744 + if (tty->ldisc.flush_buffer)
745 + tty->ldisc.flush_buffer(tty);
750 +static struct tty_operations duart_ops = {
751 + .open = duart_open,
752 + .close = duart_close,
753 + .write = duart_write,
754 + .put_char = duart_put_char,
755 + .flush_chars = duart_flush_chars,
756 + .write_room = duart_write_room,
757 + .chars_in_buffer = duart_chars_in_buffer,
758 + .flush_buffer = duart_flush_buffer,
759 + .ioctl = duart_ioctl,
760 +// .throttle = duart_throttle,
761 +// .unthrottle = duart_unthrottle,
762 + .set_termios = duart_set_termios,
763 + .stop = duart_stop,
764 + .start = duart_start,
765 + .hangup = duart_hangup,
766 + .wait_until_sent = duart_wait_until_sent,
769 +/* Initialize the sb1250_duart_present array based on SOC type. */
770 +static void __init sb1250_duart_init_present_lines(void)
774 + /* Set the number of available units based on the SOC type. */
775 + switch (soc_type) {
776 + case K_SYS_SOC_TYPE_BCM1x55:
777 + case K_SYS_SOC_TYPE_BCM1x80:
781 + /* Assume at least two serial ports at the normal address. */
785 + if (max_lines > DUART_MAX_LINE)
786 + max_lines = DUART_MAX_LINE;
788 + for (i = 0; i < max_lines; i++)
789 + sb1250_duart_present[i] = 1;
792 +/* Set up the driver and register it, register the UART interrupts. This
793 + is called from tty_init, or as a part of the module init */
794 +static int __init sb1250_duart_init(void)
798 + sb1250_duart_init_present_lines();
800 + sb1250_duart_driver = alloc_tty_driver(DUART_MAX_LINE);
801 + if (!sb1250_duart_driver)
804 + sb1250_duart_driver->owner = THIS_MODULE;
805 + sb1250_duart_driver->name = "duart";
806 + sb1250_duart_driver->major = TTY_MAJOR;
807 + sb1250_duart_driver->minor_start = SB1250_DUART_MINOR_BASE;
808 + sb1250_duart_driver->type = TTY_DRIVER_TYPE_SERIAL;
809 + sb1250_duart_driver->subtype = SERIAL_TYPE_NORMAL;
810 + sb1250_duart_driver->init_termios = tty_std_termios;
811 + sb1250_duart_driver->flags = TTY_DRIVER_REAL_RAW;
812 + tty_set_operations(sb1250_duart_driver, &duart_ops);
814 + for (i = 0; i < DUART_MAX_LINE; i++) {
815 + uart_state_t *port = uart_states + i;
817 + if (!sb1250_duart_present[i])
820 + init_duart_port(port, i);
821 + duart_mask_ints(i, M_DUART_IMR_ALL);
822 + if (request_irq(UNIT_INT(i), duart_int, 0, "uart", port)) {
823 + panic("Couldn't get uart0 interrupt line");
826 + * this generic write to a register does not implement the 1956
827 + * WAR and sometimes output gets corrupted afterwards,
828 + * especially if the port was in use as a console.
830 + __raw_writel(M_DUART_RX_EN|M_DUART_TX_EN, port->cmd);
833 + * we should really check to see if it's registered as a console
834 + * before trashing those settings
836 + duart_set_cflag(i, port->last_cflags);
839 + /* Interrupts are now active, our ISR can be called. */
841 + if (tty_register_driver(sb1250_duart_driver)) {
842 + printk(KERN_ERR "Couldn't register sb1250 duart serial driver\n");
843 + put_tty_driver(sb1250_duart_driver);
849 +/* Unload the driver. Unregister stuff, get ready to go away */
850 +static void __exit sb1250_duart_fini(void)
852 + unsigned long flags;
855 + local_irq_save(flags);
856 + tty_unregister_driver(sb1250_duart_driver);
857 + put_tty_driver(sb1250_duart_driver);
859 + for (i = 0; i < DUART_MAX_LINE; i++) {
860 + if (!sb1250_duart_present[i])
862 + free_irq(UNIT_INT(i), &uart_states[i]);
863 + disable_irq(UNIT_INT(i));
865 + local_irq_restore(flags);
868 +module_init(sb1250_duart_init);
869 +module_exit(sb1250_duart_fini);
870 +MODULE_DESCRIPTION("SB1250 Duart serial driver");
871 +MODULE_AUTHOR("Broadcom Corp.");
873 +#ifdef CONFIG_SIBYTE_SB1250_DUART_CONSOLE
876 + * Serial console stuff. Very basic, polling driver for doing serial
877 + * console output. The console_sem is held by the caller, so we
878 + * shouldn't be interrupted for more console activity.
879 + * XXXKW What about getting interrupted by uart driver activity?
882 +void serial_outc(unsigned char c, int line)
884 + uart_state_t *port = uart_states + line;
885 + while (!(READ_SERCSR(port->status, line) & M_DUART_TX_RDY)) ;
886 + WRITE_SERCSR(c, port->tx_hold, line);
887 + while (!(READ_SERCSR(port->status, port->line) & M_DUART_TX_EMT)) ;
890 +static void ser_console_write(struct console *cons, const char *s,
891 + unsigned int count)
893 + int line = cons->index;
894 + uart_state_t *port = uart_states + line;
897 + imr = READ_SERCSR(port->imr, line);
898 + WRITE_SERCSR(0, port->imr, line);
901 + serial_outc('\r', line);
902 + serial_outc(*s++, line);
904 + WRITE_SERCSR(imr, port->imr, line);
907 +static struct tty_driver *ser_console_device(struct console *c, int *index)
910 + return sb1250_duart_driver;
913 +static int ser_console_setup(struct console *cons, char *str)
917 + sb1250_duart_init_present_lines();
919 + for (i = 0; i < DUART_MAX_LINE; i++) {
920 + uart_state_t *port = uart_states + i;
921 + u32 cflags = DEFAULT_CFLAGS;
923 + if (!sb1250_duart_present[i])
926 + init_duart_port(port, i);
935 + * format is in Documentation/serial_console.txt
937 + sscanf(str, "%d%c%d", &speed, &par, &cbits);
978 + default: // we only do 7 or 8
987 + duart_set_cflag(i, cflags);
988 + WRITE_SERCSR(M_DUART_RX_EN | M_DUART_TX_EN, port->cmd, i);
994 +static struct console sb1250_ser_cons = {
996 + .write = ser_console_write,
997 + .device = ser_console_device,
998 + .setup = ser_console_setup,
999 + .flags = CON_PRINTBUFFER,
1003 +static int __init sb1250_serial_console_init(void)
1005 + //add_preferred_console("duart", 0, "57600n8");
1006 + register_console(&sb1250_ser_cons);
1010 +console_initcall(sb1250_serial_console_init);
1012 +#endif /* CONFIG_SIBYTE_SB1250_DUART_CONSOLE */
1013 diff -Nur linux-2.6.21.1/include/linux/serial.h linux-2.6.21.1-owrt/include/linux/serial.h
1014 --- linux-2.6.21.1/include/linux/serial.h 2007-04-27 23:49:26.000000000 +0200
1015 +++ linux-2.6.21.1-owrt/include/linux/serial.h 2007-05-24 22:10:29.000000000 +0200
1017 #define PORT_16654 11
1018 #define PORT_16850 12
1019 #define PORT_RSA 13 /* RSA-DV II/S card */
1020 -#define PORT_MAX 13
1021 +#define PORT_SB1250 14
1022 +#define PORT_MAX 14
1024 #define SERIAL_IO_PORT 0
1025 #define SERIAL_IO_HUB6 1