mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
Blackfin Serial Driver: updates kgdb over Blackfin serial driver with kgdb framework
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
b58602a4ba
commit
52e15f0eae
1 changed files with 89 additions and 98 deletions
|
@ -22,7 +22,8 @@
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
|
|
||||||
#ifdef CONFIG_KGDB_UART
|
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
|
||||||
|
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
|
||||||
#include <linux/kgdb.h>
|
#include <linux/kgdb.h>
|
||||||
#include <asm/irq_regs.h>
|
#include <asm/irq_regs.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,6 +46,16 @@
|
||||||
static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
|
static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
|
||||||
static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource);
|
static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource);
|
||||||
|
|
||||||
|
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
|
||||||
|
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
|
||||||
|
|
||||||
|
# ifndef CONFIG_SERIAL_BFIN_PIO
|
||||||
|
# error KGDB only support UART in PIO mode.
|
||||||
|
# endif
|
||||||
|
|
||||||
|
static int kgdboc_port_line;
|
||||||
|
static int kgdboc_break_enabled;
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Setup for console. Argument comes from the menuconfig
|
* Setup for console. Argument comes from the menuconfig
|
||||||
*/
|
*/
|
||||||
|
@ -110,9 +121,7 @@ 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_KGDB_UART
|
|
||||||
if (uart->port.line != CONFIG_KGDB_UART_PORT)
|
|
||||||
#endif
|
|
||||||
UART_CLEAR_IER(uart, ERBFI);
|
UART_CLEAR_IER(uart, ERBFI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,49 +132,6 @@ static void bfin_serial_enable_ms(struct uart_port *port)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KGDB_UART
|
|
||||||
static int kgdb_entry_state;
|
|
||||||
|
|
||||||
void kgdb_put_debug_char(int chr)
|
|
||||||
{
|
|
||||||
struct bfin_serial_port *uart;
|
|
||||||
|
|
||||||
if (CONFIG_KGDB_UART_PORT < 0
|
|
||||||
|| CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
|
|
||||||
uart = &bfin_serial_ports[0];
|
|
||||||
else
|
|
||||||
uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
|
|
||||||
|
|
||||||
while (!(UART_GET_LSR(uart) & THRE)) {
|
|
||||||
SSYNC();
|
|
||||||
}
|
|
||||||
|
|
||||||
UART_CLEAR_DLAB(uart);
|
|
||||||
UART_PUT_CHAR(uart, (unsigned char)chr);
|
|
||||||
SSYNC();
|
|
||||||
}
|
|
||||||
|
|
||||||
int kgdb_get_debug_char(void)
|
|
||||||
{
|
|
||||||
struct bfin_serial_port *uart;
|
|
||||||
unsigned char chr;
|
|
||||||
|
|
||||||
if (CONFIG_KGDB_UART_PORT < 0
|
|
||||||
|| CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
|
|
||||||
uart = &bfin_serial_ports[0];
|
|
||||||
else
|
|
||||||
uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
|
|
||||||
|
|
||||||
while(!(UART_GET_LSR(uart) & DR)) {
|
|
||||||
SSYNC();
|
|
||||||
}
|
|
||||||
UART_CLEAR_DLAB(uart);
|
|
||||||
chr = UART_GET_CHAR(uart);
|
|
||||||
SSYNC();
|
|
||||||
|
|
||||||
return chr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
|
#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
|
||||||
# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
|
# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
|
||||||
|
@ -178,7 +144,7 @@ int kgdb_get_debug_char(void)
|
||||||
#ifdef CONFIG_SERIAL_BFIN_PIO
|
#ifdef CONFIG_SERIAL_BFIN_PIO
|
||||||
static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
|
static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
|
||||||
{
|
{
|
||||||
struct tty_struct *tty = uart->port.info->port.tty;
|
struct tty_struct *tty = NULL;
|
||||||
unsigned int status, ch, flg;
|
unsigned int status, ch, flg;
|
||||||
static struct timeval anomaly_start = { .tv_sec = 0 };
|
static struct timeval anomaly_start = { .tv_sec = 0 };
|
||||||
|
|
||||||
|
@ -188,27 +154,18 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
|
||||||
ch = UART_GET_CHAR(uart);
|
ch = UART_GET_CHAR(uart);
|
||||||
uart->port.icount.rx++;
|
uart->port.icount.rx++;
|
||||||
|
|
||||||
#ifdef CONFIG_KGDB_UART
|
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
|
||||||
if (uart->port.line == CONFIG_KGDB_UART_PORT) {
|
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
|
||||||
struct pt_regs *regs = get_irq_regs();
|
if (kgdb_connected && kgdboc_port_line == uart->port.line)
|
||||||
if (uart->port.cons->index == CONFIG_KGDB_UART_PORT && ch == 0x1) { /* Ctrl + A */
|
if (ch == 0x3) {/* Ctrl + C */
|
||||||
kgdb_breakkey_pressed(regs);
|
kgdb_breakpoint();
|
||||||
return;
|
return;
|
||||||
} else if (kgdb_entry_state == 0 && ch == '$') {/* connection from KGDB */
|
|
||||||
kgdb_entry_state = 1;
|
|
||||||
} else if (kgdb_entry_state == 1 && ch == 'q') {
|
|
||||||
kgdb_entry_state = 0;
|
|
||||||
kgdb_breakkey_pressed(regs);
|
|
||||||
return;
|
|
||||||
} else if (ch == 0x3) {/* Ctrl + C */
|
|
||||||
kgdb_entry_state = 0;
|
|
||||||
kgdb_breakkey_pressed(regs);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
kgdb_entry_state = 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!uart->port.info || !uart->port.info->tty)
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
tty = uart->port.info->tty;
|
||||||
|
|
||||||
if (ANOMALY_05000363) {
|
if (ANOMALY_05000363) {
|
||||||
/* The BF533 (and BF561) family of processors have a nice anomaly
|
/* The BF533 (and BF561) family of processors have a nice anomaly
|
||||||
|
@ -630,16 +587,16 @@ static int bfin_serial_startup(struct uart_port *port)
|
||||||
uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
|
uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
|
||||||
add_timer(&(uart->rx_dma_timer));
|
add_timer(&(uart->rx_dma_timer));
|
||||||
#else
|
#else
|
||||||
|
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
|
||||||
|
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
|
||||||
|
if (kgdboc_port_line == uart->port.line && kgdboc_break_enabled)
|
||||||
|
kgdboc_break_enabled = 0;
|
||||||
|
else {
|
||||||
|
# endif
|
||||||
if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,
|
if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,
|
||||||
"BFIN_UART_RX", uart)) {
|
"BFIN_UART_RX", uart)) {
|
||||||
# ifdef CONFIG_KGDB_UART
|
|
||||||
if (uart->port.line != CONFIG_KGDB_UART_PORT) {
|
|
||||||
# endif
|
|
||||||
printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
|
printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
# ifdef CONFIG_KGDB_UART
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request_irq
|
if (request_irq
|
||||||
|
@ -685,6 +642,10 @@ static int bfin_serial_startup(struct uart_port *port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
|
||||||
|
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
|
||||||
|
}
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
UART_SET_IER(uart, ERBFI);
|
UART_SET_IER(uart, ERBFI);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -715,9 +676,6 @@ static void bfin_serial_shutdown(struct uart_port *port)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_KGDB_UART
|
|
||||||
if (uart->port.line != CONFIG_KGDB_UART_PORT)
|
|
||||||
#endif
|
#endif
|
||||||
free_irq(uart->port.irq, uart);
|
free_irq(uart->port.irq, uart);
|
||||||
free_irq(uart->port.irq+1, uart);
|
free_irq(uart->port.irq+1, uart);
|
||||||
|
@ -887,6 +845,51 @@ static void bfin_serial_set_ldisc(struct uart_port *port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr)
|
||||||
|
{
|
||||||
|
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
|
||||||
|
|
||||||
|
while (!(UART_GET_LSR(uart) & THRE))
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
UART_CLEAR_DLAB(uart);
|
||||||
|
UART_PUT_CHAR(uart, (unsigned char)chr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bfin_serial_poll_get_char(struct uart_port *port)
|
||||||
|
{
|
||||||
|
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
|
||||||
|
unsigned char chr;
|
||||||
|
|
||||||
|
while (!(UART_GET_LSR(uart) & DR))
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
UART_CLEAR_DLAB(uart);
|
||||||
|
chr = UART_GET_CHAR(uart);
|
||||||
|
|
||||||
|
return chr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
|
||||||
|
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
|
||||||
|
static void bfin_kgdboc_port_shutdown(struct uart_port *port)
|
||||||
|
{
|
||||||
|
if (kgdboc_break_enabled) {
|
||||||
|
kgdboc_break_enabled = 0;
|
||||||
|
bfin_serial_shutdown(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bfin_kgdboc_port_startup(struct uart_port *port)
|
||||||
|
{
|
||||||
|
kgdboc_port_line = port->line;
|
||||||
|
kgdboc_break_enabled = !bfin_serial_startup(port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct uart_ops bfin_serial_pops = {
|
static struct uart_ops bfin_serial_pops = {
|
||||||
.tx_empty = bfin_serial_tx_empty,
|
.tx_empty = bfin_serial_tx_empty,
|
||||||
.set_mctrl = bfin_serial_set_mctrl,
|
.set_mctrl = bfin_serial_set_mctrl,
|
||||||
|
@ -905,6 +908,15 @@ static struct uart_ops bfin_serial_pops = {
|
||||||
.request_port = bfin_serial_request_port,
|
.request_port = bfin_serial_request_port,
|
||||||
.config_port = bfin_serial_config_port,
|
.config_port = bfin_serial_config_port,
|
||||||
.verify_port = bfin_serial_verify_port,
|
.verify_port = bfin_serial_verify_port,
|
||||||
|
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
|
||||||
|
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
|
||||||
|
.kgdboc_port_startup = bfin_kgdboc_port_startup,
|
||||||
|
.kgdboc_port_shutdown = bfin_kgdboc_port_shutdown,
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
.poll_put_char = bfin_serial_poll_put_char,
|
||||||
|
.poll_get_char = bfin_serial_poll_get_char,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init bfin_serial_init_ports(void)
|
static void __init bfin_serial_init_ports(void)
|
||||||
|
@ -1076,10 +1088,7 @@ static int __init bfin_serial_rs_console_init(void)
|
||||||
{
|
{
|
||||||
bfin_serial_init_ports();
|
bfin_serial_init_ports();
|
||||||
register_console(&bfin_serial_console);
|
register_console(&bfin_serial_console);
|
||||||
#ifdef CONFIG_KGDB_UART
|
|
||||||
kgdb_entry_state = 0;
|
|
||||||
init_kgdb_uart();
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
console_initcall(bfin_serial_rs_console_init);
|
console_initcall(bfin_serial_rs_console_init);
|
||||||
|
@ -1235,10 +1244,6 @@ static struct platform_driver bfin_serial_driver = {
|
||||||
static int __init bfin_serial_init(void)
|
static int __init bfin_serial_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
#ifdef CONFIG_KGDB_UART
|
|
||||||
struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
|
|
||||||
struct ktermios t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pr_info("Serial: Blackfin serial driver\n");
|
pr_info("Serial: Blackfin serial driver\n");
|
||||||
|
|
||||||
|
@ -1252,21 +1257,6 @@ static int __init bfin_serial_init(void)
|
||||||
uart_unregister_driver(&bfin_serial_reg);
|
uart_unregister_driver(&bfin_serial_reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_KGDB_UART
|
|
||||||
if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) {
|
|
||||||
request_irq(uart->port.irq, bfin_serial_rx_int,
|
|
||||||
IRQF_DISABLED, "BFIN_UART_RX", uart);
|
|
||||||
pr_info("Request irq for kgdb uart port\n");
|
|
||||||
UART_SET_IER(uart, ERBFI);
|
|
||||||
SSYNC();
|
|
||||||
t.c_cflag = CS8|B57600;
|
|
||||||
t.c_iflag = 0;
|
|
||||||
t.c_oflag = 0;
|
|
||||||
t.c_lflag = ICANON;
|
|
||||||
t.c_line = CONFIG_KGDB_UART_PORT;
|
|
||||||
bfin_serial_set_termios(&uart->port, &t, &t);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1276,6 +1266,7 @@ static void __exit bfin_serial_exit(void)
|
||||||
uart_unregister_driver(&bfin_serial_reg);
|
uart_unregister_driver(&bfin_serial_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module_init(bfin_serial_init);
|
module_init(bfin_serial_init);
|
||||||
module_exit(bfin_serial_exit);
|
module_exit(bfin_serial_exit);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue