xscale.c 97.6 KB
Newer Older
drath's avatar
drath committed
1
/***************************************************************************
2
 *   Copyright (C) 2006, 2007 by Dominic Rath                              *
drath's avatar
drath committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
20
#ifdef HAVE_CONFIG_H
drath's avatar
drath committed
21
#include "config.h"
22
23
24
#endif

#include "replacements.h"
drath's avatar
drath committed
25
26
27
28
29
30
31

#include "xscale.h"

#include "register.h"
#include "target.h"
#include "armv4_5.h"
#include "arm_simulator.h"
32
#include "arm_disassembler.h"
drath's avatar
drath committed
33
34
35
36
37
#include "log.h"
#include "jtag.h"
#include "binarybuffer.h"
#include "time_support.h"
#include "breakpoints.h"
38
#include "fileio.h"
drath's avatar
drath committed
39
40
41
42
43
44
45
46

#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

47

drath's avatar
drath committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* cli handling */
int xscale_register_commands(struct command_context_s *cmd_ctx);

/* forward declarations */
int xscale_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
int xscale_quit();

int xscale_arch_state(struct target_s *target, char *buf, int buf_size);
enum target_state xscale_poll(target_t *target);
int xscale_halt(target_t *target);
int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
int xscale_debug_entry(target_t *target);
int xscale_restore_context(target_t *target);

int xscale_assert_reset(target_t *target);
int xscale_deassert_reset(target_t *target);
int xscale_soft_reset_halt(struct target_s *target);
67
int xscale_prepare_reset_halt(struct target_s *target);
drath's avatar
drath committed
68
69
70
71
72
73
74
75
76

int xscale_set_reg_u32(reg_t *reg, u32 value);

int xscale_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode);
int xscale_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, u32 value);

int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
ntfreak's avatar
ntfreak committed
77
int xscale_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
drath's avatar
drath committed
78
79
80
81
82
83
84
85
86

int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
void xscale_enable_watchpoints(struct target_s *target);
void xscale_enable_breakpoints(struct target_s *target);
ntfreak's avatar
ntfreak committed
87
88
static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical);
static int xscale_mmu(struct target_s *target, int *enabled);
drath's avatar
drath committed
89

90
91
int xscale_read_trace(target_t *target);

drath's avatar
drath committed
92
93
94
95
96
97
target_type_t xscale_target =
{
	.name = "xscale",

	.poll = xscale_poll,
	.arch_state = xscale_arch_state,
98
99

	.target_request_data = NULL,
drath's avatar
drath committed
100
101
102
103
104
105
106
107

	.halt = xscale_halt,
	.resume = xscale_resume,
	.step = xscale_step,

	.assert_reset = xscale_assert_reset,
	.deassert_reset = xscale_deassert_reset,
	.soft_reset_halt = xscale_soft_reset_halt,
108
	.prepare_reset_halt = xscale_prepare_reset_halt,
drath's avatar
drath committed
109
110

	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
111

drath's avatar
drath committed
112
113
114
	.read_memory = xscale_read_memory,
	.write_memory = xscale_write_memory,
	.bulk_write_memory = xscale_bulk_write_memory,
ntfreak's avatar
ntfreak committed
115
	.checksum_memory = xscale_checksum_memory,
116

drath's avatar
drath committed
117
	.run_algorithm = armv4_5_run_algorithm,
118

drath's avatar
drath committed
119
120
121
122
123
124
125
126
	.add_breakpoint = xscale_add_breakpoint,
	.remove_breakpoint = xscale_remove_breakpoint,
	.add_watchpoint = xscale_add_watchpoint,
	.remove_watchpoint = xscale_remove_watchpoint,

	.register_commands = xscale_register_commands,
	.target_command = xscale_target_command,
	.init_target = xscale_init_target,
ntfreak's avatar
ntfreak committed
127
128
129
130
	.quit = xscale_quit,
	
	.virt2phys = xscale_virt2phys,
	.mmu = xscale_mmu
drath's avatar
drath committed
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
};

char* xscale_reg_list[] =
{
	"XSCALE_MAINID",		/* 0 */
	"XSCALE_CACHETYPE",
	"XSCALE_CTRL",
	"XSCALE_AUXCTRL",
	"XSCALE_TTB",
	"XSCALE_DAC",
	"XSCALE_FSR",
	"XSCALE_FAR",
	"XSCALE_PID",
	"XSCALE_CPACCESS",
	"XSCALE_IBCR0",			/* 10 */
	"XSCALE_IBCR1",
	"XSCALE_DBR0",
	"XSCALE_DBR1",
	"XSCALE_DBCON",
	"XSCALE_TBREG",
151
	"XSCALE_CHKPT0",
drath's avatar
drath committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
	"XSCALE_CHKPT1",
	"XSCALE_DCSR",
	"XSCALE_TX",
	"XSCALE_RX",			/* 20 */
	"XSCALE_TXRXCTRL",
};

