arm926ejs.c 25.5 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2007 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007,2008,2009 by Øyvind Harboe                         *
6
7
 *   oyvind.harboe@zylin.com                                               *
 *                                                                         *
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 *   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 "arm926ejs.h"
oharboe's avatar
oharboe committed
28
#include "time_support.h"
29
#include "target_type.h"
30
31


David Brownell's avatar
David Brownell committed
32
33
34
35
36
37
38
39
40
41
42
/*
 * The ARM926 is built around the ARM9EJ-S core, and most JTAG docs
 * are in the ARM9EJ-S Technical Reference Manual (ARM DDI 0222B) not
 * the ARM926 manual (ARM DDI 0198E).  The scan chains are:
 *
 *   1 ... core debugging
 *   2 ... EmbeddedICE
 *   3 ... external boundary scan (SoC-specific, unused here)
 *   6 ... ETM
 *   15 ... coprocessor 15
 */
43

44
#if 0
David Brownell's avatar
David Brownell committed
45
#define _DEBUG_INSTRUCTION_EXECUTION_
46
#endif
47
48
49

#define ARM926EJS_CP15_ADDR(opcode_1, opcode_2, CRn, CRm) ((opcode_1 << 11) | (opcode_2 << 8) | (CRn << 4) | (CRm << 0))

50
51
static int arm926ejs_cp15_read(target_t *target, uint32_t op1, uint32_t op2,
		uint32_t CRn, uint32_t CRm, uint32_t *value)
52
{
53
	int retval = ERROR_OK;
54
	struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
55
	struct arm_jtag *jtag_info = &arm7_9->jtag_info;
56
	uint32_t address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
57
	struct scan_field fields[4];
58
59
60
	uint8_t address_buf[2];
	uint8_t nr_w_buf = 0;
	uint8_t access = 1;
oharboe's avatar
oharboe committed
61

62
	buf_set_u32(address_buf, 0, 14, address);
oharboe's avatar
oharboe committed
63

64
	jtag_set_end_state(TAP_IDLE);
65
	if ((retval = arm_jtag_scann(jtag_info, 0xf)) != ERROR_OK)
66
67
68
	{
		return retval;
	}
69
70
	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);

71
	fields[0].tap = jtag_info->tap;
72
73
	fields[0].num_bits = 32;
	fields[0].out_value = NULL;
74
	fields[0].in_value = (uint8_t *)value;
75

76

77
	fields[1].tap = jtag_info->tap;
78
79
80
	fields[1].num_bits = 1;
	fields[1].out_value = &access;
	fields[1].in_value = &access;
81

82
	fields[2].tap = jtag_info->tap;
83
84
85
	fields[2].num_bits = 14;
	fields[2].out_value = address_buf;
	fields[2].in_value = NULL;
86

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

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

94
95
96
	long long then = timeval_ms();

	for (;;)
97
98
99
100
	{
		/* rescan with NOP, to wait for the access to complete */
		access = 0;
		nr_w_buf = 0;
101
		jtag_add_dr_scan(4, fields, jtag_get_end_state());
oharboe's avatar
oharboe committed
102

103
		jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
oharboe's avatar
oharboe committed
104

105
		if ((retval = jtag_execute_queue()) != ERROR_OK)
106
107
108
		{
			return retval;
		}
109

110
111
112
113
		if (buf_get_u32(&access, 0, 1) == 1)
		{
			break;
		}
114

115
116
117
118
119
120
121
		/* 10ms timeout */
		if ((timeval_ms()-then)>10)
		{
			LOG_ERROR("cp15 read operation timed out");
			return ERROR_FAIL;
		}
	}
122
123

#ifdef _DEBUG_INSTRUCTION_EXECUTION_
124
	LOG_DEBUG("addr: 0x%x value: %8.8x", address, *value);
125
#endif
oharboe's avatar
oharboe committed
126

David Brownell's avatar
David Brownell committed
127
	arm_jtag_set_instr(jtag_info, 0xc, NULL);
128
129
130
131

	return ERROR_OK;
}

