1 #include <minix/config.h>
2 #include <minix/drivers.h>
8 #include "omap_serial.h"
13 #define UART_FREQ 48000000L /* timer frequency */
15 #define DFLT_BAUD TSPEED_DEF /* default baud rate */
17 #define DFLT_BAUD B115200 /* default baud rate */
21 #define RS_IBUFSIZE 1024 /* RS232 input buffer size */
22 #define RS_OBUFSIZE 1024 /* RS232 output buffer size */
24 /* Input buffer watermarks.
25 * The external device is asked to stop sending when the buffer
26 * exactly reaches high water, or when TTY requests it. Sending restarts
27 * when the input buffer empties below the low watermark.
29 #define RS_ILOWWATER (1 * RS_IBUFSIZE / 4)
30 #define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4)
32 /* Output buffer low watermark.
33 * TTY is notified when the output buffer empties below the low watermark, so
34 * it may continue filling the buffer if doing a large write.
36 #define RS_OLOWWATER (1 * RS_OBUFSIZE / 4)
38 /* Macros to handle flow control.
39 * Interrupts must be off when they are used.
40 * Time is critical - already the function call for outb() is annoying.
41 * If outb() can be done in-line, tests to avoid it can be dropped.
42 * istart() tells external device we are ready by raising RTS.
43 * istop() tells external device we are not ready by dropping RTS.
44 * DTR is kept high all the time (it probably should be raised by open and
45 * dropped by close of the device).
46 * OUT2 is also kept high all the time.
49 (serial_out((rs), OMAP3_MCR, UART_MCR_OUT2|UART_MCR_RTS|UART_MCR_DTR),\
50 (rs)->idevready = TRUE)
52 (serial_out((rs), OMAP3_MCR, UART_MCR_OUT2|UART_MCR_DTR), \
53 (rs)->idevready = FALSE)
55 /* Macro to tell if device is ready. The rs->cts field is set to UART_MSR_CTS
56 * if CLOCAL is in effect for a line without a CTS wire.
58 #define devready(rs) ((serial_in(rs, OMAP3_MSR) | rs->cts) & UART_MSR_CTS)
60 /* Macro to tell if transmitter is ready. */
61 #define txready(rs) (serial_in(rs, OMAP3_LSR) & UART_LSR_THRE)
63 /* RS232 device structure, one per device. */
64 typedef struct rs232
{
65 tty_t
*tty
; /* associated TTY structure */
67 int icount
; /* number of bytes in the input buffer */
68 char *ihead
; /* next free spot in input buffer */
69 char *itail
; /* first byte to give to TTY */
70 char idevready
; /* nonzero if we are ready to receive (RTS) */
71 char cts
; /* normally 0, but MS_CTS if CLOCAL is set */
73 unsigned char ostate
; /* combination of flags: */
74 #define ODONE 1 /* output completed (< output enable bits) */
75 #define ORAW 2 /* raw mode for xoff disable (< enab. bits) */
76 #define OWAKEUP 4 /* tty_wakeup() pending (asm code only) */
77 #define ODEVREADY UART_MSR_CTS /* external device hardware ready (CTS) */
78 #define OQUEUED 0x20 /* output buffer not empty */
79 #define OSWREADY 0x40 /* external device software ready (no xoff) */
80 #define ODEVHUP UART_MSR_DCD /* external device has dropped carrier */
81 #define OSOFTBITS (ODONE | ORAW | OWAKEUP | OQUEUED | OSWREADY)
82 /* user-defined bits */
83 #if (OSOFTBITS | ODEVREADY | ODEVHUP) == OSOFTBITS
84 /* a weak sanity check */
85 #error /* bits are not unique */
87 unsigned char oxoff
; /* char to stop output */
88 char inhibited
; /* output inhibited? (follows tty_inhibited) */
89 char drain
; /* if set drain output and reconfigure line */
90 int ocount
; /* number of bytes in the output buffer */
91 char *ohead
; /* next free spot in output buffer */
92 char *otail
; /* next char to output */
94 phys_bytes phys_base
; /* UART physical base address (I/O map) */
95 unsigned int reg_offset
; /* UART register offset */
96 unsigned int ier
; /* copy of ier register */
97 unsigned int scr
; /* copy of scr register */
98 unsigned int fcr
; /* copy of fcr register */
99 unsigned int dll
; /* copy of dll register */
100 unsigned int dlh
; /* copy of dlh register */
101 unsigned int uartclk
; /* UART clock rate */
103 unsigned char lstatus
; /* last line status */
104 unsigned framing_errors
; /* error counts (no reporting yet) */
105 unsigned overrun_errors
;
106 unsigned parity_errors
;
107 unsigned break_interrupts
;
109 int irq
; /* irq for this line */
110 int irq_hook_id
; /* interrupt hook */
112 char ibuf
[RS_IBUFSIZE
]; /* input buffer */
113 char obuf
[RS_OBUFSIZE
]; /* output buffer */
116 static rs232_t rs_lines
[NR_RS_LINES
];
118 typedef struct uart_port
{
119 phys_bytes base_addr
;
123 /* OMAP3 UART base addresses. */
124 static uart_port_t omap3
[] = {
125 { OMAP3_UART1_BASE
, 72}, /* UART1 */
126 { OMAP3_UART2_BASE
, 73}, /* UART2 */
127 { OMAP3_UART3_BASE
, 74}, /* UART3 */
131 static int rs_write(tty_t
*tp
, int try);
132 static void rs_echo(tty_t
*tp
, int c
);
133 static int rs_ioctl(tty_t
*tp
, int try);
134 static void rs_config(rs232_t
*rs
);
135 static int rs_read(tty_t
*tp
, int try);
136 static int rs_icancel(tty_t
*tp
, int try);
137 static int rs_ocancel(tty_t
*tp
, int try);
138 static void rs_ostart(rs232_t
*rs
);
139 static int rs_break(tty_t
*tp
, int try);
140 static int rs_close(tty_t
*tp
, int try);
141 static int rs_open(tty_t
*tp
, int try);
142 static void rs232_handler(rs232_t
*rs
);
143 static void rs_reset(rs232_t
*rs
);
144 static unsigned int check_modem_status(rs232_t
*rs
);
145 static int termios_baud_rate(struct termios
*term
);
147 static inline unsigned int readw(vir_bytes addr
);
148 static inline unsigned int serial_in(rs232_t
*rs
, int offset
);
149 static inline void serial_out(rs232_t
*rs
, int offset
, int val
);
150 static inline void writew(vir_bytes addr
, int val
);
151 static void write_chars(rs232_t
*rs
);
152 static void read_chars(rs232_t
*rs
, unsigned int status
);
154 static inline unsigned int
155 readw(vir_bytes addr
)
157 return *((volatile unsigned int *) addr
);
161 writew(vir_bytes addr
, int val
)
163 *((volatile unsigned int *) addr
) = val
;
166 static inline unsigned int
167 serial_in(rs232_t
*rs
, int offset
)
169 offset
<<= rs
->reg_offset
;
170 return readw(rs
->phys_base
+ offset
);
174 serial_out(rs232_t
*rs
, int offset
, int val
)
176 offset
<<= rs
->reg_offset
;
177 writew(rs
->phys_base
+ offset
, val
);
181 rs_reset(rs232_t
*rs
)
185 serial_out(rs
, OMAP3_SYSC
, UART_SYSC_SOFTRESET
);
187 /* Poll until done */
189 syss
= serial_in(rs
, OMAP3_SYSS
);
190 } while (!(syss
& UART_SYSS_RESETDONE
));
194 rs_write(register tty_t
*tp
, int try)
196 /* (*devwrite)() routine for RS232. */
198 rs232_t
*rs
= tp
->tty_priv
;
199 int r
, count
, ocount
;
201 if (rs
->inhibited
!= tp
->tty_inhibited
) {
202 /* Inhibition state has changed. */
203 rs
->ostate
|= OSWREADY
;
204 if (tp
->tty_inhibited
) rs
->ostate
&= ~OSWREADY
;
205 rs
->inhibited
= tp
->tty_inhibited
;
209 /* Wait for the line to drain then reconfigure and continue
211 if (rs
->ocount
> 0) return 0;
215 /* While there is something to do. */
217 ocount
= buflen(rs
->obuf
) - rs
->ocount
;
218 count
= bufend(rs
->obuf
) - rs
->ohead
;
219 if (count
> ocount
) count
= ocount
;
220 if (count
> tp
->tty_outleft
) count
= tp
->tty_outleft
;
221 if (count
== 0 || tp
->tty_inhibited
) {
228 /* Copy from user space to the RS232 output buffer. */
229 if (tp
->tty_outcaller
== KERNEL
) {
230 /* We're trying to print on kernel's behalf */
232 (void *) tp
->tty_outgrant
+ tp
->tty_outoffset
,
235 if ((r
= sys_safecopyfrom(tp
->tty_outcaller
,
236 tp
->tty_outgrant
, tp
->tty_outoffset
,
237 (vir_bytes
) rs
->ohead
, count
)) != OK
) {
242 /* Perform output processing on the output buffer. */
243 out_process(tp
, rs
->obuf
, rs
->ohead
, bufend(rs
->obuf
), &count
,
249 /* Assume echoing messed up by output. */
250 tp
->tty_reprint
= TRUE
;
253 rs
->ocount
+= ocount
;
255 if ((rs
->ohead
+= ocount
) >= bufend(rs
->obuf
))
256 rs
->ohead
-= buflen(rs
->obuf
);
257 tp
->tty_outoffset
+= count
;
258 tp
->tty_outcum
+= count
;
259 if ((tp
->tty_outleft
-= count
) == 0) {
260 /* Output is finished, reply to the writer. */
261 if(tp
->tty_outrepcode
== TTY_REVIVE
) {
262 notify(tp
->tty_outcaller
);
263 tp
->tty_outrevived
= 1;
265 tty_reply(tp
->tty_outrepcode
, tp
->tty_outcaller
,
266 tp
->tty_outproc
, tp
->tty_outcum
);
272 if (tp
->tty_outleft
> 0 && tp
->tty_termios
.c_ospeed
== B0
) {
273 /* Oops, the line has hung up. */
274 if(tp
->tty_outrepcode
== TTY_REVIVE
) {
275 notify(tp
->tty_outcaller
);
276 tp
->tty_outrevived
= 1;
278 tty_reply(tp
->tty_outrepcode
, tp
->tty_outcaller
,
279 tp
->tty_outproc
, EIO
);
280 tp
->tty_outleft
= tp
->tty_outcum
= 0;
288 rs_echo(tty_t
*tp
, int character
)
290 /* Echo one character. (Like rs_write, but only one character, optionally.) */
292 rs232_t
*rs
= tp
->tty_priv
;
295 ocount
= buflen(rs
->obuf
) - rs
->ocount
;
296 if (ocount
== 0) return; /* output buffer full */
298 *rs
->ohead
= character
; /* add one character */
300 out_process(tp
, rs
->obuf
, rs
->ohead
, bufend(rs
->obuf
), &count
, &ocount
);
301 if (count
== 0) return;
303 rs
->ocount
+= ocount
;
305 if ((rs
->ohead
+= ocount
) >= bufend(rs
->obuf
))
306 rs
->ohead
-= buflen(rs
->obuf
);
310 rs_ioctl(tty_t
*tp
, int UNUSED(dummy
))
312 /* Reconfigure the line as soon as the output has drained. */
313 rs232_t
*rs
= tp
->tty_priv
;
316 return 0; /* dummy */
320 omap_get_divisor(rs232_t
*rs
, unsigned int baud
)
322 /* Calculate divisor value. The 16750 has two oversampling modes to reach
323 * high baud rates with little error rate (see table 17-1 in OMAP TRM).
324 * Baud rates 460800, 921600, 1843200, and 3686400 use 13x oversampling,
325 * the other rates 16x. The baud rate is calculated as follows:
326 * baud rate = (functional clock / oversampling) / divisor.
329 unsigned int oversampling
;
333 case B460800
: /* Fall through */
334 case B921600
: /* Fall through */
335 case B1843200
: /* Fall through */
336 case B3686400
: oversampling
= 13; break;
337 default: oversampling
= 16;
340 return (rs
->uartclk
/ oversampling
) / baud
;
344 termios_baud_rate(struct termios
*term
)
347 switch(term
->c_ospeed
) {
348 case B0
: term
->c_ospeed
= DFLT_BAUD
; baud
= termios_baud_rate(term
);
349 case B300
: baud
= 300; break;
350 case B600
: baud
= 600; break;
351 case B1200
: baud
= 1200; break;
352 case B2400
: baud
= 2400; break;
353 case B4800
: baud
= 4800; break;
354 case B9600
: baud
= 9600; break;
355 case B38400
: baud
= 38400; break;
356 case B57600
: baud
= 57600; break;
357 case B115200
: baud
= 115200; break;
358 default: term
->c_ospeed
= DFLT_BAUD
; baud
= termios_baud_rate(term
);
363 static void rs_config(rs232_t
*rs
)
365 /* Set various line control parameters for RS232 I/O. */
367 unsigned int divisor
, efr
, lcr
, mcr
, baud
;
369 /* Fifo and DMA settings */
370 /* See OMAP35x TRM 17.5.1.1.2 */
371 lcr
= serial_in(rs
, OMAP3_LCR
); /* 1a */
372 serial_out(rs
, OMAP3_LCR
, UART_LCR_CONF_MODE_B
); /* 1b */
373 efr
= serial_in(rs
, OMAP3_EFR
); /* 2a */
374 serial_out(rs
, OMAP3_EFR
, efr
| UART_EFR_ECB
); /* 2b */
375 serial_out(rs
, OMAP3_LCR
, UART_LCR_CONF_MODE_A
); /* 3 */
376 mcr
= serial_in(rs
, OMAP3_MCR
); /* 4a */
377 serial_out(rs
, OMAP3_MCR
, mcr
| UART_MCR_TCRTLR
); /* 4b */
378 /* Set up FIFO for 1 byte */
380 rs
->fcr
&= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK
;
381 rs
->fcr
|= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT
);
382 serial_out(rs
, OMAP3_FCR
, rs
->fcr
); /* 5 */
383 serial_out(rs
, OMAP3_LCR
, UART_LCR_CONF_MODE_B
); /* 6 */
384 /* DMA triggers, not supported by this driver */ /* 7 */
385 rs
->scr
= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK
;
386 serial_out(rs
, OMAP3_SCR
, rs
->scr
); /* 8 */
387 serial_out(rs
, OMAP3_EFR
, efr
); /* 9 */
388 serial_out(rs
, OMAP3_LCR
, UART_LCR_CONF_MODE_A
); /* 10 */
389 serial_out(rs
, OMAP3_MCR
, mcr
); /* 11 */
390 serial_out(rs
, OMAP3_LCR
, lcr
); /* 12 */
392 /* RS232 needs to know the xoff character, and if CTS works. */
393 rs
->oxoff
= tp
->tty_termios
.c_cc
[VSTOP
];
394 rs
->cts
= (tp
->tty_termios
.c_cflag
& CLOCAL
) ? UART_MSR_CTS
: 0;
395 baud
= termios_baud_rate(&tp
->tty_termios
);
397 /* Look up the 16750 rate divisor from the output speed. */
398 divisor
= omap_get_divisor(rs
, baud
);
399 rs
->dll
= divisor
& 0xFF;
400 rs
->dlh
= divisor
>> 8;
402 /* Compute line control flag bits. */
404 if (tp
->tty_termios
.c_cflag
& PARENB
) {
405 lcr
|= UART_LCR_PARITY
;
406 if (!(tp
->tty_termios
.c_cflag
& PARODD
)) lcr
|= UART_LCR_EPAR
;
408 if (tp
->tty_termios
.c_cflag
& CSTOPB
) lcr
|= UART_LCR_STOP
;
409 switch(tp
->tty_termios
.c_cflag
& CSIZE
) {
411 lcr
|= UART_LCR_WLEN5
;
414 lcr
|= UART_LCR_WLEN6
;
417 lcr
|= UART_LCR_WLEN7
;
421 lcr
|= UART_LCR_WLEN8
;
425 /* Lock out interrupts while setting the speed. The receiver register
426 * is going to be hidden by the div_low register, but the input
427 * interrupt handler relies on reading it to clear the interrupt and
428 * avoid looping forever.
431 if (sys_irqdisable(&rs
->irq_hook_id
) != OK
)
432 panic("unable to disable interrupts");
434 /* Select the baud rate divisor registers and change the rate. */
435 /* See OMAP35x TRM 17.5.1.1.3 */
436 serial_out(rs
, OMAP3_MDR1
, OMAP_MDR1_DISABLE
); /* 1 */
437 serial_out(rs
, OMAP3_LCR
, UART_LCR_CONF_MODE_B
); /* 2 */
438 efr
= serial_in(rs
, OMAP3_EFR
); /* 3a */
439 serial_out(rs
, OMAP3_EFR
, efr
| UART_EFR_ECB
); /* 3b */
440 serial_out(rs
, OMAP3_LCR
, 0); /* 4 */
441 serial_out(rs
, OMAP3_IER
, 0); /* 5 */
442 serial_out(rs
, OMAP3_LCR
, UART_LCR_CONF_MODE_B
); /* 6 */
443 serial_out(rs
, OMAP3_DLL
, rs
->dll
); /* 7 */
444 serial_out(rs
, OMAP3_DLH
, rs
->dlh
); /* 7 */
445 serial_out(rs
, OMAP3_LCR
, 0); /* 8 */
446 serial_out(rs
, OMAP3_IER
, rs
->ier
); /* 9 */
447 serial_out(rs
, OMAP3_LCR
, UART_LCR_CONF_MODE_B
); /* 10 */
448 serial_out(rs
, OMAP3_EFR
, efr
); /* 11 */
449 serial_out(rs
, OMAP3_LCR
, lcr
); /* 12 */
450 if (baud
> 230400 && baud
!= 3000000)
451 serial_out(rs
, OMAP3_MDR1
, OMAP_MDR1_MODE13X
); /* 13 */
453 serial_out(rs
, OMAP3_MDR1
, OMAP_MDR1_MODE16X
);
455 rs
->ostate
= devready(rs
) | ORAW
| OSWREADY
; /* reads MSR */
456 if ((tp
->tty_termios
.c_lflag
& IXON
) && rs
->oxoff
!= _POSIX_VDISABLE
)
458 (void) serial_in(rs
, OMAP3_IIR
);
459 if (sys_irqenable(&rs
->irq_hook_id
) != OK
)
460 panic("unable to enable interrupts");
466 /* Initialize RS232 for one line. */
467 register rs232_t
*rs
;
469 uart_port_t this_omap3
;
471 struct minix_mem_range mr
;
473 /* Associate RS232 and TTY structures. */
474 line
= tp
- &tty_table
[NR_CONS
];
476 /* See if kernel debugging is enabled; if so, don't initialize this
477 * serial line, making tty not look at the irq and returning ENXIO
478 * for all requests on it from userland. (The kernel will use it.)
480 if(env_get_param(SERVARNAME
, l
, sizeof(l
)-1) == OK
&& atoi(l
) == line
){
481 printf("TTY: rs232 line %d not initialized (used by kernel)\n",
486 rs
= tp
->tty_priv
= &rs_lines
[line
];
489 /* Set up input queue. */
490 rs
->ihead
= rs
->itail
= rs
->ibuf
;
492 this_omap3
= omap3
[line
];
493 if (this_omap3
.base_addr
== 0) return;
495 /* Configure memory access */
496 mr
.mr_base
= rs
->phys_base
;
497 mr
.mr_limit
= rs
->phys_base
+ 0x100;
498 if (sys_privctl(SELF
, SYS_PRIV_ADD_MEM
, &mr
) != OK
) {
499 panic("Unable to request access to UART memory");
501 rs
->phys_base
= (vir_bytes
) vm_map_phys(SELF
,
502 (void *) this_omap3
.base_addr
, 0x100);
504 if (rs
->phys_base
== (vir_bytes
) MAP_FAILED
) {
505 panic("Unable to request access to UART memory");
509 rs
->uartclk
= UART_FREQ
;
510 rs
->ohead
= rs
->otail
= rs
->obuf
;
512 /* Override system default baud rate. We do this because u-boot
513 * configures the UART for a baud rate of 115200 b/s and the kernel
514 * directly sends data over serial out upon boot up. If we then
515 * suddenly change the settings, the output will be garbled during
518 tp
->tty_termios
.c_ospeed
= DFLT_BAUD
;
521 rs
->irq
= this_omap3
.irq
;
522 rs
->irq_hook_id
= 1 << line
; /* call back with irq line number */
523 if (sys_irqsetpolicy(rs
->irq
, 0, &rs
->irq_hook_id
) != OK
) {
524 printf("RS232: Couldn't obtain hook for irq %d\n", rs
->irq
);
526 if (sys_irqenable(&rs
->irq_hook_id
) != OK
) {
527 printf("RS232: Couldn't enable irq %d (hooked)\n",
531 rs_irq_set
|= (1 << (rs
->irq_hook_id
+ 1));
533 /* Enable interrupts */
535 rs
->ier
= UART_IER_RLSI
| UART_IER_RDI
| UART_IER_MSI
;
538 /* Fill in TTY function hooks. */
539 tp
->tty_devread
= rs_read
;
540 tp
->tty_devwrite
= rs_write
;
541 tp
->tty_echo
= rs_echo
;
542 tp
->tty_icancel
= rs_icancel
;
543 tp
->tty_ocancel
= rs_ocancel
;
544 tp
->tty_ioctl
= rs_ioctl
;
545 tp
->tty_break
= rs_break
;
546 tp
->tty_open
= rs_open
;
547 tp
->tty_close
= rs_close
;
549 /* Tell external device we are ready. */
554 rs_interrupt(message
*m
)
556 unsigned long irq_set
;
560 irq_set
= m
->NOTIFY_ARG
;
561 for (line
= 0, rs
= rs_lines
; line
< NR_RS_LINES
; line
++, rs
++) {
562 if (irq_set
& (1 << (rs
->irq_hook_id
+1))) {
564 if (sys_irqenable(&rs
->irq_hook_id
) != OK
)
565 panic("unable to enable interrupts");
571 rs_icancel(tty_t
*tp
, int UNUSED(dummy
))
573 /* Cancel waiting input. */
574 rs232_t
*rs
= tp
->tty_priv
;
577 rs
->itail
= rs
->ihead
;
579 return 0; /* dummy */
583 rs_ocancel(tty_t
*tp
, int UNUSED(dummy
))
585 /* Cancel pending output. */
586 rs232_t
*rs
= tp
->tty_priv
;
588 rs
->ostate
&= ~(ODONE
| OQUEUED
);
590 rs
->otail
= rs
->ohead
;
592 return 0; /* dummy */
596 rs_read(tty_t
*tp
, int try)
598 /* Process characters from the circular input buffer. */
600 rs232_t
*rs
= tp
->tty_priv
;
601 int icount
, count
, ostate
;
603 if (!(tp
->tty_termios
.c_cflag
& CLOCAL
)) {
606 /* Send a SIGHUP if hangup detected. */
608 rs
->ostate
&= ~ODEVHUP
; /* save ostate, clear DEVHUP */
609 if (ostate
& ODEVHUP
) {
610 sigchar(tp
, SIGHUP
, 1);
611 tp
->tty_termios
.c_ospeed
= B0
;/* Disable further I/O.*/
617 return(rs
->icount
> 0);
620 while ((count
= rs
->icount
) > 0) {
621 icount
= bufend(rs
->ibuf
) - rs
->itail
;
622 if (count
> icount
) count
= icount
;
624 /* Perform input processing on (part of) the input buffer. */
625 if ((count
= in_process(tp
, rs
->itail
, count
, -1)) == 0) break;
627 if (!rs
->idevready
&& rs
->icount
< RS_ILOWWATER
) istart(rs
);
628 if ((rs
->itail
+= count
) == bufend(rs
->ibuf
))
629 rs
->itail
= rs
->ibuf
;
636 rs_ostart(rs232_t
*rs
)
638 /* Tell RS232 there is something waiting in the output buffer. */
640 rs
->ostate
|= OQUEUED
;
641 if (txready(rs
)) write_chars(rs
);
645 rs_break(tty_t
*tp
, int UNUSED(dummy
))
647 /* Generate a break condition by setting the BREAK bit for 0.4 sec. */
648 rs232_t
*rs
= tp
->tty_priv
;
651 lsr
= serial_in(rs
, OMAP3_LSR
);
652 serial_out(rs
, OMAP3_LSR
, lsr
| UART_LSR_BI
);
654 /* milli_delay(400); */ /* ouch */
655 serial_out(rs
, OMAP3_LSR
, lsr
);
656 return 0; /* dummy */
660 rs_open(tty_t
*tp
, int UNUSED(dummy
))
662 /* Set the speed to 115200 by default */
663 tp
->tty_termios
.c_ospeed
= DFLT_BAUD
;
668 rs_close(tty_t
*tp
, int UNUSED(dummy
))
670 /* The line is closed; optionally hang up. */
671 rs232_t
*rs
= tp
->tty_priv
;
673 if (tp
->tty_termios
.c_cflag
& HUPCL
) {
674 serial_out(rs
, OMAP3_MCR
, UART_MCR_OUT2
|UART_MCR_RTS
);
675 if (rs
->ier
& UART_IER_THRI
) {
676 rs
->ier
&= ~UART_IER_THRI
;
677 serial_out(rs
, OMAP3_IER
, rs
->ier
);
680 return 0; /* dummy */
683 /* Low level (interrupt) routines. */
686 rs232_handler(struct rs232
*rs
)
688 /* Handle interrupt of a UART port */
689 unsigned int iir
, lsr
;
691 iir
= serial_in(rs
, OMAP3_IIR
);
692 if (iir
& UART_IIR_NO_INT
) /* No interrupt */
695 lsr
= serial_in(rs
, OMAP3_LSR
);
696 if (iir
& UART_IIR_RDI
) { /* Data ready interrupt */
697 if (lsr
& UART_LSR_DR
) {
701 check_modem_status(rs
);
702 if (iir
& UART_IIR_THRI
) {
703 if (lsr
& UART_LSR_THRE
) {
704 /* Ready to send and space available */
711 read_chars(rs232_t
*rs
, unsigned int status
)
718 if (lsr
& UART_LSR_DR
) {
719 c
= serial_in(rs
, OMAP3_RHR
);
720 if (!(rs
->ostate
& ORAW
)) {
721 if (c
== rs
->oxoff
) {
722 rs
->ostate
&= ~OSWREADY
;
723 } else if (!(rs
->ostate
& OSWREADY
)) {
724 rs
->ostate
= OSWREADY
;
728 if (rs
->icount
== buflen(rs
->ibuf
)) {
729 printf("%s:%d buffer full, discarding byte\n",
730 __FUNCTION__
, __LINE__
);
734 if (++rs
->icount
== RS_IHIGHWATER
&& rs
->idevready
) istop(rs
);
736 if (++rs
->ihead
== bufend(rs
->ibuf
)) rs
->ihead
= rs
->ibuf
;
737 if (rs
->icount
== 1) {
738 rs
->tty
->tty_events
= 1;
744 write_chars(rs232_t
*rs
)
746 /* If there is output to do and everything is ready, do it (local device is
748 * Notify TTY when the buffer goes empty.
751 if (rs
->ostate
>= (ODEVREADY
| OQUEUED
| OSWREADY
)) {
752 /* Bit test allows ORAW and requires the others. */
753 serial_out(rs
, OMAP3_THR
, *rs
->otail
);
754 if (++rs
->otail
== bufend(rs
->obuf
))
755 rs
->otail
= rs
->obuf
;
756 if (--rs
->ocount
== 0) {
757 /* Turn on ODONE flag, turn off OQUEUED */
758 rs
->ostate
^= (ODONE
| OQUEUED
);
759 rs
->tty
->tty_events
= 1;
760 if (rs
->ier
& UART_IER_THRI
) {
761 rs
->ier
&= ~UART_IER_THRI
;
762 serial_out(rs
, OMAP3_IER
, rs
->ier
);
765 if (rs
->icount
== RS_OLOWWATER
)
766 rs
->tty
->tty_events
= 1;
767 if (!(rs
->ier
& UART_IER_THRI
)) {
768 rs
->ier
|= UART_IER_THRI
;
769 serial_out(rs
, OMAP3_IER
, rs
->ier
);
776 check_modem_status(rs232_t
*rs
)
778 /* Check modem status */
782 msr
= serial_in(rs
, OMAP3_MSR
); /* Resets modem interrupt */
783 if ((msr
& (UART_MSR_DCD
|UART_MSR_DDCD
)) == UART_MSR_DDCD
) {
784 rs
->ostate
|= ODEVHUP
;
785 rs
->tty
->tty_events
= 1;
789 rs
->ostate
&= ~ODEVREADY
;
791 rs
->ostate
|= ODEVREADY
;
796 #endif /* NR_RS_LINES > 0 */