[U-Boot] [PATCH V3 02/12] Blackfin: bf60x: add serial support
Bob Liu
lliubbo at gmail.com
Wed Nov 14 11:24:36 CET 2012
From: Sonic Zhang <sonic.zhang at analog.com>
Add serial for bf60x.
Signed-off-by: Sonic Zhang <sonic.zhang at analog.com>
Signed-off-by: Bob Liu <lliubbo at gmail.com>
---
arch/blackfin/cpu/serial.c | 81 +++---
arch/blackfin/cpu/serial.h | 222 ++--------------
arch/blackfin/cpu/serial1.h | 275 ++++++++++++++++++++
arch/blackfin/cpu/serial4.h | 139 ++++++++++
arch/blackfin/include/asm/mach-common/bits/uart4.h | 66 +++++
5 files changed, 545 insertions(+), 238 deletions(-)
create mode 100644 arch/blackfin/cpu/serial1.h
create mode 100644 arch/blackfin/cpu/serial4.h
create mode 100644 arch/blackfin/include/asm/mach-common/bits/uart4.h
diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c
index 6603dc0..7d4dad9 100644
--- a/arch/blackfin/cpu/serial.c
+++ b/arch/blackfin/cpu/serial.c
@@ -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 serial_register_bfin_uart(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 serial_register_bfin_uart(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);
}
)
diff --git a/arch/blackfin/cpu/serial.h b/arch/blackfin/cpu/serial.h
index 8a076dd..9200339 100644
--- a/arch/blackfin/cpu/serial.h
+++ b/arch/blackfin/cpu/serial.h
@@ -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
@@ -24,88 +24,34 @@
# 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
index 0000000..986494d
--- /dev/null
+++ b/arch/blackfin/cpu/serial1.h
@@ -0,0 +1,275 @@
+/*
+ * 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.
+ */
+#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
+
+typedef uint16_t uart_lsr_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_portmux(void)
+{
+#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 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
index 0000000..d84de58
--- /dev/null
+++ b/arch/blackfin/cpu/serial4.h
@@ -0,0 +1,139 @@
+/*
+ * 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;
+};
+typedef uint32_t uart_lsr_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_portmux(void)
+{
+#if defined(__ADSPBF60x__)
+# define DO_MUX(port, tx, rx, func) do \
+{\
+ 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_##func | PORT_x_MUX_##rx##_FUNC_##func); \
+ bfin_write_PORT##port##_FER_SET(P##port##tx | P##port##rx);\
+} while (0)
+ switch (CONFIG_UART_CONSOLE) {
+ case 0:
+ DO_MUX(D, 7, 8, 2);
+ break; /* Port D; PD7 and PD8; function 2 */
+ case 1:
+ DO_MUX(G, 15, 14, 1);
+ break; /* Port G; PG15 and PH14; function 1 */
+ }
+ SSYNC();
+#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 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
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
index 0000000..37808de
--- /dev/null
+++ b/arch/blackfin/include/asm/mach-common/bits/uart4.h
@@ -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
--
1.7.9.5
More information about the U-Boot
mailing list