132
133
134
135
136
137
138
139
140
141
142
143
static int arm926ejs_mrc(target_t *target, int cpnum, uint32_t op1,
		uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
{
	if (cpnum != 15) {
		LOG_ERROR("Only cp15 is supported");
		return ERROR_FAIL;
	}
	return arm926ejs_cp15_read(target, op1, op2, CRn, CRm, value);
}

static int arm926ejs_cp15_write(target_t *target, uint32_t op1, uint32_t op2,
		uint32_t CRn, uint32_t CRm, uint32_t value)
144
{
145
	int retval = ERROR_OK;
146
	struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
147
	struct arm_jtag *jtag_info = &arm7_9->jtag_info;
148
	uint32_t address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
149
	struct scan_field fields[4];
150
151
152
153
	uint8_t value_buf[4];
	uint8_t address_buf[2];
	uint8_t nr_w_buf = 1;
	uint8_t access = 1;
oharboe's avatar
oharboe committed
154

155
156
	buf_set_u32(address_buf, 0, 14, address);
	buf_set_u32(value_buf, 0, 32, value);
oharboe's avatar
oharboe committed
157

158
	jtag_set_end_state(TAP_IDLE);
159
	if ((retval = arm_jtag_scann(jtag_info, 0xf)) != ERROR_OK)
160
161
162
	{
		return retval;
	}
163
164
	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);

165
	fields[0].tap = jtag_info->tap;
166
167
168
	fields[0].num_bits = 32;
	fields[0].out_value = value_buf;
	fields[0].in_value = NULL;
oharboe's avatar
oharboe committed
169

170
	fields[1].tap = jtag_info->tap;
171
172
173
	fields[1].num_bits = 1;
	fields[1].out_value = &access;
	fields[1].in_value = &access;
oharboe's avatar
oharboe committed
174

175
	fields[2].tap = jtag_info->tap;
176
177
178
	fields[2].num_bits = 14;
	fields[2].out_value = address_buf;
	fields[2].in_value = NULL;
oharboe's avatar
oharboe committed
179

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

185
	jtag_add_dr_scan(4, fields, jtag_get_end_state());
186
187
188
189

	long long then = timeval_ms();

	for (;;)
190
191
192
193
	{
		/* rescan with NOP, to wait for the access to complete */
		access = 0;
		nr_w_buf = 0;
194
		jtag_add_dr_scan(4, fields, jtag_get_end_state());
195
		if ((retval = jtag_execute_queue()) != ERROR_OK)
196
197
198
		{
			return retval;
		}
199
200
201
202
203
204
205
206
207
208
209
210
211

		if (buf_get_u32(&access, 0, 1) == 1)
		{
			break;
		}

		/* 10ms timeout */
		if ((timeval_ms()-then)>10)
		{
			LOG_ERROR("cp15 write operation timed out");
			return ERROR_FAIL;
		}
	}
212
213

#ifdef _DEBUG_INSTRUCTION_EXECUTION_
214
	LOG_DEBUG("addr: 0x%x value: %8.8x", address, value);
215
216
#endif

David Brownell's avatar
David Brownell committed
217
	arm_jtag_set_instr(jtag_info, 0xf, NULL);
218
219
220
221

	return ERROR_OK;
}

