You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

793 lines
23 KiB

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