blackfin: bf60x: add serial support
authorSonic Zhang <sonic.zhang@analog.com>
Thu, 16 Aug 2012 03:16:02 +0000 (11:16 +0800)
committersonic <sonic@sonic-linuxvm.(none)>
Mon, 4 Mar 2013 05:42:06 +0000 (13:42 +0800)
Add serial for bf60x.

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Bob Liu <lliubbo@gmail.com>
Signed-off-by: Sonic Zhang <sonic.adi@gmail.com>
arch/blackfin/cpu/serial.c
arch/blackfin/cpu/serial.h
arch/blackfin/cpu/serial1.h [new file with mode: 0644]
arch/blackfin/cpu/serial4.h [new file with mode: 0644]
arch/blackfin/include/asm/mach-bf533/BF531_def.h
arch/blackfin/include/asm/mach-bf561/BF561_def.h
arch/blackfin/include/asm/mach-common/bits/uart4.h [new file with mode: 0644]

index 64340ec67d552c62211aa4ca18b152d6284a5985..9847e9f2c5cc80d2e61ea211b6903567e6753885 100644 (file)
@@ -43,7 +43,6 @@
 #include <serial.h>
 #include <linux/compiler.h>
 #include <asm/blackfin.h>
-#include <asm/mach-common/bits/uart.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -52,8 +51,8 @@ DECLARE_GLOBAL_DATA_PTR;
 #include "serial.h"
 
 #ifdef CONFIG_DEBUG_SERIAL
-static uint16_t cached_lsr[256];
-static uint16_t cached_rbr[256];
+static uart_lsr_t cached_lsr[256];
+static uart_lsr_t cached_rbr[256];
 static size_t cache_count;
 
 /* The LSR is read-to-clear on some parts, so we have to make sure status
@@ -61,10 +60,10 @@ static size_t cache_count;
  * works around anomaly 05000099 at the same time by keeping a cumulative
  * tally of all the status bits.
  */
-static uint16_t uart_lsr_save;
-static uint16_t uart_lsr_read(uint32_t uart_base)
+static uart_lsr_t uart_lsr_save;
+static uart_lsr_t uart_lsr_read(uint32_t uart_base)
 {
-       uint16_t lsr = bfin_read(&pUART->lsr);
+       uart_lsr_t lsr = _lsr_read(pUART);
        uart_lsr_save |= (lsr & (OE|PE|FE|BI));
        return lsr | uart_lsr_save;
 }
@@ -72,20 +71,20 @@ static uint16_t uart_lsr_read(uint32_t uart_base)
 static void uart_lsr_clear(uint32_t uart_base)
 {
        uart_lsr_save = 0;
-       bfin_write(&pUART->lsr, bfin_read(&pUART->lsr) | -1);
+       _lsr_write(pUART, -1);
 }
 #else
 /* When debugging is disabled, we only care about the DR bit, so if other
  * bits get set/cleared, we don't really care since we don't read them
  * anyways (and thus anomaly 05000099 is irrelevant).
  */
-static inline uint16_t uart_lsr_read(uint32_t uart_base)
+static inline uart_lsr_t uart_lsr_read(uint32_t uart_base)
 {
-       return bfin_read(&pUART->lsr);
+       return _lsr_read(pUART);
 }
 static void uart_lsr_clear(uint32_t uart_base)
 {
-       bfin_write(&pUART->lsr, bfin_read(&pUART->lsr) | -1);
+       _lsr_write(pUART, -1);
 }
 #endif
 
@@ -127,20 +126,14 @@ static int uart_getc(uint32_t uart_base)
 
 #ifdef CONFIG_DEBUG_SERIAL
        /* grab & clear the LSR */