222
223
224
225
226
227
228
229
230
231
static int arm926ejs_mcr(target_t *target, int cpnum, uint32_t op1,
		uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
{
	if (cpnum != 15) {
		LOG_ERROR("Only cp15 is supported");
		return ERROR_FAIL;
	}
	return arm926ejs_cp15_write(target, op1, op2, CRn, CRm, value);
}

232
static int arm926ejs_examine_debug_reason(target_t *target)
233
{
234
	struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
235
236
237
238
239
240
241
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
	int debug_reason;
	int retval;

	embeddedice_read_reg(dbg_stat);
	if ((retval = jtag_execute_queue()) != ERROR_OK)
		return retval;
oharboe's avatar
oharboe committed
242

zwelch's avatar
zwelch committed
243
	/* Method-Of-Entry (MOE) field */
244
	debug_reason = buf_get_u32(dbg_stat->value, 6, 4);
oharboe's avatar
oharboe committed
245

246
247
	switch (debug_reason)
	{
248
249
250
251
252
		case 0:
			LOG_DEBUG("no *NEW* debug entry (?missed one?)");
			/* ... since last restart or debug reset ... */
			target->debug_reason = DBG_REASON_DBGRQ;
			break;
253
		case 1:
254
			LOG_DEBUG("breakpoint from EICE unit 0");
255
256
257
			target->debug_reason = DBG_REASON_BREAKPOINT;
			break;
		case 2:
258
			LOG_DEBUG("breakpoint from EICE unit 1");
259
260
261
			target->debug_reason = DBG_REASON_BREAKPOINT;
			break;
		case 3:
262
			LOG_DEBUG("soft breakpoint (BKPT instruction)");
263
264
265
			target->debug_reason = DBG_REASON_BREAKPOINT;
			break;
		case 4:
266
			LOG_DEBUG("vector catch breakpoint");
267
268
269
			target->debug_reason = DBG_REASON_BREAKPOINT;
			break;
		case 5:
270
			LOG_DEBUG("external breakpoint");
271
272
273
			target->debug_reason = DBG_REASON_BREAKPOINT;
			break;
		case 6:
274
			LOG_DEBUG("watchpoint from EICE unit 0");
275
276
277
			target->debug_reason = DBG_REASON_WATCHPOINT;
			break;
		case 7:
278
			LOG_DEBUG("watchpoint from EICE unit 1");
279
280
281
			target->debug_reason = DBG_REASON_WATCHPOINT;
			break;
		case 8:
282
			LOG_DEBUG("external watchpoint");
283
284
285
			target->debug_reason = DBG_REASON_WATCHPOINT;
			break;
		case 9:
286
			LOG_DEBUG("internal debug request");
287
288
289
			target->debug_reason = DBG_REASON_DBGRQ;
			break;
		case 10:
290
			LOG_DEBUG("external debug request");
291
292
293
			target->debug_reason = DBG_REASON_DBGRQ;
			break;
		case 11:
zwelch's avatar
zwelch committed
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
			LOG_DEBUG("debug re-entry from system speed access");
			/* This is normal when connecting to something that's
			 * already halted, or in some related code paths, but
			 * otherwise is surprising (and presumably wrong).
			 */
			switch (target->debug_reason) {
			case DBG_REASON_DBGRQ:
				break;
			default:
				LOG_ERROR("unexpected -- debug re-entry");
				/* FALLTHROUGH */
			case DBG_REASON_UNDEFINED:
				target->debug_reason = DBG_REASON_DBGRQ;
				break;
			}
oharboe's avatar
oharboe committed
309
310
311
312
313
314
315
316
317
			break;
		case 12:
			/* FIX!!!! here be dragons!!! We need to fail here so
			 * the target will interpreted as halted but we won't
			 * try to talk to it right now... a resume + halt seems
			 * to sync things up again. Please send an email to
			 * openocd development mailing list if you have hardware
			 * to donate to look into this problem....
			 */
318
			LOG_WARNING("WARNING: mystery debug reason MOE = 0xc. Try issuing a resume + halt.");
319
			target->debug_reason = DBG_REASON_DBGRQ;
320
321
			break;
		default:
322
323
324
325
			LOG_WARNING("WARNING: unknown debug reason: 0x%x", debug_reason);
			/* Oh agony! should we interpret this as a halt request or
			 * that the target stopped on it's own accord?
			 */
326
			target->debug_reason = DBG_REASON_DBGRQ;
327
			/* if we fail here, we won't talk to the target and it will
oharboe's avatar
oharboe committed
328
			 * be reported to be in the halted state */
329
			break;
330
	}
oharboe's avatar
oharboe committed
331

332
	return ERROR_OK;
333
334
}

335
static uint32_t arm926ejs_get_ttb(target_t *target)
336
{
337
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
338
	int retval;
339
	uint32_t ttb = 0x0;
340
341
342
343
344
345
346

	if ((retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb)) != ERROR_OK)
		return retval;

	return ttb;
}

347
348
static void arm926ejs_disable_mmu_caches(target_t *target, int mmu,
		int d_u_cache, int i_cache)
349
{
350
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
351
	uint32_t cp15_control;
352
353
354
355

	/* read cp15 control register */
	arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
	jtag_execute_queue();
oharboe's avatar
oharboe committed
356

357
358
359
360
	if (mmu)
	{
		/* invalidate TLB */
		arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0);
oharboe's avatar
oharboe committed
361

362
363
		cp15_control &= ~0x1U;
	}
