Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:49

0001 /*
0002  *  Driver for AT91RM9200 USART ports
0003  */
0004 
0005 /*
0006  * COPYRIGHT (c) 2006-2009.
0007  * NCB - Sistemas Embarcados Ltda. (Brazil)
0008  * Fernando Nicodemos <fgnicodemos@terra.com.br>
0009  *
0010  * and
0011  *
0012  * COPYRIGHT (c) 1989-2009.
0013  * On-Line Applications Research Corporation (OAR).
0014  *
0015  *  The license and distribution terms for this file may be
0016  *  found in the file LICENSE in this distribution or at
0017  *  http://www.rtems.org/license/LICENSE.
0018 */
0019 
0020 #include <bsp.h>
0021 #include <rtems/libio.h>
0022 #include <termios.h>
0023 
0024 #include <at91rm9200.h>
0025 #include <at91rm9200_usart.h>
0026 #include <at91rm9200_pmc.h>
0027 #include <rtems/bspIo.h>
0028 #include <libchip/serial.h>
0029 #include <libchip/sersupp.h>
0030 
0031 /* static function prototypes */
0032 static int     usart_first_open(int major, int minor, void *arg);
0033 static int     usart_last_close(int major, int minor, void *arg);
0034 static int     usart_read_polled(int minor);
0035 static ssize_t usart_write_polled_support(int minor, const char *buf, size_t len);
0036 static void    usart_init(int minor);
0037 static void    usart_write_polled(int minor, char c);
0038 static int     usart_set_attributes(int minor, const struct termios *t);
0039 at91rm9200_usart_regs_t *usart_get_base(int minor);
0040 
0041 /* Pointers to functions for handling the UART polled. */
0042 const console_fns usart_polling_fns = {
0043   libchip_serial_default_probe,       /* deviceProbe */
0044   usart_first_open,                   /* deviceFirstOpen */
0045   usart_last_close,                   /* deviceLastClose */
0046   usart_read_polled,                  /* deviceRead */
0047   usart_write_polled_support,         /* deviceWrite */
0048   usart_init,                         /* deviceInitialize */
0049   usart_write_polled,                 /* deviceWritePolled */
0050   usart_set_attributes,               /* deviceSetAttributes */
0051   FALSE                 /* TRUE if interrupt driven, FALSE if not. */
0052 };
0053 
0054 at91rm9200_usart_regs_t *usart_get_base(int minor)
0055 {
0056   console_tbl *console_entry;
0057   at91rm9200_usart_regs_t *port;
0058 
0059   console_entry = BSP_get_uart_from_minor(minor);
0060 
0061   if (console_entry == NULL)
0062     return 0;
0063 
0064   port = (at91rm9200_usart_regs_t *) console_entry->ulCtrlPort1;
0065   //printk( "minor=%d entry=%p port=%p\n", minor, console_entry, port );
0066 
0067   return port;
0068 }
0069 
0070 /*
0071  * Functions called via callbacks (i.e. the ones in uart_fns
0072  */
0073 
0074 /*
0075  * This is called the first time each device is opened. Since
0076  * the driver is polled, we don't have to do anything. If the driver
0077  * were interrupt driven, we'd enable interrupts here.
0078  */
0079 static int usart_first_open(int major, int minor, void *arg)
0080 {
0081   at91rm9200_usart_regs_t *usart;
0082 
0083   usart = usart_get_base(minor);
0084   if ( !usart )
0085     return -1;
0086 
0087   /* XXX port isn't being initialized or enabled */
0088 
0089   /* XXX I hope this is enough */
0090   usart->cr = (US_CR_RXEN | US_CR_TXEN);
0091   return 0;
0092 }
0093 
0094 /*
0095  * This is called the last time each device is closed.  Since
0096  * the driver is polled, we don't have to do anything. If the driver
0097  * were interrupt driven, we'd disable interrupts here.
0098  */
0099 static int usart_last_close(int major, int minor, void *arg)
0100 {
0101   at91rm9200_usart_regs_t *usart;
0102 
0103   usart = usart_get_base(minor);
0104   if ( !usart )
0105     return -1;
0106 
0107   return 0;
0108 }
0109 
0110 /*
0111  * Read one character from UART.
0112  *
0113  * return -1 if there's no data, otherwise return
0114  * the character in lowest 8 bits of returned int.
0115  */
0116 static int usart_read_polled(int minor)
0117 {
0118   at91rm9200_usart_regs_t *usart;
0119 
0120   usart = usart_get_base(minor);
0121   if ( !usart )
0122     return -1;
0123 
0124   /* if nothing ready return -1 */
0125   if ( (usart->sr & US_IER_RXRDY) == 0 )
0126     return -1;
0127 
0128   return usart->rhr;
0129 }
0130 
0131 
0132 /*
0133  *  Write character out
0134  */
0135 static void usart_write_polled(int minor, char c)
0136 {
0137   at91rm9200_usart_regs_t *usart;
0138 
0139   usart = usart_get_base(minor);
0140   if ( !usart )
0141     return;
0142 
0143   /* delay until TX empty */
0144   while ( (usart->sr & US_IER_TXEMPTY) == 0 )
0145     ;
0146 
0147   usart->thr = c;
0148 }
0149 
0150 /*
0151  * Write buffer to UART
0152  *
0153  * return 1 on success, -1 on error
0154  */
0155 static ssize_t usart_write_polled_support(int minor, const char *buf, size_t len)
0156 {
0157   at91rm9200_usart_regs_t *usart;
0158   int nwrite=0;
0159 
0160   /*
0161    *  Verify the minor number
0162    */
0163   usart = usart_get_base(minor);
0164   if ( !usart )
0165     return -1;
0166 
0167   /*
0168    * poll each byte in the string out of the port.
0169    */
0170   while (nwrite < len) {
0171     usart_write_polled(minor, *buf++);
0172     nwrite++;
0173   }
0174 
0175   /*
0176    * return the number of bytes written.
0177    */
0178   return nwrite;
0179 
0180   return 1;
0181 }
0182 
0183 
0184 /* Set up the UART. */
0185 static void usart_init(int minor)
0186 {
0187   at91rm9200_usart_regs_t *usart;
0188 
0189   usart = usart_get_base(minor);
0190   if ( !usart )
0191     return;
0192 
0193 }
0194 
0195 
0196 /* This is for setting baud rate, bits, etc. */
0197 static int usart_set_attributes(int minor, const struct termios *t)
0198 {
0199   uint32_t      brgr;
0200   uint32_t      mode, baud, baud_requested;
0201   at91rm9200_usart_regs_t *usart;
0202 
0203   usart = usart_get_base(minor);
0204   if ( !usart )
0205     return -1;
0206 
0207   /* Get current mode register */
0208   mode = usart->mr & ~(US_MR_USMODE | US_MR_USCLKS | US_MR_CHRL
0209             | US_MR_PAR | US_MR_NBSTOP);
0210 
0211   /* Byte size */
0212   switch (t->c_cflag & CSIZE){
0213   case CS5:
0214     mode |= US_MR_CHRL_5;
0215     break;
0216   case CS6:
0217     mode |= US_MR_CHRL_6;
0218     break;
0219   case CS7:
0220     mode |= US_MR_CHRL_7;
0221     break;
0222   default:
0223     mode |= US_MR_CHRL_8;
0224     break;
0225   }
0226 
0227   /* Stop bits */
0228   if (t->c_cflag & CSTOPB){
0229     mode |= US_MR_NBSTOP_2; /* 2 stop bits */
0230   } else
0231     mode |= US_MR_NBSTOP_1;     /* 1 stop bits */
0232 
0233   /* Parity */
0234   if (t->c_cflag & PARENB){
0235       /* Mark or Space parity */
0236       if (t->c_cflag & PARODD){
0237     mode |= US_MR_PAR_ODD;
0238       } else
0239     mode |= US_MR_PAR_EVEN;
0240    } else
0241     mode |= US_MR_PAR_NONE;
0242 
0243   baud_requested = t->c_ospeed;
0244 
0245   /* If not, set the dbgu console baud as USART baud default */
0246   if (!baud_requested)
0247     baud_requested = BSP_get_baud();
0248 
0249   baud = rtems_termios_baud_to_number(baud_requested);
0250 
0251   brgr = (at91rm9200_get_mck() / 16) / baud;
0252 
0253     if (brgr > 65535){    /* BRGR is 16-bit, so switch to slower clock */
0254         brgr /= 8;
0255         mode |= US_MR_USCLKS_MCK_DIV8;
0256     }
0257 
0258   usart->mr = mode;
0259   usart->brgr = brgr;
0260   return 0;
0261 }