source: rtems/c/src/lib/libcpu/mips/mongoosev/duart/mg5uart.c @ c8bd3cd

4.115
Last change on this file since c8bd3cd was c8bd3cd, checked in by Sebastian Huber <sebastian.huber@…>, on 02/08/13 at 12:39:59

libchip/serial: Add const qualifier

  • Property mode set to 100644
File size: 20.6 KB
Line 
1/**
2 *  @file
3 * 
4 *  This file contains the termios TTY driver for the UART found
5 *  on the Synova Mongoose-V.
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2012.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 */
16
17#include <rtems.h>
18#include <rtems/libio.h>
19#include <stdlib.h>
20
21#include <libchip/serial.h>
22#include <libchip/mg5uart.h>
23#include <libchip/sersupp.h>
24#include <libcpu/mongoose-v.h>
25
26#include <bsp/irq.h>
27#include <bsp.h>
28
29/*
30 *  Indices of registers
31 */
32
33/*
34 *  Per chip context control
35 */
36
37typedef struct _mg5uart_context
38{
39  int            mate;
40} mg5uart_context;
41
42/*
43 *  Define MG5UART_STATIC to nothing while debugging so the entry points
44 *  will show up in the symbol table.
45 */
46
47#define MG5UART_STATIC
48
49/* #define MG5UART_STATIC static */
50
51
52
53#define MG5UART_SETREG( _base, _register, _value ) \
54        MONGOOSEV_WRITE_REGISTER( _base, _register, _value )
55
56#define MG5UART_GETREG( _base, _register ) \
57        MONGOOSEV_READ_REGISTER( _base, _register )
58
59
60/*
61 *  Console Device Driver Support Functions
62 */
63
64MG5UART_STATIC int mg5uart_baud_rate(
65  int        minor,
66  uint32_t   baud,
67  uint32_t  *code
68);
69
70MG5UART_STATIC void mg5uart_enable_interrupts(
71  int minor,
72  int mask
73);
74
75/*
76 *  mg5uart_isr_XXX
77 *
78 *  This is the single interrupt entry point which parcels interrupts
79 *  out to the handlers for specific sources and makes sure that the
80 *  shared handler gets the right arguments.
81 *
82 *  NOTE: Yes .. this is ugly but it provides 5 interrupt source
83 *  wrappers which are nearly functionally identical.
84 */
85
86
87extern void mips_default_isr(int vector);
88
89#define __ISR(_TYPE, _OFFSET) \
90  MG5UART_STATIC void mg5uart_process_isr_ ## _TYPE ( \
91    int  minor \
92  ); \
93  \
94  MG5UART_STATIC rtems_isr mg5uart_isr_ ## _TYPE ( \
95    void *arg \
96  ) \
97  { \
98    rtems_vector_number vector = (rtems_vector_number) arg; \
99    int   minor; \
100    \
101    for(minor=0 ; minor<Console_Port_Count ; minor++) { \
102      if( Console_Port_Tbl[minor]->deviceType == SERIAL_MG5UART && \
103          vector == Console_Port_Tbl[minor]->ulIntVector + _OFFSET ) { \
104        mg5uart_process_isr_ ## _TYPE (minor); \
105        return; \
106      } \
107    } \
108    mips_default_isr( vector ); \
109  }
110
111__ISR(rx_frame_error, MG5UART_IRQ_RX_FRAME_ERROR)
112__ISR(rx_overrun_error, MG5UART_IRQ_RX_OVERRUN_ERROR)
113__ISR(tx_empty, MG5UART_IRQ_TX_EMPTY)
114__ISR(tx_ready, MG5UART_IRQ_TX_READY)
115__ISR(rx_ready, MG5UART_IRQ_RX_READY)
116
117/*
118 *  mg5uart_set_attributes
119 *
120 *  This function sets the UART channel to reflect the requested termios
121 *  port settings.
122 */
123
124MG5UART_STATIC int mg5uart_set_attributes(
125  int minor,
126  const struct termios *t
127)
128{
129  uint32_t               pMG5UART_port;
130  uint32_t               pMG5UART;
131  uint32_t               cmd, cmdSave;
132  uint32_t               baudcmd;
133  uint32_t               shift;
134  rtems_interrupt_level  Irql;
135
136  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
137  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
138
139  /*
140   *  Set the baud rate
141   */
142
143  if (mg5uart_baud_rate( minor, t->c_cflag, &baudcmd ) == -1)
144    return -1;
145
146  /*
147   *  Base settings
148   */
149
150  /*
151   *  Base settings
152   */
153
154  cmd = MONGOOSEV_UART_CMD_RX_ENABLE | MONGOOSEV_UART_CMD_TX_ENABLE;
155
156  /*
157   *  Parity
158   */
159
160  if (t->c_cflag & PARENB) {
161    cmd |= MONGOOSEV_UART_CMD_PARITY_ENABLE;
162    if (t->c_cflag & PARODD)
163      cmd |= MONGOOSEV_UART_CMD_PARITY_ODD;
164    else
165      cmd |= MONGOOSEV_UART_CMD_PARITY_EVEN;
166  } else {
167    cmd |= MONGOOSEV_UART_CMD_PARITY_DISABLE;
168  }
169
170  /*
171   *  Character Size
172   */
173
174  if (t->c_cflag & CSIZE) {
175    switch (t->c_cflag & CSIZE) {
176      case CS5:
177      case CS6:
178      case CS7:
179        return -1;
180        break;
181      case CS8:
182        /* Mongoose-V only supports CS8 */
183        break;
184
185    }
186  } /* else default to CS8 */
187
188  /*
189   *  Stop Bits
190   */
191
192#if 0
193  if (t->c_cflag & CSTOPB) {
194    /* 2 stop bits not supported by Mongoose-V uart */
195    return -1;
196  }
197#endif
198
199  /*
200   *  XXX what about CTS/RTS
201   */
202
203  /* XXX */
204
205  /*
206   *  Now write the registers
207   */
208
209  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
210    shift = MONGOOSEV_UART0_CMD_SHIFT;
211  else
212    shift = MONGOOSEV_UART1_CMD_SHIFT;
213
214
215
216  rtems_interrupt_disable(Irql);
217
218  cmdSave = MG5UART_GETREG( pMG5UART, MG5UART_COMMAND_REGISTER );
219
220  MG5UART_SETREG( pMG5UART,
221                  MG5UART_COMMAND_REGISTER,
222                  (cmdSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (cmd << shift) );
223
224  MG5UART_SETREG( pMG5UART_port, MG5UART_BAUD_RATE, baudcmd );
225
226  rtems_interrupt_enable(Irql);
227  return 0;
228}
229
230/*
231 *  mg5uart_initialize_context
232 *
233 *  This function sets the default values of the per port context structure.
234 */
235
236MG5UART_STATIC void mg5uart_initialize_context(
237  int               minor,
238  mg5uart_context  *pmg5uartContext
239)
240{
241  int          port;
242  unsigned int pMG5UART;
243  unsigned int pMG5UART_port;
244
245  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
246  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
247
248  pmg5uartContext->mate = -1;
249
250  for (port=0 ; port<Console_Port_Count ; port++ ) {
251    if ( Console_Port_Tbl[port]->ulCtrlPort1 == pMG5UART &&
252         Console_Port_Tbl[port]->ulCtrlPort2 != pMG5UART_port ) {
253      pmg5uartContext->mate = port;
254      break;
255    }
256  }
257
258}
259
260/*
261 *  mg5uart_init
262 *
263 *  This function initializes the DUART to a quiecsent state.
264 */
265
266MG5UART_STATIC void mg5uart_init(int minor)
267{
268  uint32_t              pMG5UART_port;
269  uint32_t              pMG5UART;
270  uint32_t              cmdSave;
271  uint32_t              shift;
272
273  mg5uart_context        *pmg5uartContext;
274
275  pmg5uartContext = (mg5uart_context *) malloc(sizeof(mg5uart_context));
276
277  Console_Port_Data[minor].pDeviceContext = (void *)pmg5uartContext;
278
279  mg5uart_initialize_context( minor, pmg5uartContext );
280
281  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
282  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
283
284  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
285     shift = MONGOOSEV_UART0_CMD_SHIFT;
286  else
287     shift = MONGOOSEV_UART1_CMD_SHIFT;
288
289  /*
290   *  Disable the uart and leave this port disabled.
291   */
292
293  cmdSave = MG5UART_GETREG(pMG5UART, MG5UART_COMMAND_REGISTER) & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift);
294
295  MG5UART_SETREG( pMG5UART, MG5UART_COMMAND_REGISTER, cmdSave );
296
297  /*
298   *  Disable interrupts on RX and TX for this port
299   */
300  mg5uart_enable_interrupts( minor, MG5UART_DISABLE_ALL );
301}
302
303/*
304 *  mg5uart_open
305 *
306 *  This function opens a port for communication.
307 *
308 *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
309 */
310
311MG5UART_STATIC int mg5uart_open(
312  int      major,
313  int      minor,
314  void    *arg
315)
316{
317  uint32_t      pMG5UART;
318  uint32_t      pMG5UART_port;
319  uint32_t      vector;
320  uint32_t      cmd, cmdSave;
321  uint32_t      baudcmd;
322  uint32_t      shift;
323
324  rtems_interrupt_level  Irql;
325
326  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
327  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
328  vector        = Console_Port_Tbl[minor]->ulIntVector;
329
330  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
331    shift = MONGOOSEV_UART0_CMD_SHIFT;
332  else
333    shift = MONGOOSEV_UART1_CMD_SHIFT;
334
335
336  /* XXX default baud rate could be from configuration table */
337
338  (void) mg5uart_baud_rate( minor, B19200, &baudcmd );
339
340  /*
341   *  Set the DUART channel to a default useable state
342   *  B19200, 8Nx since there is no stop bit control.
343   */
344
345  cmd = MONGOOSEV_UART_CMD_TX_ENABLE | MONGOOSEV_UART_CMD_RX_ENABLE;
346
347  rtems_interrupt_disable(Irql);
348
349  cmdSave = MG5UART_GETREG( pMG5UART, MG5UART_COMMAND_REGISTER );
350
351  MG5UART_SETREG( pMG5UART_port, MG5UART_BAUD_RATE, baudcmd );
352
353  MG5UART_SETREG( pMG5UART,
354                  MG5UART_COMMAND_REGISTER,
355                  cmd = (cmdSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (cmd << shift) );
356
357  rtems_interrupt_enable(Irql);
358
359  return RTEMS_SUCCESSFUL;
360}
361
362/*
363 *  mg5uart_close
364 *
365 *  This function shuts down the requested port.
366 */
367
368MG5UART_STATIC int mg5uart_close(
369  int      major,
370  int      minor,
371  void    *arg
372)
373{
374  uint32_t      pMG5UART;
375  uint32_t      pMG5UART_port;
376  uint32_t      cmd, cmdSave;
377  uint32_t      shift;
378  rtems_interrupt_level  Irql;
379
380  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
381  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
382
383  /*
384   *  Disable interrupts from this channel and then disable it totally.
385   */
386
387  /* XXX interrupts */
388
389  cmd = MONGOOSEV_UART_CMD_TX_DISABLE | MONGOOSEV_UART_CMD_RX_DISABLE;
390
391  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
392    shift = MONGOOSEV_UART0_CMD_SHIFT;
393  else
394    shift = MONGOOSEV_UART1_CMD_SHIFT;
395
396
397  rtems_interrupt_disable(Irql);
398  cmdSave = MG5UART_GETREG( pMG5UART, MG5UART_COMMAND_REGISTER );
399
400  MG5UART_SETREG( pMG5UART,
401                  MG5UART_COMMAND_REGISTER,
402                  (cmdSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (cmd << shift) );
403  rtems_interrupt_enable(Irql);
404
405  return(RTEMS_SUCCESSFUL);
406}
407
408
409
410
411/*
412 *  mg5uart_write_polled
413 *
414 *  This routine polls out the requested character.
415 */
416
417MG5UART_STATIC void mg5uart_write_polled(
418  int   minor,
419  char  c
420)
421{
422  uint32_t                pMG5UART;
423  uint32_t                pMG5UART_port;
424  uint32_t                status;
425  int                     shift;
426  int                     timeout;
427
428  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
429  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
430
431  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
432    shift = MONGOOSEV_UART0_IRQ_SHIFT;
433  else
434    shift = MONGOOSEV_UART1_IRQ_SHIFT;
435
436  /*
437   * wait for transmitter holding register to be empty
438   */
439  timeout = 2000;
440
441  while( --timeout )
442  {
443    status = MG5UART_GETREG(pMG5UART, MG5UART_STATUS_REGISTER) >> shift;
444
445    /*
446    if ( (status & (MONGOOSEV_UART_TX_READY | MONGOOSEV_UART_TX_EMPTY)) ==
447            (MONGOOSEV_UART_TX_READY | MONGOOSEV_UART_TX_EMPTY) )
448      break;
449    */
450
451    if( (status & (MONGOOSEV_UART_TX_READY | MONGOOSEV_UART_TX_EMPTY)) )
452       break;
453
454    /*
455     * Yield while we wait
456     */
457
458#if 0
459     if(_System_state_Is_up(_System_state_Get()))
460     {
461       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
462     }
463#endif
464  }
465
466  /*
467   * transmit character
468   */
469
470  MG5UART_SETREG(pMG5UART_port, MG5UART_TX_BUFFER, c);
471}
472
473MG5UART_STATIC void mg5uart_process_isr_rx_error(
474   int  minor,
475   uint32_t   mask
476)
477{
478  uint32_t                pMG5UART;
479  int                     shift;
480
481  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
482
483  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
484    shift = MONGOOSEV_UART0_IRQ_SHIFT;
485  else
486    shift = MONGOOSEV_UART1_IRQ_SHIFT;
487
488  /* now clear the error */
489
490  MG5UART_SETREG(
491     pMG5UART,
492     MG5UART_STATUS_REGISTER,
493     mask << shift );
494}
495
496
497MG5UART_STATIC void mg5uart_process_isr_rx_frame_error(
498  int  minor
499)
500{
501   mg5uart_process_isr_rx_error( minor, MONGOOSEV_UART_RX_FRAME_ERROR );
502}
503
504MG5UART_STATIC void mg5uart_process_isr_rx_overrun_error(
505  int  minor
506)
507{
508   mg5uart_process_isr_rx_error( minor, MONGOOSEV_UART_RX_OVERRUN_ERROR );
509}
510
511
512
513
514
515
516
517
518MG5UART_STATIC void mg5uart_process_tx_isr(
519   int        minor,
520   uint32_t   source
521)
522{
523   uint32_t        pMG5UART;
524   int             shift;
525
526   pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
527
528   mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL_EXCEPT_TX);
529
530   if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
531      shift = MONGOOSEV_UART0_IRQ_SHIFT;
532   else
533      shift = MONGOOSEV_UART1_IRQ_SHIFT;
534
535   MG5UART_SETREG(
536      pMG5UART,
537      MG5UART_STATUS_REGISTER,
538      source << shift );
539
540   if( rtems_termios_dequeue_characters( Console_Port_Data[minor].termios_data, 1) )
541   {
542      mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL);
543      return;
544   }
545
546   /*
547    *  There are no more characters to transmit.  The tx interrupts are be cleared
548    *  by writing data to the uart, so just disable the tx interrupt sources.
549    */
550
551   Console_Port_Data[minor].bActive = FALSE;
552
553   /* mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL_EXCEPT_TX); */
554}
555
556
557
558MG5UART_STATIC void mg5uart_process_isr_tx_empty(
559  int  minor
560)
561{
562   /* mg5uart_process_tx_isr( minor, MONGOOSEV_UART_TX_EMPTY ); */
563}
564
565MG5UART_STATIC void mg5uart_process_isr_tx_ready(
566  int  minor
567)
568{
569   mg5uart_process_tx_isr( minor, MONGOOSEV_UART_TX_READY );
570}
571
572
573
574
575
576MG5UART_STATIC void mg5uart_process_isr_rx_ready(
577  int  minor
578)
579{
580  uint32_t   pMG5UART_port;
581  char       c;
582
583  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
584
585  /* reading the RX buffer automatically resets the interrupt flag */
586
587  c = (char) MG5UART_GETREG(pMG5UART_port, MG5UART_RX_BUFFER);
588
589  rtems_termios_enqueue_raw_characters(
590     Console_Port_Data[minor].termios_data,
591     &c, 1 );
592}
593
594static rtems_irq_connect_data mg5uart_rx_frame_error_cd  = {  \
595  0,                             /* filled in at initialization */
596  mg5uart_isr_rx_frame_error,   /* filled in at initialization */
597  NULL,   /* (void *) minor */
598  NULL,
599  NULL,
600  NULL
601};
602
603static rtems_irq_connect_data mg5uart_rx_overrun_error_cd  = {  \
604  0,                             /* filled in at initialization */
605  mg5uart_isr_rx_overrun_error,   /* filled in at initialization */
606  NULL,   /* (void *) minor */
607  NULL,
608  NULL,
609  NULL
610};
611
612static rtems_irq_connect_data mg5uart_tx_empty_cd  = {  \
613  0,                             /* filled in at initialization */
614  mg5uart_isr_tx_empty,   /* filled in at initialization */
615  NULL,   /* (void *) minor */
616  NULL,
617  NULL,
618  NULL
619};
620
621static rtems_irq_connect_data mg5uart_tx_ready_cd  = {  \
622  0,                             /* filled in at initialization */
623  mg5uart_isr_tx_ready,   /* filled in at initialization */
624  NULL,   /* (void *) minor */
625  NULL,
626  NULL,
627  NULL
628};
629
630static rtems_irq_connect_data mg5uart_rx_ready_cd  = {  \
631  0,                             /* filled in at initialization */
632  mg5uart_isr_rx_ready,   /* filled in at initialization */
633  NULL,   /* (void *) minor */
634  NULL,
635  NULL,
636  NULL
637};
638
639
640/*
641 *  mg5uart_initialize_interrupts
642 *
643 *  This routine initializes the console's receive and transmit
644 *  ring buffers and loads the appropriate vectors to handle the interrupts.
645 */
646
647MG5UART_STATIC void mg5uart_initialize_interrupts(int minor)
648{
649  unsigned long v;
650  mg5uart_init(minor);
651
652  Console_Port_Data[minor].bActive = FALSE;
653  v = Console_Port_Tbl[minor]->ulIntVector;
654
655  mg5uart_rx_frame_error_cd.name    =  v + MG5UART_IRQ_RX_FRAME_ERROR;
656  mg5uart_rx_overrun_error_cd.name  =  v + MG5UART_IRQ_RX_OVERRUN_ERROR;
657  mg5uart_tx_empty_cd.name          =  v + MG5UART_IRQ_TX_EMPTY; 
658  mg5uart_tx_ready_cd.name          =  v + MG5UART_IRQ_TX_READY;
659  mg5uart_rx_ready_cd.name          =  v + MG5UART_IRQ_RX_READY;
660
661  mg5uart_rx_frame_error_cd.handle    =  (void *)mg5uart_rx_frame_error_cd.name;
662  mg5uart_rx_overrun_error_cd.handle  =  (void *)mg5uart_rx_overrun_error_cd.name;
663  mg5uart_tx_empty_cd.handle          =  (void *)mg5uart_tx_empty_cd.name; 
664  mg5uart_tx_ready_cd.handle          =  (void *)mg5uart_tx_ready_cd.name;
665  mg5uart_rx_ready_cd.handle          =  (void *)mg5uart_rx_ready_cd.name;
666
667 
668  BSP_install_rtems_irq_handler( &mg5uart_rx_frame_error_cd );
669  BSP_install_rtems_irq_handler( &mg5uart_rx_overrun_error_cd );
670  BSP_install_rtems_irq_handler( &mg5uart_tx_empty_cd );
671  BSP_install_rtems_irq_handler( &mg5uart_tx_ready_cd );
672  BSP_install_rtems_irq_handler( &mg5uart_rx_ready_cd );
673
674  mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL_EXCEPT_TX);
675}
676
677/*
678 *  mg5uart_write_support_int
679 *
680 *  Console Termios output entry point when using interrupt driven output.
681 */
682
683MG5UART_STATIC int mg5uart_write_support_int(
684  int         minor,
685  const char *buf,
686  size_t      len
687)
688{
689  uint32_t        Irql;
690  uint32_t        pMG5UART_port;
691
692  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
693
694  /*
695   *  We are using interrupt driven output and termios only sends us
696   *  one character at a time.
697   */
698
699  if ( !len )
700     return 0;
701
702  /*
703   *  Put the character out and enable interrupts if necessary.
704   */
705
706  rtems_interrupt_disable(Irql);
707
708  MG5UART_SETREG(pMG5UART_port, MG5UART_TX_BUFFER, *buf);
709
710  if( Console_Port_Data[minor].bActive == FALSE )
711  {
712     Console_Port_Data[minor].bActive = TRUE;
713     mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL);
714  }
715
716  rtems_interrupt_enable(Irql);
717  return 1;
718}
719
720
721
722
723/*
724 *  mg5uart_write_support_polled
725 *
726 *  Console Termios output entry point when using polled output.
727 *
728 */
729
730MG5UART_STATIC ssize_t mg5uart_write_support_polled(
731  int         minor,
732  const char *buf,
733  size_t      len
734)
735{
736  int nwrite = 0;
737
738  /*
739   * poll each byte in the string out of the port.
740   */
741  while (nwrite < len)
742  {
743    mg5uart_write_polled(minor, *buf++);
744    nwrite++;
745  }
746
747  /*
748   * return the number of bytes written.
749   */
750  return nwrite;
751}
752
753/*
754 *  mg5uart_inbyte_nonblocking_polled
755 *
756 *  Console Termios polling input entry point.
757 */
758
759MG5UART_STATIC int mg5uart_inbyte_nonblocking_polled(
760  int minor
761)
762{
763  uint32_t                pMG5UART;
764  uint32_t                pMG5UART_port;
765  uint32_t                status;
766  uint32_t                tmp,shift;
767
768  pMG5UART      = Console_Port_Tbl[minor]->ulCtrlPort1;
769  pMG5UART_port = Console_Port_Tbl[minor]->ulCtrlPort2;
770
771  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
772    shift = MONGOOSEV_UART0_IRQ_SHIFT;
773  else
774    shift = MONGOOSEV_UART1_IRQ_SHIFT;
775
776  /* reset overrrun or framing errors */
777  status = MG5UART_GETREG(pMG5UART, MG5UART_STATUS_REGISTER) >> shift;
778
779  if( (tmp = (status & 0x3)) )
780  {
781     MG5UART_SETREG(pMG5UART, MG5UART_STATUS_REGISTER, (tmp << shift) );
782     status = MG5UART_GETREG(pMG5UART, MG5UART_STATUS_REGISTER) >> shift;
783  }
784
785  if ( status & MONGOOSEV_UART_RX_READY )
786  {
787     return (int) MG5UART_GETREG(pMG5UART_port, MG5UART_RX_BUFFER);
788  }
789  else
790  {
791     return -1;
792  }
793}
794
795/*
796 *  mg5uart_baud_rate
797 */
798
799MG5UART_STATIC int mg5uart_baud_rate(
800  int           minor,
801  uint32_t      baud,
802  uint32_t     *code
803)
804{
805  uint32_t   clock;
806  uint32_t   tmp_code;
807  uint32_t   baud_requested;
808
809  baud_requested = baud & CBAUD;
810  if (!baud_requested)
811    baud_requested = B9600;              /* default to 9600 baud */
812
813  baud_requested = rtems_termios_baud_to_number( baud_requested );
814
815  clock = (uint32_t) Console_Port_Tbl[minor]->ulClock;
816  if (!clock)
817    rtems_fatal_error_occurred(RTEMS_INVALID_NUMBER);
818
819  /*
820   *  Formula is Code = round(ClockFrequency / Baud - 1).
821   *
822   *  Since this is integer math, we will divide by twice the baud and
823   *  check the remaining odd bit.
824   */
825
826  tmp_code = (clock / baud_requested) - 1;
827
828  /*
829   *  From section 12.7, "Keep C>100 for best receiver operation."
830   *  That is 100 cycles which is not a lot of instructions.  It is
831   *  reasonable to think that the Mongoose-V could not keep
832   *  up with C < 100.
833   */
834
835  if ( tmp_code < 100 )
836    return RTEMS_INVALID_NUMBER;
837
838  /*
839   *  upper word is receiver baud and lower word is transmitter baud
840   */
841
842  *code = (tmp_code << 16) | tmp_code;
843
844  return 0;
845}
846
847
848
849
850/*
851 *  mg5uart_enable_interrupts
852 *
853 *  This function enables specific interrupt sources on the DUART.
854 */
855
856MG5UART_STATIC void mg5uart_enable_interrupts(
857  int minor,
858  int mask
859)
860{
861  uint32_t              pMG5UART;
862  uint32_t              maskSave;
863  uint32_t              shift;
864  rtems_interrupt_level  Irql;
865
866  pMG5UART = Console_Port_Tbl[minor]->ulCtrlPort1;
867
868  /*
869   *  Enable interrupts on RX and TX -- not break
870   */
871
872  if ( Console_Port_Tbl[minor]->ulDataPort == MG5UART_UART0 )
873    shift = MONGOOSEV_UART0_IRQ_SHIFT;
874  else
875    shift = MONGOOSEV_UART1_IRQ_SHIFT;
876
877
878  rtems_interrupt_disable(Irql);
879
880  maskSave = MG5UART_GETREG( pMG5UART, MG5UART_INTERRUPT_MASK_REGISTER );
881
882  MG5UART_SETREG(
883     pMG5UART,
884     MG5UART_INTERRUPT_MASK_REGISTER,
885     (maskSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (mask << shift) );
886
887  rtems_interrupt_enable(Irql);
888}
889
890
891
892/*
893 * Flow control is only supported when using interrupts
894 */
895
896const console_fns mg5uart_fns =
897{
898  libchip_serial_default_probe,   /* deviceProbe */
899  mg5uart_open,                   /* deviceFirstOpen */
900  NULL,                           /* deviceLastClose */
901  NULL,                           /* deviceRead */
902  mg5uart_write_support_int,      /* deviceWrite */
903  mg5uart_initialize_interrupts,  /* deviceInitialize */
904  mg5uart_write_polled,           /* deviceWritePolled */
905  mg5uart_set_attributes,         /* deviceSetAttributes */
906  TRUE                            /* deviceOutputUsesInterrupts */
907};
908
909const console_fns mg5uart_fns_polled =
910{
911  libchip_serial_default_probe,        /* deviceProbe */
912  mg5uart_open,                        /* deviceFirstOpen */
913  mg5uart_close,                       /* deviceLastClose */
914  mg5uart_inbyte_nonblocking_polled,   /* deviceRead */
915  mg5uart_write_support_polled,        /* deviceWrite */
916  mg5uart_init,                        /* deviceInitialize */
917  mg5uart_write_polled,                /* deviceWritePolled */
918  mg5uart_set_attributes,              /* deviceSetAttributes */
919  FALSE,                               /* deviceOutputUsesInterrupts */
920};
Note: See TracBrowser for help on using the repository browser.