ARM: s3c24xx: Multiple serial port support
authorHarald Welte <laforge@openmoko.org>
Wed, 19 Dec 2007 13:24:40 +0000 (14:24 +0100)
committerWolfgang Denk <wd@denx.de>
Mon, 4 Feb 2008 22:52:49 +0000 (23:52 +0100)
This patch adds support for CONFIG_SERIAL_MULTI on s3c24x0 CPU's

Signed-off-by: Harald Welte <laforge@openmoko.org>
common/serial.c
cpu/arm920t/s3c24x0/serial.c
include/serial.h

index 56010807be599a529537d0a8df508140e9989561..bfda7ca55135c96e01bcd8bf7ded3af5a846c5e5 100644 (file)
@@ -60,6 +60,16 @@ struct serial_device *__default_serial_console (void)
 #else
                return &serial0_device;
 #endif
+#elif defined(CONFIG_S3C2410)
+#if defined(CONFIG_SERIAL1)
+       return &s3c24xx_serial0_device;
+#elif defined(CONFIG_SERIAL2)
+       return &s3c24xx_serial1_device;
+#elif defined(CONFIG_SERIAL3)
+       return &s3c24xx_serial2_device;
+#else
+#error "CONFIG_SERIAL? missing."
+#endif
 #else
 #error No default console
 #endif
@@ -122,6 +132,11 @@ void serial_initialize (void)
 #endif
 #if defined (CONFIG_STUART)
        serial_register(&serial_stuart_device);
+#endif
+#if defined(CONFIG_S3C2410)
+       serial_register(&s3c24xx_serial0_device);
+       serial_register(&s3c24xx_serial1_device);
+       serial_register(&s3c24xx_serial2_device);
 #endif
        serial_assign (default_serial_console ()->name);
 }
index 36851ad5ca86dcb95833ceb509b24d56bfebc4e5..6e853b87acc8f8c1b9465b013610dd97cb7fe420 100644 (file)
@@ -48,18 +48,74 @@ DECLARE_GLOBAL_DATA_PTR;
 #error "Bad: you didn't configure serial ..."
 #endif
 
-void serial_setbrg (void)
+#if defined(CONFIG_SERIAL_MULTI)
+#include <serial.h>
+
+/* Multi serial device functions */
+#define DECLARE_S3C_SERIAL_FUNCTIONS(port) \
+    int  s3serial##port##_init (void) {\
+       return serial_init_dev(port);}\
+    void s3serial##port##_setbrg (void) {\
+       serial_setbrg_dev(port);}\
+    int  s3serial##port##_getc (void) {\
+       return serial_getc_dev(port);}\
+    int  s3serial##port##_tstc (void) {\
+       return serial_tstc_dev(port);}\
+    void s3serial##port##_putc (const char c) {\
+       serial_putc_dev(port, c);}\
+    void s3serial##port##_puts (const char *s) {\
+       serial_puts_dev(port, s);}
+
+#define INIT_S3C_SERIAL_STRUCTURE(port,name,bus) {\
+       name,\
+       bus,\
+       s3serial##port##_init,\
+       s3serial##port##_setbrg,\
+       s3serial##port##_getc,\
+       s3serial##port##_tstc,\
+       s3serial##port##_putc,\
+       s3serial##port##_puts, }
+
+#endif /* CONFIG_SERIAL_MULTI */
+
+void _serial_setbrg(const int dev_index)
 {
-       S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
-       int i;
+       S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index);
        unsigned int reg = 0;
+       int i;
 
        /* value is calculated so : (int)(PCLK/16./baudrate) -1 */
        reg = get_PCLK() / (16 * gd->baudrate) - 1;
 
+       uart->UBRDIV = reg;
+       for (i = 0; i < 100; i++);
+}
+#if defined(CONFIG_SERIAL_MULTI)
+static inline void
+serial_setbrg_dev(unsigned int dev_index)
+{
+       _serial_setbrg(dev_index);
+}
+#else
+void serial_setbrg(void)
+{
+       _serial_setbrg(UART_NR);
+}
+#endif
+
+
+/* Initialise the serial port. The settings are always 8 data bits, no parity,
+ * 1 stop bit, no start bits.
+ */
+static int serial_init_dev(const int dev_index)
+{
+       S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index);
+       int i;
+
        /* FIFO enable, Tx/Rx FIFO clear */
        uart->UFCON = 0x07;
        uart->UMCON = 0x0;
+
        /* Normal,No parity,1 stop,8 bit */
        uart->ULCON = 0x3;
        /*
@@ -67,40 +123,57 @@ void serial_setbrg (void)
         * normal,interrupt or polling
         */
        uart->UCON = 0x245;
-       uart->UBRDIV = reg;
 
 #ifdef CONFIG_HWFLOW
        uart->UMCON = 0x1; /* RTS up */
 #endif
