arm920t.c 41.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   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.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "arm920t.h"
oharboe's avatar
oharboe committed
25
#include "time_support.h"
26
#include "target_type.h"
27
#include "register.h"
28
29


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*
 * For information about the ARM920T, see ARM DDI 0151C especially
 * Chapter 9 about debug support, which shows how to manipulate each
 * of the different scan chains:
 *
 *   0 ... ARM920 signals, e.g. to rest of SOC (unused here)
 *   1 ... debugging; watchpoint and breakpoint status, etc; also
 *	MMU and cache access in conjunction with scan chain 15
 *   2 ... EmbeddedICE
 *   3 ... external boundary scan (SoC-specific, unused here)
 *   4 ... access to cache tag RAM
 *   6 ... ETM9
 *   15 ... access coprocessor 15, "physical" or "interpreted" modes
 *	"interpreted" works with a few actual MRC/MCR instructions
 *	"physical" provides register-like behaviors.
 *
 * The ARM922T is similar, but with smaller caches (8K each, vs 16K).
 */

49
50
51
52
53
54
#if 0
#define _DEBUG_INSTRUCTION_EXECUTION_
#endif

#define ARM920T_CP15_PHYS_ADDR(x, y, z) ((x << 5) | (y << 1) << (z))

Zachary T Welch's avatar
Zachary T Welch committed
55
static int arm920t_read_cp15_physical(struct target *target,
56
		int reg_addr, uint32_t *value)
57
{
58
	struct arm920t_common *arm920t = target_to_arm920(target);
59
	struct arm_jtag *jtag_info;
60
	struct scan_field fields[4];
61
62
63
	uint8_t access_type_buf = 1;
	uint8_t reg_addr_buf = reg_addr & 0x3f;
	uint8_t nr_w_buf = 0;
64

65
	jtag_info = &arm920t->arm7_9_common.jtag_info;
66

67
	jtag_set_end_state(TAP_IDLE);
68
69
70
	arm_jtag_scann(jtag_info, 0xf);
	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);

71
	fields[0].tap = jtag_info->tap;
72
73
74
75
	fields[0].num_bits = 1;
	fields[0].out_value = &access_type_buf;
	fields[0].in_value = NULL;

76
	fields[1].tap = jtag_info->tap;
77
78
79
80
	fields[1].num_bits = 32;
	fields[1].out_value = NULL;
	fields[1].in_value = NULL;

81
	fields[2].tap = jtag_info->tap;
82
83
84
85
	fields[2].num_bits = 6;
	fields[2].out_value = &reg_addr_buf;
	fields[2].in_value = NULL;

86
	fields[3].tap = jtag_info->tap;
87
88
89
	fields[3].num_bits = 1;
	fields[3].out_value = &nr_w_buf;
	fields[3].in_value = NULL;
90

91
	jtag_add_dr_scan(4, fields, jtag_get_end_state());
92

93
	fields[1].in_value = (uint8_t *)value;
94

95
	jtag_add_dr_scan(4, fields, jtag_get_end_state());
96

97
	jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
oharboe's avatar
oharboe committed
98

99
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
100
	jtag_execute_queue();
101
	LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
102
103
104
105
106
#endif

	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
107
static int arm920t_write_cp15_physical(struct target *target,
108
		int reg_addr, uint32_t value)
109
{
110
	struct arm920t_common *arm920t = target_to_arm920(target);
111
	struct arm_jtag *jtag_info;
112
	struct scan_field fields[4];
113
114
115
116
	uint8_t access_type_buf = 1;
	uint8_t reg_addr_buf = reg_addr & 0x3f;
	uint8_t nr_w_buf = 1;
	uint8_t value_buf[4];
117

118
	jtag_info = &arm920t->arm7_9_common.jtag_info;
119

120
	buf_set_u32(value_buf, 0, 32, value);
121

122
	jtag_set_end_state(TAP_IDLE);
123
124
125
	arm_jtag_scann(jtag_info, 0xf);
	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);

126
	fields[0].tap = jtag_info->tap;
