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

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)