+ /* get pointers to arch-specific information */
+ armv4_5_common_t *armv4_5 = target->arch_info;
+
+ if ((num <= ARM_CPSR))
+ {
+ /* read a normal core register */
+ retval = cortex_a8_dap_read_coreregister_u32(target, value, num);
+
+ if (retval != ERROR_OK)
+ {
+ LOG_ERROR("JTAG failure %i", retval);
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ LOG_DEBUG("load from core reg %i value 0x%" PRIx32, num, *value);
+ }
+ else
+ {
+ return ERROR_INVALID_ARGUMENTS;
+ }
+
+ /* Register other than r0 - r14 uses r0 for access */
+ if (num > 14)
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
+ armv4_5->core_mode, 0).dirty =
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
+ armv4_5->core_mode, 0).valid;
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
+ armv4_5->core_mode, 15).dirty =
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
+ armv4_5->core_mode, 15).valid;
+
+ return ERROR_OK;
+}
+
+int cortex_a8_store_core_reg_u32(struct target_s *target, int num,
+ armv4_5_mode_t mode, uint32_t value)
+{
+ int retval;
+// uint32_t reg;
+
+ /* get pointers to arch-specific information */
+ armv4_5_common_t *armv4_5 = target->arch_info;
+
+#ifdef ARMV7_GDB_HACKS
+ /* If the LR register is being modified, make sure it will put us
+ * in "thumb" mode, or an INVSTATE exception will occur. This is a
+ * hack to deal with the fact that gdb will sometimes "forge"
+ * return addresses, and doesn't set the LSB correctly (i.e., when
+ * printing expressions containing function calls, it sets LR=0.) */
+
+ if (num == 14)
+ value |= 0x01;
+#endif
+
+ if ((num <= ARM_CPSR))
+ {
+ retval = cortex_a8_dap_write_coreregister_u32(target, value, num);
+ if (retval != ERROR_OK)
+ {
+ LOG_ERROR("JTAG failure %i", retval);
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
+ armv4_5->core_mode, num).dirty =
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
+ armv4_5->core_mode, num).valid;
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ LOG_DEBUG("write core reg %i value 0x%" PRIx32, num, value);
+ }
+ else
+ {
+ return ERROR_INVALID_ARGUMENTS;
+ }
+
+ return ERROR_OK;
+}
+
+
+int cortex_a8_read_core_reg(struct target_s *target, int num,
+ enum armv4_5_mode mode)
+{
+ uint32_t value;
+ int retval;
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ cortex_a8_dap_read_coreregister_u32(target, &value, num);
+
+ if ((retval = jtag_execute_queue()) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;
+ buf_set_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
+ mode, num).value, 0, 32, value);
+
+ return ERROR_OK;
+}
+
+int cortex_a8_write_core_reg(struct target_s *target, int num,
+ enum armv4_5_mode mode, uint32_t value)
+{
+ int retval;
+ armv4_5_common_t *armv4_5 = target->arch_info;
+
+ cortex_a8_dap_write_coreregister_u32(target, value, num);
+ if ((retval = jtag_execute_queue()) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
+ ARMV7A_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;
+
+ return ERROR_OK;
+}
+
+
+/*
+ * Cortex-A8 Breakpoint and watchpoint fuctions
+ */
+
+/* Setup hardware Breakpoint Register Pair */
+int cortex_a8_set_breakpoint(struct target_s *target,
+ breakpoint_t *breakpoint, uint8_t matchmode)
+{
+ int retval;
+ int brp_i=0;
+ uint32_t control;
+ uint8_t byte_addr_select = 0x0F;
+
+
+ /* get pointers to arch-specific information */
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ armv7a_common_t *armv7a = armv4_5->arch_info;
+ cortex_a8_common_t *cortex_a8 = armv7a->arch_info;
+ cortex_a8_brp_t * brp_list = cortex_a8->brp_list;
+
+ if (breakpoint->set)
+ {
+ LOG_WARNING("breakpoint already set");
+ return ERROR_OK;
+ }
+
+ if (breakpoint->type == BKPT_HARD)
+ {
+ while (brp_list[brp_i].used && (brp_i < cortex_a8->brp_num))
+ brp_i++ ;
+ if (brp_i >= cortex_a8->brp_num)
+ {
+ LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
+ exit(-1);
+ }
+ breakpoint->set = brp_i + 1;
+ if (breakpoint->length == 2)
+ {
+ byte_addr_select = (3 << (breakpoint->address & 0x02));
+ }
+ control = ((matchmode & 0x7) << 20)
+ | (byte_addr_select << 5)
+ | (3 << 1) | 1;
+ brp_list[brp_i].used = 1;
+ brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
+ brp_list[brp_i].control = control;
+ target_write_u32(target, OMAP3530_DEBUG_BASE
+ + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+ brp_list[brp_i].value);
+ target_write_u32(target, OMAP3530_DEBUG_BASE
+ + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+ brp_list[brp_i].control);
+ LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
+ brp_list[brp_i].control,
+ brp_list[brp_i].value);
+ }
+ else if (breakpoint->type == BKPT_SOFT)
+ {
+ uint8_t code[4];
+ if (breakpoint->length == 2)
+ {
+ buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
+ }
+ else
+ {
+ buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11));
+ }
+ retval = target->type->read_memory(target,
+ breakpoint->address & 0xFFFFFFFE,
+ breakpoint->length, 1,
+ breakpoint->orig_instr);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = target->type->write_memory(target,
+ breakpoint->address & 0xFFFFFFFE,
+ breakpoint->length, 1, code);
+ if (retval != ERROR_OK)
+ return retval;
+ breakpoint->set = 0x11; /* Any nice value but 0 */
+ }
+
+ return ERROR_OK;
+}
+
+int cortex_a8_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+ int retval;
+ /* get pointers to arch-specific information */
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ armv7a_common_t *armv7a = armv4_5->arch_info;
+ cortex_a8_common_t *cortex_a8 = armv7a->arch_info;
+ cortex_a8_brp_t * brp_list = cortex_a8->brp_list;
+
+ if (!breakpoint->set)
+ {
+ LOG_WARNING("breakpoint not set");
+ return ERROR_OK;
+ }
+
+ if (breakpoint->type == BKPT_HARD)
+ {
+ int brp_i = breakpoint->set - 1;
+ if ((brp_i < 0) || (brp_i >= cortex_a8->brp_num))
+ {
+ LOG_DEBUG("Invalid BRP number in breakpoint");
+ return ERROR_OK;
+ }
+ LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
+ brp_list[brp_i].control, brp_list[brp_i].value);
+ brp_list[brp_i].used = 0;
+ brp_list[brp_i].value = 0;
+ brp_list[brp_i].control = 0;
+ target_write_u32(target, OMAP3530_DEBUG_BASE
+ + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+ brp_list[brp_i].control);
+ target_write_u32(target, OMAP3530_DEBUG_BASE
+ + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+ brp_list[brp_i].value);
+ }
+ else
+ {
+ /* restore original instruction (kept in target endianness) */
+ if (breakpoint->length == 4)
+ {
+ retval = target->type->write_memory(target,
+ breakpoint->address & 0xFFFFFFFE,
+ 4, 1, breakpoint->orig_instr);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ else
+ {
+ retval = target->type->write_memory(target,
+ breakpoint->address & 0xFFFFFFFE,
+ 2, 1, breakpoint->orig_instr);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ }
+ breakpoint->set = 0;
+
+ return ERROR_OK;
+}
+
+int cortex_a8_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+ /* get pointers to arch-specific information */
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ armv7a_common_t *armv7a = armv4_5->arch_info;
+ cortex_a8_common_t *cortex_a8 = armv7a->arch_info;
+
+ if ((breakpoint->type == BKPT_HARD) && (cortex_a8->brp_num_available < 1))
+ {
+ LOG_INFO("no hardware breakpoint available");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
+ if (breakpoint->type == BKPT_HARD)
+ cortex_a8->brp_num_available--;
+ cortex_a8_set_breakpoint(target, breakpoint, 0x00); /* Exact match */
+
+ return ERROR_OK;
+}
+
+int cortex_a8_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+ /* get pointers to arch-specific information */
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ armv7a_common_t *armv7a = armv4_5->arch_info;
+ cortex_a8_common_t *cortex_a8 = armv7a->arch_info;
+
+#if 0
+/* It is perfectly possible to remove brakpoints while the taget is running */
+ if (target->state != TARGET_HALTED)
+ {
+ LOG_WARNING("target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+#endif
+
+ if (breakpoint->set)
+ {
+ cortex_a8_unset_breakpoint(target, breakpoint);
+ if (breakpoint->type == BKPT_HARD)
+ cortex_a8->brp_num_available++ ;
+ }
+
+
+ return ERROR_OK;
+}
+
+
+
+/*
+ * Cortex-A8 Reset fuctions
+ */
+
+
+/*
+ * Cortex-A8 Memory access
+ *
+ * This is same Cortex M3 but we must also use the correct
+ * ap number for every access.
+ */
+
+int cortex_a8_read_memory(struct target_s *target, uint32_t address,
+ uint32_t size, uint32_t count, uint8_t *buffer)
+{
+ /* get pointers to arch-specific information */
+ armv4_5_common_t *armv4_5 = target->arch_info;
+ armv7a_common_t *armv7a = armv4_5->arch_info;
+ swjdp_common_t *swjdp = &armv7a->swjdp_info;
+
+ int retval = ERROR_OK;