-       uint16_t uart_lsr_val = uart_lsr_read(uart_base);
+       uart_lsr_t uart_lsr_val = uart_lsr_read(uart_base);
 
        cached_lsr[cache_count] = uart_lsr_val;
        cached_rbr[cache_count] = uart_rbr_val;
        cache_count = (cache_count + 1) % ARRAY_SIZE(cached_lsr);
 
        if (uart_lsr_val & (OE|PE|FE|BI)) {
-               uint16_t dll, dlh;
                printf("\n[SERIAL ERROR]\n");
-               ACCESS_LATCH();
-               dll = bfin_read(&pUART->dll);
-               dlh = bfin_read(&pUART->dlh);
-               ACCESS_PORT_IER();
-               printf("\tDLL=0x%x DLH=0x%x\n", dll, dlh);
                do {
                        --cache_count;
                        printf("\t%3zu: RBR=0x%02x LSR=0x%02x\n", cache_count,
@@ -160,6 +153,8 @@ static int uart_getc(uint32_t uart_base)
 # define LOOP(x)
 #endif
 
+#if BFIN_UART_HW_VER < 4
+
 LOOP(
 static void uart_loop(uint32_t uart_base, int state)
 {
@@ -178,6 +173,28 @@ static void uart_loop(uint32_t uart_base, int state)
 }
 )
 
+#else
+
+LOOP(
+static void uart_loop(uint32_t uart_base, int state)
+{
+       u32 control;
+
+       /* Drain the TX fifo first so bytes don't come back */
+       while (!(uart_lsr_read(uart_base) & TEMT))
+               continue;
+
+       control = bfin_read(&pUART->control);
+       if (state)
+               control |= LOOP_ENA | MRTS;
+       else
+               control &= ~(LOOP_ENA | MRTS);
+       bfin_write(&pUART->control, control);
+}
+)
+
+#endif
+
 #ifdef CONFIG_SYS_BFIN_UART
 
 static void uart_puts(uint32_t uart_base, const char *s)
@@ -246,16 +263,16 @@ struct serial_device bfin_serial##n##_device = { \
        LOOP(.loop = uart##n##_loop) \
 };
 
-#ifdef UART0_DLL
+#ifdef UART0_RBR
 DECL_BFIN_UART(0)
 #endif
-#ifdef UART1_DLL
+#ifdef UART1_RBR
 DECL_BFIN_UART(1)
 #endif
-#ifdef UART2_DLL
+#ifdef UART2_RBR
 DECL_BFIN_UART(2)
 #endif
-#ifdef UART3_DLL
+#ifdef UART3_RBR
 DECL_BFIN_UART(3)
 #endif
 
@@ -274,16 +291,16 @@ __weak struct serial_device *default_serial_console(void)
 
 void bfin_serial_initialize(void)
 {
-#ifdef UART0_DLL
+#ifdef UART0_RBR
        serial_register(&bfin_serial0_device);
 #endif
-#ifdef UART1_DLL
+#ifdef UART1_RBR
        serial_register(&bfin_serial1_device);
 #endif
-#ifdef UART2_DLL
+#ifdef UART2_RBR
        serial_register(&bfin_serial2_device);
 #endif
-#ifdef UART3_DLL
+#ifdef UART3_RBR
        serial_register(&bfin_serial3_device);
 #endif
 }
@@ -293,7 +310,7 @@ void bfin_serial_initialize(void)
 /* Symbol for our assembly to call. */
 void serial_set_baud(uint32_t baud)
 {
-       serial_early_set_baud(UART_DLL, baud);
+       serial_early_set_baud(UART_BASE, baud);
 }
 
 /* Symbol for common u-boot code to call.
@@ -307,7 +324,7 @@ void serial_setbrg(void)
 /* Symbol for our assembly to call. */
 void serial_initialize(void)
 {
-       serial_early_init(UART_DLL);
+       serial_early_init(UART_BASE);
 }
 
 /* Symbol for common u-boot code to call. */
@@ -315,23 +332,23 @@ int serial_init(void)
 {
        serial_initialize();
        serial_setbrg();
-       uart_lsr_clear(UART_DLL);
+       uart_lsr_clear(UART_BASE);
        return 0;
 }
 
 int serial_tstc(void)
 {
-       return uart_tstc(UART_DLL);
+       return uart_tstc(UART_BASE);
 }
 
 int serial_getc(void)
 {
-       return uart_getc(UART_DLL);
+       return uart_getc(UART_BASE);
 }
 
 void serial_putc(const char c)
 {
-       uart_putc(UART_DLL, c);
+       uart_putc(UART_BASE, c);
 }
 
 void serial_puts(const char *s)
@@ -343,7 +360,7 @@ void serial_puts(const char *s)
 LOOP(
 void serial_loop(int state)
 {
-       uart_loop(UART_DLL, state);
+       uart_loop(UART_BASE, state);
 }
 )
 
index 8a076ddc924d7348a1c9062df658eb88c0151a01..9200339668369609661a25e32862e5da88796240 100644 (file)
@@ -3,7 +3,7 @@
  *            any functions defined here must be always_inline since
  *            initcode cannot have function calls.
  *
- * Copyright (c) 2004-2007 Analog Devices Inc.
+ * Copyright (c) 2004-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -12,7 +12,7 @@
 #define __BFIN_CPU_SERIAL_H__
 
 #include <asm/blackfin.h>
-#include <asm/mach-common/bits/uart.h>
+#include <asm/portmux.h>
 
 #ifndef CONFIG_UART_CONSOLE
 # define CONFIG_UART_CONSOLE 0
 # define BFIN_DEBUG_EARLY_SERIAL 0
 #endif
 
-#ifndef __ASSEMBLY__
-
-#include <asm/portmux.h>
-
-#define LOB(x) ((x) & 0xFF)
-#define HIB(x) (((x) >> 8) & 0xFF)
-
-#if defined(__ADSPBF50x__) || defined(__ADSPBF54x__)
+#if defined(__ADSPBF60x__)
+# define BFIN_UART_HW_VER 4
+#elif defined(__ADSPBF50x__) || defined(__ADSPBF54x__)
 # define BFIN_UART_HW_VER 2
 #else
 # define BFIN_UART_HW_VER 1
 #endif
 
-/*
- * All Blackfin system MMRs are padded to 32bits even if the register
- * itself is only 16bits.  So use a helper macro to streamline this.
- */
-#define __BFP(m) u16 m; u16 __pad_##m
-struct bfin_mmr_serial {
-#if BFIN_UART_HW_VER == 2
-       __BFP(dll);
-       __BFP(dlh);
-       __BFP(gctl);
-       __BFP(lcr);
-       __BFP(mcr);
-       __BFP(lsr);
-       __BFP(msr);
-       __BFP(scr);
-       __BFP(ier_set);
-       __BFP(ier_clear);
-       __BFP(thr);
-       __BFP(rbr);
-#else
-       union {
-               u16 dll;
-               u16 thr;
-               const u16 rbr;
-       };
-       const u16 __spad0;
-       union {
-               u16 dlh;
-               u16 ier;
-       };
-       const u16 __spad1;
-       const __BFP(iir);
-       __BFP(lcr);
-       __BFP(mcr);
-       __BFP(lsr);
-       __BFP(msr);
-       __BFP(scr);
-       const u32 __spad2;
-       __BFP(gctl);
-#endif
-};
-#undef __BFP
-
 #define __PASTE_UART(num, pfx, sfx) pfx##num##_##sfx
 #define _PASTE_UART(num, pfx, sfx) __PASTE_UART(num, pfx, sfx)
-#define MMR_UART(n) _PASTE_UART(n, UART, DLL)
 #define _P_UART(n, pin) _PASTE_UART(n, P_UART, pin)
 #define P_UART(pin) _P_UART(CONFIG_UART_CONSOLE, pin)
 
-#ifndef UART_DLL
-# define UART_DLL MMR_UART(CONFIG_UART_CONSOLE)
-#else
-# define UART0_DLL UART_DLL
-# if CONFIG_UART_CONSOLE != 0
-#  error CONFIG_UART_CONSOLE must be 0 on parts with only one UART
-# endif
-#endif
 #define pUART ((volatile struct bfin_mmr_serial *)uart_base)
 
-#if BFIN_UART_HW_VER == 2
-# define ACCESS_LATCH()
-# define ACCESS_PORT_IER()
+#ifndef __ASSEMBLY__
+__attribute__((always_inline))
+static inline void serial_do_portmux(void);
+#endif
+
+#if BFIN_UART_HW_VER < 4
+# include "serial1.h"
 #else
-# define ACCESS_LATCH() \
-       bfin_write(&pUART->lcr, bfin_read(&pUART->lcr) | DLAB)
-# define ACCESS_PORT_IER() \
-       bfin_write(&pUART->lcr, bfin_read(&pUART->lcr) & ~DLAB)
+# include "serial4.h"
 #endif
 
+#ifndef __ASSEMBLY__
+
 __attribute__((always_inline))
 static inline void serial_do_portmux(void)
 {
@@ -115,143 +61,7 @@ static inline void serial_do_portmux(void)
                return;
        }
 
-#if defined(__ADSPBF50x__)
-# 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_1 | PORT_x_MUX_##mux_rx##_FUNC_1); \
-       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, 7, 7, 12, 13); break; /* Port G; mux 7; PG12 and PG13 */
-       case 1: DO_MUX(F, 3, 3, 6, 7);   break; /* Port F; mux 3; PF6 and PF7 */
-       }
-       SSYNC();
-#elif 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);
-       switch (CONFIG_UART_CONSOLE) {
-       case 0: DO_MUX(G, 2, 7, 8);   break;    /* Port G; mux 2; PG2 and PG8 */
-       case 1: DO_MUX(F, 5, 14, 15); break;    /* Port F; mux 5; PF14 and PF15 */
-       }
-       SSYNC();
-#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__)
-       const uint16_t func[] = { PFDE, PFTE, };
-       bfin_write_PORT_MUX(bfin_read_PORT_MUX() & ~func[CONFIG_UART_CONSOLE]);
-       bfin_write_PORTF_FER(bfin_read_PORTF_FER() |
-                            (1 << P_IDENT(P_UART(RX))) |
-                            (1 << P_IDENT(P_UART(TX))));
-       SSYNC();
-#elif defined(__ADSPBF54x__)
-# define DO_MUX(port, tx, rx) \
-       bfin_write_PORT##port##_MUX((bfin_read_PORT##port##_MUX() & ~(PORT_x_MUX_##tx##_MASK | PORT_x_MUX_##rx##_MASK)) | PORT_x_MUX_##tx##_FUNC_1 | PORT_x_MUX_##rx##_FUNC_1); \
-       bfin_write_PORT##port##_FER(bfin_read_PORT##port##_FER() | P##port##tx | P##port##rx);
-       switch (CONFIG_UART_CONSOLE) {
-       case 0: DO_MUX(E, 7, 8); break; /* Port E; PE7 and PE8 */
-       case 1: DO_MUX(H, 0, 1); break; /* Port H; PH0 and PH1 */
-       case 2: DO_MUX(B, 4, 5); break; /* Port B; PB4 and PB5 */
-       case 3: DO_MUX(B, 6, 7); break; /* Port B; PB6 and PB7 */
-       }
-       SSYNC();
-#elif defined(__ADSPBF561__)
-       /* UART pins could be GPIO, but they aren't pin muxed.  */
-#else
-# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED)
-#  error "missing portmux logic for UART"
-# endif
-#endif
-}
-
-__attribute__((always_inline))
-static inline int uart_init(uint32_t uart_base)
-{
-       /* always enable UART -- avoids anomalies 05000309 and 05000350 */
-       bfin_write(&pUART->gctl, UCEN);
-
-       /* Set LCR to Word Lengh 8-bit word select */
-       bfin_write(&pUART->lcr, WLS_8);
-
-       SSYNC();
-
-       return 0;
-}
-
-__attribute__((always_inline))
-static inline int serial_early_init(uint32_t uart_base)
-{
-       /* handle portmux crap on different Blackfins */
-       serial_do_portmux();
-
-       return uart_init(uart_base);
-}
-
-__attribute__((always_inline))
-static inline int serial_early_uninit(uint32_t uart_base)
-{
-       /* disable the UART by clearing UCEN */
-       bfin_write(&pUART->gctl, 0);
-
-       return 0;
-}
-
-__attribute__((always_inline))
-static inline void serial_early_put_div(uint32_t uart_base, uint16_t divisor)
-{
-       /* Set DLAB in LCR to Access DLL and DLH */
-       ACCESS_LATCH();
-       SSYNC();
-
-       /* Program the divisor to get the baud rate we want */
-       bfin_write(&pUART->dll, LOB(divisor));
-       bfin_write(&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)
-{
-       uint32_t uart_base = UART_DLL;
-
-       /* Set DLAB in LCR to Access DLL and DLH */
-       ACCESS_LATCH();
-       SSYNC();
-
-       uint8_t dll = bfin_read(&pUART->dll);
-       uint8_t dlh = bfin_read(&pUART->dlh);
-       uint16_t divisor = (dlh << 8) | dll;
-
-       /* Clear DLAB in LCR to Access THR RBR IER */
-       ACCESS_PORT_IER();
-       SSYNC();
-
-       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 uart_base, uint32_t baud)
-{
-       /* Translate from baud into divisor in terms of SCLK.  The
-        * weird multiplication is to make sure we over sample just
-        * a little rather than under sample the incoming signals.
-        */
-       serial_early_put_div(uart_base,
-               (get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230);
+       serial_early_do_portmux();
 }
 
 #ifndef BFIN_IN_INITCODE
diff --git a/arch/blackfin/cpu/serial1.h b/arch/blackfin/cpu/serial1.h
new file mode 100644 (file)
index 0000000..a20175b
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * serial.h - common serial defines for early debug and serial driver.
+ *            any functions defined here must be always_inline since
+ *            initcode cannot have function calls.
+ *
+ * Copyright (c) 2004-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_CPU_SERIAL1_H__
+#define __BFIN_CPU_SERIAL1_H__
+
+#include <asm/mach-common/bits/uart.h>
+
+#ifndef __ASSEMBLY__
+
+#define MMR_UART(n) _PASTE_UART(n, UART, DLL)
+#ifdef UART_DLL
+# define UART0_DLL UART_DLL
+# if CONFIG_UART_CONSOLE != 0
+#  error CONFIG_UART_CONSOLE must be 0 on parts with only one UART
+# endif
+#endif
+#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE)
+
+#define LOB(x) ((x) & 0xFF)
+#define HIB(x) (((x) >> 8) & 0xFF)
+
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits.  So use a helper macro to streamline this.
+ */
+struct bfin_mmr_serial {
+#if BFIN_UART_HW_VER == 2
+       u16 dll;
+       u16 __pad_0;
+       u16 dlh;
+       u16 __pad_1;
+       u16 gctl;
+       u16 __pad_2;
+       u16 lcr;
+       u16 __pad_3;
+       u16 mcr;
+       u16 __pad_4;
+       u16 lsr;
+       u16 __pad_5;
+       u16 msr;
+       u16 __pad_6;
+       u16 scr;
+       u16 __pad_7;
+       u16 ier_set;
+       u16 __pad_8;
+       u16 ier_clear;
+       u16 __pad_9;
+       u16 thr;
+       u16 __pad_10;
+       u16 rbr;
+       u16 __pad_11;
+#else
+       union {
+               u16 dll;
+               u16 thr;
+               const u16 rbr;
+       };
+       const u16 __spad0;
+       union {
+               u16 dlh;
+               u16 ier;
+       };
+       const u16 __spad1;
+       const u16 iir;
+       u16 __pad_0;
+       u16 lcr;
+       u16 __pad_1;
+       u16 mcr;
+       u16 __pad_2;
+       u16 lsr;
+       u16 __pad_3;
+       u16 msr;
+       u16 __pad_4;
+       u16 scr;
+       u16 __pad_5;
+       const u32 __spad2;
+       u16 gctl;
+       u16 __pad_6;
+#endif
+};
+
+#define uart_lsr_t uint32_t
+#define _lsr_read(p)     bfin_read(&p->lsr)
+#define _lsr_write(p, v) bfin_write(&p->lsr, v)
+
+#if BFIN_UART_HW_VER == 2
+# define ACCESS_LATCH()
+# define ACCESS_PORT_IER()
+#else
+# define ACCESS_LATCH()    bfin_write_or(&pUART->lcr, DLAB)
+# define ACCESS_PORT_IER() bfin_write_and(&pUART->lcr, ~DLAB)
+#endif
+
+__attribute__((always_inline))
+static inline void serial_early_do_mach_portmux(char port, int mux_mask,
+       int mux_func, int port_pin)
+{
+       switch (port) {
+#if defined(__ADSPBF54x__)
+       case 'B':
+               bfin_write_PORTB_MUX((bfin_read_PORTB_MUX() &
+                       ~mux_mask) | mux_func);
+               bfin_write_PORTB_FER(bfin_read_PORTB_FER() | port_pin);
+               break;
+       case 'E':
+               bfin_write_PORTE_MUX((bfin_read_PORTE_MUX() &
+                       ~mux_mask) | mux_func);
+               bfin_write_PORTE_FER(bfin_read_PORTE_FER() | port_pin);
+               break;
+#endif
+#if defined(__ADSPBF50x__) || defined(__ADSPBF51x__) || defined(__ADSPBF52x__)
+       case 'F':
+               bfin_write_PORTF_MUX((bfin_read_PORTF_MUX() &
+                       ~mux_mask) | mux_func);
+               bfin_write_PORTF_FER(bfin_read_PORTF_FER() | port_pin);
+               break;
+       case 'G':
+               bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() &
+                       ~mux_mask) | mux_func);
+               bfin_write_PORTG_FER(bfin_read_PORTG_FER() | port_pin);
+               break;
+       case 'H':
+               bfin_write_PORTH_MUX((bfin_read_PORTH_MUX() &
+                       ~mux_mask) | mux_func);
+               bfin_write_PORTH_FER(bfin_read_PORTH_FER() | port_pin);
+               break;
+#endif
+       default:
+               break;
+       }
+}
+
+__attribute__((always_inline))
+static inline void serial_early_do_portmux(void)
+{
+#if defined(__ADSPBF50x__)
+       switch (CONFIG_UART_CONSOLE) {
+       case 0:
+               serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK,
+               PORT_x_MUX_7_FUNC_1, PG12); /* TX: G; mux 7; func 1; PG12 */
+               serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK,
+               PORT_x_MUX_7_FUNC_1, PG13); /* RX: G; mux 7; func 1; PG13 */
+               break;
+       case 1:
+               serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK,
+               PORT_x_MUX_3_FUNC_1, PF7); /* TX: F; mux 3; func 1; PF6 */
+               serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK,
+               PORT_x_MUX_3_FUNC_1, PF6); /* RX: F; mux 3; func 1; PF7 */
+               break;
+       }
+#elif defined(__ADSPBF51x__)
+       switch (CONFIG_UART_CONSOLE) {
+       case 0:
+               serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK,
+               PORT_x_MUX_5_FUNC_2, PG9); /* TX: G; mux 5; func 2; PG9 */
+               serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK,
+               PORT_x_MUX_5_FUNC_2, PG10); /* RX: G; mux 5; func 2; PG10 */
+               break;
+       case 1:
+               serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK,
+               PORT_x_MUX_3_FUNC_2, PH7); /* TX: H; mux 3; func 2; PH6 */
+               serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK,
+               PORT_x_MUX_3_FUNC_2, PH6); /* RX: H; mux 3; func 2; PH7 */
+               break;
+       }
+#elif defined(__ADSPBF52x__)
+       switch (CONFIG_UART_CONSOLE) {
+       case 0:
+               serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK,
+               PORT_x_MUX_2_FUNC_3, PG7); /* TX: G; mux 2; func 3; PG7 */
+               serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK,
+               PORT_x_MUX_2_FUNC_3, PG8); /* RX: G; mux 2; func 3; PG8 */
+               break;
+       case 1:
+               serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK,
+               PORT_x_MUX_5_FUNC_3, PF14); /* TX: F; mux 5; func 3; PF14 */
+               serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK,
+               PORT_x_MUX_5_FUNC_3, PF15); /* RX: F; mux 5; func 3; PF15 */
+               break;
+       }
+#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__)
+       const uint16_t func[] = { PFDE, PFTE, };
+       bfin_write_PORT_MUX(bfin_read_PORT_MUX() & ~func[CONFIG_UART_CONSOLE]);
+       bfin_write_PORTF_FER(bfin_read_PORTF_FER() |
+                       (1 << P_IDENT(P_UART(RX))) |
+                       (1 << P_IDENT(P_UART(TX))));
+#elif defined(__ADSPBF54x__)
+       switch (CONFIG_UART_CONSOLE) {
+       case 0:
+               serial_early_do_mach_portmux('E', PORT_x_MUX_7_MASK,
+               PORT_x_MUX_7_FUNC_1, PE7); /* TX: E; mux 7; func 1; PE7 */
+               serial_early_do_mach_portmux('E', PORT_x_MUX_8_MASK,
+               PORT_x_MUX_8_FUNC_1, PE8); /* RX: E; mux 8; func 1; PE8 */
+               break;
+       case 1:
+               serial_early_do_mach_portmux('H', PORT_x_MUX_0_MASK,
+               PORT_x_MUX_0_FUNC_1, PH0); /* TX: H; mux 0; func 1; PH0 */
+               serial_early_do_mach_portmux('H', PORT_x_MUX_1_MASK,
+               PORT_x_MUX_1_FUNC_1, PH1); /* RX: H; mux 1; func 1; PH1 */
+               break;
+       case 2:
+               serial_early_do_mach_portmux('B', PORT_x_MUX_4_MASK,
+               PORT_x_MUX_4_FUNC_1, PB4); /* TX: B; mux 4; func 1; PB4 */
+               serial_early_do_mach_portmux('B', PORT_x_MUX_5_MASK,
+               PORT_x_MUX_5_FUNC_1, PB5); /* RX: B; mux 5; func 1; PB5 */
+               break;
+       case 3:
+               serial_early_do_mach_portmux('B', PORT_x_MUX_6_MASK,
+               PORT_x_MUX_6_FUNC_1, PB6); /* TX: B; mux 6; func 1; PB6 */
+               serial_early_do_mach_portmux('B', PORT_x_MUX_7_MASK,
+               PORT_x_MUX_7_FUNC_1, PB7); /* RX: B; mux 7; func 1; PB7 */
+               break;
+       }
+#elif defined(__ADSPBF561__)
+       /* UART pins could be GPIO, but they aren't pin muxed.  */
+#else
+# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED)
+#  error "missing portmux logic for UART"
+# endif
+#endif
+       SSYNC();
+}
+
+__attribute__((always_inline))
+static inline uint32_t uart_sclk(void)
+{
+#if defined(BFIN_IN_INITCODE) || defined(CONFIG_DEBUG_EARLY_SERIAL)
+       /* We cannot use get_sclk() early on as it uses
+        * caches in external memory
+        */
+       return CONFIG_CLKIN_HZ * CONFIG_VCO_MULT / CONFIG_SCLK_DIV;
+#else
+       return get_sclk();
+#endif
+}
+
+__attribute__((always_inline))
+static inline int uart_init(uint32_t uart_base)
+{
+       /* always enable UART -- avoids anomalies 05000309 and 05000350 */
+       bfin_write(&pUART->gctl, UCEN);
+
+       /* Set LCR to Word Lengh 8-bit word select */
+       bfin_write(&pUART->lcr, WLS_8);
+
+       SSYNC();
+
+       return 0;
+}
+
+__attribute__((always_inline))
+static inline int serial_early_init(uint32_t uart_base)
+{
+       /* handle portmux crap on different Blackfins */
+       serial_do_portmux();
+
+       return uart_init(uart_base);
+}
+
+__attribute__((always_inline))
+static inline int serial_early_uninit(uint32_t uart_base)
+{
+       /* disable the UART by clearing UCEN */
+       bfin_write(&pUART->gctl, 0);
+
+       return 0;
+}
+
+__attribute__((always_inline))
+static inline int serial_early_enabled(uint32_t uart_base)
+{
+       return bfin_read(&pUART->gctl) & UCEN;
+}
+
+__attribute__((always_inline))
+static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud)
+{
+       /* Translate from baud into divisor in terms of SCLK.  The
+        * weird multiplication is to make sure we over sample just
+        * a little rather than under sample the incoming signals.
+        */
+       uint16_t divisor = (uart_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 */
+       bfin_write(&pUART->dll, LOB(divisor));
+       bfin_write(&pUART->dlh, HIB(divisor));
+       SSYNC();
+
+       /* Clear DLAB in LCR to Access THR RBR IER */
+       ACCESS_PORT_IER();
+       SSYNC();
+}
+
+__attribute__((always_inline))
+static inline void serial_early_put_div(uint16_t divisor)
+{
+       uint32_t uart_base = UART_BASE;
+
+       /* Set DLAB in LCR to Access DLL and DLH */
+       ACCESS_LATCH();
+       SSYNC();
+
+       /* Program the divisor to get the baud rate we want */
+       bfin_write(&pUART->dll, LOB(divisor));
+       bfin_write(&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)
+{
+       uint32_t uart_base = UART_BASE;
+
+       /* Set DLAB in LCR to Access DLL and DLH */
+       ACCESS_LATCH();
+       SSYNC();
+
+       uint8_t dll = bfin_read(&pUART->dll);
+       uint8_t dlh = bfin_read(&pUART->dlh);
+       uint16_t divisor = (dlh << 8) | dll;
+
+       /* Clear DLAB in LCR to Access THR RBR IER */
+       ACCESS_PORT_IER();
+       SSYNC();
+
+       return divisor;
+}
+
+#endif
+
+#endif
diff --git a/arch/blackfin/cpu/serial4.h b/arch/blackfin/cpu/serial4.h
new file mode 100644 (file)
index 0000000..887845c
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * serial.h - common serial defines for early debug and serial driver.
+ *            any functions defined here must be always_inline since
+ *            initcode cannot have function calls.
+ *
+ * Copyright (c) 2004-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_CPU_SERIAL4_H__
+#define __BFIN_CPU_SERIAL4_H__
+
+#include <asm/mach-common/bits/uart4.h>
+
+#ifndef __ASSEMBLY__
+
+#define MMR_UART(n) _PASTE_UART(n, UART, REVID)
+#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE)
+
+struct bfin_mmr_serial {
+       u32 revid;
+       u32 control;
+       u32 status;
+       u32 scr;
+       u32 clock;
+       u32 emask;
+       u32 emaskst;
+       u32 emaskcl;
+       u32 rbr;
+       u32 thr;
+       u32 taip;
+       u32 tsr;
+       u32 rsr;
+       u32 txdiv_cnt;
+       u32 rxdiv_cnt;
+};
+#define uart_lsr_t uint32_t
+#define _lsr_read(p)     bfin_read(&p->status)
+#define _lsr_write(p, v) bfin_write(&p->status, v)
+
+__attribute__((always_inline))
+static inline void serial_early_do_mach_portmux(char port, int mux_mask,
+       int mux_func, int port_pin)
+{
+       switch (port) {
+       case 'D':
+               bfin_write_PORTD_MUX((bfin_read_PORTD_MUX() &
+                       ~mux_mask) | mux_func);
+               bfin_write_PORTD_FER_SET(port_pin);
+               break;
+       case 'G':
+               bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() &
+                       ~mux_mask) | mux_func);
+               bfin_write_PORTG_FER_SET(port_pin);
+               break;
+       }
+}
+
+__attribute__((always_inline))
+static inline void serial_early_do_portmux(void)
+{
+#if defined(__ADSPBF60x__)
+       switch (CONFIG_UART_CONSOLE) {
+       case 0:
+               serial_early_do_mach_portmux('D', PORT_x_MUX_7_MASK,
+               PORT_x_MUX_7_FUNC_2, PD7); /* TX: D; mux 7; func 2; PD7 */
+               serial_early_do_mach_portmux('D', PORT_x_MUX_8_MASK,
+               PORT_x_MUX_8_FUNC_2, PD8); /* RX: D; mux 8; func 2; PD8 */
+               break;
+       case 1:
+               serial_early_do_mach_portmux('G', PORT_x_MUX_15_MASK,
+               PORT_x_MUX_15_FUNC_1, PG15); /* TX: G; mux 15; func 1; PG15 */
+               serial_early_do_mach_portmux('G', PORT_x_MUX_14_MASK,
+               PORT_x_MUX_14_FUNC_1, PG14); /* RX: G; mux 14; func 1; PG14 */
+               break;
+       }
+#else
+# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED)
+#  error "missing portmux logic for UART"
+# endif
+#endif
+       SSYNC();
+}
+
+__attribute__((always_inline))
+static inline uint32_t uart_sclk(void)
+{
+#if defined(BFIN_IN_INITCODE) || defined(CONFIG_DEBUG_EARLY_SERIAL)
+       /* We cannot use get_sclk() early on as it uses caches in
+        * external memory
+        */
+       return CONFIG_CLKIN_HZ * CONFIG_VCO_MULT / CONFIG_SCLK_DIV /
+               CONFIG_SCLK0_DIV;
+#else
+       return get_sclk0();
+#endif
+}
+
+__attribute__((always_inline))
+static inline int uart_init(uint32_t uart_base)
+{
+       /* always enable UART to 8-bit mode */
+       bfin_write(&pUART->control, UEN | UMOD_UART | WLS_8);
+
+       SSYNC();
+
+       return 0;
+}
+
+__attribute__((always_inline))
+static inline int serial_early_init(uint32_t uart_base)
+{
+       /* handle portmux crap on different Blackfins */
+       serial_do_portmux();
+
+       return uart_init(uart_base);
+}
+
+__attribute__((always_inline))
+static inline int serial_early_uninit(uint32_t uart_base)
+{
+       /* disable the UART by clearing UEN */
+       bfin_write(&pUART->control, 0);
+
+       return 0;
+}
+
+__attribute__((always_inline))
+static inline int serial_early_enabled(uint32_t uart_base)
+{
+       return bfin_read(&pUART->control) & UEN;
+}
+
+__attribute__((always_inline))
+static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud)
+{
+       uint32_t divisor = uart_sclk() / (baud * 16);
+
+       /* Program the divisor to get the baud rate we want */
+       bfin_write(&pUART->clock, divisor);
+       SSYNC();
+}
+
+__attribute__((always_inline))
+static inline void serial_early_put_div(uint32_t divisor)
+{
+       uint32_t uart_base = UART_BASE;
+       bfin_write(&pUART->clock, divisor);
+}
+
+__attribute__((always_inline))
+static inline uint32_t serial_early_get_div(void)
+{
+       uint32_t uart_base = UART_BASE;
+       return bfin_read(&pUART->clock);
+}
+
+#endif
+
+#endif
index 3b61aafcc9ddf033d377947ce9fb996eca294ac0..2bcd2d88dc3d225b04952ddf418969bce184e5c6 100644 (file)
 #define UART_LSR                       0xFFC00414
 #define UART_SCR                       0xFFC0041C
 #define UART_RBR                       0xFFC00400 /* Receive Buffer */
