[PATCH] cpukit: Add nxp-sc16is752 serial device driver

Alexander Krutwig alexander.krutwig at embedded-brains.de
Fri Sep 16 13:36:24 UTC 2016


---
 cpukit/dev/Makefile.am                        |   7 +
 cpukit/dev/include/dev/serial/nxp-sc16is752.h |  68 ++++++
 cpukit/dev/preinstall.am                      |   9 +
 cpukit/dev/serial/nxp-sc16is752-regs.h        | 122 ++++++++++
 cpukit/dev/serial/nxp-sc16is752-spi.c         |  90 +++++++
 cpukit/dev/serial/nxp-sc16is752.c             | 324 ++++++++++++++++++++++++++
 6 files changed, 620 insertions(+)
 create mode 100644 cpukit/dev/include/dev/serial/nxp-sc16is752.h
 create mode 100644 cpukit/dev/serial/nxp-sc16is752-regs.h
 create mode 100644 cpukit/dev/serial/nxp-sc16is752-spi.c
 create mode 100644 cpukit/dev/serial/nxp-sc16is752.c

diff --git a/cpukit/dev/Makefile.am b/cpukit/dev/Makefile.am
index 2b65390..cdc3fe8 100644
--- a/cpukit/dev/Makefile.am
+++ b/cpukit/dev/Makefile.am
@@ -15,6 +15,10 @@ include_dev_spidir = $(includedir)/dev/spi
 include_dev_spi_HEADERS =
 include_dev_spi_HEADERS += include/dev/spi/spi.h
 
+include_dev_serialdir = $(includedir)/dev/serial
+include_dev_serial_HEADERS =
+include_dev_serial_HEADERS += include/dev/serial/nxp-sc16is752.h
+
 include_linuxdir = $(includedir)/linux
 include_linux_HEADERS =
 include_linux_HEADERS += include/linux/i2c.h
@@ -33,6 +37,9 @@ libdev_a_SOURCES += i2c/i2c-bus.c
 libdev_a_SOURCES += i2c/i2c-dev.c
 libdev_a_SOURCES += i2c/switch-nxp-pca9548a.c
 libdev_a_SOURCES += spi/spi-bus.c
+libdev_a_SOURCES += serial/nxp-sc16is752.c
+libdev_a_SOURCES += serial/nxp-sc16is752-spi.c
+libdev_a_SOURCES += serial/nxp-sc16is752-regs.h
 
 include $(srcdir)/preinstall.am
 include $(top_srcdir)/automake/local.am
diff --git a/cpukit/dev/include/dev/serial/nxp-sc16is752.h b/cpukit/dev/include/dev/serial/nxp-sc16is752.h
new file mode 100644
index 0000000..2566ebe
--- /dev/null
+++ b/cpukit/dev/include/dev/serial/nxp-sc16is752.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016 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
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef _DEV_SERIAL_SC16IS752_H
+#define _DEV_SERIAL_SC16IS752_H
+
+#include <rtems/termiostypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* General device paths */
+#define SC16IS752_PATH "/dev/ttyUARTSC16IS752"
+
+typedef struct {
+  const char *spi_nxp_path;
+  uint8_t cs;
+  uint32_t speed_hz;
+} sc16is752_reg_ctx;
+
+typedef struct {
+  rtems_termios_device_context base;
+  sc16is752_reg_ctx *reg_ctx;
+  int (*write_reg)(int fd,
+    sc16is752_reg_ctx *reg_ctx,
+    uint8_t addr,
+    uint8_t data
+  );
+  int (*read_reg)(int fd,
+    sc16is752_reg_ctx *reg_ctx,
+    uint8_t addr,
+    uint8_t *data
+  );
+  uint32_t input_frequency;
+  rtems_vector_number irq;
+  int fd;
+  bool rs485_wanted;
+#ifdef SC16IS752_USE_INTERRUPTS
+  bool transmitting;
+#endif
+} sc16is752_uart_ctx;
+
+rtems_status_code sc16is752_initialize(
+  sc16is752_uart_ctx *uart_ctx,
+  sc16is752_reg_ctx *reg_ctx,
+  uint32_t input_frequency,
+  rtems_vector_number irq,
+  bool rs485_wanted,
+  void *arg
+);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _DEV_SERIAL_SC16IS752_H */
diff --git a/cpukit/dev/preinstall.am b/cpukit/dev/preinstall.am
index d2e63ba..801bdb5 100644
--- a/cpukit/dev/preinstall.am
+++ b/cpukit/dev/preinstall.am
@@ -48,6 +48,15 @@ $(PROJECT_INCLUDE)/dev/spi/spi.h: include/dev/spi/spi.h $(PROJECT_INCLUDE)/dev/s
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/spi/spi.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/spi/spi.h
 
