2 * Bedbug Functions specific to the PPC405 chip
7 #include <linux/ctype.h>
8 #include <bedbug/type.h>
9 #include <bedbug/bedbug.h>
10 #include <bedbug/regs.h>
11 #include <bedbug/ppc.h>
13 #if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_4xx)
15 #define MAX_BREAK_POINTS 4
17 extern CPU_DEBUG_CTX bug_ctx;
19 void bedbug405_init __P ((void));
20 void bedbug405_do_break __P ((cmd_tbl_t *, int, int, char *[]));
21 void bedbug405_break_isr __P ((struct pt_regs *));
22 int bedbug405_find_empty __P ((void));
23 int bedbug405_set __P ((int, unsigned long));
24 int bedbug405_clear __P ((int));
27 /* ======================================================================
28 * Initialize the global bug_ctx structure for the AMCC PPC405. Clear all
30 * ====================================================================== */
32 void bedbug405_init (void)
36 /* -------------------------------------------------- */
38 bug_ctx.hw_debug_enabled = 0;
40 bug_ctx.current_bp = 0;
43 bug_ctx.do_break = bedbug405_do_break;
44 bug_ctx.break_isr = bedbug405_break_isr;
45 bug_ctx.find_empty = bedbug405_find_empty;
46 bug_ctx.set = bedbug405_set;
47 bug_ctx.clear = bedbug405_clear;
49 for (i = 1; i <= MAX_BREAK_POINTS; ++i)
52 puts ("BEDBUG:ready\n");
54 } /* bedbug_init_breakpoints */
58 /* ======================================================================
59 * Set/clear/show one of the hardware breakpoints for the 405. The "off"
60 * string will disable a specific breakpoint. The "show" string will
61 * display the current breakpoints. Otherwise an address will set a
62 * breakpoint at that address. Setting a breakpoint uses the CPU-specific
63 * set routine which will assign a breakpoint number.
64 * ====================================================================== */
66 void bedbug405_do_break (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
68 long addr = 0; /* Address to break at */
69 int which_bp; /* Breakpoint number */
71 /* -------------------------------------------------- */
78 /* Turn off a breakpoint */
80 if (strcmp (argv[1], "off") == 0) {
81 if (bug_ctx.hw_debug_enabled == 0) {
82 printf ("No breakpoints enabled\n");
86 which_bp = simple_strtoul (argv[2], NULL, 10);
89 (*bug_ctx.clear) (which_bp);
91 printf ("Breakpoint %d removed\n", which_bp);
95 /* Show a list of breakpoints */
97 if (strcmp (argv[1], "show") == 0) {
98 for (which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp) {
115 printf ("Breakpoint [%d]: ", which_bp);
117 printf ("NOT SET\n");
119 disppc ((unsigned char *) addr, 0, 1, bedbug_puts,
125 /* Set a breakpoint at the address */
127 if (!isdigit (argv[1][0])) {
132 addr = simple_strtoul (argv[1], NULL, 16) & 0xfffffffc;
134 if ((bug_ctx.set) && (which_bp = (*bug_ctx.set) (0, addr)) > 0) {
135 printf ("Breakpoint [%d]: ", which_bp);
136 disppc ((unsigned char *) addr, 0, 1, bedbug_puts, F_RADHEX);
140 } /* bedbug405_do_break */
144 /* ======================================================================
145 * Handle a breakpoint. First determine which breakpoint was hit by
146 * looking at the DeBug Status Register (DBSR), clear the breakpoint
147 * and enter a mini main loop. Stay in the loop until the stopped flag
148 * in the debug context is cleared.
149 * ====================================================================== */
151 void bedbug405_break_isr (struct pt_regs *regs)
153 unsigned long dbsr_val; /* Value of the DBSR */
154 unsigned long addr = 0; /* Address stopped at */
156 /* -------------------------------------------------- */
158 dbsr_val = GET_DBSR ();
160 if (dbsr_val & DBSR_IA1) {
161 bug_ctx.current_bp = 1;
163 SET_DBSR (DBSR_IA1); /* Write a 1 to clear */
164 } else if (dbsr_val & DBSR_IA2) {
165 bug_ctx.current_bp = 2;
167 SET_DBSR (DBSR_IA2); /* Write a 1 to clear */
168 } else if (dbsr_val & DBSR_IA3) {
169 bug_ctx.current_bp = 3;
171 SET_DBSR (DBSR_IA3); /* Write a 1 to clear */
172 } else if (dbsr_val & DBSR_IA4) {
173 bug_ctx.current_bp = 4;
175 SET_DBSR (DBSR_IA4); /* Write a 1 to clear */
178 bedbug_main_loop (addr, regs);
180 } /* bedbug405_break_isr */
184 /* ======================================================================
185 * Look through all of the hardware breakpoints available to see if one
187 * ====================================================================== */
189 int bedbug405_find_empty (void)
191 /* -------------------------------------------------- */
193 if (GET_IAC1 () == 0)
196 if (GET_IAC2 () == 0)
199 if (GET_IAC3 () == 0)
202 if (GET_IAC4 () == 0)
206 } /* bedbug405_find_empty */
210 /* ======================================================================
211 * Set a breakpoint. If 'which_bp' is zero then find an unused breakpoint
212 * number, otherwise reassign the given breakpoint. If hardware debugging
213 * is not enabled, then turn it on via the MSR and DBCR0. Set the break
214 * address in the appropriate IACx register and enable proper address
215 * beakpoint in DBCR0.
216 * ====================================================================== */
218 int bedbug405_set (int which_bp, unsigned long addr)
220 /* -------------------------------------------------- */
222 /* Only look if which_bp == 0, else use which_bp */
223 if ((bug_ctx.find_empty) && (!which_bp) &&
224 (which_bp = (*bug_ctx.find_empty) ()) == 0) {
225 printf ("All breakpoints in use\n");
229 if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) {
230 printf ("Invalid break point # %d\n", which_bp);
234 if (!bug_ctx.hw_debug_enabled) {
235 SET_MSR (GET_MSR () | 0x200); /* set MSR[ DE ] */
236 SET_DBCR0 (GET_DBCR0 () | DBCR0_IDM);
237 bug_ctx.hw_debug_enabled = 1;
243 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA1);
248 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA2);
253 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA3);
258 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA4);
263 } /* bedbug405_set */
267 /* ======================================================================
268 * Disable a specific breakoint by setting the appropriate IACx register
269 * to zero and claring the instruction address breakpoint in DBCR0.
270 * ====================================================================== */
272 int bedbug405_clear (int which_bp)
274 /* -------------------------------------------------- */
276 if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) {
277 printf ("Invalid break point # (%d)\n", which_bp);
284 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA1);
289 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA2);
294 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA3);
299 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA4);
304 } /* bedbug405_clear */
307 /* ====================================================================== */