Index: c/src/lib/libbsp/arm/atsam/console/console.c
===================================================================
--- c/src/lib/libbsp/arm/atsam/console/console.c	(revision f2e0f8e1a769231257f38a6bb6ab9ea9bbad452f)
+++ c/src/lib/libbsp/arm/atsam/console/console.c	(revision f2e0f8e1a769231257f38a6bb6ab9ea9bbad452f)
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@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 <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/fatal.h>
+
+#include <rtems/termiostypes.h>
+
+#include <chip.h>
+
+typedef struct {
+  rtems_termios_device_context base;
+  Usart *regs;
+  rtems_vector_number irq;
+  uint32_t id;
+  bool console;
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  bool transmitting;
+#endif
+} atsam_usart_context;
+
+static atsam_usart_context atsam_usart_instances[] = {
+  {
+    .regs = USART0,
+    .irq = USART0_IRQn,
+    .id = ID_USART0
+  }
+#ifdef USART1
+  , {
+    .regs = USART1,
+    .irq = USART1_IRQn,
+    .id = ID_USART1
+  }
+#endif
+#ifdef USART2
+  , {
+    .regs = USART2,
+    .irq = USART2_IRQn,
+    .id = ID_USART2
+  }
+#endif
+};
+
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+static void atsam_usart_interrupt(void *arg)
+{
+  rtems_termios_tty *tty = arg;
+  atsam_usart_context *ctx = rtems_termios_get_device_context(tty);
+  Usart *regs = ctx->regs;
+  uint32_t csr = regs->US_CSR;
+
+  while ((csr & US_CSR_RXRDY) != 0) {
+    char c = (char) regs->US_RHR;
+
+    rtems_termios_enqueue_raw_characters(tty, &c, 1);
+
+    csr = regs->US_CSR;
+  }
+
+  if (ctx->transmitting && (csr & US_CSR_TXEMPTY) != 0) {
+    rtems_termios_dequeue_characters(tty, 1);
+  }
+}
+#endif
+
+static bool atsam_usart_set_attributes(
+  rtems_termios_device_context *base,
+  const struct termios *term
+)
+{
+  atsam_usart_context *ctx = (atsam_usart_context *) base;
+  Usart *regs = ctx->regs;
+  rtems_termios_baud_t baud;
+  uint32_t mr;
+
+  baud = rtems_termios_baud_to_number(term->c_cflag);
+  regs->US_BRGR = (BOARD_MCK / baud) / 16;
+
+  if ((term->c_cflag & CREAD) != 0) {
+    regs->US_CR = US_CR_RXEN | US_CR_TXEN;
+  } else {
+    regs->US_CR = US_CR_TXEN;
+  }
+
+  mr = US_MR_USART_MODE_NORMAL | US_MR_USCLKS_MCK;
+
+  switch (term->c_cflag & CSIZE) {
+    case CS5:
+      mr |= US_MR_CHRL_5_BIT;
+      break;
+    case CS6:
+      mr |= US_MR_CHRL_6_BIT;
+      break;
+    case CS7:
+      mr |= US_MR_CHRL_7_BIT;
+      break;
+    default:
+      mr |= US_MR_CHRL_8_BIT;
+      break;
+  }
+
+  if ((term->c_cflag & PARENB) != 0) {
+    if ((term->c_cflag & PARODD) != 0) {
+      mr |= US_MR_PAR_ODD;
+    } else {
+      mr |= US_MR_PAR_EVEN;
+    }
+  } else {
+    mr |= US_MR_PAR_NO;
+  }
+
+  if ((term->c_cflag & CSTOPB) != 0) {
+    mr |= US_MR_NBSTOP_2_BIT;
+  } else {
+    mr |= US_MR_NBSTOP_1_BIT;
+  }
+
+  regs->US_MR = mr;
+
+  return true;
+}
+
+static bool atsam_usart_first_open(
+  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  struct termios *term,
+  rtems_libio_open_close_args_t *args
+)
+{
+  atsam_usart_context *ctx = (atsam_usart_context *) base;
+  Usart *regs = ctx->regs;
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  rtems_status_code sc;
+#endif
+
+  regs->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RSTSTA;
+  regs->US_IDR = 0xffffffff;
+
+  PMC_EnablePeripheral(ctx->id);
+
+  rtems_termios_set_initial_baud(tty, ATSAM_CONSOLE_BAUD);
+  atsam_usart_set_attributes(base, term);
+
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  regs->US_IER = US_IDR_RXRDY;
+  sc = rtems_interrupt_handler_install(
+    ctx->irq,
+    "USART",
+    RTEMS_INTERRUPT_SHARED,
+    atsam_usart_interrupt,
+    tty
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    return false;
+  }
+#endif
+
+  return true;
+}
+
+static void atsam_usart_last_close(
+  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  rtems_libio_open_close_args_t *args
+)
+{
+  atsam_usart_context *ctx = (atsam_usart_context *) base;
+
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  rtems_interrupt_handler_remove(ctx->irq, atsam_usart_interrupt, tty);
+#endif
+
+  if (!ctx->console) {
+    PMC_DisablePeripheral(ctx->id);
+  }
+}
+
+static void atsam_usart_write(
+  rtems_termios_device_context *base,
+  const char *buf,
+  size_t len
+)
+{
+  atsam_usart_context *ctx = (atsam_usart_context *) base;
+  Usart *regs = ctx->regs;
+
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  if (len > 0) {
+    ctx->transmitting = true;
+    regs->US_THR = buf[0];
+    regs->US_IER = US_IDR_TXEMPTY;
+  } else {
+    ctx->transmitting = false;
+    regs->US_IDR = US_IDR_TXEMPTY;
+  }
+#else
+  size_t i;
+
+  for (i = 0; i < len; ++i) {
+    while ((regs->US_CSR & US_CSR_TXEMPTY) == 0) {
+      /* Wait */
+    }
+
+    regs->US_THR = buf[i];
+  }
+#endif
+}
+
+#ifndef ATSAM_CONSOLE_USE_INTERRUPTS
+static int atsam_usart_read(rtems_termios_device_context *base)
+{
+  atsam_usart_context *ctx = (atsam_usart_context *) base;
+  Usart *regs = ctx->regs;
+
+  if ((regs->US_CSR & US_CSR_RXRDY) != 0) {
+    return (char) regs->US_RHR;
+  } else {
+    return -1;
+  }
+}
+#endif
+
+static const rtems_termios_device_handler atsam_usart_handler = {
+  .first_open = atsam_usart_first_open,
+  .last_close = atsam_usart_last_close,
+  .write = atsam_usart_write,
+  .set_attributes = atsam_usart_set_attributes,
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  .mode = TERMIOS_IRQ_DRIVEN
+#else
+  .poll_read = atsam_usart_read,
+  .mode = TERMIOS_POLLED
+#endif
+};
+
+typedef struct {
+  rtems_termios_device_context base;
+  Uart *regs;
+  rtems_vector_number irq;
+  uint32_t id;
+  bool console;
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  bool transmitting;
+#endif
+} atsam_uart_context;
+
+static atsam_uart_context atsam_uart_instances[] = {
+  {
+    .regs = UART0,
+    .irq = UART0_IRQn,
+    .id = ID_UART0
+  }
+#ifdef UART1
+  , {
+    .regs = UART1,
+    .irq = UART1_IRQn,
+    .id = ID_UART1
+  }
+#endif
+#ifdef UART2
+  , {
+    .regs = UART2,
+    .irq = UART2_IRQn,
+    .id = ID_UART2
+  }
+#endif
+#ifdef UART3
+  , {
+    .regs = UART3,
+    .irq = UART3_IRQn,
+    .id = ID_UART3
+  }
+#endif
+#ifdef UART4
+  , {
+    .regs = UART4,
+    .irq = UART4_IRQn,
+    .id = ID_UART4
+  }
+#endif
+};
+
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+static void atsam_uart_interrupt(void *arg)
+{
+  rtems_termios_tty *tty = arg;
+  atsam_uart_context *ctx = rtems_termios_get_device_context(tty);
+  Uart *regs = ctx->regs;
+  uint32_t sr = regs->UART_SR;
+
+  while ((sr & UART_SR_RXRDY) != 0) {
+    char c = (char) regs->UART_RHR;
+
+    rtems_termios_enqueue_raw_characters(tty, &c, 1);
+
+    sr = regs->UART_SR;
+  }
+
+  if (ctx->transmitting && (sr & UART_SR_TXEMPTY) != 0) {
+    rtems_termios_dequeue_characters(tty, 1);
+  }
+}
+#endif
+
+static bool atsam_uart_set_attributes(
+  rtems_termios_device_context *base,
+  const struct termios *term
+)
+{
+  atsam_uart_context *ctx = (atsam_uart_context *) base;
+  Uart *regs = ctx->regs;
+  rtems_termios_baud_t baud;
+  uint32_t mr;
+
+  baud = rtems_termios_baud_to_number(term->c_cflag);
+  regs->UART_BRGR = (BOARD_MCK / baud) / 16;
+
+  if ((term->c_cflag & CREAD) != 0) {
+    regs->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
+  } else {
+    regs->UART_CR = UART_CR_TXEN;
+  }
+
+  mr = UART_MR_FILTER_DISABLED | UART_MR_BRSRCCK_PERIPH_CLK;
+
+  if ((term->c_cflag & CSIZE) != CS8) {
+    return false;
+  }
+
+  if ((term->c_cflag & PARENB) != 0) {
+    if ((term->c_cflag & PARODD) != 0) {
+      mr |= UART_MR_PAR_ODD;
+    } else {
+      mr |= UART_MR_PAR_EVEN;
+    }
+  } else {
+    mr |= UART_MR_PAR_NO;
+  }
+
+  if ((term->c_cflag & CSTOPB) != 0) {
+    return false;
+  }
+
+  regs->UART_MR = mr;
+
+  return true;
+}
+
+static bool atsam_uart_first_open(
+  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  struct termios *term,
+  rtems_libio_open_close_args_t *args
+)
+{
+  atsam_uart_context *ctx = (atsam_uart_context *) base;
+  Uart *regs = ctx->regs;
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  rtems_status_code sc;
+#endif
+
+  regs->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RSTSTA;
+  regs->UART_IDR = 0xffffffff;
+
+  PMC_EnablePeripheral(ctx->id);
+
+  rtems_termios_set_initial_baud(tty, ATSAM_CONSOLE_BAUD);
+  atsam_uart_set_attributes(base, term);
+
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  regs->UART_IER = UART_IDR_RXRDY;
+  sc = rtems_interrupt_handler_install(
+    ctx->irq,
+    "UART",
+    RTEMS_INTERRUPT_SHARED,
+    atsam_uart_interrupt,
+    tty
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    return false;
+  }
+#endif
+
+  return true;
+}
+
+static void atsam_uart_last_close(
+  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  rtems_libio_open_close_args_t *args
+)
+{
+  atsam_uart_context *ctx = (atsam_uart_context *) base;
+
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  rtems_interrupt_handler_remove(ctx->irq, atsam_uart_interrupt, tty);
+#endif
+
+  if (!ctx->console) {
+    PMC_DisablePeripheral(ctx->id);
+  }
+}
+
+static void atsam_uart_write(
+  rtems_termios_device_context *base,
+  const char *buf,
+  size_t len
+)
+{
+  atsam_uart_context *ctx = (atsam_uart_context *) base;
+  Uart *regs = ctx->regs;
+
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  if (len > 0) {
+    ctx->transmitting = true;
+    regs->UART_THR = buf[0];
+    regs->UART_IER = UART_IDR_TXEMPTY;
+  } else {
+    ctx->transmitting = false;
+    regs->UART_IDR = UART_IDR_TXEMPTY;
+  }
+#else
+  size_t i;
+
+  for (i = 0; i < len; ++i) {
+    while ((regs->UART_SR & UART_SR_TXEMPTY) == 0) {
+      /* Wait */
+    }
+
+    regs->UART_THR = buf[i];
+  }
+#endif
+}
+
+#ifndef ATSAM_CONSOLE_USE_INTERRUPTS
+static int atsam_uart_read(rtems_termios_device_context *base)
+{
+  atsam_uart_context *ctx = (atsam_uart_context *) base;
+  Uart *regs = ctx->regs;
+
+  if ((regs->UART_SR & UART_SR_RXRDY) != 0) {
+    return (char) regs->UART_RHR;
+  } else {
+    return -1;
+  }
+}
+#endif
+
+static const rtems_termios_device_handler atsam_uart_handler = {
+  .first_open = atsam_uart_first_open,
+  .last_close = atsam_uart_last_close,
+  .write = atsam_uart_write,
+  .set_attributes = atsam_uart_set_attributes,
+#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
+  .mode = TERMIOS_IRQ_DRIVEN
+#else
+  .poll_read = atsam_uart_read,
+  .mode = TERMIOS_POLLED
+#endif
+};
+
+rtems_status_code console_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  size_t i;
+
+  rtems_termios_initialize();
+
+  for (i = 0; i < RTEMS_ARRAY_SIZE(atsam_usart_instances); ++i) {
+    char usart[] = "/dev/ttyUSARTX";
+
+    usart[sizeof(usart) - 2] = (char) ('0' + i);
+    rtems_termios_device_install(
+      &usart[0],
+      major,
+      minor,
+      &atsam_usart_handler,
+      NULL,
+      &atsam_usart_instances[i].base
+    );
+
+#if ATSAM_CONSOLE_DEVICE_TYPE == 0
+    if (i == ATSAM_CONSOLE_DEVICE_INDEX) {
+      atsam_usart_instances[i].console = true;
+      rtems_io_register_name(CONSOLE_DEVICE_NAME, major, minor);
+    }
+#endif
+
+    ++minor;
+  }
+
+  for (i = 0; i < RTEMS_ARRAY_SIZE(atsam_uart_instances); ++i) {
+    char uart[] = "/dev/ttyUARTX";
+
+    uart[sizeof(uart) - 2] = (char) ('0' + i);
+    rtems_termios_device_install(
+      &uart[0],
+      major,
+      minor,
+      &atsam_uart_handler,
+      NULL,
+      &atsam_uart_instances[i].base
+    );
+
+#if ATSAM_CONSOLE_DEVICE_TYPE == 1
+    if (i == ATSAM_CONSOLE_DEVICE_INDEX) {
+      atsam_uart_instances[i].console = true;
+      rtems_io_register_name(CONSOLE_DEVICE_NAME, major, minor);
+    }
+#endif
+
+    ++minor;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
Index: c/src/lib/libbsp/arm/atsam/console/debug-console.c
===================================================================
--- c/src/lib/libbsp/arm/atsam/console/debug-console.c	(revision f2e0f8e1a769231257f38a6bb6ab9ea9bbad452f)
+++ c/src/lib/libbsp/arm/atsam/console/debug-console.c	(revision f2e0f8e1a769231257f38a6bb6ab9ea9bbad452f)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@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/bspIo.h>
+#include <rtems/sysinit.h>
+
+#include <chip.h>
+#include <include/dbg_console.h>
+
+static void atsam_debug_console_out(char c)
+{
+  if (c == '\n') {
+    DBG_PutChar('\r');
+  }
+
+  DBG_PutChar((uint8_t) c);
+}
+
+static void atsam_debug_console_init(void)
+{
+  DBG_Configure(115200, BOARD_MCK);
+  BSP_output_char = atsam_debug_console_out;
+}
+
+static void atsam_debug_console_early_init(char c)
+{
+  atsam_debug_console_init();
+  atsam_debug_console_out(c);
+}
+
+static int atsam_debug_console_in(void)
+{
+  return (int) DBG_GetChar();
+}
+
+BSP_output_char_function_type BSP_output_char = atsam_debug_console_early_init;
+
+BSP_polling_getchar_function_type BSP_poll_char = atsam_debug_console_in;
+
+RTEMS_SYSINIT_ITEM(
+  atsam_debug_console_init,
+  RTEMS_SYSINIT_BSP_START,
+  RTEMS_SYSINIT_ORDER_LAST
+);
