summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/target/xscale.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/target/xscale.c b/src/target/xscale.c
index 37f9b641..ec49a8c6 100644
--- a/src/target/xscale.c
+++ b/src/target/xscale.c
@@ -3579,6 +3579,96 @@ int xscale_handle_analyze_trace_buffer_command(struct command_context_s *cmd_ctx
return ERROR_OK;
}
+int xscale_handle_cp15(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{
+ target_t *target = get_current_target(cmd_ctx);
+ armv4_5_common_t *armv4_5;
+ xscale_common_t *xscale;
+
+ if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+ {
+ command_print(cmd_ctx, "target isn't an XScale target");
+ return ERROR_OK;
+ }
+
+ if (target->state != TARGET_HALTED)
+ {
+ command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+ return ERROR_OK;
+ }
+ u32 reg_no = 0;
+ reg_t *reg = NULL;
+ if(argc > 0)
+ {
+ reg_no = strtoul(args[0], NULL, 0);
+ /*translate from xscale cp15 register no to openocd register*/
+ switch(reg_no)
+ {
+ case 0:
+ reg_no = XSCALE_MAINID;
+ break;
+ case 1:
+ reg_no = XSCALE_CTRL;
+ break;
+ case 2:
+ reg_no = XSCALE_TTB;
+ break;
+ case 3:
+ reg_no = XSCALE_DAC;
+ break;
+ case 5:
+ reg_no = XSCALE_FSR;
+ break;
+ case 6:
+ reg_no = XSCALE_FAR;
+ break;
+ case 13:
+ reg_no = XSCALE_PID;
+ break;
+ case 15:
+ reg_no = XSCALE_CPACCESS;
+ break;
+ default:
+ command_print(cmd_ctx, "invalid register number");
+ return ERROR_INVALID_ARGUMENTS;
+ }
+ reg = &xscale->reg_cache->reg_list[reg_no];
+
+ }
+ if(argc == 1)
+ {
+ u32 value;
+
+ /* read cp15 control register */
+ xscale_get_reg(reg);
+ value = buf_get_u32(reg->value, 0, 32);
+ command_print(cmd_ctx, "%s (/%i): 0x%x", reg->name, reg->size, value);
+ }
+ else if(argc == 2)
+ {
+
+ u32 value = strtoul(args[1], NULL, 0);
+
+ /* send CP write request (command 0x41) */
+ xscale_send_u32(target, 0x41);
+
+ /* send CP register number */
+ xscale_send_u32(target, reg_no);
+
+ /* send CP register value */
+ xscale_send_u32(target, value);
+
+ /* execute cpwait to ensure outstanding operations complete */
+ xscale_send_u32(target, 0x53);
+ }
+ else
+ {
+ command_print(cmd_ctx, "usage: cp15 [register]<, [value]>");
+ }
+
+ return ERROR_OK;
+}
+
int xscale_register_commands(struct command_context_s *cmd_ctx)
{
command_t *xscale_cmd;
@@ -3603,6 +3693,8 @@ int xscale_register_commands(struct command_context_s *cmd_ctx)
register_command(cmd_ctx, xscale_cmd, "trace_image", xscale_handle_trace_image_command,
COMMAND_EXEC, "load image from <file> [base address]");
+ register_command(cmd_ctx, xscale_cmd, "cp15", xscale_handle_cp15, COMMAND_EXEC, "access coproc 15 <register> [value]");
+
armv4_5_register_commands(cmd_ctx);
return ERROR_OK;