--- /dev/null
+/***************************************************************************
+ * 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, uint32_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, uint32_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, int read)
+{
+ 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, !!read);
+ 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, uint32_t address,
+ uint32_t size, uint32_t count, uint8_t *buffer)
+{
+ LOG_DEBUG("Reading memory at physical address 0x%" PRIx32
+ "; 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, 1);
+ 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, uint32_t address,
+ uint32_t size, uint32_t count,
+ const uint8_t *buffer)
+{
+ LOG_DEBUG("Writing memory at physical address 0x%" PRIx32
+ "; 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, 0);
+ 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,
+};