xscale_reg_t xscale_reg_arch_info[] =
{
	{XSCALE_MAINID, NULL},
	{XSCALE_CACHETYPE, NULL},
	{XSCALE_CTRL, NULL},
	{XSCALE_AUXCTRL, NULL},
	{XSCALE_TTB, NULL},
	{XSCALE_DAC, NULL},
	{XSCALE_FSR, NULL},
	{XSCALE_FAR, NULL},
	{XSCALE_PID, NULL},
	{XSCALE_CPACCESS, NULL},
	{XSCALE_IBCR0, NULL},
	{XSCALE_IBCR1, NULL},
	{XSCALE_DBR0, NULL},
	{XSCALE_DBR1, NULL},
	{XSCALE_DBCON, NULL},
	{XSCALE_TBREG, NULL},
	{XSCALE_CHKPT0, NULL},
	{XSCALE_CHKPT1, NULL},
	{XSCALE_DCSR, NULL}, /* DCSR accessed via JTAG or SW */
	{-1, NULL}, /* TX accessed via JTAG */
	{-1, NULL}, /* RX accessed via JTAG */
	{-1, NULL}, /* TXRXCTRL implicit access via JTAG */
};

int xscale_reg_arch_type = -1;

int xscale_get_reg(reg_t *reg);
int xscale_set_reg(reg_t *reg, u8 *buf);

int xscale_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, xscale_common_t **xscale_p)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
194

drath's avatar
drath committed
195
196
	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
	{
ntfreak's avatar
ntfreak committed
197
		ERROR("target isn't an XScale target");
drath's avatar
drath committed
198
199
		return -1;
	}
200

drath's avatar
drath committed
201
202
	if (xscale->common_magic != XSCALE_COMMON_MAGIC)
	{
ntfreak's avatar
ntfreak committed
203
		ERROR("target isn't an XScale target");
drath's avatar
drath committed
204
205
		return -1;
	}
206

drath's avatar
drath committed
207
208
	*armv4_5_p = armv4_5;
	*xscale_p = xscale;
209

drath's avatar
drath committed
210
211
212
213
214
215
	return ERROR_OK;
}

int xscale_jtag_set_instr(int chain_pos, u32 new_instr)
{
	jtag_device_t *device = jtag_get_device(chain_pos);
216

drath's avatar
drath committed
217
218
219
	if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
	{
		scan_field_t field;
220

drath's avatar
drath committed
221
222
223
224
225
226
		field.device = chain_pos;
		field.num_bits = device->ir_length;
		field.out_value = calloc(CEIL(field.num_bits, 8), 1);
		buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
		field.out_mask = NULL;
		field.in_value = NULL;
mifi's avatar
mifi committed
227
		jtag_set_check_value(&field, device->expected, device->expected_mask, NULL);
228

229
		jtag_add_ir_scan(1, &field, -1, NULL);
230

drath's avatar
drath committed
231
232
		free(field.out_value);
	}
233

drath's avatar
drath committed
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
	return ERROR_OK;
}

int xscale_jtag_callback(enum jtag_event event, void *priv)
{
	switch (event)
	{
		case JTAG_TRST_ASSERTED:
			break;
		case JTAG_TRST_RELEASED:
			break;
		case JTAG_SRST_ASSERTED:
			break;
		case JTAG_SRST_RELEASED:
			break;
		default:
			WARNING("unhandled JTAG event");
	}
252

drath's avatar
drath committed
253
254
255
256
257
258
259
	return ERROR_OK;
}

int xscale_read_dcsr(target_t *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
260

drath's avatar
drath committed
261
	int retval;
262

drath's avatar
drath committed
263
264
265
266
267
268
269
270
271
272
	scan_field_t fields[3];
	u8 field0 = 0x0;
	u8 field0_check_value = 0x2;
	u8 field0_check_mask = 0x7;
	u8 field2 = 0x0;
	u8 field2_check_value = 0x0;
	u8 field2_check_mask = 0x1;

	jtag_add_end_state(TAP_PD);
	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);
273

drath's avatar
drath committed
274
275
	buf_set_u32(&field0, 1, 1, xscale->hold_rst);
	buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
