File indexing completed on 2025-05-11 08:23:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <rtems.h>
0018 #include <termios.h>
0019 #include <rtems/libio.h>
0020 #include "mcf5206/mcfuart.h"
0021
0022
0023
0024
0025
0026 static struct {
0027 mcfuart *uart;
0028 int vec;
0029 } int_driven_uart[2];
0030
0031
0032 static rtems_isr
0033 mcfuart_interrupt_handler(rtems_vector_number vec);
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 rtems_status_code
0052 mcfuart_init(
0053 mcfuart *uart,
0054 void *tty,
0055 uint8_t intvec,
0056 uint32_t chn
0057 )
0058 {
0059 if (uart == NULL)
0060 return RTEMS_INVALID_ADDRESS;
0061
0062 if ((chn <= 0) || (chn > MCF5206E_UART_CHANNELS))
0063 return RTEMS_INVALID_NUMBER;
0064
0065 uart->chn = chn;
0066 uart->intvec = intvec;
0067 uart->tty = tty;
0068
0069 return RTEMS_SUCCESSFUL;
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 static void
0083 mcfuart_set_baudrate(mcfuart *uart, speed_t baud)
0084 {
0085 uint32_t div;
0086 uint32_t rate;
0087
0088 switch (baud) {
0089 case B50: rate = 50; break;
0090 case B75: rate = 75; break;
0091 case B110: rate = 110; break;
0092 case B134: rate = 134; break;
0093 case B150: rate = 150; break;
0094 case B200: rate = 200; break;
0095 case B300: rate = 300; break;
0096 case B600: rate = 600; break;
0097 case B1200: rate = 1200; break;
0098 case B2400: rate = 2400; break;
0099 case B4800: rate = 4800; break;
0100 case B9600: rate = 9600; break;
0101 case B19200: rate = 19200; break;
0102 case B38400: rate = 38400; break;
0103 case B57600: rate = 57600; break;
0104 #ifdef B115200
0105 case B115200: rate = 115200; break;
0106 #endif
0107 #ifdef B230400
0108 case B230400: rate = 230400; break;
0109 #endif
0110 default: rate = 9600; break;
0111 }
0112
0113 div = SYSTEM_CLOCK_FREQUENCY / (rate * 32);
0114
0115 *MCF5206E_UBG1(MBAR,uart->chn) = (uint8_t)((div >> 8) & 0xff);
0116 *MCF5206E_UBG2(MBAR,uart->chn) = (uint8_t)(div & 0xff);
0117 }
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 rtems_status_code mcfuart_reset(mcfuart *uart)
0137 {
0138 register uint32_t chn;
0139 rtems_status_code rc;
0140
0141 if (uart == NULL)
0142 return RTEMS_INVALID_ADDRESS;
0143
0144 chn = uart->chn;
0145
0146
0147 *MCF5206E_UCR(MBAR,chn) = MCF5206E_UCR_MISC_RESET_RX;
0148 *MCF5206E_UCR(MBAR,chn) = MCF5206E_UCR_MISC_RESET_TX;
0149
0150
0151
0152
0153
0154
0155 if (uart->intvec != 0) {
0156 int_driven_uart[chn - 1].uart = uart;
0157 int_driven_uart[chn - 1].vec = uart->intvec;
0158 rc = rtems_interrupt_catch(mcfuart_interrupt_handler, uart->intvec,
0159 &uart->old_handler);
0160 if (rc != RTEMS_SUCCESSFUL)
0161 return rc;
0162 *MCF5206E_UIVR(MBAR,chn) = uart->intvec;
0163 *MCF5206E_UIMR(MBAR,chn) = MCF5206E_UIMR_FFULL;
0164 *MCF5206E_UACR(MBAR,chn) = MCF5206E_UACR_IEC;
0165 *MCF5206E_IMR(MBAR) &= ~MCF5206E_INTR_BIT(uart->chn == 1 ?
0166 MCF5206E_INTR_UART_1 :
0167 MCF5206E_INTR_UART_2);
0168 } else {
0169 *MCF5206E_UIMR(MBAR,chn) = 0;
0170 }
0171
0172
0173 mcfuart_set_baudrate(uart, B19200);
0174
0175 *MCF5206E_UCSR(MBAR,chn) = MCF5206E_UCSR_RCS_TIMER | MCF5206E_UCSR_TCS_TIMER;
0176
0177
0178 *MCF5206E_UCR(MBAR,chn) = MCF5206E_UCR_MISC_RESET_MR;
0179 *MCF5206E_UMR(MBAR,chn) =
0180
0181 MCF5206E_UMR1_PM_NO_PARITY |
0182 MCF5206E_UMR1_BC_8;
0183 *MCF5206E_UMR(MBAR,chn) =
0184 MCF5206E_UMR2_CM_NORMAL |
0185
0186 MCF5206E_UMR2_SB_1;
0187
0188
0189 *MCF5206E_UCR(MBAR,chn) = MCF5206E_UCR_MISC_RESET_ERR;
0190 *MCF5206E_UCR(MBAR,chn) = MCF5206E_UCR_TC_ENABLE;
0191 *MCF5206E_UCR(MBAR,chn) = MCF5206E_UCR_RC_ENABLE;
0192
0193 return RTEMS_SUCCESSFUL;
0194 }
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 rtems_status_code mcfuart_disable(mcfuart *uart)
0209 {
0210 rtems_status_code rc;
0211
0212 *MCF5206E_UCR(MBAR,uart->chn) =
0213 MCF5206E_UCR_TC_DISABLE |
0214 MCF5206E_UCR_RC_DISABLE;
0215 if (uart->intvec != 0) {
0216 *MCF5206E_IMR(MBAR) |= MCF5206E_INTR_BIT(uart->chn == 1 ?
0217 MCF5206E_INTR_UART_1 :
0218 MCF5206E_INTR_UART_2);
0219 rc = rtems_interrupt_catch(uart->old_handler, uart->intvec, NULL);
0220 int_driven_uart[uart->chn - 1].uart = NULL;
0221 int_driven_uart[uart->chn - 1].vec = 0;
0222 if (rc != RTEMS_SUCCESSFUL)
0223 return rc;
0224 }
0225 return RTEMS_SUCCESSFUL;
0226 }
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 int mcfuart_set_attributes(mcfuart *uart, const struct termios *t)
0241 {
0242 int level;
0243 speed_t baud;
0244 uint8_t umr1, umr2;
0245
0246 baud = cfgetospeed(t);
0247 umr1 = 0;
0248 umr2 = MCF5206E_UMR2_CM_NORMAL;
0249
0250
0251 if ((t->c_cflag & CRTSCTS) != 0) {
0252 umr1 |= MCF5206E_UMR1_RXRTS;
0253 umr2 |= MCF5206E_UMR2_TXCTS;
0254 }
0255
0256
0257 switch (t->c_cflag & CSIZE) {
0258 case CS5: umr1 |= MCF5206E_UMR1_BC_5; break;
0259 case CS6: umr1 |= MCF5206E_UMR1_BC_6; break;
0260 case CS7: umr1 |= MCF5206E_UMR1_BC_7; break;
0261 case CS8: umr1 |= MCF5206E_UMR1_BC_8; break;
0262 }
0263
0264
0265 if ((t->c_cflag & CSTOPB) != 0) {
0266 if ((t->c_cflag & CSIZE) == CS5) {
0267 umr2 |= MCF5206E_UMR2_SB5_2;
0268 } else {
0269 umr2 |= MCF5206E_UMR2_SB_2;
0270 }
0271 } else {
0272 if ((t->c_cflag & CSIZE) == CS5) {
0273 umr2 |= MCF5206E_UMR2_SB5_1;
0274 } else {
0275 umr2 |= MCF5206E_UMR2_SB_1;
0276 }
0277 }
0278
0279
0280 if ((t->c_cflag & PARENB) != 0) {
0281 if ((t->c_cflag & PARODD) != 0) {
0282 umr1 |= MCF5206E_UMR1_PM_ODD;
0283 } else {
0284 umr1 |= MCF5206E_UMR1_PM_EVEN;
0285 }
0286 } else {
0287 umr1 |= MCF5206E_UMR1_PM_NO_PARITY;
0288 }
0289
0290 rtems_interrupt_disable(level);
0291 *MCF5206E_UCR(MBAR,uart->chn) =
0292 MCF5206E_UCR_TC_DISABLE | MCF5206E_UCR_RC_DISABLE;
0293 mcfuart_set_baudrate(uart, baud);
0294 *MCF5206E_UCR(MBAR,uart->chn) = MCF5206E_UCR_MISC_RESET_MR;
0295 *MCF5206E_UMR(MBAR,uart->chn) = umr1;
0296 *MCF5206E_UMR(MBAR,uart->chn) = umr2;
0297 if ((t->c_cflag & CREAD) != 0) {
0298 *MCF5206E_UCR(MBAR,uart->chn) =
0299 MCF5206E_UCR_TC_ENABLE | MCF5206E_UCR_RC_ENABLE;
0300 } else {
0301 *MCF5206E_UCR(MBAR,uart->chn) = MCF5206E_UCR_TC_ENABLE;
0302 }
0303 rtems_interrupt_enable(level);
0304
0305 return RTEMS_SUCCESSFUL;
0306 }
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324 int mcfuart_poll_read(mcfuart *uart)
0325 {
0326 uint8_t usr;
0327 int ch;
0328
0329 if (uart->parerr_mark_flag == true) {
0330 uart->parerr_mark_flag = false;
0331 return 0;
0332 }
0333
0334 usr = *MCF5206E_USR(MBAR,uart->chn);
0335 if ((usr & MCF5206E_USR_RXRDY) != 0) {
0336 if (((usr & (MCF5206E_USR_FE | MCF5206E_USR_PE)) != 0) &&
0337 !(uart->c_iflag & IGNPAR)) {
0338 ch = *MCF5206E_URB(MBAR,uart->chn);
0339 if (uart->c_iflag & PARMRK) {
0340 uart->parerr_mark_flag = true;
0341 ch = 0xff;
0342 } else {
0343 ch = 0;
0344 }
0345 } else {
0346 ch = *MCF5206E_URB(MBAR,uart->chn);
0347 }
0348 } else
0349 ch = -1;
0350 return ch;
0351 }
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365 ssize_t mcfuart_poll_write(mcfuart *uart, const char *buf, size_t len)
0366 {
0367 size_t retval = len;
0368
0369 while (len--) {
0370 while ((*MCF5206E_USR(MBAR, uart->chn) & MCF5206E_USR_TXRDY) == 0);
0371 *MCF5206E_UTB(MBAR, uart->chn) = *buf++;
0372 }
0373 return retval;
0374 }
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 static rtems_isr mcfuart_interrupt_handler(rtems_vector_number vec)
0386 {
0387 mcfuart *uart;
0388 register uint8_t usr;
0389 register uint8_t uisr;
0390 register int chn;
0391 register int bp = 0;
0392
0393
0394 if (int_driven_uart[0].vec == vec)
0395 uart = int_driven_uart[0].uart;
0396 else if (int_driven_uart[1].vec == vec)
0397 uart = int_driven_uart[1].uart;
0398 else
0399 return;
0400
0401 chn = uart->chn;
0402
0403 uisr = *MCF5206E_UISR(MBAR, chn);
0404 if (uisr & MCF5206E_UISR_DB) {
0405 *MCF5206E_UCR(MBAR, chn) = MCF5206E_UCR_MISC_RESET_BRK;
0406 }
0407
0408
0409 while (1) {
0410 char buf[32];
0411 usr = *MCF5206E_USR(MBAR,chn);
0412 if ((bp < sizeof(buf) - 1) && ((usr & MCF5206E_USR_RXRDY) != 0)) {
0413
0414 if (((usr & (MCF5206E_USR_FE | MCF5206E_USR_PE)) != 0) &&
0415 !(uart->c_iflag & IGNPAR)) {
0416 if (uart->c_iflag & PARMRK) {
0417 buf[bp++] = 0xff;
0418 buf[bp++] = 0x00;
0419 } else {
0420 buf[bp++] = 0x00;
0421 }
0422 } else {
0423 buf[bp++] = *MCF5206E_URB(MBAR, chn);
0424 }
0425
0426
0427 if (usr & (MCF5206E_USR_RB | MCF5206E_USR_FE |
0428 MCF5206E_USR_PE | MCF5206E_USR_OE)) {
0429 *MCF5206E_UCR(MBAR, chn) = MCF5206E_UCR_MISC_RESET_ERR;
0430 }
0431 } else {
0432 if (bp != 0)
0433 rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
0434 break;
0435 }
0436 }
0437
0438
0439 while (1) {
0440 if ((*MCF5206E_USR(MBAR, chn) & MCF5206E_USR_TXRDY) == 0)
0441 break;
0442 if (uart->tx_buf != NULL) {
0443 if (uart->tx_ptr >= uart->tx_buf_len) {
0444 register int dequeue = uart->tx_buf_len;
0445
0446 *MCF5206E_UIMR(MBAR, uart->chn) = MCF5206E_UIMR_FFULL;
0447 uart->tx_buf = NULL;
0448 uart->tx_ptr = uart->tx_buf_len = 0;
0449 rtems_termios_dequeue_characters(uart->tty, dequeue);
0450 } else {
0451 *MCF5206E_UTB(MBAR, chn) = uart->tx_buf[uart->tx_ptr++];
0452 }
0453 }
0454 else
0455 break;
0456 }
0457 }
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470 ssize_t mcfuart_interrupt_write(
0471 mcfuart *uart,
0472 const char *buf,
0473 size_t len
0474 )
0475 {
0476 if (len > 0) {
0477 uart->tx_buf = buf;
0478 uart->tx_buf_len = len;
0479 uart->tx_ptr = 0;
0480 *MCF5206E_UIMR(MBAR, uart->chn) =
0481 MCF5206E_UIMR_FFULL | MCF5206E_UIMR_TXRDY;
0482 while (((*MCF5206E_USR(MBAR,uart->chn) & MCF5206E_USR_TXRDY) != 0) &&
0483 (uart->tx_ptr < uart->tx_buf_len)) {
0484 *MCF5206E_UTB(MBAR,uart->chn) = uart->tx_buf[uart->tx_ptr++];
0485 }
0486 }
0487
0488 return 0;
0489 }
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500 int mcfuart_stop_remote_tx(mcfuart *uart)
0501 {
0502 *MCF5206E_UOP0(MBAR, uart->chn) = 1;
0503 return RTEMS_SUCCESSFUL;
0504 }
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515 int mcfuart_start_remote_tx(mcfuart *uart)
0516 {
0517 *MCF5206E_UOP1(MBAR, uart->chn) = 1;
0518 return RTEMS_SUCCESSFUL;
0519 }