This is an automated email from Gerrit.

Peter Mamonov ([email protected]) just uploaded a new patch set to Gerrit, 
which you can find at http://openocd.zylin.com/4024

-- gerrit

commit 82cf73c9179933da51f05b68861a219d9f7977dc
Author: Peter Mamonov <[email protected]>
Date:   Mon Jan 18 12:21:14 2016 +0300

    mips64: implement fastdata upload mechanism
    
    Change-Id: I008fa35da50ed3951ed1f2f89d839ad8adf8ee9b
    Signed-off-by: Peter Mamonov <[email protected]>

diff --git a/src/target/mips64.c b/src/target/mips64.c
index dff5868..3b7e1f2 100644
--- a/src/target/mips64.c
+++ b/src/target/mips64.c
@@ -391,6 +391,8 @@ int mips64_init_arch_info(struct target *target, 
mips64_common_t *mips64, struct
        mips64->read_core_reg = mips64_read_core_reg;
        mips64->write_core_reg = mips64_write_core_reg;
 
+       mips64->fast_data_area = NULL;
+
        return ERROR_OK;
 }
 
diff --git a/src/target/mips64.h b/src/target/mips64.h
index 315604d..4777833 100644
--- a/src/target/mips64.h
+++ b/src/target/mips64.h
@@ -55,6 +55,8 @@ typedef struct mips64_common_s {
        struct mips_ejtag ejtag_info;
        uint64_t core_regs[MIPS64NUMCOREREGS];
 
+       struct working_area *fast_data_area;
+
        int bp_scanned;
        int num_inst_bpoints;
        int num_data_bpoints;
@@ -77,6 +79,8 @@ typedef struct mips64_core_reg_s {
 #define MIPS64_OP_BEQ  0x04
 #define MIPS64_OP_BNE  0x05
 #define MIPS64_OP_ADDI 0x08
+#define MIPS64_OP_DADDI        24
+#define MIPS64_OP_DADDIU       25
 #define MIPS64_OP_AND  0x24
 #define MIPS64_OP_LUI  0x0F
 #define MIPS64_OP_LW   0x23
@@ -92,6 +96,7 @@ typedef struct mips64_core_reg_s {
 #define MIPS64_OP_SW   0x2B
 #define MIPS64_OP_SD   0x3F
 #define MIPS64_OP_ORI  0x0D
+#define MIPS64_OP_JR   0x08
 
 #define MIPS64_OP_COP0 0x10
 #define MIPS64_OP_COP1 0x11
@@ -111,6 +116,8 @@ typedef struct mips64_core_reg_s {
 
 #define MIPS64_NOP                     0
 #define MIPS64_ADDI(tar, src, val)     MIPS64_I_INST(MIPS64_OP_ADDI, src, tar, 
val)
+#define MIPS64_DADDI(tar, src, val)    MIPS64_I_INST(MIPS64_OP_DADDI, src, 
tar, val)
+#define MIPS64_DADDIU(tar, src, val)   MIPS64_I_INST(MIPS64_OP_DADDIU, src, 
tar, val)
 #define MIPS64_AND(reg, off, val)      MIPS64_R_INST(0, off, val, reg, 0, 
MIPS64_OP_AND)
 #define MIPS64_B(off)                  MIPS64_BEQ(0, 0, off)
 #define MIPS64_BEQ(src, tar, off)      MIPS64_I_INST(MIPS64_OP_BEQ, src, tar, 
off)
@@ -143,6 +150,7 @@ typedef struct mips64_core_reg_s {
 #define MIPS64_SD(reg, off, base)      MIPS64_I_INST(MIPS64_OP_SD, base, reg, 
off)
 #define MIPS64_CACHE(op, reg, off)     (47 << 26 | (reg) << 21 | (op) << 16 | 
(off))
 #define MIPS64_SYNCI(reg, off)         (1 << 26 | (reg) << 21 | 0x1f << 16 | 
(off))
+#define MIPS64_JR(reg)                 MIPS64_R_INST(0, reg, 0, 0, 0, 
MIPS64_OP_JR)
 
 /* ejtag specific instructions */
 #define MIPS64_DRET                    0x4200001F