276

drath's avatar
drath committed
277
278
279
280
281
	fields[0].device = xscale->jtag_info.chain_pos;
	fields[0].num_bits = 3;
	fields[0].out_value = &field0;
	fields[0].out_mask = NULL;
	fields[0].in_value = NULL;
mifi's avatar
mifi committed
282
	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
283

drath's avatar
drath committed
284
285
286
287
288
289
290
291
292
	fields[1].device = xscale->jtag_info.chain_pos;
	fields[1].num_bits = 32;
	fields[1].out_value = NULL;
	fields[1].out_mask = NULL;
	fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
	fields[1].in_handler = NULL;
	fields[1].in_handler_priv = NULL;
	fields[1].in_check_value = NULL;
	fields[1].in_check_mask = NULL;
293
294


drath's avatar
drath committed
295
296
297
298
299
300

	fields[2].device = xscale->jtag_info.chain_pos;
	fields[2].num_bits = 1;
	fields[2].out_value = &field2;
	fields[2].out_mask = NULL;
	fields[2].in_value = NULL;
mifi's avatar
mifi committed
301
	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
302

303
	jtag_add_dr_scan(3, fields, -1, NULL);
drath's avatar
drath committed
304
305
306
307

	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
		ERROR("JTAG error while reading DCSR");
308
		return retval;
drath's avatar
drath committed
309
	}
310

drath's avatar
drath committed
311
312
	xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;
	xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;
313

drath's avatar
drath committed
314
315
316
317
318
319
	/* write the register with the value we just read
	 * on this second pass, only the first bit of field0 is guaranteed to be 0)
	 */
	field0_check_mask = 0x1;
	fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
	fields[1].in_value = NULL;
320

drath's avatar
drath committed
321
	jtag_add_end_state(TAP_RTI);
322

323
	jtag_add_dr_scan(3, fields, -1, NULL);
324

drath's avatar
drath committed
325
326
327
328
329
	return ERROR_OK;
}

int xscale_receive(target_t *target, u32 *buffer, int num_words)
{
330
	int retval = ERROR_OK;
drath's avatar
drath committed
331
332
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
333

drath's avatar
drath committed
334
335
	enum tap_state path[3];
	scan_field_t fields[3];
336

drath's avatar
drath committed
337
338
339
340
341
342
343
344
	u8 *field0 = malloc(num_words * 1);
	u8 field0_check_value = 0x2;
	u8 field0_check_mask = 0x6;
	u32 *field1 = malloc(num_words * 4);
	u8 field2_check_value = 0x0;
	u8 field2_check_mask = 0x1;
	int words_done = 0;
	int words_scheduled = 0;
345

drath's avatar
drath committed
346
347
348
349
350
	int i;

	path[0] = TAP_SDS;
	path[1] = TAP_CD;
	path[2] = TAP_SD;
351

drath's avatar
drath committed
352
353
354
355
356
	fields[0].device = xscale->jtag_info.chain_pos;
	fields[0].num_bits = 3;
	fields[0].out_value = NULL;
	fields[0].out_mask = NULL;
	/* fields[0].in_value = field0; */
mifi's avatar
mifi committed
357
	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
358

drath's avatar
drath committed
359
360
361
362
363
364
365
366
367
	fields[1].device = xscale->jtag_info.chain_pos;
	fields[1].num_bits = 32;
	fields[1].out_value = NULL;
	fields[1].out_mask = NULL;
	fields[1].in_value = NULL;
	fields[1].in_handler = NULL;
	fields[1].in_handler_priv = NULL;
	fields[1].in_check_value = NULL;
	fields[1].in_check_mask = NULL;
368
369


drath's avatar
drath committed
370
371
372
373
374
375

	fields[2].device = xscale->jtag_info.chain_pos;
	fields[2].num_bits = 1;
	fields[2].out_value = NULL;
	fields[2].out_mask = NULL;
	fields[2].in_value = NULL;
mifi's avatar
mifi committed
376
	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
drath's avatar
drath committed
377
378
379
380

	jtag_add_end_state(TAP_RTI);
	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgtx);
	jtag_add_runtest(1, -1);
381

drath's avatar
drath committed
382
	/* repeat until all words have been collected */
383
	int attempts = 0;
