File indexing completed on 2025-05-11 08:23:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <rtems.h>
0014 #include <rtems/libio.h>
0015 #include <rtems/termiostypes.h>
0016 #include <termios.h>
0017 #include <stdlib.h>
0018
0019 #include <libcpu/uartRegs.h>
0020 #include <libcpu/dmaRegs.h>
0021 #include <libcpu/uart.h>
0022
0023
0024 #define BFIN_UART_XMIT_BUSY 0x01
0025
0026 static bfin_uart_config_t *uartsConfig;
0027
0028 static int pollRead(int minor)
0029 {
0030 int c;
0031 uint32_t base;
0032
0033 base = uartsConfig->channels[minor].uart_baseAddress;
0034
0035
0036
0037
0038 if (!uartsConfig->channels[minor].uart_useInterrupts &&
0039 *((uint16_t volatile *) (base + UART_LSR_OFFSET)) & UART_LSR_DR)
0040 c = *((uint16_t volatile *) (base + UART_RBR_OFFSET));
0041 else
0042 c = -1;
0043
0044 return c;
0045 }
0046
0047 char bfin_uart_poll_read(rtems_device_minor_number minor)
0048 {
0049 int c;
0050
0051 do {
0052 c = pollRead(minor);
0053 } while (c == -1);
0054
0055 return c;
0056 }
0057
0058 void bfin_uart_poll_write(int minor, char c)
0059 {
0060 uint32_t base;
0061
0062 base = uartsConfig->channels[minor].uart_baseAddress;
0063
0064 while (!(*((uint16_t volatile *) (base + UART_LSR_OFFSET)) & UART_LSR_THRE))
0065 ;
0066 *(uint16_t volatile *) (base + UART_THR_OFFSET) = c;
0067 }
0068
0069
0070
0071
0072
0073
0074 static ssize_t pollWrite(int minor, const char *buf, size_t len)
0075 {
0076 size_t count;
0077 for ( count = 0; count < len; count++ )
0078 bfin_uart_poll_write(minor, *buf++);
0079
0080 return count;
0081 }
0082
0083
0084
0085
0086
0087
0088 static void initializeHardware(bfin_uart_channel_t *channel)
0089 {
0090 uint16_t divisor = 0;
0091 uint32_t base = 0;
0092 uint32_t tx_dma_base = 0;
0093
0094 if ( NULL == channel ) {
0095 return;
0096 }
0097
0098 base = channel->uart_baseAddress;
0099 tx_dma_base = channel->uart_txDmaBaseAddress;
0100
0101
0102
0103
0104
0105
0106
0107
0108 *(uint16_t volatile *) (base + UART_IER_OFFSET) = 0;
0109
0110 if ( 0 != channel->uart_baud) {
0111 divisor = (uint16_t) (uartsConfig->freq /
0112 (channel->uart_baud * 16));
0113 } else {
0114 divisor = (uint16_t) (uartsConfig->freq / (9600 * 16));
0115 }
0116
0117 *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_DLAB;
0118 *(uint16_t volatile *) (base + UART_DLL_OFFSET) = (divisor & 0xff);
0119 *(uint16_t volatile *) (base + UART_DLH_OFFSET) = ((divisor >> 8) & 0xff);
0120
0121 *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_WLS_8;
0122
0123 *(uint16_t volatile *) (base + UART_GCTL_OFFSET) = UART_GCTL_UCEN;
0124
0125
0126
0127
0128
0129 divisor = *(uint16_t volatile *) (base + UART_LSR_OFFSET);
0130 divisor = *(uint16_t volatile *) (base + UART_RBR_OFFSET);
0131 divisor = *(uint16_t volatile *) (base + UART_IIR_OFFSET);
0132
0133 if ( channel->uart_useDma ) {
0134 *(uint16_t volatile *)(tx_dma_base + DMA_CONFIG_OFFSET) = 0;
0135 *(uint16_t volatile *)(tx_dma_base + DMA_CONFIG_OFFSET) = DMA_CONFIG_DI_EN
0136 | DMA_CONFIG_SYNC ;
0137 *(uint16_t volatile *)(tx_dma_base + DMA_IRQ_STATUS_OFFSET) |=
0138 DMA_IRQ_STATUS_DMA_DONE | DMA_IRQ_STATUS_DMA_ERR;
0139
0140 } else {
0141
0142
0143
0144 }
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154 static int setAttributes(int minor, const struct termios *termios)
0155 {
0156 uint32_t base;
0157 int baud;
0158 uint16_t divisor;
0159 uint16_t lcr;
0160
0161 base = uartsConfig->channels[minor].uart_baseAddress;
0162 switch (termios->c_ospeed) {
0163 case B0: baud = 0; break;
0164 case B50: baud = 50; break;
0165 case B75: baud = 75; break;
0166 case B110: baud = 110; break;
0167 case B134: baud = 134; break;
0168 case B150: baud = 150; break;
0169 case B200: baud = 200; break;
0170 case B300: baud = 300; break;
0171 case B600: baud = 600; break;
0172 case B1200: baud = 1200; break;
0173 case B1800: baud = 1800; break;
0174 case B2400: baud = 2400; break;
0175 case B4800: baud = 4800; break;
0176 case B9600: baud = 9600; break;
0177 case B19200: baud = 19200; break;
0178 case B38400: baud = 38400; break;
0179 case B57600: baud = 57600; break;
0180 case B115200: baud = 115200; break;
0181 case B230400: baud = 230400; break;
0182 case B460800: baud = 460800; break;
0183 default: baud = -1; break;
0184 }
0185 if (baud > 0 && uartsConfig->channels[minor].uart_baud)
0186 baud = uartsConfig->channels[minor].uart_baud;
0187 switch (termios->c_cflag & CSIZE) {
0188 case CS5: lcr = UART_LCR_WLS_5; break;
0189 case CS6: lcr = UART_LCR_WLS_6; break;
0190 case CS7: lcr = UART_LCR_WLS_7; break;
0191 default:
0192 case CS8: lcr = UART_LCR_WLS_8; break;
0193 }
0194 switch (termios->c_cflag & (PARENB | PARODD)) {
0195 case PARENB:
0196 lcr |= UART_LCR_PEN | UART_LCR_EPS;
0197 break;
0198 case PARENB | PARODD:
0199 lcr |= UART_LCR_PEN;
0200 break;
0201 default:
0202 break;
0203 }
0204 if (termios->c_cflag & CSTOPB)
0205 lcr |= UART_LCR_STB;
0206
0207 if (baud > 0) {
0208 divisor = (uint16_t) (uartsConfig->freq / (baud * 16));
0209 *(uint16_t volatile *) (base + UART_LCR_OFFSET) = lcr | UART_LCR_DLAB;
0210 *(uint16_t volatile *) (base + UART_DLL_OFFSET) = (divisor & 0xff);
0211 *(uint16_t volatile *) (base + UART_DLH_OFFSET) = ((divisor >> 8) & 0xff);
0212 }
0213 *(uint16_t volatile *) (base + UART_LCR_OFFSET) = lcr;
0214
0215 return 0;
0216 }
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 static ssize_t uart_interruptWrite(int minor, const char *buf, size_t len)
0227 {
0228 uint32_t base = 0;
0229 bfin_uart_channel_t* channel = NULL;
0230
0231
0232
0233
0234 if (
0235 NULL == buf || NULL == channel || NULL == uartsConfig
0236 || minor < 0 || 0 == len
0237 ) {
0238 return 0;
0239 }
0240
0241 channel = &(uartsConfig->channels[minor]);
0242
0243 if ( NULL == channel || channel->flags & BFIN_UART_XMIT_BUSY ) {
0244 return 0;
0245 }
0246
0247 base = channel->uart_baseAddress;
0248
0249 channel->flags |= BFIN_UART_XMIT_BUSY;
0250 channel->length = 1;
0251 *(uint16_t volatile *) (base + UART_THR_OFFSET) = *buf;
0252 *(uint16_t volatile *) (base + UART_IER_OFFSET) = UART_IER_ETBEI;
0253
0254 return 0;
0255 }
0256
0257
0258
0259
0260 void bfinUart_rxIsr(void *_arg)
0261 {
0262
0263
0264
0265 }
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 void bfinUart_txIsr(void *_arg)
0276 {
0277 bfin_uart_channel_t* channel = NULL;
0278 uint32_t base = 0;
0279
0280
0281
0282
0283 if (NULL == _arg) {
0284
0285 return;
0286 }
0287
0288 channel = (bfin_uart_channel_t *) _arg;
0289
0290 base = channel->uart_baseAddress;
0291
0292 *(uint16_t volatile *) (base + UART_IER_OFFSET) &= ~UART_IER_ETBEI;
0293 channel->flags &= ~BFIN_UART_XMIT_BUSY;
0294
0295 rtems_termios_dequeue_characters(channel->termios, channel->length);
0296 }
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307 static ssize_t uart_DmaWrite(int minor, const char *buf, size_t len)
0308 {
0309 uint32_t base = 0;
0310 bfin_uart_channel_t* channel = NULL;
0311 uint32_t tx_dma_base = 0;
0312
0313
0314
0315
0316 if ( NULL == buf || 0 > minor || NULL == uartsConfig || 0 == len ) {
0317 return 0;
0318 }
0319
0320 channel = &(uartsConfig->channels[minor]);
0321
0322
0323
0324
0325 if ( NULL == channel || BFIN_UART_XMIT_BUSY & channel->flags ) {
0326 return 0;
0327 }
0328
0329 base = channel->uart_baseAddress;
0330 tx_dma_base = channel->uart_txDmaBaseAddress;
0331
0332 channel->flags |= BFIN_UART_XMIT_BUSY;
0333 channel->length = len;
0334
0335 *(uint16_t volatile *) (tx_dma_base + DMA_CONFIG_OFFSET) &= ~DMA_CONFIG_DMAEN;
0336 *(uint32_t volatile *) (tx_dma_base + DMA_START_ADDR_OFFSET) = (uint32_t)buf;
0337 *(uint16_t volatile *) (tx_dma_base + DMA_X_COUNT_OFFSET) = channel->length;
0338 *(uint16_t volatile *) (tx_dma_base + DMA_X_MODIFY_OFFSET) = 1;
0339 *(uint16_t volatile *) (tx_dma_base + DMA_CONFIG_OFFSET) |= DMA_CONFIG_DMAEN;
0340 *(uint16_t volatile *) (base + UART_IER_OFFSET) = UART_IER_ETBEI;
0341
0342 return 0;
0343 }
0344
0345
0346
0347
0348
0349
0350
0351 void bfinUart_rxDmaIsr(void *_arg)
0352 {
0353
0354
0355
0356 }
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369 void bfinUart_txDmaIsr(void *_arg)
0370 {
0371 bfin_uart_channel_t* channel = NULL;
0372 uint32_t tx_dma_base = 0;
0373
0374
0375
0376
0377 if (NULL == _arg) {
0378
0379 return;
0380 }
0381
0382 channel = (bfin_uart_channel_t *) _arg;
0383
0384 tx_dma_base = channel->uart_txDmaBaseAddress;
0385
0386 if ((*(uint16_t volatile *) (tx_dma_base + DMA_IRQ_STATUS_OFFSET)
0387 & DMA_IRQ_STATUS_DMA_DONE)) {
0388
0389 *(uint16_t volatile *) (tx_dma_base + DMA_IRQ_STATUS_OFFSET)
0390 |= DMA_IRQ_STATUS_DMA_DONE | DMA_IRQ_STATUS_DMA_ERR;
0391 channel->flags &= ~BFIN_UART_XMIT_BUSY;
0392 rtems_termios_dequeue_characters(channel->termios, channel->length);
0393 } else {
0394
0395
0396
0397 }
0398 }
0399
0400
0401
0402
0403 static void uart_exit(void)
0404 {
0405
0406
0407
0408 }
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422 rtems_device_driver bfin_uart_open(rtems_device_major_number major,
0423 rtems_device_minor_number minor, void *arg) {
0424 rtems_status_code sc = RTEMS_NOT_DEFINED;
0425 rtems_libio_open_close_args_t *args = NULL;
0426
0427
0428
0429
0430 static const rtems_termios_callbacks pollCallbacks = {
0431 NULL,
0432 NULL,
0433 pollRead,
0434 pollWrite,
0435 setAttributes,
0436 NULL,
0437 NULL,
0438 TERMIOS_POLLED
0439 };
0440
0441
0442
0443
0444
0445 static const rtems_termios_callbacks interruptCallbacks = {
0446 NULL,
0447 NULL,
0448 pollRead,
0449 uart_interruptWrite,
0450 setAttributes,
0451 NULL,
0452 NULL,
0453 TERMIOS_IRQ_DRIVEN
0454 };
0455
0456
0457
0458
0459
0460 static const rtems_termios_callbacks interruptDmaCallbacks = {
0461 NULL,
0462 NULL,
0463 NULL,
0464 uart_DmaWrite,
0465 setAttributes,
0466 NULL,
0467 NULL,
0468 TERMIOS_IRQ_DRIVEN
0469 };
0470
0471 if ( NULL == uartsConfig || 0 > minor || minor >= uartsConfig->num_channels) {
0472 return RTEMS_INVALID_NUMBER;
0473 }
0474
0475
0476
0477
0478
0479
0480
0481 if ( uartsConfig->channels[minor].uart_useDma ) {
0482 sc = rtems_termios_open(major, minor, arg, &interruptDmaCallbacks);
0483 } else {
0484 sc = rtems_termios_open(major, minor, arg,
0485 uartsConfig->channels[minor].uart_useInterrupts ?
0486 &interruptCallbacks : &pollCallbacks);
0487 }
0488
0489 args = arg;
0490 uartsConfig->channels[minor].termios = args->iop->data1;
0491
0492 atexit(uart_exit);
0493
0494 return sc;
0495 }
0496
0497
0498
0499
0500
0501
0502
0503 rtems_status_code bfin_uart_initialize(
0504 rtems_device_major_number major,
0505 bfin_uart_config_t *config
0506 )
0507 {
0508 rtems_status_code sc = RTEMS_NOT_DEFINED;
0509 int i = 0;
0510
0511 rtems_termios_initialize();
0512
0513
0514
0515
0516 uartsConfig = config;
0517 for (i = 0; i < config->num_channels; i++) {
0518 config->channels[i].termios = NULL;
0519 config->channels[i].flags = 0;
0520 initializeHardware(&(config->channels[i]));
0521 sc = rtems_io_register_name(config->channels[i].name, major, i);
0522 if (RTEMS_SUCCESSFUL != sc) {
0523 return sc;
0524 }
0525 }
0526
0527 return sc;
0528 }