127
128
129
	fields[0].num_bits = 1;
	fields[0].out_value = &access_type_buf;
	fields[0].in_value = NULL;
oharboe's avatar
oharboe committed
130

131
	fields[1].tap = jtag_info->tap;
132
133
134
	fields[1].num_bits = 32;
	fields[1].out_value = value_buf;
	fields[1].in_value = NULL;
oharboe's avatar
oharboe committed
135

136
	fields[2].tap = jtag_info->tap;
137
138
139
	fields[2].num_bits = 6;
	fields[2].out_value = &reg_addr_buf;
	fields[2].in_value = NULL;
oharboe's avatar
oharboe committed
140

141
	fields[3].tap = jtag_info->tap;
142
143
144
	fields[3].num_bits = 1;
	fields[3].out_value = &nr_w_buf;
	fields[3].in_value = NULL;
oharboe's avatar
oharboe committed
145

146
	jtag_add_dr_scan(4, fields, jtag_get_end_state());
147
148

#ifdef _DEBUG_INSTRUCTION_EXECUTION_
149
	LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
150
151
152
153
154
#endif

	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
155
static int arm920t_execute_cp15(struct target *target, uint32_t cp15_opcode,
156
		uint32_t arm_opcode)
157
{
158
	int retval;
159
	struct arm920t_common *arm920t = target_to_arm920(target);
160
	struct arm_jtag *jtag_info;
161
	struct scan_field fields[4];
162
163
164
165
	uint8_t access_type_buf = 0;		/* interpreted access */
	uint8_t reg_addr_buf = 0x0;
	uint8_t nr_w_buf = 0;
	uint8_t cp15_opcode_buf[4];
166

167
	jtag_info = &arm920t->arm7_9_common.jtag_info;
168

169
	jtag_set_end_state(TAP_IDLE);
170
171
	arm_jtag_scann(jtag_info, 0xf);
	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
172

173
174
	buf_set_u32(cp15_opcode_buf, 0, 32, cp15_opcode);

175
	fields[0].tap = jtag_info->tap;
176
177
178
	fields[0].num_bits = 1;
	fields[0].out_value = &access_type_buf;
	fields[0].in_value = NULL;
oharboe's avatar
oharboe committed
179

180
	fields[1].tap = jtag_info->tap;
181
182
183
	fields[1].num_bits = 32;
	fields[1].out_value = cp15_opcode_buf;
	fields[1].in_value = NULL;
oharboe's avatar
oharboe committed
184

185
	fields[2].tap = jtag_info->tap;
186
187
188
	fields[2].num_bits = 6;
	fields[2].out_value = &reg_addr_buf;
	fields[2].in_value = NULL;
oharboe's avatar
oharboe committed
189

190
	fields[3].tap = jtag_info->tap;
191
192
193
	fields[3].num_bits = 1;
	fields[3].out_value = &nr_w_buf;
	fields[3].in_value = NULL;
oharboe's avatar
oharboe committed
194

195
	jtag_add_dr_scan(4, fields, jtag_get_end_state());
196
197
198

	arm9tdmi_clock_out(jtag_info, arm_opcode, 0, NULL, 0);
	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
199
200
201
	retval = arm7_9_execute_sys_speed(target);
	if (retval != ERROR_OK)
		return retval;
202

203
	if ((retval = jtag_execute_queue()) != ERROR_OK)
204
	{
205
		LOG_ERROR("failed executing JTAG queue");
206
		return retval;
207
	}
208

209
210
211
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
212
static int arm920t_read_cp15_interpreted(struct target *target,
213
		uint32_t cp15_opcode, uint32_t address, uint32_t *value)
214
{
215
	struct arm *armv4_5 = target_to_armv4_5(target);
216
217
218
	uint32_t* regs_p[1];
	uint32_t regs[2];
	uint32_t cp15c15 = 0x0;
David Brownell's avatar
David Brownell committed
219
	struct reg *r = armv4_5->core_cache->reg_list;
220
221
222

	/* load address into R1 */
	regs[1] = address;
223
224
225
	arm9tdmi_write_core_regs(target, 0x2, regs);

	/* read-modify-write CP15 test state register
226
	* to enable interpreted access mode */
227
	arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
228
229
230
231
232
233
	jtag_execute_queue();
	cp15c15 |= 1;	/* set interpret mode */
	arm920t_write_cp15_physical(target, 0x1e, cp15c15);

	/* execute CP15 instruction and ARM load (reading from coprocessor) */
	arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_LDR(0, 1));
234

235
236
237
238
239
240
241
242
	/* disable interpreted access mode */
	cp15c15 &= ~1U;	/* clear interpret mode */
	arm920t_write_cp15_physical(target, 0x1e, cp15c15);

	/* retrieve value from R0 */
	regs_p[0] = value;
	arm9tdmi_read_core_regs(target, 0x1, regs_p);
	jtag_execute_queue();
243

244
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
245
	LOG_DEBUG("cp15_opcode: %8.8x, address: %8.8x, value: %8.8x", cp15_opcode, address, *value);
246
247
#endif

David Brownell's avatar
David Brownell committed
248
	if (!is_arm_mode(armv4_5->core_mode))
249
250
		return ERROR_FAIL;

David Brownell's avatar
David Brownell committed
251
252
	r[0].dirty = 1;
	r[1].dirty = 1;
253
254
255
256

	return ERROR_OK;
}