drath's avatar
drath committed
384
385
386
387
388
389
390
391
392
	while (words_done < num_words)
	{
		/* schedule reads */
		words_scheduled = 0;
		for (i = words_done; i < num_words; i++)
		{
			fields[0].in_value = &field0[i];
			fields[1].in_handler = buf_to_u32_handler;
			fields[1].in_handler_priv = (u8*)&field1[i];
393

drath's avatar
drath committed
394
			jtag_add_pathmove(3, path);
395
			jtag_add_dr_scan(3, fields, TAP_RTI, NULL);
drath's avatar
drath committed
396
397
			words_scheduled++;
		}
398

drath's avatar
drath committed
399
400
401
		if ((retval = jtag_execute_queue()) != ERROR_OK)
		{
			ERROR("JTAG error while receiving data from debug handler");
402
			break;
drath's avatar
drath committed
403
		}
404

drath's avatar
drath committed
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
		/* examine results */
		for (i = words_done; i < num_words; i++)
		{
			if (!(field0[0] & 1))
			{
				/* move backwards if necessary */
				int j;
				for (j = i; j < num_words - 1; j++)
				{
					field0[j] = field0[j+1];
					field1[j] = field1[j+1];
				}
				words_scheduled--;
			}
		}
420
421
422
423
424
425
426
427
428
429
		if (words_scheduled == 0)
		{
			if (attempts++ == 1000)
			{
				ERROR("Failed to receiving data from debug handler after 1000 attempts");
				retval = ERROR_JTAG_QUEUE_FAILED;
				break;
			}
		}
		
drath's avatar
drath committed
430
431
		words_done += words_scheduled;
	}
432

drath's avatar
drath committed
433
434
	for (i = 0; i < num_words; i++)
		*(buffer++) = buf_get_u32((u8*)&field1[i], 0, 32);
435

drath's avatar
drath committed
436
	free(field1);
437

438
	return retval;
drath's avatar
drath committed
439
440
441
442
443
444
445
}

int xscale_read_tx(target_t *target, int consume)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
	enum tap_state path[3];
ntfreak's avatar
ntfreak committed
446
	enum tap_state noconsume_path[9];
447

drath's avatar
drath committed
448
449
	int retval;
	struct timeval timeout, now;
450

drath's avatar
drath committed
451
452
453
454
455
456
	scan_field_t fields[3];
	u8 field0_in = 0x0;
	u8 field0_check_value = 0x2;
	u8 field0_check_mask = 0x6;
	u8 field2_check_value = 0x0;
	u8 field2_check_mask = 0x1;
457

drath's avatar
drath committed
458
	jtag_add_end_state(TAP_RTI);
459

drath's avatar
drath committed
460
	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgtx);
461

drath's avatar
drath committed
462
463
464
	path[0] = TAP_SDS;
	path[1] = TAP_CD;
	path[2] = TAP_SD;
465

466
467
468
469
470
	noconsume_path[0] = TAP_SDS;
	noconsume_path[1] = TAP_CD;
	noconsume_path[2] = TAP_E1D;
	noconsume_path[3] = TAP_PD;
	noconsume_path[4] = TAP_E2D;
ntfreak's avatar
ntfreak committed
471
472
473
474
	noconsume_path[5] = TAP_UD;
	noconsume_path[6] = TAP_SDS;
	noconsume_path[7] = TAP_CD;
	noconsume_path[8] = TAP_SD;
475

drath's avatar
drath committed
476
477
478
479
480
	fields[0].device = xscale->jtag_info.chain_pos;
	fields[0].num_bits = 3;
	fields[0].out_value = NULL;
	fields[0].out_mask = NULL;
	fields[0].in_value = &field0_in;
mifi's avatar
mifi committed
481
	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
482

drath's avatar
drath committed
483
484
485
486
487
488
489
490
491
	fields[1].device = xscale->jtag_info.chain_pos;
	fields[1].num_bits = 32;
	fields[1].out_value = NULL;
	fields[1].out_mask = NULL;
	fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_TX].value;
	fields[1].in_handler = NULL;
	fields[1].in_handler_priv = NULL;
	fields[1].in_check_value = NULL;
	fields[1].in_check_mask = NULL;
492
493


drath's avatar
drath committed
494
495
496
497
498
499

	fields[2].device = xscale->jtag_info.chain_pos;
	fields[2].num_bits = 1;
	fields[2].out_value = NULL;
	fields[2].out_mask = NULL;
	fields[2].in_value = NULL;
mifi's avatar
mifi committed
500
	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
501

drath's avatar
drath committed
502
503
	gettimeofday(&timeout, NULL);
	timeval_add_time(&timeout, 5, 0);
504

