- added checksum_memory and blank_check_memory for xscale
[fw/openocd] / src / target / feroceon.c
index e1a4e955d50676b8f6c887ff6a44761b3d822db2..a912dbd365c2171320ce787a2abb77151ca388d2 100644 (file)
@@ -1,26 +1,26 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Marvell Semiconductors, Inc.                    *
+ *   Written by Nicolas Pitre <nico@marvell.com>                           *
+ *                                                                         *
+ *   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     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
 /*
  * Marvell Feroceon (88F5182, 88F5281) support.
  *
- * Copyright (C) 2008 Marvell Semiconductors, Inc.
- * Written by Nicolas Pitre <nico@marvell.com>
- *
- * 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 
- * (at your option) any later version. 
- *  
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- * GNU General Public License for more details. 
- *
- * 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.
- */
-
-/*
  * The Feroceon core mimics the ARM926 ICE interface with the following
  * differences:
  *
@@ -54,7 +54,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-
+int feroceon_examine(struct command_context_s *cmd_ctx, struct target_s *target);
 int feroceon_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
 int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
 int feroceon_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
@@ -76,7 +76,6 @@ target_type_t feroceon_target =
        .assert_reset = arm7_9_assert_reset,
        .deassert_reset = arm7_9_deassert_reset,
        .soft_reset_halt = arm926ejs_soft_reset_halt,
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,
        
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
@@ -84,6 +83,7 @@ target_type_t feroceon_target =
        .write_memory = arm926ejs_write_memory,
        .bulk_write_memory = feroceon_bulk_write_memory,
        .checksum_memory = arm7_9_checksum_memory,
+       .blank_check_memory = arm7_9_blank_check_memory,
        
        .run_algorithm = armv4_5_run_algorithm,
 
@@ -95,6 +95,7 @@ target_type_t feroceon_target =
        .register_commands = arm926ejs_register_commands,
        .target_command = feroceon_target_command,
        .init_target = feroceon_init_target,
+       .examine = feroceon_examine,
        .quit = feroceon_quit
 };
 
@@ -229,7 +230,7 @@ void feroceon_write_xpsr(target_t *target, u32 xpsr, int spsr)
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
        arm_jtag_t *jtag_info = &arm7_9->jtag_info;
                
-       DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
+       LOG_DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
 
        arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
        arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
@@ -270,7 +271,7 @@ void feroceon_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
        arm_jtag_t *jtag_info = &arm7_9->jtag_info;
 
-       DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
+       LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
 
        arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
        arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
@@ -320,7 +321,7 @@ void feroceon_branch_resume(target_t *target)
 
 void feroceon_branch_resume_thumb(target_t *target)
 {
-       DEBUG("-");
+       LOG_DEBUG("-");
        
        armv4_5_common_t *armv4_5 = target->arch_info;
        arm7_9_common_t *arm7_9 = armv4_5->arch_info;
@@ -362,6 +363,47 @@ void feroceon_branch_resume_thumb(target_t *target)
        arm_jtag_set_instr(jtag_info, 0xf, NULL);
 }
 
+int feroceon_read_cp15(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 *value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       int err;
+
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+       err = arm7_9_execute_sys_speed(target);
+       if (err != ERROR_OK)
+               return err;
+
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, value, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       return jtag_execute_queue();
+}
+
+int feroceon_write_cp15(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, value, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+       return arm7_9_execute_sys_speed(target);
+}
+
 void feroceon_enable_single_step(target_t *target)
 {
        armv4_5_common_t *armv4_5 = target->arch_info;
@@ -374,7 +416,7 @@ void feroceon_enable_single_step(target_t *target)
                u32 current_pc, current_opcode;
                current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
                target_read_u32(target, current_pc, &current_opcode);
-               ERROR("BUG: couldn't calculate PC of next instruction, "
+               LOG_ERROR("BUG: couldn't calculate PC of next instruction, "
                      "current opcode is 0x%8.8x", current_opcode);
                next_pc = current_pc;
        }
@@ -400,7 +442,6 @@ void feroceon_disable_single_step(target_t *target)
        embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
 }
 
-
 int feroceon_examine_debug_reason(target_t *target)
 {
        /* the MOE is not implemented */