oharboe's avatar
oharboe committed
364

365
366
	if (d_u_cache)
	{
367
		uint32_t debug_override;
oharboe's avatar
oharboe committed
368
		/* read-modify-write CP15 debug override register
369
370
371
372
		 * to enable "test and clean all" */
		arm926ejs->read_cp15(target, 0, 0, 15, 0, &debug_override);
		debug_override |= 0x80000;
		arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
oharboe's avatar
oharboe committed
373

374
375
376
		/* clean and invalidate DCache */
		arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);

oharboe's avatar
oharboe committed
377
		/* write CP15 debug override register
378
379
380
		 * to disable "test and clean all" */
		debug_override &= ~0x80000;
		arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
oharboe's avatar
oharboe committed
381

382
383
		cp15_control &= ~0x4U;
	}
oharboe's avatar
oharboe committed
384

385
386
387
388
	if (i_cache)
	{
		/* invalidate ICache */
		arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
oharboe's avatar
oharboe committed
389

390
391
		cp15_control &= ~0x1000U;
	}
oharboe's avatar
oharboe committed
392

393
394
395
	arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
}

396
397
static void arm926ejs_enable_mmu_caches(target_t *target, int mmu,
		int d_u_cache, int i_cache)
398
{
399
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
400
	uint32_t cp15_control;
401
402
403
404

	/* read cp15 control register */
	arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
	jtag_execute_queue();
oharboe's avatar
oharboe committed
405

406
407
	if (mmu)
		cp15_control |= 0x1U;
oharboe's avatar
oharboe committed
408

409
410
	if (d_u_cache)
		cp15_control |= 0x4U;
oharboe's avatar
oharboe committed
411

412
413
	if (i_cache)
		cp15_control |= 0x1000U;
oharboe's avatar
oharboe committed
414

415
416
417
	arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
}

418
static void arm926ejs_post_debug_entry(target_t *target)
419
{
420
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
421
422
423
424

	/* examine cp15 control reg */
	arm926ejs->read_cp15(target, 0, 0, 1, 0, &arm926ejs->cp15_control_reg);
	jtag_execute_queue();
duane's avatar
duane committed
425
	LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm926ejs->cp15_control_reg);
426
427
428

	if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1)
	{
429
		uint32_t cache_type_reg;
430
431
432
433
434
435
436
437
438
439
440
441
442
443
		/* identify caches */
		arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
		jtag_execute_queue();
		armv4_5_identify_cache(cache_type_reg, &arm926ejs->armv4_5_mmu.armv4_5_cache);
	}

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

	/* save i/d fault status and address register */
	arm926ejs->read_cp15(target, 0, 0, 5, 0, &arm926ejs->d_fsr);
	arm926ejs->read_cp15(target, 0, 1, 5, 0, &arm926ejs->i_fsr);
	arm926ejs->read_cp15(target, 0, 0, 6, 0, &arm926ejs->d_far);
oharboe's avatar
oharboe committed
444

duane's avatar
duane committed
445
	LOG_DEBUG("D FSR: 0x%8.8" PRIx32 ", D FAR: 0x%8.8" PRIx32 ", I FSR: 0x%8.8" PRIx32 "",
oharboe's avatar
oharboe committed
446
		arm926ejs->d_fsr, arm926ejs->d_far, arm926ejs->i_fsr);
447

448
	uint32_t cache_dbg_ctrl;
oharboe's avatar
oharboe committed
449
450

	/* read-modify-write CP15 cache debug control register
451
452
453
454
455
456
	 * to disable I/D-cache linefills and force WT */
	arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
	cache_dbg_ctrl |= 0x7;
	arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
}

457
static void arm926ejs_pre_restore_context(target_t *target)
458
{
459
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
460
461
462
463
464

	/* restore i/d fault status and address register */
	arm926ejs->write_cp15(target, 0, 0, 5, 0, arm926ejs->d_fsr);
	arm926ejs->write_cp15(target, 0, 1, 5, 0, arm926ejs->i_fsr);
	arm926ejs->write_cp15(target, 0, 0, 6, 0, arm926ejs->d_far);
oharboe's avatar
oharboe committed
465

466
	uint32_t cache_dbg_ctrl;
oharboe's avatar
oharboe committed
467
468

	/* read-modify-write CP15 cache debug control register
469
470
471
472
473
474
	 * to reenable I/D-cache linefills and disable WT */
	arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
	cache_dbg_ctrl &= ~0x7;
	arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
}