257
static
Zachary T Welch's avatar
Zachary T Welch committed
258
int arm920t_write_cp15_interpreted(struct target *target,
259
		uint32_t cp15_opcode, uint32_t value, uint32_t address)
260
{
261
	uint32_t cp15c15 = 0x0;
262
	struct arm *armv4_5 = target_to_armv4_5(target);
263
	uint32_t regs[2];
David Brownell's avatar
David Brownell committed
264
	struct reg *r = armv4_5->core_cache->reg_list;
265
266
267
268
269
270

	/* load value, address into R0, R1 */
	regs[0] = value;
	regs[1] = address;
	arm9tdmi_write_core_regs(target, 0x3, regs);

271
	/* read-modify-write CP15 test state register
272
273
274
275
276
277
278
279
280
281
282
283
284
285
	* to enable interpreted access mode */
	arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
	jtag_execute_queue();
	cp15c15 |= 1;	/* set interpret mode */
	arm920t_write_cp15_physical(target, 0x1e, cp15c15);

	/* execute CP15 instruction and ARM store (writing to coprocessor) */
	arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_STR(0, 1));

	/* disable interpreted access mode */
	cp15c15 &= ~1U;	/* set interpret mode */
	arm920t_write_cp15_physical(target, 0x1e, cp15c15);

#ifdef _DEBUG_INSTRUCTION_EXECUTION_
286
	LOG_DEBUG("cp15_opcode: %8.8x, value: %8.8x, address: %8.8x", cp15_opcode, value, address);
287
288
#endif

David Brownell's avatar
David Brownell committed
289
	if (!is_arm_mode(armv4_5->core_mode))
290
		return ERROR_FAIL;
291

David Brownell's avatar
David Brownell committed
292
293
	r[0].dirty = 1;
	r[1].dirty = 1;
294

295
296
297
	return ERROR_OK;
}

298
// EXPORTED to FA256
Zachary T Welch's avatar
Zachary T Welch committed
299
uint32_t arm920t_get_ttb(struct target *target)
300
301
{
	int retval;
302
	uint32_t ttb = 0x0;
303
304
305
306
307
308
309

	if ((retval = arm920t_read_cp15_interpreted(target, 0xeebf0f51, 0x0, &ttb)) != ERROR_OK)
		return retval;

	return ttb;
}

310
// EXPORTED to FA256
Zachary T Welch's avatar
Zachary T Welch committed
311
void arm920t_disable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache)
312
{
313
	uint32_t cp15_control;
314
315
316
317

	/* read cp15 control register */
	arm920t_read_cp15_physical(target, 0x2, &cp15_control);
	jtag_execute_queue();
318

319
320
	if (mmu)
		cp15_control &= ~0x1U;
321

322
323
	if (d_u_cache)
		cp15_control &= ~0x4U;
324

325
326
327
328
329
330
	if (i_cache)
		cp15_control &= ~0x1000U;

	arm920t_write_cp15_physical(target, 0x2, cp15_control);
}

