File indexing completed on 2025-05-11 08:24:00
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 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include <rtems/bspIo.h>
0033 #include <rtems/console.h>
0034 #include <rtems/sysinit.h>
0035 #include <rtems/termiostypes.h>
0036
0037 #include <bsp/fatal.h>
0038 #include <bsp/irq.h>
0039 #include <bsp/niosv.h>
0040 #include <bsp.h>
0041 #include <bsp/console-termios.h>
0042 #include <rtems/libio.h>
0043
0044 typedef struct {
0045 rtems_termios_device_context base;
0046 rtems_termios_tty *tty;
0047 rtems_vector_number irq;
0048 size_t out_total;
0049 size_t out_remaining;
0050 size_t out_current;
0051 const char *out_buf;
0052 } jtag_uart_context;
0053
0054 static void jtag_uart_initialize_interrupts(
0055 struct rtems_termios_tty *tty,
0056 jtag_uart_context *ctx, void (*isr)(void *)
0057 );
0058 static bool jtag_uart_console_first_open(
0059 struct rtems_termios_tty *tty,
0060 rtems_termios_device_context *base, struct termios *term,
0061 rtems_libio_open_close_args_t *args
0062 );
0063 static void jtag_uart_close(
0064 struct rtems_termios_tty *tty,
0065 rtems_termios_device_context *base,
0066 rtems_libio_open_close_args_t *args
0067 );
0068 static void jtag_uart_console_write_int(
0069 rtems_termios_device_context *base,
0070 const char *buf, size_t len
0071 );
0072 static size_t jtag_uart_write_to_fifo(const char *buf, size_t len);
0073 static void jtag_uart_clear_and_set_control(
0074 jtag_uart_context *ctx,
0075 uint32_t clear, uint32_t set
0076 );
0077 static void jtag_uart_console_putchar(char c);
0078
0079 static jtag_uart_context jtag_uart_console_instance;
0080
0081 static const rtems_termios_device_handler jtag_uart_console_handler = {
0082 .first_open = jtag_uart_console_first_open,
0083 .last_close = jtag_uart_close,
0084 .poll_read = NULL,
0085 .write = jtag_uart_console_write_int,
0086 .set_attributes = NULL,
0087 .mode = TERMIOS_IRQ_DRIVEN
0088 };
0089
0090 static void jtag_uart_clear_and_set_control(
0091 jtag_uart_context *ctx,
0092 uint32_t clear,
0093 uint32_t set
0094 )
0095 {
0096 volatile altera_avalon_jtag_uart_regs *ajur = JTAG_UART_REGS;
0097 rtems_interrupt_lock_context lock_context;
0098 uint8_t val;
0099
0100 rtems_termios_device_lock_acquire(&ctx->base, &lock_context);
0101 val = ajur->control;
0102 val &= ~clear;
0103 val |= set;
0104 ajur->control = val;
0105 rtems_termios_device_lock_release(&ctx->base, &lock_context);
0106 }
0107
0108 static size_t jtag_uart_write_to_fifo(const char *buf, size_t len)
0109 {
0110 volatile altera_avalon_jtag_uart_regs *ajur = JTAG_UART_REGS;
0111 uint32_t space = (
0112 ajur->control & ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK
0113 ) >> ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_OFST;
0114 size_t out = len > space ? space : len;
0115 size_t i;
0116
0117 for (i = 0; i < out; ++i) {
0118 ajur->data = buf[i];
0119 }
0120
0121 return out;
0122 }
0123
0124 static void jtag_uart_isr(void *arg)
0125 {
0126 rtems_termios_tty *tty = arg;
0127 jtag_uart_context *ctx = rtems_termios_get_device_context(tty);
0128 volatile altera_avalon_jtag_uart_regs *ajur = JTAG_UART_REGS;
0129 int i = 0;
0130 char buf [JTAG_UART_READ_DEPTH];
0131
0132
0133 do {
0134 if (ajur->control & ALTERA_AVALON_JTAG_UART_CONTROL_RI_MSK) {
0135
0136 for (i = 0; i < JTAG_UART_READ_DEPTH; ++i) {
0137 uint32_t data = ajur->data;
0138 if ((data & ALTERA_AVALON_JTAG_UART_DATA_RVALID_MSK) == 0) {
0139 break;
0140 } else {
0141 buf[i] = (char) data;
0142 }
0143 }
0144
0145
0146 rtems_termios_enqueue_raw_characters(tty, buf, i);
0147 }
0148
0149
0150 if (ctx->out_total > 0 &&
0151 ajur->control & ALTERA_AVALON_JTAG_UART_CONTROL_WI_MSK
0152 ) {
0153 size_t current = ctx->out_current;
0154
0155 ctx->out_buf += current;
0156 ctx->out_remaining -= current;
0157
0158 if(ctx->out_remaining > 0) {
0159 ctx->out_current =
0160 jtag_uart_write_to_fifo(ctx->out_buf, ctx->out_remaining);
0161 } else {
0162 rtems_termios_dequeue_characters(tty, ctx->out_total);
0163 }
0164 }
0165 } while((ajur->control & (ALTERA_AVALON_JTAG_UART_CONTROL_RI_MSK |
0166 ALTERA_AVALON_JTAG_UART_CONTROL_WI_MSK)) != 0);
0167 }
0168
0169 static void jtag_uart_console_putchar(char c)
0170 {
0171 volatile altera_avalon_jtag_uart_regs *ajur = JTAG_UART_REGS;
0172
0173
0174
0175
0176
0177
0178 while ((ajur->control & ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK) == 0);
0179
0180 ajur->data = c;
0181 }
0182
0183 static void jtag_uart_console_probe(void)
0184 {
0185 rtems_termios_device_context_initialize(
0186 &jtag_uart_console_instance.base,
0187 "JURT"
0188 );
0189
0190 jtag_uart_console_instance.irq =
0191 NIOSV_INTERRUPT_VECTOR_EXTERNAL(JTAG_UART_IRQ);
0192 }
0193
0194 rtems_status_code console_initialize(
0195 rtems_device_major_number major,
0196 rtems_device_minor_number minor,
0197 void *arg
0198 )
0199 {
0200 rtems_termios_device_context *base;
0201 char jtag_uart_path[] = "/dev/ttyJtagUart";
0202
0203 rtems_termios_initialize();
0204
0205 base = &jtag_uart_console_instance.base;
0206 rtems_termios_device_install(
0207 jtag_uart_path,
0208 &jtag_uart_console_handler,
0209 NULL,
0210 base
0211 );
0212
0213 link(jtag_uart_path, CONSOLE_DEVICE_NAME);
0214
0215 return RTEMS_SUCCESSFUL;
0216 }
0217
0218 static void jtag_uart_initialize_interrupts(
0219 struct rtems_termios_tty *tty,
0220 jtag_uart_context *ctx,
0221 void (*isr)(void *)
0222 )
0223 {
0224 rtems_status_code sc = RTEMS_SUCCESSFUL;
0225 sc = rtems_interrupt_handler_install(
0226 ctx->irq,
0227 "JTAG_UART",
0228 RTEMS_INTERRUPT_UNIQUE,
0229 isr,
0230 tty
0231 );
0232 if (sc != RTEMS_SUCCESSFUL) {
0233 printk( "%s: Error: Install interrupt handler\n", __func__);
0234 rtems_fatal_error_occurred(0xdeadbeef);
0235 }
0236
0237 alt_irq_enable(JTAG_UART_IRQ);
0238 }
0239
0240 static void jtag_uart_cleanup_interrupts(
0241 struct rtems_termios_tty *tty,
0242 jtag_uart_context *ctx,
0243 void (*isr)(void *)
0244 )
0245 {
0246 rtems_status_code sc = RTEMS_SUCCESSFUL;
0247
0248
0249 alt_irq_disable(JTAG_UART_IRQ);
0250
0251 sc = rtems_interrupt_handler_remove(
0252 ctx->irq,
0253 isr,
0254 tty
0255 );
0256 if (sc != RTEMS_SUCCESSFUL) {
0257
0258 printk("%s: Error: Remove interrupt handler\n", __func__);
0259 rtems_fatal_error_occurred(0xdeadbeef);
0260 }
0261 }
0262
0263 static bool jtag_uart_console_first_open(
0264 struct rtems_termios_tty *tty,
0265 rtems_termios_device_context *base,
0266 struct termios *term,
0267 rtems_libio_open_close_args_t *args
0268 )
0269 {
0270 jtag_uart_context *ctx = (jtag_uart_context *)base;
0271
0272 ctx->tty = tty;
0273
0274 if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
0275 jtag_uart_initialize_interrupts(tty, ctx, jtag_uart_isr);
0276 jtag_uart_clear_and_set_control(
0277 ctx,
0278 ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK,
0279 ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK
0280 );
0281 }
0282
0283 return true;
0284 }
0285
0286 static void jtag_uart_close(
0287 struct rtems_termios_tty *tty,
0288 rtems_termios_device_context *base,
0289 rtems_libio_open_close_args_t *args
0290 )
0291 {
0292 jtag_uart_context *ctx = (jtag_uart_context *) base;
0293
0294
0295 jtag_uart_clear_and_set_control(
0296 ctx,
0297 ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK |
0298 ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK,
0299 0
0300 );
0301
0302 if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
0303 jtag_uart_cleanup_interrupts(tty, ctx, jtag_uart_isr);
0304 }
0305 }
0306
0307 static void jtag_uart_console_write_int(
0308 rtems_termios_device_context *base,
0309 const char *buf,
0310 size_t len
0311 )
0312 {
0313 jtag_uart_context *ctx = (jtag_uart_context *) base;
0314
0315 ctx->out_total = len;
0316
0317 if (len > 0) {
0318 ctx->out_remaining = len;
0319 ctx->out_buf = buf;
0320 ctx->out_current = jtag_uart_write_to_fifo(buf, len);
0321
0322 jtag_uart_clear_and_set_control(
0323 ctx,
0324 0,
0325 ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK
0326 );
0327 } else {
0328 jtag_uart_clear_and_set_control(
0329 ctx,
0330 ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK,
0331 0
0332 );
0333 }
0334 }
0335
0336 static void jtag_uart_output_char_init(char c)
0337 {
0338 BSP_output_char = jtag_uart_console_putchar;
0339 jtag_uart_console_putchar(c);
0340 }
0341
0342 BSP_output_char_function_type BSP_output_char = jtag_uart_output_char_init;
0343 BSP_polling_getchar_function_type BSP_poll_char = NULL;
0344
0345 RTEMS_SYSINIT_ITEM(
0346 jtag_uart_console_probe,
0347 RTEMS_SYSINIT_BSP_START,
0348 RTEMS_SYSINIT_ORDER_LAST_BUT_5
0349 );