475
static const char arm926_not[] = "target is not an ARM926";
oharboe's avatar
oharboe committed
476

477
static int arm926ejs_verify_pointer(struct command_context_s *cmd_ctx,
478
		struct arm926ejs_common *arm926)
479
480
481
482
{
	if (arm926->common_magic != ARM926EJS_COMMON_MAGIC) {
		command_print(cmd_ctx, arm926_not);
		return ERROR_TARGET_INVALID;
483
484
485
486
	}
	return ERROR_OK;
}

David Brownell's avatar
David Brownell committed
487
/** Logs summary of ARM926 state for a halted target. */
488
489
int arm926ejs_arch_state(struct target_s *target)
{
490
	static const char *state[] =
491
492
493
	{
		"disabled", "enabled"
	};
oharboe's avatar
oharboe committed
494

495
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
496
497
498
	struct armv4_5_common_s *armv4_5;

	if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC)
499
	{
500
501
		LOG_ERROR("BUG: %s", arm926_not);
		return ERROR_TARGET_INVALID;
502
	}
oharboe's avatar
oharboe committed
503

504
505
506
	armv4_5 = &arm926ejs->arm9tdmi_common.arm7_9_common.armv4_5_common;

	LOG_USER("target halted in %s state due to %s, current mode: %s\n"
duane's avatar
duane committed
507
			"cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
508
509
			"MMU: %s, D-Cache: %s, I-Cache: %s",
			 armv4_5_state_strings[armv4_5->core_state],
510
			 Jim_Nvp_value2name_simple(nvp_target_debug_reason,target->debug_reason)->name,
511
512
513
514
			 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[arm926ejs->armv4_5_mmu.mmu_enabled],
oharboe's avatar
oharboe committed
515
			 state[arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
516
			 state[arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
oharboe's avatar
oharboe committed
517

518
519
520
521
522
	return ERROR_OK;
}

int arm926ejs_soft_reset_halt(struct target_s *target)
{
523
	int retval = ERROR_OK;
524
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
525
	struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
526
	struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
527
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
oharboe's avatar
oharboe committed
528

529
	if ((retval = target_halt(target)) != ERROR_OK)
530
531
532
	{
		return retval;
	}
oharboe's avatar
oharboe committed
533

zwelch's avatar
zwelch committed
534
	long long then = timeval_ms();
oharboe's avatar
oharboe committed
535
	int timeout;
zwelch's avatar
zwelch committed
536
	while (!(timeout = ((timeval_ms()-then) > 1000)))
537
	{
538
539
540
		if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
		{
			embeddedice_read_reg(dbg_stat);
541
			if ((retval = jtag_execute_queue()) != ERROR_OK)
542
543
544
			{
				return retval;
			}
545
546
547
548
		}  else
		{
			break;
		}
zwelch's avatar
zwelch committed
549
		if (debug_level >= 1)
oharboe's avatar
oharboe committed
550
551
552
553
554
555
556
		{
			/* do not eat all CPU, time out after 1 se*/
			alive_sleep(100);
		} else
		{
			keep_alive();
		}
557
	}
oharboe's avatar
oharboe committed
558
	if (timeout)
559
560
561
	{
		LOG_ERROR("Failed to halt CPU after 1 sec");
		return ERROR_TARGET_TIMEOUT;
562
	}
oharboe's avatar
oharboe committed
563

564
	target->state = TARGET_HALTED;
oharboe's avatar
oharboe committed
565

566
567
568
569
	/* SVC, ARM state, IRQ and FIQ disabled */
	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
oharboe's avatar
oharboe committed
570

571
572
573
574
	/* 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;
oharboe's avatar
oharboe committed
575

576
577
	armv4_5->core_mode = ARMV4_5_MODE_SVC;
	armv4_5->core_state = ARMV4_5_STATE_ARM;
oharboe's avatar
oharboe committed
578

579
580
581
582
	arm926ejs_disable_mmu_caches(target, 1, 1, 1);
	arm926ejs->armv4_5_mmu.mmu_enabled = 0;
	arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
	arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
oharboe's avatar
oharboe committed
583

584
	return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
585
586
}

David Brownell's avatar
David Brownell committed
587
/** Writes a buffer, in the specified word size, with current MMU settings. */
588
589
int arm926ejs_write_memory(struct target_s *target, uint32_t address,
		uint32_t size, uint32_t count, uint8_t *buffer)
590
591
{
	int retval;
592
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
oharboe's avatar
oharboe committed
593

594
595
596
	/* FIX!!!! this should be cleaned up and made much more general. The
	 * plan is to write up and test on arm926ejs specifically and
	 * then generalize and clean up afterwards. */
597
	if (arm926ejs->armv4_5_mmu.mmu_enabled && (count == 1) && ((size==2) || (size==4)))
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
	{
		/* special case the handling of single word writes to bypass MMU
		 * to allow implementation of breakpoints in memory marked read only
		 * by MMU */
		if (arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
		{
			/* flush and invalidate data cache
			 *
			 * MCR p15,0,p,c7,c10,1 - clean cache line using virtual address
			 *
			 */
			retval = arm926ejs->write_cp15(target, 0, 1, 7, 10, address&~0x3);
			if (retval != ERROR_OK)
				return retval;
		}

		uint32_t pa;
		retval = target->type->virt2phys(target, address, &pa);
		if (retval != ERROR_OK)
			return retval;

		/* write directly to physical memory bypassing any read only MMU bits, etc. */
		retval = armv4_5_mmu_write_physical(target, &arm926ejs->armv4_5_mmu, pa, size, count, buffer);
		if (retval != ERROR_OK)
			return retval;
	} else
	{
		if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
			return retval;
	}
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

	/* If ICache is enabled, we have to invalidate affected ICache lines
	 * the DCache is forced to write-through, so we don't have to clean it here
	 */
	if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
	{
		if (count <= 1)
		{
			/* invalidate ICache single entry with MVA */
			arm926ejs->write_cp15(target, 0, 1, 7, 5, address);
		}
		else
		{
			/* invalidate ICache */
			arm926ejs->write_cp15(target, 0, 0, 7, 5, address);
		}
	}

	return retval;
}

649
650
651
static int arm926ejs_write_phys_memory(struct target_s *target,
		uint32_t address, uint32_t size,
		uint32_t count, uint8_t *buffer)
652
{
653
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
654

655
656
	return armv4_5_mmu_write_physical(target, &arm926ejs->armv4_5_mmu,
			address, size, count, buffer);
657
658
}

659
660
661
static int arm926ejs_read_phys_memory(struct target_s *target,
		uint32_t address, uint32_t size,
		uint32_t count, uint8_t *buffer)
662
{
663
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
664

665
666
	return armv4_5_mmu_read_physical(target, &arm926ejs->armv4_5_mmu,
			address, size, count, buffer);
667
668
}

669
int arm926ejs_init_arch_info(target_t *target, struct arm926ejs_common *arm926ejs,
670
		struct jtag_tap *tap)
671
{
672
	struct arm9tdmi_common *arm9tdmi = &arm926ejs->arm9tdmi_common;
673
	struct arm7_9_common *arm7_9 = &arm9tdmi->arm7_9_common;
oharboe's avatar
oharboe committed
674

675
676
	/* initialize arm9tdmi specific info (including arm7_9 and armv4_5)
	 */
677
	arm9tdmi_init_arch_info(target, arm9tdmi, tap);
678
679

	arm926ejs->common_magic = ARM926EJS_COMMON_MAGIC;
oharboe's avatar
oharboe committed
680

681
682
	arm7_9->post_debug_entry = arm926ejs_post_debug_entry;
	arm7_9->pre_restore_context = arm926ejs_pre_restore_context;
oharboe's avatar
oharboe committed
683

684
685
686
687
688
689
690
691
692
693
	arm926ejs->read_cp15 = arm926ejs_cp15_read;
	arm926ejs->write_cp15 = arm926ejs_cp15_write;
	arm926ejs->armv4_5_mmu.armv4_5_cache.ctype = -1;
	arm926ejs->armv4_5_mmu.get_ttb = arm926ejs_get_ttb;
	arm926ejs->armv4_5_mmu.read_memory = arm7_9_read_memory;
	arm926ejs->armv4_5_mmu.write_memory = arm7_9_write_memory;
	arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches;
	arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches;
	arm926ejs->armv4_5_mmu.has_tiny_pages = 1;
	arm926ejs->armv4_5_mmu.mmu_enabled = 0;
oharboe's avatar
oharboe committed
694

695
	arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason;
oharboe's avatar
oharboe committed
696

697
698
699
700
701
	/* The ARM926EJ-S implements the ARMv5TE architecture which
	 * has the BKPT instruction, so we don't have to use a watchpoint comparator
	 */
	arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
	arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
oharboe's avatar
oharboe committed
702

703
704
705
	return ERROR_OK;
}

706
static int arm926ejs_target_create(struct target_s *target, Jim_Interp *interp)
707
{
708
	struct arm926ejs_common *arm926ejs = calloc(1,sizeof(struct arm926ejs_common));
oharboe's avatar
oharboe committed
709

David Brownell's avatar
David Brownell committed
710
711
	/* ARM9EJ-S core always reports 0x1 in Capture-IR */
	target->tap->ir_capture_mask = 0x0f;
712

David Brownell's avatar
David Brownell committed
713
	return arm926ejs_init_arch_info(target, arm926ejs, target->tap);
714
715
}

716
COMMAND_HANDLER(arm926ejs_handle_cp15_command)
717
718
719
{
	int retval;
	target_t *target = get_current_target(cmd_ctx);
720
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
721
722
723
724
725
726
727
728
729
730
	int opcode_1;
	int opcode_2;
	int CRn;
	int CRm;

	if ((argc < 4) || (argc > 5))
	{
		command_print(cmd_ctx, "usage: arm926ejs cp15 <opcode_1> <opcode_2> <CRn> <CRm> [value]");
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
731

732
733
734
735
	COMMAND_PARSE_NUMBER(int, args[0], opcode_1);
	COMMAND_PARSE_NUMBER(int, args[1], opcode_2);
	COMMAND_PARSE_NUMBER(int, args[2], CRn);
	COMMAND_PARSE_NUMBER(int, args[3], CRm);
736

737
738
739
	retval = arm926ejs_verify_pointer(cmd_ctx, arm926ejs);
	if (retval != ERROR_OK)
		return retval;
oharboe's avatar
oharboe committed
740

741
742
	if (target->state != TARGET_HALTED)
	{
743
		command_print(cmd_ctx, "target must be stopped for \"%s\" command", CMD_NAME);
744
745
		return ERROR_OK;
	}
oharboe's avatar
oharboe committed
746

747
748
	if (argc == 4)
	{
749
		uint32_t value;
750
751
752
753
754
		if ((retval = arm926ejs->read_cp15(target, opcode_1, opcode_2, CRn, CRm, &value)) != ERROR_OK)
		{
			command_print(cmd_ctx, "couldn't access register");
			return ERROR_OK;
		}
755
		if ((retval = jtag_execute_queue()) != ERROR_OK)
756
757
758
		{
			return retval;
		}
oharboe's avatar
oharboe committed
759

duane's avatar
duane committed
760
		command_print(cmd_ctx, "%i %i %i %i: %8.8" PRIx32 "", opcode_1, opcode_2, CRn, CRm, value);
761
762
763
	}
	else
	{
764
765
		uint32_t value;
		COMMAND_PARSE_NUMBER(u32, args[4], value);
766
767
768
769
770
		if ((retval = arm926ejs->write_cp15(target, opcode_1, opcode_2, CRn, CRm, value)) != ERROR_OK)
		{
			command_print(cmd_ctx, "couldn't access register");
			return ERROR_OK;
		}
duane's avatar
duane committed
771
		command_print(cmd_ctx, "%i %i %i %i: %8.8" PRIx32 "", opcode_1, opcode_2, CRn, CRm, value);
772
773
774
775
776
	}

	return ERROR_OK;
}

777
COMMAND_HANDLER(arm926ejs_handle_cache_info_command)
778
{
779
	int retval;
780
	target_t *target = get_current_target(cmd_ctx);
781
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
oharboe's avatar
oharboe committed
782

783
784
785
	retval = arm926ejs_verify_pointer(cmd_ctx, arm926ejs);
	if (retval != ERROR_OK)
		return retval;
oharboe's avatar
oharboe committed
786

787
788
789
	return armv4_5_handle_cache_info_command(cmd_ctx, &arm926ejs->armv4_5_mmu.armv4_5_cache);
}

790
static int arm926ejs_virt2phys(struct target_s *target, uint32_t virtual, uint32_t *physical)
791
792
{
	int type;
793
	uint32_t cb;
794
	int domain;
795
	uint32_t ap;
796
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
oharboe's avatar
oharboe committed
797

798
	uint32_t ret = armv4_5_mmu_translate_va(target, &arm926ejs->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
799
800
801
802
803
804
805
806
807
808
	if (type == -1)
	{
		return ret;
	}
	*physical = ret;
	return ERROR_OK;
}

static int arm926ejs_mmu(struct target_s *target, int *enabled)
{
809
	struct arm926ejs_common *arm926ejs = target_to_arm926(target);
oharboe's avatar
oharboe committed
810

811
812
	if (target->state != TARGET_HALTED)
	{
813
		LOG_ERROR("Target not halted");
814
815
816
817
818
		return ERROR_TARGET_INVALID;
	}
	*enabled = arm926ejs->armv4_5_mmu.mmu_enabled;
	return ERROR_OK;
}
819

David Brownell's avatar
David Brownell committed
820
/** Registers commands to access coprocessor, cache, and debug resources.  */
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
int arm926ejs_register_commands(struct command_context_s *cmd_ctx)
{
	int retval;
	command_t *arm926ejs_cmd;

	retval = arm9tdmi_register_commands(cmd_ctx);

	arm926ejs_cmd = register_command(cmd_ctx, NULL, "arm926ejs",
		NULL, COMMAND_ANY,
		"arm926ejs specific commands");

	register_command(cmd_ctx, arm926ejs_cmd, "cp15",
		arm926ejs_handle_cp15_command, COMMAND_EXEC,
		"display/modify cp15 register "
		"<opcode_1> <opcode_2> <CRn> <CRm> [value]");

	register_command(cmd_ctx, arm926ejs_cmd, "cache_info",
		arm926ejs_handle_cache_info_command, COMMAND_EXEC,
		"display information about target caches");

	return retval;
}

David Brownell's avatar
David Brownell committed
844
/** Holds methods for ARM926 targets. */
845
struct target_type arm926ejs_target =
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
{
	.name = "arm926ejs",

	.poll = arm7_9_poll,
	.arch_state = arm926ejs_arch_state,

	.target_request_data = arm7_9_target_request_data,

	.halt = arm7_9_halt,
	.resume = arm7_9_resume,
	.step = arm7_9_step,

	.assert_reset = arm7_9_assert_reset,
	.deassert_reset = arm7_9_deassert_reset,
	.soft_reset_halt = arm926ejs_soft_reset_halt,

	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,

	.read_memory = arm7_9_read_memory,
	.write_memory = arm926ejs_write_memory,
	.bulk_write_memory = arm7_9_bulk_write_memory,
	.checksum_memory = arm7_9_checksum_memory,
	.blank_check_memory = arm7_9_blank_check_memory,

	.run_algorithm = armv4_5_run_algorithm,

	.add_breakpoint = arm7_9_add_breakpoint,
	.remove_breakpoint = arm7_9_remove_breakpoint,
	.add_watchpoint = arm7_9_add_watchpoint,
	.remove_watchpoint = arm7_9_remove_watchpoint,

	.register_commands = arm926ejs_register_commands,
	.target_create = arm926ejs_target_create,
David Brownell's avatar
David Brownell committed
879
	.init_target = arm9tdmi_init_target,
880
881
882
883
884
885
886
887
888
	.examine = arm9tdmi_examine,
	.virt2phys = arm926ejs_virt2phys,
	.mmu = arm926ejs_mmu,

	.read_phys_memory = arm926ejs_read_phys_memory,
	.write_phys_memory = arm926ejs_write_phys_memory,
	.mrc = arm926ejs_mrc,
	.mcr = arm926ejs_mcr,
};