mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 02:50:43 +00:00
Blackfin serial driver: supporting BF548-EZKIT serial port
Signed-off-by: Roy Huang <roy.huang@analog.com> Signed-off-by: Mike Frysinger <michael.frysinger@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com>
This commit is contained in:
parent
db83b991bc
commit
f4d640c9be
2 changed files with 117 additions and 6 deletions
|
@ -599,7 +599,7 @@ config UART0_RTS_PIN
|
||||||
|
|
||||||
config SERIAL_BFIN_UART1
|
config SERIAL_BFIN_UART1
|
||||||
bool "Enable UART1"
|
bool "Enable UART1"
|
||||||
depends on SERIAL_BFIN && (BF534 || BF536 || BF537)
|
depends on SERIAL_BFIN && (BF534 || BF536 || BF537 || BF54x)
|
||||||
help
|
help
|
||||||
Enable UART1
|
Enable UART1
|
||||||
|
|
||||||
|
@ -612,18 +612,58 @@ config BFIN_UART1_CTSRTS
|
||||||
|
|
||||||
config UART1_CTS_PIN
|
config UART1_CTS_PIN
|
||||||
int "UART1 CTS pin"
|
int "UART1 CTS pin"
|
||||||
depends on BFIN_UART1_CTSRTS
|
depends on BFIN_UART1_CTSRTS && (BF53x || BF561)
|
||||||
default -1
|
default -1
|
||||||
help
|
help
|
||||||
Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
|
Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
|
||||||
|
|
||||||
config UART1_RTS_PIN
|
config UART1_RTS_PIN
|
||||||
int "UART1 RTS pin"
|
int "UART1 RTS pin"
|
||||||
depends on BFIN_UART1_CTSRTS
|
depends on BFIN_UART1_CTSRTS && (BF53x || BF561)
|
||||||
default -1
|
default -1
|
||||||
help
|
help
|
||||||
Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
|
Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
|
||||||
|
|
||||||
|
config SERIAL_BFIN_UART2
|
||||||
|
bool "Enable UART2"
|
||||||
|
depends on SERIAL_BFIN && (BF54x)
|
||||||
|
help
|
||||||
|
Enable UART2
|
||||||
|
|
||||||
|
config BFIN_UART2_CTSRTS
|
||||||
|
bool "Enable UART2 hardware flow control"
|
||||||
|
depends on SERIAL_BFIN_UART2
|
||||||
|
help
|
||||||
|
Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
|
||||||
|
signal.
|
||||||
|
|
||||||
|
config UART2_CTS_PIN
|
||||||
|
int "UART2 CTS pin"
|
||||||
|
depends on BFIN_UART2_CTSRTS
|
||||||
|
default -1
|
||||||
|
help
|
||||||
|
Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
|
||||||
|
|
||||||
|
config UART2_RTS_PIN
|
||||||
|
int "UART2 RTS pin"
|
||||||
|
depends on BFIN_UART2_CTSRTS
|
||||||
|
default -1
|
||||||
|
help
|
||||||
|
Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
|
||||||
|
|
||||||
|
config SERIAL_BFIN_UART3
|
||||||
|
bool "Enable UART3"
|
||||||
|
depends on SERIAL_BFIN && (BF54x)
|
||||||
|
help
|
||||||
|
Enable UART3
|
||||||
|
|
||||||
|
config BFIN_UART3_CTSRTS
|
||||||
|
bool "Enable UART3 hardware flow control"
|
||||||
|
depends on SERIAL_BFIN_UART3
|
||||||
|
help
|
||||||
|
Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
|
||||||
|
signal.
|
||||||
|
|
||||||
config SERIAL_IMX
|
config SERIAL_IMX
|
||||||
bool "IMX serial port support"
|
bool "IMX serial port support"
|
||||||
depends on ARM && ARCH_IMX
|
depends on ARM && ARCH_IMX
|
||||||
|
|
|
@ -86,8 +86,21 @@ static void bfin_serial_stop_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
|
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
|
||||||
|
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
while (!(UART_GET_LSR(uart) & TEMT))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_DMA
|
#ifdef CONFIG_SERIAL_BFIN_DMA
|
||||||
disable_dma(uart->tx_dma_channel);
|
disable_dma(uart->tx_dma_channel);
|
||||||
|
#else
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
/* Waiting for Transmission Finished */
|
||||||
|
while (!(UART_GET_LSR(uart) & TFI))
|
||||||
|
continue;
|
||||||
|
/* Clear TFI bit */
|
||||||
|
UART_PUT_LSR(uart, TFI);
|
||||||
|
UART_CLEAR_IER(uart, ETBEI);
|
||||||
#else
|
#else
|
||||||
unsigned short ier;
|
unsigned short ier;
|
||||||
|
|
||||||
|
@ -95,6 +108,7 @@ static void bfin_serial_stop_tx(struct uart_port *port)
|
||||||
ier &= ~ETBEI;
|
ier &= ~ETBEI;
|
||||||
UART_PUT_IER(uart, ier);
|
UART_PUT_IER(uart, ier);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,6 +120,9 @@ static void bfin_serial_start_tx(struct uart_port *port)
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_DMA
|
#ifdef CONFIG_SERIAL_BFIN_DMA
|
||||||
bfin_serial_dma_tx_chars(uart);
|
bfin_serial_dma_tx_chars(uart);
|
||||||
|
#else
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
UART_SET_IER(uart, ETBEI);
|
||||||
#else
|
#else
|
||||||
unsigned short ier;
|
unsigned short ier;
|
||||||
ier = UART_GET_IER(uart);
|
ier = UART_GET_IER(uart);
|
||||||
|
@ -113,6 +130,7 @@ static void bfin_serial_start_tx(struct uart_port *port)
|
||||||
UART_PUT_IER(uart, ier);
|
UART_PUT_IER(uart, ier);
|
||||||
bfin_serial_tx_chars(uart);
|
bfin_serial_tx_chars(uart);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -121,6 +139,9 @@ static void bfin_serial_start_tx(struct uart_port *port)
|
||||||
static void bfin_serial_stop_rx(struct uart_port *port)
|
static void bfin_serial_stop_rx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
|
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
UART_CLEAR_IER(uart, ERBFI);
|
||||||
|
#else
|
||||||
unsigned short ier;
|
unsigned short ier;
|
||||||
|
|
||||||
ier = UART_GET_IER(uart);
|
ier = UART_GET_IER(uart);
|
||||||
|
@ -129,6 +150,7 @@ static void bfin_serial_stop_rx(struct uart_port *port)
|
||||||
#endif
|
#endif
|
||||||
ier &= ~ERBFI;
|
ier &= ~ERBFI;
|
||||||
UART_PUT_IER(uart, ier);
|
UART_PUT_IER(uart, ier);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -325,10 +347,21 @@ static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct bfin_serial_port *uart = dev_id;
|
struct bfin_serial_port *uart = dev_id;
|
||||||
|
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
unsigned short status;
|
||||||
|
spin_lock(&uart->port.lock);
|
||||||
|
status = UART_GET_LSR(uart);
|
||||||
|
while ((UART_GET_IER(uart) & ERBFI) && (status & DR)) {
|
||||||
|
bfin_serial_rx_chars(uart);
|
||||||
|
status = UART_GET_LSR(uart);
|
||||||
|
}
|
||||||
|
spin_unlock(&uart->port.lock);
|
||||||
|
#else
|
||||||
spin_lock(&uart->port.lock);
|
spin_lock(&uart->port.lock);
|
||||||
while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY)
|
while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY)
|
||||||
bfin_serial_rx_chars(uart);
|
bfin_serial_rx_chars(uart);
|
||||||
spin_unlock(&uart->port.lock);
|
spin_unlock(&uart->port.lock);
|
||||||
|
#endif
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,10 +369,21 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct bfin_serial_port *uart = dev_id;
|
struct bfin_serial_port *uart = dev_id;
|
||||||
|
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
unsigned short status;
|
||||||
|
spin_lock(&uart->port.lock);
|
||||||
|
status = UART_GET_LSR(uart);
|
||||||
|
while ((UART_GET_IER(uart) & ETBEI) && (status & THRE)) {
|
||||||
|
bfin_serial_tx_chars(uart);
|
||||||
|
status = UART_GET_LSR(uart);
|
||||||
|
}
|
||||||
|
spin_unlock(&uart->port.lock);
|
||||||
|
#else
|
||||||
spin_lock(&uart->port.lock);
|
spin_lock(&uart->port.lock);
|
||||||
while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY)
|
while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY)
|
||||||
bfin_serial_tx_chars(uart);
|
bfin_serial_tx_chars(uart);
|
||||||
spin_unlock(&uart->port.lock);
|
spin_unlock(&uart->port.lock);
|
||||||
|
#endif
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +394,6 @@ static void bfin_serial_do_work(struct work_struct *work)
|
||||||
|
|
||||||
bfin_serial_mctrl_check(uart);
|
bfin_serial_mctrl_check(uart);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_DMA
|
#ifdef CONFIG_SERIAL_BFIN_DMA
|
||||||
|
@ -399,9 +442,13 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
|
||||||
set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
|
set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
|
||||||
set_dma_x_modify(uart->tx_dma_channel, 1);
|
set_dma_x_modify(uart->tx_dma_channel, 1);
|
||||||
enable_dma(uart->tx_dma_channel);
|
enable_dma(uart->tx_dma_channel);
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
UART_SET_IER(uart, ETBEI);
|
||||||
|
#else
|
||||||
ier = UART_GET_IER(uart);
|
ier = UART_GET_IER(uart);
|
||||||
ier |= ETBEI;
|
ier |= ETBEI;
|
||||||
UART_PUT_IER(uart, ier);
|
UART_PUT_IER(uart, ier);
|
||||||
|
#endif
|
||||||
spin_unlock_irqrestore(&uart->port.lock, flags);
|
spin_unlock_irqrestore(&uart->port.lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,9 +528,13 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
|
||||||
if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
|
if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
|
||||||
clear_dma_irqstat(uart->tx_dma_channel);
|
clear_dma_irqstat(uart->tx_dma_channel);
|
||||||
disable_dma(uart->tx_dma_channel);
|
disable_dma(uart->tx_dma_channel);
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
UART_CLEAR_IER(uart, ETBEI);
|
||||||
|
#else
|
||||||
ier = UART_GET_IER(uart);
|
ier = UART_GET_IER(uart);
|
||||||
ier &= ~ETBEI;
|
ier &= ~ETBEI;
|
||||||
UART_PUT_IER(uart, ier);
|
UART_PUT_IER(uart, ier);
|
||||||
|
#endif
|
||||||
xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1);
|
xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1);
|
||||||
uart->port.icount.tx+=uart->tx_count;
|
uart->port.icount.tx+=uart->tx_count;
|
||||||
|
|
||||||
|
@ -665,7 +716,11 @@ static int bfin_serial_startup(struct uart_port *port)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
UART_SET_IER(uart, ERBFI);
|
||||||
|
#else
|
||||||
UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
|
UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,29 +811,41 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
|
|
||||||
/* Disable UART */
|
/* Disable UART */
|
||||||
ier = UART_GET_IER(uart);
|
ier = UART_GET_IER(uart);
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
UART_CLEAR_IER(uart, 0xF);
|
||||||
|
#else
|
||||||
UART_PUT_IER(uart, 0);
|
UART_PUT_IER(uart, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_BF54x
|
||||||
/* Set DLAB in LCR to Access DLL and DLH */
|
/* Set DLAB in LCR to Access DLL and DLH */
|
||||||
val = UART_GET_LCR(uart);
|
val = UART_GET_LCR(uart);
|
||||||
val |= DLAB;
|
val |= DLAB;
|
||||||
UART_PUT_LCR(uart, val);
|
UART_PUT_LCR(uart, val);
|
||||||
SSYNC();
|
SSYNC();
|
||||||
|
#endif
|
||||||
|
|
||||||
UART_PUT_DLL(uart, quot & 0xFF);
|
UART_PUT_DLL(uart, quot & 0xFF);
|
||||||
SSYNC();
|
SSYNC();
|
||||||
UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
|
UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
|
||||||
SSYNC();
|
SSYNC();
|
||||||
|
|
||||||
|
#ifndef CONFIG_BF54x
|
||||||
/* Clear DLAB in LCR to Access THR RBR IER */
|
/* Clear DLAB in LCR to Access THR RBR IER */
|
||||||
val = UART_GET_LCR(uart);
|
val = UART_GET_LCR(uart);
|
||||||
val &= ~DLAB;
|
val &= ~DLAB;
|
||||||
UART_PUT_LCR(uart, val);
|
UART_PUT_LCR(uart, val);
|
||||||
SSYNC();
|
SSYNC();
|
||||||
|
#endif
|
||||||
|
|
||||||
UART_PUT_LCR(uart, lcr);
|
UART_PUT_LCR(uart, lcr);
|
||||||
|
|
||||||
/* Enable UART */
|
/* Enable UART */
|
||||||
|
#ifdef CONFIG_BF54x
|
||||||
|
UART_SET_IER(uart, ier);
|
||||||
|
#else
|
||||||
UART_PUT_IER(uart, ier);
|
UART_PUT_IER(uart, ier);
|
||||||
|
#endif
|
||||||
|
|
||||||
val = UART_GET_GCTL(uart);
|
val = UART_GET_GCTL(uart);
|
||||||
val |= UCEN;
|
val |= UCEN;
|
||||||
|
@ -890,15 +957,15 @@ static void __init bfin_serial_init_ports(void)
|
||||||
bfin_serial_resource[i].uart_rts_pin;
|
bfin_serial_resource[i].uart_rts_pin;
|
||||||
#endif
|
#endif
|
||||||
bfin_serial_hw_init(&bfin_serial_ports[i]);
|
bfin_serial_hw_init(&bfin_serial_ports[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_BFIN_CONSOLE
|
#ifdef CONFIG_SERIAL_BFIN_CONSOLE
|
||||||
static void bfin_serial_console_putchar(struct uart_port *port, int ch)
|
static void bfin_serial_console_putchar(struct uart_port *port, int ch)
|
||||||
{
|
{
|
||||||
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
|
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
|
||||||
while (!(UART_GET_LSR(uart)))
|
while (!(UART_GET_LSR(uart) & THRE))
|
||||||
barrier();
|
barrier();
|
||||||
UART_PUT_CHAR(uart, ch);
|
UART_PUT_CHAR(uart, ch);
|
||||||
SSYNC();
|
SSYNC();
|
||||||
|
@ -950,18 +1017,22 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
|
||||||
case 2: *bits = 7; break;
|
case 2: *bits = 7; break;
|
||||||
case 3: *bits = 8; break;
|
case 3: *bits = 8; break;
|
||||||
}
|
}
|
||||||
|
#ifndef CONFIG_BF54x
|
||||||
/* Set DLAB in LCR to Access DLL and DLH */
|
/* Set DLAB in LCR to Access DLL and DLH */
|
||||||
val = UART_GET_LCR(uart);
|
val = UART_GET_LCR(uart);
|
||||||
val |= DLAB;
|
val |= DLAB;
|
||||||
UART_PUT_LCR(uart, val);
|
UART_PUT_LCR(uart, val);
|
||||||
|
#endif
|
||||||
|
|
||||||
dll = UART_GET_DLL(uart);
|
dll = UART_GET_DLL(uart);
|
||||||
dlh = UART_GET_DLH(uart);
|
dlh = UART_GET_DLH(uart);
|
||||||
|
|
||||||
|
#ifndef CONFIG_BF54x
|
||||||
/* Clear DLAB in LCR to Access THR RBR IER */
|
/* Clear DLAB in LCR to Access THR RBR IER */
|
||||||
val = UART_GET_LCR(uart);
|
val = UART_GET_LCR(uart);
|
||||||
val &= ~DLAB;
|
val &= ~DLAB;
|
||||||
UART_PUT_LCR(uart, val);
|
UART_PUT_LCR(uart, val);
|
||||||
|
#endif
|
||||||
|
|
||||||
*baud = get_sclk() / (16*(dll | dlh << 8));
|
*baud = get_sclk() / (16*(dll | dlh << 8));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue