source: rtems/c/src/lib/libbsp/mips/genmongoosev/console/mg5uart.c @ 8536b67

4.115
Last change on this file since 8536b67 was 8536b67, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 8, 2014 at 8:06:52 PM

Move Mongoose-V specific devices into BSP.

Putting the duart in libcpu was very optimistic and presumptuous.
It has never been used again on another SoC and is BSP specific.

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