diff options
Diffstat (limited to 'drivers/serial/bfin_5xx.c')
-rw-r--r-- | drivers/serial/bfin_5xx.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 22569bd5d821..f7926dc7fa78 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -41,6 +41,11 @@ | |||
41 | #include <linux/tty_flip.h> | 41 | #include <linux/tty_flip.h> |
42 | #include <linux/serial_core.h> | 42 | #include <linux/serial_core.h> |
43 | 43 | ||
44 | #ifdef CONFIG_KGDB_UART | ||
45 | #include <linux/kgdb.h> | ||
46 | #include <asm/irq_regs.h> | ||
47 | #endif | ||
48 | |||
44 | #include <asm/gpio.h> | 49 | #include <asm/gpio.h> |
45 | #include <asm/mach/bfin_serial_5xx.h> | 50 | #include <asm/mach/bfin_serial_5xx.h> |
46 | 51 | ||
@@ -119,6 +124,9 @@ static void bfin_serial_stop_rx(struct uart_port *port) | |||
119 | unsigned short ier; | 124 | unsigned short ier; |
120 | 125 | ||
121 | ier = UART_GET_IER(uart); | 126 | ier = UART_GET_IER(uart); |
127 | #ifdef CONFIG_KGDB_UART | ||
128 | if (uart->port.line != CONFIG_KGDB_UART_PORT) | ||
129 | #endif | ||
122 | ier &= ~ERBFI; | 130 | ier &= ~ERBFI; |
123 | UART_PUT_IER(uart, ier); | 131 | UART_PUT_IER(uart, ier); |
124 | } | 132 | } |
@@ -130,6 +138,49 @@ static void bfin_serial_enable_ms(struct uart_port *port) | |||
130 | { | 138 | { |
131 | } | 139 | } |
132 | 140 | ||
141 | #ifdef CONFIG_KGDB_UART | ||
142 | static int kgdb_entry_state; | ||
143 | |||
144 | void kgdb_put_debug_char(int chr) | ||
145 | { | ||
146 | struct bfin_serial_port *uart; | ||
147 | |||
148 | if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS) | ||
149 | uart = &bfin_serial_ports[0]; | ||
150 | else | ||
151 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | ||
152 | |||
153 | while (!(UART_GET_LSR(uart) & THRE)) { | ||
154 | __builtin_bfin_ssync(); | ||
155 | } | ||
156 | UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB)); | ||
157 | __builtin_bfin_ssync(); | ||
158 | UART_PUT_CHAR(uart, (unsigned char)chr); | ||
159 | __builtin_bfin_ssync(); | ||
160 | } | ||
161 | |||
162 | int kgdb_get_debug_char(void) | ||
163 | { | ||
164 | struct bfin_serial_port *uart; | ||
165 | unsigned char chr; | ||
166 | |||
167 | if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS) | ||
168 | uart = &bfin_serial_ports[0]; | ||
169 | else | ||
170 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | ||
171 | |||
172 | while(!(UART_GET_LSR(uart) & DR)) { | ||
173 | __builtin_bfin_ssync(); | ||
174 | } | ||
175 | UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB)); | ||
176 | __builtin_bfin_ssync(); | ||
177 | chr = UART_GET_CHAR(uart); | ||
178 | __builtin_bfin_ssync(); | ||
179 | |||
180 | return chr; | ||
181 | } | ||
182 | #endif | ||
183 | |||
133 | #ifdef CONFIG_SERIAL_BFIN_PIO | 184 | #ifdef CONFIG_SERIAL_BFIN_PIO |
134 | static void local_put_char(struct bfin_serial_port *uart, char ch) | 185 | static void local_put_char(struct bfin_serial_port *uart, char ch) |
135 | { | 186 | { |
@@ -152,6 +203,9 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
152 | { | 203 | { |
153 | struct tty_struct *tty = uart->port.info->tty; | 204 | struct tty_struct *tty = uart->port.info->tty; |
154 | unsigned int status, ch, flg; | 205 | unsigned int status, ch, flg; |
206 | #ifdef CONFIG_KGDB_UART | ||
207 | struct pt_regs *regs = get_irq_regs(); | ||
208 | #endif | ||
155 | #ifdef BF533_FAMILY | 209 | #ifdef BF533_FAMILY |
156 | static int in_break = 0; | 210 | static int in_break = 0; |
157 | #endif | 211 | #endif |
@@ -160,6 +214,27 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
160 | ch = UART_GET_CHAR(uart); | 214 | ch = UART_GET_CHAR(uart); |
161 | uart->port.icount.rx++; | 215 | uart->port.icount.rx++; |
162 | 216 | ||
217 | #ifdef CONFIG_KGDB_UART | ||
218 | if (uart->port.line == CONFIG_KGDB_UART_PORT) { | ||
219 | if (uart->port.cons->index == CONFIG_KGDB_UART_PORT && ch == 0x1) { /* Ctrl + A */ | ||
220 | kgdb_breakkey_pressed(regs); | ||
221 | return; | ||
222 | } else if (kgdb_entry_state == 0 && ch == '$') {/* connection from KGDB */ | ||
223 | kgdb_entry_state = 1; | ||
224 | } else if (kgdb_entry_state == 1 && ch == 'q') { | ||
225 | kgdb_entry_state = 0; | ||
226 | kgdb_breakkey_pressed(regs); | ||
227 | return; | ||
228 | } else if (ch == 0x3) {/* Ctrl + C */ | ||
229 | kgdb_entry_state = 0; | ||
230 | kgdb_breakkey_pressed(regs); | ||
231 | return; | ||
232 | } else { | ||
233 | kgdb_entry_state = 0; | ||
234 | } | ||
235 | } | ||
236 | #endif | ||
237 | |||
163 | #ifdef BF533_FAMILY | 238 | #ifdef BF533_FAMILY |
164 | /* The BF533 family of processors have a nice misbehavior where | 239 | /* The BF533 family of processors have a nice misbehavior where |
165 | * they continuously generate characters for a "single" break. | 240 | * they continuously generate characters for a "single" break. |
@@ -571,7 +646,11 @@ static int bfin_serial_startup(struct uart_port *port) | |||
571 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; | 646 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; |
572 | add_timer(&(uart->rx_dma_timer)); | 647 | add_timer(&(uart->rx_dma_timer)); |
573 | #else | 648 | #else |
649 | # ifdef CONFIG_KGDB_UART | ||
650 | if (uart->port.line != CONFIG_KGDB_UART_PORT && request_irq | ||
651 | # else | ||
574 | if (request_irq | 652 | if (request_irq |
653 | # endif | ||
575 | (uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, | 654 | (uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, |
576 | "BFIN_UART_RX", uart)) { | 655 | "BFIN_UART_RX", uart)) { |
577 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); | 656 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); |
@@ -601,6 +680,9 @@ static void bfin_serial_shutdown(struct uart_port *port) | |||
601 | free_dma(uart->rx_dma_channel); | 680 | free_dma(uart->rx_dma_channel); |
602 | del_timer(&(uart->rx_dma_timer)); | 681 | del_timer(&(uart->rx_dma_timer)); |
603 | #else | 682 | #else |
683 | #ifdef CONFIG_KGDB_UART | ||
684 | if (uart->port.line != CONFIG_KGDB_UART_PORT) | ||
685 | #endif | ||
604 | free_irq(uart->port.irq, uart); | 686 | free_irq(uart->port.irq, uart); |
605 | free_irq(uart->port.irq+1, uart); | 687 | free_irq(uart->port.irq+1, uart); |
606 | #endif | 688 | #endif |
@@ -931,6 +1013,10 @@ static int __init bfin_serial_rs_console_init(void) | |||
931 | { | 1013 | { |
932 | bfin_serial_init_ports(); | 1014 | bfin_serial_init_ports(); |
933 | register_console(&bfin_serial_console); | 1015 | register_console(&bfin_serial_console); |
1016 | #ifdef CONFIG_KGDB_UART | ||
1017 | kgdb_entry_state = 0; | ||
1018 | init_kgdb_uart(); | ||
1019 | #endif | ||
934 | return 0; | 1020 | return 0; |
935 | } | 1021 | } |
936 | console_initcall(bfin_serial_rs_console_init); | 1022 | console_initcall(bfin_serial_rs_console_init); |
@@ -1023,6 +1109,10 @@ static struct platform_driver bfin_serial_driver = { | |||
1023 | static int __init bfin_serial_init(void) | 1109 | static int __init bfin_serial_init(void) |
1024 | { | 1110 | { |
1025 | int ret; | 1111 | int ret; |
1112 | #ifdef CONFIG_KGDB_UART | ||
1113 | struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | ||
1114 | struct termios t; | ||
1115 | #endif | ||
1026 | 1116 | ||
1027 | pr_info("Serial: Blackfin serial driver\n"); | 1117 | pr_info("Serial: Blackfin serial driver\n"); |
1028 | 1118 | ||
@@ -1036,6 +1126,21 @@ static int __init bfin_serial_init(void) | |||
1036 | uart_unregister_driver(&bfin_serial_reg); | 1126 | uart_unregister_driver(&bfin_serial_reg); |
1037 | } | 1127 | } |
1038 | } | 1128 | } |
1129 | #ifdef CONFIG_KGDB_UART | ||
1130 | if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) { | ||
1131 | request_irq(uart->port.irq, bfin_serial_int, | ||
1132 | IRQF_DISABLED, "BFIN_UART_RX", uart); | ||
1133 | pr_info("Request irq for kgdb uart port\n"); | ||
1134 | UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI); | ||
1135 | __builtin_bfin_ssync(); | ||
1136 | t.c_cflag = CS8|B57600; | ||
1137 | t.c_iflag = 0; | ||
1138 | t.c_oflag = 0; | ||
1139 | t.c_lflag = ICANON; | ||
1140 | t.c_line = CONFIG_KGDB_UART_PORT; | ||
1141 | bfin_serial_set_termios(&uart->port, &t, &t); | ||
1142 | } | ||
1143 | #endif | ||
1039 | return ret; | 1144 | return ret; |
1040 | } | 1145 | } |
1041 | 1146 | ||