drath's avatar
drath committed
505
506
507
508
509
510
511
512
513
	do
	{
		/* if we want to consume the register content (i.e. clear TX_READY),
		 * we have to go straight from Capture-DR to Shift-DR
		 * otherwise, we go from Capture-DR to Exit1-DR to Pause-DR
		*/
		if (consume)
			jtag_add_pathmove(3, path);
		else
ntfreak's avatar
ntfreak committed
514
			jtag_add_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path);
515

516
		jtag_add_dr_scan(3, fields, TAP_RTI, NULL);
517

drath's avatar
drath committed
518
519
520
		if ((retval = jtag_execute_queue()) != ERROR_OK)
		{
			ERROR("JTAG error while reading TX");
521
			return ERROR_TARGET_TIMEOUT;
drath's avatar
drath committed
522
		}
523

drath's avatar
drath committed
524
		gettimeofday(&now, NULL);
525
		if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))
drath's avatar
drath committed
526
527
528
529
530
		{
			ERROR("time out reading TX register");
			return ERROR_TARGET_TIMEOUT;
		}
	} while ((!(field0_in & 1)) && consume);
531

drath's avatar
drath committed
532
533
	if (!(field0_in & 1))
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
534

drath's avatar
drath committed
535
536
537
538
539
540
541
	return ERROR_OK;
}

int xscale_write_rx(target_t *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
542

drath's avatar
drath committed
543
544
	int retval;
	struct timeval timeout, now;
545

drath's avatar
drath committed
546
547
548
549
550
551
552
553
	scan_field_t fields[3];
	u8 field0_out = 0x0;
	u8 field0_in = 0x0;
	u8 field0_check_value = 0x2;
	u8 field0_check_mask = 0x6;
	u8 field2 = 0x0;
	u8 field2_check_value = 0x0;
	u8 field2_check_mask = 0x1;
554

drath's avatar
drath committed
555
	jtag_add_end_state(TAP_RTI);
556

drath's avatar
drath committed
557
	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgrx);
558

drath's avatar
drath committed
559
560
561
562
563
	fields[0].device = xscale->jtag_info.chain_pos;
	fields[0].num_bits = 3;
	fields[0].out_value = &field0_out;
	fields[0].out_mask = NULL;
	fields[0].in_value = &field0_in;
mifi's avatar
mifi committed
564
	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
565

drath's avatar
drath committed
566
567
568
569
570
571
572
573
574
	fields[1].device = xscale->jtag_info.chain_pos;
	fields[1].num_bits = 32;
	fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_RX].value;
	fields[1].out_mask = NULL;
	fields[1].in_value = NULL;
	fields[1].in_handler = NULL;
	fields[1].in_handler_priv = NULL;
	fields[1].in_check_value = NULL;
	fields[1].in_check_mask = NULL;
575
576


drath's avatar
drath committed
577
578
579
580
581
582

	fields[2].device = xscale->jtag_info.chain_pos;
	fields[2].num_bits = 1;
	fields[2].out_value = &field2;
	fields[2].out_mask = NULL;
	fields[2].in_value = NULL;
mifi's avatar
mifi committed
583
	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
584

drath's avatar
drath committed
585
586
	gettimeofday(&timeout, NULL);
	timeval_add_time(&timeout, 5, 0);
587

drath's avatar
drath committed
588
	/* poll until rx_read is low */
589
	DEBUG("polling RX");
drath's avatar
drath committed
590
591
	do
	{
592
		jtag_add_dr_scan(3, fields, TAP_RTI, NULL);
593

drath's avatar
drath committed
594
595
596
		if ((retval = jtag_execute_queue()) != ERROR_OK)
		{
			ERROR("JTAG error while writing RX");
597
			return retval;
drath's avatar
drath committed
598
		}
599

drath's avatar
drath committed
600
		gettimeofday(&now, NULL);
601
		if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))
drath's avatar
drath committed
602
603
604
605
606
		{
			ERROR("time out writing RX register");
			return ERROR_TARGET_TIMEOUT;
		}
	} while (field0_in & 1);
607

drath's avatar
drath committed
608
609
	/* set rx_valid */
	field2 = 0x1;
610
	jtag_add_dr_scan(3, fields, TAP_RTI, NULL);
611

drath's avatar
drath committed
612
613
614
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
		ERROR("JTAG error while writing RX");
615
		return retval;
drath's avatar
drath committed
616
	}
617

drath's avatar
drath committed
618
619
620
621
622
623
624
625
	return ERROR_OK;
}

/* send count elements of size byte to the debug handler */
int xscale_send(target_t *target, u8 *buffer, int count, int size)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
626