331
// EXPORTED to FA256
Zachary T Welch's avatar
Zachary T Welch committed
332
void arm920t_enable_mmu_caches(struct target *target, int mmu, int d_u_cache, int i_cache)
333
{
334
	uint32_t cp15_control;
335
336
337
338

	/* read cp15 control register */
	arm920t_read_cp15_physical(target, 0x2, &cp15_control);
	jtag_execute_queue();
339

340
341
	if (mmu)
		cp15_control |= 0x1U;
342

343
344
	if (d_u_cache)
		cp15_control |= 0x4U;
345

346
347
	if (i_cache)
		cp15_control |= 0x1000U;
348

349
350
351
	arm920t_write_cp15_physical(target, 0x2, cp15_control);
}

352
// EXPORTED to FA256
Zachary T Welch's avatar
Zachary T Welch committed
353
void arm920t_post_debug_entry(struct target *target)
354
{
355
	uint32_t cp15c15;
356
	struct arm920t_common *arm920t = target_to_arm920(target);
357

358
359
360
	/* examine cp15 control reg */
	arm920t_read_cp15_physical(target, 0x2, &arm920t->cp15_control_reg);
	jtag_execute_queue();
duane's avatar
duane committed
361
	LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm920t->cp15_control_reg);
362
363
364

	if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1)
	{
365
		uint32_t cache_type_reg;
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
		/* identify caches */
		arm920t_read_cp15_physical(target, 0x1, &cache_type_reg);
		jtag_execute_queue();
		armv4_5_identify_cache(cache_type_reg, &arm920t->armv4_5_mmu.armv4_5_cache);
	}

	arm920t->armv4_5_mmu.mmu_enabled = (arm920t->cp15_control_reg & 0x1U) ? 1 : 0;
	arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm920t->cp15_control_reg & 0x4U) ? 1 : 0;
	arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;

	/* save i/d fault status and address register */
	arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr);
	arm920t_read_cp15_interpreted(target, 0xee150f30, 0x0, &arm920t->i_fsr);
	arm920t_read_cp15_interpreted(target, 0xee160f10, 0x0, &arm920t->d_far);
	arm920t_read_cp15_interpreted(target, 0xee160f30, 0x0, &arm920t->i_far);
381

duane's avatar
duane committed
382
	LOG_DEBUG("D FSR: 0x%8.8" PRIx32 ", D FAR: 0x%8.8" PRIx32 ", I FSR: 0x%8.8" PRIx32 ", I FAR: 0x%8.8" PRIx32 "",
383
		arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far);
384
385
386

	if (arm920t->preserve_cache)
	{
387
		/* read-modify-write CP15 test state register
388
389
390
391
392
393
394
395
		 * to disable I/D-cache linefills */
		arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
		jtag_execute_queue();
		cp15c15 |= 0x600;
		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
	}
}

396
// EXPORTED to FA256
Zachary T Welch's avatar
Zachary T Welch committed
397
void arm920t_pre_restore_context(struct target *target)
398
{
399
	uint32_t cp15c15;
400
	struct arm920t_common *arm920t = target_to_arm920(target);
401

402
403
404
405
406
	/* restore i/d fault status and address register */
	arm920t_write_cp15_interpreted(target, 0xee050f10, arm920t->d_fsr, 0x0);
	arm920t_write_cp15_interpreted(target, 0xee050f30, arm920t->i_fsr, 0x0);
	arm920t_write_cp15_interpreted(target, 0xee060f10, arm920t->d_far, 0x0);
	arm920t_write_cp15_interpreted(target, 0xee060f30, arm920t->i_far, 0x0);
407
408

	/* read-modify-write CP15 test state register
409
410
411
412
413
414
415
416
417
418
	* to reenable I/D-cache linefills */
	if (arm920t->preserve_cache)
	{
		arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
		jtag_execute_queue();
		cp15c15 &= ~0x600U;
		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
	}
}

