[PATCH 4/7] libchip/serial: Add alternative NS16550 driver
Sebastian Huber
sebastian.huber at embedded-brains.de
Tue Oct 7 14:36:28 UTC 2014
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
* <rtems at 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
* <rtems at 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
* <rtems at 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
* <rtems at 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
* <rtems at 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
* <rtems at 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
- * <rtems at embedded-brains.de>
+ * Copyright (c) 2009-2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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
- * <rtems at embedded-brains.de>
+ * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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
+ * <rtems at 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
* <rtems at 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
- * rtems at embedded-brains.de
+ * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <info at 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
* <rtems at 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
* <rtems at 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
* <rtems at 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
More information about the devel
mailing list