Merge branch 'master' of git://git.denx.de/u-boot-i2c
[oweals/u-boot.git] / cpu / blackfin / serial.h
index ec40c266ac58a1b2bf2294221206f4edeec153ea..6cbc564b532b974ebbf5ecd1a2fb8893545b3959 100644 (file)
 #include <asm/blackfin.h>
 #include <asm/mach-common/bits/uart.h>
 
+#ifndef CONFIG_UART_CONSOLE
+# define CONFIG_UART_CONSOLE 0
+#endif
+
 #ifdef CONFIG_DEBUG_EARLY_SERIAL
 # define BFIN_DEBUG_EARLY_SERIAL 1
 #else
 
 #ifndef __ASSEMBLY__
 
-/* We cannot use get_sclk() in initcode as it is defined elsewhere. */
-#ifdef BFIN_IN_INITCODE
-# define get_sclk() (CONFIG_CLKIN_HZ * CONFIG_VCO_MULT / CONFIG_SCLK_DIV)
-#endif
-
 #ifdef __ADSPBF54x__
 # define ACCESS_LATCH()
 # define ACCESS_PORT_IER()
 __attribute__((always_inline))
 static inline void serial_do_portmux(void)
 {
-#ifdef __ADSPBF52x__
+#if defined(__ADSPBF51x__)
+# define DO_MUX(port, mux_tx, mux_rx, tx, rx) \
+       bfin_write_PORT##port##_MUX((bfin_read_PORT##port##_MUX() & ~(PORT_x_MUX_##mux_tx##_MASK | PORT_x_MUX_##mux_rx##_MASK)) | PORT_x_MUX_##mux_tx##_FUNC_2 | PORT_x_MUX_##mux_rx##_FUNC_2); \
+       bfin_write_PORT##port##_FER(bfin_read_PORT##port##_FER() | P##port##tx | P##port##rx);
+       switch (CONFIG_UART_CONSOLE) {
+       case 0: DO_MUX(G, 5, 5, 9, 10);  break; /* Port G; mux 5; PG9 and PG10 */
+       case 1: DO_MUX(F, 2, 3, 14, 15); break; /* Port H; mux 2/3; PH14 and PH15 */
+       }
+       SSYNC();
+#elif defined(__ADSPBF52x__)
 # define DO_MUX(port, mux, tx, rx) \
        bfin_write_PORT##port##_MUX((bfin_read_PORT##port##_MUX() & ~PORT_x_MUX_##mux##_MASK) | PORT_x_MUX_##mux##_FUNC_3); \
        bfin_write_PORT##port##_FER(bfin_read_PORT##port##_FER() | P##port##tx | P##port##rx);
@@ -133,7 +141,7 @@ static inline void serial_early_init(void)
        /* handle portmux crap on different Blackfins */
        serial_do_portmux();
 
-       /* Enable UART */
+       /* always enable UART -- avoids anomalies 05000309 and 05000350 */
        *pUART_GCTL = UCEN;
 
        /* Set LCR to Word Lengh 8-bit word select */
@@ -143,16 +151,25 @@ static inline void serial_early_init(void)
 }
 
 __attribute__((always_inline))
-static inline uint32_t serial_early_get_baud(void)
+static inline void serial_early_put_div(uint16_t divisor)
 {
-       /* If the UART isnt enabled, then we are booting an LDR
-        * from a non-UART source (so like flash) which means
-        * the baud rate here is meaningless.
-        */
-       if ((*pUART_GCTL & UCEN) != UCEN)
-               return 0;
+       /* Set DLAB in LCR to Access DLL and DLH */
+       ACCESS_LATCH();
+       SSYNC();
 
-#if (0)        /* See comment for serial_reset_baud() in initcode.c */
+       /* Program the divisor to get the baud rate we want */
+       *pUART_DLL = LOB(divisor);
+       *pUART_DLH = HIB(divisor);
+       SSYNC();
+
+       /* Clear DLAB in LCR to Access THR RBR IER */
+       ACCESS_PORT_IER();
+       SSYNC();
+}
+
+__attribute__((always_inline))
+static inline uint16_t serial_early_get_div(void)
+{
        /* Set DLAB in LCR to Access DLL and DLH */
        ACCESS_LATCH();
        SSYNC();
@@ -160,18 +177,19 @@ static inline uint32_t serial_early_get_baud(void)
        uint8_t dll = *pUART_DLL;
        uint8_t dlh = *pUART_DLH;
        uint16_t divisor = (dlh << 8) | dll;
-       uint32_t baud = get_sclk() / (divisor * 16);
 
        /* Clear DLAB in LCR to Access THR RBR IER */
        ACCESS_PORT_IER();
        SSYNC();
 
-       return baud;
-#else
-       return CONFIG_BAUDRATE;
-#endif
+       return divisor;
 }
 
+/* We cannot use get_sclk() early on as it uses caches in external memory */
+#if defined(BFIN_IN_INITCODE) || defined(CONFIG_DEBUG_EARLY_SERIAL)
+# define get_sclk() (CONFIG_CLKIN_HZ * CONFIG_VCO_MULT / CONFIG_SCLK_DIV)
+#endif
+
 __attribute__((always_inline))
 static inline void serial_early_set_baud(uint32_t baud)
 {
@@ -179,20 +197,7 @@ static inline void serial_early_set_baud(uint32_t baud)
         * weird multiplication is to make sure we over sample just
         * a little rather than under sample the incoming signals.
         */
-       uint16_t divisor = (get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230;
-
-       /* Set DLAB in LCR to Access DLL and DLH */
-       ACCESS_LATCH();
-       SSYNC();
-
-       /* Program the divisor to get the baud rate we want */
-       *pUART_DLL = LOB(divisor);
-       *pUART_DLH = HIB(divisor);
-       SSYNC();
-
-       /* Clear DLAB in LCR to Access THR RBR IER */
-       ACCESS_PORT_IER();
-       SSYNC();
+       serial_early_put_div((get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230);
 }
 
 #ifndef BFIN_IN_INITCODE
@@ -222,32 +227,6 @@ static inline void serial_early_puts(const char *s)
 #endif
 .endm
 
-/* Recursively expand calls to _serial_putc for every byte
- * passed to us.  Append a newline when we're all done.
- */
-.macro _serial_early_putc byte:req morebytes:vararg
-#ifdef CONFIG_DEBUG_EARLY_SERIAL
-       R0 = \byte;
-       call _serial_putc;
-.ifnb \morebytes
-       _serial_early_putc \morebytes
-.else
-.if (\byte != '\n')
-       _serial_early_putc '\n'
-.endif
-.endif
-#endif
-.endm
-
-/* Wrapper around recurisve _serial_early_putc macro which
- * simply prepends the string "Early: "
- */
-.macro serial_early_putc byte:req morebytes:vararg
-#ifdef CONFIG_DEBUG_EARLY_SERIAL
-       _serial_early_putc 'E', 'a', 'r', 'l', 'y', ':', ' ', \byte, \morebytes
-#endif
-.endm
-
 /* Since we embed the string right into our .text section, we need
  * to find its address.  We do this by getting our PC and adding 2
  * bytes (which is the length of the jump instruction).  Then we