419
static const char arm920_not[] = "target is not an ARM920";
420

421
static int arm920t_verify_pointer(struct command_context *cmd_ctx,
422
		struct arm920t_common *arm920t)
423
424
425
426
{
	if (arm920t->common_magic != ARM920T_COMMON_MAGIC) {
		command_print(cmd_ctx, arm920_not);
		return ERROR_TARGET_INVALID;
427
	}
428

429
430
431
	return ERROR_OK;
}

432
/** Logs summary of ARM920 state for a halted target. */
Zachary T Welch's avatar
Zachary T Welch committed
433
int arm920t_arch_state(struct target *target)
434
{
435
	static const char *state[] =
436
437
438
	{
		"disabled", "enabled"
	};
439

440
	struct arm920t_common *arm920t = target_to_arm920(target);
441
	struct arm *armv4_5;
442
443

	if (arm920t->common_magic != ARM920T_COMMON_MAGIC)
444
	{
445
446
		LOG_ERROR("BUG: %s", arm920_not);
		return ERROR_TARGET_INVALID;
447
	}
448

449
	armv4_5 = &arm920t->arm7_9_common.armv4_5_common;
450

451
	LOG_USER("target halted in %s state due to %s, current mode: %s\n"
duane's avatar
duane committed
452
			"cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
453
454
			"MMU: %s, D-Cache: %s, I-Cache: %s",
			 armv4_5_state_strings[armv4_5->core_state],
455
			 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
David Brownell's avatar
David Brownell committed
456
			 arm_mode_name(armv4_5->core_mode),
David Brownell's avatar
David Brownell committed
457
			 buf_get_u32(armv4_5->cpsr->value, 0, 32),
458
459
			 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
			 state[arm920t->armv4_5_mmu.mmu_enabled],
460
			 state[arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
461
			 state[arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
462

463
464
465
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
466
static int arm920_mmu(struct target *target, int *enabled)
467
468
469
470
471
472
473
474
475
476
{
	if (target->state != TARGET_HALTED) {
		LOG_ERROR("%s: target not halted", __func__);
		return ERROR_TARGET_INVALID;
	}

	*enabled = target_to_arm920(target)->armv4_5_mmu.mmu_enabled;
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
477
static int arm920_virt2phys(struct target *target,
478
479
480
481
482
483
484
		uint32_t virt, uint32_t *phys)
{
	/** @todo Implement this!  */
	LOG_ERROR("%s: not implemented", __func__);
	return ERROR_FAIL;
}

485
/** Reads a buffer, in the specified word size, with current MMU settings. */
Zachary T Welch's avatar
Zachary T Welch committed
486
int arm920t_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
487
488
{
	int retval;
489

490
	retval = arm7_9_read_memory(target, address, size, count, buffer);
491

492
493
494
	return retval;
}

495

Zachary T Welch's avatar
Zachary T Welch committed
496
static int arm920t_read_phys_memory(struct target *target,
497
498
		uint32_t address, uint32_t size,
		uint32_t count, uint8_t *buffer)
499
{
500
	struct arm920t_common *arm920t = target_to_arm920(target);
501

502
503
	return armv4_5_mmu_read_physical(target, &arm920t->armv4_5_mmu,
			address, size, count, buffer);
504
505
}

Zachary T Welch's avatar
Zachary T Welch committed
506
static int arm920t_write_phys_memory(struct target *target,
507
508
		uint32_t address, uint32_t size,
		uint32_t count, uint8_t *buffer)
509
{
510
	struct arm920t_common *arm920t = target_to_arm920(target);
511

512
513
	return armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu,
			address, size, count, buffer);
514
515
516
}


517
/** Writes a buffer, in the specified word size, with current MMU settings. */
Zachary T Welch's avatar
Zachary T Welch committed
518
int arm920t_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
519
520
{
	int retval;
521

522
523
524
	if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
		return retval;

525
526
527
528
	/* This fn is used to write breakpoints, so we need to make sure
	 * that the data cache is flushed and the instruction cache is
	 * invalidated
	 */
529
530
	if (((size == 4) || (size == 2)) && (count == 1))
	{
531
		struct arm920t_common *arm920t = target_to_arm920(target);
532

533
534
		if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
		{
535
536
537
538
539
			LOG_DEBUG("D-Cache enabled, flush and invalidate cache line");
			/* MCR p15,0,Rd,c7,c10,2 */
			retval = arm920t_write_cp15_interpreted(target, 0xee070f5e, 0x0, address);
			if (retval != ERROR_OK)
				return retval;
540
		}
541

542
543
		if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
		{
544
			LOG_DEBUG("I-Cache enabled, invalidating affected I-Cache line");
545
546
547
			retval = arm920t_write_cp15_interpreted(target, 0xee070f35, 0x0, address);
			if (retval != ERROR_OK)
				return retval;
548
549
550
551
552
553
		}
	}

	return retval;
}

554
// EXPORTED to FA256
Zachary T Welch's avatar
Zachary T Welch committed
555
int arm920t_soft_reset_halt(struct target *target)
556
{
557
	int retval = ERROR_OK;
558
	struct arm920t_common *arm920t = target_to_arm920(target);
559
	struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
560
	struct arm *armv4_5 = &arm7_9->armv4_5_common;
Zachary T Welch's avatar
Zachary T Welch committed
561
	struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
562

563
	if ((retval = target_halt(target)) != ERROR_OK)
564
565
566
	{
		return retval;
	}
567

zwelch's avatar
zwelch committed
568
	long long then = timeval_ms();
oharboe's avatar
oharboe committed
569
	int timeout;
zwelch's avatar
zwelch committed
570
	while (!(timeout = ((timeval_ms()-then) > 1000)))
571
	{
572
573
574
		if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
		{
			embeddedice_read_reg(dbg_stat);
575
			if ((retval = jtag_execute_queue()) != ERROR_OK)
576
577
578
			{
				return retval;
			}
579
580
581
582
		} else
		{
			break;
		}
zwelch's avatar
zwelch committed
583
		if (debug_level >= 3)
oharboe's avatar
oharboe committed
584
585
586
587
588
589
590
		{
			/* do not eat all CPU, time out after 1 se*/
			alive_sleep(100);
		} else
		{
			keep_alive();
		}
591
	}
oharboe's avatar
oharboe committed
592
	if (timeout)
593
594
595
	{
		LOG_ERROR("Failed to halt CPU after 1 sec");
		return ERROR_TARGET_TIMEOUT;
596
	}
597

598
	target->state = TARGET_HALTED;
599

600
	/* SVC, ARM state, IRQ and FIQ disabled */
601
602
603
604
605
606
	uint32_t cpsr;

	cpsr = buf_get_u32(armv4_5->cpsr->value, 0, 32);
	cpsr &= ~0xff;
	cpsr |= 0xd3;
	arm_set_cpsr(armv4_5, cpsr);
David Brownell's avatar
David Brownell committed
607
	armv4_5->cpsr->dirty = 1;
608

609
610
611
612
	/* start fetching from 0x0 */
	buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
	armv4_5->core_cache->reg_list[15].dirty = 1;
	armv4_5->core_cache->reg_list[15].valid = 1;
613

614
615
616
617
618
	arm920t_disable_mmu_caches(target, 1, 1, 1);
	arm920t->armv4_5_mmu.mmu_enabled = 0;
	arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
	arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;

619
	if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
620
621
622
	{
		return retval;
	}
623

624
625
626
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
627
int arm920t_init_arch_info(struct target *target, struct arm920t_common *arm920t, struct jtag_tap *tap)
628
{
629
	struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common;
630

631
632
	/* initialize arm7/arm9 specific info (including armv4_5) */
	arm9tdmi_init_arch_info(target, arm7_9, tap);
633
634

	arm920t->common_magic = ARM920T_COMMON_MAGIC;
635

636
637
	arm7_9->post_debug_entry = arm920t_post_debug_entry;
	arm7_9->pre_restore_context = arm920t_pre_restore_context;
638

639
640
641
642
643
644
645
646
	arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;
	arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;
	arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;
	arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;
	arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
	arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
	arm920t->armv4_5_mmu.has_tiny_pages = 1;
	arm920t->armv4_5_mmu.mmu_enabled = 0;
647

648
649
650
651
652
	/* disabling linefills leads to lockups, so keep them enabled for now
	 * this doesn't affect correctness, but might affect timing issues, if
	 * important data is evicted from the cache during the debug session
	 * */
	arm920t->preserve_cache = 0;
653

654
655
	/* override hw single-step capability from ARM9TDMI */
	arm7_9->has_single_step = 1;
656

657
658
659
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
660
static int arm920t_target_create(struct target *target, Jim_Interp *interp)
661
{
662
	struct arm920t_common *arm920t = calloc(1,sizeof(struct arm920t_common));
663

664
	return arm920t_init_arch_info(target, arm920t, target->tap);
665
666
}

667
COMMAND_HANDLER(arm920t_handle_read_cache_command)
668
{
669
	int retval = ERROR_OK;
670
	struct target *target = get_current_target(CMD_CTX);
671
	struct arm920t_common *arm920t = target_to_arm920(target);
672
	struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
673
	struct arm *armv4_5 = &arm7_9->armv4_5_common;
674
675
676
677
678
	uint32_t cp15c15;
	uint32_t cp15_ctrl, cp15_ctrl_saved;
	uint32_t regs[16];
	uint32_t *regs_p[16];
	uint32_t C15_C_D_Ind, C15_C_I_Ind;
679
680
	int i;
	FILE *output;
681
	struct arm920t_cache_line d_cache[8][64], i_cache[8][64];
682
	int segment, index;
David Brownell's avatar
David Brownell committed
683
	struct reg *r;
684

685
	retval = arm920t_verify_pointer(CMD_CTX, arm920t);
686
687
688
	if (retval != ERROR_OK)
		return retval;

689
	if (CMD_ARGC != 1)
690
	{
691
		command_print(CMD_CTX, "usage: arm920t read_cache <filename>");
692
693
		return ERROR_OK;
	}
694

695
	if ((output = fopen(CMD_ARGV[0], "w")) == NULL)
696
	{
697
		LOG_DEBUG("error opening cache content file");
698
699
		return ERROR_OK;
	}
700

701
702
	for (i = 0; i < 16; i++)
		regs_p[i] = &regs[i];
703

704
705
	/* disable MMU and Caches */
	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), &cp15_ctrl);
706
	if ((retval = jtag_execute_queue()) != ERROR_OK)
707
708
709
	{
		return retval;
	}
710
711
712
713
	cp15_ctrl_saved = cp15_ctrl;
	cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl);

714
	/* read CP15 test state register */
715
716
	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), &cp15c15);
	jtag_execute_queue();
717

718
719
	/* read DCache content */
	fprintf(output, "DCache:\n");
720
721

	/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */
722
723
724
	for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)
	{
		fprintf(output, "\nsegment: %i\n----------", segment);
725

726
727
728
		/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
		regs[0] = 0x0 | (segment << 5);
		arm9tdmi_write_core_regs(target, 0x1, regs);
729

730
731
732
		/* set interpret mode */
		cp15c15 |= 0x1;
		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
733

734
735
		/* D CAM Read, loads current victim into C15.C.D.Ind */
		arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(1, 0));
736

737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
		/* read current victim */
		arm920t_read_cp15_physical(target, 0x3d, &C15_C_D_Ind);

		/* clear interpret mode */
		cp15c15 &= ~0x1;
		arm920t_write_cp15_physical(target, 0x1e, cp15c15);

		for (index = 0; index < 64; index++)
		{
			/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
			regs[0] = 0x0 | (segment << 5) | (index << 26);
			arm9tdmi_write_core_regs(target, 0x1, regs);

			/* set interpret mode */
			cp15c15 |= 0x1;
			arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
753

754
755
			/* Write DCache victim */
			arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
756

757
758
			/* Read D RAM */
			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,10,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
759

760
761
			/* Read D CAM */
			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(9, 0));
762

763
764
765
766
767
768
			/* clear interpret mode */
			cp15c15 &= ~0x1;
			arm920t_write_cp15_physical(target, 0x1e, cp15c15);

			/* read D RAM and CAM content */
			arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
769
			if ((retval = jtag_execute_queue()) != ERROR_OK)
770
771
772
			{
				return retval;
			}
773
774

			d_cache[segment][index].cam = regs[9];
775

776
777
			/* mask LFSR[6] */
			regs[9] &= 0xfffffffe;
duane's avatar
duane committed
778
			fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8" PRIx32 ", content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");
779

780
781
782
			for (i = 1; i < 9; i++)
			{
				 d_cache[segment][index].data[i] = regs[i];
duane's avatar
duane committed
783
				 fprintf(output, "%i: 0x%8.8" PRIx32 "\n", i-1, regs[i]);
784
			}
785

786
		}