diff --git a/src/target/mips64_pracc.c b/src/target/mips64_pracc.c
index 234b423..cf79990 100644
--- a/src/target/mips64_pracc.c
+++ b/src/target/mips64_pracc.c
@@ -928,4 +928,171 @@ int mips64_pracc_read_regs(struct mips_ejtag *ejtag_info, 
uint64_t *regs)
                0, NULL, MIPS64NUMCOREREGS, regs, 1);
 }
 
+/* fastdata upload/download requires an initialized working area
+ * to load the download code; it should not be called otherwise
+ * fetch order from the fastdata area
+ * 1. start addr
+ * 2. end addr
+ * 3. data ...
+ */
+int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, 
+               struct working_area *source,
+               int write_t, uint64_t addr, int count, uint64_t *buf)
+{
+       uint32_t handler_code[] = {
+               /* caution when editing, table is modified below */
+               /* r15 points to the start of this code */
+               MIPS64_SD(8, MIPS64_FASTDATA_HANDLER_SIZE - 8, 15),
+               MIPS64_SD(9, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 2, 15),
+               MIPS64_SD(10, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 3, 15),
+               MIPS64_SD(11, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 4, 15),
+               /* start of fastdata area in t0 */
+               MIPS64_LUI(8, UPPER16(MIPS64_PRACC_FASTDATA_AREA)),
+               MIPS64_ORI(8, 8, LOWER16(MIPS64_PRACC_FASTDATA_AREA)),
+               MIPS64_LD(9, 0, 8),                                             
                /* start addr in t1 */
+               MIPS64_LD(10, 0, 8),                                            
        /* end addr to t2 */
+                                                                               
                                /* loop: */
+               /* 8 */ MIPS64_LD(11, 0, 0),                                    
/* lw t3,[t8 | r9] */
+               /* 9 */ MIPS64_SD(11, 0, 0),                                    
/* sw t3,[r9 | r8] */
+               MIPS64_BNE(10, 9, NEG16(3)),                                    
/* bne $t2,t1,loop */
+               MIPS64_DADDIU(9, 9, 8),                                         
        /* addi t1,t1,4 */
+
+               MIPS64_LD(8, MIPS64_FASTDATA_HANDLER_SIZE - 8, 15),
+               MIPS64_LD(9, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 2, 15),
+               MIPS64_LD(10, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 3, 15),
+               MIPS64_LD(11, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 4, 15),
+
+               MIPS64_LUI(15, UPPER16(MIPS64_PRACC_TEXT)),
+               MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_TEXT)),
+               MIPS64_JR(15),                                                  
        /* jr start */
+               MIPS64_DMFC0(15, 31, 0),                                        
        /* move COP0 DeSave to $15 */
