diff options
author | Sonic Zhang <sonic.zhang@analog.com> | 2009-01-02 08:40:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:34 -0500 |
commit | 52e15f0eae193a8e4ca31c1520179b8d65c79811 (patch) | |
tree | b904fe05f51100d94477a6cb38ea621f4732bf8f /drivers/serial | |
parent | b58602a4bac012b5f4fc12fe6b46ab237b610d5d (diff) |
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>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/bfin_5xx.c | 187 |
1 files changed, 89 insertions, 98 deletions
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 569f0e2476c6..d63fad7363b7 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -22,7 +22,8 @@ | |||
22 | #include <linux/tty_flip.h> | 22 | #include <linux/tty_flip.h> |
23 | #include <linux/serial_core.h> | 23 | #include <linux/serial_core.h> |
24 | 24 | ||
25 | #ifdef CONFIG_KGDB_UART | 25 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ |
26 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
26 | #include <linux/kgdb.h> | 27 | #include <linux/kgdb.h> |
27 | #include <asm/irq_regs.h> | 28 | #include <asm/irq_regs.h> |
28 | #endif | 29 | #endif |
@@ -45,6 +46,16 @@ | |||
45 | static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; | 46 | static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; |
46 | static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource); | 47 | static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource); |
47 | 48 | ||
49 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
50 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
51 | |||
52 | # ifndef CONFIG_SERIAL_BFIN_PIO | ||
53 | # error KGDB only support UART in PIO mode. | ||
54 | # endif | ||
55 | |||
56 | static int kgdboc_port_line; | ||
57 | static int kgdboc_break_enabled; | ||
58 | #endif | ||
48 | /* | 59 | /* |
49 | * Setup for console. Argument comes from the menuconfig | 60 | * Setup for console. Argument comes from the menuconfig |
50 | */ | 61 | */ |
@@ -110,9 +121,7 @@ static void bfin_serial_start_tx(struct uart_port *port) | |||
110 | static void bfin_serial_stop_rx(struct uart_port *port) | 121 | static void bfin_serial_stop_rx(struct uart_port *port) |
111 | { | 122 | { |
112 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 123 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
113 | #ifdef CONFIG_KGDB_UART | 124 | |
114 | if (uart->port.line != CONFIG_KGDB_UART_PORT) | ||
115 | #endif | ||
116 | UART_CLEAR_IER(uart, ERBFI); | 125 | UART_CLEAR_IER(uart, ERBFI); |
117 | } | 126 | } |
118 | 127 | ||
@@ -123,49 +132,6 @@ static void bfin_serial_enable_ms(struct uart_port *port) | |||
123 | { | 132 | { |
124 | } | 133 | } |
125 | 134 | ||
126 | #ifdef CONFIG_KGDB_UART | ||
127 | static int kgdb_entry_state; | ||
128 | |||
129 | void kgdb_put_debug_char(int chr) | ||
130 | { | ||
131 | struct bfin_serial_port *uart; | ||
132 | |||
133 | if (CONFIG_KGDB_UART_PORT < 0 | ||
134 | || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS) | ||
135 | uart = &bfin_serial_ports[0]; | ||
136 | else | ||
137 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | ||
138 | |||
139 | while (!(UART_GET_LSR(uart) & THRE)) { | ||
140 | SSYNC(); | ||
141 | } | ||
142 | |||
143 | UART_CLEAR_DLAB(uart); | ||
144 | UART_PUT_CHAR(uart, (unsigned char)chr); | ||
145 | SSYNC(); | ||
146 | } | ||
147 | |||
148 | int kgdb_get_debug_char(void) | ||
149 | { | ||
150 | struct bfin_serial_port *uart; | ||
151 | unsigned char chr; | ||
152 | |||
153 | if (CONFIG_KGDB_UART_PORT < 0 | ||
154 | || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS) | ||
155 | uart = &bfin_serial_ports[0]; | ||
156 | else | ||
157 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | ||
158 | |||
159 | while(!(UART_GET_LSR(uart) & DR)) { | ||
160 | SSYNC(); | ||
161 | } | ||
162 | UART_CLEAR_DLAB(uart); | ||
163 | chr = UART_GET_CHAR(uart); | ||
164 | SSYNC(); | ||
165 | |||
166 | return chr; | ||
167 | } | ||
168 | #endif | ||
169 | 135 | ||
170 | #if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO) | 136 | #if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO) |
171 | # define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold) | 137 | # define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold) |
@@ -178,7 +144,7 @@ int kgdb_get_debug_char(void) | |||
178 | #ifdef CONFIG_SERIAL_BFIN_PIO | 144 | #ifdef CONFIG_SERIAL_BFIN_PIO |
179 | static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | 145 | static void bfin_serial_rx_chars(struct bfin_serial_port *uart) |
180 | { | 146 | { |
181 | struct tty_struct *tty = uart->port.info->port.tty; | 147 | struct tty_struct *tty = NULL; |
182 | unsigned int status, ch, flg; | 148 | unsigned int status, ch, flg; |
183 | static struct timeval anomaly_start = { .tv_sec = 0 }; | 149 | static struct timeval anomaly_start = { .tv_sec = 0 }; |
184 | 150 | ||
@@ -188,27 +154,18 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
188 | ch = UART_GET_CHAR(uart); | 154 | ch = UART_GET_CHAR(uart); |
189 | uart->port.icount.rx++; | 155 | uart->port.icount.rx++; |
190 | 156 | ||
191 | #ifdef CONFIG_KGDB_UART | 157 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ |
192 | if (uart->port.line == CONFIG_KGDB_UART_PORT) { | 158 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) |
193 | struct pt_regs *regs = get_irq_regs(); | 159 | if (kgdb_connected && kgdboc_port_line == uart->port.line) |
194 | if (uart->port.cons->index == CONFIG_KGDB_UART_PORT && ch == 0x1) { /* Ctrl + A */ | 160 | if (ch == 0x3) {/* Ctrl + C */ |
195 | kgdb_breakkey_pressed(regs); | 161 | kgdb_breakpoint(); |
196 | return; | ||
197 | } else if (kgdb_entry_state == 0 && ch == '$') {/* connection from KGDB */ | ||
198 | kgdb_entry_state = 1; | ||
199 | } else if (kgdb_entry_state == 1 && ch == 'q') { | ||
200 | kgdb_entry_state = 0; | ||
201 | kgdb_breakkey_pressed(regs); | ||
202 | return; | 162 | return; |
203 | } else if (ch == 0x3) {/* Ctrl + C */ | ||
204 | kgdb_entry_state = 0; | ||
205 | kgdb_breakkey_pressed(regs); | ||
206 | return; | ||
207 | } else { | ||
208 | kgdb_entry_state = 0; | ||
209 | } | 163 | } |
210 | } | 164 | |
165 | if (!uart->port.info || !uart->port.info->tty) | ||
166 | return; | ||
211 | #endif | 167 | #endif |
168 | tty = uart->port.info->tty; | ||
212 | 169 | ||
213 | if (ANOMALY_05000363) { | 170 | if (ANOMALY_05000363) { |
214 | /* The BF533 (and BF561) family of processors have a nice anomaly | 171 | /* The BF533 (and BF561) family of processors have a nice anomaly |
@@ -630,16 +587,16 @@ static int bfin_serial_startup(struct uart_port *port) | |||
630 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; | 587 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; |
631 | add_timer(&(uart->rx_dma_timer)); | 588 | add_timer(&(uart->rx_dma_timer)); |
632 | #else | 589 | #else |
590 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
591 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
592 | if (kgdboc_port_line == uart->port.line && kgdboc_break_enabled) | ||
593 | kgdboc_break_enabled = 0; | ||
594 | else { | ||
595 | # endif | ||
633 | if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, | 596 | if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, |
634 | "BFIN_UART_RX", uart)) { | 597 | "BFIN_UART_RX", uart)) { |
635 | # ifdef CONFIG_KGDB_UART | ||
636 | if (uart->port.line != CONFIG_KGDB_UART_PORT) { | ||
637 | # endif | ||
638 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); | 598 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); |
639 | return -EBUSY; | 599 | return -EBUSY; |
640 | # ifdef CONFIG_KGDB_UART | ||
641 | } | ||
642 | # endif | ||
643 | } | 600 | } |
644 | 601 | ||
645 | if (request_irq | 602 | if (request_irq |
@@ -685,6 +642,10 @@ static int bfin_serial_startup(struct uart_port *port) | |||
685 | } | 642 | } |
686 | } | 643 | } |
687 | # endif | 644 | # endif |
645 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
646 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
647 | } | ||
648 | # endif | ||
688 | #endif | 649 | #endif |
689 | UART_SET_IER(uart, ERBFI); | 650 | UART_SET_IER(uart, ERBFI); |
690 | return 0; | 651 | return 0; |
@@ -716,9 +677,6 @@ static void bfin_serial_shutdown(struct uart_port *port) | |||
716 | break; | 677 | break; |
717 | }; | 678 | }; |
718 | #endif | 679 | #endif |
719 | #ifdef CONFIG_KGDB_UART | ||
720 | if (uart->port.line != CONFIG_KGDB_UART_PORT) | ||
721 | #endif | ||
722 | free_irq(uart->port.irq, uart); | 680 | free_irq(uart->port.irq, uart); |
723 | free_irq(uart->port.irq+1, uart); | 681 | free_irq(uart->port.irq+1, uart); |
724 | #endif | 682 | #endif |
@@ -887,6 +845,51 @@ static void bfin_serial_set_ldisc(struct uart_port *port) | |||
887 | } | 845 | } |
888 | } | 846 | } |
889 | 847 | ||
848 | #ifdef CONFIG_CONSOLE_POLL | ||
849 | static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr) | ||
850 | { | ||
851 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | ||
852 | |||
853 | while (!(UART_GET_LSR(uart) & THRE)) | ||
854 | cpu_relax(); | ||
855 | |||
856 | UART_CLEAR_DLAB(uart); | ||
857 | UART_PUT_CHAR(uart, (unsigned char)chr); | ||
858 | } | ||
859 | |||
860 | static int bfin_serial_poll_get_char(struct uart_port *port) | ||
861 | { | ||
862 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | ||
863 | unsigned char chr; | ||
864 | |||
865 | while (!(UART_GET_LSR(uart) & DR)) | ||
866 | cpu_relax(); | ||
867 | |||
868 | UART_CLEAR_DLAB(uart); | ||
869 | chr = UART_GET_CHAR(uart); | ||
870 | |||
871 | return chr; | ||
872 | } | ||
873 | #endif | ||
874 | |||
875 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
876 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
877 | static void bfin_kgdboc_port_shutdown(struct uart_port *port) | ||
878 | { | ||
879 | if (kgdboc_break_enabled) { | ||
880 | kgdboc_break_enabled = 0; | ||
881 | bfin_serial_shutdown(port); | ||
882 | } | ||
883 | } | ||
884 | |||
885 | static int bfin_kgdboc_port_startup(struct uart_port *port) | ||
886 | { | ||
887 | kgdboc_port_line = port->line; | ||
888 | kgdboc_break_enabled = !bfin_serial_startup(port); | ||
889 | return 0; | ||
890 | } | ||
891 | #endif | ||
892 | |||
890 | static struct uart_ops bfin_serial_pops = { | 893 | static struct uart_ops bfin_serial_pops = { |
891 | .tx_empty = bfin_serial_tx_empty, | 894 | .tx_empty = bfin_serial_tx_empty, |
892 | .set_mctrl = bfin_serial_set_mctrl, | 895 | .set_mctrl = bfin_serial_set_mctrl, |
@@ -905,6 +908,15 @@ static struct uart_ops bfin_serial_pops = { | |||
905 | .request_port = bfin_serial_request_port, | 908 | .request_port = bfin_serial_request_port, |
906 | .config_port = bfin_serial_config_port, | 909 | .config_port = bfin_serial_config_port, |
907 | .verify_port = bfin_serial_verify_port, | 910 | .verify_port = bfin_serial_verify_port, |
911 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
912 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
913 | .kgdboc_port_startup = bfin_kgdboc_port_startup, | ||
914 | .kgdboc_port_shutdown = bfin_kgdboc_port_shutdown, | ||
915 | #endif | ||
916 | #ifdef CONFIG_CONSOLE_POLL | ||
917 | .poll_put_char = bfin_serial_poll_put_char, | ||
918 | .poll_get_char = bfin_serial_poll_get_char, | ||
919 | #endif | ||
908 | }; | 920 | }; |
909 | 921 | ||
910 | static void __init bfin_serial_init_ports(void) | 922 | static void __init bfin_serial_init_ports(void) |
@@ -1076,10 +1088,7 @@ static int __init bfin_serial_rs_console_init(void) | |||
1076 | { | 1088 | { |
1077 | bfin_serial_init_ports(); | 1089 | bfin_serial_init_ports(); |
1078 | register_console(&bfin_serial_console); | 1090 | register_console(&bfin_serial_console); |
1079 | #ifdef CONFIG_KGDB_UART | 1091 | |
1080 | kgdb_entry_state = 0; | ||
1081 | init_kgdb_uart(); | ||
1082 | #endif | ||
1083 | return 0; | 1092 | return 0; |
1084 | } | 1093 | } |
1085 | console_initcall(bfin_serial_rs_console_init); | 1094 | console_initcall(bfin_serial_rs_console_init); |
@@ -1235,10 +1244,6 @@ static struct platform_driver bfin_serial_driver = { | |||
1235 | static int __init bfin_serial_init(void) | 1244 | static int __init bfin_serial_init(void) |
1236 | { | 1245 | { |
1237 | int ret; | 1246 | int ret; |
1238 | #ifdef CONFIG_KGDB_UART | ||
1239 | struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | ||
1240 | struct ktermios t; | ||
1241 | #endif | ||
1242 | 1247 | ||
1243 | pr_info("Serial: Blackfin serial driver\n"); | 1248 | pr_info("Serial: Blackfin serial driver\n"); |
1244 | 1249 | ||
@@ -1252,21 +1257,6 @@ static int __init bfin_serial_init(void) | |||
1252 | uart_unregister_driver(&bfin_serial_reg); | 1257 | uart_unregister_driver(&bfin_serial_reg); |
1253 | } | 1258 | } |
1254 | } | 1259 | } |
1255 | #ifdef CONFIG_KGDB_UART | ||
1256 | if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) { | ||
1257 | request_irq(uart->port.irq, bfin_serial_rx_int, | ||
1258 | IRQF_DISABLED, "BFIN_UART_RX", uart); | ||
1259 | pr_info("Request irq for kgdb uart port\n"); | ||
1260 | UART_SET_IER(uart, ERBFI); | ||
1261 | SSYNC(); | ||
1262 | t.c_cflag = CS8|B57600; | ||
1263 | t.c_iflag = 0; | ||
1264 | t.c_oflag = 0; | ||
1265 | t.c_lflag = ICANON; | ||
1266 | t.c_line = CONFIG_KGDB_UART_PORT; | ||
1267 | bfin_serial_set_termios(&uart->port, &t, &t); | ||
1268 | } | ||
1269 | #endif | ||
1270 | return ret; | 1260 | return ret; |
1271 | } | 1261 | } |
1272 | 1262 | ||
@@ -1276,6 +1266,7 @@ static void __exit bfin_serial_exit(void) | |||
1276 | uart_unregister_driver(&bfin_serial_reg); | 1266 | uart_unregister_driver(&bfin_serial_reg); |
1277 | } | 1267 | } |
1278 | 1268 | ||
1269 | |||
1279 | module_init(bfin_serial_init); | 1270 | module_init(bfin_serial_init); |
1280 | module_exit(bfin_serial_exit); | 1271 | module_exit(bfin_serial_exit); |
1281 | 1272 | ||