]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/serial/serial_s5p.c
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
[karo-tx-uboot.git] / drivers / serial / serial_s5p.c
index 68b8d0101bfc7258c5f1605f9a23e88c879953b5..e65125ccd7422dda5dd5a5e11956701c0c43c2ae 100644 (file)
  */
 
 #include <common.h>
+#include <linux/compiler.h>
 #include <asm/io.h>
 #include <asm/arch/uart.h>
 #include <asm/arch/clk.h>
 #include <serial.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
+#define RX_FIFO_COUNT_MASK     0xff
+#define RX_FIFO_FULL_MASK      (1 << 8)
+#define TX_FIFO_FULL_MASK      (1 << 24)
+
 static inline struct s5p_uart *s5p_get_base_uart(int dev_index)
 {
        u32 offset = dev_index * sizeof(struct s5p_uart);
-
-       if (cpu_is_s5pc100())
-               return (struct s5p_uart *)(S5PC100_UART_BASE + offset);
-       else
-               return (struct s5p_uart *)(S5PC110_UART_BASE + offset);
+       return (struct s5p_uart *)(samsung_get_base_uart() + offset);
 }
 
 /*
@@ -65,16 +68,19 @@ static const int udivslot[] = {
 
 void serial_setbrg_dev(const int dev_index)
 {
-       DECLARE_GLOBAL_DATA_PTR;
        struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
-       u32 pclk = get_pclk();
+       u32 uclk = get_uart_clk(dev_index);
        u32 baudrate = gd->baudrate;
        u32 val;
 
-       val = pclk / baudrate;
+       val = uclk / baudrate;
 
        writel(val / 16 - 1, &uart->ubrdiv);
-       writew(udivslot[val % 16], &uart->udivslot);
+
+       if (s5p_uart_divslot())
+               writew(udivslot[val % 16], &uart->rest.slot);
+       else
+               writeb(val % 16, &uart->rest.value);
 }
 
 /*
@@ -85,8 +91,8 @@ int serial_init_dev(const int dev_index)
 {
        struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
 
-       /* reset and enable FIFOs, set triggers to the maximum */
-       writel(0, &uart->ufcon);
+       /* enable FIFOs */
+       writel(0x1, &uart->ufcon);
        writel(0, &uart->umcon);
        /* 8N1 */
        writel(0x3, &uart->ulcon);
@@ -128,12 +134,13 @@ int serial_getc_dev(const int dev_index)
        struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
 
        /* wait for character to arrive */
-       while (!(readl(&uart->utrstat) & 0x1)) {
+       while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
+                                        RX_FIFO_FULL_MASK))) {
                if (serial_err_check(dev_index, 0))
                        return 0;
        }
 
-       return (int)(readl(&uart->urxh) & 0xff);
+       return (int)(readb(&uart->urxh) & 0xff);
 }
 
 /*
@@ -144,12 +151,12 @@ void serial_putc_dev(const char c, const int dev_index)
        struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
 
        /* wait for room in the tx FIFO */
-       while (!(readl(&uart->utrstat) & 0x2)) {
+       while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
                if (serial_err_check(dev_index, 1))
                        return;
        }
 
-       writel(c, &uart->utxh);
+       writeb(c, &uart->utxh);
 
        /* If \n, also do \r */
        if (c == '\n')
@@ -181,25 +188,49 @@ int s5p_serial##port##_tstc(void) { return serial_tstc_dev(port); } \
 void s5p_serial##port##_putc(const char c) { serial_putc_dev(c, port); } \
 void s5p_serial##port##_puts(const char *s) { serial_puts_dev(s, port); }
 
-#define INIT_S5P_SERIAL_STRUCTURE(port, name, bus) { \
-       name, \
-       bus, \
-       s5p_serial##port##_init, \
-       s5p_serial##port##_setbrg, \
-       s5p_serial##port##_getc, \
-       s5p_serial##port##_tstc, \
-       s5p_serial##port##_putc, \
-       s5p_serial##port##_puts, }
+#define INIT_S5P_SERIAL_STRUCTURE(port, __name) {      \
+       .name   = __name,                               \
+       .start  = s5p_serial##port##_init,              \
+       .stop   = NULL,                                 \
+       .setbrg = s5p_serial##port##_setbrg,            \
+       .getc   = s5p_serial##port##_getc,              \
+       .tstc   = s5p_serial##port##_tstc,              \
+       .putc   = s5p_serial##port##_putc,              \
+       .puts   = s5p_serial##port##_puts,              \
+}
 
 DECLARE_S5P_SERIAL_FUNCTIONS(0);
 struct serial_device s5p_serial0_device =
-       INIT_S5P_SERIAL_STRUCTURE(0, "s5pser0", "S5PUART0");
+       INIT_S5P_SERIAL_STRUCTURE(0, "s5pser0");
 DECLARE_S5P_SERIAL_FUNCTIONS(1);
 struct serial_device s5p_serial1_device =
-       INIT_S5P_SERIAL_STRUCTURE(1, "s5pser1", "S5PUART1");
+       INIT_S5P_SERIAL_STRUCTURE(1, "s5pser1");
 DECLARE_S5P_SERIAL_FUNCTIONS(2);
 struct serial_device s5p_serial2_device =
-       INIT_S5P_SERIAL_STRUCTURE(2, "s5pser2", "S5PUART2");
+       INIT_S5P_SERIAL_STRUCTURE(2, "s5pser2");
 DECLARE_S5P_SERIAL_FUNCTIONS(3);
 struct serial_device s5p_serial3_device =
-       INIT_S5P_SERIAL_STRUCTURE(3, "s5pser3", "S5PUART3");
+       INIT_S5P_SERIAL_STRUCTURE(3, "s5pser3");
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if defined(CONFIG_SERIAL0)
+       return &s5p_serial0_device;
+#elif defined(CONFIG_SERIAL1)
+       return &s5p_serial1_device;
+#elif defined(CONFIG_SERIAL2)
+       return &s5p_serial2_device;
+#elif defined(CONFIG_SERIAL3)
+       return &s5p_serial3_device;
+#else
+#error "CONFIG_SERIAL? missing."
+#endif
+}
+
+void s5p_serial_initialize(void)
+{
+       serial_register(&s5p_serial0_device);
+       serial_register(&s5p_serial1_device);
+       serial_register(&s5p_serial2_device);
+       serial_register(&s5p_serial3_device);
+}