~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to cpu/mpc8xx/bedbug_860.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Bedbug Functions specific to the MPC860 chip
 
3
 */
 
4
 
 
5
#include <common.h>
 
6
#include <command.h>
 
7
#include <linux/ctype.h>
 
8
#include <bedbug/bedbug.h>
 
9
#include <bedbug/regs.h>
 
10
#include <bedbug/ppc.h>
 
11
#include <bedbug/type.h>
 
12
 
 
13
#if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_8xx)
 
14
 
 
15
#define MAX_BREAK_POINTS 2
 
16
 
 
17
extern CPU_DEBUG_CTX bug_ctx;
 
18
 
 
19
void bedbug860_init __P((void));
 
20
void bedbug860_do_break __P((cmd_tbl_t*,int,int,char*[]));
 
21
void bedbug860_break_isr __P((struct pt_regs*));
 
22
int  bedbug860_find_empty __P((void));
 
23
int  bedbug860_set __P((int,unsigned long));
 
24
int  bedbug860_clear __P((int));
 
25
 
 
26
 
 
27
/* ======================================================================
 
28
 * Initialize the global bug_ctx structure for the MPC860.  Clear all
 
29
 * of the breakpoints.
 
30
 * ====================================================================== */
 
31
 
 
32
void bedbug860_init( void )
 
33
{
 
34
  int   i;
 
35
  /* -------------------------------------------------- */
 
36
 
 
37
  bug_ctx.hw_debug_enabled = 0;
 
38
  bug_ctx.stopped = 0;
 
39
  bug_ctx.current_bp = 0;
 
40
  bug_ctx.regs = NULL;
 
41
 
 
42
  bug_ctx.do_break   = bedbug860_do_break;
 
43
  bug_ctx.break_isr  = bedbug860_break_isr;
 
44
  bug_ctx.find_empty = bedbug860_find_empty;
 
45
  bug_ctx.set        = bedbug860_set;
 
46
  bug_ctx.clear      = bedbug860_clear;
 
47
 
 
48
  for( i = 1; i <= MAX_BREAK_POINTS; ++i )
 
49
    (*bug_ctx.clear)( i );
 
50
 
 
51
  puts ("BEDBUG:ready\n");
 
52
  return;
 
53
} /* bedbug_init_breakpoints */
 
54
 
 
55
 
 
56
 
 
57
/* ======================================================================
 
58
 * Set/clear/show one of the hardware breakpoints for the 860.  The "off"
 
59
 * string will disable a specific breakpoint.  The "show" string will
 
60
 * display the current breakpoints.  Otherwise an address will set a
 
61
 * breakpoint at that address.  Setting a breakpoint uses the CPU-specific
 
62
 * set routine which will assign a breakpoint number.
 
63
 * ====================================================================== */
 
64
 
 
65
void bedbug860_do_break (cmd_tbl_t *cmdtp, int flag, int argc,
 
66
                         char *argv[])
 
