blackfin: bf60x: add serial support

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>
This commit is contained in:
Sonic Zhang 2012-08-16 11:16:02 +08:00 committed by sonic
parent a2979dcdbe
commit a12c51f640
7 changed files with 643 additions and 239 deletions

View 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);
}
)

View 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
@ -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()
#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)
#ifndef __ASSEMBLY__
__attribute__((always_inline))
static inline void serial_do_portmux(void);
#endif
#if BFIN_UART_HW_VER < 4
# include "serial1.h"
#else
# 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

348
arch/blackfin/cpu/serial1.h Normal file
View File

@ -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

161
arch/blackfin/cpu/serial4.h Normal file
View File

@ -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

View File

@ -149,6 +149,7 @@
#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

View File

@ -690,6 +690,7 @@
#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

View File

@ -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