+#define UART0_RBR                      UART_RBR
 #define UART_GCTL                      0xFFC00424
 #define SPT0_TX_CONFIG0                0xFFC00800
 #define SPT0_TX_CONFIG1                0xFFC00804
index 46925f8c070dc74be5e81ed86a9551882037623a..a7ff5a3feba842575801d4ea72b8c68808687052 100644 (file)
 #define PPI1_FRAME                     0xFFC01310
 #define UART_THR                       0xFFC00400
 #define UART_RBR                       0xFFC00400
+#define UART0_RBR                      UART_RBR
 #define UART_DLL                       0xFFC00400
 #define UART_DLH                       0xFFC00404
 #define UART_IER                       0xFFC00404
diff --git a/arch/blackfin/include/asm/mach-common/bits/uart4.h b/arch/blackfin/include/asm/mach-common/bits/uart4.h
new file mode 100644 (file)
index 0000000..37808de
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * UART4 Masks
+ */
+
+#ifndef __BFIN_PERIPHERAL_UART4__
+#define __BFIN_PERIPHERAL_UART4__
+
+/* UART_CONTROL */
+#define UEN                    (1 << 0)
+#define LOOP_ENA               (1 << 1)
+#define UMOD                   (3 << 4)
+#define UMOD_UART              (0 << 4)
+#define UMOD_MDB               (1 << 4)
+#define UMOD_IRDA              (1 << 4)
+#define WLS                    (3 << 8)
+#define WLS_5                  (0 << 8)
+#define WLS_6                  (1 << 8)
+#define WLS_7                  (2 << 8)
+#define WLS_8                  (3 << 8)
+#define STB                    (1 << 12)
+#define STBH                   (1 << 13)
+#define PEN                    (1 << 14)
+#define EPS                    (1 << 15)
+#define STP                    (1 << 16)
+#define FPE                    (1 << 17)
+#define FFE                    (1 << 18)
+#define SB                     (1 << 19)
+#define FCPOL                  (1 << 22)
+#define RPOLC                  (1 << 23)
+#define TPOLC                  (1 << 24)
+#define MRTS                   (1 << 25)
+#define XOFF                   (1 << 26)
+#define ARTS                   (1 << 27)
+#define ACTS                   (1 << 28)
+#define RFIT                   (1 << 29)
+#define RFRT                   (1 << 30)
+
+/* UART_STATUS */
+#define DR                     (1 << 0)
+#define OE                     (1 << 1)
+#define PE                     (1 << 2)
+#define FE                     (1 << 3)
+#define BI                     (1 << 4)
+#define THRE                   (1 << 5)
+#define TEMT                   (1 << 7)
+#define TFI                    (1 << 8)
+#define ASTKY                  (1 << 9)
+#define ADDR                   (1 << 10)
+#define RO                     (1 << 11)
+#define SCTS                   (1 << 12)
+#define CTS                    (1 << 16)
+#define RFCS                   (1 << 17)
+
+/* UART_EMASK */
+#define ERBFI                  (1 << 0)
+#define ETBEI                  (1 << 1)
+#define ELSI                   (1 << 2)
+#define EDSSI                  (1 << 3)
+#define EDTPTI                 (1 << 4)
+#define ETFI                   (1 << 5)
+#define ERFCI                  (1 << 6)
+#define EAWI                   (1 << 7)
+#define ERXS                   (1 << 8)
+#define ETXS                   (1 << 9)
+
+#endif