787

788
789
790
791
792
793
794
		/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
		regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
		arm9tdmi_write_core_regs(target, 0x1, regs);

		/* set interpret mode */
		cp15c15 |= 0x1;
		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
795

796
797
		/* Write DCache victim */
		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
798

799
800
801
802
803
804
805
		/* clear interpret mode */
		cp15c15 &= ~0x1;
		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
	}

	/* read ICache content */
	fprintf(output, "ICache:\n");
806
807

	/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */
808
809
810
	for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)
	{
		fprintf(output, "segment: %i\n----------", segment);
811

812
813
814
		/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
		regs[0] = 0x0 | (segment << 5);
		arm9tdmi_write_core_regs(target, 0x1, regs);
815

816
817
818
		/* set interpret mode */
		cp15c15 |= 0x1;
		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
819

820
821
		/* I CAM Read, loads current victim into C15.C.I.Ind */
		arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(1, 0));
822

823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
		/* read current victim */
		arm920t_read_cp15_physical(target, 0x3b, &C15_C_I_Ind);

		/* clear interpret mode */
		cp15c15 &= ~0x1;
		arm920t_write_cp15_physical(target, 0x1e, cp15c15);

		for (index = 0; index < 64; index++)
		{
			/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
			regs[0] = 0x0 | (segment << 5) | (index << 26);
			arm9tdmi_write_core_regs(target, 0x1, regs);

			/* set interpret mode */
			cp15c15 |= 0x1;
			arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
839

840
841
			/* Write ICache victim */
			arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));
842

843
844
			/* Read I RAM */
			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,9,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
845

846
847
			/* Read I CAM */
			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(9, 0));
848

849
850
851
852
853
854
			/* clear interpret mode */
			cp15c15 &= ~0x1;
			arm920t_write_cp15_physical(target, 0x1e, cp15c15);

			/* read I RAM and CAM content */
			arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
855
			if ((retval = jtag_execute_queue()) != ERROR_OK)
856
857
858
			{
				return retval;
			}
859
860

			i_cache[segment][index].cam = regs[9];
861

862
863
			/* mask LFSR[6] */
			regs[9] &= 0xfffffffe;
duane's avatar
duane committed
864
			fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8" PRIx32 ", content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");
865

866
867
868
			for (i = 1; i < 9; i++)
			{
				 i_cache[segment][index].data[i] = regs[i];
duane's avatar
duane committed
869
				 fprintf(output, "%i: 0x%8.8" PRIx32 "\n", i-1, regs[i]);
870
871
			}
		}
872

873
874
875
876
877
878
879
		/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
		regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
		arm9tdmi_write_core_regs(target, 0x1, regs);

		/* set interpret mode */
		cp15c15 |= 0x1;
		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
kc8apf's avatar