source: rtems/c/src/lib/libcpu/arm/at91rm9200/usart/usart.c @ c193baad

4.104.11
Last change on this file since c193baad was c193baad, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Apr 9, 2010 at 8:24:57 PM

unify irq data types and code, merge s3c2400/s3c2410 support

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2 *  Driver for AT91RM9200 USART ports
3 *
4 * COPYRIGHT (c) 2006-2009.
5 * NCB - Sistemas Embarcados Ltda. (Brazil)
6 * Fernando Nicodemos <fgnicodemos@terra.com.br>
7 *
8 * and
9 *
10 * COPYRIGHT (c) 1989-2009.
11 * On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.com/license/LICENSE.
16 *
17 *  $Id$
18*/
19
20#include <bsp.h>
21#include <rtems/libio.h>
22#include <termios.h>
23
24#include <at91rm9200.h>
25#include <at91rm9200_usart.h>
26#include <at91rm9200_pmc.h>
27#include <rtems/bspIo.h>
28#include <libchip/serial.h>
29#include <libchip/sersupp.h>
30
31/* static function prototypes */
32static int     usart_first_open(int major, int minor, void *arg);
33static int     usart_last_close(int major, int minor, void *arg);
34static int     usart_read_polled(int minor);
35static int     usart_write_polled_support(int minor, const char *buf, int len);
36static void    usart_init(int minor);
37static void    usart_write_polled(int minor, char c);
38static int     usart_set_attributes(int minor, const struct termios *t);
39at91rm9200_usart_regs_t *usart_get_base(int minor);
40
41/* Pointers to functions for handling the UART polled. */
42console_fns usart_polling_fns = {
43  libchip_serial_default_probe,       /* deviceProbe */
44  usart_first_open,                   /* deviceFirstOpen */
45  usart_last_close,                   /* deviceLastClose */
46  usart_read_polled,                  /* deviceRead */
47  usart_write_polled_support,         /* deviceWrite */
48  usart_init,                         /* deviceInitialize */
49  usart_write_polled,                 /* deviceWritePolled */
50  usart_set_attributes,               /* deviceSetAttributes */
51  FALSE                 /* TRUE if interrupt driven, FALSE if not. */
52};
53
54at91rm9200_usart_regs_t *usart_get_base(int minor)
55{
56  console_tbl *console_entry;
57  at91rm9200_usart_regs_t *port;
58
59  console_entry = BSP_get_uart_from_minor(minor);
60
61  if (console_entry == NULL)
62    return 0;
63
64  port = (at91rm9200_usart_regs_t *) console_entry->ulCtrlPort1;
65  //printk( "minor=%d entry=%p port=%p\n", minor, console_entry, port );
66
67  return port;
68}
69
70/*
71 * Functions called via callbacks (i.e. the ones in uart_fns
72 */
73
74/*
75 * This is called the first time each device is opened. Since
76 * the driver is polled, we don't have to do anything. If the driver
77 * were interrupt driven, we'd enable interrupts here.
78 */
79static int usart_first_open(int major, int minor, void *arg)
80{
81  at91rm9200_usart_regs_t *usart;
82
83  usart = usart_get_base(minor);
84  if ( !usart )
85    return -1;
86
87  /* XXX port isn't being initialized or enabled */
88
89  /* XXX I hope this is enough */
90  usart->cr = (US_CR_RXEN | US_CR_TXEN);
91  return 0;
92}
93
94/*
95 * This is called the last time each device is closed.  Since
96 * the driver is polled, we don't have to do anything. If the driver
97 * were interrupt driven, we'd disable interrupts here.
98 */
99static int usart_last_close(int major, int minor, void *arg)
100{
101  at91rm9200_usart_regs_t *usart;
102
103  usart = usart_get_base(minor);
104  if ( !usart )
105    return -1;
106
107  return 0;
108}
109
110/*
111 * Read one character from UART.
112 *
113 * return -1 if there's no data, otherwise return
114 * the character in lowest 8 bits of returned int.
115 */
116static int usart_read_polled(int minor)
117{
118  at91rm9200_usart_regs_t *usart;
119
120  usart = usart_get_base(minor);
121  if ( !usart )
122    return -1;
123
124  /* if nothing ready return -1 */
125  if ( (usart->sr & US_IER_RXBUFF) == 0 )
126    return -1;
127
128  return usart->thr;
129}
130
131
132/*
133 *  Write character out
134 */
135static void usart_write_polled(int minor, char c)
136{
137  at91rm9200_usart_regs_t *usart;
138
139  usart = usart_get_base(minor);
140  if ( !usart )
141    return;
142
143  /* delay until TX empty */
144  while ( (usart->sr & US_IER_TXEMPTY) == 0 )
145    ;
146
147  usart->thr = c;
148}
149
150/*
151 * Write buffer to UART
152 *
153 * return 1 on success, -1 on error
154 */
155static int usart_write_polled_support(int minor, const char *buf, int len)
156{
157  at91rm9200_usart_regs_t *usart;
158  int nwrite=0;
159
160  /*
161   *  Verify the minor number
162   */
163  usart = usart_get_base(minor);
164  if ( !usart )
165    return -1;
166
167  /*
168   * poll each byte in the string out of the port.
169   */
170  while (nwrite < len) {
171    usart_write_polled(minor, *buf++);
172    nwrite++;
173  }
174
175  /*
176   * return the number of bytes written.
177   */
178  return nwrite;
179
180  return 1;
181}
182
183
184/* Set up the UART. */
185static void usart_init(int minor)
186{
187  at91rm9200_usart_regs_t *usart;
188
189  usart = usart_get_base(minor);
190  if ( !usart )
191    return;
192
193}
194
195
196/* This is for setting baud rate, bits, etc. */
197static int usart_set_attributes(int minor, const struct termios *t)
198{
199  uint32_t      brgr;
200  uint32_t      mode, baud, baud_requested;
201  at91rm9200_usart_regs_t *usart;
202
203  usart = usart_get_base(minor);
204  if ( !usart )
205    return -1;
206
207  /* Get current mode register */
208  mode = usart->mr & ~(US_MR_USMODE | US_MR_USCLKS | US_MR_CHRL
209                        | US_MR_PAR | US_MR_NBSTOP);
210
211  /* Byte size */
212  switch (t->c_cflag & CSIZE){
213  case CS5:
214    mode |= US_MR_CHRL_5;
215    break;
216  case CS6:
217    mode |= US_MR_CHRL_6;
218    break;
219  case CS7:
220    mode |= US_MR_CHRL_7;
221    break;
222  default:
223    mode |= US_MR_CHRL_8;
224    break;
225  }
226
227  /* Stop bits */
228  if (t->c_cflag & CSTOPB){
229        mode |= US_MR_NBSTOP_2; /* 2 stop bits */
230  } else
231    mode |= US_MR_NBSTOP_1;     /* 1 stop bits */
232
233  /* Parity */
234  if (t->c_cflag & PARENB){
235      /* Mark or Space parity */
236      if (t->c_cflag & PARODD){
237        mode |= US_MR_PAR_ODD;
238      } else
239        mode |= US_MR_PAR_EVEN;
240   } else
241        mode |= US_MR_PAR_NONE;
242
243  baud_requested = t->c_cflag & CBAUD;
244
245  /* If not, set the dbgu console baud as USART baud default */
246  if (!baud_requested)
247    baud_requested = BSP_get_baud();
248
249  baud = rtems_termios_baud_to_number(baud_requested);
250
251  brgr = (at91rm9200_get_mck() / 16) / baud;
252
253        if (brgr > 65535){    /* BRGR is 16-bit, so switch to slower clock */
254                brgr /= 8;
255                mode |= US_MR_USCLKS_MCK_DIV8;
256        }
257
258  usart->mr = mode;
259  usart->brgr = brgr;
260  return 0;
261}
262
263/*
264 * The following functions are not used by TERMIOS, but other RTEMS
265 * functions use them instead.
266 */
267
268/*
269 * Read from UART. This is used in the exit code, and can't
270 * rely on interrupts.
271 */
272int usart_poll_read(int minor)
273{
274  return usart_read_polled(minor);
275}
Note: See TracBrowser for help on using the repository browser.