@@ -461,7 +502,7 @@ int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buf
                /* make sure we have a working area */
                if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK)
                {
-                       INFO("no working area available, falling back to memory writes");
+                       LOG_INFO("no working area available, falling back to memory writes");
                        return target->type->write_memory(target, address, 4, count, buffer);
                }
 
@@ -507,9 +548,9 @@ int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buf
                buffer += 4;
        }
 
-       target->type->halt(target);
+       target_halt(target);
        while (target->state != TARGET_HALTED)
-               target->type->poll(target);
+               target_poll(target);
 
        /* restore target state */
        for (i = 0; i <= 5; i++)
@@ -528,32 +569,7 @@ int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buf
 
 int feroceon_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
 {
-       armv4_5_common_t *armv4_5;
-       arm7_9_common_t *arm7_9;
-
        arm9tdmi_init_target(cmd_ctx, target);
-
-       armv4_5 = target->arch_info;
-       arm7_9 = armv4_5->arch_info;
-
-       /* the COMMS_CTRL bits are all contiguous */
-       if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
-               ERROR("unexpected Feroceon EICE version signature");
-
-       arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6; 
-       arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5; 
-       arm7_9->has_monitor_mode = 1;
-
-       /* vector catch reg is not initialized on reset */
-       embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
-
-       /* clear monitor mode, enable comparators */
-       embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
-       jtag_execute_queue(); 
-       buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
-       buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0); 
-       embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
-
        return ERROR_OK;
 }
 
@@ -569,10 +585,11 @@ int feroceon_target_command(struct command_context_s *cmd_ctx, char *cmd, char *
        armv4_5_common_t *armv4_5;
        arm7_9_common_t *arm7_9;
        arm926ejs_common_t *arm926ejs = malloc(sizeof(arm926ejs_common_t));
+       memset(arm926ejs, 0, sizeof(*arm926ejs));
        
        if (argc < 4)
        {
-               ERROR("'target arm926ejs' requires at least one additional argument");
+               LOG_ERROR("'target arm926ejs' requires at least one additional argument");
                exit(-1);
        }
        
@@ -581,7 +598,7 @@ int feroceon_target_command(struct command_context_s *cmd_ctx, char *cmd, char *
        if (argc >= 5)
                variant = args[4];
        
-       DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
+       LOG_DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
        
        arm926ejs_init_arch_info(target, arm926ejs, chain_pos, variant);
 
@@ -606,6 +623,10 @@ int feroceon_target_command(struct command_context_s *cmd_ctx, char *cmd, char *
        /* MOE is not implemented */
        arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
 
+       /* the standard ARM926 methods don't always work (don't ask...) */
+       arm926ejs->read_cp15 = feroceon_read_cp15;
+       arm926ejs->write_cp15 = feroceon_write_cp15;
+
        /* asserting DBGRQ won't win over the undef exception */
        arm7_9->use_dbgrq = 0;
 
@@ -615,3 +636,38 @@ int feroceon_target_command(struct command_context_s *cmd_ctx, char *cmd, char *
 
        return ERROR_OK;
 }
+
+
+int feroceon_examine(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       int retval;
+
+       retval = arm9tdmi_examine(cmd_ctx, target);
+       if (retval!=ERROR_OK)
+               return retval;
+                       
+       armv4_5 = target->arch_info;
+       arm7_9 = armv4_5->arch_info;
+       
+       /* the COMMS_CTRL bits are all contiguous */
+       if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
+               LOG_ERROR("unexpected Feroceon EICE version signature");
+       
+       arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6; 
+       arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5; 
+       arm7_9->has_monitor_mode = 1;
+       
+       /* vector catch reg is not initialized on reset */
+       embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
+       
+       /* clear monitor mode, enable comparators */
+       embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
+       jtag_execute_queue(); 
+       buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
+       buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0); 
+       embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
+       
+       return ERROR_OK;
+}