67
{
 
68
  long          addr = 0;       /* Address to break at  */
 
69
  int           which_bp;       /* Breakpoint number    */
 
70
  /* -------------------------------------------------- */
 
71
 
 
72
  if (argc < 2)
 
73
  {
 
74
    cmd_usage(cmdtp);
 
75
    return;
 
76
  }
 
77
 
 
78
  /* Turn off a breakpoint */
 
79
 
 
80
  if( strcmp( argv[ 1 ], "off" ) == 0 )
 
81
  {
 
82
    if( bug_ctx.hw_debug_enabled == 0 )
 
83
    {
 
84
      printf( "No breakpoints enabled\n" );
 
85
      return;
 
86
    }
 
87
 
 
88
    which_bp = simple_strtoul( argv[ 2 ], NULL, 10 );
 
89
 
 
90
    if( bug_ctx.clear )
 
91
      (*bug_ctx.clear)( which_bp );
 
92
 
 
93
    printf( "Breakpoint %d removed\n", which_bp );
 
94
    return;
 
95
  }
 
96
 
 
97
  /* Show a list of breakpoints */
 
98
 
 
99
  if( strcmp( argv[ 1 ], "show" ) == 0 )
 
100
  {
 
101
    for( which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp )
 
102
    {
 
103
 
 
104
      switch( which_bp )
 
105
      {
 
106
      case 1: addr = GET_CMPA(); break;
 
107
      case 2: addr = GET_CMPB(); break;
 
108
      case 3: addr = GET_CMPC(); break;
 
109
      case 4: addr = GET_CMPD(); break;
 
110
      }
 
111
 
 
112
      printf( "Breakpoint [%d]: ", which_bp );
 
113
      if( addr == 0 )
 
114
        printf( "NOT SET\n" );
 
115
      else
 
116
        disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
 
117
    }
 
118
    return;
 
119
  }
 
120
 
 
121
  /* Set a breakpoint at the address */
 
122
 
 
123
  if( !isdigit( argv[ 1 ][ 0 ]))
 
124
  {
 
125
    cmd_usage(cmdtp);
 
126
    return;
 
127
  }
 
128
 
 
129
  addr = simple_strtoul( argv[ 1 ], NULL, 16 ) & 0xfffffffc;
 
130
 
 
131
  if(( bug_ctx.set ) && ( which_bp = (*bug_ctx.set)( 0, addr )) > 0 )
 
132
  {
 
133
    printf( "Breakpoint [%d]: ", which_bp );
 
134
    disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
 
135
  }
 
136
 
 
137
  return;
 
138
} /* bedbug860_do_break */
 
139
 
 
140
 
 
141
 
 
142
/* ======================================================================
 
143
 * Handle a breakpoint.  First determine which breakpoint was hit by
 
144
 * looking at the DeBug Status Register (DBSR), clear the breakpoint
 
145
 * and enter a mini main loop.  Stay in the loop until the stopped flag
 
146
 * in the debug context is cleared.
 
147
 * ====================================================================== */
 
148
 
 
149
void bedbug860_break_isr( struct pt_regs *regs )
 
150
{
 
151
  unsigned long addr;     /* Address stopped at   */
 
152
  unsigned long cause;     /* Address stopped at   */
 
153
  /* -------------------------------------------------- */
 
154
 
 
155
  cause = GET_ICR();
 
156
 
 
157
  if( !(cause & 0x00000004)) {
 
158
    printf( "Not an instruction breakpoint (ICR 0x%08lx)\n", cause );
 
159
    return;
 
160
  }
 
161
 
 
162
  addr = regs->nip;
 
163
 
 
164
  if( addr == GET_CMPA() )
 
165
  {
 
166
    bug_ctx.current_bp = 1;
 
167
  }
 
168
  else if( addr == GET_CMPB() )
 
169
  {
 
170
    bug_ctx.current_bp = 2;
 
171
  }
 
172
  else if( addr == GET_CMPC() )
 
173
  {
 
174
    bug_ctx.current_bp = 3;
 
175
  }
 
176
  else if( addr == GET_CMPD() )
 
177
  {
 
178
    bug_ctx.current_bp = 4;
 
179
  }
 
180
 
 
181
  bedbug_main_loop( addr, regs );
 
182
  return;
 
183
} /* bedbug860_break_isr */
 
184
 
 
185
 
 
186
 
 
187
/* ======================================================================
 
188
 * Look through all of the hardware breakpoints available to see if one
 
189
 * is unused.
 
190
 * ====================================================================== */
 
191
 
 
192
int bedbug860_find_empty( void )
 
193
{
 
194
  /* -------------------------------------------------- */
 
195
 
 
196
  if( GET_CMPA() == 0 )
 
197
    return 1;
 
198
 
 
199
  if( GET_CMPB() == 0 )
 
200
    return 2;
 
201
 
 
202
  if( GET_CMPC() == 0 )
 
203
    return 3;
 
204
 
 
205
  if( GET_CMPD() == 0 )
 
206
    return 4;
 
207
 
 
208
  return 0;
 
209
} /* bedbug860_find_empty */
 
210
 
 
211
 
 
212
 
 
213
/* ======================================================================
 
214
 * Set a breakpoint.  If 'which_bp' is zero then find an unused breakpoint
 
215
 * number, otherwise reassign the given breakpoint.  If hardware debugging
 
216
 * is not enabled, then turn it on via the MSR and DBCR0.  Set the break
 
217
 * address in the appropriate IACx register and enable proper address
 
218
 * beakpoint in DBCR0.
 
219
 * ====================================================================== */
 
