X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Ftarget%2Fcortex_a.c;h=13b8ca54930c753603cf7d8c9ed21f0e9ea7f468;hb=bd0fbef5c8819c9f58b48f02acd862d9be4d87b9;hp=27b780e6720fadfdaf5f39a90074df5e94f0e2bb;hpb=4e47519f6c519b792297efaa482852cd9eef554a;p=fw%2Fopenocd diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 27b780e67..13b8ca549 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -17,6 +17,9 @@ * Copyright (C) ST-Ericsson SA 2011 * * michel.jaouen@stericsson.com : smp minimum support * * * + * Copyright (C) Broadcom 2012 * + * ehunter@broadcom.com : Cortex R4 support * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -30,10 +33,11 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * * * Cortex-A8(tm) TRM, ARM DDI 0344H * * Cortex-A9(tm) TRM, ARM DDI 0407F * + * Cortex-A4(tm) TRM, ARM DDI 0363E * * * ***************************************************************************/ @@ -98,14 +102,14 @@ static int cortex_a8_check_address(struct target *target, uint32_t address) uint32_t os_border = armv7a->armv7a_mmu.os_border; if ((address < os_border) && (armv7a->arm.core_mode == ARM_MODE_SVC)) { - LOG_ERROR("%x access in userspace and target in supervisor", address); + LOG_ERROR("%" PRIx32 " access in userspace and target in supervisor", address); return ERROR_FAIL; } if ((address >= os_border) && (cortex_a8->curr_mode != ARM_MODE_SVC)) { dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC); cortex_a8->curr_mode = ARM_MODE_SVC; - LOG_INFO("%x access in kernel space and target not in supervisor", + LOG_INFO("%" PRIx32 " access in kernel space and target not in supervisor", address); return ERROR_OK; } @@ -275,8 +279,8 @@ static int cortex_a8_read_regs_through_mem(struct target *target, uint32_t addre if (retval != ERROR_OK) return retval; - retval = mem_ap_sel_read_buf_u32(swjdp, armv7a->memory_ap, - (uint8_t *)(®file[1]), 4*15, address); + retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, + (uint8_t *)(®file[1]), 4, 15, address); return retval; } @@ -1240,8 +1244,12 @@ static int cortex_a8_post_debug_entry(struct target *target) if (armv7a->armv7a_mmu.armv7a_cache.ctype == -1) armv7a_identify_cache(target); - armv7a->armv7a_mmu.mmu_enabled = - (cortex_a8->cp15_control_reg & 0x1U) ? 1 : 0; + if (armv7a->is_armv7r) { + armv7a->armv7a_mmu.mmu_enabled = 0; + } else { + armv7a->armv7a_mmu.mmu_enabled = + (cortex_a8->cp15_control_reg & 0x1U) ? 1 : 0; + } armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled = (cortex_a8->cp15_control_reg & 0x4U) ? 1 : 0; armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled = @@ -1883,8 +1891,8 @@ static int cortex_a8_write_apb_ab_memory(struct target *target, goto error_unset_dtr_w; /* Do the write */ - retval = mem_ap_sel_write_buf_u32_noincr(swjdp, armv7a->debug_ap, - tmp_buff, (total_u32)<<2, armv7a->debug_base + CPUDBG_DTRRX); + retval = mem_ap_sel_write_buf_noincr(swjdp, armv7a->debug_ap, + tmp_buff, 4, total_u32, armv7a->debug_base + CPUDBG_DTRRX); if (retval != ERROR_OK) goto error_unset_dtr_w; @@ -1903,7 +1911,7 @@ static int cortex_a8_write_apb_ab_memory(struct target *target, goto error_free_buff_w; if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { /* Abort occurred - clear it and exit */ - LOG_ERROR("abort occurred - dscr = 0x%08x", dscr); + LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, 1<<2); goto error_free_buff_w; @@ -1941,7 +1949,7 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, int start_byte = address & 0x3; struct reg *reg; uint32_t dscr; - char *tmp_buff = NULL; + uint32_t *tmp_buff; uint32_t buff32[2]; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -1950,6 +1958,14 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, total_u32 = DIV_ROUND_UP((address & 3) + total_bytes, 4); + /* Due to offset word alignment, the buffer may not have space + * to read the full first and last int32 words, + * hence, malloc space to read into, then copy and align into the buffer. + */ + tmp_buff = malloc(total_u32 * 4); + if (tmp_buff == NULL) + return ERROR_FAIL; + /* Mark register R0 as dirty, as it will be used * for transferring the data. * It will be restored automatically when exiting @@ -1962,7 +1978,7 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, 1<<2); if (retval != ERROR_OK) - return retval; + goto error_free_buff_r; /* Read DSCR */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, @@ -1995,18 +2011,12 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, dscr = (dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_FAST_MODE; buff32[1] = dscr; /* group the 2 access CPUDBG_ITR 0x84 and CPUDBG_DSCR 0x88 */ - retval += mem_ap_sel_write_buf_u32(swjdp, armv7a->debug_ap, (uint8_t *)buff32, 8, + retval += mem_ap_sel_write_buf(swjdp, armv7a->debug_ap, (uint8_t *)buff32, 4, 2, armv7a->debug_base + CPUDBG_ITR); if (retval != ERROR_OK) goto error_unset_dtr_r; - /* Due to offset word alignment, the buffer may not have space - * to read the full first and last int32 words, - * hence, malloc space to read into, then copy and align into the buffer. - */ - tmp_buff = (char *) malloc(total_u32<<2); - /* The last word needs to be handled separately - read all other words in one go. */ if (total_u32 > 1) { @@ -2015,7 +2025,7 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, * * This data is read in aligned to 32 bit boundary, hence may need shifting later. */ - retval = mem_ap_sel_read_buf_u32_noincr(swjdp, armv7a->debug_ap, (uint8_t *)tmp_buff, (total_u32-1)<<2, + retval = mem_ap_sel_read_buf_noincr(swjdp, armv7a->debug_ap, (uint8_t *)tmp_buff, 4, total_u32 - 1, armv7a->debug_base + CPUDBG_DTRTX); if (retval != ERROR_OK) goto error_unset_dtr_r; @@ -2044,7 +2054,7 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, goto error_free_buff_r; if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { /* Abort occurred - clear it and exit */ - LOG_ERROR("abort occurred - dscr = 0x%08x", dscr); + LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap, armv7a->debug_base + CPUDBG_DRCR, 1<<2); goto error_free_buff_r; @@ -2052,12 +2062,12 @@ static int cortex_a8_read_apb_ab_memory(struct target *target, /* Read the last word */ retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap, - armv7a->debug_base + CPUDBG_DTRTX, (uint32_t *)&tmp_buff[(total_u32-1)<<2]); + armv7a->debug_base + CPUDBG_DTRTX, &tmp_buff[total_u32 - 1]); if (retval != ERROR_OK) goto error_free_buff_r; /* Copy and align the data into the output buffer */ - memcpy(buffer, &tmp_buff[start_byte], total_bytes); + memcpy(buffer, (uint8_t *)tmp_buff + start_byte, total_bytes); free(tmp_buff); @@ -2094,7 +2104,7 @@ static int cortex_a8_read_phys_memory(struct target *target, struct adiv5_dap *swjdp = armv7a->arm.dap; int retval = ERROR_COMMAND_SYNTAX_ERROR; uint8_t apsel = swjdp->apsel; - LOG_DEBUG("Reading memory at real address 0x%x; size %d; count %d", + LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); if (count && buffer) { @@ -2102,28 +2112,16 @@ static int cortex_a8_read_phys_memory(struct target *target, if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { /* read memory through AHB-AP */ - - switch (size) { - case 4: - retval = mem_ap_sel_read_buf_u32(swjdp, armv7a->memory_ap, - buffer, 4 * count, address); - break; - case 2: - retval = mem_ap_sel_read_buf_u16(swjdp, armv7a->memory_ap, - buffer, 2 * count, address); - break; - case 1: - retval = mem_ap_sel_read_buf_u8(swjdp, armv7a->memory_ap, - buffer, count, address); - break; - } + retval = mem_ap_sel_read_buf(swjdp, armv7a->memory_ap, buffer, size, count, address); } else { - /* read memory through APB-AP - * disable mmu */ - retval = cortex_a8_mmu_modify(target, 0); - if (retval != ERROR_OK) - return retval; + /* read memory through APB-AP */ + if (!armv7a->is_armv7r) { + /* disable mmu */ + retval = cortex_a8_mmu_modify(target, 0); + if (retval != ERROR_OK) + return retval; + } retval = cortex_a8_read_apb_ab_memory(target, address, size, count, buffer); } } @@ -2141,33 +2139,37 @@ static int cortex_a8_read_memory(struct target *target, uint32_t address, uint8_t apsel = swjdp->apsel; /* cortex_a8 handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address, + LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { - retval = cortex_a8_mmu(target, &enabled); - if (retval != ERROR_OK) - return retval; - - - if (enabled) { - virt = address; - retval = cortex_a8_virt2phys(target, virt, &phys); + if (!armv7a->is_armv7r) { + retval = cortex_a8_mmu(target, &enabled); if (retval != ERROR_OK) return retval; - LOG_DEBUG("Reading at virtual address. Translating v:0x%x to r:0x%x", - virt, phys); - address = phys; + + if (enabled) { + virt = address; + retval = cortex_a8_virt2phys(target, virt, &phys); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, + virt, phys); + address = phys; + } } retval = cortex_a8_read_phys_memory(target, address, size, count, buffer); } else { - retval = cortex_a8_check_address(target, address); - if (retval != ERROR_OK) - return retval; - /* enable mmu */ - retval = cortex_a8_mmu_modify(target, 1); - if (retval != ERROR_OK) - return retval; + if (!armv7a->is_armv7r) { + retval = cortex_a8_check_address(target, address); + if (retval != ERROR_OK) + return retval; + /* enable mmu */ + retval = cortex_a8_mmu_modify(target, 1); + if (retval != ERROR_OK) + return retval; + } retval = cortex_a8_read_apb_ab_memory(target, address, size, count, buffer); } return retval; @@ -2182,7 +2184,7 @@ static int cortex_a8_write_phys_memory(struct target *target, int retval = ERROR_COMMAND_SYNTAX_ERROR; uint8_t apsel = swjdp->apsel; - LOG_DEBUG("Writing memory to real address 0x%x; size %d; count %d", address, + LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); if (count && buffer) { @@ -2190,28 +2192,15 @@ static int cortex_a8_write_phys_memory(struct target *target, if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { /* write memory through AHB-AP */ - - switch (size) { - case 4: - retval = mem_ap_sel_write_buf_u32(swjdp, armv7a->memory_ap, - buffer, 4 * count, address); - break; - case 2: - retval = mem_ap_sel_write_buf_u16(swjdp, armv7a->memory_ap, - buffer, 2 * count, address); - break; - case 1: - retval = mem_ap_sel_write_buf_u8(swjdp, armv7a->memory_ap, - buffer, count, address); - break; - } - + retval = mem_ap_sel_write_buf(swjdp, armv7a->memory_ap, buffer, size, count, address); } else { /* write memory through APB-AP */ - retval = cortex_a8_mmu_modify(target, 0); - if (retval != ERROR_OK) - return retval; + if (!armv7a->is_armv7r) { + retval = cortex_a8_mmu_modify(target, 0); + if (retval != ERROR_OK) + return retval; + } return cortex_a8_write_apb_ab_memory(target, address, size, count, buffer); } } @@ -2284,48 +2273,46 @@ static int cortex_a8_write_memory(struct target *target, uint32_t address, struct adiv5_dap *swjdp = armv7a->arm.dap; uint8_t apsel = swjdp->apsel; /* cortex_a8 handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%x; size %d; count %d", address, + LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap)) { - LOG_DEBUG("Writing memory to address 0x%x; size %d; count %d", address, size, + LOG_DEBUG("Writing memory to address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, size, count); - retval = cortex_a8_mmu(target, &enabled); - if (retval != ERROR_OK) - return retval; - - if (enabled) { - virt = address; - retval = cortex_a8_virt2phys(target, virt, &phys); + if (!armv7a->is_armv7r) { + retval = cortex_a8_mmu(target, &enabled); if (retval != ERROR_OK) return retval; - LOG_DEBUG("Writing to virtual address. Translating v:0x%x to r:0x%x", - virt, - phys); - address = phys; + + if (enabled) { + virt = address; + retval = cortex_a8_virt2phys(target, virt, &phys); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, + virt, + phys); + address = phys; + } } retval = cortex_a8_write_phys_memory(target, address, size, count, buffer); } else { - retval = cortex_a8_check_address(target, address); - if (retval != ERROR_OK) - return retval; - /* enable mmu */ - retval = cortex_a8_mmu_modify(target, 1); - if (retval != ERROR_OK) - return retval; + if (!armv7a->is_armv7r) { + retval = cortex_a8_check_address(target, address); + if (retval != ERROR_OK) + return retval; + /* enable mmu */ + retval = cortex_a8_mmu_modify(target, 1); + if (retval != ERROR_OK) + return retval; + } retval = cortex_a8_write_apb_ab_memory(target, address, size, count, buffer); } return retval; } -static int cortex_a8_bulk_write_memory(struct target *target, uint32_t address, - uint32_t count, const uint8_t *buffer) -{ - return cortex_a8_write_memory(target, address, 4, count, buffer); -} - static int cortex_a8_handle_target_request(void *priv) { struct target *target = priv; @@ -2557,9 +2544,19 @@ static int cortex_a8_target_create(struct target *target, Jim_Interp *interp) { struct cortex_a8_common *cortex_a8 = calloc(1, sizeof(struct cortex_a8_common)); + cortex_a8->armv7a_common.is_armv7r = false; + return cortex_a8_init_arch_info(target, cortex_a8, target->tap); } +static int cortex_r4_target_create(struct target *target, Jim_Interp *interp) +{ + struct cortex_a8_common *cortex_a8 = calloc(1, sizeof(struct cortex_a8_common)); + + cortex_a8->armv7a_common.is_armv7r = true; + + return cortex_a8_init_arch_info(target, cortex_a8, target->tap); +} static int cortex_a8_mmu(struct target *target, int *enabled) @@ -2670,7 +2667,7 @@ COMMAND_HANDLER(cortex_a8_handle_smp_gdb_command) target->gdb_service->core[1] = coreid; } - command_print(CMD_CTX, "gdb coreid %d -> %d", target->gdb_service->core[0] + command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] , target->gdb_service->core[1]); } return ERROR_OK; @@ -2722,9 +2719,9 @@ static const struct command_registration cortex_a8_command_handlers[] = { .chain = armv7a_command_handlers, }, { - .name = "cortex_a8", + .name = "cortex_a", .mode = COMMAND_ANY, - .help = "Cortex-A8 command group", + .help = "Cortex-A command group", .usage = "", .chain = cortex_a8_exec_command_handlers, }, @@ -2732,27 +2729,24 @@ static const struct command_registration cortex_a8_command_handlers[] = { }; struct target_type cortexa8_target = { - .name = "cortex_a8", + .name = "cortex_a", + .deprecated_name = "cortex_a8", .poll = cortex_a8_poll, .arch_state = armv7a_arch_state, - .target_request_data = NULL, - .halt = cortex_a8_halt, .resume = cortex_a8_resume, .step = cortex_a8_step, .assert_reset = cortex_a8_assert_reset, .deassert_reset = cortex_a8_deassert_reset, - .soft_reset_halt = NULL, /* REVISIT allow exporting VFP3 registers ... */ .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = cortex_a8_read_memory, .write_memory = cortex_a8_write_memory, - .bulk_write_memory = cortex_a8_bulk_write_memory, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, @@ -2776,3 +2770,75 @@ struct target_type cortexa8_target = { .mmu = cortex_a8_mmu, .virt2phys = cortex_a8_virt2phys, }; + +static const struct command_registration cortex_r4_exec_command_handlers[] = { + { + .name = "cache_info", + .handler = cortex_a8_handle_cache_info_command, + .mode = COMMAND_EXEC, + .help = "display information about target caches", + .usage = "", + }, + { + .name = "dbginit", + .handler = cortex_a8_handle_dbginit_command, + .mode = COMMAND_EXEC, + .help = "Initialize core debug", + .usage = "", + }, + + COMMAND_REGISTRATION_DONE +}; +static const struct command_registration cortex_r4_command_handlers[] = { + { + .chain = arm_command_handlers, + }, + { + .chain = armv7a_command_handlers, + }, + { + .name = "cortex_r4", + .mode = COMMAND_ANY, + .help = "Cortex-R4 command group", + .usage = "", + .chain = cortex_r4_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +struct target_type cortexr4_target = { + .name = "cortex_r4", + + .poll = cortex_a8_poll, + .arch_state = armv7a_arch_state, + + .halt = cortex_a8_halt, + .resume = cortex_a8_resume, + .step = cortex_a8_step, + + .assert_reset = cortex_a8_assert_reset, + .deassert_reset = cortex_a8_deassert_reset, + + /* REVISIT allow exporting VFP3 registers ... */ + .get_gdb_reg_list = arm_get_gdb_reg_list, + + .read_memory = cortex_a8_read_memory, + .write_memory = cortex_a8_write_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, + + .run_algorithm = armv4_5_run_algorithm, + + .add_breakpoint = cortex_a8_add_breakpoint, + .add_context_breakpoint = cortex_a8_add_context_breakpoint, + .add_hybrid_breakpoint = cortex_a8_add_hybrid_breakpoint, + .remove_breakpoint = cortex_a8_remove_breakpoint, + .add_watchpoint = NULL, + .remove_watchpoint = NULL, + + .commands = cortex_r4_command_handlers, + .target_create = cortex_r4_target_create, + .init_target = cortex_a8_init_target, + .examine = cortex_a8_examine, +};