244 lines
6.1 KiB
C
244 lines
6.1 KiB
C
/***************************************************************************
|
|
* 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 <jtag/jtag.h>
|
|
|
|
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,
|
|
};
|