+$(PROJECT_INCLUDE)/dev/serial/$(dirstamp):
+	@$(MKDIR_P) $(PROJECT_INCLUDE)/dev/serial
+	@: > $(PROJECT_INCLUDE)/dev/serial/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/dev/serial/$(dirstamp)
+
+$(PROJECT_INCLUDE)/dev/serial/nxp-sc16is752.h: include/dev/serial/nxp-sc16is752.h $(PROJECT_INCLUDE)/dev/serial/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/serial/nxp-sc16is752.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/serial/nxp-sc16is752.h
+
 $(PROJECT_INCLUDE)/linux/$(dirstamp):
 	@$(MKDIR_P) $(PROJECT_INCLUDE)/linux
 	@: > $(PROJECT_INCLUDE)/linux/$(dirstamp)
diff --git a/cpukit/dev/serial/nxp-sc16is752-regs.h b/cpukit/dev/serial/nxp-sc16is752-regs.h
new file mode 100644
index 0000000..0b1c024
--- /dev/null
+++ b/cpukit/dev/serial/nxp-sc16is752-regs.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016 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
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_ATSAM_SC16IS752_H
+#define LIBBSP_ARM_ATSAM_SC16IS752_H
+
+#include <dev/serial/nxp-sc16is752.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* General device paths */
+#define SC16IS752_PATH "/dev/ttyUARTSC16IS752"
+
+/* General register set */
+#define SC16IS752_RHR 0x0
+#define SC16IS752_THR 0x0
+#define SC16IS752_IER 0x1
+#define SC16IS752_FCR 0x2
+#define SC16IS752_IIR 0x2
+#define SC16IS752_LCR 0x3
+#define SC16IS752_MCR 0x4
+#define SC16IS752_LSR 0x5
+#define SC16IS752_MSR 0x6
+#define SC16IS752_TCR 0x6
+#define SC16IS752_SPR 0x7
+#define SC16IS752_TLR 0x7
+#define SC16IS752_TXLVL 0x8
+#define SC16IS752_RXLVL 0x9
+#define SC16IS752_IODIR 0xA
+#define SC16IS752_IOSTATE 0xB
+#define SC16IS752_IOINTENA 0xC
+#define SC16IS752_IOCONTROL 0xE
+#define SC16IS752_EFCR 0xF
+
+/* Special register set */
+#define SC16IS752_DLL 0x0
+#define SC16IS752_DLH 0x1
+
+/* Enhanced register set */
+#define SC16IS752_EFR 0x2
+#define SC16IS752_XON1 0x4
+#define SC16IS752_XON2 0x5
+#define SC16IS752_XOFF1 0x6
+#define SC16IS752_XOFF2 0x7
+
+/* EFCR Bit masks */
+#define EFCR_RS485ENABLE (1 << 0)
+#define EFCR_RXENABLE (0 << 1)
+#define EFCR_TXENABLE (0 << 2)
+
+/* IER Bit masks */
+#define IER_ENABLE_RHR_INTERRUPT (1u << 0)
+#define IER_ENABLE_THR_INTERRUPT (1u << 1)
+
+/* LCR Bit masks */
+#define LCR_CHRL_5_BIT (0u << 1) | (0u << 0)
+#define LCR_CHRL_6_BIT (0u << 1) | (1u << 0)
+#define LCR_CHRL_7_BIT (1u << 1) | (0u << 0)
+#define LCR_CHRL_8_BIT (1u << 1) | (1u << 0)
+#define LCR_2_STOP_BIT (1u << 2)
+#define LCR_SET_PARITY (1u << 3)
+#define LCR_EVEN_PARITY (1u << 4)
+#define LCR_ENABLE_DIVISOR (1u << 7)
+#define LCR_ENABLE_DIVISOR (1u << 7)
+
+/* LSR Bit masks */
+#define LSR_TXEMPTY (1u << 5)
+#define LSR_RXRDY (1u << 0)
+#define LSR_ERROR_BITS (7u << 2)
+
+/* MCR Bit masks */
+#define MCR_PRESCALE_NEEDED (1u << 0)
+
+/**
+ * @brief Writes a value to a register specified by an offset.
+ *
+ * @param[in] reg_addr The register address expressed as an offset.
+ * @param[in] reg_val The register value that shall be written to the specified
+ * address.
+ * @param[in] msg The message that shall be sent.
+ */
+int sc16is752_write_register (
+  int fd,
+  sc16is752_reg_ctx *ctx,
+  uint8_t reg_addr,
+  const uint8_t reg_val
+);
+
+/**
+ * @brief Reads a value from a register specified by an offset.
+ *
+ * @param[in] reg_addr The register address expressed as an offset.
+ * @param[out] reg_val The register value that shall be read from the specified
+ * address.
+ * @param[in] msg The message that shall be sent.
+ */
+int sc16is752_read_register (
+  int fd,
+  sc16is752_reg_ctx *ctx,
+  uint8_t reg_addr,
+  uint8_t *reg_val
+);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_ATSAM_SC16IS752_H */
diff --git a/cpukit/dev/serial/nxp-sc16is752-spi.c b/cpukit/dev/serial/nxp-sc16is752-spi.c
new file mode 100644
index 0000000..65f7070
--- /dev/null
+++ b/cpukit/dev/serial/nxp-sc16is752-spi.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016 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
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <bsp/spi.h>
+#include <bsp/atsam-spi.h>
+#include "nxp-sc16is752-regs.h"
+
+static void set_default_msg(
+  struct spi_ioc_transfer *msg,
+  uint8_t cs,
+  uint32_t speed,
+  uint8_t *rx_buf,
+  uint8_t *tx_buf
+)
+{
+	msg->rx_buf = rx_buf;
+	msg->tx_buf = tx_buf;
+	msg->len = REGISTER_COMMAND_LENGTH;
+	msg->speed_hz = speed;
+	msg->delay_usecs = 1;
+	msg->bits_per_word = 8;
+	msg->cs_change = 1;
+	msg->rx_nbits = 0;
+	msg->tx_nbits = 0;
+	msg->mode = 0;
+	msg->cs = cs;
+}
+
+
+int sc16is752_write_register(
+  int fd,
+  sc16is752_reg_ctx *ctx,
+  uint8_t reg_addr,
+  const uint8_t reg_val
+)
+{
+  int rv;
+  spi_ioc_transfer msg;
+  uint8_t tx_buf[REGISTER_COMMAND_LENGTH];
+  uint8_t rx_buf[REGISTER_COMMAND_LENGTH];
+
+  tx_buf[0] = reg_addr << 3;
+  tx_buf[1] = reg_val;
+
+  set_default_msg(&msg, ctx->cs, ctx->speed_hz, &rx_buf[0], &tx_buf[0]);
+
+  rv = ioctl(fd, SPI_IOC_MESSAGE(1), &msg);
+
+  return rv;
+}
+
+int sc16is752_read_register(
+  int fd,
+  sc16is752_reg_ctx *ctx,
+  uint8_t reg_addr,
+  uint8_t *reg_val
+)
+{
+  int rv;
+  spi_ioc_transfer msg;
+  uint8_t tx_buf[REGISTER_COMMAND_LENGTH];
+  uint8_t rx_buf[REGISTER_COMMAND_LENGTH];
+
+  tx_buf[0] = 0x80 | reg_addr << 3;
+  tx_buf[1] = 0x00;
+
+  set_default_msg(&msg, ctx->cs, ctx->speed_hz, &rx_buf[0], &tx_buf[0]);
+
+  rv = ioctl(fd, SPI_IOC_MESSAGE(1), &msg);
+  *reg_val = rx_buf[1];
+
+  return rv;
+}
+
diff --git a/cpukit/dev/serial/nxp-sc16is752.c b/cpukit/dev/serial/nxp-sc16is752.c
new file mode 100644
index 0000000..f6435e8
--- /dev/null
+++ b/cpukit/dev/serial/nxp-sc16is752.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2016 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 <fcntl.h>
+
+#include <bsp/atsam-spi.h>
+#include <bsp/spi.h>
+#include <dev/serial/nxp-sc16is752.h>
+#include "nxp-sc16is752-regs.h"
+
+#include <rtems/termiostypes.h>
+
+static void sc16is752_uart_set_baud_rate(
+  sc16is752_uart_ctx *ctx,
+  uint32_t value_mcr,
+  uint32_t divisor
+)
+{
+  uint8_t value_lcr;
+
+  ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_LCR, &value_lcr);
+  value_lcr |= LCR_ENABLE_DIVISOR;
+
+  ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_LCR, value_lcr);
+  ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_MCR, value_mcr);
+  ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_DLH, divisor >> 8);
+  ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_DLL, divisor);
+  value_lcr &= ~LCR_ENABLE_DIVISOR;
+  ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_LCR, value_lcr);
+}
+
+static bool sc16is752_uart_prepare_baud_rate(
+  sc16is752_uart_ctx *ctx,
+  rtems_termios_baud_t baud
+)
+{
+  uint32_t freq = ctx->input_frequency;
+  uint8_t value_mcr;
+  uint32_t divisor;
+
+  ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_MCR, &value_mcr);
+
+  divisor = freq / baud / 16;
+  if (divisor > 0xFFFF){
+    divisor = (freq / (4 * baud)) / 16;
+    if (divisor > 0xFFFF){
+      return false;
+    } else {
+      value_mcr |= MCR_PRESCALE_NEEDED;
+      sc16is752_uart_set_baud_rate(ctx, value_mcr, divisor);
+    }
+  } else {
+      value_mcr &= ~MCR_PRESCALE_NEEDED;
+      sc16is752_uart_set_baud_rate(ctx, value_mcr, divisor);
+  }
+  return true;
+}
+
+#ifdef SC16IS752_USE_INTERRUPTS
+static void sc16is752_uart_interrupt(void *arg)
+{
+  rtems_termios_tty *tty = arg;
+  sc16is752_uart_ctx *ctx = rtems_termios_get_device_context(tty);
+  uint8_t value_lsr;
+  uint8_t value_rhr;
+
+  ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_LSR, &value_lsr);
+
+  while ((value & LSR_RXRDY) != 0) {
+    char c;
+    ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_RHR, &value_rhr);
+    c = (char) value_rhr;
+
+    rtems_termios_enqueue_raw_characters(tty, &c, 1);
+
+    ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_LSR, &value_lsr);
+  }
+
+  if (ctx->transmitting && (value_lsr & LSR_TXEMPTY) != 0) {
+    rtems_termios_dequeue_characters(tty, 1);
+  }
+}
+#endif
+
+static bool sc16is752_uart_set_attributes(
+  rtems_termios_device_context *base,
+  const struct termios *term
+)
+{
+  sc16is752_uart_ctx *ctx = (sc16is752_uart_ctx *) base;
+  uint8_t lcr_value = 0;
+  uint8_t efcr_value = 0;
+  bool baud_successful;
+  rtems_termios_baud_t baud;
+
+  baud = rtems_termios_baud_to_number(term->c_cflag);
+  baud_successful = sc16is752_uart_prepare_baud_rate(ctx, baud);
+  if (!baud_successful){
+    return false;
+  }
+
+  if (ctx->rs485_wanted){
+    efcr_value = EFCR_RS485ENABLE;
+  }
+
+  if ((term->c_cflag & CREAD) != 0){
+    efcr_value |= EFCR_RXENABLE | EFCR_TXENABLE;
+  } else {
+    efcr_value |= EFCR_TXENABLE;
+  }
+  ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_EFCR, efcr_value);
+
+  switch (term->c_cflag & CSIZE) {
+    case CS5:
+      lcr_value |= LCR_CHRL_5_BIT;
+      break;
+    case CS6:
+      lcr_value |= LCR_CHRL_6_BIT;
+      break;
+    case CS7:
+      lcr_value |= LCR_CHRL_7_BIT;
+      break;
+    case CS8:
+      lcr_value |= LCR_CHRL_8_BIT;
+      break;
+  }
+
+  if ((term->c_cflag & PARENB) != 0){
+    if ((term->c_cflag & PARODD) != 0) {
+      lcr_value &= ~LCR_EVEN_PARITY;
+    } else {
+      lcr_value |= LCR_EVEN_PARITY;
+    }
+  } else {
+    lcr_value &= ~LCR_SET_PARITY;
+  }
+
+  if ((term->c_cflag & CSTOPB) != 0) {
+    lcr_value |= LCR_2_STOP_BIT;
+  } else {
+    lcr_value &= ~LCR_2_STOP_BIT;
+  }
+
+  ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_LCR, lcr_value);
+
+  return true;
+}
+
+static bool sc16is752_uart_first_open(
+  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  struct termios *term,
+  rtems_libio_open_close_args_t *args
+)
+{
+  (void)args;
+  sc16is752_uart_ctx *ctx = (sc16is752_uart_ctx *) base;
+#ifdef SC16IS752_USE_INTERRUPTS
+  rtems_status_code sc;
+#endif
+  ctx->fd = open(ATSAM_SPI_0_BUS_PATH, O_RDWR);
+  if (ctx->fd < 0) {
+    return false;
+  }
+
+  ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_FCR, 0x7);
+  ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_IER, 0x0);
+
+  rtems_termios_set_initial_baud(tty, ATSAM_CONSOLE_BAUD);
+  sc16is752_uart_set_attributes(base, term);
+
+#ifdef SC16IS752_USE_INTERRUPTS
+    ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_IER, &value);
+    value |= IER_ENABLE_RHR_INTERRUPT;
+    ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_IER, value);
+    sc = rtems_interrupt_handler_install(
+      ctx->irq,
+      "SC16IS752",
+      RTEMS_INTERRUPT_SHARED,
+      sc16is752_uart_interrupt,
+      tty
+    );
+    if (sc != RTEMS_SUCCESSFUL) {
+      return false;
+    }
+#endif
+
+  return true;
+}
+
+static void sc16is752_uart_last_close(
+  rtems_termios_tty *tty,
+  rtems_termios_device_context *base,
+  rtems_libio_open_close_args_t *args
+)
+{
+  (void) tty;
+  (void) args;
+  sc16is752_uart_ctx *ctx = (sc16is752_uart_ctx *) base;
+#ifdef SC16IS752_USE_INTERRUPTS
+  rtems_interrupt_handler_remove(ctx->irq, sc16is752_uart_interrupt, tty);
+#endif
+  close(ctx->fd);
+}
+
+static void sc16is752_uart_write(
+  rtems_termios_device_context *base,
+  const char *buf,
+  size_t len
+)
+{
+  uint8_t value;
+
+  sc16is752_uart_ctx *ctx = (sc16is752_uart_ctx *) base;
+
+#ifdef SC16IS752_USE_INTERRUPTS
+  if (len > 0) {
+    ctx->transmitting = true;
+    ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_THR, buf[0]);
+    ctx->write_reg(
+      ctx->fd,
+      ctx->reg_ctx,
+      SC16IS752_IER,
+      IER_ENABLE_THR_INTERRUPT
+    );
+  } else {
+    ctx->transmitting = false;
+    ctx->write_reg(
+      ctx->fd,
+      ctx->reg_ctx,
+      SC16IS752_IER,
+      IER_DISABLE_THR_INTERRUPT
+    );
+  }
+#else
+  size_t i;
+
+  for (i = 0; i < len; i++) {
+    do{
+      ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_LSR, &value);
+    } while ((value & LSR_TXEMPTY) == 0);
+
+    ctx->write_reg(ctx->fd, ctx->reg_ctx, SC16IS752_THR, buf[i]);
+  }
+#endif
+}
+
+#ifndef SC16IS752_USE_INTERRUPTS
+static int sc16is752_uart_read(rtems_termios_device_context *base)
+{
+  uint8_t status;
+  uint8_t rhr;
+  uint8_t rx_amount;
+
+  sc16is752_uart_ctx *ctx = (sc16is752_uart_ctx *) base;
+
+  ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_RXLVL, &rx_amount);
+
+  ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_LSR, &status);
+  if (((status & LSR_RXRDY) != 0) && ((status & LSR_ERROR_BITS) == 0)) {
+    ctx->read_reg(ctx->fd, ctx->reg_ctx, SC16IS752_RHR, &rhr);
+    return (char) rhr;
+  } else {
+    return -1;
+  }
+}
+#endif
+
+static const rtems_termios_device_handler sc16is752_uart_handler = {
+  .first_open = sc16is752_uart_first_open,
+  .last_close = sc16is752_uart_last_close,
+  .write = sc16is752_uart_write,
+  .set_attributes = sc16is752_uart_set_attributes,
+#ifdef SC16IS752_USE_INTERRUPTS
+  .mode = TERMIOS_IRQ_DRIVEN
+#else
+  .poll_read = sc16is752_uart_read,
+  .mode = TERMIOS_POLLED
+#endif
+};
+
+rtems_status_code sc16is752_initialize(
+  sc16is752_uart_ctx *uart_ctx,
+  sc16is752_reg_ctx *reg_ctx,
+  uint32_t input_frequency,
+  rtems_vector_number irq,
+  bool rs485_wanted,
+  void *arg
+)
+{
+  (void)arg;
+
+  rtems_termios_initialize();
+
+  uart_ctx->reg_ctx = reg_ctx;
+  uart_ctx->write_reg = sc16is752_write_register;
+  uart_ctx->read_reg = sc16is752_read_register;
+  uart_ctx->input_frequency = input_frequency;
+  uart_ctx->irq = irq;
+
+  char uart_sc16is752[] = "/dev/ttyUARTSC16IS752";
+
+  rtems_termios_device_install(
+    &uart_sc16is752[0],
+    &sc16is752_uart_handler,
+    NULL,
+    &uart_ctx->base
+  );
+
+  uart_ctx->rs485_wanted = rs485_wanted;
+
+  return RTEMS_SUCCESSFUL;
+}
-- 
1.8.4.5



More information about the devel mailing list