220
 
 
221
int bedbug860_set( int which_bp, unsigned long addr )
 
222
{
 
223
  /* -------------------------------------------------- */
 
224
 
 
225
  /* Only look if which_bp == 0, else use which_bp */
 
226
  if(( bug_ctx.find_empty ) && ( !which_bp ) &&
 
227
     ( which_bp = (*bug_ctx.find_empty)()) == 0 )
 
228
  {
 
229
    printf( "All breakpoints in use\n" );
 
230
    return 0;
 
231
  }
 
232
 
 
233
  if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
 
234
  {
 
235
    printf( "Invalid break point # %d\n", which_bp );
 
236
    return 0;
 
237
  }
 
238
 
 
239
  if( ! bug_ctx.hw_debug_enabled )
 
240
  {
 
241
    bug_ctx.hw_debug_enabled = 1;
 
242
    SET_DER( GET_DER() | 0x00000004 );
 
243
  }
 
244
 
 
245
  switch( which_bp )
 
246
  {
 
247
  case 1:
 
248
    SET_CMPA( addr );
 
249
    SET_ICTRL( GET_ICTRL() | 0x80080800 ); /* CTA=Equal,IW0=Match A,SIW0EN */
 
250
    break;
 
251
 
 
252
  case 2:
 
253
    SET_CMPB( addr );
 
254
    SET_ICTRL( GET_ICTRL() | 0x10020400 ); /* CTB=Equal,IW1=Match B,SIW1EN */
 
255
    break;
 
256
 
 
257
  case 3:
 
258
    SET_CMPC( addr );
 
259
    SET_ICTRL( GET_ICTRL() | 0x02008200 ); /* CTC=Equal,IW2=Match C,SIW2EN */
 
260
    break;
 
261
 
 
262
  case 4:
 
263
    SET_CMPD( addr );
 
264
    SET_ICTRL( GET_ICTRL() | 0x00404100 ); /* CTD=Equal,IW3=Match D,SIW3EN */
 
265
    break;
 
266
  }
 
267
 
 
268
  return which_bp;
 
269
} /* bedbug860_set */
 
270
 
 
271
 
 
272
 
 
273
/* ======================================================================
 
274
 * Disable a specific breakoint by setting the appropriate IACx register
 
275
 * to zero and claring the instruction address breakpoint in DBCR0.
 
276
 * ====================================================================== */
 
277
 
 
278
int bedbug860_clear( int which_bp )
 
279
{
 
280
  /* -------------------------------------------------- */
 
281
 
 
282
  if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
 
283
  {
 
284
    printf( "Invalid break point # (%d)\n", which_bp );
 
285
    return -1;
 
286
  }
 
287
 
 
288
  switch( which_bp )
 
289
  {
 
290
  case 1:
 
291
    SET_CMPA( 0 );
 
292
    SET_ICTRL( GET_ICTRL() & ~0x80080800 ); /* CTA=Equal,IW0=Match A,SIW0EN */
 
293
    break;
 
294
 
 
295
  case 2:
 
296
    SET_CMPB( 0 );
 
297
    SET_ICTRL( GET_ICTRL() & ~0x10020400 ); /* CTB=Equal,IW1=Match B,SIW1EN */
 
298
    break;
 
299
 
 
300
  case 3:
 
301
    SET_CMPC( 0 );
 
302
    SET_ICTRL( GET_ICTRL() & ~0x02008200 ); /* CTC=Equal,IW2=Match C,SIW2EN */
 
303
    break;
 
304
 
 
305
  case 4:
 
306
    SET_CMPD( 0 );
 
307
    SET_ICTRL( GET_ICTRL() & ~0x00404100 ); /* CTD=Equal,IW3=Match D,SIW3EN */
 
308
    break;
 
309
  }
 
310
 
 
311
  return 0;
 
312
} /* bedbug860_clear */
 
313
 
 
314
 
 
315
/* ====================================================================== */
 
316
#endif