openocd: src/target: replace the GPL-2.0-or-later license tag
[openocd.git] / src / target / arm946e.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 * *
7 * Copyright (C) 2008 by Spencer Oliver *
8 * spen@spen-soft.co.uk *
9 * *
10 * Copyright (C) 2010 by Drasko DRASKOVIC *
11 * drasko.draskovic@gmail.com *
12 ***************************************************************************/
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include "arm946e.h"
19 #include "target_type.h"
20 #include "arm_opcodes.h"
21
22 #include "breakpoints.h"
23
24 #if 0
25 #define _DEBUG_INSTRUCTION_EXECUTION_
26 #endif
27
28 #define NB_CACHE_WAYS 4
29
30 #define CP15_CTL 0x02
31 #define CP15_CTL_DCACHE (1<<2)
32 #define CP15_CTL_ICACHE (1<<12)
33
34 /**
35 * flag to give info about cache manipulation during debug :
36 * "0" - cache lines are invalidated "on the fly", for affected addresses.
37 * This is preferred from performance point of view.
38 * "1" - cache is invalidated and switched off on debug_entry, and switched back on on restore.
39 * It is kept off during debugging.
40 */
41 static uint8_t arm946e_preserve_cache;
42
43 static int arm946e_post_debug_entry(struct target *target);
44 static void arm946e_pre_restore_context(struct target *target);
45 static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value);
46
47 int arm946e_init_arch_info(struct target *target,
48 struct arm946e_common *arm946e,
49 struct jtag_tap *tap)
50 {
51 struct arm7_9_common *arm7_9 = &arm946e->arm7_9_common;
52
53 /* initialize arm7/arm9 specific info (including armv4_5) */
54 arm9tdmi_init_arch_info(target, arm7_9, tap);
55
56 arm946e->common_magic = ARM946E_COMMON_MAGIC;
57
58 /**
59 * The ARM946E-S implements the ARMv5TE architecture which
60 * has the BKPT instruction, so we don't have to use a watchpoint comparator
61 */
62 arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
63 arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
64
65
66 arm7_9->post_debug_entry = arm946e_post_debug_entry;
67 arm7_9->pre_restore_context = arm946e_pre_restore_context;
68
69 /**
70 * disabling linefills leads to lockups, so keep them enabled for now
71 * this doesn't affect correctness, but might affect timing issues, if
72 * important data is evicted from the cache during the debug session
73 */
74 arm946e_preserve_cache = 0;
75
76 /* override hw single-step capability from ARM9TDMI */
77 /* arm7_9->has_single_step = 1; */
78
79 return ERROR_OK;
80 }
81
82 static int arm946e_target_create(struct target *target, Jim_Interp *interp)
83 {
84 struct arm946e_common *arm946e = calloc(1, sizeof(struct arm946e_common));
85
86 arm946e_init_arch_info(target, arm946e, target->tap);
87
88 return ERROR_OK;
89 }
90
91 static void arm946e_deinit_target(struct target *target)
92 {
93 struct arm *arm = target_to_arm(target);
94 struct arm946e_common *arm946e = target_to_arm946(target);
95
96 arm7_9_deinit(target);
97 arm_free_reg_cache(arm);
98 free(arm946e);
99 }
100
101 static int arm946e_verify_pointer(struct command_invocation *cmd,
102 struct arm946e_common *arm946e)
103 {
104 if (arm946e->common_magic != ARM946E_COMMON_MAGIC) {
105 command_print(cmd, "target is not an ARM946");
106 return ERROR_TARGET_INVALID;
107 }
108 return ERROR_OK;
109 }
110
111 /*
112 * Update cp15_control_reg, saved on debug_entry.
113 */
114 static void arm946e_update_cp15_caches(struct target *target, uint32_t value)
115 {
116 struct arm946e_common *arm946e = target_to_arm946(target);
117 arm946e->cp15_control_reg = (arm946e->cp15_control_reg & ~(CP15_CTL_DCACHE|CP15_CTL_ICACHE))
118 | (value & (CP15_CTL_DCACHE|CP15_CTL_ICACHE));
119 }
120
121 /*
122 * REVISIT: The "read_cp15" and "write_cp15" commands could hook up
123 * to eventual mrc() and mcr() routines ... the reg_addr values being
124 * constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values.
125 * See section 7.3 of the ARM946E-S TRM.
126 */
127 static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value)
128 {
129 int retval = ERROR_OK;
130 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
131 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
132 struct scan_field fields[3];
133 uint8_t reg_addr_buf = reg_addr & 0x3f;
134 uint8_t nr_w_buf = 0;
135
136 retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
137 if (retval != ERROR_OK)
138 return retval;
139 retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
140 if (retval != ERROR_OK)
141 return retval;
142
143 fields[0].num_bits = 32;
144 /* REVISIT: table 7-2 shows that bits 31-31 need to be
145 * specified for accessing BIST registers ...
146 */
147 fields[0].out_value = NULL;
148 fields[0].in_value = NULL;
149
150 fields[1].num_bits = 6;
151 fields[1].out_value = &reg_addr_buf;
152 fields[1].in_value = NULL;
153
154 fields[2].num_bits = 1;
155 fields[2].out_value = &nr_w_buf;
156 fields[2].in_value = NULL;
157
158 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
159
160 fields[0].in_value = (uint8_t *)value;
161 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
162
163 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
164
165 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
166 LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
167 #endif
168
169 retval = jtag_execute_queue();
170 if (retval != ERROR_OK)
171 return retval;
172
173 return ERROR_OK;
174 }
175
176 int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value)
177 {
178 int retval = ERROR_OK;
179 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
180 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
181 struct scan_field fields[3];
182 uint8_t reg_addr_buf = reg_addr & 0x3f;
183 uint8_t nr_w_buf = 1;
184 uint8_t value_buf[4];
185
186 buf_set_u32(value_buf, 0, 32, value);
187
188 retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
189 if (retval != ERROR_OK)
190 return retval;
191 retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
192 if (retval != ERROR_OK)
193 return retval;
194
195 fields[0].num_bits = 32;
196 fields[0].out_value = value_buf;
197 fields[0].in_value = NULL;
198
199 fields[1].num_bits = 6;
200 fields[1].out_value = &reg_addr_buf;
201 fields[1].in_value = NULL;
202
203 fields[2].num_bits = 1;
204 fields[2].out_value = &nr_w_buf;
205 fields[2].in_value = NULL;
206
207 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
208
209 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
210 LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
211 #endif
212
213 retval = jtag_execute_queue();
214 if (retval != ERROR_OK)
215 return retval;
216
217 return ERROR_OK;
218 }
219
220 #define GET_ICACHE_SIZE 6
221 #define GET_DCACHE_SIZE 18
222
223 /*
224 * \param target struct target pointer
225 * \param idsel select GET_ICACHE_SIZE or GET_DCACHE_SIZE
226 * \returns cache size, given in bytes
227 */
228 static uint32_t arm946e_cp15_get_csize(struct target *target, int idsel)
229 {
230 struct arm946e_common *arm946e = target_to_arm946(target);
231 uint32_t csize = arm946e->cp15_cache_info;
232 if (csize == 0) {
233 if (arm946e_read_cp15(target, 0x01, &csize) == ERROR_OK)
234 arm946e->cp15_cache_info = csize;
235 }
236 if (csize & (1<<(idsel-4))) /* cache absent */
237 return 0;
238 csize = (csize >> idsel) & 0x0F;
239 return csize ? 1 << (12 + (csize-3)) : 0;
240 }
241
242 static uint32_t arm946e_invalidate_whole_dcache(struct target *target)
243 {
244 uint32_t csize = arm946e_cp15_get_csize(target, GET_DCACHE_SIZE);
245 if (csize == 0)
246 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
247
248 /* One line (index) is 32 bytes (8 words) long, 4-way assoc
249 * ARM DDI 0201D, Section 3.3.5
250 */
251 int nb_idx = (csize / (4*8*NB_CACHE_WAYS)); /* gives nb of lines (indexes) in the cache */
252
253 /* Loop for all segments (i.e. ways) */
254 uint32_t seg;
255 for (seg = 0; seg < NB_CACHE_WAYS; seg++) {
256 /* Loop for all indexes */
257 int idx;
258 for (idx = 0; idx < nb_idx; idx++) {
259 /* Form and write cp15 index (segment + line idx) */
260 uint32_t cp15_idx = seg << 30 | idx << 5;
261 int retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
262 if (retval != ERROR_OK) {
263 LOG_DEBUG("ERROR writing index");
264 return retval;
265 }
266
267 /* Read dtag */
268 uint32_t dtag;
269 retval = arm946e_read_cp15(target, 0x16, &dtag);
270 if (retval != ERROR_OK) {
271 LOG_DEBUG("ERROR reading dtag");
272 return retval;
273 }
274
275 /* Check cache line VALID bit */
276 if (!(dtag >> 4 & 0x1))
277 continue;
278
279 /* Clean data cache line */
280 retval = arm946e_write_cp15(target, 0x35, 0x1);
281 if (retval != ERROR_OK) {
282 LOG_DEBUG("ERROR cleaning cache line");
283 return retval;
284 }
285
286 /* Flush data cache line */
287 retval = arm946e_write_cp15(target, 0x1a, 0x1);
288 if (retval != ERROR_OK) {
289 LOG_DEBUG("ERROR flushing cache line");
290 return retval;
291 }
292 }
293 }
294
295 return ERROR_OK;
296 }
297
298 static uint32_t arm946e_invalidate_whole_icache(struct target *target)
299 {
300 /* Check cache presence before flushing - avoid undefined behavior */
301 uint32_t csize = arm946e_cp15_get_csize(target, GET_ICACHE_SIZE);
302 if (csize == 0)
303 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
304
305 LOG_DEBUG("FLUSHING I$");
306 /**
307 * Invalidate (flush) I$
308 * mcr 15, 0, r0, cr7, cr5, {0}
309 */
310 int retval = arm946e_write_cp15(target, 0x0f, 0x1);
311 if (retval != ERROR_OK) {
312 LOG_DEBUG("ERROR flushing I$");
313 return retval;
314 }
315
316 return ERROR_OK;
317 }
318
319 static int arm946e_post_debug_entry(struct target *target)
320 {
321 uint32_t ctr_reg = 0x0;
322 uint32_t retval = ERROR_OK;
323 struct arm946e_common *arm946e = target_to_arm946(target);
324
325 /* See if CACHES are enabled, and save that info
326 * in the context bits, so that arm946e_pre_restore_context() can use them */
327 arm946e_read_cp15(target, CP15_CTL, &ctr_reg);
328
329 /* Save control reg in the context */
330 arm946e->cp15_control_reg = ctr_reg;
331
332 if (arm946e_preserve_cache) {
333 if (ctr_reg & CP15_CTL_DCACHE) {
334 /* Clean and flush D$ */
335 arm946e_invalidate_whole_dcache(target);
336
337 /* Disable D$ */
338 ctr_reg &= ~CP15_CTL_DCACHE;
339 }
340
341 if (ctr_reg & CP15_CTL_ICACHE) {
342 /* Flush I$ */
343 arm946e_invalidate_whole_icache(target);
344
345 /* Disable I$ */
346 ctr_reg &= ~CP15_CTL_ICACHE;
347 }
348
349 /* Write the new configuration */
350 retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg);
351 if (retval != ERROR_OK) {
352 LOG_DEBUG("ERROR disabling cache");
353 return retval;
354 }
355 } /* if preserve_cache */
356
357 return ERROR_OK;
358 }
359
360 static void arm946e_pre_restore_context(struct target *target)
361 {
362 uint32_t ctr_reg = 0x0;
363 uint32_t retval;
364
365 if (arm946e_preserve_cache) {
366 struct arm946e_common *arm946e = target_to_arm946(target);
367 /* Get the contents of the CTR reg */
368 arm946e_read_cp15(target, CP15_CTL, &ctr_reg);
369
370 /**
371 * Read-modify-write CP15 control
372 * to reenable I/D-cache operation
373 * NOTE: It is not possible to disable cache by CP15.
374 * if arm946e_preserve_cache debugging flag enabled.
375 */
376 ctr_reg |= arm946e->cp15_control_reg & (CP15_CTL_DCACHE|CP15_CTL_ICACHE);
377
378 /* Write the new configuration */
379 retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg);
380 if (retval != ERROR_OK)
381 LOG_DEBUG("ERROR enabling cache");
382 } /* if preserve_cache */
383 }
384
385 static uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
386 uint32_t size, uint32_t count)
387 {
388 uint32_t cur_addr = 0x0;
389 uint32_t cp15_idx, set, way, dtag;
390 uint32_t i = 0;
391 int retval;
392
393 for (i = 0; i < count*size; i++) {
394 cur_addr = address + i;
395
396
397 set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
398
399 for (way = 0; way < NB_CACHE_WAYS; way++) {
400 /**
401 * Find if the affected address is kept in the cache.
402 * Because JTAG Scan Chain 15 offers limited approach,
403 * we have to loop through all cache ways (segments) and
404 * read cache tags, then compare them with with address.
405 */
406
407 /* Form and write cp15 index (segment + line idx) */
408 cp15_idx = way << 30 | set << 5;
409 retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
410 if (retval != ERROR_OK) {
411 LOG_DEBUG("ERROR writing index");
412 return retval;
413 }
414
415 /* Read dtag */
416 retval = arm946e_read_cp15(target, 0x16, &dtag);
417 if (retval != ERROR_OK) {
418 LOG_DEBUG("ERROR reading dtag");
419 return retval;
420 }
421
422 /* Check cache line VALID bit */
423 if (!(dtag >> 4 & 0x1))
424 continue;
425
426 /* If line is valid and corresponds to affected address - invalidate it */
427 if (dtag >> 5 == cur_addr >> 5) {
428 /* Clean data cache line */
429 retval = arm946e_write_cp15(target, 0x35, 0x1);
430 if (retval != ERROR_OK) {
431 LOG_DEBUG("ERROR cleaning cache line");
432 return retval;
433 }
434
435 /* Flush data cache line */
436 retval = arm946e_write_cp15(target, 0x1c, 0x1);
437 if (retval != ERROR_OK) {
438 LOG_DEBUG("ERROR flushing cache line");
439 return retval;
440 }
441
442 break;
443 }
444 } /* loop through all 4 ways */
445 } /* loop through all addresses */
446
447 return ERROR_OK;
448 }
449
450 static uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address,
451 uint32_t size, uint32_t count)
452 {
453 uint32_t cur_addr = 0x0;
454 uint32_t cp15_idx, set, way, itag;
455 uint32_t i = 0;
456 int retval;
457
458 for (i = 0; i < count*size; i++) {
459 cur_addr = address + i;
460
461 set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
462
463 for (way = 0; way < NB_CACHE_WAYS; way++) {
464 /* Form and write cp15 index (segment + line idx) */
465 cp15_idx = way << 30 | set << 5;
466 retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
467 if (retval != ERROR_OK) {
468 LOG_DEBUG("ERROR writing index");
469 return retval;
470 }
471
472 /* Read itag */
473 retval = arm946e_read_cp15(target, 0x17, &itag);
474 if (retval != ERROR_OK) {
475 LOG_DEBUG("ERROR reading itag");
476 return retval;
477 }
478
479 /* Check cache line VALID bit */
480 if (!(itag >> 4 & 0x1))
481 continue;
482
483 /* If line is valid and corresponds to affected address - invalidate it */
484 if (itag >> 5 == cur_addr >> 5) {
485 /* Flush I$ line */
486 retval = arm946e_write_cp15(target, 0x1d, 0x0);
487 if (retval != ERROR_OK) {
488 LOG_DEBUG("ERROR flushing cache line");
489 return retval;
490 }
491
492 break;
493 }
494 } /* way loop */
495 } /* addr loop */
496
497 return ERROR_OK;
498 }
499
500 /** Writes a buffer, in the specified word size, with current MMU settings. */
501 static int arm946e_write_memory(struct target *target, target_addr_t address,
502 uint32_t size, uint32_t count, const uint8_t *buffer)
503 {
504 int retval;
505
506 LOG_DEBUG("-");
507
508 struct arm946e_common *arm946e = target_to_arm946(target);
509 /* Invalidate D$ if it is ON */
510 if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_DCACHE))
511 arm946e_invalidate_dcache(target, address, size, count);
512
513 /**
514 * Write memory
515 */
516 retval = arm7_9_write_memory_opt(target, address, size, count, buffer);
517 if (retval != ERROR_OK)
518 return retval;
519
520 /* *
521 * Invalidate I$ if it is ON.
522 *
523 * D$ has been cleaned and flushed before mem write thus forcing it to behave like write-through,
524 * because arm7_9_write_memory() has seen non-valid bit in D$
525 * and wrote data into physical RAM (without touching or allocating the cache line).
526 * From ARM946ES Technical Reference Manual we can see that it uses "allocate on read-miss"
527 * policy for both I$ and D$ (Chapter 3.2 and 3.3)
528 *
529 * Explanation :
530 * "ARM system developer's guide: designing and optimizing system software" by
531 * Andrew N. Sloss, Dominic Symes and Chris Wright,
532 * Chapter 12.3.3 Allocating Policy on a Cache Miss :
533 * A read allocate on cache miss policy allocates a cache line only during a read from main memory.
534 * If the victim cache line contains valid data, then it is written to main memory before the cache line
535 * is filled with new data.
536 * Under this strategy, a write of new data to memory does not update the contents of the cache memory
537 * unless a cache line was allocated on a previous read from main memory.
538 * If the cache line contains valid data, then the write updates the cache and may update the main memory if
539 * the cache write policy is write-through.
540 * If the data is not in the cache, the controller writes to main memory only.
541 */
542 if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_ICACHE))
543 arm946e_invalidate_icache(target, address, size, count);
544
545 return ERROR_OK;
546
547 }
548
549 static int arm946e_read_memory(struct target *target, target_addr_t address,
550 uint32_t size, uint32_t count, uint8_t *buffer)
551 {
552 int retval;
553
554 LOG_DEBUG("-");
555
556 retval = arm7_9_read_memory(target, address, size, count, buffer);
557 if (retval != ERROR_OK)
558 return retval;
559
560 return ERROR_OK;
561 }
562
563 COMMAND_HANDLER(arm946e_handle_cp15)
564 {
565 /* one or two arguments, access a single register (write if second argument is given) */
566 if (CMD_ARGC < 1 || CMD_ARGC > 2)
567 return ERROR_COMMAND_SYNTAX_ERROR;
568
569 struct target *target = get_current_target(CMD_CTX);
570
571 struct arm946e_common *arm946e = target_to_arm946(target);
572 int retval = arm946e_verify_pointer(CMD, arm946e);
573 if (retval != ERROR_OK)
574 return retval;
575
576 if (target->state != TARGET_HALTED) {
577 command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
578 return ERROR_TARGET_NOT_HALTED;
579 }
580
581 uint32_t address;
582 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
583
584 if (CMD_ARGC == 1) {
585 uint32_t value;
586 retval = arm946e_read_cp15(target, address, &value);
587 if (retval != ERROR_OK) {
588 command_print(CMD, "%s cp15 reg %" PRIu32 " access failed", target_name(target), address);
589 return retval;
590 }
591 retval = jtag_execute_queue();
592 if (retval != ERROR_OK)
593 return retval;
594
595 /* Return value in hex format */
596 command_print(CMD, "0x%08" PRIx32, value);
597 } else if (CMD_ARGC == 2) {
598 uint32_t value;
599 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
600
601 retval = arm946e_write_cp15(target, address, value);
602 if (retval != ERROR_OK) {
603 command_print(CMD, "%s cp15 reg %" PRIu32 " access failed", target_name(target), address);
604 return retval;
605 }
606 if (address == CP15_CTL)
607 arm946e_update_cp15_caches(target, value);
608 }
609
610 return ERROR_OK;
611 }
612
613 COMMAND_HANDLER(arm946e_handle_idcache)
614 {
615 if (CMD_ARGC > 1)
616 return ERROR_COMMAND_SYNTAX_ERROR;
617
618 int retval;
619 struct target *target = get_current_target(CMD_CTX);
620 struct arm946e_common *arm946e = target_to_arm946(target);
621
622 retval = arm946e_verify_pointer(CMD, arm946e);
623 if (retval != ERROR_OK)
624 return retval;
625
626 if (target->state != TARGET_HALTED) {
627 command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
628 return ERROR_TARGET_NOT_HALTED;
629 }
630
631 bool icache = (strcmp(CMD_NAME, "icache") == 0);
632 uint32_t csize = arm946e_cp15_get_csize(target, icache ? GET_ICACHE_SIZE : GET_DCACHE_SIZE) / 1024;
633 if (CMD_ARGC == 0) {
634 bool bena = ((arm946e->cp15_control_reg & (icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE)) != 0)
635 && (arm946e->cp15_control_reg & 0x1);
636 if (csize == 0)
637 command_print(CMD, "%s-cache absent", icache ? "I" : "D");
638 else
639 command_print(CMD, "%s-cache size: %" PRIu32 "K, %s",
640 icache ? "I" : "D", csize, bena ? "enabled" : "disabled");
641 return ERROR_OK;
642 }
643
644 bool flush = false;
645 bool enable = false;
646 retval = command_parse_bool_arg(CMD_ARGV[0], &enable);
647 if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
648 if (strcmp(CMD_ARGV[0], "flush") == 0) {
649 flush = true;
650 retval = ERROR_OK;
651 } else
652 return retval;
653 }
654
655 /* Do not invalidate or change state, if cache is absent */
656 if (csize == 0) {
657 command_print(CMD, "%s-cache absent, '%s' operation undefined", icache ? "I" : "D", CMD_ARGV[0]);
658 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
659 }
660
661 /* NOTE: flushing entire cache will not preserve lock-down cache regions */
662 if (icache) {
663 if ((arm946e->cp15_control_reg & CP15_CTL_ICACHE) && !enable)
664 retval = arm946e_invalidate_whole_icache(target);
665 } else {
666 if ((arm946e->cp15_control_reg & CP15_CTL_DCACHE) && !enable)
667 retval = arm946e_invalidate_whole_dcache(target);
668 }
669
670 if (retval != ERROR_OK || flush)
671 return retval;
672
673 uint32_t value;
674 retval = arm946e_read_cp15(target, CP15_CTL, &value);
675 if (retval != ERROR_OK)
676 return retval;
677
678 uint32_t vnew = value;
679 uint32_t cmask = icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE;
680 if (enable) {
681 if ((value & 0x1) == 0)
682 LOG_WARNING("arm946e: MPU must be enabled for cache to operate");
683 vnew |= cmask;
684 } else
685 vnew &= ~cmask;
686
687 if (vnew == value)
688 return ERROR_OK;
689
690 retval = arm946e_write_cp15(target, CP15_CTL, vnew);
691 if (retval != ERROR_OK)
692 return retval;
693
694 arm946e_update_cp15_caches(target, vnew);
695 return ERROR_OK;
696 }
697
698 static const struct command_registration arm946e_exec_command_handlers[] = {
699 {
700 .name = "cp15",
701 .handler = arm946e_handle_cp15,
702 .mode = COMMAND_EXEC,
703 .usage = "regnum [value]",
704 .help = "read/modify cp15 register",
705 },
706 {
707 .name = "icache",
708 .handler = arm946e_handle_idcache,
709 .mode = COMMAND_EXEC,
710 .usage = "['enable'|'disable'|'flush']",
711 .help = "I-cache info and operations",
712 },
713 {
714 .name = "dcache",
715 .handler = arm946e_handle_idcache,
716 .mode = COMMAND_EXEC,
717 .usage = "['enable'|'disable'|'flush']",
718 .help = "D-cache info and operations",
719 },
720 COMMAND_REGISTRATION_DONE
721 };
722
723 const struct command_registration arm946e_command_handlers[] = {
724 {
725 .chain = arm9tdmi_command_handlers,
726 },
727 {
728 .name = "arm946e",
729 .mode = COMMAND_ANY,
730 .help = "arm946e command group",
731 .usage = "",
732 .chain = arm946e_exec_command_handlers,
733 },
734 COMMAND_REGISTRATION_DONE
735 };
736
737 /** Holds methods for ARM946 targets. */
738 struct target_type arm946e_target = {
739 .name = "arm946e",
740
741 .poll = arm7_9_poll,
742 .arch_state = arm_arch_state,
743
744 .target_request_data = arm7_9_target_request_data,
745
746 .halt = arm7_9_halt,
747 .resume = arm7_9_resume,
748 .step = arm7_9_step,
749
750 .assert_reset = arm7_9_assert_reset,
751 .deassert_reset = arm7_9_deassert_reset,
752 .soft_reset_halt = arm7_9_soft_reset_halt,
753
754 .get_gdb_arch = arm_get_gdb_arch,
755 .get_gdb_reg_list = arm_get_gdb_reg_list,
756
757 /* .read_memory = arm7_9_read_memory, */
758 /* .write_memory = arm7_9_write_memory, */
759 .read_memory = arm946e_read_memory,
760 .write_memory = arm946e_write_memory,
761
762 .checksum_memory = arm_checksum_memory,
763 .blank_check_memory = arm_blank_check_memory,
764
765 .run_algorithm = armv4_5_run_algorithm,
766
767 .add_breakpoint = arm7_9_add_breakpoint,
768 .remove_breakpoint = arm7_9_remove_breakpoint,
769 /* .add_breakpoint = arm946e_add_breakpoint, */
770 /* .remove_breakpoint = arm946e_remove_breakpoint, */
771
772 .add_watchpoint = arm7_9_add_watchpoint,
773 .remove_watchpoint = arm7_9_remove_watchpoint,
774
775 .commands = arm946e_command_handlers,
776 .target_create = arm946e_target_create,
777 .init_target = arm9tdmi_init_target,
778 .deinit_target = arm946e_deinit_target,
779 .examine = arm7_9_examine,
780 .check_reset = arm7_9_check_reset,
781 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)