3 Copyright 2002 Broadcom Corp. All Rights Reserved.
5 This program is free software; you can distribute it and/or modify it
6 under the terms of the GNU General Public License (Version 2) as
7 published by the Free Software Foundation.
9 This program is distributed in the hope it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
20 /* Description: Serial port driver for the BCM963XX. */
22 #define CARDNAME "bcm963xx_serial driver"
24 #define VER_STR CARDNAME " v" VERSION "\n"
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/version.h>
30 #include <linux/init.h>
31 #include <linux/slab.h>
32 #include <linux/interrupt.h>
33 #include <linux/spinlock.h>
35 /* for definition of struct console */
36 #include <linux/console.h>
37 #include <linux/tty.h>
38 #include <linux/tty_flip.h>
39 #include <linux/serial.h>
40 #include <linux/serialP.h>
41 #include <asm/uaccess.h>
45 #include <bcm_map_part.h>
47 #include <6348_map_part.h>
48 #include <6348_intr.h>
50 static DEFINE_SPINLOCK(bcm963xx_serial_lock);
52 extern void _putc(char);
53 extern void _puts(const char *);
55 typedef struct bcm_serial {
62 unsigned short close_delay;
63 unsigned short closing_wait;
64 unsigned short line; /* port/line number */
65 unsigned short cflags; /* line configuration flag */
66 unsigned short x_char; /* xon/xoff character */
67 unsigned short read_status_mask; /* mask for read condition */
68 unsigned short ignore_status_mask; /* mask for ignore condition */
69 unsigned long event; /* mask used in BH */
70 int xmit_head; /* Position of the head */
71 int xmit_tail; /* Position of the tail */
72 int xmit_cnt; /* Count of the chars in the buffer */
73 int count; /* indicates how many times it has been opened */
76 struct async_icount icount; /* keep track of things ... */
77 struct tty_struct *tty; /* tty associated */
78 struct ktermios normal_termios;
80 wait_queue_head_t open_wait;
81 wait_queue_head_t close_wait;
83 long session; /* Session of opening process */
84 long pgrp; /* pgrp of opening process */
86 unsigned char is_initialized;
90 /*---------------------------------------------------------------------*/
91 /* Define bits in the Interrupt Enable register */
92 /*---------------------------------------------------------------------*/
93 /* Enable receive interrupt */
94 #define RXINT (RXFIFONE|RXOVFERR)
96 /* Enable transmit interrupt */
97 #define TXINT (TXFIFOEMT|TXUNDERR|TXOVFERR)
99 /* Enable receiver line status interrupt */
100 #define LSINT (RXBRK|RXPARERR|RXFRAMERR)
102 #define BCM_NUM_UARTS 1
104 #define BD_BCM63XX_TIMER_CLOCK_INPUT (FPERIPH)
107 static struct bcm_serial multi[BCM_NUM_UARTS];
108 static struct bcm_serial *lines[BCM_NUM_UARTS];
109 static struct tty_driver *serial_driver;
110 static struct ktermios *serial_termios[BCM_NUM_UARTS];
111 static struct ktermios *serial_termios_locked[BCM_NUM_UARTS];
114 static void bcm_stop(struct tty_struct *tty);
115 static void bcm_start(struct tty_struct *tty);
116 static inline void receive_chars(struct bcm_serial *info);
117 static int startup(struct bcm_serial *info);
118 static void shutdown(struct bcm_serial *info);
119 static void change_speed(volatile Uart * pUart, tcflag_t cFlag);
120 static void bcm63xx_cons_flush_chars(struct tty_struct *tty);
121 static int bcm63xx_cons_write(struct tty_struct *tty,
122 const unsigned char *buf, int count);
123 static int bcm63xx_cons_write_room(struct tty_struct *tty);
124 static int bcm_chars_in_buffer(struct tty_struct *tty);
125 static void bcm_flush_buffer(struct tty_struct *tty);
126 static void bcm_throttle(struct tty_struct *tty);
127 static void bcm_unthrottle(struct tty_struct *tty);
128 static void bcm_send_xchar(struct tty_struct *tty, char ch);
129 static int get_serial_info(struct bcm_serial *info,
130 struct serial_struct *retinfo);
131 static int set_serial_info(struct bcm_serial *info,
132 struct serial_struct *new_info);
133 static int get_lsr_info(struct bcm_serial *info, unsigned int *value);
134 static void send_break(struct bcm_serial *info, int duration);
135 static int bcm_ioctl(struct tty_struct *tty, struct file *file,
136 unsigned int cmd, unsigned long arg);
137 static void bcm_set_termios(struct tty_struct *tty,
138 struct ktermios *old_termios);
139 static void bcm63xx_cons_close(struct tty_struct *tty, struct file *filp);
140 static void bcm_hangup(struct tty_struct *tty);
141 static int block_til_ready(struct tty_struct *tty, struct file *filp,
142 struct bcm_serial *info);
143 static int bcm63xx_cons_open(struct tty_struct *tty, struct file *filp);
144 static int __init bcm63xx_serialinit(void);
148 * ------------------------------------------------------------
149 * rs_stop () and rs_start ()
151 * These routines are called before setting or resetting
152 * tty->stopped. They enable or disable transmitter interrupts,
154 * ------------------------------------------------------------
156 static void bcm_stop(struct tty_struct *tty)
160 static void bcm_start(struct tty_struct *tty)
162 _puts(CARDNAME " Start\n");
166 * ------------------------------------------------------------
169 * This routine deals with inputs from any lines.
170 * ------------------------------------------------------------
172 static inline void receive_chars(struct bcm_serial *info)
174 struct tty_struct *tty = 0;
175 struct async_icount *icount;
177 unsigned short status, tmp;
179 while ((status = info->port->intStatus) & RXINT) {
180 char flag_char = TTY_NORMAL;
182 if (status & RXFIFONE)
183 ch = info->port->Data; // Read the character
184 tty = info->tty; /* now tty points to the proper dev */
185 icount = &info->icount;
188 if (!tty_buffer_request_room(tty, 1))
191 if (status & RXBRK) {
192 flag_char = TTY_BREAK;
195 // keep track of the statistics
196 if (status & (RXFRAMERR | RXPARERR | RXOVFERR)) {
197 if (status & RXPARERR) /* parity error */
199 else if (status & RXFRAMERR) /* frame error */
201 if (status & RXOVFERR) {
202 // Overflow. Reset the RX FIFO
203 info->port->fifoctl |= RSTRXFIFOS;
206 // check to see if we should ignore the character
207 // and mask off conditions that should be ignored
208 if (status & info->ignore_status_mask) {
213 // Mask off the error conditions we want to ignore
214 tmp = status & info->read_status_mask;
215 if (tmp & RXPARERR) {
216 flag_char = TTY_PARITY;
217 } else if (tmp & RXFRAMERR) {
218 flag_char = TTY_FRAME;
220 if (tmp & RXOVFERR) {
221 tty_insert_flip_char(tty, ch, flag_char);
223 flag_char = TTY_OVERRUN;
224 if (!tty_buffer_request_room(tty, 1))
228 tty_insert_flip_char(tty, ch, flag_char);
231 tty_flip_buffer_push(tty);
232 tty_schedule_flip(tty);
238 * ------------------------------------------------------------
241 * this is the main interrupt routine for the chip.
242 * It deals with the multiple ports.
243 * ------------------------------------------------------------
245 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
246 static irqreturn_t bcm_interrupt(int irq, void *dev)
248 static void bcm_interrupt(int irq, void *dev, struct pt_regs *regs)
251 struct bcm_serial *info = lines[0];
254 /* get pending interrupt flags from UART */
256 /* Mask with only the serial interrupts that are enabled */
257 intStat = info->port->intStatus & info->port->intMask;
261 else if (intStat & TXINT)
262 info->port->intStatus = TXINT;
263 else /* don't know what it was, so let's mask it */
264 info->port->intMask &= ~intStat;
266 intStat = info->port->intStatus & info->port->intMask;
269 // Clear the interrupt
270 enable_brcm_irq(INTERRUPT_ID_UART);
271 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
277 * -------------------------------------------------------------------
280 * various initialization tasks
281 * -------------------------------------------------------------------
283 static int startup(struct bcm_serial *info)
285 // Port is already started...
290 * -------------------------------------------------------------------
293 * This routine will shutdown a serial port; interrupts are disabled, and
294 * DTR is dropped if the hangup on close termio flag is on.
295 * -------------------------------------------------------------------
297 static void shutdown(struct bcm_serial *info)
300 if (!info->is_initialized)
303 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
305 info->port->control &= ~(BRGEN | TXEN | RXEN);
307 set_bit(TTY_IO_ERROR, &info->tty->flags);
308 info->is_initialized = 0;
310 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
314 * -------------------------------------------------------------------
317 * Set the baud rate, character size, parity and stop bits.
318 * -------------------------------------------------------------------
320 static void change_speed(volatile Uart * pUart, tcflag_t cFlag)
322 unsigned long ulFlags, ulBaud, ulClockFreqHz, ulTmp;
324 spin_lock_irqsave(&bcm963xx_serial_lock, ulFlags);
325 switch (cFlag & (CBAUD | CBAUDEX)) {
382 /* Calculate buad rate. */
383 ulClockFreqHz = BD_BCM63XX_TIMER_CLOCK_INPUT;
384 ulTmp = (ulClockFreqHz / ulBaud) / 16;
386 ulTmp /= 2; /* Rounding up, so sub is already accounted for */
388 ulTmp = (ulTmp / 2) - 1; /* Rounding down so we must sub 1 */
389 pUart->baudword = ulTmp;
391 /* Set character size, stop bits and parity. */
392 switch (cFlag & CSIZE) {
394 ulTmp = BITS5SYM; /* select transmit 5 bit data size */
397 ulTmp = BITS6SYM; /* select transmit 6 bit data size */
400 ulTmp = BITS7SYM; /* select transmit 7 bit data size */
403 ulTmp = BITS8SYM; /* select transmit 8 bit data size */
407 ulTmp |= TWOSTOP; /* select 2 stop bits */
409 ulTmp |= ONESTOP; /* select one stop bit */
411 /* Write these values into the config reg. */
412 pUart->config = ulTmp;
414 ~(RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN);
415 switch (cFlag & (PARENB | PARODD)) {
416 case PARENB | PARODD:
417 pUart->control |= RXPARITYEN | TXPARITYEN;
421 RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN;
428 /* Reset and flush uart */
429 pUart->fifoctl = RSTTXFIFOS | RSTRXFIFOS;
430 spin_unlock_irqrestore(&bcm963xx_serial_lock, ulFlags);
435 * -------------------------------------------------------------------
438 * Nothing to flush. Polled I/O is used.
439 * -------------------------------------------------------------------
441 static void bcm63xx_cons_flush_chars(struct tty_struct *tty)
447 * -------------------------------------------------------------------
448 * bcm63xx_cons_write ()
450 * Main output routine using polled I/O.
451 * -------------------------------------------------------------------
453 static int bcm63xx_cons_write(struct tty_struct *tty,
454 const unsigned char *buf, int count)
458 for (c = 0; c < count; c++)
464 * -------------------------------------------------------------------
465 * bcm63xx_cons_write_room ()
467 * Compute the amount of space available for writing.
468 * -------------------------------------------------------------------
470 static int bcm63xx_cons_write_room(struct tty_struct *tty)
472 /* Pick a number. Any number. Polled I/O is used. */
477 * -------------------------------------------------------------------
478 * bcm_chars_in_buffer ()
480 * compute the amount of char left to be transmitted
481 * -------------------------------------------------------------------
483 static int bcm_chars_in_buffer(struct tty_struct *tty)
489 * -------------------------------------------------------------------
490 * bcm_flush_buffer ()
492 * Empty the output buffer
493 * -------------------------------------------------------------------
495 static void bcm_flush_buffer(struct tty_struct *tty)
501 * ------------------------------------------------------------
502 * bcm_throttle () and bcm_unthrottle ()
504 * This routine is called by the upper-layer tty layer to signal that
505 * incoming characters should be throttled (or not).
506 * ------------------------------------------------------------
508 static void bcm_throttle(struct tty_struct *tty)
510 struct bcm_serial *info = (struct bcm_serial *) tty->driver_data;
512 info->x_char = STOP_CHAR(tty);
515 static void bcm_unthrottle(struct tty_struct *tty)
517 struct bcm_serial *info = (struct bcm_serial *) tty->driver_data;
522 info->x_char = START_CHAR(tty);
526 static void bcm_send_xchar(struct tty_struct *tty, char ch)
528 struct bcm_serial *info = (struct bcm_serial *) tty->driver_data;
531 bcm_start(info->tty);
535 * ------------------------------------------------------------
536 * rs_ioctl () and friends
537 * ------------------------------------------------------------
539 static int get_serial_info(struct bcm_serial *info,
540 struct serial_struct *retinfo)
542 struct serial_struct tmp;
547 memset(&tmp, 0, sizeof(tmp));
548 tmp.type = info->type;
549 tmp.line = info->line;
550 tmp.port = (int) info->port;
553 tmp.baud_base = info->baud_base;
554 tmp.close_delay = info->close_delay;
555 tmp.closing_wait = info->closing_wait;
557 return copy_to_user(retinfo, &tmp, sizeof(*retinfo));
560 static int set_serial_info(struct bcm_serial *info,
561 struct serial_struct *new_info)
563 struct serial_struct new_serial;
564 struct bcm_serial old_info;
570 copy_from_user(&new_serial, new_info, sizeof(new_serial));
573 if (!capable(CAP_SYS_ADMIN))
580 /* OK, past this point, all the error checking has been done.
581 * At this point, we start making changes.....
583 info->baud_base = new_serial.baud_base;
584 info->type = new_serial.type;
585 info->close_delay = new_serial.close_delay;
586 info->closing_wait = new_serial.closing_wait;
587 retval = startup(info);
592 * get_lsr_info - get line status register info
594 * Purpose: Let user call ioctl() to get info when the UART physically
595 * is emptied. On bus types like RS485, the transmitter must
596 * release the bus after transmitting. This must be done when
597 * the transmit shift register is empty, not be done when the
598 * transmit holding register is empty. This functionality
599 * allows an RS485 driver to be written in user space.
601 static int get_lsr_info(struct bcm_serial *info, unsigned int *value)
607 * This routine sends a break character out the serial port.
609 static void send_break(struct bcm_serial *info, int duration)
616 current->state = TASK_INTERRUPTIBLE;
618 /*save_flags (flags);
620 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
622 info->port->control |= XMITBREAK;
623 schedule_timeout(duration);
624 info->port->control &= ~XMITBREAK;
626 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
627 //restore_flags (flags);
630 static int bcm_ioctl(struct tty_struct *tty, struct file *file,
631 unsigned int cmd, unsigned long arg)
634 struct bcm_serial *info = (struct bcm_serial *) tty->driver_data;
637 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
638 (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
639 (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
640 if (tty->flags & (1 << TTY_IO_ERROR))
645 case TCSBRK: /* SVID version: non-zero arg --> no break */
646 retval = tty_check_change(tty);
649 tty_wait_until_sent(tty, 0);
651 send_break(info, HZ / 4); /* 1/4 second */
654 case TCSBRKP: /* support for POSIX tcsendbreak() */
655 retval = tty_check_change(tty);
658 tty_wait_until_sent(tty, 0);
659 send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
664 access_ok(VERIFY_WRITE, (void *) arg, sizeof(long));
668 put_user(C_CLOCAL(tty) ? 1 : 0,
669 (unsigned long *) arg);
674 error = get_user(arg, (unsigned long *) arg);
677 tty->termios->c_cflag =
679 c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
684 access_ok(VERIFY_WRITE, (void *) arg,
685 sizeof(struct serial_struct));
689 return get_serial_info(info,
690 (struct serial_struct *)
694 return set_serial_info(info, (struct serial_struct *) arg);
696 case TIOCSERGETLSR: /* Get line status register */
698 access_ok(VERIFY_WRITE, (void *) arg,
699 sizeof(unsigned int));
703 return get_lsr_info(info, (unsigned int *) arg);
707 access_ok(VERIFY_WRITE, (void *) arg,
708 sizeof(struct bcm_serial));
712 copy_to_user((struct bcm_serial *) arg, info,
713 sizeof(struct bcm_serial));
723 static void bcm_set_termios(struct tty_struct *tty,
724 struct ktermios *old_termios)
726 struct bcm_serial *info = (struct bcm_serial *) tty->driver_data;
728 if (tty->termios->c_cflag != old_termios->c_cflag)
729 change_speed(info->port, tty->termios->c_cflag);
733 * ------------------------------------------------------------
734 * bcm63xx_cons_close()
736 * This routine is called when the serial port gets closed. First, we
737 * wait for the last remaining data to be sent. Then, we turn off
738 * the transmit enable and receive enable flags.
739 * ------------------------------------------------------------
741 static void bcm63xx_cons_close(struct tty_struct *tty, struct file *filp)
743 struct bcm_serial *info = (struct bcm_serial *) tty->driver_data;
749 /*save_flags (flags);
751 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
753 if (tty_hung_up_p(filp)) {
754 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
755 //restore_flags (flags);
759 if ((tty->count == 1) && (info->count != 1)) {
761 /* Uh, oh. tty->count is 1, which means that the tty
762 * structure will be freed. Info->count should always
763 * be one in these conditions. If it's greater than
764 * one, we've got real problems, since it means the
765 * serial port won't be shutdown.
768 ("bcm63xx_cons_close: bad serial port count; tty->count is 1, "
769 "info->count is %d\n", info->count);
773 if (--info->count < 0) {
774 printk("ds_close: bad serial port count for ttys%d: %d\n",
775 info->line, info->count);
780 //restore_flags (flags);
781 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
785 /* Now we wait for the transmit buffer to clear; and we notify
786 * the line discipline to only process XON/XOFF characters.
790 /* At this point we stop accepting input. To do this, we
791 * disable the receive line status interrupts.
794 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
795 if (tty->driver->flush_buffer)
796 tty->driver->flush_buffer(tty);
798 if (tty->driver.flush_buffer)
799 tty->driver.flush_buffer(tty);
801 if (tty->ldisc.flush_buffer)
802 tty->ldisc.flush_buffer(tty);
807 if (tty->ldisc.num != tty_ldisc_get(N_TTY)->num) {
808 if (tty->ldisc.close)
809 (tty->ldisc.close) (tty);
810 tty->ldisc = *tty_ldisc_get(N_TTY);
811 tty->termios->c_line = N_TTY;
813 (tty->ldisc.open) (tty);
815 if (info->blocked_open) {
816 if (info->close_delay) {
817 current->state = TASK_INTERRUPTIBLE;
818 schedule_timeout(info->close_delay);
820 wake_up_interruptible(&info->open_wait);
822 wake_up_interruptible(&info->close_wait);
824 //restore_flags (flags);
825 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
829 * bcm_hangup () --- called by tty_hangup() when a hangup is signaled.
831 static void bcm_hangup(struct tty_struct *tty)
834 struct bcm_serial *info = (struct bcm_serial *) tty->driver_data;
840 wake_up_interruptible(&info->open_wait);
844 * ------------------------------------------------------------
845 * rs_open() and friends
846 * ------------------------------------------------------------
848 static int block_til_ready(struct tty_struct *tty, struct file *filp,
849 struct bcm_serial *info)
855 * This routine is called whenever a serial port is opened. It
856 * enables interrupts for a serial port. It also performs the
857 * serial-specific initialization for the tty structure.
859 static int bcm63xx_cons_open(struct tty_struct *tty, struct file *filp)
861 struct bcm_serial *info;
864 // Make sure we're only opening on of the ports we support
865 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
866 line = MINOR(tty->driver->cdev.dev) - tty->driver->minor_start;
868 line = MINOR(tty->device) - tty->driver.minor_start;
871 if ((line < 0) || (line >= BCM_NUM_UARTS))
876 tty->low_latency = 1;
877 info->port->intMask = 0; /* Clear any pending interrupts */
878 info->port->intMask = RXINT; /* Enable RX */
881 tty->driver_data = info;
883 enable_brcm_irq(INTERRUPT_ID_UART);
885 // Start up serial port
886 retval = startup(info);
890 retval = block_til_ready(tty, filp, info);
895 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
896 info->pgrp = task_pgrp(current);
898 info->session = current->session;
899 info->pgrp = current->pgrp;
906 static struct tty_operations rs_ops = {
907 .open = bcm63xx_cons_open,
908 .close = bcm63xx_cons_close,
909 .write = bcm63xx_cons_write,
910 .flush_chars = bcm63xx_cons_flush_chars,
911 .write_room = bcm63xx_cons_write_room,
912 .chars_in_buffer = bcm_chars_in_buffer,
913 .flush_buffer = bcm_flush_buffer,
915 .throttle = bcm_throttle,
916 .unthrottle = bcm_unthrottle,
917 .send_xchar = bcm_send_xchar,
918 .set_termios = bcm_set_termios,
921 .hangup = bcm_hangup,
924 /* --------------------------------------------------------------------------
925 Name: bcm63xx_serialinit
926 Purpose: Initialize our BCM63xx serial driver
927 -------------------------------------------------------------------------- */
928 static int __init bcm63xx_serialinit(void)
931 struct bcm_serial *info;
933 // Print the driver version information
935 serial_driver = alloc_tty_driver(BCM_NUM_UARTS);
939 serial_driver->owner = THIS_MODULE;
940 serial_driver->name = "ttyS";
941 serial_driver->major = TTY_MAJOR;
942 serial_driver->minor_start = 64;
943 serial_driver->num = 1;
944 serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
945 serial_driver->subtype = SERIAL_TYPE_NORMAL;
946 serial_driver->init_termios = tty_std_termios;
947 serial_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
948 serial_driver->flags = TTY_DRIVER_REAL_RAW;
950 serial_driver->termios = serial_termios;
951 serial_driver->termios_locked = serial_termios_locked;
953 tty_set_operations(serial_driver, &rs_ops);
955 if (tty_register_driver(serial_driver))
956 panic("Couldn't register serial driver\n");
958 //save_flags(flags); cli();
959 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
961 for (i = 0; i < 1; i++) {
964 info->magic = SERIAL_MAGIC;
965 info->port = (Uart *) ((char *) UART_BASE + (i * 0x20));
967 info->irq = (2 - i) + 8;
969 info->close_delay = 50;
970 info->closing_wait = 3000;
974 info->blocked_open = 0;
975 info->normal_termios = serial_driver->init_termios;
976 init_waitqueue_head(&info->open_wait);
977 init_waitqueue_head(&info->close_wait);
979 /* If we are pointing to address zero then punt - not correctly
980 * set up in setup.c to handle this.
984 BcmHalMapInterrupt(bcm_interrupt, 0, INTERRUPT_ID_UART);
987 /* order matters here... the trick is that flags
988 * is updated... in request_irq - to immediatedly obliterate
991 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
995 module_init(bcm63xx_serialinit);
997 /* --------------------------------------------------------------------------
998 Name: bcm_console_print
999 Purpose: bcm_console_print is registered for printk.
1000 The console_lock must be held when we get here.
1001 -------------------------------------------------------------------------- */
1002 static void bcm_console_print(struct console *cons, const char *str,
1007 for (i = 0; i < count; i++, str++) {
1015 static struct tty_driver *bcm_console_device(struct console *c, int *index)
1018 return serial_driver;
1021 static int __init bcm_console_setup(struct console *co, char *options)
1026 static struct console bcm_sercons = {
1028 .write = bcm_console_print,
1029 .device = bcm_console_device,
1030 .setup = bcm_console_setup,
1031 .flags = CON_PRINTBUFFER,
1035 static int __init bcm63xx_console_init(void)
1037 register_console(&bcm_sercons);
1041 console_initcall(bcm63xx_console_init);