File indexing completed on 2025-05-11 08:24:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <grlib/apbuart_termios.h>
0034 #include <grlib/apbuart.h>
0035 #include <grlib/io.h>
0036 #include <bsp.h>
0037
0038 static void apbuart_isr(void *arg)
0039 {
0040 rtems_termios_tty *tty = arg;
0041 struct apbuart_context *uart = rtems_termios_get_device_context(tty);
0042 unsigned int status;
0043 char data;
0044
0045
0046 while ((status=grlib_load_32(&uart->regs->status)) & APBUART_STATUS_DR) {
0047
0048 data = (char)grlib_load_32(&uart->regs->data);
0049
0050
0051 rtems_termios_enqueue_raw_characters(tty, &data, 1);
0052 }
0053
0054 if (
0055 (status & APBUART_STATUS_TE)
0056 && (grlib_load_32(&uart->regs->ctrl) & APBUART_CTRL_TI) != 0
0057 ) {
0058
0059 rtems_termios_dequeue_characters(tty, 1);
0060 }
0061 }
0062
0063 static void apbuart_write_support(
0064 rtems_termios_device_context *base,
0065 const char *buf,
0066 size_t len
0067 )
0068 {
0069 struct apbuart_context *uart = (struct apbuart_context *) base;
0070 int sending;
0071 uint32_t ctrl;
0072
0073 ctrl = grlib_load_32(&uart->regs->ctrl);
0074
0075 if (len > 0) {
0076
0077 ctrl |= APBUART_CTRL_TI;
0078
0079
0080 grlib_store_32(&uart->regs->data, (uint8_t)*buf);
0081
0082 sending = 1;
0083 } else {
0084
0085 ctrl &= ~APBUART_CTRL_TI;
0086
0087
0088 sending = 0;
0089 }
0090
0091 grlib_store_32(&uart->regs->ctrl, ctrl);
0092 uart->sending = sending;
0093 }
0094
0095 static void apbuart_write_polled(
0096 rtems_termios_device_context *base,
0097 const char *buf,
0098 size_t len
0099 )
0100 {
0101 struct apbuart_context *uart = (struct apbuart_context *) base;
0102 size_t nwrite = 0;
0103
0104 while (nwrite < len) {
0105 apbuart_outbyte_polled(uart->regs, *buf++);
0106 nwrite++;
0107 }
0108 }
0109
0110 static int apbuart_poll_read(rtems_termios_device_context *base)
0111 {
0112 struct apbuart_context *uart = (struct apbuart_context *) base;
0113
0114 return apbuart_inbyte_nonblocking(uart->regs);
0115 }
0116
0117 static bool apbuart_set_attributes(
0118 rtems_termios_device_context *base,
0119 const struct termios *t
0120 )
0121 {
0122 struct apbuart_context *uart = (struct apbuart_context *) base;
0123 rtems_interrupt_lock_context lock_context;
0124 unsigned int scaler;
0125 unsigned int ctrl;
0126 int baud;
0127
0128 switch (t->c_cflag & CSIZE) {
0129 default:
0130 case CS5:
0131 case CS6:
0132 case CS7:
0133
0134 return false;
0135 case CS8:
0136 break;
0137 }
0138
0139 rtems_termios_device_lock_acquire(base, &lock_context);
0140
0141
0142 ctrl = grlib_load_32(&uart->regs->ctrl);
0143
0144 switch (t->c_cflag & (PARENB|PARODD)) {
0145 case (PARENB|PARODD):
0146
0147 ctrl |= APBUART_CTRL_PE|APBUART_CTRL_PS;
0148 break;
0149
0150 case PARENB:
0151
0152 ctrl &= ~APBUART_CTRL_PS;
0153 ctrl |= APBUART_CTRL_PE;
0154 break;
0155
0156 default:
0157 case 0:
0158 case PARODD:
0159
0160 ctrl &= ~(APBUART_CTRL_PS|APBUART_CTRL_PE);
0161 }
0162
0163 if (!(t->c_cflag & CLOCAL)) {
0164 ctrl |= APBUART_CTRL_FL;
0165 } else {
0166 ctrl &= ~APBUART_CTRL_FL;
0167 }
0168
0169
0170 grlib_store_32(&uart->regs->ctrl, ctrl);
0171
0172 rtems_termios_device_lock_release(base, &lock_context);
0173
0174
0175 baud = rtems_termios_baud_to_number(t->c_ospeed);
0176 if (baud > 0) {
0177
0178 scaler = (((uart->freq_hz * 10) / (baud * 8)) - 5) / 10;
0179
0180
0181 grlib_store_32(&uart->regs->scaler, scaler);
0182 }
0183
0184 return true;
0185 }
0186
0187 static void apbuart_set_best_baud(
0188 const struct apbuart_context *uart,
0189 struct termios *term
0190 )
0191 {
0192 uint32_t baud = (uart->freq_hz * 10) /
0193 ((grlib_load_32(&uart->regs->scaler) * 10 + 5) * 8);
0194
0195 rtems_termios_set_best_baud(term, baud);
0196 }
0197
0198 static bool apbuart_first_open_polled(
0199 rtems_termios_tty *tty,
0200 rtems_termios_device_context *base,
0201 struct termios *term,
0202 rtems_libio_open_close_args_t *args
0203 )
0204 {
0205 struct apbuart_context *uart = (struct apbuart_context *) base;
0206 uint32_t ctrl;
0207
0208 apbuart_set_best_baud(uart, term);
0209
0210
0211 ctrl = grlib_load_32(&uart->regs->ctrl);
0212 ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
0213 grlib_store_32(&uart->regs->ctrl, ctrl);
0214 grlib_store_32(&uart->regs->status, 0);
0215
0216 return true;
0217 }
0218
0219 static bool apbuart_first_open_interrupt(
0220 rtems_termios_tty *tty,
0221 rtems_termios_device_context *base,
0222 struct termios *term,
0223 rtems_libio_open_close_args_t *args
0224 )
0225 {
0226 struct apbuart_context *uart = (struct apbuart_context *) base;
0227 rtems_status_code sc;
0228 uint32_t ctrl;
0229
0230 apbuart_set_best_baud(uart, term);
0231
0232
0233 sc = rtems_interrupt_handler_install(uart->irq, "console",
0234 RTEMS_INTERRUPT_SHARED,
0235 apbuart_isr,
0236 tty);
0237 if (sc != RTEMS_SUCCESSFUL)
0238 return false;
0239
0240 uart->sending = 0;
0241
0242 ctrl = grlib_load_32(&uart->regs->ctrl);
0243 ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE | APBUART_CTRL_RI;
0244 grlib_store_32(&uart->regs->ctrl, ctrl);
0245
0246 ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
0247 grlib_store_32(&uart->regs->ctrl, ctrl);
0248 grlib_store_32(&uart->regs->status, 0);
0249
0250 return true;
0251 }
0252
0253 static void apbuart_last_close_interrupt(
0254 rtems_termios_tty *tty,
0255 rtems_termios_device_context *base,
0256 rtems_libio_open_close_args_t *args
0257 )
0258 {
0259 struct apbuart_context *uart = (struct apbuart_context *) base;
0260 rtems_interrupt_lock_context lock_context;
0261 uint32_t ctrl;
0262
0263
0264 rtems_termios_device_lock_acquire(base, &lock_context);
0265 ctrl = grlib_load_32(&uart->regs->ctrl);
0266 ctrl &= ~APBUART_CTRL_RI;
0267 grlib_store_32(&uart->regs->ctrl, ctrl);
0268 rtems_termios_device_lock_release(base, &lock_context);
0269
0270
0271 while (uart->sending) {
0272
0273 }
0274
0275
0276 rtems_interrupt_handler_remove(uart->irq, apbuart_isr, tty);
0277 }
0278
0279 const rtems_termios_device_handler apbuart_handler_interrupt = {
0280 .first_open = apbuart_first_open_interrupt,
0281 .last_close = apbuart_last_close_interrupt,
0282 .write = apbuart_write_support,
0283 .set_attributes = apbuart_set_attributes,
0284 .mode = TERMIOS_IRQ_DRIVEN
0285 };
0286
0287 const rtems_termios_device_handler apbuart_handler_polled = {
0288 .first_open = apbuart_first_open_polled,
0289 .poll_read = apbuart_poll_read,
0290 .write = apbuart_write_polled,
0291 .set_attributes = apbuart_set_attributes,
0292 .mode = TERMIOS_POLLED
0293 };