drath's avatar
drath committed
627
	int retval;
628

drath's avatar
drath committed
629
630
	int done_count = 0;
	u8 output[4] = {0, 0, 0, 0};
631

drath's avatar
drath committed
632
633
634
635
636
637
638
639
	scan_field_t fields[3];
	u8 field0_out = 0x0;
	u8 field0_in = 0x0;
	u8 field0_check_value = 0x2;
	u8 field0_check_mask = 0x6;
	u8 field2 = 0x1;
	u8 field2_check_value = 0x0;
	u8 field2_check_mask = 0x1;
640

drath's avatar
drath committed
641
	jtag_add_end_state(TAP_RTI);
642

drath's avatar
drath committed
643
	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgrx);
644

drath's avatar
drath committed
645
646
647
648
649
	fields[0].device = xscale->jtag_info.chain_pos;
	fields[0].num_bits = 3;
	fields[0].out_value = &field0_out;
	fields[0].out_mask = NULL;
	fields[0].in_value = &field0_in;
mifi's avatar
mifi committed
650
	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
651

drath's avatar
drath committed
652
653
654
655
656
657
658
659
660
	fields[1].device = xscale->jtag_info.chain_pos;
	fields[1].num_bits = 32;
	fields[1].out_value = output;
	fields[1].out_mask = NULL;
	fields[1].in_value = NULL;
	fields[1].in_handler = NULL;
	fields[1].in_handler_priv = NULL;
	fields[1].in_check_value = NULL;
	fields[1].in_check_mask = NULL;
661
662


drath's avatar
drath committed
663
664
665
666
667
668

	fields[2].device = xscale->jtag_info.chain_pos;
	fields[2].num_bits = 1;
	fields[2].out_value = &field2;
	fields[2].out_mask = NULL;
	fields[2].in_value = NULL;
mifi's avatar
mifi committed
669
	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
670

drath's avatar
drath committed
671
672
	while (done_count++ < count)
	{
673
		/* extract sized element from target-endian buffer, and put it
drath's avatar
drath committed
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
		 * into little-endian output buffer
		 */
		switch (size)
		{
			case 4:
				buf_set_u32(output, 0, 32, target_buffer_get_u32(target, buffer));
				break;
			case 2:
				buf_set_u32(output, 0, 32, target_buffer_get_u16(target, buffer));
				break;
			case 1:
				output[0] = *buffer;
				break;
			default:
				ERROR("BUG: size neither 4, 2 nor 1");
689
				exit(-1);
drath's avatar
drath committed
690
691
		}

692
		jtag_add_dr_scan(3, fields, TAP_RTI, NULL);
drath's avatar
drath committed
693
694
		buffer += size;
	}
695

drath's avatar
drath committed
696
697
698
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
		ERROR("JTAG error while sending data to debug handler");
699
		return retval;
drath's avatar
drath committed
700
	}
701

drath's avatar
drath committed
702
703
704
705
706
707
708
	return ERROR_OK;
}

int xscale_send_u32(target_t *target, u32 value)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
709

drath's avatar
drath committed
710
711
712
713
714
715
716
717
	buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value);
	return xscale_write_rx(target);
}

int xscale_write_dcsr(target_t *target, int hold_rst, int ext_dbg_brk)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
718

drath's avatar
drath committed
719
	int retval;
720

drath's avatar
drath committed
721
722
723
724
725
726
727
	scan_field_t fields[3];
	u8 field0 = 0x0;
	u8 field0_check_value = 0x2;
	u8 field0_check_mask = 0x7;
	u8 field2 = 0x0;
	u8 field2_check_value = 0x0;
	u8 field2_check_mask = 0x1;
728

drath's avatar
drath committed
729
730
	if (hold_rst != -1)
		xscale->hold_rst = hold_rst;
731

drath's avatar
drath committed
732
733
734
735
736
	if (ext_dbg_brk != -1)
		xscale->external_debug_break = ext_dbg_brk;

	jtag_add_end_state(TAP_RTI);
	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);
737

drath's avatar
drath committed
738
739
	buf_set_u32(&field0, 1, 1, xscale->hold_rst);
	buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
740

drath's avatar
drath committed
741
742
743
744
745
	fields[0].device = xscale->jtag_info.chain_pos;
	fields[0].num_bits = 3;
	fields[0].out_value = &field0;
	fields[0].out_mask = NULL;
	fields[0].in_value = NULL;
mifi's avatar
mifi committed
746
	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
747

