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