changeset 1640:b958d883e5f5

New package whch implements generic support for the serial port on the arm s3c4510
author asl
date Fri, 14 May 2004 14:53:37 +0000
parents 73b71f156116
children 23c0a1c0b988
files packages/devs/serial/arm/s3c4510/current/ChangeLog packages/devs/serial/arm/s3c4510/current/cdl/ser_arm_s3c4510.cdl packages/devs/serial/arm/s3c4510/current/src/s3c4510_serial.c packages/devs/serial/arm/s3c4510/current/src/s3c4510_serial.h
diffstat 4 files changed, 655 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/devs/serial/arm/s3c4510/current/ChangeLog
@@ -0,0 +1,49 @@
+2004-02-11  Roland Caßebohm  <roland.cassebohm@visionsystem.de>
+
+        * src/s3c4510_serial.c: The UART doesn't generate an interrupt
+	  before the first time a character was send. Changed
+	  s3c4510_serial_start_xmit() to first try to send characters.
+
+2003-02-24  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* cdl/ser_arm_s3c4510.cdl: Remove irrelevant doc link.
+
+2001-10-19  Lars Lindqvist  <Lars.Lindqvist@combitechsystems.com>
+2001-10-19  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* New package.
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
new file mode 100644
--- /dev/null
+++ b/packages/devs/serial/arm/s3c4510/current/cdl/ser_arm_s3c4510.cdl
@@ -0,0 +1,113 @@
+# ====================================================================
+#
+#      ser_arm_s3c4510.cdl
+#
+#      eCos serial ARM/S3C4510 configuration data
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Lars.Lindqvist@combitechsystems.com
+# Contributors:   jlarmour
+# Date:           2001-10-19
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+
+cdl_package CYGPKG_IO_SERIAL_ARM_S3C4510 {
+    display       "ARM S3C4510 serial device drivers"
+
+    parent        CYGPKG_IO_SERIAL_DEVICES
+    active_if     CYGPKG_IO_SERIAL
+
+    active_if     CYGINT_IO_SERIAL_ARM_S3C4510_REQUIRED
+
+    requires      CYGPKG_ERROR
+    include_dir   cyg/io
+    include_files ; # none _exported_ whatsoever
+    description   "
+           This package contains serial device drivers for the
+           ARM S3C4510."
+
+    compile       -library=libextras.a   s3c4510_serial.c
+
+    define_proc {
+        puts $::cdl_system_header "/***** serial driver proc output start *****/"
+        puts $::cdl_system_header "#ifndef CYGDAT_IO_SERIAL_DEVICE_HEADER"
+        puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_DEVICE_HEADER <pkgconf/io_serial_arm_s3c4510.h>"
+        puts $::cdl_system_header "#endif"
+        puts $::cdl_system_header "/*****  serial driver proc output end  *****/"
+        puts $::cdl_header "#include <pkgconf/system.h>";
+        puts $::cdl_header "#include CYGDAT_IO_SERIAL_ARM_S3C4510_CFG";
+    }
+
+    cdl_component CYGPKG_IO_SERIAL_ARM_S3C4510_OPTIONS {
+        display "Serial device driver build options"
+        flavor  none
+        description   "
+	    Package specific build options including control over
+	    compiler flags used only in building this package,
+	    and details of which tests are built."
+
+
+        cdl_option CYGPKG_IO_SERIAL_ARM_S3C4510_CFLAGS_ADD {
+            display "Additional compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building these serial device drivers. These flags are used in addition
+                to the set of global flags."
+        }
+
+        cdl_option CYGPKG_IO_SERIAL_ARM_S3C4510_CFLAGS_REMOVE {
+            display "Suppressed compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building these serial device drivers. These flags are removed from
+                the set of global flags if present."
+        }
+    }
+
+}
+
+# EOF ser_arm_s3c4510.cdl
new file mode 100644
--- /dev/null
+++ b/packages/devs/serial/arm/s3c4510/current/src/s3c4510_serial.c
@@ -0,0 +1,297 @@
+//==========================================================================
+//
+//      io/serial/arm/s3c4510_serial.c
+//
+//      ARM S3C4510 Serial I/O Interface Module (interrupt driven)
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+// ====================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Lars.Lindqvist@combitechsystems.com
+// Contributors: jlarmour
+// Date:         2001-10-19
+// Purpose:      ARM S3C4510 Serial I/O Interface Module (interrupt driven)
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+// ====================================================================
+
+#include <pkgconf/system.h>
+#include <pkgconf/io_serial.h>
+#include <pkgconf/io.h>
+#include <cyg/io/io.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/io/devtab.h>
+#include <cyg/io/serial.h>
+#include <cyg/io/serialio.h>
+#include <cyg/infra/diag.h>
+
+#if defined(CYGPKG_IO_SERIAL_ARM_S3C4510) && defined(CYGDAT_IO_SERIAL_ARM_S3C4510_INL)
+
+typedef struct s3c4510_serial_info {
+    CYG_ADDRWORD   base;
+    CYG_WORD       tx_int_num;
+    CYG_WORD       rx_int_num;
+    cyg_interrupt  serial_tx_interrupt;
+    cyg_interrupt  serial_rx_interrupt;
+    cyg_handle_t   serial_tx_interrupt_handle;
+    cyg_handle_t   serial_rx_interrupt_handle;
+    bool           tx_enabled;
+} s3c4510_serial_info;
+
+static bool s3c4510_serial_init(struct cyg_devtab_entry *tab);
+static bool s3c4510_serial_putc(serial_channel *chan, unsigned char c);
+static Cyg_ErrNo s3c4510_serial_lookup(struct cyg_devtab_entry **tab, 
+                                   struct cyg_devtab_entry *sub_tab,
+                                   const char *name);
+static unsigned char s3c4510_serial_getc(serial_channel *chan);
+static Cyg_ErrNo s3c4510_serial_set_config(serial_channel *chan, 
+                                       cyg_uint32 key,
+                                       const void *xbuf, cyg_uint32 *len);
+static void s3c4510_serial_start_xmit(serial_channel *chan);
+static void s3c4510_serial_stop_xmit(serial_channel *chan);
+
+static cyg_uint32 s3c4510_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data);
+static void       s3c4510_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
+static cyg_uint32 s3c4510_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data);
+static void       s3c4510_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
+
+static SERIAL_FUNS(s3c4510_serial_funs, 
+                   s3c4510_serial_putc, 
+                   s3c4510_serial_getc,
+                   s3c4510_serial_set_config,
+                   s3c4510_serial_start_xmit,
+                   s3c4510_serial_stop_xmit
+    );
+
+#include CYGDAT_IO_SERIAL_ARM_S3C4510_INL
+
+#include "s3c4510_serial.h"
+
+// Internal function to actually configure the hardware to desired baud rate, etc.
+static bool
+s3c4510_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init)
+{
+  s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+  volatile struct serial_port *port = (volatile struct serial_port *)s3c4510_chan->base;
+  cyg_uint32 word_length = select_word_length[(new_config->word_length)-CYGNUM_SERIAL_WORD_LENGTH_5];
+  cyg_uint32 stop_bits = select_stop_bits[(new_config->stop)-CYGNUM_SERIAL_STOP_1];
+  cyg_uint32 parity_mode = select_parity[(new_config->parity)-CYGNUM_SERIAL_PARITY_NONE];
+  cyg_uint32 baud_divisor = select_baud[(new_config->baud)-CYGNUM_SERIAL_BAUD_50];
+  cyg_uint32 res = word_length | stop_bits | parity_mode | ULCON_SCI | ULCON_IROFF;
+  if ((word_length|stop_bits|parity_mode|baud_divisor) == U_NOT_SUPP) {
+    return false;
+  };
+  port->REG_ULCON = res;
+  port->REG_UCON = UCON_RXMINT | UCON_RXSIOFF | UCON_TXMINT | UCON_DSROFF | UCON_SBKOFF | UCON_LPBOFF;
+  port->REG_UBRDIV = baud_divisor;
+  if (new_config != &chan->config) {
+    chan->config = *new_config;
+  };
+  return true;
+}
+
+// Function to initialize the device.  Called at bootstrap time.
+static bool 
+s3c4510_serial_init(struct cyg_devtab_entry *tab)
+{
+    serial_channel *chan = (serial_channel *)tab->priv;
+    s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+#ifdef CYGDBG_IO_INIT
+    diag_printf("S3C4510 SERIAL init - dev: %x.%d.%d\n", s3c4510_chan->base, s3c4510_chan->tx_int_num, s3c4510_chan->rx_int_num);
+#endif
+    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
+    if (chan->out_cbuf.len != 0) {         // If bufferlength > 0 then interrupts are used for tx
+        cyg_drv_interrupt_create(s3c4510_chan->tx_int_num,
+                                 99,                     // Priority - unused
+                                 (cyg_addrword_t)chan,   //  Data item passed to interrupt handler
+                                 s3c4510_serial_tx_ISR,
+                                 s3c4510_serial_tx_DSR,
+                                 &s3c4510_chan->serial_tx_interrupt_handle,
+                                 &s3c4510_chan->serial_tx_interrupt);
+        cyg_drv_interrupt_attach(s3c4510_chan->serial_tx_interrupt_handle);
+        cyg_drv_interrupt_mask(s3c4510_chan->tx_int_num);
+        s3c4510_chan->tx_enabled = false;
+    }
+    if (chan->in_cbuf.len != 0) {         // If bufferlength > 0 then interrupts are used for rx
+        cyg_drv_interrupt_create(s3c4510_chan->rx_int_num,
+                                 99,                     // Priority - unused
+                                 (cyg_addrword_t)chan,   //  Data item passed to interrupt handler
+                                 s3c4510_serial_rx_ISR,
+                                 s3c4510_serial_rx_DSR,
+                                 &s3c4510_chan->serial_rx_interrupt_handle,
+                                 &s3c4510_chan->serial_rx_interrupt);
+        cyg_drv_interrupt_attach(s3c4510_chan->serial_rx_interrupt_handle);
+        cyg_drv_interrupt_unmask(s3c4510_chan->rx_int_num);
+    }
+    s3c4510_serial_config_port(chan, &chan->config, true);
+    return true;
+}
+
+// This routine is called when the device is "looked" up (i.e. attached)
+static Cyg_ErrNo 
+s3c4510_serial_lookup(struct cyg_devtab_entry **tab, 
+                  struct cyg_devtab_entry *sub_tab,
+                  const char *name)
+{
+    serial_channel *chan = (serial_channel *)(*tab)->priv;
+    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
+    return ENOERR;
+}
+
+// Send a character to the device output buffer.
+// Return 'true' if character is sent to device
+static bool
+s3c4510_serial_putc(serial_channel *chan, unsigned char c)
+{
+    s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+    volatile struct serial_port *port = (volatile struct serial_port *)s3c4510_chan->base;
+
+    if (port->REG_USTAT & USTAT_TBE) {
+      // Transmit buffer is empty
+      port->REG_UTXBUF = c;
+      return true;
+    } else {
+      // No space
+      return false;
+    }
+}
+
+// Fetch a character from the device input buffer, waiting if necessary
+static unsigned char 
+s3c4510_serial_getc(serial_channel *chan)
+{
+    unsigned char c;
+    s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+    volatile struct serial_port *port = (volatile struct serial_port *)s3c4510_chan->base;
+    while ((port->REG_USTAT & USTAT_RDR) == 0) ;   // Wait for char
+    c = port->REG_URXBUF;
+    return c;
+}
+
+// Set up the device characteristics; baud rate, etc.
+static Cyg_ErrNo
+s3c4510_serial_set_config(serial_channel *chan, cyg_uint32 key,
+                      const void *xbuf, cyg_uint32 *len)
+{
+    switch (key) {
+    case CYG_IO_SET_CONFIG_SERIAL_INFO:
+      {
+        cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
+        if ( *len < sizeof(cyg_serial_info_t) ) {
+            return -EINVAL;
+        }
+        *len = sizeof(cyg_serial_info_t);
+        if ( true != s3c4510_serial_config_port(chan, config, false) )
+            return -EINVAL;
+      }
+      break;
+    default:
+        return -EINVAL;
+    }
+    return ENOERR;
+}
+
+// Enable the transmitter on the device
+static void
+s3c4510_serial_start_xmit(serial_channel *chan)
+{
+    s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+    s3c4510_chan->tx_enabled = true;
+    (chan->callbacks->xmt_char)(chan);
+    if (s3c4510_chan->tx_enabled) {
+        cyg_drv_interrupt_unmask(s3c4510_chan->tx_int_num);
+    }
+}
+
+// Disable the transmitter on the device
+static void 
+s3c4510_serial_stop_xmit(serial_channel *chan)
+{
+    s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+    cyg_drv_interrupt_mask(s3c4510_chan->tx_int_num);
+    s3c4510_chan->tx_enabled = false;
+}
+
+// Serial I/O - low level tx interrupt handler (ISR)
+static cyg_uint32 
+s3c4510_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+    serial_channel *chan = (serial_channel *)data;
+    s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+    cyg_drv_interrupt_mask(s3c4510_chan->tx_int_num);
+    cyg_drv_interrupt_acknowledge(s3c4510_chan->tx_int_num);
+    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
+}
+
+// Serial I/O - high level tx interrupt handler (DSR)
+static void       
+s3c4510_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    serial_channel *chan = (serial_channel *)data;
+    s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+    (chan->callbacks->xmt_char)(chan);
+    if (s3c4510_chan->tx_enabled) {
+        cyg_drv_interrupt_unmask(s3c4510_chan->tx_int_num);
+    }
+}
+
+// Serial I/O - low level rx interrupt handler (ISR)
+static cyg_uint32 
+s3c4510_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+    serial_channel *chan = (serial_channel *)data;
+    s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+    cyg_drv_interrupt_mask(s3c4510_chan->rx_int_num);
+    cyg_drv_interrupt_acknowledge(s3c4510_chan->rx_int_num);
+    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
+}
+
+// Serial I/O - high level rx interrupt handler (DSR)
+static void       
+s3c4510_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    serial_channel *chan = (serial_channel *)data;
+    s3c4510_serial_info *s3c4510_chan = (s3c4510_serial_info *)chan->dev_priv;
+    volatile struct serial_port *port = (volatile struct serial_port *)s3c4510_chan->base;
+    (chan->callbacks->rcv_char)(chan, port->REG_URXBUF);
+    cyg_drv_interrupt_unmask(s3c4510_chan->rx_int_num);
+}
+
+#endif // CYGPKG_IO_SERIAL_ARM_S3C4510 && CYGDAT_IO_SERIAL_ARM_S3C4510_INL
+
+// EOF s3c4510_serial.c
new file mode 100644
--- /dev/null
+++ b/packages/devs/serial/arm/s3c4510/current/src/s3c4510_serial.h
@@ -0,0 +1,196 @@
+#ifndef CYGONCE_ARM_S3C4510_SERIAL_H
+#define CYGONCE_ARM_S3C4510_SERIAL_H
+// ====================================================================
+//
+//      s3c4510_serial.h
+//
+//      Device I/O - Description of ARM S3C4510 serial hardware
+//
+// ====================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+// ====================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Lars.Lindqvist@combitechsystems.com
+// Contributors: jlarmour
+// Date:         2001-10-19
+// Purpose:      Internal interfaces for serial I/O drivers
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+// ====================================================================
+
+#include <pkgconf/hal.h>        // Value CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED needed
+#include <cyg/infra/cyg_type.h> // base types
+
+// Description of serial ports on ARM S3C4510
+
+struct serial_port {
+    cyg_uint32 _reg[8];
+};
+
+#define REG(n) _reg[n]
+
+// Misc values
+#define U_NOT_SUPP    (0xFFFFFFFF)  // Used to indicate unsupported parameter values
+
+// Registers
+#define REG_ULCON  REG(0)    // Line control registers
+#define REG_UCON   REG(1)    // Control registers
+#define REG_USTAT  REG(2)    // Status registers
+#define REG_UTXBUF REG(3)    // Transmit buffer registers
+#define REG_URXBUF REG(4)    // Receive buffer registers
+#define REG_UBRDIV REG(5)    // Baud rate divisor registers
+
+// Line Control Register Values
+#define ULCON_WL5     (0x00000000 << 0)  // Word length 5
+#define ULCON_WL6     (0x00000001 << 0)  // Word length 6
+#define ULCON_WL7     (0x00000002 << 0)  // Word length 7
+#define ULCON_WL8     (0x00000003 << 0)  // Word length 8
+#define ULCON_STB1    (0x00000000 << 2)  // One stop bit
+#define ULCON_STB2    (0x00000001 << 2)  // Two stop bits
+#define ULCON_PMDOFF  (0x00000000 << 3)  // No parity
+#define ULCON_PMDODD  (0x00000004 << 3)  // Odd parity
+#define ULCON_PMDEVEN (0x00000005 << 3)  // Even parity
+#define ULCON_PMDFC1  (0x00000006 << 3)  // Parity forced/checked as 1
+#define ULCON_PMDFC0  (0x00000007 << 3)  // Parity forced/checked as 0
+#define ULCON_SCI     (0x00000000 << 6)  // Internal clock
+#define ULCON_SCE     (0x00000001 << 6)  // External clock
+#define ULCON_IROFF   (0x00000000 << 7)  // Normal mode
+#define ULCON_IRON    (0x00000001 << 7)  // IR mode
+
+// Control Register Values
+#define UCON_RXMOFF   (0x00000000 << 0)  // Disable Rx mode
+#define UCON_RXMINT   (0x00000001 << 0)  // Interrupt request Rx mode
+#define UCON_RXMDMA0  (0x00000002 << 0)  // GDMA channel 0 request Rx mode
+#define UCON_RXMDMA1  (0x00000003 << 0)  // GDMA channel 1 request Rx mode
+#define UCON_RXSIOFF  (0x00000000 << 2)  // Rx status interrupt disabled
+#define UCON_RXSION   (0x00000001 << 2)  // Rx status interrupt enabled
+#define UCON_TXMOFF   (0x00000000 << 3)  // Disable Tx mode
+#define UCON_TXMINT   (0x00000001 << 3)  // Interrupt request Tx mode
+#define UCON_TXMDMA0  (0x00000002 << 3)  // GDMA channel 0 request Tx mode
+#define UCON_TXMDMA1  (0x00000003 << 3)  // GDMA channel 1 request Tx mode
+#define UCON_DSROFF   (0x00000000 << 5)  // Data set ready output off
+#define UCON_DSRON    (0x00000001 << 5)  // Data set ready output on
+#define UCON_SBKOFF   (0x00000000 << 6)  // No break sent
+#define UCON_SBKON    (0x00000001 << 6)  // Break sent
+#define UCON_LPBOFF   (0x00000000 << 7)  // Loop back mode off// Baud rate divisor registers
+#define UCON_LPBON    (0x00000001 << 7)  // Loop back mode on^M
+
+// Status Register Values
+#define USTAT_OV      (0x00000001 << 0)  // Overrun error
+#define USTAT_PE      (0x00000001 << 1)  // Parity error
+#define USTAT_FE      (0x00000001 << 2)  // Frame error
+
+#define USTAT_BKD     (0x00000001 << 3)  // Break detect
+#define USTAT_DTR     (0x00000001 << 4)  // Data terminal ready
+#define USTAT_RDR     (0x00000001 << 5)  // Receive data ready
+#define USTAT_TBE     (0x00000001 << 6)  // Transmit buffer register empty
+#define USTAT_TC      (0x00000001 << 7)  // Transmit complete
+
+// Baud rate divisor registers
+#define UBRDIV_50     ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/16/16/50)-1)<<4)|1)
+#define UBRDIV_75     ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/16/16/75)-1)<<4)|1)
+#define UBRDIV_110    ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/16/16/110)-1)<<4)|1)
+#define UBRDIV_134_5  ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/16/8/269)-1)<<4)|1)
+#define UBRDIV_150    ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/16/16/150)-1)<<4)|1)
+#define UBRDIV_200    ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/16/16/200)-1)<<4)|1)
+#define UBRDIV_300    ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/16/16/300)-1)<<4)|1)
+#define UBRDIV_600    ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/600)-1)<<4)|0)
+#define UBRDIV_1200   ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/1200)-1)<<4)|0)
+#define UBRDIV_1800   ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/1800)-1)<<4)|0)
+#define UBRDIV_2400   ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/2400)-1)<<4)|0)
+#define UBRDIV_3600   ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/3600)-1)<<4)|0)
+#define UBRDIV_4800   ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/4800)-1)<<4)|0)
+#define UBRDIV_7200   ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/7200)-1)<<4)|0)
+#define UBRDIV_9600   ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/9600)-1)<<4)|0)
+#define UBRDIV_14400  ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/14400)-1)<<4)|0)
+#define UBRDIV_19200  ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/19200)-1)<<4)|0)
+#define UBRDIV_38400  ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/38400)-1)<<4)|0)
+#define UBRDIV_57600  ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/57600)-1)<<4)|0)
+#define UBRDIV_115200 ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/115200)-1)<<4)|0)
+#define UBRDIV_230400 ((((CYGNUM_HAL_ARM_S3C4510_CLOCK_SPEED/2/1/16/230400)-1)<<4)|0)
+
+// Arrays used for conversion of eCos serial driver
+// configuration parameters to parameters for S3C4510
+
+static cyg_uint32 select_word_length[] = {
+    ULCON_WL5,    // 5 bits / word (char)
+    ULCON_WL6,
+    ULCON_WL7,
+    ULCON_WL8
+};
+
+static cyg_uint32 select_stop_bits[] = {
+    ULCON_STB1,    // 1 stop bit
+    U_NOT_SUPP,    // 1.5 stop bit not supported
+    ULCON_STB2     // 2 stop bits
+};
+
+static cyg_uint32 select_parity[] = {
+    ULCON_PMDOFF,     // No parity
+    ULCON_PMDEVEN,    // Even parity
+    ULCON_PMDODD,     // Odd parity
+    ULCON_PMDFC1,     // Mark parity
+    ULCON_PMDFC0,     // Space parity
+};
+
+static cyg_uint32 select_baud[] = {
+     UBRDIV_50,     // 50
+     UBRDIV_75,     // 75
+     UBRDIV_110,    // 110
+     UBRDIV_134_5,  // 134.5
+     UBRDIV_150,    // 150
+     UBRDIV_200,    // 200
+     UBRDIV_300,    // 300
+     UBRDIV_600,    // 600
+     UBRDIV_1200,   // 1200
+     UBRDIV_1800,   // 1800
+     UBRDIV_2400,   // 2400
+     UBRDIV_3600,   // 3600
+     UBRDIV_4800,   // 4800
+     UBRDIV_7200,   // 7200
+     UBRDIV_9600,   // 9600
+     UBRDIV_14400,  // 14400
+     UBRDIV_19200,  // 19200
+     UBRDIV_38400,  // 38400
+     UBRDIV_57600,  // 57600
+     UBRDIV_115200, // 115200
+     UBRDIV_230400, // 230400
+};
+
+#endif // CYGONCE_ARM_S3C4510_SERIAL_H
+
+// EOF s3c4510_serial.h