Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:57

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsPowerPCQorIQ
0007  *
0008  * @brief Console configuration.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2010, 2017 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #include <string.h>
0037 
0038 #include <libfdt.h>
0039 
0040 #include <rtems/bspIo.h>
0041 
0042 #include <libchip/ns16550.h>
0043 
0044 #include <asm/epapr_hcalls.h>
0045 
0046 #include <bsp.h>
0047 #include <bsp/fdt.h>
0048 #include <bsp/irq.h>
0049 #include <bsp/qoriq.h>
0050 #include <bsp/intercom.h>
0051 #include <bsp/uart-bridge.h>
0052 #include <bsp/console-termios.h>
0053 
0054 static void output_char(char c);
0055 
0056 #ifdef QORIQ_IS_HYPERVISOR_GUEST
0057 typedef struct {
0058   rtems_termios_device_context base;
0059   uint32_t handle;
0060 } qoriq_bc_context;
0061 
0062 static bool qoriq_bc_probe(rtems_termios_device_context *base)
0063 {
0064   qoriq_bc_context *ctx;
0065   const void *fdt;
0066   int node;
0067   const uint32_t *handle;
0068   int len;
0069 
0070   fdt = bsp_fdt_get();
0071 
0072   node = fdt_node_offset_by_compatible(fdt, -1, "epapr,hv-byte-channel");
0073   if (node < 0) {
0074     return false;
0075   }
0076 
0077   handle = fdt_getprop(fdt, node, "hv-handle", &len);
0078   if (handle == NULL || len != 4) {
0079     return false;
0080   }
0081 
0082   ctx = (qoriq_bc_context *) base;
0083   ctx->handle = fdt32_to_cpu(*handle);
0084 
0085   BSP_output_char = output_char;
0086   return true;
0087 }
0088 
0089 static int qoriq_bc_read_polled(rtems_termios_device_context *base)
0090 {
0091   qoriq_bc_context *ctx;
0092   char buf[EV_BYTE_CHANNEL_MAX_BYTES];
0093   unsigned int count;
0094   unsigned int status;
0095 
0096   ctx = (qoriq_bc_context *) base;
0097   count = 1;
0098   status = ev_byte_channel_receive(ctx->handle, &count, buf);
0099 
0100   if (status != EV_SUCCESS || count == 0) {
0101     return -1;
0102   }
0103 
0104   return (unsigned char) buf[0];
0105 }
0106 
0107 static void qoriq_bc_write_polled(
0108   rtems_termios_device_context *base,
0109   const char *buf,
0110   size_t len
0111 )
0112 {
0113   qoriq_bc_context *ctx;
0114   uint32_t handle;
0115 
0116   ctx = (qoriq_bc_context *) base;
0117   handle = ctx->handle;
0118 
0119   while (len > 0) {
0120     unsigned int count;
0121     unsigned int status;
0122     char buf2[EV_BYTE_CHANNEL_MAX_BYTES];
0123     const char *out;
0124 
0125     if (len < EV_BYTE_CHANNEL_MAX_BYTES) {
0126       count = len;
0127       out = memcpy(buf2, buf, len);
0128     } else {
0129       count = EV_BYTE_CHANNEL_MAX_BYTES;
0130       out = buf;
0131     }
0132 
0133     status = ev_byte_channel_send(handle, &count, out);
0134 
0135     if (status == EV_SUCCESS) {
0136       len -= count;
0137       buf += count;
0138     }
0139   }
0140 }
0141 
0142 static const rtems_termios_device_handler qoriq_bc_handler_polled = {
0143   .poll_read = qoriq_bc_read_polled,
0144   .write = qoriq_bc_write_polled,
0145   .mode = TERMIOS_POLLED
0146 };
0147 
0148 static qoriq_bc_context qoriq_bc_context_0 = {
0149   .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("BC 0"),
0150 };
0151 #endif /* QORIQ_IS_HYPERVISOR_GUEST */
0152 
0153 #if (QORIQ_UART_0_ENABLE + QORIQ_UART_BRIDGE_0_ENABLE == 2) \
0154   || (QORIQ_UART_1_ENABLE + QORIQ_UART_BRIDGE_1_ENABLE == 2)
0155   #define BRIDGE_MASTER
0156 #elif QORIQ_UART_BRIDGE_0_ENABLE || QORIQ_UART_BRIDGE_1_ENABLE
0157   #define BRIDGE_SLAVE
0158 #endif
0159 
0160 #ifdef BSP_USE_UART_INTERRUPTS
0161   #define DEVICE_FNS &ns16550_handler_interrupt
0162 #else
0163   #define DEVICE_FNS &ns16550_handler_polled
0164 #endif
0165 
0166 #if QORIQ_UART_0_ENABLE || QORIQ_UART_1_ENABLE
0167   static bool uart_probe(rtems_termios_device_context *base)
0168   {
0169     ns16550_context *ctx = (ns16550_context *) base;
0170 
0171     ctx->clock = BSP_bus_frequency;
0172 
0173     return ns16550_probe(base);
0174   }
0175 
0176   static uint8_t get_register(uintptr_t addr, uint8_t i)
0177   {
0178     volatile uint8_t *reg = (uint8_t *) addr;
0179 
0180     return reg [i];
0181   }
0182 
0183   static void set_register(uintptr_t addr, uint8_t i, uint8_t val)
0184   {
0185     volatile uint8_t *reg = (uint8_t *) addr;
0186 
0187     reg [i] = val;
0188   }
0189 #endif
0190 
0191 #if QORIQ_UART_0_ENABLE
0192 static ns16550_context qoriq_uart_context_0 = {
0193   .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
0194   .get_reg = get_register,
0195   .set_reg = set_register,
0196   .port = (uintptr_t) &qoriq.uart_0,
0197   .irq = QORIQ_IRQ_DUART_1,
0198   .initial_baud = BSP_CONSOLE_BAUD
0199 };
0200 #endif
0201 
0202 #if QORIQ_UART_1_ENABLE
0203 static ns16550_context qoriq_uart_context_1 = {
0204   .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
0205   .get_reg = get_register,
0206   .set_reg = set_register,
0207   .port = (uintptr_t) &qoriq.uart_1,
0208   .irq = QORIQ_IRQ_DUART_1,
0209   .initial_baud = BSP_CONSOLE_BAUD
0210 };
0211 #endif
0212 
0213 #ifdef BRIDGE_MASTER
0214   #define BRIDGE_PROBE qoriq_uart_bridge_master_probe
0215   #define BRIDGE_FNS &qoriq_uart_bridge_master
0216   #if QORIQ_UART_BRIDGE_0_ENABLE
0217     static uart_bridge_master_context bridge_0_context = {
0218       .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 0"),
0219       .device_path = "/dev/ttyS0",
0220       .type = INTERCOM_TYPE_UART_0,
0221       .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
0222         bridge_0_context.transmit_fifo
0223       )
0224     };
0225     #define BRIDGE_0_CONTEXT &bridge_0_context.base
0226   #endif
0227   #if QORIQ_UART_BRIDGE_1_ENABLE
0228     static uart_bridge_master_context bridge_1_context = {
0229       .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 1"),
0230       .device_path = "/dev/ttyS1",
0231       .type = INTERCOM_TYPE_UART_1,
0232       .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
0233         bridge_1_context.transmit_fifo
0234       )
0235     };
0236     #define BRIDGE_1_CONTEXT &bridge_1_context.base
0237   #endif
0238 #endif
0239 
0240 #ifdef BRIDGE_SLAVE
0241   #define BRIDGE_PROBE console_device_probe_default
0242   #define BRIDGE_FNS &qoriq_uart_bridge_slave
0243   #if QORIQ_UART_BRIDGE_0_ENABLE
0244     static uart_bridge_slave_context bridge_0_context = {
0245       .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 0"),
0246       .type = INTERCOM_TYPE_UART_0,
0247       .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
0248         bridge_0_context.transmit_fifo
0249       )
0250     };
0251     #define BRIDGE_0_CONTEXT &bridge_0_context.base
0252   #endif
0253   #if QORIQ_UART_BRIDGE_1_ENABLE
0254     static uart_bridge_slave_context bridge_1_context = {
0255       .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 1"),
0256       .type = INTERCOM_TYPE_UART_1,
0257       .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
0258         bridge_1_context.transmit_fifo
0259       )
0260     };
0261     #define BRIDGE_1_CONTEXT &bridge_1_context.base
0262   #endif
0263 #endif
0264 
0265 const console_device console_device_table[] = {
0266   #ifdef QORIQ_IS_HYPERVISOR_GUEST
0267     {
0268       .device_file = "/dev/ttyBC0",
0269       .probe = qoriq_bc_probe,
0270       .handler = &qoriq_bc_handler_polled,
0271       .context = &qoriq_bc_context_0.base
0272     },
0273   #endif
0274   #if QORIQ_UART_0_ENABLE
0275     {
0276       .device_file = "/dev/ttyS0",
0277       .probe = uart_probe,
0278       .handler = DEVICE_FNS,
0279       .context = &qoriq_uart_context_0.base
0280     },
0281   #endif
0282   #if QORIQ_UART_1_ENABLE
0283     {
0284       .device_file = "/dev/ttyS1",
0285       .probe = uart_probe,
0286       .handler = DEVICE_FNS,
0287       .context = &qoriq_uart_context_1.base
0288     },
0289   #endif
0290   #if QORIQ_UART_BRIDGE_0_ENABLE
0291     {
0292       #if QORIQ_UART_1_ENABLE
0293         .device_file = "/dev/ttyB0",
0294       #else
0295         .device_file = "/dev/ttyS0",
0296       #endif
0297       .probe = BRIDGE_PROBE,
0298       .handler = BRIDGE_FNS,
0299       .context = BRIDGE_0_CONTEXT
0300     },
0301   #endif
0302   #if QORIQ_UART_BRIDGE_1_ENABLE
0303     {
0304       #if QORIQ_UART_1_ENABLE
0305         .device_file = "/dev/ttyB1",
0306       #else
0307         .device_file = "/dev/ttyS1",
0308       #endif
0309       .probe = BRIDGE_PROBE,
0310       .handler = BRIDGE_FNS,
0311       .context = BRIDGE_1_CONTEXT
0312     }
0313   #endif
0314 };
0315 
0316 const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
0317 
0318 static void output_char(char c)
0319 {
0320   rtems_termios_device_context *base = console_device_table[0].context;
0321 
0322 #ifdef QORIQ_IS_HYPERVISOR_GUEST
0323   qoriq_bc_write_polled(base, &c, 1);
0324 #else
0325   ns16550_polled_putchar(base, c);
0326 #endif
0327 }
0328 
0329 #ifdef QORIQ_IS_HYPERVISOR_GUEST
0330 static void qoriq_bc_output_char_init(char c)
0331 {
0332   rtems_termios_device_context *base = console_device_table[0].context;
0333 
0334   qoriq_bc_probe(base);
0335   output_char(c);
0336 }
0337 
0338 BSP_output_char_function_type BSP_output_char = qoriq_bc_output_char_init;
0339 #else
0340 BSP_output_char_function_type BSP_output_char = output_char;
0341 #endif
0342 
0343 BSP_polling_getchar_function_type BSP_poll_char = NULL;