+       };
+
+       uint32_t jmp_code[] = {
+               /* 0 */ MIPS64_LUI(15, 0),              /* addr of working area 
added below */
+               /* 1 */ MIPS64_ORI(15, 15, 0),  /* addr of working area added 
below */
+               MIPS64_JR(15),                                  /* jump to ram 
program */
+               MIPS64_NOP,
+       };
+
+       int retval, i;
+       uint32_t ejtag_ctrl, address32;
+       uint64_t address, val;
+
+       if (source->size < MIPS64_FASTDATA_HANDLER_SIZE)
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+
+       if (write_t) {
+               handler_code[8] = MIPS64_LD(11, 0, 8);  /* load data from probe 
at fastdata area */
+               handler_code[9] = MIPS64_SD(11, 0, 9);  /* store data to RAM @ 
r9 */
+       } else {
+               handler_code[8] = MIPS64_LD(11, 0, 9);  /* load data from RAM @ 
r9 */
+               handler_code[9] = MIPS64_SD(11, 0, 8);  /* store data to probe 
at fastdata area */
+       }
+
+       /* write program into RAM */
+       if (write_t != ejtag_info->fast_access_save) {
+               mips64_pracc_write_mem(ejtag_info, source->address, 4, 
ARRAY_SIZE(handler_code), handler_code);
+               /* save previous operation to speed to any consecutive 
read/writes */
+               ejtag_info->fast_access_save = write_t;
+       }
+
+       LOG_DEBUG("%s using " TARGET_ADDR_FMT " for write handler", __func__, 
source->address);
+       LOG_DEBUG("daddiu: %08x", handler_code[11]);
+
+       jmp_code[0] |= UPPER16(source->address);
+       jmp_code[1] |= LOWER16(source->address);
+#if 0
+       for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) {
+               uint64_t inst;
+               retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
+               if (retval != ERROR_OK)
+                       return retval;
+               inst = jmp_code[i];
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
+               mips_ejtag_drscan_64(ejtag_info, &inst); /* FIXME: excessive 
nop's */
+
+               /* Clear the access pending bit (let the processor eat!) */
+               ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
+               mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
+               mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl);
+       }
+
+       /* wait PrAcc pending bit for FASTDATA write */
+       retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
+       if (retval != ERROR_OK)
+               return retval;
+#endif
+       mips64_pracc_exec(ejtag_info, 
+                         ARRAY_SIZE(jmp_code), jmp_code,
+                         0, NULL, 0, NULL, 1);
+
+       /* next fetch to dmseg should be in FASTDATA_AREA, check */
+       address = 0;
+
+       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
+       retval = mips_ejtag_drscan_32(ejtag_info, &address32);
+       if (retval != ERROR_OK)
+               return retval;
+       address = 0xffffffffff200000ull | address32;
+       if ((address & ~7ull) != MIPS64_PRACC_FASTDATA_AREA) {
+               LOG_ERROR("! @MIPS64_PRACC_FASTDATA_AREA (" TARGET_ADDR_FMT 
")", address);
+               return ERROR_FAIL;
+       }
+       /* Send the load start address */
+       val = addr;
+       LOG_DEBUG("start: " TARGET_ADDR_FMT, val);
+       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
+       mips64_ejtag_fastdata_scan(ejtag_info, 1, &val);
+
+       retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* Send the load end address */
+       val = addr + (count - 1) * 8;
+       LOG_DEBUG("stop: " TARGET_ADDR_FMT, val);
+       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
+       mips64_ejtag_fastdata_scan(ejtag_info, 1, &val);
+
+       unsigned num_clocks = 0;        /* like in legacy code */
+       if (ejtag_info->mode != 0)
+               num_clocks = ((uint64_t)(ejtag_info->scan_delay) * 
jtag_get_speed_khz() + 500000) / 1000000;
+       LOG_DEBUG("num_clocks=%d", num_clocks); 
+       for (i = 0; i < count; i++) {
+               jtag_add_clocks(num_clocks);
+               retval = mips64_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("mips64_ejtag_fastdata_scan failed");
+                       return retval;
+               }
+       }
+
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK) {
+               LOG_ERROR("jtag_execute_queue failed");
+               return retval;
+       }
+
+       retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("wait_for_pracc_rw failed");
+               return retval;
+       }
+
+       address = 0;
+       mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
+       retval = mips_ejtag_drscan_32(ejtag_info, &address32);
+       address = 0xffffffffff200000ull | address32;
+       if (retval != ERROR_OK) {
+               LOG_ERROR("mips_ejtag_drscan_32 failed");
+               return retval;
+       }
+
+       if ((address & ~7ull) != MIPS64_PRACC_TEXT)
+               LOG_ERROR("mini program did not return to start");
+
+       return retval;
+}
+
 #endif /* BUILD_TARGET64 */
diff --git a/src/target/mips64_pracc.h b/src/target/mips64_pracc.h
index 00def78..2190495 100644
--- a/src/target/mips64_pracc.h
+++ b/src/target/mips64_pracc.h
@@ -40,6 +40,9 @@
 #undef LOWER16
 #define UPPER16(v) ((uint32_t)((v >> 16) & 0xFFFF))
 #define LOWER16(v) ((uint32_t)(v & 0xFFFF))
+#define MIPS64_PRACC_FASTDATA_AREA             0xffffffffFF200000
+#define MIPS64_PRACC_FASTDATA_SIZE             16
+#define MIPS64_FASTDATA_HANDLER_SIZE   0x80
 
 /* FIXME: 16-bit NEG */
 #undef NEG16
