source: rtems/c/src/lib/libbsp/powerpc/shared/console/uart.c @ 969de1f3

4.104.114.84.95
Last change on this file since 969de1f3 was acc25ee, checked in by Joel Sherrill <joel.sherrill@…>, on Dec 2, 1999 at 2:31:19 PM

Merged of mcp750 and mvme2307 BSP by Eric Valette <valette@…>.
As part of this effort, the mpc750 libcpu code is now shared with the
ppc6xx.

  • Property mode set to 100644
File size: 14.3 KB
Line 
1/*
2 * This software is Copyright (C) 1998 by T.sqware - all rights limited
3 * It is provided in to the public domain "as is", can be freely modified
4 * as far as this copyight notice is kept unchanged, but does not imply
5 * an endorsement by T.sqware of the product in which it is included.
6 *
7 *  $Id$
8 */
9
10#include <bsp.h>
11#include <bsp/irq.h>
12#include <bsp/uart.h>
13#include <rtems/libio.h>
14#include <assert.h>
15
16/*
17 * Basic 16552 driver
18 */
19
20struct uart_data
21{
22  int hwFlow;
23  int baud;
24};
25
26static struct uart_data uart_data[2];
27
28/*
29 * Macros to read/wirte register of uart, if configuration is
30 * different just rewrite these macros
31 */ 
32
33static inline unsigned char
34uread(int uart, unsigned int reg)
35{
36  register unsigned char val;
37
38  if(uart == 0)
39    {
40      inport_byte(COM1_BASE_IO+reg, val);
41    }
42  else
43    {
44      inport_byte(COM2_BASE_IO+reg, val);
45    }
46
47  return val;
48}
49
50static inline void     
51uwrite(int uart, int reg, unsigned int val)
52{
53  if(uart == 0)
54    {
55      outport_byte(COM1_BASE_IO+reg, val);
56    } 
57  else
58    {
59      outport_byte(COM2_BASE_IO+reg, val);
60    }
61}
62
63#ifdef UARTDEBUG
64    static void
65uartError(int uart)
66{
67  unsigned char uartStatus, dummy;
68
69  uartStatus = uread(uart, LSR);
70  dummy = uread(uart, RBR);
71
72  if (uartStatus & OE)
73    printk("********* Over run Error **********\n");
74  if (uartStatus & PE)
75    printk("********* Parity Error   **********\n");
76  if (uartStatus & FE)
77    printk("********* Framing Error  **********\n");
78  if (uartStatus & BI)
79    printk("********* Parity Error   **********\n");
80  if (uartStatus & ERFIFO)
81    printk("********* Error receive Fifo **********\n");
82
83}
84#else
85inline void uartError(int uart)
86{
87  unsigned char uartStatus;
88 
89  uartStatus = uread(uart, LSR);
90  uartStatus = uread(uart, RBR);
91}
92#endif
93
94/*
95 * Uart initialization, it is hardcoded to 8 bit, no parity,
96 * one stop bit, FIFO, things to be changed
97 * are baud rate and nad hw flow control,
98 * and longest rx fifo setting
99 */
100void
101BSP_uart_init(int uart, int baud, int hwFlow)
102{
103  unsigned char tmp;
104 
105  /* Sanity check */
106  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
107 
108  switch(baud)
109    {
110    case 50:
111    case 75:
112    case 110:
113    case 134:
114    case 300:
115    case 600:
116    case 1200:
117    case 2400:
118    case 9600:
119    case 19200:
120    case 38400:
121    case 57600:
122    case 115200:
123      break;
124    default:
125      assert(0);
126      return;
127    }
128 
129  /* Set DLAB bit to 1 */
130  uwrite(uart, LCR, DLAB);
131 
132  /* Set baud rate */
133  uwrite(uart, DLL,  (BSPBaseBaud/baud) & 0xff); 
134  uwrite(uart, DLM,  ((BSPBaseBaud/baud) >> 8) & 0xff); 
135
136  /* 8-bit, no parity , 1 stop */
137  uwrite(uart, LCR, CHR_8_BITS);
138 
139
140  /* Set DTR, RTS and OUT2 high */
141  uwrite(uart, MCR, DTR | RTS | OUT_2);
142
143  /* Enable FIFO */
144  uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12); 
145
146  /* Disable Interrupts */
147  uwrite(uart, IER, 0);
148
149  /* Read status to clear them */
150  tmp = uread(uart, LSR);
151  tmp = uread(uart, RBR);
152  tmp = uread(uart, MSR);
153
154  /* Remember state */
155  uart_data[uart].hwFlow     = hwFlow;
156  uart_data[uart].baud       = baud;
157  return;
158}
159
160/*
161 * Set baud
162 */
163void
164BSP_uart_set_baud(int uart, int baud)
165{
166  unsigned char mcr, ier;
167
168  /* Sanity check */
169  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
170 
171  /*
172   * This function may be called whenever TERMIOS parameters
173   * are changed, so we have to make sire that baud change is
174   * indeed required
175   */
176
177  if(baud == uart_data[uart].baud)
178    {
179      return;
180    }
181
182  mcr = uread(uart, MCR);
183  ier = uread(uart, IER);
184
185  BSP_uart_init(uart, baud, uart_data[uart].hwFlow);
186
187  uwrite(uart, MCR, mcr);
188  uwrite(uart, IER, ier);
189 
190  return;
191}
192
193/*
194 * Enable/disable interrupts
195 */
196void 
197BSP_uart_intr_ctrl(int uart, int cmd)
198{
199
200  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
201
202  switch(cmd)
203    {
204    case BSP_UART_INTR_CTRL_DISABLE:
205      uwrite(uart, IER, INTERRUPT_DISABLE);
206      break;
207    case BSP_UART_INTR_CTRL_ENABLE:
208      if(uart_data[uart].hwFlow)
209        {
210          uwrite(uart, IER,
211                 (RECEIVE_ENABLE  |
212                  TRANSMIT_ENABLE |
213                  RECEIVER_LINE_ST_ENABLE |
214                  MODEM_ENABLE
215                 )
216                );
217        }
218      else
219        {
220          uwrite(uart, IER,
221                 (RECEIVE_ENABLE  |
222                  TRANSMIT_ENABLE |
223                  RECEIVER_LINE_ST_ENABLE
224                 )
225                );
226        }
227      break;
228    case BSP_UART_INTR_CTRL_TERMIOS:
229      if(uart_data[uart].hwFlow)
230        {
231          uwrite(uart, IER,
232                 (RECEIVE_ENABLE  |
233                  RECEIVER_LINE_ST_ENABLE |
234                  MODEM_ENABLE
235                 )
236                );
237        }
238      else
239        {
240          uwrite(uart, IER,
241                 (RECEIVE_ENABLE  |
242                  RECEIVER_LINE_ST_ENABLE
243                 )
244                );
245        }
246      break;
247    case BSP_UART_INTR_CTRL_GDB:
248      uwrite(uart, IER, RECEIVE_ENABLE);
249      break;
250    default:
251      assert(0);
252      break;
253    }
254 
255  return;
256}
257
258void
259BSP_uart_throttle(int uart)
260{
261  unsigned int mcr;
262 
263  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
264
265  if(!uart_data[uart].hwFlow)
266    {
267      /* Should not happen */
268      assert(0);
269      return;
270    }
271  mcr = uread (uart, MCR);
272  /* RTS down */
273  mcr &= ~RTS;
274  uwrite(uart, MCR, mcr);
275
276  return;
277}
278
279void
280BSP_uart_unthrottle(int uart)
281{
282  unsigned int mcr;
283
284  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
285
286  if(!uart_data[uart].hwFlow)
287    {
288      /* Should not happen */
289      assert(0);
290      return;
291    }
292  mcr = uread (uart, MCR);
293  /* RTS up */
294  mcr |= RTS;
295  uwrite(uart, MCR, mcr);
296
297  return;
298}
299
300/*
301 * Status function, -1 if error
302 * detected, 0 if no received chars available,
303 * 1 if received char available, 2 if break
304 * is detected, it will eat break and error
305 * chars. It ignores overruns - we cannot do
306 * anything about - it execpt count statistics
307 * and we are not counting it.
308 */
309int 
310BSP_uart_polled_status(int uart)
311{
312  unsigned char val;
313
314  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
315
316  val = uread(uart, LSR);
317
318  if(val & BI)
319    {
320      /* BREAK found, eat character */
321      uread(uart, RBR);
322      return BSP_UART_STATUS_BREAK;
323    }
324
325  if((val & (DR | OE | FE)) ==  1)
326    {
327      /* No error, character present */ 
328      return BSP_UART_STATUS_CHAR;
329    }
330
331  if((val & (DR | OE | FE)) == 0)
332    {
333      /* Nothing */
334      return BSP_UART_STATUS_NOCHAR;
335    }
336
337  /*
338   * Framing or parity error
339   * eat character
340   */
341  uread(uart, RBR);
342 
343  return BSP_UART_STATUS_ERROR;
344}
345
346
347/*
348 * Polled mode write function
349 */
350void 
351BSP_uart_polled_write(int uart, int val)
352{
353  unsigned char val1;
354 
355  /* Sanity check */
356  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
357 
358  for(;;)
359    {
360      if((val1=uread(uart, LSR)) & THRE)
361        {
362          break;
363        }
364    }
365
366  if(uart_data[uart].hwFlow)
367    {
368      for(;;)
369        {
370          if(uread(uart, MSR) & CTS)
371            {
372              break;
373            }
374        }
375    }
376
377  uwrite(uart, THR, val & 0xff);
378     
379  return;
380}
381
382void
383BSP_output_char_via_serial(int val)
384{
385  BSP_uart_polled_write(BSPConsolePort, val);
386  if (val == '\n') BSP_uart_polled_write(BSPConsolePort,'\r');
387}
388
389/*
390 * Polled mode read function
391 */
392int 
393BSP_uart_polled_read(int uart)
394{
395  unsigned char val;
396
397  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
398 
399  for(;;)
400    {
401      if(uread(uart, LSR) & DR)
402        {
403          break;
404        }
405    }
406 
407  val = uread(uart, RBR);
408
409  return (int)(val & 0xff);
410}
411
412unsigned 
413BSP_poll_char_via_serial()
414{
415        return BSP_uart_polled_read(BSPConsolePort);
416}
417
418
419/* ================ Termios support  =================*/
420
421static volatile int  termios_stopped_com1        = 0;
422static volatile int  termios_tx_active_com1      = 0;
423static void*         termios_ttyp_com1           = NULL;
424static char          termios_tx_hold_com1        = 0;
425static volatile char termios_tx_hold_valid_com1  = 0;
426
427static volatile int  termios_stopped_com2        = 0;
428static volatile int  termios_tx_active_com2      = 0;
429static void*         termios_ttyp_com2           = NULL;
430static char          termios_tx_hold_com2        = 0;
431static volatile char termios_tx_hold_valid_com2  = 0;
432
433/*
434 * Set channel parameters
435 */
436void
437BSP_uart_termios_set(int uart, void *ttyp)
438{
439  unsigned char val;
440  assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2);
441 
442  if(uart == BSP_UART_COM1)
443    {
444      if(uart_data[uart].hwFlow)
445        {
446          val = uread(uart, MSR);
447
448          termios_stopped_com1   = (val & CTS) ? 0 : 1;
449        }
450      else
451        {
452          termios_stopped_com1 = 0;
453        }
454      termios_tx_active_com1      = 0;
455      termios_ttyp_com1           = ttyp;
456      termios_tx_hold_com1        = 0; 
457      termios_tx_hold_valid_com1  = 0;
458    }
459  else
460    {
461      if(uart_data[uart].hwFlow)
462        {
463          val = uread(uart, MSR);
464
465          termios_stopped_com2   = (val & CTS) ? 0 : 1;
466        }
467      else
468        {
469          termios_stopped_com2 = 0;
470        }
471      termios_tx_active_com2      = 0;
472      termios_ttyp_com2           = ttyp;
473      termios_tx_hold_com2        = 0; 
474      termios_tx_hold_valid_com2  = 0;
475    }
476
477  return;
478}
479
480int
481BSP_uart_termios_write_com1(int minor, const char *buf, int len)
482{
483  assert(buf != NULL);
484
485  if(len <= 0)
486    {
487      return 0;
488    }
489
490  /* If there TX buffer is busy - something is royally screwed up */
491  /*   assert((uread(BSP_UART_COM1, LSR) & THRE) != 0); */
492       
493
494  if(termios_stopped_com1)
495    {
496      /* CTS low */
497      termios_tx_hold_com1       = *buf;
498      termios_tx_hold_valid_com1 = 1;
499      return 0;
500    }
501
502  /* Write character */
503  uwrite(BSP_UART_COM1, THR, *buf & 0xff);
504
505  /* Enable interrupts if necessary */
506  if(!termios_tx_active_com1 && uart_data[BSP_UART_COM1].hwFlow)
507    {
508      termios_tx_active_com1 = 1;
509      uwrite(BSP_UART_COM1, IER,
510             (RECEIVE_ENABLE  |
511              TRANSMIT_ENABLE |
512              RECEIVER_LINE_ST_ENABLE |
513              MODEM_ENABLE
514             )
515            );
516    }
517  else if(!termios_tx_active_com1)
518    {
519      termios_tx_active_com1 = 1;
520      uwrite(BSP_UART_COM1, IER, 
521             (RECEIVE_ENABLE  |
522              TRANSMIT_ENABLE |
523              RECEIVER_LINE_ST_ENABLE
524             )
525            );
526    }
527
528  return 0;
529}
530
531int
532BSP_uart_termios_write_com2(int minor, const char *buf, int len)
533{
534  assert(buf != NULL);
535
536  if(len <= 0)
537    {
538      return 0;
539    }
540
541
542  /* If there TX buffer is busy - something is royally screwed up */
543  assert((uread(BSP_UART_COM2, LSR) & THRE) != 0);
544
545  if(termios_stopped_com2)
546    {
547      /* CTS low */
548      termios_tx_hold_com2       = *buf;
549      termios_tx_hold_valid_com2 = 1;
550      return 0;
551    }
552
553  /* Write character */
554
555  uwrite(BSP_UART_COM2, THR, *buf & 0xff);
556
557  /* Enable interrupts if necessary */
558  if(!termios_tx_active_com2 && uart_data[BSP_UART_COM2].hwFlow)
559    {
560      termios_tx_active_com2 = 1;
561      uwrite(BSP_UART_COM2, IER,
562             (RECEIVE_ENABLE  |
563              TRANSMIT_ENABLE |
564              RECEIVER_LINE_ST_ENABLE |
565              MODEM_ENABLE
566             )
567            );
568    }
569  else if(!termios_tx_active_com2)
570    {
571      termios_tx_active_com2 = 1;
572      uwrite(BSP_UART_COM2, IER,
573             (RECEIVE_ENABLE  |
574              TRANSMIT_ENABLE |
575              RECEIVER_LINE_ST_ENABLE
576             )
577            );
578    }
579
580  return 0;
581}
582
583
584void
585BSP_uart_termios_isr_com1(void)
586{
587  unsigned char buf[40];
588  unsigned char val;
589  int      off, ret, vect;
590
591  off = 0;
592
593  for(;;)
594    {
595      vect = uread(BSP_UART_COM1, IIR) & 0xf;
596     
597      switch(vect)
598        {
599        case MODEM_STATUS :
600          val = uread(BSP_UART_COM1, MSR);
601          if(uart_data[BSP_UART_COM1].hwFlow)
602            {
603              if(val & CTS)
604                {
605                  /* CTS high */
606                  termios_stopped_com1 = 0;
607                  if(termios_tx_hold_valid_com1)
608                    {
609                      termios_tx_hold_valid_com1 = 0;
610                      BSP_uart_termios_write_com1(0, &termios_tx_hold_com1,
611                                                    1);
612                    }
613                }
614              else
615                {
616                  /* CTS low */
617                  termios_stopped_com1 = 1;
618                }
619            }
620          break;
621        case NO_MORE_INTR :
622          /* No more interrupts */
623          if(off != 0)
624            {
625              /* Update rx buffer */
626              rtems_termios_enqueue_raw_characters(termios_ttyp_com1,
627                                                   (char *)buf,
628                                                   off);
629            }
630          return;
631        case TRANSMITTER_HODING_REGISTER_EMPTY :
632          /*
633           * TX holding empty: we have to disable these interrupts
634           * if there is nothing more to send.
635           */
636
637          ret = rtems_termios_dequeue_characters(termios_ttyp_com1, 1);
638
639          /* If nothing else to send disable interrupts */
640          if(ret == 0 && uart_data[BSP_UART_COM1].hwFlow)
641            {
642              uwrite(BSP_UART_COM1, IER,
643                     (RECEIVE_ENABLE  |
644                      RECEIVER_LINE_ST_ENABLE |
645                      MODEM_ENABLE
646                     )
647                    );
648              termios_tx_active_com1 = 0;
649            }
650          else if(ret == 0)
651            {
652              uwrite(BSP_UART_COM1, IER,
653                     (RECEIVE_ENABLE  |
654                      RECEIVER_LINE_ST_ENABLE
655                     )
656                    );
657              termios_tx_active_com1 = 0;
658            }
659          break;
660        case RECEIVER_DATA_AVAIL :
661        case CHARACTER_TIMEOUT_INDICATION:
662          /* RX data ready */
663          assert(off < sizeof(buf));
664          buf[off++] = uread(BSP_UART_COM1, RBR);
665          break;
666        case RECEIVER_ERROR:
667          /* RX error: eat character */
668           uartError(BSP_UART_COM1);
669          break;
670        default:
671          /* Should not happen */
672          assert(0);
673          return;
674        }
675    }
676}
677         
678void
679BSP_uart_termios_isr_com2()
680{
681  unsigned char buf[40];
682  unsigned char val;
683  int      off, ret, vect;
684
685  off = 0;
686
687  for(;;)
688    {
689      vect = uread(BSP_UART_COM2, IIR) & 0xf;
690     
691      switch(vect)
692        {
693        case MODEM_STATUS :
694          val = uread(BSP_UART_COM2, MSR);
695          if(uart_data[BSP_UART_COM2].hwFlow)
696            {
697              if(val & CTS)
698                {
699                  /* CTS high */
700                  termios_stopped_com2 = 0;
701                  if(termios_tx_hold_valid_com2)
702                    {
703                      termios_tx_hold_valid_com2 = 0;
704                      BSP_uart_termios_write_com2(0, &termios_tx_hold_com2,
705                                                    1);
706                    }
707                }
708              else
709                {
710                  /* CTS low */
711                  termios_stopped_com2 = 1;
712                }
713            }
714          break;
715        case NO_MORE_INTR :
716          /* No more interrupts */
717          if(off != 0)
718            {
719              /* Update rx buffer */
720              rtems_termios_enqueue_raw_characters(termios_ttyp_com2,
721                                                   (char *)buf,
722                                                   off);
723            }
724          return;
725        case TRANSMITTER_HODING_REGISTER_EMPTY :
726          /*
727           * TX holding empty: we have to disable these interrupts
728           * if there is nothing more to send.
729           */
730
731          ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1);
732
733          /* If nothing else to send disable interrupts */
734          if(ret == 0 && uart_data[BSP_UART_COM2].hwFlow)
735            {
736              uwrite(BSP_UART_COM2, IER,
737                     (RECEIVE_ENABLE  |
738                      RECEIVER_LINE_ST_ENABLE |
739                      MODEM_ENABLE
740                     )
741                    );
742              termios_tx_active_com2 = 0;
743            }
744          else if(ret == 0)
745            {
746              uwrite(BSP_UART_COM2, IER,
747                     (RECEIVE_ENABLE  |
748                      RECEIVER_LINE_ST_ENABLE
749                     )
750                    );
751              termios_tx_active_com2 = 0;
752            }
753          break;
754        case RECEIVER_DATA_AVAIL :
755        case CHARACTER_TIMEOUT_INDICATION:
756          /* RX data ready */
757          assert(off < sizeof(buf));
758          buf[off++] = uread(BSP_UART_COM2, RBR);
759          break;
760        case RECEIVER_ERROR:
761          /* RX error: eat character */
762           uartError(BSP_UART_COM2);
763          break;
764        default:
765          /* Should not happen */
766          assert(0);
767          return;
768        }
769    }
770}
771         
772 
773
774
775
776
777
778
Note: See TracBrowser for help on using the repository browser.