-       for (i = 0; i < 100; i++);
+
+       /* FIXME: This is sooooooooooooooooooo ugly */
+#if defined(CONFIG_ARCH_GTA02_v1) || defined(CONFIG_ARCH_GTA02_v2)
+       /* we need auto hw flow control on the gsm and gps port */
+       if (dev_index == 0 || dev_index == 1)
+               uart->UMCON = 0x10;
+#endif
+       _serial_setbrg(dev_index);
+
+       return (0);
 }
 
-/*
- * Initialise the serial port with the given baudrate. The settings
- * are always 8 data bits, no parity, 1 stop bit, no start bits.
- *
+#if !defined(CONFIG_SERIAL_MULTI)
+/* Initialise the serial port. The settings are always 8 data bits, no parity,
+ * 1 stop bit, no start bits.
  */
 int serial_init (void)
 {
-       serial_setbrg ();
-
-       return (0);
+       return serial_init_dev(UART_NR);
 }
+#endif
 
 /*
  * Read a single byte from the serial port. Returns 1 on success, 0
  * otherwise. When the function is succesfull, the character read is
  * written into its argument c.
  */
-int serial_getc (void)
+int _serial_getc (const int dev_index)
 {
-       S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+       S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index);
 
        /* wait for character to arrive */
        while (!(uart->UTRSTAT & 0x1));
 
        return uart->URXH & 0xff;
 }
+#if defined(CONFIG_SERIAL_MULTI)
+static inline int serial_getc_dev(unsigned int dev_index)
+{
+       return _serial_getc(dev_index);
+}
+#else
+int serial_getc (void)
+{
+       return _serial_getc(UART_NR);
+}
+#endif
 
 #ifdef CONFIG_HWFLOW
 static int hwflow = 0; /* turned off by default */
@@ -138,9 +211,9 @@ void enable_putc(void)
 /*
  * Output a single byte to the serial port.
  */
-void serial_putc (const char c)
+void _serial_putc (const char c, const int dev_index)
 {
-       S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+       S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index);
 #ifdef CONFIG_MODEM_SUPPORT
        if (be_quiet)
                return;
@@ -161,23 +234,72 @@ void serial_putc (const char c)
        if (c == '\n')
                serial_putc ('\r');
 }
+#if defined(CONFIG_SERIAL_MULTI)
+static inline void serial_putc_dev(unsigned int dev_index, const char c)
+{
+       _serial_putc(c, dev_index);
+}
+#else
+void serial_putc(const char c)
+{
+       _serial_putc(c, UART_NR);
+}
+#endif
+
 
 /*
  * Test whether a character is in the RX buffer
  */
-int serial_tstc (void)
+int _serial_tstc(const int dev_index)
 {
-       S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+       S3C24X0_UART * const uart = S3C24X0_GetBase_UART(dev_index);
 
        return uart->UTRSTAT & 0x1;
 }
+#if defined(CONFIG_SERIAL_MULTI)
+static inline int
+serial_tstc_dev(unsigned int dev_index)
+{
+       return _serial_tstc(dev_index);
+}
+#else
+int serial_tstc(void)
+{
+       return _serial_tstc(UART_NR);
+}
+#endif
 
-void
-serial_puts (const char *s)
+void _serial_puts(const char *s, const int dev_index)
 {
        while (*s) {
-               serial_putc (*s++);
+               _serial_putc (*s++, dev_index);
        }
 }
+#if defined(CONFIG_SERIAL_MULTI)
+static inline void
+serial_puts_dev(int dev_index, const char *s)
+{
+       _serial_puts(s, dev_index);
+}
+#else
+void
+serial_puts (const char *s)
+{
+       _serial_puts(s, UART_NR);
+}
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+DECLARE_S3C_SERIAL_FUNCTIONS(0);
+struct serial_device s3c24xx_serial0_device =
+       INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0", "S3UART1");
+DECLARE_S3C_SERIAL_FUNCTIONS(1);
+struct serial_device s3c24xx_serial1_device =
+       INIT_S3C_SERIAL_STRUCTURE(1, "s3ser1", "S3UART2");
+DECLARE_S3C_SERIAL_FUNCTIONS(2);
+struct serial_device s3c24xx_serial2_device =
+       INIT_S3C_SERIAL_STRUCTURE(2, "s3ser2", "S3UART3");
+
+#endif /* CONFIG_SERIAL_MULTI */
 
 #endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */
index e292f0cd9010c7590bb10dea5258364ccc055215..2b99e539c1491500be8cd103f59f2889253de8f8 100644 (file)
@@ -36,6 +36,11 @@ extern struct serial_device eserial4_device;
 
 #endif
 
+#if defined(CONFIG_S3C2410)
+extern struct serial_device s3c24xx_serial0_device;
+extern struct serial_device s3c24xx_serial1_device;
+extern struct serial_device s3c24xx_serial2_device;
+#endif
 
 extern struct serial_device serial_ffuart_device;
 extern struct serial_device serial_btuart_device;