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

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)