@@ -74,4 +77,10 @@ extern int mips64_pracc_write_regs(struct mips_ejtag 
*ejtag_info, uint64_t *regs
 
 extern int mips64_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, 
uint32_t *code,
        int num_param_in, uint64_t *param_in, int num_param_out, uint64_t 
*param_out, int cycle);
+
+extern int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, 
+               struct working_area *source,
+               int write_t, uint64_t addr,
+               int count, uint64_t *buf);
+
 #endif /* OPENOCD_TARGET_MIPS64_PRACC_H */
diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c
index e4ef3c1..fdf320e 100644
--- a/src/target/mips_ejtag.c
+++ b/src/target/mips_ejtag.c
@@ -514,7 +514,6 @@ int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, 
int write_t, uint32_
        return ERROR_OK;
 }
 
-
 #if BUILD_TARGET64 == 1
 
 int mips64_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step)
@@ -588,4 +587,41 @@ int mips64_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
        return ERROR_OK;
 }
 
+int mips64_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, 
uint64_t *data)
+{
+       struct jtag_tap *tap;
+
+       tap = ejtag_info->tap;
+       assert(tap != NULL);
+
+       struct scan_field fields[2];
+       uint8_t spracc = 0;
+       uint8_t t[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+       /* fastdata 1-bit register */
+       fields[0].num_bits = 1;
+       fields[0].out_value = &spracc;
+       fields[0].in_value = NULL;
+
+       /* processor access data register 32 bit */
+       fields[1].num_bits = 64;
+       fields[1].out_value = t;
+
+       if (write_t) {
+               fields[1].in_value = NULL;
+               buf_set_u64(t, 0, 64, *data);
+       } else
+               fields[1].in_value = (uint8_t *) data;
+
+       jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
+
+       /* FIXME: mips_le_to_h_u64*/
+       if (!write_t && data)
+               jtag_add_callback(mips_le_to_h_u32,
+                       (jtag_callback_data_t) data);
+       keep_alive();
+
+       return ERROR_OK;
+}
+
 #endif /* BUILD_TARGET64 */
diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h
index 21b3e68..9dd2f03 100644
--- a/src/target/mips_ejtag.h
+++ b/src/target/mips_ejtag.h
@@ -238,6 +238,7 @@ int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, 
uint32_t *data);
 void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data);
 int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data);
 int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, 
uint32_t *data);
+int mips64_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, 
uint64_t *data);
 
 int mips_ejtag_init(struct mips_ejtag *ejtag_info);
 int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step);
@@ -249,4 +250,10 @@ static inline void mips_le_to_h_u32(jtag_callback_data_t 
arg)
        *((uint32_t *)arg) = le_to_h_u32(in);
 }
 
+static inline void mips_le_to_h_u64(jtag_callback_data_t arg)
+{
+       uint8_t *in = (uint8_t *)arg;
+       *((uint64_t *)arg) = le_to_h_u64(in);
+}
+
 #endif /* OPENOCD_TARGET_MIPS_EJTAG_H */
diff --git a/src/target/mips_mips64.c b/src/target/mips_mips64.c
index 26e8342..8153f1a 100644
--- a/src/target/mips_mips64.c
+++ b/src/target/mips_mips64.c
@@ -741,6 +741,73 @@ static int mips_mips64_read_memory(struct target *target, 
uint64_t address,
        return retval;
 }
 
