Use the Termios device API. --- c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am | 7 +- .../arm/altera-cyclone-v/console/console-config.c | 159 +++-- c/src/lib/libbsp/arm/lpc176x/Makefile.am | 7 +- .../libbsp/arm/lpc176x/console/console-config.c | 168 +++-- c/src/lib/libbsp/arm/lpc24xx/Makefile.am | 7 +- .../libbsp/arm/lpc24xx/console/console-config.c | 151 +++-- .../lib/libbsp/arm/lpc24xx/console/uart-probe-1.c | 10 +- .../lib/libbsp/arm/lpc24xx/console/uart-probe-2.c | 10 +- .../lib/libbsp/arm/lpc24xx/console/uart-probe-3.c | 10 +- c/src/lib/libbsp/arm/lpc24xx/include/bsp.h | 12 +- c/src/lib/libbsp/arm/lpc32xx/Makefile.am | 12 +- .../libbsp/arm/lpc32xx/console/console-config.c | 259 ++++---- c/src/lib/libbsp/arm/lpc32xx/console/hsu.c | 192 +++--- c/src/lib/libbsp/arm/lpc32xx/include/hsu.h | 68 +++ c/src/lib/libbsp/arm/lpc32xx/preinstall.am | 4 + c/src/lib/libbsp/powerpc/gen83xx/Makefile.am | 10 +- .../powerpc/gen83xx/console/console-config.c | 114 ++-- .../lib/libbsp/powerpc/gen83xx/startup/bspstart.c | 34 +- c/src/lib/libbsp/powerpc/qoriq/Makefile.am | 14 +- .../libbsp/powerpc/qoriq/console/console-config.c | 195 +++--- .../powerpc/qoriq/console/uart-bridge-master.c | 88 ++- .../powerpc/qoriq/console/uart-bridge-slave.c | 114 ++-- .../lib/libbsp/powerpc/qoriq/include/uart-bridge.h | 18 +- c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c | 40 +- c/src/libchip/Makefile.am | 1 + c/src/libchip/serial/ns16550-context.c | 677 +++++++++++++++++++++ c/src/libchip/serial/ns16550.c | 100 ++- c/src/libchip/serial/ns16550.h | 32 + c/src/libchip/serial/ns16550_p.h | 76 --- 29 files changed, 1640 insertions(+), 949 deletions(-) create mode 100644 c/src/lib/libbsp/arm/lpc32xx/include/hsu.h create mode 100644 c/src/libchip/serial/ns16550-context.c
diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am index fdae4f2..6e2d431 100644 --- a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am @@ -190,11 +190,8 @@ libbsp_a_SOURCES += ../shared/arm-gic-irq.c libbsp_a_SOURCES += network/network.c # Console -libbsp_a_SOURCES += ../../shared/console.c -libbsp_a_SOURCES += ../../shared/console_control.c -libbsp_a_SOURCES += ../../shared/console_read.c -libbsp_a_SOURCES += ../../shared/console_select_simple.c -libbsp_a_SOURCES += ../../shared/console_write.c +libbsp_a_SOURCES += ../../shared/console-termios-init.c +libbsp_a_SOURCES += ../../shared/console-termios.c libbsp_a_SOURCES += console/console-config.c # Clock diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c index c2a287c..5cc7849 100644 --- a/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -12,28 +12,23 @@ * http://www.rtems.org/license/LICENSE. */ -#include <assert.h> -#include <stdint.h> -#include <stdbool.h> -#include <libchip/serial.h> #include <libchip/ns16550.h> #include <bsp.h> #include <bsp/irq.h> #include <bsp/alt_clock_manager.h> +#include <bsp/console-termios.h> #include "socal/alt_rstmgr.h" #include "socal/socal.h" #include "socal/alt_uart.h" #include "socal/hps.h" #ifdef BSP_USE_UART_INTERRUPTS - #define DEVICE_FNS &ns16550_fns + #define DEVICE_FNS &ns16550_handler_interrupt #else - #define DEVICE_FNS &ns16550_fns_polled + #define DEVICE_FNS &ns16550_handler_polled #endif -static bool altera_cyclone_v_uart_probe( int minor ); - static uint8_t altera_cyclone_v_uart_get_register(uintptr_t addr, uint8_t i) { volatile uint32_t *reg = (volatile uint32_t *) addr; @@ -48,92 +43,25 @@ static void altera_cyclone_v_uart_set_register(uintptr_t addr, uint8_t i, uint8_ reg [i] = val; } -console_tbl Console_Configuration_Ports[] = { -#ifdef CYCLONE_V_CONFIG_CONSOLE - { - .sDeviceName = "/dev/ttyS0", - .deviceType = SERIAL_NS16550, - .pDeviceFns = DEVICE_FNS, - .deviceProbe = altera_cyclone_v_uart_probe, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *)CYCLONE_V_UART_BAUD, - .ulCtrlPort1 = (uint32_t)ALT_UART0_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = (uint32_t)ALT_UART0_ADDR, - .getRegister = altera_cyclone_v_uart_get_register, - .setRegister = altera_cyclone_v_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 0, - .ulIntVector = ALT_INT_INTERRUPT_UART0 - }, -#endif -#ifdef CYCLONE_V_CONFIG_UART_1 - { - .sDeviceName = "/dev/ttyS1", - .deviceType = SERIAL_NS16550, - .pDeviceFns = DEVICE_FNS, - .deviceProbe = altera_cyclone_v_uart_probe, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *)CYCLONE_V_UART_BAUD, - .ulCtrlPort1 = (uint32_t)ALT_UART1_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = (uint32_t)ALT_UART1_ADDR, - .getRegister = altera_cyclone_v_uart_get_register, - .setRegister = altera_cyclone_v_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 0, - .ulIntVector = ALT_INT_INTERRUPT_UART1 - } -#endif -}; - -unsigned long Console_Configuration_Count = - RTEMS_ARRAY_SIZE(Console_Configuration_Ports); - -bool altera_cyclone_v_uart_probe(int minor) +static bool altera_cyclone_v_uart_probe( + rtems_termios_device_context *base, + uint32_t uart_set_mask +) { + ns16550_context *ctx = (ns16550_context *) base; bool ret = true; - uint32_t uart_set_mask; uint32_t ucr; ALT_STATUS_CODE sc; - void* location; + void* location = (void *) ctx->port; /* The ALT_CLK_L4_SP is required for all SoCFPGA UARTs. * Check that it's enabled. */ - assert( alt_clk_is_enabled(ALT_CLK_L4_SP) == ALT_E_TRUE ); if ( alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE ) { ret = false; } if ( ret ) { - switch(minor) - { - case(0): - /* UART 0 */ - uart_set_mask = ALT_RSTMGR_PERMODRST_UART0_SET_MSK; - location = ALT_UART0_ADDR; - break; - case(1): - /* UART 1 */ - uart_set_mask = ALT_RSTMGR_PERMODRST_UART1_SET_MSK; - location = ALT_UART1_ADDR; - break; - default: - /* Unknown case */ - assert( minor == 0 || minor == 1 ); - ret = false; - break; - } - } - if ( ret ) { - sc = alt_clk_freq_get(ALT_CLK_L4_SP, &Console_Configuration_Ports[minor].ulClock); - assert( sc == ALT_E_SUCCESS ); + sc = alt_clk_freq_get(ALT_CLK_L4_SP, &ctx->clock); if ( sc != ALT_E_SUCCESS ) { ret = false; } @@ -145,8 +73,6 @@ bool altera_cyclone_v_uart_probe(int minor) // Verify the UCR (UART Component Version) ucr = alt_read_word( ALT_UART_UCV_ADDR( location ) ); - - assert( ucr == ALT_UART_UCV_UART_COMPONENT_VER_RESET ); if ( ucr != ALT_UART_UCV_UART_COMPONENT_VER_RESET ) { ret = false; } @@ -158,22 +84,75 @@ bool altera_cyclone_v_uart_probe(int minor) // Read the MSR to work around case:119085. (void)alt_read_word( ALT_UART_MSR_ADDR( location ) ); + + ret = ns16550_probe( base ); } return ret; } +#ifdef CYCLONE_V_CONFIG_CONSOLE +static bool altera_cyclone_v_uart_probe_0(rtems_termios_device_context *base) +{ + return altera_cyclone_v_uart_probe(base, ALT_RSTMGR_PERMODRST_UART0_SET_MSK); +} + +static ns16550_context altera_cyclone_v_uart_context_0 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"), + .get_reg = altera_cyclone_v_uart_get_register, + .set_reg = altera_cyclone_v_uart_set_register, + .port = (uintptr_t) ALT_UART0_ADDR, + .irq = ALT_INT_INTERRUPT_UART0, + .initial_baud = CYCLONE_V_UART_BAUD +}; +#endif + +#ifdef CYCLONE_V_CONFIG_CONSOLE +static bool altera_cyclone_v_uart_probe_1(rtems_termios_device_context *base) +{ + return altera_cyclone_v_uart_probe(base, ALT_RSTMGR_PERMODRST_UART1_SET_MSK); +} + +static ns16550_context altera_cyclone_v_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .get_reg = altera_cyclone_v_uart_get_register, + .set_reg = altera_cyclone_v_uart_set_register, + .port = (uintptr_t) ALT_UART1_ADDR, + .irq = ALT_INT_INTERRUPT_UART1, + .initial_baud = CYCLONE_V_UART_BAUD +}; +#endif + +const console_device console_device_table[] = { + #ifdef CYCLONE_V_CONFIG_CONSOLE + { + .device_file = "/dev/ttyS0", + .probe = altera_cyclone_v_uart_probe_0, + .handler = DEVICE_FNS, + .context = &altera_cyclone_v_uart_context_0.base + }, + #endif + #ifdef CYCLONE_V_CONFIG_UART_1 + { + .device_file = "/dev/ttyS1", + .probe = altera_cyclone_v_uart_probe_1, + .handler = DEVICE_FNS, + .context = &altera_cyclone_v_uart_context_1.base + }, + #endif +}; + +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); + static void output_char(char c) { - int minor = (int) Console_Port_Minor; - console_tbl *ct = Console_Port_Tbl != NULL ? - Console_Port_Tbl[minor] : &Console_Configuration_Ports[minor]; + rtems_termios_device_context *ctx = console_device_table[0].context; if (c == '\n') { - ns16550_outch_polled( ct, '\r' ); + ns16550_polled_putchar( ctx, '\r' ); } - ns16550_outch_polled( ct, c ); + ns16550_polled_putchar( ctx, c ); } BSP_output_char_function_type BSP_output_char = output_char; diff --git a/c/src/lib/libbsp/arm/lpc176x/Makefile.am b/c/src/lib/libbsp/arm/lpc176x/Makefile.am index bbd2fec..3f60f23 100644 --- a/c/src/lib/libbsp/arm/lpc176x/Makefile.am +++ b/c/src/lib/libbsp/arm/lpc176x/Makefile.am @@ -110,11 +110,8 @@ libbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq-dispatch.c libbsp_a_SOURCES += irq/irq.c # Console -libbsp_a_SOURCES += ../../shared/console.c -libbsp_a_SOURCES += ../../shared/console_control.c -libbsp_a_SOURCES += ../../shared/console_read.c -libbsp_a_SOURCES += ../../shared/console_select.c -libbsp_a_SOURCES += ../../shared/console_write.c +libbsp_a_SOURCES += ../../shared/console-termios-init.c +libbsp_a_SOURCES += ../../shared/console-termios.c libbsp_a_SOURCES += console/console-config.c # Clock diff --git a/c/src/lib/libbsp/arm/lpc176x/console/console-config.c b/c/src/lib/libbsp/arm/lpc176x/console/console-config.c index 246a9e6..3b56a2c 100644 --- a/c/src/lib/libbsp/arm/lpc176x/console/console-config.c +++ b/c/src/lib/libbsp/arm/lpc176x/console/console-config.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2008-2011 embedded brains GmbH. All rights reserved. + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -20,12 +20,12 @@ * http://www.rtems.com/license/LICENSE. */ -#include <libchip/serial.h> #include <libchip/ns16550.h> #include <bsp.h> #include <bsp/io.h> #include <bsp/irq.h> +#include <bsp/console-termios.h> /** * @brief Gets the uart register according to the current address. @@ -62,97 +62,91 @@ static inline void lpc176x_uart_set_register( reg[ i ] = val; } -/** - * @brief Represents the uart configuration ports. - */ -console_tbl Console_Configuration_Ports[] = { #ifdef LPC176X_CONFIG_CONSOLE - { - .sDeviceName = "/dev/ttyS0", - .deviceType = SERIAL_NS16550_WITH_FDR, - .pDeviceFns = &ns16550_fns, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC176X_UART_BAUD, - .ulCtrlPort1 = UART0_BASE_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = UART0_BASE_ADDR, - .getRegister = lpc176x_uart_get_register, - .setRegister = lpc176x_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = LPC176X_PCLK, - .ulIntVector = LPC176X_IRQ_UART_0 - }, +static ns16550_context lpc176x_uart_context_0 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"), + .get_reg = lpc176x_uart_get_register, + .set_reg = lpc176x_uart_set_register, + .port = UART0_BASE_ADDR, + .irq = LPC176X_IRQ_UART_0, + .clock = LPC176X_PCLK, + .initial_baud = LPC176X_UART_BAUD, + .has_fractional_divider_register = true +}; #endif + #ifdef LPC176X_CONFIG_UART_1 - { - .sDeviceName = "/dev/ttyS1", - .deviceType = SERIAL_NS16550_WITH_FDR, - .pDeviceFns = &ns16550_fns, - .deviceProbe = lpc176x_uart_probe_1, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC176X_UART_BAUD, - .ulCtrlPort1 = UART1_BASE_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = UART1_BASE_ADDR, - .getRegister = lpc176x_uart_get_register, - .setRegister = lpc176x_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = LPC176X_PCLK, - .ulIntVector = LPC176X_IRQ_UART_1 - }, +static ns16550_context lpc176x_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .get_reg = lpc176x_uart_get_register, + .set_reg = lpc176x_uart_set_register, + .port = UART1_BASE_ADDR, + .irq = LPC176X_IRQ_UART_1, + .clock = LPC176X_PCLK, + .initial_baud = LPC176X_UART_BAUD, + .has_fractional_divider_register = true +}; #endif + #ifdef LPC176X_CONFIG_UART_2 - { - .sDeviceName = "/dev/ttyS2", - .deviceType = SERIAL_NS16550_WITH_FDR, - .pDeviceFns = &ns16550_fns, - .deviceProbe = lpc176x_uart_probe_2, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC176X_UART_BAUD, - .ulCtrlPort1 = UART2_BASE_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = UART2_BASE_ADDR, - .getRegister = lpc176x_uart_get_register, - .setRegister = lpc176x_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = LPC176X_PCLK, - .ulIntVector = LPC176X_IRQ_UART_2 - }, +static ns16550_context lpc176x_uart_context_2 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"), + .get_reg = lpc176x_uart_get_register, + .set_reg = lpc176x_uart_set_register, + .port = UART2_BASE_ADDR, + .irq = LPC176X_IRQ_UART_2, + .clock = LPC176X_PCLK, + .initial_baud = LPC176X_UART_BAUD, + .has_fractional_divider_register = true +}; #endif + #ifdef LPC176X_CONFIG_UART_3 - { - .sDeviceName = "/dev/ttyS3", - .deviceType = SERIAL_NS16550_WITH_FDR, - .pDeviceFns = &ns16550_fns, - .deviceProbe = lpc176x_uart_probe_3, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC176X_UART_BAUD, - .ulCtrlPort1 = UART3_BASE_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = UART3_BASE_ADDR, - .getRegister = lpc176x_uart_get_register, - .setRegister = lpc176x_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = LPC176X_PCLK, - .ulIntVector = LPC176X_IRQ_UART_3 - }, -#endif +static ns16550_context lpc176x_uart_context_3 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"), + .get_reg = lpc176x_uart_get_register, + .set_reg = lpc176x_uart_set_register, + .port = UART3_BASE_ADDR, + .irq = LPC176X_IRQ_UART_3, + .clock = LPC176X_PCLK, + .initial_baud = LPC176X_UART_BAUD, + .has_fractional_divider_register = true }; +#endif -#define LPC176X_UART_COUNT ( sizeof( Console_Configuration_Ports ) \ - / sizeof( Console_Configuration_Ports[ 0 ] ) ) +const console_device console_device_table[] = { + #ifdef LPC176X_CONFIG_CONSOLE + { + .device_file = "/dev/ttyS0", + .probe = console_device_probe_default, + .handler = &ns16550_handler_interrupt, + .context = &lpc176x_uart_context_0.base + }, + #endif + #ifdef LPC176X_CONFIG_UART_1 + { + .device_file = "/dev/ttyS1", + .probe = ns16550_probe, + .handler = &ns16550_handler_interrupt, + .context = &lpc176x_uart_context_1.base + }, + #endif + #ifdef LPC176X_CONFIG_UART_2 + { + .device_file = "/dev/ttyS2", + .probe = ns16550_probe, + .handler = &ns16550_handler_interrupt, + .context = &lpc176x_uart_context_2.base + }, + #endif + #ifdef LPC176X_CONFIG_UART_3 + { + .device_file = "/dev/ttyS3", + .probe = ns16550_probe, + .handler = &ns16550_handler_interrupt, + .context = &lpc176x_uart_context_3.base + }, + #endif +}; -unsigned long Console_Configuration_Count = LPC176X_UART_COUNT; +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); diff --git a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am index 3ff85d6..c7fcb86 100644 --- a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am +++ b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am @@ -121,11 +121,8 @@ libbsp_a_SOURCES += irq/irq.c libbsp_a_SOURCES += irq/irq-dispatch.c # Console -libbsp_a_SOURCES += ../../shared/console.c -libbsp_a_SOURCES += ../../shared/console_control.c -libbsp_a_SOURCES += ../../shared/console_read.c -libbsp_a_SOURCES += ../../shared/console_select.c -libbsp_a_SOURCES += ../../shared/console_write.c +libbsp_a_SOURCES += ../../shared/console-termios-init.c +libbsp_a_SOURCES += ../../shared/console-termios.c libbsp_a_SOURCES += console/console-config.c libbsp_a_SOURCES += console/uart-probe-1.c libbsp_a_SOURCES += console/uart-probe-2.c diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c b/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c index cce146f..de94552 100644 --- a/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c +++ b/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2008-2011 embedded brains GmbH. All rights reserved. + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -20,13 +20,15 @@ * http://www.rtems.org/license/LICENSE. */ -#include <libchip/serial.h> +#include <rtems/console.h> + #include <libchip/ns16550.h> #include <bsp.h> #include <bsp/lpc24xx.h> #include <bsp/irq.h> #include <bsp/io.h> +#include <bsp/console-termios.h> static uint8_t lpc24xx_uart_get_register(uintptr_t addr, uint8_t i) { @@ -42,94 +44,91 @@ static void lpc24xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val) reg [i] = val; } -console_tbl Console_Configuration_Ports [] = { +#ifdef LPC24XX_CONFIG_CONSOLE +static ns16550_context lpc24xx_uart_context_0 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"), + .get_reg = lpc24xx_uart_get_register, + .set_reg = lpc24xx_uart_set_register, + .port = UART0_BASE_ADDR, + .irq = LPC24XX_IRQ_UART_0, + .clock = LPC24XX_PCLK, + .initial_baud = LPC24XX_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +#ifdef LPC24XX_CONFIG_UART_1 +static ns16550_context lpc24xx_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .get_reg = lpc24xx_uart_get_register, + .set_reg = lpc24xx_uart_set_register, + .port = UART1_BASE_ADDR, + .irq = LPC24XX_IRQ_UART_1, + .clock = LPC24XX_PCLK, + .initial_baud = LPC24XX_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +#ifdef LPC24XX_CONFIG_UART_2 +static ns16550_context lpc24xx_uart_context_2 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"), + .get_reg = lpc24xx_uart_get_register, + .set_reg = lpc24xx_uart_set_register, + .port = UART2_BASE_ADDR, + .irq = LPC24XX_IRQ_UART_2, + .clock = LPC24XX_PCLK, + .initial_baud = LPC24XX_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +#ifdef LPC24XX_CONFIG_UART_3 +static ns16550_context lpc24xx_uart_context_3 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"), + .get_reg = lpc24xx_uart_get_register, + .set_reg = lpc24xx_uart_set_register, + .port = UART3_BASE_ADDR, + .irq = LPC24XX_IRQ_UART_3, + .clock = LPC24XX_PCLK, + .initial_baud = LPC24XX_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +const console_device console_device_table[] = { #ifdef LPC24XX_CONFIG_CONSOLE { - .sDeviceName = "/dev/ttyS0", - .deviceType = SERIAL_NS16550_WITH_FDR, - .pDeviceFns = &ns16550_fns, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC24XX_UART_BAUD, - .ulCtrlPort1 = UART0_BASE_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = UART0_BASE_ADDR, - .getRegister = lpc24xx_uart_get_register, - .setRegister = lpc24xx_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = LPC24XX_PCLK, - .ulIntVector = LPC24XX_IRQ_UART_0 + .device_file = "/dev/ttyS0", + .probe = console_device_probe_default, + .handler = &ns16550_handler_interrupt, + .context = &lpc24xx_uart_context_0.base }, #endif #ifdef LPC24XX_CONFIG_UART_1 { - .sDeviceName = "/dev/ttyS1", - .deviceType = SERIAL_NS16550_WITH_FDR, - .pDeviceFns = &ns16550_fns, - .deviceProbe = lpc24xx_uart_probe_1, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC24XX_UART_BAUD, - .ulCtrlPort1 = UART1_BASE_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = UART1_BASE_ADDR, - .getRegister = lpc24xx_uart_get_register, - .setRegister = lpc24xx_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = LPC24XX_PCLK, - .ulIntVector = LPC24XX_IRQ_UART_1 + .device_file = "/dev/ttyS1", + .probe = lpc24xx_uart_probe_1, + .handler = &ns16550_handler_interrupt, + .context = &lpc24xx_uart_context_1.base }, #endif #ifdef LPC24XX_CONFIG_UART_2 { - .sDeviceName = "/dev/ttyS2", - .deviceType = SERIAL_NS16550_WITH_FDR, - .pDeviceFns = &ns16550_fns, - .deviceProbe = lpc24xx_uart_probe_2, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC24XX_UART_BAUD, - .ulCtrlPort1 = UART2_BASE_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = UART2_BASE_ADDR, - .getRegister = lpc24xx_uart_get_register, - .setRegister = lpc24xx_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = LPC24XX_PCLK, - .ulIntVector = LPC24XX_IRQ_UART_2 + .device_file = "/dev/ttyS2", + .probe = lpc24xx_uart_probe_2, + .handler = &ns16550_handler_interrupt, + .context = &lpc24xx_uart_context_2.base }, #endif #ifdef LPC24XX_CONFIG_UART_3 { - .sDeviceName = "/dev/ttyS3", - .deviceType = SERIAL_NS16550_WITH_FDR, - .pDeviceFns = &ns16550_fns, - .deviceProbe = lpc24xx_uart_probe_3, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC24XX_UART_BAUD, - .ulCtrlPort1 = UART3_BASE_ADDR, - .ulCtrlPort2 = 0, - .ulDataPort = UART3_BASE_ADDR, - .getRegister = lpc24xx_uart_get_register, - .setRegister = lpc24xx_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = LPC24XX_PCLK, - .ulIntVector = LPC24XX_IRQ_UART_3 + .device_file = "/dev/ttyS3", + .probe = lpc24xx_uart_probe_3, + .handler = &ns16550_handler_interrupt, + .context = &lpc24xx_uart_context_3.base }, #endif }; -#define LPC24XX_UART_COUNT \ - (sizeof(Console_Configuration_Ports) \ - / sizeof(Console_Configuration_Ports [0])) -unsigned long Console_Configuration_Count = LPC24XX_UART_COUNT; +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c index e3af151..3b5f080 100644 --- a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c +++ b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2011-2013 embedded brains GmbH. All rights reserved. + * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -20,10 +20,12 @@ * http://www.rtems.org/license/LICENSE. */ +#include <libchip/ns16550.h> + #include <bsp.h> #include <bsp/io.h> -bool lpc24xx_uart_probe_1(int minor) +bool lpc24xx_uart_probe_1(rtems_termios_device_context *context) { static const lpc24xx_pin_range pins [] = { LPC24XX_PIN_UART_1_TXD_P0_15, @@ -34,5 +36,5 @@ bool lpc24xx_uart_probe_1(int minor) lpc24xx_module_enable(LPC24XX_MODULE_UART_1, LPC24XX_MODULE_PCLK_DEFAULT); lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION); - return true; + return ns16550_probe(context); } diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c index 4f69d7f..d45dbb7 100644 --- a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c +++ b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2011-2013 embedded brains GmbH. All rights reserved. + * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -20,10 +20,12 @@ * http://www.rtems.org/license/LICENSE. */ +#include <libchip/ns16550.h> + #include <bsp.h> #include <bsp/io.h> -bool lpc24xx_uart_probe_2(int minor) +bool lpc24xx_uart_probe_2(rtems_termios_device_context *context) { static const lpc24xx_pin_range pins [] = { LPC24XX_PIN_UART_2_TXD_P0_10, @@ -34,5 +36,5 @@ bool lpc24xx_uart_probe_2(int minor) lpc24xx_module_enable(LPC24XX_MODULE_UART_2, LPC24XX_MODULE_PCLK_DEFAULT); lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION); - return true; + return ns16550_probe(context); } diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c index d71002f..fad932e 100644 --- a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c +++ b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2011-2013 embedded brains GmbH. All rights reserved. + * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -20,10 +20,12 @@ * http://www.rtems.org/license/LICENSE. */ +#include <libchip/ns16550.h> + #include <bsp.h> #include <bsp/io.h> -bool lpc24xx_uart_probe_3(int minor) +bool lpc24xx_uart_probe_3(rtems_termios_device_context *context) { static const lpc24xx_pin_range pins [] = { LPC24XX_PIN_UART_3_TXD_P0_0, @@ -34,5 +36,5 @@ bool lpc24xx_uart_probe_3(int minor) lpc24xx_module_enable(LPC24XX_MODULE_UART_3, LPC24XX_MODULE_PCLK_DEFAULT); lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION); - return true; + return ns16550_probe(context); } diff --git a/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h b/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h index fad125a..e8c5d9a 100644 --- a/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h +++ b/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved. + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -53,6 +53,8 @@ extern "C" { struct rtems_bsdnet_ifconfig; +struct rtems_termios_device_context; + /** * @defgroup lpc24xx LPC24XX Support * @@ -111,11 +113,11 @@ void *bsp_idle_thread(uintptr_t ignored); void bsp_restart(void *addr); -bool lpc24xx_uart_probe_1(int minor); +bool lpc24xx_uart_probe_1(struct rtems_termios_device_context *context); -bool lpc24xx_uart_probe_2(int minor); +bool lpc24xx_uart_probe_2(struct rtems_termios_device_context *context); -bool lpc24xx_uart_probe_3(int minor); +bool lpc24xx_uart_probe_3(struct rtems_termios_device_context *context); /** @} */ diff --git a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am index 0eef512..524d07e 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am +++ b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am @@ -48,6 +48,7 @@ include_bsp_HEADERS += include/lpc-clock-config.h include_bsp_HEADERS += include/lpc-ethernet-config.h include_bsp_HEADERS += include/nand-mlc.h include_bsp_HEADERS += include/boot.h +include_bsp_HEADERS += include/hsu.h include_bsp_HEADERS += include/i2c.h include_bsp_HEADERS += include/emc.h @@ -111,13 +112,10 @@ libbsp_a_SOURCES += ../../shared/src/irq-shell.c libbsp_a_SOURCES += irq/irq.c # Console -libbsp_a_SOURCES += ../../shared/console.c \ - ../../shared/console_select.c \ - console/console-config.c \ - console/hsu.c \ - ../../shared/console_read.c \ - ../../shared/console_write.c \ - ../../shared/console_control.c +libbsp_a_SOURCES += ../../shared/console-termios-init.c +libbsp_a_SOURCES += ../../shared/console-termios.c +libbsp_a_SOURCES += console/console-config.c +libbsp_a_SOURCES += console/hsu.c # Clock libbsp_a_SOURCES += ../shared/lpc/clock/lpc-clock-config.c diff --git a/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c b/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c index d288985..17e6b0a 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c +++ b/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c @@ -7,26 +7,26 @@ */ /* - * Copyright (c) 2009 - * embedded brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * <rt...@embedded-brains.de> + * Copyright (c) 2009-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */ -#include <libchip/serial.h> #include <libchip/ns16550.h> #include <bsp.h> #include <bsp/lpc32xx.h> #include <bsp/irq.h> - -extern const console_fns lpc32xx_hsu_fns; +#include <bsp/hsu.h> +#include <bsp/console-termios.h> static uint8_t lpc32xx_uart_get_register(uintptr_t addr, uint8_t i) { @@ -43,18 +43,18 @@ static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val) } #ifdef LPC32XX_UART_3_BAUD - static bool lpc32xx_uart_probe_3(int minor) + static bool lpc32xx_uart_probe_3(rtems_termios_device_context *context) { LPC32XX_UARTCLK_CTRL |= BSP_BIT32(0); LPC32XX_U3CLK = LPC32XX_CONFIG_U3CLK; LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 4, 5); - return true; + return ns16550_probe(context); } #endif #ifdef LPC32XX_UART_4_BAUD - static bool lpc32xx_uart_probe_4(int minor) + static bool lpc32xx_uart_probe_4(rtems_termios_device_context *context) { volatile lpc32xx_gpio *gpio = &lpc32xx.gpio; @@ -68,12 +68,12 @@ static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val) LPC32XX_U4CLK = LPC32XX_CONFIG_U4CLK; LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 6, 7); - return true; + return ns16550_probe(context); } #endif #ifdef LPC32XX_UART_6_BAUD - static bool lpc32xx_uart_probe_6(int minor) + static bool lpc32xx_uart_probe_6(rtems_termios_device_context *context) { /* Bypass the IrDA modulator/demodulator */ LPC32XX_UART_CTRL |= BSP_BIT32(5); @@ -82,163 +82,144 @@ static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val) LPC32XX_U6CLK = LPC32XX_CONFIG_U6CLK; LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 10, 11); - return true; + return ns16550_probe(context); } #endif /* FIXME: Console selection */ -console_tbl Console_Configuration_Ports [] = { +#ifdef LPC32XX_UART_5_BAUD +static ns16550_context lpc32xx_uart_context_5 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 5"), + .get_reg = lpc32xx_uart_get_register, + .set_reg = lpc32xx_uart_set_register, + .port = LPC32XX_BASE_UART_5, + .irq = LPC32XX_IRQ_UART_5, + .clock = 16 * LPC32XX_UART_5_BAUD, + .initial_baud = LPC32XX_UART_5_BAUD +}; +#endif + +#ifdef LPC32XX_UART_3_BAUD +static ns16550_context lpc32xx_uart_context_3 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"), + .get_reg = lpc32xx_uart_get_register, + .set_reg = lpc32xx_uart_set_register, + .port = LPC32XX_BASE_UART_3, + .irq = LPC32XX_IRQ_UART_3, + .clock = 16 * LPC32XX_UART_3_BAUD, + .initial_baud = LPC32XX_UART_3_BAUD +}; +#endif + +#ifdef LPC32XX_UART_4_BAUD +static ns16550_context lpc32xx_uart_context_4 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 4"), + .get_reg = lpc32xx_uart_get_register, + .set_reg = lpc32xx_uart_set_register, + .port = LPC32XX_BASE_UART_4, + .irq = LPC32XX_IRQ_UART_4, + .clock = 16 * LPC32XX_UART_4_BAUD, + .initial_baud = LPC32XX_UART_4_BAUD +}; +#endif + +#ifdef LPC32XX_UART_6_BAUD +static ns16550_context lpc32xx_uart_context_6 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 6"), + .get_reg = lpc32xx_uart_get_register, + .set_reg = lpc32xx_uart_set_register, + .port = LPC32XX_BASE_UART_6, + .irq = LPC32XX_IRQ_UART_6, + .clock = 16 * LPC32XX_UART_6_BAUD, + .initial_baud = LPC32XX_UART_6_BAUD +}; +#endif + +#ifdef LPC32XX_UART_1_BAUD +static lpc32xx_hsu_context lpc32xx_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_1, + .irq = LPC32XX_IRQ_UART_1, + .initial_baud = LPC32XX_UART_1_BAUD +}; +#endif + +#ifdef LPC32XX_UART_2_BAUD +static lpc32xx_hsu_context lpc32xx_uart_context_2 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"), + .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_2, + .irq = LPC32XX_IRQ_UART_2, + .initial_baud = LPC32XX_UART_2_BAUD +}; +#endif + +#ifdef LPC32XX_UART_7_BAUD +static lpc32xx_hsu_context lpc32xx_uart_context_7 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 7"), + .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_7, + .irq = LPC32XX_IRQ_UART_7, + .initial_baud = LPC32XX_UART_7_BAUD +}; +#endif + +const console_device console_device_table[] = { #ifdef LPC32XX_UART_5_BAUD { - .sDeviceName = "/dev/ttyS5", - .deviceType = SERIAL_NS16550, - .pDeviceFns = &ns16550_fns, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC32XX_UART_5_BAUD, - .ulCtrlPort1 = LPC32XX_BASE_UART_5, - .ulCtrlPort2 = 0, - .ulDataPort = LPC32XX_BASE_UART_5, - .getRegister = lpc32xx_uart_get_register, - .setRegister = lpc32xx_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 16 * LPC32XX_UART_5_BAUD, - .ulIntVector = LPC32XX_IRQ_UART_5 + .device_file = "/dev/ttyS5", + .probe = console_device_probe_default, + .handler = &ns16550_handler_interrupt, + .context = &lpc32xx_uart_context_5.base }, #endif #ifdef LPC32XX_UART_3_BAUD { - .sDeviceName = "/dev/ttyS3", - .deviceType = SERIAL_NS16550, - .pDeviceFns = &ns16550_fns, - .deviceProbe = lpc32xx_uart_probe_3, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC32XX_UART_3_BAUD, - .ulCtrlPort1 = LPC32XX_BASE_UART_3, - .ulCtrlPort2 = 0, - .ulDataPort = LPC32XX_BASE_UART_3, - .getRegister = lpc32xx_uart_get_register, - .setRegister = lpc32xx_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 16 * LPC32XX_UART_3_BAUD, - .ulIntVector = LPC32XX_IRQ_UART_3 + .device_file = "/dev/ttyS3", + .probe = lpc32xx_uart_probe_3, + .handler = &ns16550_handler_interrupt, + .context = &lpc32xx_uart_context_3.base }, #endif #ifdef LPC32XX_UART_4_BAUD { - .sDeviceName = "/dev/ttyS4", - .deviceType = SERIAL_NS16550, - .pDeviceFns = &ns16550_fns, - .deviceProbe = lpc32xx_uart_probe_4, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC32XX_UART_4_BAUD, - .ulCtrlPort1 = LPC32XX_BASE_UART_4, - .ulCtrlPort2 = 0, - .ulDataPort = LPC32XX_BASE_UART_4, - .getRegister = lpc32xx_uart_get_register, - .setRegister = lpc32xx_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 16 * LPC32XX_UART_4_BAUD, - .ulIntVector = LPC32XX_IRQ_UART_4 + .device_file = "/dev/ttyS4", + .probe = lpc32xx_uart_probe_4, + .handler = &ns16550_handler_interrupt, + .context = &lpc32xx_uart_context_4.base }, #endif #ifdef LPC32XX_UART_6_BAUD { - .sDeviceName = "/dev/ttyS6", - .deviceType = SERIAL_NS16550, - .pDeviceFns = &ns16550_fns, - .deviceProbe = lpc32xx_uart_probe_6, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC32XX_UART_6_BAUD, - .ulCtrlPort1 = LPC32XX_BASE_UART_6, - .ulCtrlPort2 = 0, - .ulDataPort = LPC32XX_BASE_UART_6, - .getRegister = lpc32xx_uart_get_register, - .setRegister = lpc32xx_uart_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 16 * LPC32XX_UART_6_BAUD, - .ulIntVector = LPC32XX_IRQ_UART_6 + .device_file = "/dev/ttyS6", + .probe = lpc32xx_uart_probe_6, + .handler = &ns16550_handler_interrupt, + .context = &lpc32xx_uart_context_6.base }, #endif #ifdef LPC32XX_UART_1_BAUD { - .sDeviceName = "/dev/ttyS1", - .deviceType = SERIAL_CUSTOM, - .pDeviceFns = &lpc32xx_hsu_fns, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC32XX_UART_1_BAUD, - .ulCtrlPort1 = LPC32XX_BASE_UART_1, - .ulCtrlPort2 = 0, - .ulDataPort = 0, - .getRegister = NULL, - .setRegister = NULL, - .getData = NULL, - .setData = NULL, - .ulClock = 16, - .ulIntVector = LPC32XX_IRQ_UART_1 + .device_file = "/dev/ttyS1", + .probe = lpc32xx_hsu_probe, + .handler = &lpc32xx_hsu_fns, + .context = &lpc32xx_uart_context_1.base }, #endif #ifdef LPC32XX_UART_2_BAUD { - .sDeviceName = "/dev/ttyS2", - .deviceType = SERIAL_CUSTOM, - .pDeviceFns = &lpc32xx_hsu_fns, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC32XX_UART_2_BAUD, - .ulCtrlPort1 = LPC32XX_BASE_UART_2, - .ulCtrlPort2 = 0, - .ulDataPort = 0, - .getRegister = NULL, - .setRegister = NULL, - .getData = NULL, - .setData = NULL, - .ulClock = 16, - .ulIntVector = LPC32XX_IRQ_UART_2 + .device_file = "/dev/ttyS2", + .probe = lpc32xx_hsu_probe, + .handler = &lpc32xx_hsu_fns, + .context = &lpc32xx_uart_context_2.base }, #endif #ifdef LPC32XX_UART_7_BAUD { - .sDeviceName = "/dev/ttyS7", - .deviceType = SERIAL_CUSTOM, - .pDeviceFns = &lpc32xx_hsu_fns, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) LPC32XX_UART_7_BAUD, - .ulCtrlPort1 = LPC32XX_BASE_UART_7, - .ulCtrlPort2 = 0, - .ulDataPort = 0, - .getRegister = NULL, - .setRegister = NULL, - .getData = NULL, - .setData = NULL, - .ulClock = 16, - .ulIntVector = LPC32XX_IRQ_UART_7 + .device_file = "/dev/ttyS7", + .probe = lpc32xx_hsu_probe, + .handler = &lpc32xx_hsu_fns, + .context = &lpc32xx_uart_context_7.base }, #endif }; -#define LPC32XX_UART_COUNT \ - (sizeof(Console_Configuration_Ports) / sizeof(Console_Configuration_Ports [0])) - -unsigned long Console_Configuration_Count = LPC32XX_UART_COUNT; +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); diff --git a/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c b/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c index 0dc4a61..8beeeef 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c +++ b/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c @@ -7,36 +7,23 @@ */ /* - * Copyright (c) 2010 - * embedded brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * <rt...@embedded-brains.de> + * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */ -#include <rtems.h> -#include <rtems/libio.h> -#include <rtems/termiostypes.h> - -#include <libchip/serial.h> -#include <libchip/sersupp.h> - #include <bsp.h> #include <bsp/lpc32xx.h> #include <bsp/irq.h> - -typedef struct { - uint32_t fifo; - uint32_t level; - uint32_t iir; - uint32_t ctrl; - uint32_t rate; -} lpc32xx_hsu; +#include <bsp/hsu.h> #define HSU_FIFO_SIZE 64 @@ -60,54 +47,29 @@ typedef struct { /* We are interested in RX timeout, RX trigger and TX trigger interrupts */ #define HSU_IIR_MASK 0x7U -static int lpc32xx_hsu_first_open(int major, int minor, void *arg) -{ - rtems_libio_open_close_args_t *oca = arg; - struct rtems_termios_tty *tty = oca->iop->data1; - console_tbl *ct = Console_Port_Tbl [minor]; - console_data *cd = &Console_Port_Data [minor]; - volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1; - - cd->termios_data = tty; - rtems_termios_set_initial_baud(tty, (int32_t) ct->pDeviceParams); - hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED; - - return 0; -} - -static ssize_t lpc32xx_hsu_write(int minor, const char *buf, size_t len) +bool lpc32xx_hsu_probe(rtems_termios_device_context *base) { - console_tbl *ct = Console_Port_Tbl [minor]; - console_data *cd = &Console_Port_Data [minor]; - volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1; - size_t tx_level = (hsu->level & HSU_LEVEL_TX_MASK) >> HSU_LEVEL_TX_SHIFT; - size_t tx_free = HSU_FIFO_SIZE - tx_level; - size_t i = 0; - size_t out = len > tx_free ? tx_free : len; + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; - for (i = 0; i < out; ++i) { - hsu->fifo = buf [i]; - } + hsu->ctrl = HSU_CTRL_INTR_DISABLED; - if (len > 0) { - cd->pDeviceContext = (void *) out; - cd->bActive = true; - hsu->ctrl = HSU_CTRL_RX_AND_TX_INTR_ENABLED; + /* Drain FIFOs */ + while (hsu->level != 0) { + hsu->fifo; } - return 0; + return true; } static void lpc32xx_hsu_interrupt_handler(void *arg) { - int minor = (int) arg; - console_tbl *ct = Console_Port_Tbl [minor]; - console_data *cd = &Console_Port_Data [minor]; - volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1; + rtems_termios_tty *tty = arg; + lpc32xx_hsu_context *ctx = rtems_termios_get_device_context(tty); + volatile lpc32xx_hsu *hsu = ctx->hsu; /* Iterate until no more interrupts are pending */ do { - int chars_to_dequeue = (int) cd->pDeviceContext; int rv = 0; int i = 0; char buf [HSU_FIFO_SIZE]; @@ -125,49 +87,97 @@ static void lpc32xx_hsu_interrupt_handler(void *arg) break; } } - rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i); + rtems_termios_enqueue_raw_characters(tty, buf, i); /* Dequeue transmitted characters */ - cd->pDeviceContext = 0; - rv = rtems_termios_dequeue_characters(cd->termios_data, chars_to_dequeue); + rv = rtems_termios_dequeue_characters(tty, (int) ctx->chars_in_transmission); if (rv == 0) { /* Nothing to transmit */ - cd->bActive = false; - hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED; - hsu->iir = HSU_IIR_TX; } } while ((hsu->iir & HSU_IIR_MASK) != 0); } -static void lpc32xx_hsu_initialize(int minor) +static bool lpc32xx_hsu_first_open( + struct rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) { - console_tbl *ct = Console_Port_Tbl [minor]; - console_data *cd = &Console_Port_Data [minor]; - volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1; - - hsu->ctrl = HSU_CTRL_INTR_DISABLED; + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; + rtems_status_code sc; + bool ok; - cd->bActive = false; - cd->pDeviceContext = 0; + sc = rtems_interrupt_handler_install( + ctx->irq, + "HSU", + RTEMS_INTERRUPT_UNIQUE, + lpc32xx_hsu_interrupt_handler, + tty + ); + ok = sc == RTEMS_SUCCESSFUL; - /* Drain FIFOs */ - while (hsu->level != 0) { - hsu->fifo; + if (ok) { + rtems_termios_set_initial_baud(tty, ctx->initial_baud); + hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED; } - rtems_interrupt_handler_install( - ct->ulIntVector, - "HSU", - RTEMS_INTERRUPT_UNIQUE, + return ok; +} + +static void lpc32xx_hsu_last_close( + struct rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) +{ + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; + + hsu->ctrl = HSU_CTRL_INTR_DISABLED; + + rtems_interrupt_handler_remove( + ctx->irq, lpc32xx_hsu_interrupt_handler, - (void *) minor + tty ); } -static int lpc32xx_hsu_set_attributes(int minor, const struct termios *term) +static void lpc32xx_hsu_write( + rtems_termios_device_context *base, + const char *buf, + size_t len +) +{ + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; + size_t tx_level = (hsu->level & HSU_LEVEL_TX_MASK) >> HSU_LEVEL_TX_SHIFT; + size_t tx_free = HSU_FIFO_SIZE - tx_level; + size_t i = 0; + size_t out = len > tx_free ? tx_free : len; + + for (i = 0; i < out; ++i) { + hsu->fifo = buf [i]; + } + + ctx->chars_in_transmission = out; + + if (len > 0) { + hsu->ctrl = HSU_CTRL_RX_AND_TX_INTR_ENABLED; + } else { + hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED; + hsu->iir = HSU_IIR_TX; + } +} + +static bool lpc32xx_hsu_set_attributes( + rtems_termios_device_context *base, + const struct termios *term +) { - console_tbl *ct = Console_Port_Tbl [minor]; - volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1; + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; int baud_flags = term->c_cflag & CBAUD; if (baud_flags != 0) { @@ -186,17 +196,13 @@ static int lpc32xx_hsu_set_attributes(int minor, const struct termios *term) } } - return 0; + return true; } -const console_fns lpc32xx_hsu_fns = { - .deviceProbe = libchip_serial_default_probe, - .deviceFirstOpen = lpc32xx_hsu_first_open, - .deviceLastClose = NULL, - .deviceRead = NULL, - .deviceWrite = lpc32xx_hsu_write, - .deviceInitialize = lpc32xx_hsu_initialize, - .deviceWritePolled = NULL, - .deviceSetAttributes = lpc32xx_hsu_set_attributes, - .deviceOutputUsesInterrupts = true +const rtems_termios_device_handler lpc32xx_hsu_fns = { + .first_open = lpc32xx_hsu_first_open, + .last_close = lpc32xx_hsu_last_close, + .write = lpc32xx_hsu_write, + .set_attributes = lpc32xx_hsu_set_attributes, + .mode = TERMIOS_IRQ_DRIVEN }; diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/hsu.h b/c/src/lib/libbsp/arm/lpc32xx/include/hsu.h new file mode 100644 index 0000000..ba97dfb --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc32xx/include/hsu.h @@ -0,0 +1,68 @@ +/** + * @file + * + * @ingroup lpc32xx_hsu + * + * @brief HSU support API. + */ + +/* + * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_ARM_LPC32XX_HSU_H +#define LIBBSP_ARM_LPC32XX_HSU_H + +#include <rtems/termiostypes.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup lpc32xx_hsu HSU Support + * + * @ingroup arm_lpc32xx + * + * @brief HSU Support + * + * @{ + */ + +typedef struct { + uint32_t fifo; + uint32_t level; + uint32_t iir; + uint32_t ctrl; + uint32_t rate; +} lpc32xx_hsu; + +typedef struct { + rtems_termios_device_context base; + volatile lpc32xx_hsu *hsu; + size_t chars_in_transmission; + rtems_vector_number irq; + uint32_t initial_baud; +} lpc32xx_hsu_context; + +extern const rtems_termios_device_handler lpc32xx_hsu_fns; + +bool lpc32xx_hsu_probe(rtems_termios_device_context *base); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_ARM_LPC32XX_HSU_H */ diff --git a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am index b15e8cd..9a2571e 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am +++ b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am @@ -146,6 +146,10 @@ $(PROJECT_INCLUDE)/bsp/boot.h: include/boot.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/boot.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/boot.h +$(PROJECT_INCLUDE)/bsp/hsu.h: include/hsu.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/hsu.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/hsu.h + $(PROJECT_INCLUDE)/bsp/i2c.h: include/i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2c.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i2c.h diff --git a/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am b/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am index 3e24d30..35a093b 100644 --- a/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am +++ b/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am @@ -82,12 +82,10 @@ libbsp_a_SOURCES += ../../shared/src/irq-shell.c libbsp_a_SOURCES += irq/irq.c # console -libbsp_a_SOURCES += ../../shared/console.c \ - ../../shared/console_select.c \ - console/console-config.c \ - ../../shared/console_read.c \ - ../../shared/console_write.c \ - ../../shared/console_control.c +libbsp_a_SOURCES += ../../shared/console-termios-init.c +libbsp_a_SOURCES += ../../shared/console-termios.c +libbsp_a_SOURCES += console/console-config.c + # bsp_i2c libbsp_a_SOURCES += i2c/i2c_init.c # bsp_spi diff --git a/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c b/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c index b3ccb9c..8dd7249 100644 --- a/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c +++ b/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c @@ -5,10 +5,10 @@ */ /* - * Copyright (c) 2008, 2010 embedded brains GmbH. All rights reserved. + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -20,104 +20,92 @@ #include <rtems/bspIo.h> -#include <libchip/serial.h> #include <libchip/ns16550.h> -#include "../../../shared/console_private.h" #include <mpc83xx/mpc83xx.h> -#include <bspopts.h> +#include <bsp.h> #include <bsp/irq.h> - -#ifdef BSP_USE_UART2 - #define PORT_COUNT 2 -#else - #define PORT_COUNT 1 -#endif +#include <bsp/console-termios.h> #ifdef BSP_USE_UART_INTERRUPTS - #define DEVICE_FNS &ns16550_fns + #define DEVICE_FNS &ns16550_handler_interrupt #else - #define DEVICE_FNS &ns16550_fns_polled + #define DEVICE_FNS &ns16550_handler_polled #endif -static uint8_t gen83xx_console_get_register(uint32_t addr, uint8_t i) +static uint8_t gen83xx_console_get_register(uintptr_t addr, uint8_t i) { volatile uint8_t *reg = (volatile uint8_t *) addr; return reg [i]; } -static void gen83xx_console_set_register(uint32_t addr, uint8_t i, uint8_t val) +static void gen83xx_console_set_register(uintptr_t addr, uint8_t i, uint8_t val) { volatile uint8_t *reg = (volatile uint8_t *) addr; - reg [i] = val; + reg [i] = val; } -unsigned long Console_Configuration_Count = PORT_COUNT; - -console_tbl Console_Configuration_Ports [PORT_COUNT] = { - { - .sDeviceName = "/dev/ttyS0", - .deviceType = SERIAL_NS16550, - .pDeviceFns = DEVICE_FNS, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) BSP_CONSOLE_BAUD, - .ulCtrlPort1 = (uint32_t) &mpc83xx.duart [0], - .ulCtrlPort2 = 0, - .ulDataPort = (uint32_t) &mpc83xx.duart [0], - .getRegister = gen83xx_console_get_register, - .setRegister = gen83xx_console_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 0, +static ns16550_context gen83xx_uart_context_0 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"), + .get_reg = gen83xx_console_get_register, + .set_reg = gen83xx_console_set_register, + .port = (uintptr_t) &mpc83xx.duart[0], #if MPC83XX_CHIP_TYPE / 10 == 830 - .ulIntVector = BSP_IPIC_IRQ_UART + .irq = BSP_IPIC_IRQ_UART, #else - .ulIntVector = BSP_IPIC_IRQ_UART1 + .irq = BSP_IPIC_IRQ_UART1, #endif - } + .initial_baud = BSP_CONSOLE_BAUD +}; + #ifdef BSP_USE_UART2 - , { - .sDeviceName = "/dev/ttyS1", - .deviceType = SERIAL_NS16550, - .pDeviceFns = DEVICE_FNS, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) BSP_CONSOLE_BAUD, - .ulCtrlPort1 = (uint32_t) &mpc83xx.duart [1], - .ulCtrlPort2 = 0, - .ulDataPort = (uint32_t) &mpc83xx.duart [1], - .getRegister = gen83xx_console_get_register, - .setRegister = gen83xx_console_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 0, +static ns16550_context gen83xx_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .get_reg = gen83xx_console_get_register, + .set_reg = gen83xx_console_set_register, + .port = (uintptr_t) &mpc83xx.duart[1], #if MPC83XX_CHIP_TYPE / 10 == 830 - .ulIntVector = BSP_IPIC_IRQ_UART + .irq = BSP_IPIC_IRQ_UART, #else - .ulIntVector = BSP_IPIC_IRQ_UART2 + .irq = BSP_IPIC_IRQ_UART2, #endif + .initial_baud = BSP_CONSOLE_BAUD +}; +#endif + +const console_device console_device_table[] = { + { + .device_file = "/dev/ttyS0", + .probe = ns16550_probe, + .handler = DEVICE_FNS, + .context = &gen83xx_uart_context_0.base + } +#ifdef BSP_USE_UART2 + , { + .device_file = "/dev/ttyS1", + .probe = ns16550_probe, + .handler = DEVICE_FNS, + .context = &gen83xx_uart_context_1.base } #endif }; +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); + static void gen83xx_output_char(char c) { - const console_fns *console = Console_Port_Tbl [Console_Port_Minor]->pDeviceFns; - + rtems_termios_device_context *ctx = console_device_table[0].context; + if (c == '\n') { - console->deviceWritePolled((int) Console_Port_Minor, '\r'); + ns16550_polled_putchar(ctx, '\r'); } - console->deviceWritePolled((int) Console_Port_Minor, c); + + ns16550_polled_putchar(ctx, c); } -BSP_output_char_function_type BSP_output_char = gen83xx_output_char; +BSP_output_char_function_type BSP_output_char = gen83xx_output_char; BSP_polling_getchar_function_type BSP_poll_char = NULL; diff --git a/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c b/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c index 4428b8d..f1ffcac 100644 --- a/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c +++ b/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c @@ -7,12 +7,13 @@ */ /* - * Copyright (c) 2008 - * Embedded Brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * rt...@embedded-brains.de + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <i...@embedded-brains.de> * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -21,7 +22,7 @@ #include <rtems/counter.h> -#include <libchip/serial.h> +#include <libchip/ns16550.h> #include <libcpu/powerpc-utility.h> @@ -31,6 +32,7 @@ #include <bsp/irq-generic.h> #include <bsp/linker-symbols.h> #include <bsp/u-boot.h> +#include <bsp/console-termios.h> /* Configuration parameters for console driver, ... */ unsigned int BSP_bus_frequency; @@ -54,6 +56,7 @@ void BSP_panic(char *s) rtems_interrupt_level level; rtems_interrupt_disable(level); + (void) level; printk("%s PANIC %s\n", rtems_get_version_string(), s); @@ -67,6 +70,7 @@ void _BSP_Fatal_error(unsigned n) rtems_interrupt_level level; rtems_interrupt_disable( level); + (void) level; printk( "%s PANIC ERROR %u\n", rtems_get_version_string(), n); @@ -80,15 +84,12 @@ void bsp_start( void) rtems_status_code sc = RTEMS_SUCCESSFUL; unsigned long i = 0; - ppc_cpu_id_t myCpu; - ppc_cpu_revision_t myCpuRevision; - /* * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function * store the result in global variables so that it can be used latter... */ - myCpu = get_ppc_cpu_type(); - myCpuRevision = get_ppc_cpu_revision(); + get_ppc_cpu_type(); + get_ppc_cpu_revision(); /* Basic CPU initialization */ cpu_init(); @@ -122,12 +123,13 @@ void bsp_start( void) rtems_counter_initialize_converter(bsp_time_base_frequency); /* Initialize some console parameters */ - for (i = 0; i < Console_Configuration_Count; ++i) { - Console_Configuration_Ports [i].ulClock = BSP_bus_frequency; + for (i = 0; i < console_device_count; ++i) { + ns16550_context *ctx = (ns16550_context *) console_device_table[i].context; + + ctx->clock = BSP_bus_frequency; #ifdef HAS_UBOOT - Console_Configuration_Ports [i].pDeviceParams = - (void *) bsp_uboot_board_info.bi_baudrate; + ctx->initial_baud = bsp_uboot_board_info.bi_baudrate; #endif } diff --git a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am index ebd4160..97d97a2 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am +++ b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am @@ -92,15 +92,11 @@ libbsp_a_SOURCES += ../../shared/src/irq-shell.c libbsp_a_SOURCES += irq/irq.c # Console -libbsp_a_SOURCES += ../../shared/console.c \ - ../../shared/console_select.c \ - console/uart-bridge-master.c \ - console/uart-bridge-slave.c \ - console/console-config.c \ - ../../shared/console_read.c \ - ../../shared/console_write.c \ - ../../shared/console_control.c - +libbsp_a_SOURCES += ../../shared/console-termios-init.c +libbsp_a_SOURCES += ../../shared/console-termios.c +libbsp_a_SOURCES += console/uart-bridge-master.c +libbsp_a_SOURCES += console/uart-bridge-slave.c +libbsp_a_SOURCES += console/console-config.c # RTC libbsp_a_SOURCES += ../../shared/tod.c \ diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c b/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c index 6260fd3..1abefe8 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c +++ b/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -20,25 +20,16 @@ * http://www.rtems.org/license/LICENSE. */ -#include <assert.h> - #include <rtems/bspIo.h> -#include <libchip/serial.h> #include <libchip/ns16550.h> -#include "../../../shared/console_private.h" -#include <bspopts.h> +#include <bsp.h> #include <bsp/irq.h> #include <bsp/qoriq.h> #include <bsp/intercom.h> #include <bsp/uart-bridge.h> - -#define CONSOLE_COUNT \ - (QORIQ_UART_0_ENABLE \ - + QORIQ_UART_1_ENABLE \ - + QORIQ_UART_BRIDGE_0_ENABLE \ - + QORIQ_UART_BRIDGE_1_ENABLE) +#include <bsp/console-termios.h> #if (QORIQ_UART_0_ENABLE + QORIQ_UART_BRIDGE_0_ENABLE == 2) \ || (QORIQ_UART_1_ENABLE + QORIQ_UART_BRIDGE_1_ENABLE == 2) @@ -47,158 +38,156 @@ #define BRIDGE_SLAVE #endif +#ifdef BSP_USE_UART_INTERRUPTS + #define DEVICE_FNS &ns16550_handler_interrupt +#else + #define DEVICE_FNS &ns16550_handler_polled +#endif + +#if QORIQ_UART_0_ENABLE || QORIQ_UART_1_ENABLE + static uint8_t get_register(uintptr_t addr, uint8_t i) + { + volatile uint8_t *reg = (uint8_t *) addr; + + return reg [i]; + } + + static void set_register(uintptr_t addr, uint8_t i, uint8_t val) + { + volatile uint8_t *reg = (uint8_t *) addr; + + reg [i] = val; + } +#endif + +#if QORIQ_UART_0_ENABLE +static ns16550_context qoriq_uart_context_0 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"), + .get_reg = get_register, + .set_reg = set_register, + .port = (uintptr_t) &qoriq.uart_0, + .irq = QORIQ_IRQ_DUART, + .initial_baud = BSP_CONSOLE_BAUD +}; +#endif + +#if QORIQ_UART_1_ENABLE +static ns16550_context qoriq_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .get_reg = get_register, + .set_reg = set_register, + .port = (uintptr_t) &qoriq.uart_1, + .irq = QORIQ_IRQ_DUART, + .initial_baud = BSP_CONSOLE_BAUD +}; +#endif + #ifdef BRIDGE_MASTER + #define BRIDGE_PROBE qoriq_uart_bridge_master_probe #define BRIDGE_FNS &qoriq_uart_bridge_master #if QORIQ_UART_BRIDGE_0_ENABLE - static uart_bridge_master_control bridge_0_control = { + static uart_bridge_master_context bridge_0_context = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 0"), .device_path = "/dev/ttyS0", .type = INTERCOM_TYPE_UART_0, .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY( - bridge_0_control.transmit_fifo + bridge_0_context.transmit_fifo ) }; - #define BRIDGE_0_CONTROL &bridge_0_control + #define BRIDGE_0_CONTEXT &bridge_0_context #endif #if QORIQ_UART_BRIDGE_1_ENABLE - static uart_bridge_master_control bridge_1_control = { + static uart_bridge_master_context bridge_1_context = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 1"), .device_path = "/dev/ttyS1", .type = INTERCOM_TYPE_UART_1, .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY( - bridge_1_control.transmit_fifo + bridge_1_context.transmit_fifo ) }; - #define BRIDGE_1_CONTROL &bridge_1_control + #define BRIDGE_1_CONTEXT &bridge_1_context #endif #endif #ifdef BRIDGE_SLAVE + #define BRIDGE_PROBE console_device_probe_default #define BRIDGE_FNS &qoriq_uart_bridge_slave #if QORIQ_UART_BRIDGE_0_ENABLE - static uart_bridge_slave_control bridge_0_control = { + static uart_bridge_slave_context bridge_0_context = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 0"), .type = INTERCOM_TYPE_UART_0, .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY( - bridge_0_control.transmit_fifo + bridge_0_context.transmit_fifo ) }; - #define BRIDGE_0_CONTROL &bridge_0_control + #define BRIDGE_0_CONTEXT &bridge_0_context #endif #if QORIQ_UART_BRIDGE_1_ENABLE - static uart_bridge_slave_control bridge_1_control = { + static uart_bridge_slave_context bridge_1_context = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 1"), .type = INTERCOM_TYPE_UART_1, .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY( - bridge_1_control.transmit_fifo + bridge_1_context.transmit_fifo ) }; - #define BRIDGE_1_CONTROL &bridge_1_control + #define BRIDGE_1_CONTEXT &bridge_1_context #endif #endif -#ifdef BSP_USE_UART_INTERRUPTS - #define DEVICE_FNS &ns16550_fns -#else - #define DEVICE_FNS &ns16550_fns_polled -#endif - -#if QORIQ_UART_0_ENABLE || QORIQ_UART_1_ENABLE - static uint8_t get_register(uintptr_t addr, uint8_t i) - { - volatile uint8_t *reg = (uint8_t *) addr; - - return reg [i]; - } - - static void set_register(uintptr_t addr, uint8_t i, uint8_t val) - { - volatile uint8_t *reg = (uint8_t *) addr; - - reg [i] = val; - } -#endif - -unsigned long Console_Configuration_Count = CONSOLE_COUNT; -console_tbl Console_Configuration_Ports [CONSOLE_COUNT] = { +const console_device console_device_table[] = { #if QORIQ_UART_0_ENABLE { - .sDeviceName = "/dev/ttyS0", - .deviceType = SERIAL_NS16550, - .pDeviceFns = DEVICE_FNS, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) BSP_CONSOLE_BAUD, - .ulCtrlPort1 = (uintptr_t) &qoriq.uart_0, - .ulCtrlPort2 = 0, - .ulDataPort = (uintptr_t) &qoriq.uart_0, - .getRegister = get_register, - .setRegister = set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 0, - .ulIntVector = QORIQ_IRQ_DUART + .device_file = "/dev/ttyS0", + .probe = ns16550_probe, + .handler = DEVICE_FNS, + .context = &qoriq_uart_context_0.base }, #endif #if QORIQ_UART_1_ENABLE { - .sDeviceName = "/dev/ttyS1", - .deviceType = SERIAL_NS16550, - .pDeviceFns = DEVICE_FNS, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) BSP_CONSOLE_BAUD, - .ulCtrlPort1 = (uintptr_t) &qoriq.uart_1, - .ulCtrlPort2 = 0, - .ulDataPort = (uintptr_t) &qoriq.uart_1, - .getRegister = get_register, - .setRegister = set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 0, - .ulIntVector = QORIQ_IRQ_DUART + .device_file = "/dev/ttyS1", + .probe = ns16550_probe, + .handler = DEVICE_FNS, + .context = &qoriq_uart_context_1.base }, #endif #if QORIQ_UART_BRIDGE_0_ENABLE { #if QORIQ_UART_1_ENABLE - .sDeviceName = "/dev/ttyB0", + .device_file = "/dev/ttyB0", #else - .sDeviceName = "/dev/ttyS0", + .device_file = "/dev/ttyS0", #endif - .deviceType = SERIAL_CUSTOM, - .pDeviceFns = BRIDGE_FNS, - .pDeviceParams = BRIDGE_0_CONTROL + .probe = BRIDGE_PROBE, + .handler = BRIDGE_FNS, + .context = BRIDGE_0_CONTEXT }, #endif #if QORIQ_UART_BRIDGE_1_ENABLE { #if QORIQ_UART_1_ENABLE - .sDeviceName = "/dev/ttyB1", + .device_file = "/dev/ttyB1", #else - .sDeviceName = "/dev/ttyS1", + .device_file = "/dev/ttyS1", #endif - .deviceType = SERIAL_CUSTOM, - .pDeviceFns = BRIDGE_FNS, - .pDeviceParams = BRIDGE_1_CONTROL + .probe = BRIDGE_PROBE, + .handler = BRIDGE_FNS, + .context = BRIDGE_1_CONTEXT } #endif }; +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); + static void output_char(char c) { - int minor = (int) Console_Port_Minor; - const console_tbl **ct_tbl = Console_Port_Tbl; - - if (ct_tbl != NULL) { - const console_fns *cf = ct_tbl[minor]->pDeviceFns; + rtems_termios_device_context *ctx = console_device_table[0].context; - if (c == '\n') { - (*cf->deviceWritePolled)(minor, '\r'); - } - - (*cf->deviceWritePolled)(minor, c); + if (c == '\n') { + ns16550_polled_putchar(ctx, '\r'); } + + ns16550_polled_putchar(ctx, c); } BSP_output_char_function_type BSP_output_char = output_char; diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c index 939448a..41ad517 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c +++ b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -26,8 +26,6 @@ #include <unistd.h> #include <termios.h> -#include <libchip/sersupp.h> - #include <bspopts.h> #include <bsp/uart-bridge.h> @@ -55,12 +53,12 @@ static void serial_settings(int fd) static void uart_bridge_master_service(intercom_packet *packet, void *arg) { rtems_status_code sc = RTEMS_SUCCESSFUL; - uart_bridge_master_control *control = arg; + uart_bridge_master_context *ctx = arg; sc = rtems_chain_append_with_notification( - &control->transmit_fifo, + &ctx->transmit_fifo, &packet->glue.node, - control->transmit_task, + ctx->transmit_task, TRANSMIT_EVENT ); assert(sc == RTEMS_SUCCESSFUL); @@ -68,10 +66,10 @@ static void uart_bridge_master_service(intercom_packet *packet, void *arg) static void receive_task(rtems_task_argument arg) { - uart_bridge_master_control *control = (uart_bridge_master_control *) arg; - intercom_type type = control->type; + uart_bridge_master_context *ctx = (uart_bridge_master_context *) arg; + intercom_type type = ctx->type; - int fd = open(control->device_path, O_RDONLY); + int fd = open(ctx->device_path, O_RDONLY); assert(fd >= 0); serial_settings(fd); @@ -94,10 +92,10 @@ static void receive_task(rtems_task_argument arg) static void transmit_task(rtems_task_argument arg) { rtems_status_code sc = RTEMS_SUCCESSFUL; - uart_bridge_master_control *control = (uart_bridge_master_control *) arg; - rtems_chain_control *fifo = &control->transmit_fifo; + uart_bridge_master_context *ctx = (uart_bridge_master_context *) arg; + rtems_chain_control *fifo = &ctx->transmit_fifo; - int fd = open(control->device_path, O_WRONLY); + int fd = open(ctx->device_path, O_WRONLY); assert(fd >= 0); serial_settings(fd); @@ -119,12 +117,12 @@ static void transmit_task(rtems_task_argument arg) static rtems_id create_task( char name, rtems_task_entry entry, - uart_bridge_master_control *control + uart_bridge_master_context *ctx ) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_id task = RTEMS_ID_NONE; - char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0); + char index = (char) ('0' + ctx->type - INTERCOM_TYPE_UART_0); sc = rtems_task_create( rtems_build_name('U', 'B', name, index), @@ -139,57 +137,45 @@ static rtems_id create_task( sc = rtems_task_start( task, entry, - (rtems_task_argument) control + (rtems_task_argument) ctx ); assert(sc == RTEMS_SUCCESSFUL); return task; } -static void initialize(int minor) +bool qoriq_uart_bridge_master_probe(rtems_termios_device_context *base) { - console_tbl *ct = Console_Port_Tbl [minor]; - uart_bridge_master_control *control = ct->pDeviceParams; - intercom_type type = control->type; - - qoriq_intercom_service_install(type, uart_bridge_master_service, control); - create_task('R', receive_task, control); - control->transmit_task = create_task('T', transmit_task, control); -} + uart_bridge_master_context *ctx = (uart_bridge_master_context *) base; + intercom_type type = ctx->type; -static int first_open(int major, int minor, void *arg) -{ - return -1; -} + qoriq_intercom_service_install(type, uart_bridge_master_service, ctx); + create_task('R', receive_task, ctx); + ctx->transmit_task = create_task('T', transmit_task, ctx); -static int last_close(int major, int minor, void *arg) -{ - return -1; + return true; } -static int read_polled(int minor) -{ - return -1; -} - -static void write_polled(int minor, char c) +static bool first_open( + struct rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) { - /* Do nothing */ + return false; } -static int set_attributes(int minor, const struct termios *term) +static bool set_attributes( + rtems_termios_device_context *base, + const struct termios *term +) { - return -1; + return false; } -const console_fns qoriq_uart_bridge_master = { - .deviceProbe = libchip_serial_default_probe, - .deviceFirstOpen = first_open, - .deviceLastClose = last_close, - .deviceRead = read_polled, - .deviceWrite = NULL, - .deviceInitialize = initialize, - .deviceWritePolled = write_polled, - .deviceSetAttributes = set_attributes, - .deviceOutputUsesInterrupts = false +const rtems_termios_device_handler qoriq_uart_bridge_master = { + .first_open = first_open, + .set_attributes = set_attributes, + .mode = TERMIOS_POLLED }; diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c index 71969e3..44d4cfb 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c +++ b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c @@ -50,8 +50,8 @@ static void restore_preemption(rtems_mode prev_mode) static void uart_bridge_slave_service(intercom_packet *packet, void *arg) { - uart_bridge_slave_control *control = arg; - struct rtems_termios_tty *tty = control->tty; + uart_bridge_slave_context *ctx = arg; + struct rtems_termios_tty *tty = ctx->tty; /* Workaround for https://www.rtems.org/bugzilla/show_bug.cgi?id=1736 */ rtems_mode prev_mode = disable_preemption(); @@ -65,9 +65,9 @@ static void uart_bridge_slave_service(intercom_packet *packet, void *arg) static void transmit_task(rtems_task_argument arg) { rtems_status_code sc = RTEMS_SUCCESSFUL; - uart_bridge_slave_control *control = (uart_bridge_slave_control *) arg; - rtems_chain_control *fifo = &control->transmit_fifo; - struct rtems_termios_tty *tty = control->tty; + uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) arg; + rtems_chain_control *fifo = &ctx->transmit_fifo; + struct rtems_termios_tty *tty = ctx->tty; while (true) { intercom_packet *packet = NULL; @@ -91,12 +91,12 @@ static void transmit_task(rtems_task_argument arg) } static void create_transmit_task( - uart_bridge_slave_control *control + uart_bridge_slave_context *ctx ) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_id task = RTEMS_ID_NONE; - char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0); + char index = (char) ('0' + ctx->type - INTERCOM_TYPE_UART_0); sc = rtems_task_create( rtems_build_name('U', 'B', 'T', index), @@ -111,54 +111,53 @@ static void create_transmit_task( sc = rtems_task_start( task, transmit_task, - (rtems_task_argument) control + (rtems_task_argument) ctx ); assert(sc == RTEMS_SUCCESSFUL); - control->transmit_task = task; + ctx->transmit_task = task; } -static void initialize(int minor) +static bool first_open( + struct rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) { - /* Do nothing */ -} + uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base; + intercom_type type = ctx->type; -static int first_open(int major, int minor, void *arg) -{ - rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; - struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; - console_tbl *ct = Console_Port_Tbl[minor]; - console_data *cd = &Console_Port_Data [minor]; - uart_bridge_slave_control *control = ct->pDeviceParams; - intercom_type type = control->type; - - control->tty = tty; - cd->termios_data = tty; + ctx->tty = tty; rtems_termios_set_initial_baud(tty, 115200); - create_transmit_task(control); - qoriq_intercom_service_install(type, uart_bridge_slave_service, control); + create_transmit_task(ctx); + qoriq_intercom_service_install(type, uart_bridge_slave_service, ctx); - return 0; + return true; } -static int last_close(int major, int minor, void *arg) +static void last_close( + struct rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) { - console_tbl *ct = Console_Port_Tbl[minor]; - uart_bridge_slave_control *control = ct->pDeviceParams; - - qoriq_intercom_service_remove(control->type); + uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base; - return 0; + qoriq_intercom_service_remove(ctx->type); } -static ssize_t write_with_interrupts(int minor, const char *buf, size_t len) +static void write_with_interrupts( + rtems_termios_device_context *base, + const char *buf, + size_t len +) { if (len > 0) { rtems_status_code sc = RTEMS_SUCCESSFUL; - console_tbl *ct = Console_Port_Tbl[minor]; - uart_bridge_slave_control *control = ct->pDeviceParams; + uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base; intercom_packet *packet = qoriq_intercom_allocate_packet( - control->type, + ctx->type, INTERCOM_SIZE_64 ); @@ -170,44 +169,27 @@ static ssize_t write_with_interrupts(int minor, const char *buf, size_t len) * another context. */ sc = rtems_chain_append_with_notification( - &control->transmit_fifo, + &ctx->transmit_fifo, &packet->glue.node, - control->transmit_task, + ctx->transmit_task, TRANSMIT_EVENT ); assert(sc == RTEMS_SUCCESSFUL); } - - return 0; -} - -static void write_polled(int minor, char c) -{ - console_tbl *ct = Console_Port_Tbl[minor]; - uart_bridge_slave_control *control = ct->pDeviceParams; - intercom_packet *packet = qoriq_intercom_allocate_packet( - control->type, - INTERCOM_SIZE_64 - ); - char *data = packet->data; - data [0] = c; - packet->size = 1; - qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_MASTER_CORE, packet); } -static int set_attribues(int minor, const struct termios *term) +static bool set_attributes( + rtems_termios_device_context *base, + const struct termios *term +) { - return -1; + return false; } -const console_fns qoriq_uart_bridge_slave = { - .deviceProbe = libchip_serial_default_probe, - .deviceFirstOpen = first_open, - .deviceLastClose = last_close, - .deviceRead = NULL, - .deviceWrite = write_with_interrupts, - .deviceInitialize = initialize, - .deviceWritePolled = write_polled, - .deviceSetAttributes = set_attribues, - .deviceOutputUsesInterrupts = true +const rtems_termios_device_handler qoriq_uart_bridge_slave = { + .first_open = first_open, + .last_close = last_close, + .write = write_with_interrupts, + .set_attributes = set_attributes, + .mode = TERMIOS_IRQ_DRIVEN }; diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h b/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h index e94fe20..cd342ff 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h +++ b/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * <rt...@embedded-brains.de> @@ -23,7 +23,7 @@ #ifndef LIBBSP_POWERPC_QORIQ_UART_BRIDGE_H #define LIBBSP_POWERPC_QORIQ_UART_BRIDGE_H -#include <libchip/serial.h> +#include <rtems/termiostypes.h> #include <bsp/intercom.h> @@ -42,22 +42,26 @@ extern "C" { */ typedef struct { + rtems_termios_device_context base; const char *device_path; intercom_type type; rtems_id transmit_task; rtems_chain_control transmit_fifo; -} uart_bridge_master_control; +} uart_bridge_master_context; typedef struct { + rtems_termios_device_context base; struct rtems_termios_tty *tty; intercom_type type; rtems_id transmit_task; rtems_chain_control transmit_fifo; -} uart_bridge_slave_control; +} uart_bridge_slave_context; -extern const console_fns qoriq_uart_bridge_master; +bool qoriq_uart_bridge_master_probe(rtems_termios_device_context *base); -extern const console_fns qoriq_uart_bridge_slave; +extern const rtems_termios_device_handler qoriq_uart_bridge_master; + +extern const rtems_termios_device_handler qoriq_uart_bridge_slave; /** @} */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c index 5785078..43caabb 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c @@ -24,7 +24,7 @@ #include <rtems/config.h> #include <rtems/counter.h> -#include <libchip/serial.h> +#include <libchip/ns16550.h> #include <libcpu/powerpc-utility.h> @@ -36,6 +36,7 @@ #include <bsp/linker-symbols.h> #include <bsp/mmu.h> #include <bsp/qoriq.h> +#include <bsp/console-termios.h> LINKER_SYMBOL(bsp_exc_vector_base); @@ -50,6 +51,7 @@ void BSP_panic(char *s) rtems_interrupt_level level; rtems_interrupt_disable(level); + (void) level; printk("%s PANIC %s\n", rtems_get_version_string(), s); @@ -63,6 +65,7 @@ void _BSP_Fatal_error(unsigned n) rtems_interrupt_level level; rtems_interrupt_disable(level); + (void) level; printk("%s PANIC ERROR %u\n", rtems_get_version_string(), n); @@ -75,15 +78,12 @@ void bsp_start(void) { unsigned long i = 0; - ppc_cpu_id_t myCpu; - ppc_cpu_revision_t myCpuRevision; - /* * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function * store the result in global variables so that it can be used latter... */ - myCpu = get_ppc_cpu_type(); - myCpuRevision = get_ppc_cpu_revision(); + get_ppc_cpu_type(); + get_ppc_cpu_revision(); /* Initialize some device driver parameters */ #ifdef HAS_UBOOT @@ -93,16 +93,24 @@ void bsp_start(void) rtems_counter_initialize_converter(BSP_bus_frequency / 8); /* Initialize some console parameters */ - for (i = 0; i < Console_Configuration_Count; ++i) { - console_tbl *ct = &Console_Configuration_Ports[i]; - - ct->ulClock = BSP_bus_frequency; - - #ifdef HAS_UBOOT - if (ct->deviceType == SERIAL_NS16550) { - ct->pDeviceParams = (void *) bsp_uboot_board_info.bi_baudrate; - } - #endif + for (i = 0; i < console_device_count; ++i) { + const console_device *dev = &console_device_table[i]; + const rtems_termios_device_handler *ns16550 = + #ifdef BSP_USE_UART_INTERRUPTS + &ns16550_handler_interrupt; + #else + &ns16550_handler_polled; + #endif + + if (dev->handler == ns16550) { + ns16550_context *ctx = (ns16550_context *) dev->context; + + ctx->clock = BSP_bus_frequency; + + #ifdef HAS_UBOOT + ctx->initial_baud = bsp_uboot_board_info.bi_baudrate; + #endif + } } /* Disable decrementer */ diff --git a/c/src/libchip/Makefile.am b/c/src/libchip/Makefile.am index 003c3c1..904561f 100644 --- a/c/src/libchip/Makefile.am +++ b/c/src/libchip/Makefile.am @@ -110,6 +110,7 @@ libserialio_a_SOURCES = serial/mc68681.c serial/mc68681_baud.c \ serial/mc68681_reg8.c serial/ns16550.c serial/z85c30.c \ serial/z85c30_reg.c serial/serprobe.c serial/mc68681_p.h \ serial/z85c30_p.h +libserialio_a_SOURCES += serial/ns16550-context.c EXTRA_DIST += serial/README.mc68681 serial/README.ns16550 \ serial/README.xr88681 serial/README.z85c30 serial/STATUS diff --git a/c/src/libchip/serial/ns16550-context.c b/c/src/libchip/serial/ns16550-context.c new file mode 100644 index 0000000..a812271 --- /dev/null +++ b/c/src/libchip/serial/ns16550-context.c @@ -0,0 +1,677 @@ +/** + * @file + * + * This file contains the TTY driver for the National Semiconductor NS16550. + * + * This part is widely cloned and second sourced. It is found in a number + * of "Super IO" controllers. + * + * This driver uses the termios pseudo driver. + */ + +/* + * COPYRIGHT (c) 1998 by Radstone Technology + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <stdlib.h> + +#include <rtems/bspIo.h> + +#include <bsp.h> + +#include "ns16550.h" +#include "ns16550_p.h" + +#if defined(BSP_FEATURE_IRQ_EXTENSION) + #include <bsp/irq.h> +#elif defined(BSP_FEATURE_IRQ_LEGACY) + #include <bsp/irq.h> +#elif defined(__PPC__) || defined(__i386__) + #include <bsp/irq.h> + #define BSP_FEATURE_IRQ_LEGACY + #ifdef BSP_SHARED_HANDLER_SUPPORT + #define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT + #endif +#endif + +static uint32_t NS16550_GetBaudDivisor(ns16550_context *ctx, uint32_t baud) +{ + uint32_t clock = ctx->clock; + uint32_t baudDivisor = (clock != 0 ? clock : 115200) / (baud * 16); + + if (ctx->has_fractional_divider_register) { + uint32_t fractionalDivider = 0x10; + uint32_t err = baud; + uint32_t mulVal; + uint32_t divAddVal; + + clock /= 16 * baudDivisor; + for (mulVal = 1; mulVal < 16; ++mulVal) { + for (divAddVal = 0; divAddVal < mulVal; ++divAddVal) { + uint32_t actual = (mulVal * clock) / (mulVal + divAddVal); + uint32_t newErr = actual > baud ? actual - baud : baud - actual; + + if (newErr < err) { + err = newErr; + fractionalDivider = (mulVal << 4) | divAddVal; + } + } + } + + (*ctx->set_reg)( + ctx->port, + NS16550_FRACTIONAL_DIVIDER, + fractionalDivider + ); + } + + return baudDivisor; +} + +/* + * ns16550_enable_interrupts + * + * This routine initializes the port to have the specified interrupts masked. + */ +static void ns16550_enable_interrupts( + ns16550_context *ctx, + int mask +) +{ + (*ctx->set_reg)(ctx->port, NS16550_INTERRUPT_ENABLE, mask); +} + +/* + * ns16550_probe + */ + +bool ns16550_probe(rtems_termios_device_context *base) +{ + ns16550_context *ctx = (ns16550_context *) base; + uintptr_t pNS16550; + uint8_t ucDataByte; + uint32_t ulBaudDivisor; + ns16550_set_reg setReg; + ns16550_get_reg getReg; + + ctx->modem_control = SP_MODEM_IRQ; + + pNS16550 = ctx->port; + setReg = ctx->set_reg; + getReg = ctx->get_reg; + + /* Clear the divisor latch, clear all interrupt enables, + * and reset and + * disable the FIFO's. + */ + + (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0); + ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR ); + + /* Set the divisor latch and set the baud rate. */ + + ulBaudDivisor = NS16550_GetBaudDivisor(ctx, ctx->initial_baud); + ucDataByte = SP_LINE_DLAB; + (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); + + /* XXX */ + (*setReg)(pNS16550,NS16550_TRANSMIT_BUFFER,(uint8_t)(ulBaudDivisor & 0xffU)); + (*setReg)( + pNS16550,NS16550_INTERRUPT_ENABLE, + (uint8_t)(( ulBaudDivisor >> 8 ) & 0xffU ) + ); + + /* Clear the divisor latch and set the character size to eight bits */ + /* with one stop bit and no parity checking. */ + ucDataByte = EIGHT_BITS; + (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); + + /* Enable and reset transmit and receive FIFOs. TJA */ + ucDataByte = SP_FIFO_ENABLE; + (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); + + ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST; + (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); + + ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR); + + /* Set data terminal ready. */ + /* And open interrupt tristate line */ + (*setReg)(pNS16550, NS16550_MODEM_CONTROL,ctx->modem_control); + + (*getReg)(pNS16550, NS16550_LINE_STATUS ); + (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER ); + + return true; +} + +#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) + +/** + * @brief Process interrupt. + */ +static void ns16550_isr(void *arg) +{ + rtems_termios_tty *tty = arg; + ns16550_context *ctx = rtems_termios_get_device_context(tty); + uint32_t port = ctx->port; + ns16550_get_reg get = ctx->get_reg; + int i = 0; + char buf [SP_FIFO_SIZE]; + + /* Iterate until no more interrupts are pending */ + do { + /* Fetch received characters */ + for (i = 0; i < SP_FIFO_SIZE; ++i) { + if ((get( port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) { + buf [i] = (char) get(port, NS16550_RECEIVE_BUFFER); + } else { + break; + } + } + + /* Enqueue fetched characters */ + rtems_termios_enqueue_raw_characters(tty, buf, i); + + /* Check if we can dequeue transmitted characters */ + if (ctx->transmit_fifo_chars > 0 + && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) { + + /* Dequeue transmitted characters */ + rtems_termios_dequeue_characters( + tty, + ctx->transmit_fifo_chars + ); + } + } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0); +} +#endif + +/* + * ns16550_initialize_interrupts + * + * This routine initializes the port to operate in interrupt driver mode. + */ +static void ns16550_initialize_interrupts( + struct rtems_termios_tty *tty, + ns16550_context *ctx +) +{ + #ifdef BSP_FEATURE_IRQ_EXTENSION + { + rtems_status_code sc = RTEMS_SUCCESSFUL; + sc = rtems_interrupt_handler_install( + ctx->irq, + "NS16550", + RTEMS_INTERRUPT_SHARED, + ns16550_isr, + tty + ); + if (sc != RTEMS_SUCCESSFUL) { + /* FIXME */ + printk( "%s: Error: Install interrupt handler\n", __func__); + rtems_fatal_error_occurred( 0xdeadbeef); + } + } + #elif defined(BSP_FEATURE_IRQ_LEGACY) + { + int rv = 0; + #ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT + rtems_irq_connect_data cd = { + ctx->irq, + ns16550_isr, + tty, + NULL, + NULL, + NULL, + NULL + }; + rv = BSP_install_rtems_shared_irq_handler( &cd); + #else + rtems_irq_connect_data cd = { + ctx->irq, + ns16550_isr, + tty, + NULL, + NULL, + NULL + }; + rv = BSP_install_rtems_irq_handler( &cd); + #endif + if (rv == 0) { + /* FIXME */ + printk( "%s: Error: Install interrupt handler\n", __func__); + rtems_fatal_error_occurred( 0xdeadbeef); + } + } + #endif +} + +/* + * ns16550_open + */ + +static bool ns16550_open( + struct rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) +{ + ns16550_context *ctx = (ns16550_context *) base; + + /* Set initial baud */ + rtems_termios_set_initial_baud(tty, ctx->initial_baud); + + if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) { + ns16550_initialize_interrupts(tty, ctx); + ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); + } + + return true; +} + +static void ns16550_cleanup_interrupts( + struct rtems_termios_tty *tty, + ns16550_context *ctx +) +{ + #if defined(BSP_FEATURE_IRQ_EXTENSION) + rtems_status_code sc = RTEMS_SUCCESSFUL; + sc = rtems_interrupt_handler_remove( + ctx->irq, + ns16550_isr, + tty + ); + if (sc != RTEMS_SUCCESSFUL) { + /* FIXME */ + printk("%s: Error: Remove interrupt handler\n", __func__); + rtems_fatal_error_occurred(0xdeadbeef); + } + #elif defined(BSP_FEATURE_IRQ_LEGACY) + int rv = 0; + rtems_irq_connect_data cd = { + .name = ctx->irq, + .hdl = ns16550_isr, + .handle = tty + }; + rv = BSP_remove_rtems_irq_handler(&cd); + if (rv == 0) { + /* FIXME */ + printk("%s: Error: Remove interrupt handler\n", __func__); + rtems_fatal_error_occurred(0xdeadbeef); + } + #endif +} + +/* + * ns16550_close + */ + +static void ns16550_close( + struct rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) +{ + ns16550_context *ctx = (ns16550_context *) base; + + ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR); + + if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) { + ns16550_cleanup_interrupts(tty, ctx); + } +} + +/** + * @brief Polled write for NS16550. + */ +void ns16550_polled_putchar(rtems_termios_device_context *base, char out) +{ + ns16550_context *ctx = (ns16550_context *) base; + uintptr_t port = ctx->port; + ns16550_get_reg get = ctx->get_reg; + ns16550_set_reg set = ctx->set_reg; + uint32_t status = 0; + rtems_interrupt_lock_context lock_context; + + /* Save port interrupt mask */ + uint32_t interrupt_mask = get( port, NS16550_INTERRUPT_ENABLE); + + /* Disable port interrupts */ + ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR); + + while (true) { + /* Try to transmit the character in a critical section */ + rtems_termios_device_lock_acquire(&ctx->base, &lock_context); + + /* Read the transmitter holding register and check it */ + status = get( port, NS16550_LINE_STATUS); + if ((status & SP_LSR_THOLD) != 0) { + /* Transmit character */ + set( port, NS16550_TRANSMIT_BUFFER, out); + + /* Finished */ + rtems_termios_device_lock_release(&ctx->base, &lock_context); + break; + } else { + rtems_termios_device_lock_release(&ctx->base, &lock_context); + } + + /* Wait for transmitter holding register to be empty */ + do { + status = get( port, NS16550_LINE_STATUS); + } while ((status & SP_LSR_THOLD) == 0); + } + + /* Restore port interrupt mask */ + set( port, NS16550_INTERRUPT_ENABLE, interrupt_mask); +} + +/* + * These routines provide control of the RTS and DTR lines + */ + +/* + * ns16550_assert_RTS + */ + +static void ns16550_assert_RTS(rtems_termios_device_context *base) +{ + ns16550_context *ctx = (ns16550_context *) base; + rtems_interrupt_lock_context lock_context; + + /* + * Assert RTS + */ + rtems_termios_device_lock_acquire(base, &lock_context); + ctx->modem_control |= SP_MODEM_RTS; + (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control); + rtems_termios_device_lock_release(base, &lock_context); +} + +/* + * ns16550_negate_RTS + */ + +static void ns16550_negate_RTS(rtems_termios_device_context *base) +{ + ns16550_context *ctx = (ns16550_context *) base; + rtems_interrupt_lock_context lock_context; + + /* + * Negate RTS + */ + rtems_termios_device_lock_acquire(base, &lock_context); + ctx->modem_control &= ~SP_MODEM_RTS; + (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control); + rtems_termios_device_lock_release(base, &lock_context); +} + +/* + * These flow control routines utilise a connection from the local DTR + * line to the remote CTS line + */ + +/* + * ns16550_assert_DTR + */ + +static void ns16550_assert_DTR(rtems_termios_device_context *base) +{ + ns16550_context *ctx = (ns16550_context *) base; + rtems_interrupt_lock_context lock_context; + + /* + * Assert DTR + */ + rtems_termios_device_lock_acquire(base, &lock_context); + ctx->modem_control |= SP_MODEM_DTR; + (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control); + rtems_termios_device_lock_release(base, &lock_context); +} + +/* + * ns16550_negate_DTR + */ + +static void ns16550_negate_DTR(rtems_termios_device_context *base) +{ + ns16550_context *ctx = (ns16550_context *) base; + rtems_interrupt_lock_context lock_context; + + /* + * Negate DTR + */ + rtems_termios_device_lock_acquire(base, &lock_context); + ctx->modem_control &=~SP_MODEM_DTR; + (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL,ctx->modem_control); + rtems_termios_device_lock_release(base, &lock_context); +} + +/* + * ns16550_set_attributes + * + * This function sets the channel to reflect the requested termios + * port settings. + */ + +static bool ns16550_set_attributes( + rtems_termios_device_context *base, + const struct termios *t +) +{ + ns16550_context *ctx = (ns16550_context *) base; + uint32_t pNS16550; + uint32_t ulBaudDivisor; + uint8_t ucLineControl; + uint32_t baud_requested; + ns16550_set_reg setReg; + rtems_interrupt_lock_context lock_context; + + pNS16550 = ctx->port; + setReg = ctx->set_reg; + + /* + * Calculate the baud rate divisor + */ + + baud_requested = rtems_termios_baud_to_number(t->c_cflag); + ulBaudDivisor = NS16550_GetBaudDivisor(ctx, baud_requested); + + ucLineControl = 0; + + /* + * Parity + */ + + if (t->c_cflag & PARENB) { + ucLineControl |= SP_LINE_PAR; + if (!(t->c_cflag & PARODD)) + ucLineControl |= SP_LINE_ODD; + } + + /* + * Character Size + */ + + if (t->c_cflag & CSIZE) { + switch (t->c_cflag & CSIZE) { + case CS5: ucLineControl |= FIVE_BITS; break; + case CS6: ucLineControl |= SIX_BITS; break; + case CS7: ucLineControl |= SEVEN_BITS; break; + case CS8: ucLineControl |= EIGHT_BITS; break; + } + } else { + ucLineControl |= EIGHT_BITS; /* default to 9600,8,N,1 */ + } + + /* + * Stop Bits + */ + + if (t->c_cflag & CSTOPB) { + ucLineControl |= SP_LINE_STOP; /* 2 stop bits */ + } else { + ; /* 1 stop bit */ + } + + /* + * Now actually set the chip + */ + + rtems_termios_device_lock_acquire(base, &lock_context); + + /* + * Set the baud rate + * + * NOTE: When the Divisor Latch Access Bit (DLAB) is set to 1, + * the transmit buffer and interrupt enable registers + * turn into the LSB and MSB divisor latch registers. + */ + + (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB); + (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff); + (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff); + + /* + * Now write the line control + */ + (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl ); + + rtems_termios_device_lock_release(base, &lock_context); + + return true; +} + +/** + * @brief Transmits up to @a len characters from @a buf. + * + * This routine is invoked either from task context with disabled interrupts to + * start a new transmission process with exactly one character in case of an + * idle output state or from the interrupt handler to refill the transmitter. + * + * Returns always zero. + */ +static void ns16550_write_support_int( + rtems_termios_device_context *base, + const char *buf, + size_t len +) +{ + ns16550_context *ctx = (ns16550_context *) base; + uint32_t port = ctx->port; + ns16550_set_reg set = ctx->set_reg; + int i = 0; + int out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len; + + for (i = 0; i < out; ++i) { + set( port, NS16550_TRANSMIT_BUFFER, buf [i]); + } + + ctx->transmit_fifo_chars = out; + + if (out > 0) { + ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR); + } else { + ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); + } +} + +/* + * ns16550_write_support_polled + * + * Console Termios output entry point. + * + */ + +static void ns16550_write_support_polled( + rtems_termios_device_context *base, + const char *buf, + size_t len +) +{ + size_t nwrite = 0; + + /* + * poll each byte in the string out of the port. + */ + while (nwrite < len) { + /* + * transmit character + */ + ns16550_polled_putchar(base, *buf++); + nwrite++; + } +} + +/* + * Debug gets() support + */ +int ns16550_polled_getchar(rtems_termios_device_context *base) +{ + ns16550_context *ctx = (ns16550_context *) base; + uint32_t pNS16550; + unsigned char ucLineStatus; + uint8_t cChar; + ns16550_get_reg getReg; + + pNS16550 = ctx->port; + getReg = ctx->get_reg; + + ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS); + if (ucLineStatus & SP_LSR_RDY) { + cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER); + return (int)cChar; + } + return -1; +} + +/* + * Flow control is only supported when using interrupts + */ + +const rtems_termios_device_flow ns16550_flow_rtscts = { + .stop_remote_tx = ns16550_negate_RTS, + .start_remote_tx = ns16550_assert_RTS +}; + +const rtems_termios_device_flow ns16550_flow_dtrcts = { + .stop_remote_tx = ns16550_negate_DTR, + .start_remote_tx = ns16550_assert_DTR +}; + +const rtems_termios_device_handler ns16550_handler_interrupt = { + .first_open = ns16550_open, + .last_close = ns16550_close, + .poll_read = NULL, + .write = ns16550_write_support_int, + .set_attributes = ns16550_set_attributes, + .mode = TERMIOS_IRQ_DRIVEN +}; + +const rtems_termios_device_handler ns16550_handler_polled = { + .first_open = ns16550_open, + .last_close = ns16550_close, + .poll_read = ns16550_polled_getchar, + .write = ns16550_write_support_polled, + .set_attributes = ns16550_set_attributes, + .mode = TERMIOS_POLLED +}; diff --git a/c/src/libchip/serial/ns16550.c b/c/src/libchip/serial/ns16550.c index 390c729..b0aa38f 100644 --- a/c/src/libchip/serial/ns16550.c +++ b/c/src/libchip/serial/ns16550.c @@ -58,6 +58,82 @@ #endif #endif +typedef struct { + uint8_t ucModemCtrl; + int transmitFifoChars; +} NS16550Context; + +/* + * Driver functions + */ + +NS16550_STATIC void ns16550_init(int minor); + +NS16550_STATIC int ns16550_open( + int major, + int minor, + void * arg +); + +NS16550_STATIC int ns16550_close( + int major, + int minor, + void * arg +); + +NS16550_STATIC void ns16550_write_polled( + int minor, + char cChar +); + +NS16550_STATIC int ns16550_assert_RTS( + int minor +); + +NS16550_STATIC int ns16550_negate_RTS( + int minor +); + +NS16550_STATIC int ns16550_assert_DTR( + int minor +); + +NS16550_STATIC int ns16550_negate_DTR( + int minor +); + +NS16550_STATIC void ns16550_initialize_interrupts(int minor); + +NS16550_STATIC void ns16550_cleanup_interrupts(int minor); + +NS16550_STATIC ssize_t ns16550_write_support_int( + int minor, + const char *buf, + size_t len +); + +NS16550_STATIC ssize_t ns16550_write_support_polled( + int minor, + const char *buf, + size_t len + ); + +int ns16550_inbyte_nonblocking_polled( + int minor +); + +NS16550_STATIC void ns16550_enable_interrupts( + console_tbl *c, + int mask +); + +NS16550_STATIC int ns16550_set_attributes( + int minor, + const struct termios *t +); + +NS16550_STATIC void ns16550_isr(void *arg); + static rtems_interrupt_lock ns16550_lock = RTEMS_INTERRUPT_LOCK_INITIALIZER("NS16550"); @@ -142,12 +218,12 @@ void ns16550_init(int minor) uintptr_t pNS16550; uint8_t ucDataByte; uint32_t ulBaudDivisor; - ns16550_context *pns16550Context; + NS16550Context *pns16550Context; setRegister_f setReg; getRegister_f getReg; console_tbl *c = Console_Port_Tbl [minor]; - pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context)); + pns16550Context=(NS16550Context *)malloc(sizeof(NS16550Context)); if (pns16550Context == NULL) { printk( "%s: Error: Not enough memory\n", __func__); @@ -328,10 +404,10 @@ NS16550_STATIC int ns16550_assert_RTS(int minor) { uint32_t pNS16550; rtems_interrupt_lock_context lock_context; - ns16550_context *pns16550Context; + NS16550Context *pns16550Context; setRegister_f setReg; - pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext; + pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; setReg = Console_Port_Tbl[minor]->setRegister; @@ -354,10 +430,10 @@ NS16550_STATIC int ns16550_negate_RTS(int minor) { uint32_t pNS16550; rtems_interrupt_lock_context lock_context; - ns16550_context *pns16550Context; + NS16550Context *pns16550Context; setRegister_f setReg; - pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext; + pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; setReg = Console_Port_Tbl[minor]->setRegister; @@ -385,10 +461,10 @@ NS16550_STATIC int ns16550_assert_DTR(int minor) { uint32_t pNS16550; rtems_interrupt_lock_context lock_context; - ns16550_context *pns16550Context; + NS16550Context *pns16550Context; setRegister_f setReg; - pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext; + pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; setReg = Console_Port_Tbl[minor]->setRegister; @@ -411,10 +487,10 @@ NS16550_STATIC int ns16550_negate_DTR(int minor) { uint32_t pNS16550; rtems_interrupt_lock_context lock_context; - ns16550_context *pns16550Context; + NS16550Context *pns16550Context; setRegister_f setReg; - pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext; + pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; setReg = Console_Port_Tbl[minor]->setRegister; @@ -533,7 +609,7 @@ NS16550_STATIC void ns16550_process( int minor) { console_tbl *c = Console_Port_Tbl [minor]; console_data *d = &Console_Port_Data [minor]; - ns16550_context *ctx = d->pDeviceContext; + NS16550Context *ctx = d->pDeviceContext; uint32_t port = c->ulCtrlPort1; getRegister_f get = c->getRegister; int i = 0; @@ -584,7 +660,7 @@ ssize_t ns16550_write_support_int( { console_tbl *c = Console_Port_Tbl [minor]; console_data *d = &Console_Port_Data [minor]; - ns16550_context *ctx = d->pDeviceContext; + NS16550Context *ctx = d->pDeviceContext; uint32_t port = c->ulCtrlPort1; setRegister_f set = c->setRegister; int i = 0; diff --git a/c/src/libchip/serial/ns16550.h b/c/src/libchip/serial/ns16550.h index 2890566..ef1f9f9 100644 --- a/c/src/libchip/serial/ns16550.h +++ b/c/src/libchip/serial/ns16550.h @@ -27,6 +27,7 @@ #ifndef _NS16550_H_ #define _NS16550_H_ +#include <rtems/termiostypes.h> #include <libchip/serial.h> #ifdef __cplusplus @@ -53,6 +54,37 @@ extern const console_flow ns16550_flow_DTRCTS; void ns16550_outch_polled(console_tbl *c, char out); int ns16550_inch_polled(console_tbl *c); +/* Alternative NS16550 driver using the Termios device context */ + +typedef uint8_t (*ns16550_get_reg)(uintptr_t port, uint8_t reg); + +typedef void (*ns16550_set_reg)(uintptr_t port, uint8_t reg, uint8_t value); + +typedef struct { + rtems_termios_device_context base; + ns16550_get_reg get_reg; + ns16550_set_reg set_reg; + uintptr_t port; + rtems_vector_number irq; + uint32_t clock; + uint32_t initial_baud; + bool has_fractional_divider_register; + uint8_t modem_control; + size_t transmit_fifo_chars; +} ns16550_context; + +extern const rtems_termios_device_handler ns16550_handler_interrupt; +extern const rtems_termios_device_handler ns16550_handler_polled; + +extern const rtems_termios_device_flow ns16550_flow_rtscts; +extern const rtems_termios_device_flow ns16550_flow_dtrcts; + +void ns16550_polled_putchar(rtems_termios_device_context *base, char out); + +int ns16550_polled_getchar(rtems_termios_device_context *base); + +bool ns16550_probe(rtems_termios_device_context *base); + #ifdef __cplusplus } #endif diff --git a/c/src/libchip/serial/ns16550_p.h b/c/src/libchip/serial/ns16550_p.h index 4e6d784..0fe817a 100644 --- a/c/src/libchip/serial/ns16550_p.h +++ b/c/src/libchip/serial/ns16550_p.h @@ -131,82 +131,6 @@ extern "C" { #define SP_LSR_TX 0x40 #define SP_LSR_EFIFO 0x80 -typedef struct { - uint8_t ucModemCtrl; - int transmitFifoChars; -} ns16550_context; - -/* - * Driver functions - */ - -void ns16550_init(int minor); - -int ns16550_open( - int major, - int minor, - void * arg -); - -int ns16550_close( - int major, - int minor, - void * arg -); - -void ns16550_write_polled( - int minor, - char cChar -); - -NS16550_STATIC int ns16550_assert_RTS( - int minor -); - -NS16550_STATIC int ns16550_negate_RTS( - int minor -); - -NS16550_STATIC int ns16550_assert_DTR( - int minor -); - -NS16550_STATIC int ns16550_negate_DTR( - int minor -); - -NS16550_STATIC void ns16550_initialize_interrupts(int minor); - -NS16550_STATIC void ns16550_cleanup_interrupts(int minor); - -ssize_t ns16550_write_support_int( - int minor, - const char *buf, - size_t len -); - -ssize_t ns16550_write_support_polled( - int minor, - const char *buf, - size_t len - ); - -int ns16550_inbyte_nonblocking_polled( - int minor -); - -NS16550_STATIC void ns16550_enable_interrupts( - console_tbl *c, - int mask -); - -int ns16550_set_attributes( - int minor, - const struct termios *t -); - -void ns16550_isr(void *arg); - #ifdef __cplusplus } #endif -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel