From patchwork Tue Aug 21 05:27:02 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bob Liu X-Patchwork-Id: 178958 X-Patchwork-Delegate: vapier@gentoo.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 4F6C82C008C for ; Tue, 21 Aug 2012 15:27:47 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id DF957282C7; Tue, 21 Aug 2012 07:27:39 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id uYgfPuOC-3Lf; Tue, 21 Aug 2012 07:27:39 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id EF7B428283; Tue, 21 Aug 2012 07:27:17 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 01AD628185 for ; Tue, 21 Aug 2012 07:27:15 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id we61V5irBE5K for ; Tue, 21 Aug 2012 07:27:13 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from am1outboundpool.messaging.microsoft.com (am1ehsobe006.messaging.microsoft.com [213.199.154.209]) by theia.denx.de (Postfix) with ESMTPS id 3B6362817D for ; Tue, 21 Aug 2012 07:27:11 +0200 (CEST) Received: from mail89-am1-R.bigfish.com (10.3.201.226) by AM1EHSOBE002.bigfish.com (10.3.204.22) with Microsoft SMTP Server id 14.1.225.23; Tue, 21 Aug 2012 05:27:11 +0000 Received: from mail89-am1 (localhost [127.0.0.1]) by mail89-am1-R.bigfish.com (Postfix) with ESMTP id 0AFBA1E00C5; Tue, 21 Aug 2012 05:27:11 +0000 (UTC) X-Forefront-Antispam-Report: CIP:137.71.25.57; KIP:(null); UIP:(null); IPV:NLI; H:nwd2mta2.analog.com; RD:nwd2mail11.analog.com; EFVD:NLI X-SpamScore: 6 X-BigFish: VS6(zz1414Jzz1202h1cabhzz8275bhz2ei87h2a8h668h839hd24he5bhe96h107ahff4o1155h1151h) Received-SPF: neutral (mail89-am1: 137.71.25.57 is neither permitted nor denied by domain of gmail.com) client-ip=137.71.25.57; envelope-from=lliubbo@gmail.com; helo=nwd2mta2.analog.com ; 2.analog.com ; X-FB-DOMAIN-IP-MATCH: fail Received: from mail89-am1 (localhost.localdomain [127.0.0.1]) by mail89-am1 (MessageSwitch) id 1345526828535993_28467; Tue, 21 Aug 2012 05:27:08 +0000 (UTC) Received: from AM1EHSMHS011.bigfish.com (unknown [10.3.201.229]) by mail89-am1.bigfish.com (Postfix) with ESMTP id 80A513E0047; Tue, 21 Aug 2012 05:27:08 +0000 (UTC) Received: from nwd2mta2.analog.com (137.71.25.57) by AM1EHSMHS011.bigfish.com (10.3.207.111) with Microsoft SMTP Server (TLS) id 14.1.225.23; Tue, 21 Aug 2012 05:27:07 +0000 Received: from NWD2HUBCAS1.ad.analog.com (nwd2hubcas1.ad.analog.com [10.64.73.29]) by nwd2mta2.analog.com (8.13.8/8.13.8) with ESMTP id q7L6VOFJ013417 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL); Tue, 21 Aug 2012 02:31:24 -0400 Received: from zeus.spd.analog.com (10.64.82.11) by NWD2HUBCAS1.ad.analog.com (10.64.73.29) with Microsoft SMTP Server id 8.3.83.0; Tue, 21 Aug 2012 01:27:06 -0400 Received: from linux.site ([10.99.22.20]) by zeus.spd.analog.com (8.14.5/8.14.5) with ESMTP id q7L5R255009683; Tue, 21 Aug 2012 01:27:03 -0400 Received: from bob-OptiPlex-760.analog.com (unknown [10.99.24.84]) by linux.site (Postfix) with ESMTP id CF68242CB7C2; Mon, 20 Aug 2012 15:53:13 -0600 (MDT) From: Bob Liu To: , , Date: Tue, 21 Aug 2012 13:27:02 +0800 Message-ID: <1345526833-10804-2-git-send-email-lliubbo@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1345526833-10804-1-git-send-email-lliubbo@gmail.com> References: <1345526833-10804-1-git-send-email-lliubbo@gmail.com> MIME-Version: 1.0 Cc: u-boot-devel@blackfin.uclinux.org, sonic.zhang@analog.com Subject: [U-Boot] [PATCH 02/13] Blackfin: bf60x: add serial support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Sonic Zhang Add serial for bf60x. Signed-off-by: Sonic Zhang Signed-off-by: Bob Liu --- arch/blackfin/cpu/serial.c | 81 ++++--- arch/blackfin/cpu/serial.h | 222 ++--------------- arch/blackfin/cpu/serial1.h | 255 ++++++++++++++++++++ arch/blackfin/cpu/serial4.h | 140 +++++++++++ arch/blackfin/include/asm/mach-common/bits/uart4.h | 66 +++++ 5 files changed, 526 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 #include #include -#include 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 -#include +#include #ifndef CONFIG_UART_CONSOLE # define CONFIG_UART_CONSOLE 0 @@ -24,88 +24,34 @@ # define BFIN_DEBUG_EARLY_SERIAL 0 #endif -#ifndef __ASSEMBLY__ - -#include - -#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..0d038d5 --- /dev/null +++ b/arch/blackfin/cpu/serial1.h @@ -0,0 +1,255 @@ +/* + * 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 + +#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..bf4db6f --- /dev/null +++ b/arch/blackfin/cpu/serial4.h @@ -0,0 +1,140 @@ +/* + * 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 + +#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