drath's avatar
drath committed
748
749
750
751
752
753
754
755
756
	fields[1].device = xscale->jtag_info.chain_pos;
	fields[1].num_bits = 32;
	fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
	fields[1].out_mask = NULL;
	fields[1].in_value = NULL;
	fields[1].in_handler = NULL;
	fields[1].in_handler_priv = NULL;
	fields[1].in_check_value = NULL;
	fields[1].in_check_mask = NULL;
757
758


drath's avatar
drath committed
759
760
761
762
763
764

	fields[2].device = xscale->jtag_info.chain_pos;
	fields[2].num_bits = 1;
	fields[2].out_value = &field2;
	fields[2].out_mask = NULL;
	fields[2].in_value = NULL;
mifi's avatar
mifi committed
765
	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
766

767
	jtag_add_dr_scan(3, fields, -1, NULL);
768

drath's avatar
drath committed
769
770
771
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
		ERROR("JTAG error while writing DCSR");
772
		return retval;
drath's avatar
drath committed
773
	}
774

drath's avatar
drath committed
775
776
	xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;
	xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;
777

drath's avatar
drath committed
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
	return ERROR_OK;
}

/* parity of the number of bits 0 if even; 1 if odd. for 32 bit words */
unsigned int parity (unsigned int v)
{
	unsigned int ov = v;
	v ^= v >> 16;
	v ^= v >> 8;
	v ^= v >> 4;
	v &= 0xf;
	DEBUG("parity of 0x%x is %i", ov, (0x6996 >> v) & 1);
	return (0x6996 >> v) & 1;
}

int xscale_load_ic(target_t *target, int mini, u32 va, u32 buffer[8])
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
	u8 packet[4];
	u8 cmd;
	int word;
800

drath's avatar
drath committed
801
802
803
804
805
806
	scan_field_t fields[2];

	DEBUG("loading miniIC at 0x%8.8x", va);

	jtag_add_end_state(TAP_RTI);
	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.ldic); /* LDIC */
807

drath's avatar
drath committed
808
809
810
811
812
	/* CMD is b010 for Main IC and b011 for Mini IC */
	if (mini)
		buf_set_u32(&cmd, 0, 3, 0x3);
	else
		buf_set_u32(&cmd, 0, 3, 0x2);
813

drath's avatar
drath committed
814
	buf_set_u32(&cmd, 3, 3, 0x0);
815

drath's avatar
drath committed
816
817
	/* virtual address of desired cache line */
	buf_set_u32(packet, 0, 27, va >> 5);
818

drath's avatar
drath committed
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
	fields[0].device = xscale->jtag_info.chain_pos;
	fields[0].num_bits = 6;
	fields[0].out_value = &cmd;
	fields[0].out_mask = NULL;
	fields[0].in_value = NULL;
	fields[0].in_check_value = NULL;
	fields[0].in_check_mask = NULL;
	fields[0].in_handler = NULL;
	fields[0].in_handler_priv = NULL;

	fields[1].device = xscale->jtag_info.chain_pos;
	fields[1].num_bits = 27;
	fields[1].out_value = packet;
	fields[1].out_mask = NULL;
	fields[1].in_value = NULL;
	fields[1].in_check_value = NULL;
	fields[1].in_check_mask = NULL;
	fields[1].in_handler = NULL;
	fields[1].in_handler_priv = NULL;
838

839
	jtag_add_dr_scan(2, fields, -1, NULL);
drath's avatar
drath committed
840
841
842

	fields[0].num_bits = 32;
	fields[0].out_value = packet;
843

drath's avatar
drath committed
844
845
	fields[1].num_bits = 1;
	fields[1].out_value = &cmd;
846

drath's avatar
drath committed
847
848
849
850
	for (word = 0; word < 8; word++)
	{
		buf_set_u32(packet, 0, 32, buffer[word]);
		cmd = parity(*((u32*)packet));
851
		jtag_add_dr_scan(2, fields, -1, NULL);
drath's avatar
drath committed
852
	}
853

drath's avatar
drath committed
854
	jtag_execute_queue();
855

drath's avatar
drath committed
856
857
858
859
860
861
862
863
864
	return ERROR_OK;
}

int xscale_invalidate_ic_line(target_t *target, u32 va)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
	u8 packet[4];
	u8 cmd;
865

drath's avatar
drath committed
866
867
868
869
	scan_field_t fields[2];

	jtag_add_end_state(TAP_RTI);
	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.ldic); /* LDIC */
870