+static int mips_mips64_bulk_write_memory(struct target *target, target_addr_t 
address,
+               uint32_t count, const uint8_t *buffer)
+{
+       mips64_common_t *mips64 = target->arch_info;
+       struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
+       struct working_area *fast_data_area;
+       int retval;
+       int write_t = 1;
+
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", count: 0x%8.8" PRIx32 "", 
address, count);
+
+       /* check alignment */
+       if (address & 0x7u)
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+
+       if (mips64->fast_data_area == NULL) {
+               /* Get memory for block write handler
+                * we preserve this area between calls and gain a speed increase
+                * of about 3kb/sec when writing flash
+                * this will be released/nulled by the system when the target 
is resumed or reset */
+               retval = target_alloc_working_area(target,
+                               MIPS64_FASTDATA_HANDLER_SIZE,
+                               &mips64->fast_data_area);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("No working area available");
+                       return retval;
+               }
+
+               /* reset fastadata state so the algo get reloaded */
+               ejtag_info->fast_access_save = -1;
+       }
+
+       fast_data_area = mips64->fast_data_area;
+
+       if (address <= fast_data_area->address + fast_data_area->size &&
+                       fast_data_area->address <= address + count) {
+               LOG_ERROR("fast_data (" TARGET_ADDR_FMT ") is within write area 
"
+                         "(" TARGET_ADDR_FMT "-" TARGET_ADDR_FMT ").",
+                         fast_data_area->address, address, address + count);
+               LOG_ERROR("Change work-area-phys or load_image address!");
+               return ERROR_FAIL;
+       }
+
+       /* mips32_pracc_fastdata_xfer requires uint32_t in host endianness, */
+       /* but byte array represents target endianness                      */
+       uint64_t *t = NULL;
+       t = malloc(count * sizeof(uint64_t));
+       if (t == NULL) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+
+       target_buffer_get_u64_array(target, buffer, count, t);
+
+       retval = mips64_pracc_fastdata_xfer(ejtag_info, mips64->fast_data_area,
+                       write_t, address,
+                       count, t);
+
+       if (t != NULL)
+               free(t);
+
+       if (retval != ERROR_OK)
+               LOG_ERROR("Fastdata access Failed");
+
+       return retval;
+}
+
 static int mips_mips64_write_memory(struct target *target, uint64_t address,
        uint32_t size, uint32_t count, const uint8_t *buffer)
 {
@@ -755,6 +822,7 @@ static int mips_mips64_write_memory(struct target *target, 
uint64_t address,
                return ERROR_TARGET_NOT_HALTED;
        }
 
+
        /* sanitize arguments */
        if (((size != 8) && (size != 4) && (size != 2) && (size != 1)) || 
(count == 0) || !(buffer))
                return ERROR_COMMAND_ARGUMENT_INVALID;
@@ -763,6 +831,16 @@ static int mips_mips64_write_memory(struct target *target, 
uint64_t address,
            ((size == 2) && (address & 0x1u)))
                return ERROR_TARGET_UNALIGNED_ACCESS;
 
+       if (size == 8 && count > 8) {
+               retval = mips_mips64_bulk_write_memory(target,
+                       address,
+                       count,
+                       buffer);
+               if (retval == ERROR_OK)
+                       return ERROR_OK;
+               LOG_WARNING("Falling back to non-bulk write");
+       }
+
        void *t = NULL;
        if (size > 1) {
                /* mips32_..._write_mem with size 4/2 requires 
uint32_t/uint16_t in host */
diff --git a/src/target/target.h b/src/target/target.h
index f0dd723..5848760 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -656,6 +656,7 @@ void target_buffer_set_u64(struct target *target, uint8_t 
*buffer, uint64_t valu
 void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t 
value);
 void target_buffer_set_u24(struct target *target, uint8_t *buffer, uint32_t 
value);
 void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t 
value);
+void target_buffer_set_array(struct target *target, uint8_t *buffer, uint32_t 
count, uint32_t size, const uint8_t *srcbuf);
 
 void target_buffer_get_u64_array(struct target *target, const uint8_t *buffer, 
uint32_t count, uint64_t *dstbuf);
 void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, 
uint32_t count, uint32_t *dstbuf);
diff --git a/tcl/target/netl_xlp3xx.cfg b/tcl/target/netl_xlp3xx.cfg
index 643e964..90ef9ca 100644
--- a/tcl/target/netl_xlp3xx.cfg
+++ b/tcl/target/netl_xlp3xx.cfg
@@ -36,3 +36,4 @@ proc chipreset {} {
 jtag configure xlp.jrc -event setup "jtag tapenable xlp.cpu_1"
 
 target create xlp.cpu_1 mips_mips64 -endian big -chain-position xlp.cpu_1
+xlp.cpu_1 configure -work-area-phys 0xffffffffa0600000 -work-area-size 0x20000

-- 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to