X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farc.c;h=6cf0ec7af7376b1dae36a57ae3163a381d41c8de;hp=cec6441a563ec332194726d135242a9ab9265092;hb=HEAD;hpb=0d3a67b23f7848584a36712741252a73b03ae3a5 diff --git a/src/target/arc.c b/src/target/arc.c index cec6441a56..72e4d918de 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -1,11 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + /*************************************************************************** * Copyright (C) 2013-2015,2019-2020 Synopsys, Inc. * * Frank Dols * * Mischa Jonker * * Anton Kolesov * * Evgeniy Didin * - * * - * SPDX-License-Identifier: GPL-2.0-or-later * ***************************************************************************/ @@ -50,6 +50,13 @@ static int arc_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); +static int arc_enable_watchpoints(struct target *target); +static int arc_enable_breakpoints(struct target *target); +static int arc_unset_breakpoint(struct target *target, + struct breakpoint *breakpoint); +static int arc_set_breakpoint(struct target *target, + struct breakpoint *breakpoint); +static int arc_single_step_core(struct target *target); void arc_reg_data_type_add(struct target *target, struct arc_reg_data_type *data_type) @@ -93,7 +100,7 @@ struct reg *arc_reg_get_by_name(struct reg_cache *first, * * @param target Target for which to reset caches states. */ -int arc_reset_caches_states(struct target *target) +static int arc_reset_caches_states(struct target *target) { struct arc_common *arc = target_to_arc(target); @@ -227,7 +234,7 @@ static int arc_get_register(struct reg *reg) if (desc->is_core) { /* Accessing to R61/R62 registers causes Jtag hang */ - if (desc->arch_num == CORE_R61_NUM || desc->arch_num == CORE_R62_NUM) { + if (desc->arch_num == ARC_R61 || desc->arch_num == ARC_R62) { LOG_ERROR("It is forbidden to read core registers 61 and 62."); return ERROR_FAIL; } @@ -267,8 +274,8 @@ static int arc_set_register(struct reg *reg, uint8_t *buf) return ERROR_TARGET_NOT_HALTED; /* Accessing to R61/R62 registers causes Jtag hang */ - if (desc->is_core && (desc->arch_num == CORE_R61_NUM || - desc->arch_num == CORE_R62_NUM)) { + if (desc->is_core && (desc->arch_num == ARC_R61 || + desc->arch_num == ARC_R62)) { LOG_ERROR("It is forbidden to write core registers 61 and 62."); return ERROR_FAIL; } @@ -283,7 +290,7 @@ static int arc_set_register(struct reg *reg, uint8_t *buf) return ERROR_OK; } -const struct reg_arch_type arc_reg_type = { +static const struct reg_arch_type arc_reg_type = { .get = arc_get_register, .set = arc_set_register, }; @@ -305,7 +312,7 @@ static int arc_init_reg(struct target *target, struct reg *reg, /* Initialize struct reg */ reg->name = reg_desc->name; reg->size = 32; /* All register in ARC are 32-bit */ - reg->value = ®_desc->reg_value; + reg->value = reg_desc->reg_value; reg->type = &arc_reg_type; reg->arch_info = reg_desc; reg->caller_save = true; /* @todo should be configurable. */ @@ -748,6 +755,29 @@ static int arc_examine(struct target *target) return ERROR_OK; } +static int arc_exit_debug(struct target *target) +{ + uint32_t value; + struct arc_common *arc = target_to_arc(target); + + /* Do read-modify-write sequence, or DEBUG.UB will be reset unintentionally. */ + CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, &value)); + value |= SET_CORE_FORCE_HALT; /* set the HALT bit */ + CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, value)); + alive_sleep(1); + + target->state = TARGET_HALTED; + CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); + + if (debug_level >= LOG_LVL_DEBUG) { + LOG_DEBUG("core stopped (halted) debug-reg: 0x%08" PRIx32, value); + CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, &value)); + LOG_DEBUG("core STATUS32: 0x%08" PRIx32, value); + } + + return ERROR_OK; +} + static int arc_halt(struct target *target) { uint32_t value, irq_state; @@ -846,27 +876,23 @@ static int arc_save_context(struct target *target) memset(aux_addrs, 0xff, aux_regs_size); for (i = 0; i < MIN(arc->num_core_regs, regs_to_scan); i++) { - struct reg *reg = &(reg_list[i]); + struct reg *reg = reg_list + i; struct arc_reg_desc *arc_reg = reg->arch_info; - if (!reg->valid && reg->exist) { - core_addrs[core_cnt] = arc_reg->arch_num; - core_cnt += 1; - } + if (!reg->valid && reg->exist) + core_addrs[core_cnt++] = arc_reg->arch_num; } for (i = arc->num_core_regs; i < regs_to_scan; i++) { - struct reg *reg = &(reg_list[i]); + struct reg *reg = reg_list + i; struct arc_reg_desc *arc_reg = reg->arch_info; - if (!reg->valid && reg->exist) { - aux_addrs[aux_cnt] = arc_reg->arch_num; - aux_cnt += 1; - } + if (!reg->valid && reg->exist) + aux_addrs[aux_cnt++] = arc_reg->arch_num; } /* Read data from target. */ if (core_cnt > 0) { retval = arc_jtag_read_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values); - if (ERROR_OK != retval) { + if (retval != ERROR_OK) { LOG_ERROR("Attempt to read core registers failed."); retval = ERROR_FAIL; goto exit; @@ -874,7 +900,7 @@ static int arc_save_context(struct target *target) } if (aux_cnt > 0) { retval = arc_jtag_read_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values); - if (ERROR_OK != retval) { + if (retval != ERROR_OK) { LOG_ERROR("Attempt to read aux registers failed."); retval = ERROR_FAIL; goto exit; @@ -884,30 +910,30 @@ static int arc_save_context(struct target *target) /* Parse core regs */ core_cnt = 0; for (i = 0; i < MIN(arc->num_core_regs, regs_to_scan); i++) { - struct reg *reg = &(reg_list[i]); + struct reg *reg = reg_list + i; struct arc_reg_desc *arc_reg = reg->arch_info; if (!reg->valid && reg->exist) { target_buffer_set_u32(target, reg->value, core_values[core_cnt]); - core_cnt += 1; reg->valid = true; reg->dirty = false; LOG_DEBUG("Get core register regnum=%u, name=%s, value=0x%08" PRIx32, i, arc_reg->name, core_values[core_cnt]); + core_cnt++; } } /* Parse aux regs */ aux_cnt = 0; for (i = arc->num_core_regs; i < regs_to_scan; i++) { - struct reg *reg = &(reg_list[i]); + struct reg *reg = reg_list + i; struct arc_reg_desc *arc_reg = reg->arch_info; if (!reg->valid && reg->exist) { target_buffer_set_u32(target, reg->value, aux_values[aux_cnt]); - aux_cnt += 1; reg->valid = true; reg->dirty = false; LOG_DEBUG("Get aux register regnum=%u, name=%s, value=0x%08" PRIx32, i, arc_reg->name, aux_values[aux_cnt]); + aux_cnt++; } } @@ -924,14 +950,15 @@ exit: * Finds an actionpoint that triggered last actionpoint event, as specified by * DEBUG.ASR. * + * @param target * @param actionpoint Pointer to be set to last active actionpoint. Pointer * will be set to NULL if DEBUG.AH is 0. */ static int get_current_actionpoint(struct target *target, struct arc_actionpoint **actionpoint) { - assert(target != NULL); - assert(actionpoint != NULL); + assert(target); + assert(actionpoint); uint32_t debug_ah; /* Check if actionpoint caused halt */ @@ -980,7 +1007,7 @@ static int arc_examine_debug_reason(struct target *target) struct arc_actionpoint *actionpoint = NULL; CHECK_RETVAL(get_current_actionpoint(target, &actionpoint)); - if (actionpoint != NULL) { + if (actionpoint) { if (!actionpoint->used) LOG_WARNING("Target halted by an unused actionpoint."); @@ -1196,7 +1223,7 @@ static int arc_restore_context(struct target *target) * Check before write, if aux and core count is greater than 0. */ if (core_cnt > 0) { retval = arc_jtag_write_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values); - if (ERROR_OK != retval) { + if (retval != ERROR_OK) { LOG_ERROR("Attempt to write to core registers failed."); retval = ERROR_FAIL; goto exit; @@ -1205,7 +1232,7 @@ static int arc_restore_context(struct target *target) if (aux_cnt > 0) { retval = arc_jtag_write_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values); - if (ERROR_OK != retval) { + if (retval != ERROR_OK) { LOG_ERROR("Attempt to write to aux registers failed."); retval = ERROR_FAIL; goto exit; @@ -1252,7 +1279,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, uint32_t value; struct reg *pc = &arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache]; - LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints(not supported yet):%i," + LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints:%i," " debug_execution:%i", current, address, handle_breakpoints, debug_execution); /* We need to reset ARC cache variables so caches @@ -1261,15 +1288,22 @@ static int arc_resume(struct target *target, int current, target_addr_t address, CHECK_RETVAL(arc_reset_caches_states(target)); if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); + LOG_TARGET_ERROR(target, "not halted"); return ERROR_TARGET_NOT_HALTED; } + if (!debug_execution) { + /* (gdb) continue = execute until we hit break/watch-point */ + target_free_all_working_areas(target); + CHECK_RETVAL(arc_enable_breakpoints(target)); + CHECK_RETVAL(arc_enable_watchpoints(target)); + } + /* current = 1: continue on current PC, otherwise continue at
*/ if (!current) { target_buffer_set_u32(target, pc->value, address); - pc->dirty = 1; - pc->valid = 1; + pc->dirty = true; + pc->valid = true; LOG_DEBUG("Changing the value of current PC to 0x%08" TARGET_PRIxADDR, address); } @@ -1284,12 +1318,25 @@ static int arc_resume(struct target *target, int current, target_addr_t address, resume_pc, pc->dirty, pc->valid); /* check if GDB tells to set our PC where to continue from */ - if ((pc->valid == 1) && (resume_pc == target_buffer_get_u32(target, pc->value))) { + if (pc->valid && resume_pc == target_buffer_get_u32(target, pc->value)) { value = target_buffer_get_u32(target, pc->value); LOG_DEBUG("resume Core (when start-core) with PC @:0x%08" PRIx32, value); CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_PC_REG, value)); } + /* the front-end may request us not to handle breakpoints here */ + if (handle_breakpoints) { + /* Single step past breakpoint at current address */ + struct breakpoint *breakpoint = breakpoint_find(target, resume_pc); + if (breakpoint) { + LOG_DEBUG("skipping past breakpoint at 0x%08" TARGET_PRIxADDR, + breakpoint->address); + CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); + CHECK_RETVAL(arc_single_step_core(target)); + CHECK_RETVAL(arc_set_breakpoint(target, breakpoint)); + } + } + /* Restore IRQ state if not in debug_execution*/ if (!debug_execution) CHECK_RETVAL(arc_enable_interrupts(target, arc->irq_state)); @@ -1400,7 +1447,7 @@ static int arc_target_create(struct target *target, Jim_Interp *interp) * little endian, so different type of conversion should be done. * Middle endian: instruction "aabbccdd", stored as "bbaaddcc" */ -int arc_write_instruction_u32(struct target *target, uint32_t address, +static int arc_write_instruction_u32(struct target *target, uint32_t address, uint32_t instr) { uint8_t value_buf[4]; @@ -1427,7 +1474,7 @@ int arc_write_instruction_u32(struct target *target, uint32_t address, * case of little endian ARC instructions are in middle endian format, so * different type of conversion should be done. */ -int arc_read_instruction_u32(struct target *target, uint32_t address, +static int arc_read_instruction_u32(struct target *target, uint32_t address, uint32_t *value) { uint8_t value_buf[4]; @@ -1466,7 +1513,7 @@ static int arc_configure_actionpoint(struct target *target, uint32_t ap_num, if (control_tt != AP_AC_TT_DISABLE) { if (arc->actionpoints_num_avail < 1) { - LOG_ERROR("No free actionpoints, maximim amount is %u", + LOG_ERROR("No free actionpoints, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1499,7 +1546,7 @@ static int arc_configure_actionpoint(struct target *target, uint32_t ap_num, static int arc_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } @@ -1541,7 +1588,7 @@ static int arc_set_breakpoint(struct target *target, return ERROR_COMMAND_ARGUMENT_INVALID; } - breakpoint->set = 64; /* Any nice value but 0 */ + breakpoint->is_set = true; } else if (breakpoint->type == BKPT_HARD) { struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; @@ -1562,7 +1609,7 @@ static int arc_set_breakpoint(struct target *target, breakpoint->address, AP_AC_TT_READWRITE, AP_AC_AT_INST_ADDR); if (retval == ERROR_OK) { - breakpoint->set = bp_num + 1; + breakpoint_hw_set(breakpoint, bp_num); ap_list[bp_num].used = 1; ap_list[bp_num].bp_value = breakpoint->address; ap_list[bp_num].type = ARC_AP_BREAKPOINT; @@ -1576,9 +1623,6 @@ static int arc_set_breakpoint(struct target *target, return ERROR_FAIL; } - /* core instruction cache is now invalid. */ - CHECK_RETVAL(arc_cache_invalidate(target)); - return ERROR_OK; } @@ -1587,7 +1631,7 @@ static int arc_unset_breakpoint(struct target *target, { int retval = ERROR_OK; - if (!breakpoint->set) { + if (!breakpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } @@ -1632,14 +1676,14 @@ static int arc_unset_breakpoint(struct target *target, LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4"); return ERROR_COMMAND_ARGUMENT_INVALID; } - breakpoint->set = 0; + breakpoint->is_set = false; } else if (breakpoint->type == BKPT_HARD) { struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; - unsigned int bp_num = breakpoint->set - 1; + unsigned int bp_num = breakpoint->number; - if ((breakpoint->set == 0) || (bp_num >= arc->actionpoints_num)) { + if (bp_num >= arc->actionpoints_num) { LOG_DEBUG("Invalid actionpoint ID: %u in breakpoint: %" PRIu32, bp_num, breakpoint->unique_id); return ERROR_OK; @@ -1649,11 +1693,11 @@ static int arc_unset_breakpoint(struct target *target, breakpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_INST_ADDR); if (retval == ERROR_OK) { - breakpoint->set = 0; + breakpoint->is_set = false; ap_list[bp_num].used = 0; ap_list[bp_num].bp_value = 0; - LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %i", + LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %u", breakpoint->unique_id, bp_num); } } else { @@ -1661,12 +1705,22 @@ static int arc_unset_breakpoint(struct target *target, return ERROR_FAIL; } - /* core instruction cache is now invalid. */ - CHECK_RETVAL(arc_cache_invalidate(target)); - return retval; } +static int arc_enable_breakpoints(struct target *target) +{ + struct breakpoint *breakpoint = target->breakpoints; + + /* set any pending breakpoints */ + while (breakpoint) { + if (!breakpoint->is_set) + CHECK_RETVAL(arc_set_breakpoint(target, breakpoint)); + breakpoint = breakpoint->next; + } + + return ERROR_OK; +} static int arc_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { @@ -1674,7 +1728,7 @@ static int arc_add_breakpoint(struct target *target, struct breakpoint *breakpoi return arc_set_breakpoint(target, breakpoint); } else { - LOG_WARNING(" > core was not halted, please try again."); + LOG_TARGET_ERROR(target, "not halted (add breakpoint)"); return ERROR_TARGET_NOT_HALTED; } } @@ -1683,17 +1737,17 @@ static int arc_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state == TARGET_HALTED) { - if (breakpoint->set) + if (breakpoint->is_set) CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); } else { - LOG_WARNING("target not halted"); + LOG_TARGET_ERROR(target, "not halted (remove breakpoint)"); return ERROR_TARGET_NOT_HALTED; } return ERROR_OK; } -void arc_reset_actionpoints(struct target *target) +static void arc_reset_actionpoints(struct target *target) { struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; @@ -1817,7 +1871,7 @@ static int arc_set_watchpoint(struct target *target, struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; - if (watchpoint->set) { + if (watchpoint->is_set) { LOG_WARNING("watchpoint already set"); return ERROR_OK; } @@ -1858,7 +1912,7 @@ static int arc_set_watchpoint(struct target *target, watchpoint->address, enable, AP_AC_AT_MEMORY_ADDR); if (retval == ERROR_OK) { - watchpoint->set = wp_num + 1; + watchpoint_set(watchpoint, wp_num); ap_list[wp_num].used = 1; ap_list[wp_num].bp_value = watchpoint->address; ap_list[wp_num].type = ARC_AP_WATCHPOINT; @@ -1877,13 +1931,13 @@ static int arc_unset_watchpoint(struct target *target, struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; - if (!watchpoint->set) { + if (!watchpoint->is_set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } - unsigned int wp_num = watchpoint->set - 1; - if ((watchpoint->set == 0) || (wp_num >= arc->actionpoints_num)) { + unsigned int wp_num = watchpoint->number; + if (wp_num >= arc->actionpoints_num) { LOG_DEBUG("Invalid actionpoint ID: %u in watchpoint: %" PRIu32, wp_num, watchpoint->unique_id); return ERROR_OK; @@ -1893,7 +1947,7 @@ static int arc_unset_watchpoint(struct target *target, watchpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_MEMORY_ADDR); if (retval == ERROR_OK) { - watchpoint->set = 0; + watchpoint->is_set = false; ap_list[wp_num].used = 0; ap_list[wp_num].bp_value = 0; @@ -1904,11 +1958,25 @@ static int arc_unset_watchpoint(struct target *target, return retval; } +static int arc_enable_watchpoints(struct target *target) +{ + struct watchpoint *watchpoint = target->watchpoints; + + /* set any pending watchpoints */ + while (watchpoint) { + if (!watchpoint->is_set) + CHECK_RETVAL(arc_set_watchpoint(target, watchpoint)); + watchpoint = watchpoint->next; + } + + return ERROR_OK; +} + static int arc_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); + LOG_TARGET_ERROR(target, "not halted"); return ERROR_TARGET_NOT_HALTED; } @@ -1921,11 +1989,11 @@ static int arc_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); + LOG_TARGET_ERROR(target, "not halted"); return ERROR_TARGET_NOT_HALTED; } - if (watchpoint->set) + if (watchpoint->is_set) CHECK_RETVAL(arc_unset_watchpoint(target, watchpoint)); return ERROR_OK; @@ -1939,7 +2007,7 @@ static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_wat struct arc_actionpoint *actionpoint = NULL; CHECK_RETVAL(get_current_actionpoint(target, &actionpoint)); - if (actionpoint != NULL) { + if (actionpoint) { if (!actionpoint->used) LOG_WARNING("Target halted by unused actionpoint."); @@ -1948,12 +2016,12 @@ static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_wat LOG_WARNING("Target halted by breakpoint, but is treated as a watchpoint."); for (struct watchpoint *watchpoint = target->watchpoints; - watchpoint != NULL; + watchpoint; watchpoint = watchpoint->next) { if (actionpoint->bp_value == watchpoint->address) { *hit_watchpoint = watchpoint; - LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %i", - watchpoint->unique_id, watchpoint->set - 1); + LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %u", + watchpoint->unique_id, watchpoint->number); return ERROR_OK; } } @@ -1964,7 +2032,7 @@ static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_wat /* Helper function which switches core to single_step mode by * doing aux r/w operations. */ -int arc_config_step(struct target *target, int enable_step) +static int arc_config_step(struct target *target, int enable_step) { uint32_t value; @@ -2000,7 +2068,23 @@ int arc_config_step(struct target *target, int enable_step) return ERROR_OK; } -int arc_step(struct target *target, int current, target_addr_t address, +static int arc_single_step_core(struct target *target) +{ + CHECK_RETVAL(arc_debug_entry(target)); + + /* disable interrupts while stepping */ + CHECK_RETVAL(arc_enable_interrupts(target, 0)); + + /* configure single step mode */ + CHECK_RETVAL(arc_config_step(target, 1)); + + /* exit debug mode */ + CHECK_RETVAL(arc_exit_debug(target)); + + return ERROR_OK; +} + +static int arc_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { /* get pointers to arch-specific information */ @@ -2009,15 +2093,15 @@ int arc_step(struct target *target, int current, target_addr_t address, struct reg *pc = &(arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache]); if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); + LOG_TARGET_ERROR(target, "not halted"); return ERROR_TARGET_NOT_HALTED; } /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) { buf_set_u32(pc->value, 0, 32, address); - pc->dirty = 1; - pc->valid = 1; + pc->dirty = true; + pc->valid = true; } LOG_DEBUG("Target steps one instruction from PC=0x%" PRIx32, @@ -2164,7 +2248,7 @@ int arc_cache_invalidate(struct target *target) * values directly from memory, bypassing cache, so if there are unflushed * lines debugger will read invalid values, which will cause a lot of troubles. * */ -int arc_dcache_flush(struct target *target) +static int arc_dcache_flush(struct target *target) { uint32_t value, dc_ctrl_value; bool has_to_set_dc_ctrl_im;