[rtems commit] PC386 Add RTD316 and Exar 17D15x multi-port serial card support
Joel Sherrill
joel at rtems.org
Thu Mar 29 20:30:44 UTC 2012
Module: rtems
Branch: master
Commit: 2cc30b0d0c83d6fa9c5a84ba8d29fb0887073a0b
Changeset: http://git.rtems.org/rtems/commit/?id=2cc30b0d0c83d6fa9c5a84ba8d29fb0887073a0b
Author: Joel Sherrill <joel.sherrill at oarcorp.com>
Date: Thu Mar 29 15:28:13 2012 -0500
PC386 Add RTD316 and Exar 17D15x multi-port serial card support
- RTD316 is a PC-104 board with one Z85C30 SCC for two synchronous
or asynchronous serial ports.
http://www.rtd.com/PC104/UM/network/CM316HR.htm
- Exar 17D15X is a chip with 2, 4, or 8 NS16550 compatible
serial ports with a PCI interface. It may be found on
many multi-port serial ports including:
http://www.rtd.com/PC104/UM/network/CM17320HR.htm
---
c/src/lib/libbsp/i386/pc386/console/exar17d15x.c | 224 ++++++++++++++++++++++
c/src/lib/libbsp/i386/pc386/console/exar17d15x.h | 54 +++++
c/src/lib/libbsp/i386/pc386/console/rtd316.c | 108 +++++++++++
c/src/lib/libbsp/i386/pc386/console/rtd316.h | 56 ++++++
4 files changed, 442 insertions(+), 0 deletions(-)
diff --git a/c/src/lib/libbsp/i386/pc386/console/exar17d15x.c b/c/src/lib/libbsp/i386/pc386/console/exar17d15x.c
new file mode 100644
index 0000000..95ba3c1
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/console/exar17d15x.c
@@ -0,0 +1,224 @@
+/**
+ * @file
+ *
+ * @brief Driver for Exar XR17D15x Multiport UARTs
+ *
+ * This driver supports 2, 4 or 8 port Exar parts which are NS16550
+ * compatible.
+ */
+
+/*
+ * 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.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <termios.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems/termiostypes.h>
+#include <libchip/serial.h>
+#include <libchip/ns16550.h>
+#include <rtems/bspIo.h>
+#include <rtems/pci.h>
+#include <bsp/exar17d15x.h>
+#include "../../../shared/console_private.h"
+
+#define MAX_BOARDS 4
+
+/*
+ * This is the rate for the clock internal to the parts.
+ */
+#define EXAR_CLOCK_RATE (921600*16)
+
+/*
+ * Supported PCI Ids
+ */
+#define PCI_VENDOR_ID_EXAR 0x13A8
+#define PCI_VENDOR_ID_EXAR_XR17D158 0x0158
+#define PCI_VENDOR_ID_EXAR_XR17D154 0x0154
+#define PCI_VENDOR_ID_EXAR_XR17D152 0x0152
+
+/*
+ * Structure to manage each instance found.
+ */
+typedef struct {
+ uint16_t vendor;
+ uint16_t device;
+ uint8_t ports;
+} exar_parts_t;
+
+static exar_parts_t Supported[] = {
+ { PCI_VENDOR_ID_EXAR, PCI_VENDOR_ID_EXAR_XR17D158, 8 },
+ { PCI_VENDOR_ID_EXAR, PCI_VENDOR_ID_EXAR_XR17D154, 4 },
+ { PCI_VENDOR_ID_EXAR, PCI_VENDOR_ID_EXAR_XR17D152, 2 },
+ { 0, 0, 0 }
+};
+
+/*
+ * Information saved from PCI scan
+ */
+typedef struct {
+ bool found;
+ uint32_t base;
+ uint8_t irq;
+ uint8_t bus;
+ uint8_t slot;
+ uint8_t ports;
+} exar17d15x_conf_t;
+
+/*
+ * Register Access Routines
+ */
+static uint8_t xr17d15x_get_register(uint32_t addr, uint8_t i)
+{
+ uint8_t val = 0;
+ volatile uint8_t *reg = (volatile uint8_t *)(addr + i);
+
+ val = *reg;
+ // printk( "RD %p -> 0x%02x\n", reg, val );
+ return val;
+}
+
+static void xr17d15x_set_register(uint32_t addr, uint8_t i, uint8_t val)
+{
+ volatile uint8_t *reg = (volatile uint8_t *)(addr + i);
+
+ // printk( "WR %p <- 0x%02x\n", reg, val );
+ *reg = val;
+}
+
+rtems_device_driver exar17d15x_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor_arg,
+ void *arg
+)
+{
+ // int pbus, pdev, pfun;
+ exar17d15x_conf_t conf[MAX_BOARDS];
+ int boards = 0;
+ int b = 0;
+ int p;
+ console_tbl *ports;
+ console_tbl *port_p;
+ int pbus;
+ int pdev;
+ int pfun;
+ int status;
+ int instance;
+ int i;
+ int total_ports = 0;
+
+ for ( b=0 ; b<MAX_BOARDS ; b++ ) {
+ conf[b].found = false;
+ }
+
+ /*
+ * Scan for Serial port boards
+ *
+ * NOTE: There appear to be Exar parts with 2 and 4 ports which would
+ * be easy to support. Just change the hard-coded 8 ports per
+ * board to variable and adjust.
+ *
+ * NOTE: There are likely other board vendors which could be supported
+ * by this.
+ */
+ for ( instance=0 ; instance < MAX_BOARDS ; instance++ ) {
+
+ for ( i=0 ; Supported[i].ports != 0 ; i++ ) {
+ status = pci_find_device(
+ Supported[i].vendor,
+ Supported[i].device,
+ instance,
+ &pbus,
+ &pdev,
+ &pfun
+ );
+ if ( status == PCIB_ERR_SUCCESS ) {
+ boards++;
+ conf[instance].found = true;
+ conf[instance].ports = Supported[i].ports;
+ total_ports += conf[instance].ports;
+ break;
+ }
+ }
+
+ if ( status != PCIB_ERR_SUCCESS )
+ continue;
+
+ pci_read_config_byte(
+ pbus,
+ pdev,
+ pfun,
+ PCI_INTERRUPT_LINE,
+ &conf[instance].irq
+ );
+ pci_read_config_dword(
+ pbus,
+ pdev,
+ pfun,
+ PCI_BASE_ADDRESS_0,
+ &conf[instance].base
+ );
+ printk(
+ "Found Exar 17D15x %d at 0x%08x IRQ %d with %d ports\n",
+ instance,
+ conf[instance].base,
+ conf[instance].irq,
+ conf[instance].ports
+ );
+ }
+
+ /*
+ * Now allocate array of device structures and fill them in
+ */
+ ports = calloc( total_ports, sizeof( console_tbl ) );
+ port_p = ports;
+ for ( b=0 ; b<MAX_BOARDS ; b++ ) {
+ if ( conf[b].found == false )
+ continue;
+ for ( p=0 ; p<conf[b].ports ; p++ ) {
+ char name[32];
+
+ sprintf( name, "/dev/exar17d15x_%d_%d", b, p );
+ //printk("Found %s\n", name );
+ port_p->sDeviceName = strdup( name );
+ port_p->deviceType = SERIAL_NS16550;
+ #if 1
+ port_p->pDeviceFns = &ns16550_fns_polled;
+ #else
+ port_p->pDeviceFns = &ns16550_fns;
+ #endif
+
+ port_p->deviceProbe = NULL;
+ port_p->pDeviceFlow = NULL;
+ port_p->ulMargin = 16;
+ port_p->ulHysteresis = 8;
+ port_p->pDeviceParams = (void *) 9600;
+ port_p->ulCtrlPort1 = conf[b].base + (p * 0x0200);
+ port_p->ulCtrlPort2 = 0; /* NA */
+ port_p->ulDataPort = 0; /* NA */
+ port_p->getRegister = xr17d15x_get_register;
+ port_p->setRegister = xr17d15x_set_register;
+ port_p->getData = NULL; /* NA */
+ port_p->setData = NULL; /* NA */
+ port_p->ulClock = EXAR_CLOCK_RATE;
+ port_p->ulIntVector = conf[b].irq;
+
+ port_p++;
+ } /* end ports */
+ } /* end boards */
+
+ /*
+ * Register the devices
+ */
+ if ( boards )
+ console_register_devices( ports, total_ports );
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libbsp/i386/pc386/console/exar17d15x.h b/c/src/lib/libbsp/i386/pc386/console/exar17d15x.h
new file mode 100644
index 0000000..40922e9
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/console/exar17d15x.h
@@ -0,0 +1,54 @@
+/**
+ * @file bsp/exar17d15x.h
+ *
+ * This file provides the interface to the Exar Multiport
+ * PCI UART controller.
+ */
+
+/*
+ * 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.com/license/LICENSE.
+ */
+
+#ifndef _BSP_EXAR17D15X__h
+#define _BSP_EXAR17D15X__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This macro defines the standard device driver table entry for
+ * a console device driver.
+ */
+#define EXAR17D15X_DRIVER_TABLE_ENTRY \
+ { exar17d15x_initialize, NULL, NULL, NULL, NULL, NULL }
+
+/**
+ * @brief Exar 17D15x Initialization Entry Point
+ *
+ * This method initializes the Exar XR17D15x device driver.
+ *
+ * @param[in] major is the device driver major number
+ * @param[in] minor is the device driver minor number
+ * @param[in] arg is the parameters to this call
+ *
+ * @return This method returns RTEMS_SUCCESSFUL when
+ * the device driver is successfully initialized.
+ */
+rtems_device_driver exar17d15x_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/lib/libbsp/i386/pc386/console/rtd316.c b/c/src/lib/libbsp/i386/pc386/console/rtd316.c
new file mode 100644
index 0000000..4abffb7
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/console/rtd316.c
@@ -0,0 +1,108 @@
+/**
+ * @file
+ *
+ * @brief Driver for RTD316 ISA SCC Board
+ *
+ * The RTD316 has a single Z85C30.
+ */
+
+/*
+ * 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.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <termios.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems/termiostypes.h>
+#include <libchip/serial.h>
+#include <libchip/z85c30.h>
+#include <rtems/bspIo.h>
+#include <bsp/rtd316.h>
+#include <rtems/score/i386.h>
+
+#define RTD_CLOCK_RATE (460800 * 32)
+
+uint8_t rtd316_com_get_register(uint32_t addr, uint8_t reg)
+{
+ register uint8_t val = 0;
+
+ outport_byte( addr, reg );
+ /* It appears the no delay is needed between the accesses. */
+ inport_byte( addr, val );
+
+ return val;
+}
+
+void rtd316_com_set_register(uint32_t addr,uint8_t reg, uint8_t val)
+{
+ outport_byte( addr, reg );
+ /* It appears the no delay is needed between the accesses. */
+ outport_byte( addr, val );
+}
+
+rtems_device_driver rtd316_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor_arg,
+ void *arg
+)
+{
+ int p;
+ console_tbl *ports;
+ console_tbl *port_p;
+
+ /*
+ * Now allocate array of device structures and fill them in
+ */
+ ports = calloc( 2, sizeof( console_tbl ) );
+ port_p = ports;
+
+ for ( p=0 ; p<2 ; p++ ) {
+ char name[32];
+ sprintf( name, "/dev/rtd316_1_%d", p );
+ printk("Found %s\n", name );
+ port_p->sDeviceName = strdup( name );
+ port_p->deviceType = SERIAL_Z85C30;
+ #if 0
+ port_p->pDeviceFns = &z85c30_fns_polled;
+ #else
+ port_p->pDeviceFns = &z85c30_fns;
+ #endif
+
+ port_p->deviceProbe = NULL;
+ port_p->pDeviceFlow = NULL;
+ port_p->ulMargin = 16;
+ port_p->ulHysteresis = 8;
+ port_p->pDeviceParams = (void *) 9600;
+ port_p->getRegister = rtd316_com_get_register;
+ port_p->setRegister = rtd316_com_set_register;
+ port_p->getData = NULL;
+ port_p->setData = NULL;
+ port_p->ulClock = RTD_CLOCK_RATE;
+ port_p->ulIntVector = 9;
+
+ if ( p==0 ) {
+ port_p->ulDataPort = 0;
+ port_p->ulCtrlPort1 = 0x340;
+ port_p->ulCtrlPort2 = 0x341;
+ } else {
+ port_p->ulDataPort = 1;
+ port_p->ulCtrlPort1 = 0x342;
+ port_p->ulCtrlPort2 = 0x343;
+ }
+ port_p++;
+ } /* end ports */
+
+ /*
+ * Register the devices
+ */
+ console_register_devices( ports, 2 );
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libbsp/i386/pc386/console/rtd316.h b/c/src/lib/libbsp/i386/pc386/console/rtd316.h
new file mode 100644
index 0000000..a88d001
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/console/rtd316.h
@@ -0,0 +1,56 @@
+/**
+ * @file bsp/rtd316.h
+ *
+ * @brief RTD316 Driver Interface Definition
+ *
+ * This file provides the interface to the RTD316 Dual
+ * serial port utility module.
+ */
+
+/*
+ * 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.com/license/LICENSE.
+ */
+
+#ifndef _BSP_RTD_316_h
+#define _BSP_RTD_316_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This macro defines the standard device driver table entry for
+ * a console device driver.
+ */
+#define RTD316_DRIVER_TABLE_ENTRY \
+ { rtd316_initialize, NULL, NULL, NULL, NULL, NULL }
+
+/**
+ * @brief RTD316 Initialization Entry Point
+ *
+ * This method initializes the RTD316 device driver.
+ *
+ * @param[in] major is the device driver major number
+ * @param[in] minor is the device driver minor number
+ * @param[in] arg is the parameters to this call
+ *
+ * @return This method returns RTEMS_SUCCESSFUL when
+ * the device driver is successfully initialized.
+ */
+rtems_device_driver rtd316_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
More information about the vc
mailing list