Split up brcm63xx into files/
[openwrt/staging/dedeckeh.git] / target / linux / brcm63xx-2.6 / files / drivers / serial / bcm63xx_cons.c
1 /*
2 <:copyright-gpl
3 Copyright 2002 Broadcom Corp. All Rights Reserved.
4
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.
8
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
12 for more details.
13
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.
17 :>
18 */
19
20 /* Description: Serial port driver for the BCM963XX. */
21
22 #define CARDNAME "bcm963xx_serial driver"
23 #define VERSION "2.0"
24 #define VER_STR CARDNAME " v" VERSION "\n"
25
26
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>
34
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>
42
43 #include <bcmtypes.h>
44 #include <board.h>
45 #include <bcm_map_part.h>
46 #include <bcm_intr.h>
47
48 static DEFINE_SPINLOCK(bcm963xx_serial_lock);
49
50 extern void _putc(char);
51 extern void _puts(const char *);
52
53 typedef struct bcm_serial {
54 volatile Uart * port;
55 int type;
56 int flags;
57 int irq;
58 int baud_base;
59 int blocked_open;
60 unsigned short close_delay;
61 unsigned short closing_wait;
62 unsigned short line; /* port/line number */
63 unsigned short cflags; /* line configuration flag */
64 unsigned short x_char; /* xon/xoff character */
65 unsigned short read_status_mask; /* mask for read condition */
66 unsigned short ignore_status_mask; /* mask for ignore condition */
67 unsigned long event; /* mask used in BH */
68 int xmit_head; /* Position of the head */
69 int xmit_tail; /* Position of the tail */
70 int xmit_cnt; /* Count of the chars in the buffer */
71 int count; /* indicates how many times it has been opened */
72 int magic;
73
74 struct async_icount icount; /* keep track of things ... */
75 struct tty_struct *tty; /* tty associated */
76 struct termios normal_termios;
77
78 wait_queue_head_t open_wait;
79 wait_queue_head_t close_wait;
80
81 long session; /* Session of opening process */
82 long pgrp; /* pgrp of opening process */
83
84 unsigned char is_initialized;
85 } Context;
86
87
88 /*---------------------------------------------------------------------*/
89 /* Define bits in the Interrupt Enable register */
90 /*---------------------------------------------------------------------*/
91 /* Enable receive interrupt */
92 #define RXINT (RXFIFONE|RXOVFERR)
93
94 /* Enable transmit interrupt */
95 #define TXINT (TXFIFOEMT|TXUNDERR|TXOVFERR)
96
97 /* Enable receiver line status interrupt */
98 #define LSINT (RXBRK|RXPARERR|RXFRAMERR)
99
100 #define BCM_NUM_UARTS 1
101
102 #define BD_BCM63XX_TIMER_CLOCK_INPUT (FPERIPH)
103
104
105 static struct bcm_serial multi[BCM_NUM_UARTS];
106 static struct bcm_serial *lines[BCM_NUM_UARTS];
107 static struct tty_driver *serial_driver;
108 static struct termios *serial_termios[BCM_NUM_UARTS];
109 static struct termios *serial_termios_locked[BCM_NUM_UARTS];
110
111
112 static void bcm_stop (struct tty_struct *tty);
113 static void bcm_start (struct tty_struct *tty);
114 static inline void receive_chars (struct bcm_serial * info);
115 static int startup (struct bcm_serial *info);
116 static void shutdown (struct bcm_serial * info);
117 static void change_speed( volatile Uart *pUart, tcflag_t cFlag );
118 static void bcm63xx_cons_flush_chars (struct tty_struct *tty);
119 static int bcm63xx_cons_write (struct tty_struct *tty,
120 const unsigned char *buf, int count);
121 static int bcm63xx_cons_write_room (struct tty_struct *tty);
122 static int bcm_chars_in_buffer (struct tty_struct *tty);
123 static void bcm_flush_buffer (struct tty_struct *tty);
124 static void bcm_throttle (struct tty_struct *tty);
125 static void bcm_unthrottle (struct tty_struct *tty);
126 static void bcm_send_xchar (struct tty_struct *tty, char ch);
127 static int get_serial_info(struct bcm_serial *info, struct serial_struct *retinfo);
128 static int set_serial_info (struct bcm_serial *info, struct serial_struct *new_info);
129 static int get_lsr_info (struct bcm_serial *info, unsigned int *value);
130 static void send_break (struct bcm_serial *info, int duration);
131 static int bcm_ioctl (struct tty_struct * tty, struct file * file,
132 unsigned int cmd, unsigned long arg);
133 static void bcm_set_termios (struct tty_struct *tty, struct termios *old_termios);
134 static void bcm63xx_cons_close (struct tty_struct *tty, struct file *filp);
135 static void bcm_hangup (struct tty_struct *tty);
136 static int block_til_ready (struct tty_struct *tty, struct file *filp, struct bcm_serial *info);
137 static int bcm63xx_cons_open (struct tty_struct * tty, struct file * filp);
138 static int __init bcm63xx_serialinit(void);
139
140
141 /*
142 * ------------------------------------------------------------
143 * rs_stop () and rs_start ()
144 *
145 * These routines are called before setting or resetting
146 * tty->stopped. They enable or disable transmitter interrupts,
147 * as necessary.
148 * ------------------------------------------------------------
149 */
150 static void bcm_stop (struct tty_struct *tty)
151 {
152 }
153
154 static void bcm_start (struct tty_struct *tty)
155 {
156 _puts(CARDNAME " Start\n");
157 }
158
159 /*
160 * ------------------------------------------------------------
161 * receive_char ()
162 *
163 * This routine deals with inputs from any lines.
164 * ------------------------------------------------------------
165 */
166 static inline void receive_chars (struct bcm_serial * info)
167 {
168 struct tty_struct *tty = 0;
169 struct async_icount * icount;
170 int ignore = 0;
171 unsigned short status, tmp;
172 UCHAR ch = 0;
173 while ((status = info->port->intStatus) & RXINT)
174 {
175 char flag_char = TTY_NORMAL;
176
177 if (status & RXFIFONE)
178 ch = info->port->Data; // Read the character
179 tty = info->tty; /* now tty points to the proper dev */
180 icount = &info->icount;
181 if (! tty)
182 break;
183 if (!tty_buffer_request_room(tty, 1))
184 break;
185 icount->rx++;
186 if (status & RXBRK)
187 {
188 flag_char = TTY_BREAK;
189 icount->brk++;
190 }
191 // keep track of the statistics
192 if (status & (RXFRAMERR | RXPARERR | RXOVFERR))
193 {
194 if (status & RXPARERR) /* parity error */
195 icount->parity++;
196 else
197 if (status & RXFRAMERR) /* frame error */
198 icount->frame++;
199 if (status & RXOVFERR)
200 {
201 // Overflow. Reset the RX FIFO
202 info->port->fifoctl |= RSTRXFIFOS;
203 icount->overrun++;
204 }
205 // check to see if we should ignore the character
206 // and mask off conditions that should be ignored
207 if (status & info->ignore_status_mask)
208 {
209 if (++ignore > 100 )
210 break;
211 goto ignore_char;
212 }
213 // Mask off the error conditions we want to ignore
214 tmp = status & info->read_status_mask;
215 if (tmp & RXPARERR)
216 {
217 flag_char = TTY_PARITY;
218 }
219 else
220 if (tmp & RXFRAMERR)
221 {
222 flag_char = TTY_FRAME;
223 }
224 if (tmp & RXOVFERR)
225 {
226 tty_insert_flip_char(tty, ch, flag_char);
227 ch = 0;
228 flag_char = TTY_OVERRUN;
229 if (!tty_buffer_request_room(tty, 1))
230 break;
231 }
232 }
233 tty_insert_flip_char(tty, ch, flag_char);
234 }
235 ignore_char:;
236 tty_flip_buffer_push(tty);
237 tty_schedule_flip(tty);
238
239 }
240
241
242 /*
243 * ------------------------------------------------------------
244 * bcm_interrupt ()
245 *
246 * this is the main interrupt routine for the chip.
247 * It deals with the multiple ports.
248 * ------------------------------------------------------------
249 */
250 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
251 static irqreturn_t bcm_interrupt (int irq, void * dev)
252 #else
253 static void bcm_interrupt (int irq, void * dev, struct pt_regs * regs)
254 #endif
255 {
256 struct bcm_serial * info = lines[0];
257 UINT16 intStat;
258
259 /* get pending interrupt flags from UART */
260
261 /* Mask with only the serial interrupts that are enabled */
262 intStat = info->port->intStatus & info->port->intMask;
263 while (intStat)
264 {
265 if (intStat & RXINT)
266 receive_chars (info);
267 else
268 if (intStat & TXINT)
269 info->port->intStatus = TXINT;
270 else /* don't know what it was, so let's mask it */
271 info->port->intMask &= ~intStat;
272
273 intStat = info->port->intStatus & info->port->intMask;
274 }
275
276 // Clear the interrupt
277 BcmHalInterruptEnable (INTERRUPT_ID_UART);
278 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
279 return IRQ_HANDLED;
280 #endif
281 }
282
283 /*
284 * -------------------------------------------------------------------
285 * startup ()
286 *
287 * various initialization tasks
288 * -------------------------------------------------------------------
289 */
290 static int startup (struct bcm_serial *info)
291 {
292 // Port is already started...
293 return 0;
294 }
295
296 /*
297 * -------------------------------------------------------------------
298 * shutdown ()
299 *
300 * This routine will shutdown a serial port; interrupts are disabled, and
301 * DTR is dropped if the hangup on close termio flag is on.
302 * -------------------------------------------------------------------
303 */
304 static void shutdown (struct bcm_serial * info)
305 {
306 unsigned long flags;
307 if (!info->is_initialized)
308 return;
309
310 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
311
312 info->port->control &= ~(BRGEN|TXEN|RXEN);
313 if (info->tty)
314 set_bit (TTY_IO_ERROR, &info->tty->flags);
315 info->is_initialized = 0;
316
317 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
318 }
319 /*
320 * -------------------------------------------------------------------
321 * change_speed ()
322 *
323 * Set the baud rate, character size, parity and stop bits.
324 * -------------------------------------------------------------------
325 */
326 static void change_speed( volatile Uart *pUart, tcflag_t cFlag )
327 {
328 unsigned long ulFlags, ulBaud, ulClockFreqHz, ulTmp;
329
330 spin_lock_irqsave(&bcm963xx_serial_lock, ulFlags);
331 switch( cFlag & (CBAUD | CBAUDEX) )
332 {
333 case B115200:
334 ulBaud = 115200;
335 break;
336 case B57600:
337 ulBaud = 57600;
338 break;
339 case B38400:
340 ulBaud = 38400;
341 break;
342 case B19200:
343 ulBaud = 19200;
344 break;
345 case B9600:
346 ulBaud = 9600;
347 break;
348 case B4800:
349 ulBaud = 4800;
350 break;
351 case B2400:
352 ulBaud = 2400;
353 break;
354 case B1800:
355 ulBaud = 1800;
356 break;
357 case B1200:
358 ulBaud = 1200;
359 break;
360 case B600:
361 ulBaud = 600;
362 break;
363 case B300:
364 ulBaud = 300;
365 break;
366 case B200:
367 ulBaud = 200;
368 break;
369 case B150:
370 ulBaud = 150;
371 break;
372 case B134:
373 ulBaud = 134;
374 break;
375 case B110:
376 ulBaud = 110;
377 break;
378 case B75:
379 ulBaud = 75;
380 break;
381 case B50:
382 ulBaud = 50;
383 break;
384 default:
385 ulBaud = 115200;
386 break;
387 }
388
389 /* Calculate buad rate. */
390 ulClockFreqHz = BD_BCM63XX_TIMER_CLOCK_INPUT;
391 ulTmp = (ulClockFreqHz / ulBaud) / 16;
392 if( ulTmp & 0x01 )
393 ulTmp /= 2; /* Rounding up, so sub is already accounted for */
394 else
395 ulTmp = (ulTmp / 2) - 1; /* Rounding down so we must sub 1 */
396 pUart->baudword = ulTmp;
397
398 /* Set character size, stop bits and parity. */
399 switch( cFlag & CSIZE )
400 {
401 case CS5:
402 ulTmp = BITS5SYM; /* select transmit 5 bit data size */
403 break;
404 case CS6:
405 ulTmp = BITS6SYM; /* select transmit 6 bit data size */
406 break;
407 case CS7:
408 ulTmp = BITS7SYM; /* select transmit 7 bit data size */
409 break;
410 default:
411 ulTmp = BITS8SYM; /* select transmit 8 bit data size */
412 break;
413 }
414 if( cFlag & CSTOPB )
415 ulTmp |= TWOSTOP; /* select 2 stop bits */
416 else
417 ulTmp |= ONESTOP; /* select one stop bit */
418
419 /* Write these values into the config reg. */
420 pUart->config = ulTmp;
421 pUart->control &= ~(RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN);
422 switch( cFlag & (PARENB | PARODD) )
423 {
424 case PARENB|PARODD:
425 pUart->control |= RXPARITYEN | TXPARITYEN;
426 break;
427 case PARENB:
428 pUart->control |= RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN;
429 break;
430 default:
431 pUart->control |= 0;
432 break;
433 }
434
435 /* Reset and flush uart */
436 pUart->fifoctl = RSTTXFIFOS | RSTRXFIFOS;
437 spin_unlock_irqrestore(&bcm963xx_serial_lock, ulFlags);
438 }
439
440
441 /*
442 * -------------------------------------------------------------------
443 * bcm_flush_char ()
444 *
445 * Nothing to flush. Polled I/O is used.
446 * -------------------------------------------------------------------
447 */
448 static void bcm63xx_cons_flush_chars (struct tty_struct *tty)
449 {
450 }
451
452
453 /*
454 * -------------------------------------------------------------------
455 * bcm63xx_cons_write ()
456 *
457 * Main output routine using polled I/O.
458 * -------------------------------------------------------------------
459 */
460 static int bcm63xx_cons_write (struct tty_struct *tty,
461 const unsigned char *buf, int count)
462 {
463 int c;
464
465 for (c = 0; c < count; c++)
466 _putc(buf[c]);
467 return count;
468 }
469
470 /*
471 * -------------------------------------------------------------------
472 * bcm63xx_cons_write_room ()
473 *
474 * Compute the amount of space available for writing.
475 * -------------------------------------------------------------------
476 */
477 static int bcm63xx_cons_write_room (struct tty_struct *tty)
478 {
479 /* Pick a number. Any number. Polled I/O is used. */
480 return 1024;
481 }
482
483 /*
484 * -------------------------------------------------------------------
485 * bcm_chars_in_buffer ()
486 *
487 * compute the amount of char left to be transmitted
488 * -------------------------------------------------------------------
489 */
490 static int bcm_chars_in_buffer (struct tty_struct *tty)
491 {
492 return 0;
493 }
494
495 /*
496 * -------------------------------------------------------------------
497 * bcm_flush_buffer ()
498 *
499 * Empty the output buffer
500 * -------------------------------------------------------------------
501 */
502 static void bcm_flush_buffer (struct tty_struct *tty)
503 {
504 tty_wakeup(tty);
505 }
506
507 /*
508 * ------------------------------------------------------------
509 * bcm_throttle () and bcm_unthrottle ()
510 *
511 * This routine is called by the upper-layer tty layer to signal that
512 * incoming characters should be throttled (or not).
513 * ------------------------------------------------------------
514 */
515 static void bcm_throttle (struct tty_struct *tty)
516 {
517 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
518 if (I_IXOFF(tty))
519 info->x_char = STOP_CHAR(tty);
520 }
521
522 static void bcm_unthrottle (struct tty_struct *tty)
523 {
524 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
525 if (I_IXOFF(tty))
526 {
527 if (info->x_char)
528 info->x_char = 0;
529 else
530 info->x_char = START_CHAR(tty);
531 }
532 }
533
534 static void bcm_send_xchar (struct tty_struct *tty, char ch)
535 {
536 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
537 info->x_char = ch;
538 if (ch)
539 bcm_start (info->tty);
540 }
541
542 /*
543 * ------------------------------------------------------------
544 * rs_ioctl () and friends
545 * ------------------------------------------------------------
546 */
547 static int get_serial_info(struct bcm_serial *info, struct serial_struct *retinfo)
548 {
549 struct serial_struct tmp;
550
551 if (!retinfo)
552 return -EFAULT;
553
554 memset (&tmp, 0, sizeof(tmp));
555 tmp.type = info->type;
556 tmp.line = info->line;
557 tmp.port = (int) info->port;
558 tmp.irq = info->irq;
559 tmp.flags = 0;
560 tmp.baud_base = info->baud_base;
561 tmp.close_delay = info->close_delay;
562 tmp.closing_wait = info->closing_wait;
563
564 return copy_to_user (retinfo, &tmp, sizeof(*retinfo));
565 }
566
567 static int set_serial_info (struct bcm_serial *info, struct serial_struct *new_info)
568 {
569 struct serial_struct new_serial;
570 struct bcm_serial old_info;
571 int retval = 0;
572
573 if (!new_info)
574 return -EFAULT;
575
576 copy_from_user (&new_serial, new_info, sizeof(new_serial));
577 old_info = *info;
578
579 if (!capable(CAP_SYS_ADMIN))
580 return -EPERM;
581
582
583 if (info->count > 1)
584 return -EBUSY;
585
586 /* OK, past this point, all the error checking has been done.
587 * At this point, we start making changes.....
588 */
589 info->baud_base = new_serial.baud_base;
590 info->type = new_serial.type;
591 info->close_delay = new_serial.close_delay;
592 info->closing_wait = new_serial.closing_wait;
593 retval = startup (info);
594 return retval;
595 }
596
597 /*
598 * get_lsr_info - get line status register info
599 *
600 * Purpose: Let user call ioctl() to get info when the UART physically
601 * is emptied. On bus types like RS485, the transmitter must
602 * release the bus after transmitting. This must be done when
603 * the transmit shift register is empty, not be done when the
604 * transmit holding register is empty. This functionality
605 * allows an RS485 driver to be written in user space.
606 */
607 static int get_lsr_info (struct bcm_serial *info, unsigned int *value)
608 {
609 return( 0 );
610 }
611
612 /*
613 * This routine sends a break character out the serial port.
614 */
615 static void send_break (struct bcm_serial *info, int duration)
616 {
617 unsigned long flags;
618
619 if (!info->port)
620 return;
621
622 current->state = TASK_INTERRUPTIBLE;
623
624 /*save_flags (flags);
625 cli();*/
626 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
627
628 info->port->control |= XMITBREAK;
629 schedule_timeout(duration);
630 info->port->control &= ~XMITBREAK;
631
632 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
633 //restore_flags (flags);
634 }
635
636 static int bcm_ioctl (struct tty_struct * tty, struct file * file,
637 unsigned int cmd, unsigned long arg)
638 {
639 int error;
640 struct bcm_serial * info = (struct bcm_serial *)tty->driver_data;
641 int retval;
642
643 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
644 (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
645 (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT))
646 {
647 if (tty->flags & (1 << TTY_IO_ERROR))
648 return -EIO;
649 }
650 switch (cmd)
651 {
652
653 case TCSBRK: /* SVID version: non-zero arg --> no break */
654 retval = tty_check_change (tty);
655 if (retval)
656 return retval;
657 tty_wait_until_sent (tty, 0);
658 if (!arg)
659 send_break (info, HZ/4); /* 1/4 second */
660 return 0;
661
662 case TCSBRKP: /* support for POSIX tcsendbreak() */
663 retval = tty_check_change (tty);
664 if (retval)
665 return retval;
666 tty_wait_until_sent (tty, 0);
667 send_break (info, arg ? arg*(HZ/10) : HZ/4);
668 return 0;
669
670 case TIOCGSOFTCAR:
671 error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(long));
672 if (!error)
673 return -EFAULT;
674 else
675 {
676 put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
677 return 0;
678 }
679
680 case TIOCSSOFTCAR:
681 error = get_user (arg, (unsigned long *)arg);
682 if (error)
683 return error;
684 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
685 return 0;
686
687 case TIOCGSERIAL:
688 error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct));
689 if (!error)
690 return -EFAULT;
691 else
692 return get_serial_info (info, (struct serial_struct *)arg);
693
694 case TIOCSSERIAL:
695 return set_serial_info (info, (struct serial_struct *) arg);
696
697 case TIOCSERGETLSR: /* Get line status register */
698 error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(unsigned int));
699 if (!error)
700 return -EFAULT;
701 else
702 return get_lsr_info (info, (unsigned int *)arg);
703
704 case TIOCSERGSTRUCT:
705 error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(struct bcm_serial));
706 if (!error)
707 return -EFAULT;
708 else
709 {
710 copy_to_user((struct bcm_serial *)arg, info, sizeof(struct bcm_serial));
711 return 0;
712 }
713
714 default:
715 return -ENOIOCTLCMD;
716 }
717 return 0;
718 }
719
720 static void bcm_set_termios (struct tty_struct *tty, struct termios *old_termios)
721 {
722 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
723
724 if( tty->termios->c_cflag != old_termios->c_cflag )
725 change_speed (info->port, tty->termios->c_cflag);
726 }
727
728 /*
729 * ------------------------------------------------------------
730 * bcm63xx_cons_close()
731 *
732 * This routine is called when the serial port gets closed. First, we
733 * wait for the last remaining data to be sent. Then, we turn off
734 * the transmit enable and receive enable flags.
735 * ------------------------------------------------------------
736 */
737 static void bcm63xx_cons_close (struct tty_struct *tty, struct file *filp)
738 {
739 struct bcm_serial * info = (struct bcm_serial *)tty->driver_data;
740 unsigned long flags;
741
742 if (!info)
743 return;
744
745 /*save_flags (flags);
746 cli();*/
747 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
748
749 if (tty_hung_up_p (filp))
750 {
751 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
752 //restore_flags (flags);
753 return;
754 }
755
756 if ((tty->count == 1) && (info->count != 1))
757 {
758
759 /* Uh, oh. tty->count is 1, which means that the tty
760 * structure will be freed. Info->count should always
761 * be one in these conditions. If it's greater than
762 * one, we've got real problems, since it means the
763 * serial port won't be shutdown.
764 */
765 printk("bcm63xx_cons_close: bad serial port count; tty->count is 1, "
766 "info->count is %d\n", info->count);
767 info->count = 1;
768 }
769
770 if (--info->count < 0)
771 {
772 printk("ds_close: bad serial port count for ttys%d: %d\n",
773 info->line, info->count);
774 info->count = 0;
775 }
776
777 if (info->count)
778 {
779 //restore_flags (flags);
780 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
781 return;
782 }
783
784 /* Now we wait for the transmit buffer to clear; and we notify
785 * the line discipline to only process XON/XOFF characters.
786 */
787 tty->closing = 1;
788
789 /* At this point we stop accepting input. To do this, we
790 * disable the receive line status interrupts.
791 */
792 shutdown (info);
793 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
794 if (tty->driver->flush_buffer)
795 tty->driver->flush_buffer (tty);
796 #else
797 if (tty->driver.flush_buffer)
798 tty->driver.flush_buffer (tty);
799 #endif
800 if (tty->ldisc.flush_buffer)
801 tty->ldisc.flush_buffer (tty);
802
803 tty->closing = 0;
804 info->event = 0;
805 info->tty = 0;
806 if (tty->ldisc.num != tty_ldisc_get(N_TTY)->num)
807 {
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;
812 if (tty->ldisc.open)
813 (tty->ldisc.open)(tty);
814 }
815 if (info->blocked_open)
816 {
817 if (info->close_delay)
818 {
819 current->state = TASK_INTERRUPTIBLE;
820 schedule_timeout(info->close_delay);
821 }
822 wake_up_interruptible (&info->open_wait);
823 }
824 wake_up_interruptible (&info->close_wait);
825
826 //restore_flags (flags);
827 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
828 }
829
830 /*
831 * bcm_hangup () --- called by tty_hangup() when a hangup is signaled.
832 */
833 static void bcm_hangup (struct tty_struct *tty)
834 {
835
836 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
837
838 shutdown (info);
839 info->event = 0;
840 info->count = 0;
841 info->tty = 0;
842 wake_up_interruptible (&info->open_wait);
843 }
844
845 /*
846 * ------------------------------------------------------------
847 * rs_open() and friends
848 * ------------------------------------------------------------
849 */
850 static int block_til_ready (struct tty_struct *tty, struct file *filp,
851 struct bcm_serial *info)
852 {
853 return 0;
854 }
855
856 /*
857 * This routine is called whenever a serial port is opened. It
858 * enables interrupts for a serial port. It also performs the
859 * serial-specific initialization for the tty structure.
860 */
861 static int bcm63xx_cons_open (struct tty_struct * tty, struct file * filp)
862 {
863 struct bcm_serial *info;
864 int retval, line;
865
866 // Make sure we're only opening on of the ports we support
867 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
868 line = MINOR(tty->driver->cdev.dev) - tty->driver->minor_start;
869 #else
870 line = MINOR(tty->device) - tty->driver.minor_start;
871 #endif
872
873 if ((line < 0) || (line >= BCM_NUM_UARTS))
874 return -ENODEV;
875
876 info = lines[line];
877
878 tty->low_latency=1;
879 info->port->intMask = 0; /* Clear any pending interrupts */
880 info->port->intMask = RXINT; /* Enable RX */
881
882 info->count++;
883 tty->driver_data = info;
884 info->tty = tty;
885 BcmHalInterruptEnable (INTERRUPT_ID_UART);
886
887 // Start up serial port
888 retval = startup (info);
889 if (retval)
890 return retval;
891
892 retval = block_til_ready (tty, filp, info);
893 if (retval)
894 return retval;
895
896
897 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
898 info->pgrp = process_group(current);
899 info->session = current->signal->session;
900 #else
901 info->session = current->session;
902 info->pgrp = current->pgrp;
903 #endif
904
905 return 0;
906 }
907
908
909 static struct tty_operations rs_ops = {
910 .open = bcm63xx_cons_open,
911 .close = bcm63xx_cons_close,
912 .write = bcm63xx_cons_write,
913 .flush_chars = bcm63xx_cons_flush_chars,
914 .write_room = bcm63xx_cons_write_room,
915 .chars_in_buffer = bcm_chars_in_buffer,
916 .flush_buffer = bcm_flush_buffer,
917 .ioctl = bcm_ioctl,
918 .throttle = bcm_throttle,
919 .unthrottle = bcm_unthrottle,
920 .send_xchar = bcm_send_xchar,
921 .set_termios = bcm_set_termios,
922 .stop = bcm_stop,
923 .start = bcm_start,
924 .hangup = bcm_hangup,
925 };
926
927 /* --------------------------------------------------------------------------
928 Name: bcm63xx_serialinit
929 Purpose: Initialize our BCM63xx serial driver
930 -------------------------------------------------------------------------- */
931 static int __init bcm63xx_serialinit(void)
932 {
933 int i, flags;
934 struct bcm_serial * info;
935
936 // Print the driver version information
937 printk(VER_STR);
938 serial_driver = alloc_tty_driver(BCM_NUM_UARTS);
939 if (!serial_driver)
940 return -ENOMEM;
941
942 serial_driver->owner = THIS_MODULE;
943 // serial_driver->devfs_name = "tts/";
944 // serial_driver.magic = TTY_DRIVER_MAGIC;
945 serial_driver->name = "ttyS";
946 serial_driver->major = TTY_MAJOR;
947 serial_driver->minor_start = 64;
948 // serial_driver.num = BCM_NUM_UARTS;
949 serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
950 serial_driver->subtype = SERIAL_TYPE_NORMAL;
951 serial_driver->init_termios = tty_std_termios;
952 serial_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
953 serial_driver->flags = TTY_DRIVER_REAL_RAW;
954
955 serial_driver->termios = serial_termios;
956 serial_driver->termios_locked = serial_termios_locked;
957
958 tty_set_operations(serial_driver, &rs_ops);
959
960 if (tty_register_driver (serial_driver))
961 panic("Couldn't register serial driver\n");
962
963 //save_flags(flags); cli();
964 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
965
966 for (i = 0; i < BCM_NUM_UARTS; i++)
967 {
968 info = &multi[i];
969 lines[i] = info;
970 info->magic = SERIAL_MAGIC;
971 info->port = (Uart *) ((char *)UART_BASE + (i * 0x20));
972 info->tty = 0;
973 info->irq = (2 - i) + 8;
974 info->line = i;
975 info->close_delay = 50;
976 info->closing_wait = 3000;
977 info->x_char = 0;
978 info->event = 0;
979 info->count = 0;
980 info->blocked_open = 0;
981 info->normal_termios = serial_driver->init_termios;
982 init_waitqueue_head(&info->open_wait);
983 init_waitqueue_head(&info->close_wait);
984
985 /* If we are pointing to address zero then punt - not correctly
986 * set up in setup.c to handle this.
987 */
988 if (! info->port)
989 return 0;
990 BcmHalMapInterrupt(bcm_interrupt, 0, INTERRUPT_ID_UART);
991 }
992
993 /* order matters here... the trick is that flags
994 * is updated... in request_irq - to immediatedly obliterate
995 * it is unwise.
996 */
997 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
998 return 0;
999 }
1000
1001 module_init(bcm63xx_serialinit);
1002
1003 /* --------------------------------------------------------------------------
1004 Name: bcm_console_print
1005 Purpose: bcm_console_print is registered for printk.
1006 The console_lock must be held when we get here.
1007 -------------------------------------------------------------------------- */
1008 static void bcm_console_print (struct console * cons, const char * str,
1009 unsigned int count)
1010 {
1011 unsigned int i;
1012 //_puts(str);
1013 for(i=0; i<count; i++, str++)
1014 {
1015 _putc(*str);
1016 if (*str == 10)
1017 {
1018 _putc(13);
1019 }
1020 }
1021 }
1022
1023 static struct tty_driver * bcm_console_device(struct console * c, int *index)
1024 {
1025 *index = c->index;
1026 return serial_driver;
1027 }
1028
1029 static int __init bcm_console_setup(struct console * co, char * options)
1030 {
1031 return 0;
1032 }
1033
1034 static struct console bcm_sercons = {
1035 .name = "ttyS",
1036 .write = bcm_console_print,
1037 .device = bcm_console_device,
1038 .setup = bcm_console_setup,
1039 .flags = CON_PRINTBUFFER,
1040 .index = -1,
1041 };
1042
1043 static int __init bcm63xx_console_init(void)
1044 {
1045 register_console(&bcm_sercons);
1046 return 0;
1047 }
1048
1049 console_initcall(bcm63xx_console_init);