/*************************************************************************** * Copyright (C) 2015 by Esben Haabendal * * eha@deif.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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "target.h" #include "target_type.h" #include struct ls1_sap { struct jtag_tap *tap; }; static int ls1_sap_target_create(struct target *target, Jim_Interp *interp) { struct ls1_sap *ls1_sap = calloc(1, sizeof(struct ls1_sap)); ls1_sap->tap = target->tap; target->arch_info = ls1_sap; return ERROR_OK; } static int ls1_sap_init_target(struct command_context *cmd_ctx, struct target *target) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int ls1_sap_arch_state(struct target *target) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int ls1_sap_poll(struct target *target) { if ((target->state == TARGET_UNKNOWN) || (target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING)) target->state = TARGET_HALTED; return ERROR_OK; } static int ls1_sap_halt(struct target *target) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int ls1_sap_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int ls1_sap_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { LOG_DEBUG("%s", __func__); return ERROR_OK; } static int ls1_sap_assert_reset(struct target *target) { target->state = TARGET_RESET; LOG_DEBUG("%s", __func__); return ERROR_OK; } static int ls1_sap_deassert_reset(struct target *target) { target->state = TARGET_RUNNING; LOG_DEBUG("%s", __func__); return ERROR_OK; } static void ls1_sap_set_instr(struct jtag_tap *tap, uint32_t new_instr) { struct scan_field field; if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == new_instr) return; field.num_bits = tap->ir_length; uint8_t *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_instr); field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); free(t); } static void ls1_sap_set_addr_high(struct jtag_tap *tap, uint16_t addr_high) { struct scan_field field; uint8_t buf[2]; ls1_sap_set_instr(tap, 0x21); field.num_bits = 16; field.out_value = buf; buf_set_u32(buf, 0, 16, addr_high); field.in_value = NULL; field.check_value = NULL; field.check_mask = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); } static void ls1_sap_memory_cmd(struct jtag_tap *tap, uint32_t address, int32_t size, bool rnw) { struct scan_field field; uint8_t cmd[8]; ls1_sap_set_instr(tap, 0x24); field.num_bits = 64; field.out_value = cmd; buf_set_u64(cmd, 0, 9, 0); buf_set_u64(cmd, 9, 3, size); buf_set_u64(cmd, 12, 1, rnw); buf_set_u64(cmd, 13, 3, 0); buf_set_u64(cmd, 16, 32, address); buf_set_u64(cmd, 48, 16, 0); field.in_value = NULL; field.check_value = NULL; field.check_mask = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); } static void ls1_sap_memory_read(struct jtag_tap *tap, uint32_t size, uint8_t *value) { struct scan_field field; ls1_sap_set_instr(tap, 0x25); field.num_bits = 8 * size; field.out_value = NULL; field.in_value = value; field.check_value = NULL; field.check_mask = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); } static void ls1_sap_memory_write(struct jtag_tap *tap, uint32_t size, const uint8_t *value) { struct scan_field field; ls1_sap_set_instr(tap, 0x25); field.num_bits = 8 * size; field.out_value = value; field.in_value = NULL; field.check_value = NULL; field.check_mask = NULL; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); } static int ls1_sap_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { LOG_DEBUG("Reading memory at physical address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, size, count); if (count == 0 || buffer == NULL) return ERROR_COMMAND_SYNTAX_ERROR; ls1_sap_set_addr_high(target->tap, 0); while (count--) { ls1_sap_memory_cmd(target->tap, address, size, true); ls1_sap_memory_read(target->tap, size, buffer); address += size; buffer += size; } return jtag_execute_queue(); } static int ls1_sap_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { LOG_DEBUG("Writing memory at physical address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, size, count); if (count == 0 || buffer == NULL) return ERROR_COMMAND_SYNTAX_ERROR; ls1_sap_set_addr_high(target->tap, 0); while (count--) { ls1_sap_memory_cmd(target->tap, address, size, false); ls1_sap_memory_write(target->tap, size, buffer); address += size; buffer += size; } return jtag_execute_queue(); } struct target_type ls1_sap_target = { .name = "ls1_sap", .target_create = ls1_sap_target_create, .init_target = ls1_sap_init_target, .poll = ls1_sap_poll, .arch_state = ls1_sap_arch_state, .halt = ls1_sap_halt, .resume = ls1_sap_resume, .step = ls1_sap_step, .assert_reset = ls1_sap_assert_reset, .deassert_reset = ls1_sap_deassert_reset, .read_memory = ls1_sap_read_memory, .write_memory = ls1_sap_write_memory, };