drath's avatar
drath committed
871
872
	/* CMD for invalidate IC line b000, bits [6:4] b000 */
	buf_set_u32(&cmd, 0, 6, 0x0);
873

drath's avatar
drath committed
874
875
	/* virtual address of desired cache line */
	buf_set_u32(packet, 0, 27, va >> 5);
876

drath's avatar
drath committed
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
	fields[0].device = xscale->jtag_info.chain_pos;
	fields[0].num_bits = 6;
	fields[0].out_value = &cmd;
	fields[0].out_mask = NULL;
	fields[0].in_value = NULL;
	fields[0].in_check_value = NULL;
	fields[0].in_check_mask = NULL;
	fields[0].in_handler = NULL;
	fields[0].in_handler_priv = NULL;

	fields[1].device = xscale->jtag_info.chain_pos;
	fields[1].num_bits = 27;
	fields[1].out_value = packet;
	fields[1].out_mask = NULL;
	fields[1].in_value = NULL;
	fields[1].in_check_value = NULL;
	fields[1].in_check_mask = NULL;
	fields[1].in_handler = NULL;
	fields[1].in_handler_priv = NULL;
896

897
	jtag_add_dr_scan(2, fields, -1, NULL);
898

drath's avatar
drath committed
899
900
901
902
903
904
905
906
	return ERROR_OK;
}

int xscale_update_vectors(target_t *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
	int i;
907

drath's avatar
drath committed
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
	u32 low_reset_branch, high_reset_branch;

	for (i = 1; i < 8; i++)
	{
		/* if there's a static vector specified for this exception, override */
		if (xscale->static_high_vectors_set & (1 << i))
		{
			xscale->high_vectors[i] = xscale->static_high_vectors[i];
		}
		else
		{
			if (target_read_u32(target, 0xffff0000 + 4*i, &xscale->high_vectors[i]) != ERROR_OK)
			{
				xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);
			}
		}
	}

	for (i = 1; i < 8; i++)
	{
		if (xscale->static_low_vectors_set & (1 << i))
		{
			xscale->low_vectors[i] = xscale->static_low_vectors[i];
		}
		else
		{
			if (target_read_u32(target, 0x0 + 4*i, &xscale->low_vectors[i]) != ERROR_OK)
			{
				xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);
			}
		}
	}
940

drath's avatar
drath committed
941
942
943
	/* calculate branches to debug handler */
	low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2;
	high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2;
944

drath's avatar
drath committed
945
946
	xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0);
	xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0);
947

drath's avatar
drath committed
948
949
950
	/* invalidate and load exception vectors in mini i-cache */
	xscale_invalidate_ic_line(target, 0x0);
	xscale_invalidate_ic_line(target, 0xffff0000);
951

drath's avatar
drath committed
952
953
	xscale_load_ic(target, 1, 0x0, xscale->low_vectors);
	xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);
954

drath's avatar
drath committed
955
956
957
958
959
960
961
	return ERROR_OK;
}

int xscale_arch_state(struct target_s *target, char *buf, int buf_size)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	xscale_common_t *xscale = armv4_5->arch_info;
962
963

	char *state[] =
drath's avatar
drath committed
964
965
966
	{
		"disabled", "enabled"
	};
967

drath's avatar
drath committed
968
969
970
971
	char *arch_dbg_reason[] =
	{
		"", "\n(processor reset)", "\n(trace buffer full)"
	};
972

drath's avatar
drath committed
973
974
975
976
977
	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
	{
		ERROR("BUG: called for a non-ARMv4/5 target");
		exit(-1);
	}
978

drath's avatar
drath committed
979
980
981
982
983
984
985
986
987
988
989
	snprintf(buf, buf_size,
			"target halted in %s state due to %s, current mode: %s\n"
			"cpsr: 0x%8.8x pc: 0x%8.8x\n"
			"MMU: %s, D-Cache: %s, I-Cache: %s"
			"%s",
			 armv4_5_state_strings[armv4_5->core_state],
			 target_debug_reason_strings[target->debug_reason],
			 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
			 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
			 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
			 state[xscale->armv4_5_mmu.mmu_enabled],
990
			 state[xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
drath's avatar
drath committed
991
992
			 state[xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled],
			 arch_dbg_reason[xscale->arch_debug_reason]);
993

drath's avatar
drath committed
994
995
996
997
998
999
1000
	return ERROR_OK;
}

enum target_state xscale_poll(target_t *target)
{
	int retval;
	armv4_5_common_t *armv4_5 = target->arch_info;
For faster browsing, not all history is shown. View entire blame