File indexing completed on 2025-05-11 08:23:57
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
0034
0035
0036 #include <assert.h>
0037
0038 #include <libchip/sersupp.h>
0039
0040 #include <bspopts.h>
0041 #include <bsp/uart-bridge.h>
0042
0043 #define TRANSMIT_EVENT RTEMS_EVENT_13
0044
0045 static rtems_mode disable_preemption(void)
0046 {
0047 rtems_status_code sc = RTEMS_SUCCESSFUL;
0048 rtems_mode prev_mode = 0;
0049
0050 sc = rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &prev_mode);
0051 assert(sc == RTEMS_SUCCESSFUL);
0052
0053 return prev_mode;
0054 }
0055
0056 static void restore_preemption(rtems_mode prev_mode)
0057 {
0058 rtems_status_code sc = RTEMS_SUCCESSFUL;
0059
0060 sc = rtems_task_mode (prev_mode, RTEMS_PREEMPT_MASK, &prev_mode);
0061 assert(sc == RTEMS_SUCCESSFUL);
0062 }
0063
0064 static void uart_bridge_slave_service(intercom_packet *packet, void *arg)
0065 {
0066 uart_bridge_slave_context *ctx = arg;
0067 struct rtems_termios_tty *tty = ctx->tty;
0068
0069
0070 rtems_mode prev_mode = disable_preemption();
0071
0072 rtems_termios_enqueue_raw_characters(tty, packet->data, (int) packet->size);
0073 qoriq_intercom_free_packet(packet);
0074
0075 restore_preemption(prev_mode);
0076 }
0077
0078 static void transmit_task(rtems_task_argument arg)
0079 {
0080 rtems_status_code sc = RTEMS_SUCCESSFUL;
0081 uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) arg;
0082 rtems_chain_control *fifo = &ctx->transmit_fifo;
0083 struct rtems_termios_tty *tty = ctx->tty;
0084
0085 while (true) {
0086 intercom_packet *packet = NULL;
0087 sc = rtems_chain_get_with_wait(
0088 fifo,
0089 TRANSMIT_EVENT,
0090 RTEMS_NO_TIMEOUT,
0091 (rtems_chain_node **) &packet
0092 );
0093 assert(sc == RTEMS_SUCCESSFUL);
0094
0095
0096 rtems_mode prev_mode = disable_preemption();
0097
0098 size_t size = packet->size;
0099 qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_MASTER_CORE, packet);
0100 rtems_termios_dequeue_characters(tty, (int) size);
0101
0102 restore_preemption(prev_mode);
0103 }
0104 }
0105
0106 static void create_transmit_task(
0107 uart_bridge_slave_context *ctx
0108 )
0109 {
0110 rtems_status_code sc = RTEMS_SUCCESSFUL;
0111 rtems_id task = RTEMS_ID_NONE;
0112 char index = (char) ('0' + ctx->type - INTERCOM_TYPE_UART_0);
0113
0114 sc = rtems_task_create(
0115 rtems_build_name('U', 'B', 'T', index),
0116 QORIQ_UART_BRIDGE_TASK_PRIORITY,
0117 0,
0118 RTEMS_DEFAULT_MODES,
0119 RTEMS_DEFAULT_ATTRIBUTES,
0120 &task
0121 );
0122 assert(sc == RTEMS_SUCCESSFUL);
0123
0124 sc = rtems_task_start(
0125 task,
0126 transmit_task,
0127 (rtems_task_argument) ctx
0128 );
0129 assert(sc == RTEMS_SUCCESSFUL);
0130
0131 ctx->transmit_task = task;
0132 }
0133
0134 static bool first_open(
0135 struct rtems_termios_tty *tty,
0136 rtems_termios_device_context *base,
0137 struct termios *term,
0138 rtems_libio_open_close_args_t *args
0139 )
0140 {
0141 uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base;
0142 intercom_type type = ctx->type;
0143
0144 ctx->tty = tty;
0145 rtems_termios_set_initial_baud(tty, 115200);
0146 create_transmit_task(ctx);
0147 qoriq_intercom_service_install(type, uart_bridge_slave_service, ctx);
0148
0149 return true;
0150 }
0151
0152 static void last_close(
0153 struct rtems_termios_tty *tty,
0154 rtems_termios_device_context *base,
0155 rtems_libio_open_close_args_t *args
0156 )
0157 {
0158 uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base;
0159
0160 qoriq_intercom_service_remove(ctx->type);
0161 }
0162
0163 static void write_with_interrupts(
0164 rtems_termios_device_context *base,
0165 const char *buf,
0166 size_t len
0167 )
0168 {
0169 if (len > 0) {
0170 rtems_status_code sc = RTEMS_SUCCESSFUL;
0171 uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base;
0172 intercom_packet *packet = qoriq_intercom_allocate_packet(
0173 ctx->type,
0174 INTERCOM_SIZE_64
0175 );
0176
0177 packet->size = len;
0178 memcpy(packet->data, buf, len);
0179
0180
0181
0182
0183
0184 sc = rtems_chain_append_with_notification(
0185 &ctx->transmit_fifo,
0186 &packet->glue.node,
0187 ctx->transmit_task,
0188 TRANSMIT_EVENT
0189 );
0190 assert(sc == RTEMS_SUCCESSFUL);
0191 }
0192 }
0193
0194 static bool set_attributes(
0195 rtems_termios_device_context *base,
0196 const struct termios *term
0197 )
0198 {
0199 return false;
0200 }
0201
0202 const rtems_termios_device_handler qoriq_uart_bridge_slave = {
0203 .first_open = first_open,
0204 .last_close = last_close,
0205 .write = write_with_interrupts,
0206 .set_attributes = set_attributes,
0207 .mode = TERMIOS_IRQ_DRIVEN
0208 };