diff options
-rw-r--r-- | Documentation/blackfin/kgdb.txt | 155 | ||||
-rw-r--r-- | arch/blackfin/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/kgdb.c | 421 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 2 | ||||
-rw-r--r-- | drivers/serial/bfin_5xx.c | 105 | ||||
-rw-r--r-- | include/asm-blackfin/kgdb.h | 183 |
6 files changed, 866 insertions, 1 deletions
diff --git a/Documentation/blackfin/kgdb.txt b/Documentation/blackfin/kgdb.txt new file mode 100644 index 000000000000..84f6a484ae9a --- /dev/null +++ b/Documentation/blackfin/kgdb.txt | |||
@@ -0,0 +1,155 @@ | |||
1 | A Simple Guide to Configure KGDB | ||
2 | |||
3 | Sonic Zhang <sonic.zhang@analog.com> | ||
4 | Aug. 24th 2006 | ||
5 | |||
6 | |||
7 | This KGDB patch enables the kernel developer to do source level debugging on | ||
8 | the kernel for the Blackfin architecture. The debugging works over either the | ||
9 | ethernet interface or one of the uarts. Both software breakpoints and | ||
10 | hardware breakpoints are supported in this version. | ||
11 | http://docs.blackfin.uclinux.org/doku.php?id=kgdb | ||
12 | |||
13 | |||
14 | 2 known issues: | ||
15 | 1. This bug: | ||
16 | http://blackfin.uclinux.org/tracker/index.php?func=detail&aid=544&group_id=18&atid=145 | ||
17 | The GDB client for Blackfin uClinux causes incorrect values of local | ||
18 | variables to be displayed when the user breaks the running of kernel in GDB. | ||
19 | 2. Because of a hardware bug in Blackfin 533 v1.0.3: | ||
20 | 05000067 - Watchpoints (Hardware Breakpoints) are not supported | ||
21 | Hardware breakpoints cannot be set properly. | ||
22 | |||
23 | |||
24 | Debug over Ethernet: | ||
25 | |||
26 | 1. Compile and install the cross platform version of gdb for blackfin, which | ||
27 | can be found at $(BINROOT)/bfin-elf-gdb. | ||
28 | |||
29 | 2. Apply this patch to the 2.6.x kernel. Select the menuconfig option under | ||
30 | "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb". | ||
31 | With this selected, option "Full Symbolic/Source Debugging support" and | ||
32 | "Compile the kernel with frame pointers" are also selected. | ||
33 | |||
34 | 3. Select option "KGDB: connect over (Ethernet)". Add "kgdboe=@target-IP/,@host-IP/" to | ||
35 | the option "Compiled-in Kernel Boot Parameter" under "Kernel hacking". | ||
36 | |||
37 | 4. Connect minicom to the serial port and boot the kernel image. | ||
38 | |||
39 | 5. Configure the IP "/> ifconfig eth0 target-IP" | ||
40 | |||
41 | 6. Start GDB client "bfin-elf-gdb vmlinux". | ||
42 | |||
43 | 7. Connect to the target "(gdb) target remote udp:target-IP:6443". | ||
44 | |||
45 | 8. Set software breakpoint "(gdb) break sys_open". | ||
46 | |||
47 | 9. Continue "(gdb) c". | ||
48 | |||
49 | 10. Run ls in the target console "/> ls". | ||
50 | |||
51 | 11. Breakpoint hits. "Breakpoint 1: sys_open(..." | ||
52 | |||
53 | 12. Display local variables and function paramters. | ||
54 | (*) This operation gives wrong results, see known issue 1. | ||
55 | |||
56 | 13. Single stepping "(gdb) si". | ||
57 | |||
58 | 14. Remove breakpoint 1. "(gdb) del 1" | ||
59 | |||
60 | 15. Set hardware breakpoint "(gdb) hbreak sys_open". | ||
61 | |||
62 | 16. Continue "(gdb) c". | ||
63 | |||
64 | 17. Run ls in the target console "/> ls". | ||
65 | |||
66 | 18. Hardware breakpoint hits. "Breakpoint 1: sys_open(...". | ||
67 | (*) This hardware breakpoint will not be hit, see known issue 2. | ||
68 | |||
69 | 19. Continue "(gdb) c". | ||
70 | |||
71 | 20. Interrupt the target in GDB "Ctrl+C". | ||
72 | |||
73 | 21. Detach from the target "(gdb) detach". | ||
74 | |||
75 | 22. Exit GDB "(gdb) quit". | ||
76 | |||
77 | |||
78 | Debug over the UART: | ||
79 | |||
80 | 1. Compile and install the cross platform version of gdb for blackfin, which | ||
81 | can be found at $(BINROOT)/bfin-elf-gdb. | ||
82 | |||
83 | 2. Apply this patch to the 2.6.x kernel. Select the menuconfig option under | ||
84 | "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb". | ||
85 | With this selected, option "Full Symbolic/Source Debugging support" and | ||
86 | "Compile the kernel with frame pointers" are also selected. | ||
87 | |||
88 | 3. Select option "KGDB: connect over (UART)". Set "KGDB: UART port number" to be | ||
89 | a different one from the console. Don't forget to change the mode of | ||
90 | blackfin serial driver to PIO. Otherwise kgdb works incorrectly on UART. | ||
91 | |||
92 | 4. If you want connect to kgdb when the kernel boots, enable | ||
93 | "KGDB: Wait for gdb connection early" | ||
94 | |||
95 | 5. Compile kernel. | ||
96 | |||
97 | 6. Connect minicom to the serial port of the console and boot the kernel image. | ||
98 | |||
99 | 7. Start GDB client "bfin-elf-gdb vmlinux". | ||
100 | |||
101 | 8. Set the baud rate in GDB "(gdb) set remotebaud 57600". | ||
102 | |||
103 | 9. Connect to the target on the second serial port "(gdb) target remote /dev/ttyS1". | ||
104 | |||
105 | 10. Set software breakpoint "(gdb) break sys_open". | ||
106 | |||
107 | 11. Continue "(gdb) c". | ||
108 | |||
109 | 12. Run ls in the target console "/> ls". | ||
110 | |||
111 | 13. A breakpoint is hit. "Breakpoint 1: sys_open(..." | ||
112 | |||
113 | 14. All other operations are the same as that in KGDB over Ethernet. | ||
114 | |||
115 | |||
116 | Debug over the same UART as console: | ||
117 | |||
118 | 1. Compile and install the cross platform version of gdb for blackfin, which | ||
119 | can be found at $(BINROOT)/bfin-elf-gdb. | ||
120 | |||
121 | 2. Apply this patch to the 2.6.x kernel. Select the menuconfig option under | ||
122 | "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb". | ||
123 | With this selected, option "Full Symbolic/Source Debugging support" and | ||
124 | "Compile the kernel with frame pointers" are also selected. | ||
125 | |||
126 | 3. Select option "KGDB: connect over UART". Set "KGDB: UART port number" to console. | ||
127 | Don't forget to change the mode of blackfin serial driver to PIO. | ||
128 | Otherwise kgdb works incorrectly on UART. | ||
129 | |||
130 | 4. If you want connect to kgdb when the kernel boots, enable | ||
131 | "KGDB: Wait for gdb connection early" | ||
132 | |||
133 | 5. Connect minicom to the serial port and boot the kernel image. | ||
134 | |||
135 | 6. (Optional) Ask target to wait for gdb connection by entering Ctrl+A. In minicom, you should enter Ctrl+A+A. | ||
136 | |||
137 | 7. Start GDB client "bfin-elf-gdb vmlinux". | ||
138 | |||
139 | 8. Set the baud rate in GDB "(gdb) set remotebaud 57600". | ||
140 | |||
141 | 9. Connect to the target "(gdb) target remote /dev/ttyS0". | ||
142 | |||
143 | 10. Set software breakpoint "(gdb) break sys_open". | ||
144 | |||
145 | 11. Continue "(gdb) c". Then enter Ctrl+C twice to stop GDB connection. | ||
146 | |||
147 | 12. Run ls in the target console "/> ls". Dummy string can be seen on the console. | ||
148 | |||
149 | 13. Then connect the gdb to target again. "(gdb) target remote /dev/ttyS0". | ||
150 | Now you will find a breakpoint is hit. "Breakpoint 1: sys_open(..." | ||
151 | |||
152 | 14. All other operations are the same as that in KGDB over Ethernet. The only | ||
153 | difference is that after continue command in GDB, please stop GDB | ||
154 | connection by 2 "Ctrl+C"s and connect again after breakpoints are hit or | ||
155 | Ctrl+A is entered. | ||
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index b7b6de824011..6fac57f6ce06 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile | |||
@@ -14,3 +14,4 @@ obj-$(CONFIG_BF561) += bfin_gpio.o | |||
14 | obj-$(CONFIG_MODULES) += module.o | 14 | obj-$(CONFIG_MODULES) += module.o |
15 | obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o | 15 | obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o |
16 | obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o | 16 | obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o |
17 | obj-$(CONFIG_KGDB) += kgdb.o | ||
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c new file mode 100644 index 000000000000..a9c15515bfd7 --- /dev/null +++ b/arch/blackfin/kernel/kgdb.c | |||
@@ -0,0 +1,421 @@ | |||
1 | /* | ||
2 | * File: arch/blackfin/kernel/kgdb.c | ||
3 | * Based on: | ||
4 | * Author: Sonic Zhang | ||
5 | * | ||
6 | * Created: | ||
7 | * Description: | ||
8 | * | ||
9 | * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $ | ||
10 | * | ||
11 | * Modified: | ||
12 | * Copyright 2005-2006 Analog Devices Inc. | ||
13 | * | ||
14 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, see the file COPYING, or write | ||
28 | * to the Free Software Foundation, Inc., | ||
29 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
30 | */ | ||
31 | |||
32 | #include <linux/string.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/smp.h> | ||
36 | #include <linux/spinlock.h> | ||
37 | #include <linux/delay.h> | ||
38 | #include <linux/ptrace.h> /* for linux pt_regs struct */ | ||
39 | #include <linux/kgdb.h> | ||
40 | #include <linux/console.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/debugger.h> | ||
43 | #include <linux/errno.h> | ||
44 | #include <linux/irq.h> | ||
45 | #include <asm/system.h> | ||
46 | #include <asm/traps.h> | ||
47 | #include <asm/blackfin.h> | ||
48 | |||
49 | /* Put the error code here just in case the user cares. */ | ||
50 | int gdb_bf533errcode; | ||
51 | /* Likewise, the vector number here (since GDB only gets the signal | ||
52 | number through the usual means, and that's not very specific). */ | ||
53 | int gdb_bf533vector = -1; | ||
54 | |||
55 | #if KGDB_MAX_NO_CPUS != 8 | ||
56 | #error change the definition of slavecpulocks | ||
57 | #endif | ||
58 | |||
59 | void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
60 | { | ||
61 | gdb_regs[BFIN_R0] = regs->r0; | ||
62 | gdb_regs[BFIN_R1] = regs->r1; | ||
63 | gdb_regs[BFIN_R2] = regs->r2; | ||
64 | gdb_regs[BFIN_R3] = regs->r3; | ||
65 | gdb_regs[BFIN_R4] = regs->r4; | ||
66 | gdb_regs[BFIN_R5] = regs->r5; | ||
67 | gdb_regs[BFIN_R6] = regs->r6; | ||
68 | gdb_regs[BFIN_R7] = regs->r7; | ||
69 | gdb_regs[BFIN_P0] = regs->p0; | ||
70 | gdb_regs[BFIN_P1] = regs->p1; | ||
71 | gdb_regs[BFIN_P2] = regs->p2; | ||
72 | gdb_regs[BFIN_P3] = regs->p3; | ||
73 | gdb_regs[BFIN_P4] = regs->p4; | ||
74 | gdb_regs[BFIN_P5] = regs->p5; | ||
75 | gdb_regs[BFIN_SP] = regs->reserved; | ||
76 | gdb_regs[BFIN_FP] = regs->fp; | ||
77 | gdb_regs[BFIN_I0] = regs->i0; | ||
78 | gdb_regs[BFIN_I1] = regs->i1; | ||
79 | gdb_regs[BFIN_I2] = regs->i2; | ||
80 | gdb_regs[BFIN_I3] = regs->i3; | ||
81 | gdb_regs[BFIN_M0] = regs->m0; | ||
82 | gdb_regs[BFIN_M1] = regs->m1; | ||
83 | gdb_regs[BFIN_M2] = regs->m2; | ||
84 | gdb_regs[BFIN_M3] = regs->m3; | ||
85 | gdb_regs[BFIN_B0] = regs->b0; | ||
86 | gdb_regs[BFIN_B1] = regs->b1; | ||
87 | gdb_regs[BFIN_B2] = regs->b2; | ||
88 | gdb_regs[BFIN_B3] = regs->b3; | ||
89 | gdb_regs[BFIN_L0] = regs->l0; | ||
90 | gdb_regs[BFIN_L1] = regs->l1; | ||
91 | gdb_regs[BFIN_L2] = regs->l2; | ||
92 | gdb_regs[BFIN_L3] = regs->l3; | ||
93 | gdb_regs[BFIN_A0_DOT_X] = regs->a0x; | ||
94 | gdb_regs[BFIN_A0_DOT_W] = regs->a0w; | ||
95 | gdb_regs[BFIN_A1_DOT_X] = regs->a1x; | ||
96 | gdb_regs[BFIN_A1_DOT_W] = regs->a1w; | ||
97 | gdb_regs[BFIN_ASTAT] = regs->astat; | ||
98 | gdb_regs[BFIN_RETS] = regs->rets; | ||
99 | gdb_regs[BFIN_LC0] = regs->lc0; | ||
100 | gdb_regs[BFIN_LT0] = regs->lt0; | ||
101 | gdb_regs[BFIN_LB0] = regs->lb0; | ||
102 | gdb_regs[BFIN_LC1] = regs->lc1; | ||
103 | gdb_regs[BFIN_LT1] = regs->lt1; | ||
104 | gdb_regs[BFIN_LB1] = regs->lb1; | ||
105 | gdb_regs[BFIN_CYCLES] = 0; | ||
106 | gdb_regs[BFIN_CYCLES2] = 0; | ||
107 | gdb_regs[BFIN_USP] = regs->usp; | ||
108 | gdb_regs[BFIN_SEQSTAT] = regs->seqstat; | ||
109 | gdb_regs[BFIN_SYSCFG] = regs->syscfg; | ||
110 | gdb_regs[BFIN_RETI] = regs->pc; | ||
111 | gdb_regs[BFIN_RETX] = regs->retx; | ||
112 | gdb_regs[BFIN_RETN] = regs->retn; | ||
113 | gdb_regs[BFIN_RETE] = regs->rete; | ||
114 | gdb_regs[BFIN_PC] = regs->pc; | ||
115 | gdb_regs[BFIN_CC] = 0; | ||
116 | gdb_regs[BFIN_EXTRA1] = 0; | ||
117 | gdb_regs[BFIN_EXTRA2] = 0; | ||
118 | gdb_regs[BFIN_EXTRA3] = 0; | ||
119 | gdb_regs[BFIN_IPEND] = regs->ipend; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Extracts ebp, esp and eip values understandable by gdb from the values | ||
124 | * saved by switch_to. | ||
125 | * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp | ||
126 | * prior to entering switch_to is 8 greater then the value that is saved. | ||
127 | * If switch_to changes, change following code appropriately. | ||
128 | */ | ||
129 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | ||
130 | { | ||
131 | gdb_regs[BFIN_SP] = p->thread.ksp; | ||
132 | gdb_regs[BFIN_PC] = p->thread.pc; | ||
133 | gdb_regs[BFIN_SEQSTAT] = p->thread.seqstat; | ||
134 | } | ||
135 | |||
136 | void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
137 | { | ||
138 | regs->r0 = gdb_regs[BFIN_R0]; | ||
139 | regs->r1 = gdb_regs[BFIN_R1]; | ||
140 | regs->r2 = gdb_regs[BFIN_R2]; | ||
141 | regs->r3 = gdb_regs[BFIN_R3]; | ||
142 | regs->r4 = gdb_regs[BFIN_R4]; | ||
143 | regs->r5 = gdb_regs[BFIN_R5]; | ||
144 | regs->r6 = gdb_regs[BFIN_R6]; | ||
145 | regs->r7 = gdb_regs[BFIN_R7]; | ||
146 | regs->p0 = gdb_regs[BFIN_P0]; | ||
147 | regs->p1 = gdb_regs[BFIN_P1]; | ||
148 | regs->p2 = gdb_regs[BFIN_P2]; | ||
149 | regs->p3 = gdb_regs[BFIN_P3]; | ||
150 | regs->p4 = gdb_regs[BFIN_P4]; | ||
151 | regs->p5 = gdb_regs[BFIN_P5]; | ||
152 | regs->fp = gdb_regs[BFIN_FP]; | ||
153 | regs->i0 = gdb_regs[BFIN_I0]; | ||
154 | regs->i1 = gdb_regs[BFIN_I1]; | ||
155 | regs->i2 = gdb_regs[BFIN_I2]; | ||
156 | regs->i3 = gdb_regs[BFIN_I3]; | ||
157 | regs->m0 = gdb_regs[BFIN_M0]; | ||
158 | regs->m1 = gdb_regs[BFIN_M1]; | ||
159 | regs->m2 = gdb_regs[BFIN_M2]; | ||
160 | regs->m3 = gdb_regs[BFIN_M3]; | ||
161 | regs->b0 = gdb_regs[BFIN_B0]; | ||
162 | regs->b1 = gdb_regs[BFIN_B1]; | ||
163 | regs->b2 = gdb_regs[BFIN_B2]; | ||
164 | regs->b3 = gdb_regs[BFIN_B3]; | ||
165 | regs->l0 = gdb_regs[BFIN_L0]; | ||
166 | regs->l1 = gdb_regs[BFIN_L1]; | ||
167 | regs->l2 = gdb_regs[BFIN_L2]; | ||
168 | regs->l3 = gdb_regs[BFIN_L3]; | ||
169 | regs->a0x = gdb_regs[BFIN_A0_DOT_X]; | ||
170 | regs->a0w = gdb_regs[BFIN_A0_DOT_W]; | ||
171 | regs->a1x = gdb_regs[BFIN_A1_DOT_X]; | ||
172 | regs->a1w = gdb_regs[BFIN_A1_DOT_W]; | ||
173 | regs->rets = gdb_regs[BFIN_RETS]; | ||
174 | regs->lc0 = gdb_regs[BFIN_LC0]; | ||
175 | regs->lt0 = gdb_regs[BFIN_LT0]; | ||
176 | regs->lb0 = gdb_regs[BFIN_LB0]; | ||
177 | regs->lc1 = gdb_regs[BFIN_LC1]; | ||
178 | regs->lt1 = gdb_regs[BFIN_LT1]; | ||
179 | regs->lb1 = gdb_regs[BFIN_LB1]; | ||
180 | regs->usp = gdb_regs[BFIN_USP]; | ||
181 | regs->syscfg = gdb_regs[BFIN_SYSCFG]; | ||
182 | regs->retx = gdb_regs[BFIN_PC]; | ||
183 | regs->retn = gdb_regs[BFIN_RETN]; | ||
184 | regs->rete = gdb_regs[BFIN_RETE]; | ||
185 | regs->pc = gdb_regs[BFIN_PC]; | ||
186 | |||
187 | #if 0 /* can't change these */ | ||
188 | regs->astat = gdb_regs[BFIN_ASTAT]; | ||
189 | regs->seqstat = gdb_regs[BFIN_SEQSTAT]; | ||
190 | regs->ipend = gdb_regs[BFIN_IPEND]; | ||
191 | #endif | ||
192 | } | ||
193 | |||
194 | struct hw_breakpoint { | ||
195 | unsigned int occupied:1; | ||
196 | unsigned int skip:1; | ||
197 | unsigned int enabled:1; | ||
198 | unsigned int type:1; | ||
199 | unsigned int dataacc:2; | ||
200 | unsigned short count; | ||
201 | unsigned int addr; | ||
202 | } breakinfo[HW_BREAKPOINT_NUM]; | ||
203 | |||
204 | int kgdb_arch_init(void) | ||
205 | { | ||
206 | kgdb_remove_all_hw_break(); | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | int kgdb_set_hw_break(unsigned long addr) | ||
211 | { | ||
212 | int breakno; | ||
213 | for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) | ||
214 | if (!breakinfo[breakno].occupied) { | ||
215 | breakinfo[breakno].occupied = 1; | ||
216 | breakinfo[breakno].enabled = 1; | ||
217 | breakinfo[breakno].type = 1; | ||
218 | breakinfo[breakno].addr = addr; | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | return -ENOSPC; | ||
223 | } | ||
224 | |||
225 | int kgdb_remove_hw_break(unsigned long addr) | ||
226 | { | ||
227 | int breakno; | ||
228 | for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) | ||
229 | if (breakinfo[breakno].addr == addr) | ||
230 | memset(&(breakinfo[breakno]), 0, sizeof(struct hw_breakpoint)); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | void kgdb_remove_all_hw_break(void) | ||
236 | { | ||
237 | memset(breakinfo, 0, sizeof(struct hw_breakpoint)*8); | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | void kgdb_show_info(void) | ||
242 | { | ||
243 | printk(KERN_DEBUG "hwd: wpia0=0x%x, wpiacnt0=%d, wpiactl=0x%x, wpstat=0x%x\n", | ||
244 | bfin_read_WPIA0(), bfin_read_WPIACNT0(), | ||
245 | bfin_read_WPIACTL(), bfin_read_WPSTAT()); | ||
246 | } | ||
247 | */ | ||
248 | |||
249 | void kgdb_correct_hw_break(void) | ||
250 | { | ||
251 | int breakno; | ||
252 | int correctit; | ||
253 | uint32_t wpdactl = bfin_read_WPDACTL(); | ||
254 | |||
255 | correctit = 0; | ||
256 | for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) { | ||
257 | if (breakinfo[breakno].type == 1) { | ||
258 | switch (breakno) { | ||
259 | case 0: | ||
260 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN0)) { | ||
261 | correctit = 1; | ||
262 | wpdactl &= ~(WPIREN01|EMUSW0); | ||
263 | wpdactl |= WPIAEN0|WPICNTEN0; | ||
264 | bfin_write_WPIA0(breakinfo[breakno].addr); | ||
265 | bfin_write_WPIACNT0(breakinfo[breakno].skip); | ||
266 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN0)) { | ||
267 | correctit = 1; | ||
268 | wpdactl &= ~WPIAEN0; | ||
269 | } | ||
270 | break; | ||
271 | |||
272 | case 1: | ||
273 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN1)) { | ||
274 | correctit = 1; | ||
275 | wpdactl &= ~(WPIREN01|EMUSW1); | ||
276 | wpdactl |= WPIAEN1|WPICNTEN1; | ||
277 | bfin_write_WPIA1(breakinfo[breakno].addr); | ||
278 | bfin_write_WPIACNT1(breakinfo[breakno].skip); | ||
279 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN1)) { | ||
280 | correctit = 1; | ||
281 | wpdactl &= ~WPIAEN1; | ||
282 | } | ||
283 | break; | ||
284 | |||
285 | case 2: | ||
286 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN2)) { | ||
287 | correctit = 1; | ||
288 | wpdactl &= ~(WPIREN23|EMUSW2); | ||
289 | wpdactl |= WPIAEN2|WPICNTEN2; | ||
290 | bfin_write_WPIA2(breakinfo[breakno].addr); | ||
291 | bfin_write_WPIACNT2(breakinfo[breakno].skip); | ||
292 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN2)) { | ||
293 | correctit = 1; | ||
294 | wpdactl &= ~WPIAEN2; | ||
295 | } | ||
296 | break; | ||
297 | |||
298 | case 3: | ||
299 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN3)) { | ||
300 | correctit = 1; | ||
301 | wpdactl &= ~(WPIREN23|EMUSW3); | ||
302 | wpdactl |= WPIAEN3|WPICNTEN3; | ||
303 | bfin_write_WPIA3(breakinfo[breakno].addr); | ||
304 | bfin_write_WPIACNT3(breakinfo[breakno].skip); | ||
305 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN3)) { | ||
306 | correctit = 1; | ||
307 | wpdactl &= ~WPIAEN3; | ||
308 | } | ||
309 | break; | ||
310 | case 4: | ||
311 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN4)) { | ||
312 | correctit = 1; | ||
313 | wpdactl &= ~(WPIREN45|EMUSW4); | ||
314 | wpdactl |= WPIAEN4|WPICNTEN4; | ||
315 | bfin_write_WPIA4(breakinfo[breakno].addr); | ||
316 | bfin_write_WPIACNT4(breakinfo[breakno].skip); | ||
317 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN4)) { | ||
318 | correctit = 1; | ||
319 | wpdactl &= ~WPIAEN4; | ||
320 | } | ||
321 | break; | ||
322 | case 5: | ||
323 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN5)) { | ||
324 | correctit = 1; | ||
325 | wpdactl &= ~(WPIREN45|EMUSW5); | ||
326 | wpdactl |= WPIAEN5|WPICNTEN5; | ||
327 | bfin_write_WPIA5(breakinfo[breakno].addr); | ||
328 | bfin_write_WPIACNT5(breakinfo[breakno].skip); | ||
329 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN5)) { | ||
330 | correctit = 1; | ||
331 | wpdactl &= ~WPIAEN5; | ||
332 | } | ||
333 | break; | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | if (correctit) { | ||
338 | wpdactl &= ~WPAND; | ||
339 | wpdactl |= WPPWR; | ||
340 | /*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/ | ||
341 | bfin_write_WPDACTL(wpdactl); | ||
342 | CSYNC(); | ||
343 | /*kgdb_show_info();*/ | ||
344 | } | ||
345 | } | ||
346 | |||
347 | void kgdb_disable_hw_debug(struct pt_regs *regs) | ||
348 | { | ||
349 | /* Disable hardware debugging while we are in kgdb */ | ||
350 | bfin_write_WPIACTL(bfin_read_WPIACTL() & ~0x1); | ||
351 | CSYNC(); | ||
352 | } | ||
353 | |||
354 | void kgdb_post_master_code(struct pt_regs *regs, int eVector, int err_code) | ||
355 | { | ||
356 | /* Master processor is completely in the debugger */ | ||
357 | gdb_bf533vector = eVector; | ||
358 | gdb_bf533errcode = err_code; | ||
359 | } | ||
360 | |||
361 | int kgdb_arch_handle_exception(int exceptionVector, int signo, | ||
362 | int err_code, char *remcom_in_buffer, | ||
363 | char *remcom_out_buffer, | ||
364 | struct pt_regs *linux_regs) | ||
365 | { | ||
366 | long addr; | ||
367 | long breakno; | ||
368 | char *ptr; | ||
369 | int newPC; | ||
370 | int wp_status; | ||
371 | |||
372 | switch (remcom_in_buffer[0]) { | ||
373 | case 'c': | ||
374 | case 's': | ||
375 | if (kgdb_contthread && kgdb_contthread != current) { | ||
376 | strcpy(remcom_out_buffer, "E00"); | ||
377 | break; | ||
378 | } | ||
379 | |||
380 | kgdb_contthread = NULL; | ||
381 | |||
382 | /* try to read optional parameter, pc unchanged if no parm */ | ||
383 | ptr = &remcom_in_buffer[1]; | ||
384 | if (kgdb_hex2long(&ptr, &addr)) { | ||
385 | linux_regs->retx = addr; | ||
386 | } | ||
387 | newPC = linux_regs->retx; | ||
388 | |||
389 | /* clear the trace bit */ | ||
390 | linux_regs->syscfg &= 0xfffffffe; | ||
391 | |||
392 | /* set the trace bit if we're stepping */ | ||
393 | if (remcom_in_buffer[0] == 's') { | ||
394 | linux_regs->syscfg |= 0x1; | ||
395 | debugger_step = 1; | ||
396 | } | ||
397 | |||
398 | wp_status = bfin_read_WPSTAT(); | ||
399 | CSYNC(); | ||
400 | |||
401 | if (exceptionVector == VEC_WATCH) { | ||
402 | for (breakno = 0; breakno < 6; ++breakno) { | ||
403 | if (wp_status & (1 << breakno)) { | ||
404 | breakinfo->skip = 1; | ||
405 | break; | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | kgdb_correct_hw_break(); | ||
410 | |||
411 | bfin_write_WPSTAT(0); | ||
412 | |||
413 | return 0; | ||
414 | } /* switch */ | ||
415 | return -1; /* this means that we do not want to exit from the handler */ | ||
416 | } | ||
417 | |||
418 | struct kgdb_arch arch_kgdb_ops = { | ||
419 | .gdb_bpt_instr = {0xa1}, | ||
420 | .flags = KGDB_HW_BREAKPOINT, | ||
421 | }; | ||
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 315ea9916456..71a4ac53a7ef 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -556,7 +556,7 @@ choice | |||
556 | 556 | ||
557 | config SERIAL_BFIN_DMA | 557 | config SERIAL_BFIN_DMA |
558 | bool "DMA mode" | 558 | bool "DMA mode" |
559 | depends on DMA_UNCACHED_1M | 559 | depends on DMA_UNCACHED_1M && !KGDB_UART |
560 | help | 560 | help |
561 | This driver works under DMA mode. If this option is selected, the | 561 | This driver works under DMA mode. If this option is selected, the |
562 | blackfin simple dma driver is also enabled. | 562 | blackfin simple dma driver is also enabled. |
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 | ||
diff --git a/include/asm-blackfin/kgdb.h b/include/asm-blackfin/kgdb.h new file mode 100644 index 000000000000..532bd9052004 --- /dev/null +++ b/include/asm-blackfin/kgdb.h | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * File: include/asm-blackfin/kgdb.h | ||
3 | * Based on: | ||
4 | * Author: Sonic Zhang | ||
5 | * | ||
6 | * Created: | ||
7 | * Description: | ||
8 | * | ||
9 | * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $ | ||
10 | * | ||
11 | * Modified: | ||
12 | * Copyright 2005-2006 Analog Devices Inc. | ||
13 | * | ||
14 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, see the file COPYING, or write | ||
28 | * to the Free Software Foundation, Inc., | ||
29 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
30 | */ | ||
31 | |||
32 | #ifndef __ASM_BLACKFIN_KGDB_H__ | ||
33 | #define __ASM_BLACKFIN_KGDB_H__ | ||
34 | |||
35 | #include <linux/ptrace.h> | ||
36 | |||
37 | /* gdb locks */ | ||
38 | #define KGDB_MAX_NO_CPUS 8 | ||
39 | |||
40 | /************************************************************************/ | ||
41 | /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ | ||
42 | /* at least NUMREGBYTES*2 are needed for register packets */ | ||
43 | /* Longer buffer is needed to list all threads */ | ||
44 | #define BUFMAX 2048 | ||
45 | |||
46 | /* | ||
47 | * Note that this register image is different from | ||
48 | * the register image that Linux produces at interrupt time. | ||
49 | * | ||
50 | * Linux's register image is defined by struct pt_regs in ptrace.h. | ||
51 | */ | ||
52 | enum regnames { | ||
53 | /* Core Registers */ | ||
54 | BFIN_R0 = 0, | ||
55 | BFIN_R1, | ||
56 | BFIN_R2, | ||
57 | BFIN_R3, | ||
58 | BFIN_R4, | ||
59 | BFIN_R5, | ||
60 | BFIN_R6, | ||
61 | BFIN_R7, | ||
62 | BFIN_P0, | ||
63 | BFIN_P1, | ||
64 | BFIN_P2, | ||
65 | BFIN_P3, | ||
66 | BFIN_P4, | ||
67 | BFIN_P5, | ||
68 | BFIN_SP, | ||
69 | BFIN_FP, | ||
70 | BFIN_I0, | ||
71 | BFIN_I1, | ||
72 | BFIN_I2, | ||
73 | BFIN_I3, | ||
74 | BFIN_M0, | ||
75 | BFIN_M1, | ||
76 | BFIN_M2, | ||
77 | BFIN_M3, | ||
78 | BFIN_B0, | ||
79 | BFIN_B1, | ||
80 | BFIN_B2, | ||
81 | BFIN_B3, | ||
82 | BFIN_L0, | ||
83 | BFIN_L1, | ||
84 | BFIN_L2, | ||
85 | BFIN_L3, | ||
86 | BFIN_A0_DOT_X, | ||
87 | BFIN_A0_DOT_W, | ||
88 | BFIN_A1_DOT_X, | ||
89 | BFIN_A1_DOT_W, | ||
90 | BFIN_ASTAT, | ||
91 | BFIN_RETS, | ||
92 | BFIN_LC0, | ||
93 | BFIN_LT0, | ||
94 | BFIN_LB0, | ||
95 | BFIN_LC1, | ||
96 | BFIN_LT1, | ||
97 | BFIN_LB1, | ||
98 | BFIN_CYCLES, | ||
99 | BFIN_CYCLES2, | ||
100 | BFIN_USP, | ||
101 | BFIN_SEQSTAT, | ||
102 | BFIN_SYSCFG, | ||
103 | BFIN_RETI, | ||
104 | BFIN_RETX, | ||
105 | BFIN_RETN, | ||
106 | BFIN_RETE, | ||
107 | |||
108 | /* Pseudo Registers */ | ||
109 | BFIN_PC, | ||
110 | BFIN_CC, | ||
111 | BFIN_EXTRA1, /* Address of .text section. */ | ||
112 | BFIN_EXTRA2, /* Address of .data section. */ | ||
113 | BFIN_EXTRA3, /* Address of .bss section. */ | ||
114 | BFIN_FDPIC_EXEC, | ||
115 | BFIN_FDPIC_INTERP, | ||
116 | |||
117 | /* MMRs */ | ||
118 | BFIN_IPEND, | ||
119 | |||
120 | /* LAST ENTRY SHOULD NOT BE CHANGED. */ | ||
121 | BFIN_NUM_REGS /* The number of all registers. */ | ||
122 | }; | ||
123 | |||
124 | /* Number of bytes of registers. */ | ||
125 | #define NUMREGBYTES BFIN_NUM_REGS*4 | ||
126 | |||
127 | #define BREAKPOINT() asm(" EXCPT 2;"); | ||
128 | #define BREAK_INSTR_SIZE 2 | ||
129 | #define HW_BREAKPOINT_NUM 6 | ||
130 | |||
131 | /* Instruction watchpoint address control register bits mask */ | ||
132 | #define WPPWR 0x1 | ||
133 | #define WPIREN01 0x2 | ||
134 | #define WPIRINV01 0x4 | ||
135 | #define WPIAEN0 0x8 | ||
136 | #define WPIAEN1 0x10 | ||
137 | #define WPICNTEN0 0x20 | ||
138 | #define WPICNTEN1 0x40 | ||
139 | #define EMUSW0 0x80 | ||
140 | #define EMUSW1 0x100 | ||
141 | #define WPIREN23 0x200 | ||
142 | #define WPIRINV23 0x400 | ||
143 | #define WPIAEN2 0x800 | ||
144 | #define WPIAEN3 0x1000 | ||
145 | #define WPICNTEN2 0x2000 | ||
146 | #define WPICNTEN3 0x4000 | ||
147 | #define EMUSW2 0x8000 | ||
148 | #define EMUSW3 0x10000 | ||
149 | #define WPIREN45 0x20000 | ||
150 | #define WPIRINV45 0x40000 | ||
151 | #define WPIAEN4 0x80000 | ||
152 | #define WPIAEN5 0x100000 | ||
153 | #define WPICNTEN4 0x200000 | ||
154 | #define WPICNTEN5 0x400000 | ||
155 | #define EMUSW4 0x800000 | ||
156 | #define EMUSW5 0x1000000 | ||
157 | #define WPAND 0x2000000 | ||
158 | |||
159 | /* Data watchpoint address control register bits mask */ | ||
160 | #define WPDREN01 0x1 | ||
161 | #define WPDRINV01 0x2 | ||
162 | #define WPDAEN0 0x4 | ||
163 | #define WPDAEN1 0x8 | ||
164 | #define WPDCNTEN0 0x10 | ||
165 | #define WPDCNTEN1 0x20 | ||
166 | #define WPDSRC0 0xc0 | ||
167 | #define WPDACC0 0x300 | ||
168 | #define WPDSRC1 0xc00 | ||
169 | #define WPDACC1 0x3000 | ||
170 | |||
171 | /* Watchpoint status register bits mask */ | ||
172 | #define STATIA0 0x1 | ||
173 | #define STATIA1 0x2 | ||
174 | #define STATIA2 0x4 | ||
175 | #define STATIA3 0x8 | ||
176 | #define STATIA4 0x10 | ||
177 | #define STATIA5 0x20 | ||
178 | #define STATDA0 0x40 | ||
179 | #define STATDA1 0x80 | ||
180 | |||
181 | extern void kgdb_print(const char *fmt, ...); | ||
182 | |||
183 | #endif | ||