X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Ftarget%2Farm_adi_v5.c;h=9ea7b5a145ea7f27b8ac8734e5d0cbeb6c24ffc5;hb=b9346fbd644253afe81e786b6649f000c4003214;hp=2695c463b47c275af89f68ab878e2911a6c730a0;hpb=e26bda10bc8bba1721ffddecd41a79acc3586331;p=fw%2Fopenocd diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 2695c463b..9ea7b5a14 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -100,13 +100,13 @@ static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address * @param apsel Number of the AP to (implicitly) use with further * transactions. This normally identifies a MEM-AP. */ -void dap_ap_select(struct adiv5_dap *dap,uint8_t apsel) +void dap_ap_select(struct adiv5_dap *dap,uint8_t ap) { - uint32_t select_apsel = (apsel << 24) & 0xFF000000; + uint32_t new_ap = (ap << 24) & 0xFF000000; - if (select_apsel != dap->apsel) + if (new_ap != dap->ap_current) { - dap->apsel = select_apsel; + dap->ap_current = new_ap; /* Switching AP invalidates cached values. * Values MUST BE UPDATED BEFORE AP ACCESS. */ @@ -270,11 +270,11 @@ int mem_ap_write_atomic_u32(struct adiv5_dap *dap, uint32_t address, * Write a buffer in target order (little endian) * * * *****************************************************************************/ -int mem_ap_write_buf_u32(struct adiv5_dap *dap, uint8_t *buffer, int count, uint32_t address) +int mem_ap_write_buf_u32(struct adiv5_dap *dap, const uint8_t *buffer, int count, uint32_t address) { int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK; uint32_t adr = address; - uint8_t* pBuffer = buffer; + const uint8_t* pBuffer = buffer; count >>= 2; wcount = count; @@ -343,7 +343,7 @@ int mem_ap_write_buf_u32(struct adiv5_dap *dap, uint8_t *buffer, int count, uint } static int mem_ap_write_buf_packed_u16(struct adiv5_dap *dap, - uint8_t *buffer, int count, uint32_t address) + const uint8_t *buffer, int count, uint32_t address) { int retval = ERROR_OK; int wcount, blocksize, writecount, i; @@ -424,7 +424,7 @@ static int mem_ap_write_buf_packed_u16(struct adiv5_dap *dap, return retval; } -int mem_ap_write_buf_u16(struct adiv5_dap *dap, uint8_t *buffer, int count, uint32_t address) +int mem_ap_write_buf_u16(struct adiv5_dap *dap, const uint8_t *buffer, int count, uint32_t address) { int retval = ERROR_OK; @@ -456,7 +456,7 @@ int mem_ap_write_buf_u16(struct adiv5_dap *dap, uint8_t *buffer, int count, uint } static int mem_ap_write_buf_packed_u8(struct adiv5_dap *dap, - uint8_t *buffer, int count, uint32_t address) + const uint8_t *buffer, int count, uint32_t address) { int retval = ERROR_OK; int wcount, blocksize, writecount, i; @@ -532,7 +532,7 @@ static int mem_ap_write_buf_packed_u8(struct adiv5_dap *dap, return retval; } -int mem_ap_write_buf_u8(struct adiv5_dap *dap, uint8_t *buffer, int count, uint32_t address) +int mem_ap_write_buf_u8(struct adiv5_dap *dap, const uint8_t *buffer, int count, uint32_t address) { int retval = ERROR_OK; @@ -882,6 +882,258 @@ int mem_ap_read_buf_u8(struct adiv5_dap *dap, uint8_t *buffer, return retval; } +/*--------------------------------------------------------------------*/ +/* Wrapping function with selection of AP */ +/*--------------------------------------------------------------------*/ +int mem_ap_sel_read_u32(struct adiv5_dap *swjdp, uint8_t ap, + uint32_t address, uint32_t *value) +{ + dap_ap_select(swjdp, ap); + return mem_ap_read_u32(swjdp, address, value); +} + +int mem_ap_sel_write_u32(struct adiv5_dap *swjdp, uint8_t ap, + uint32_t address, uint32_t value) +{ + dap_ap_select(swjdp, ap); + return mem_ap_write_u32(swjdp, address, value); +} + +int mem_ap_sel_read_atomic_u32(struct adiv5_dap *swjdp, uint8_t ap, + uint32_t address, uint32_t *value) +{ + dap_ap_select(swjdp, ap); + return mem_ap_read_atomic_u32(swjdp, address, value); +} + +int mem_ap_sel_write_atomic_u32(struct adiv5_dap *swjdp, uint8_t ap, + uint32_t address, uint32_t value) +{ + dap_ap_select(swjdp, ap); + return mem_ap_write_atomic_u32(swjdp, address, value); +} + +int mem_ap_sel_read_buf_u8(struct adiv5_dap *swjdp, uint8_t ap, + uint8_t *buffer, int count, uint32_t address) +{ + dap_ap_select(swjdp, ap); + return mem_ap_read_buf_u8(swjdp, buffer, count, address); +} + +int mem_ap_sel_read_buf_u16(struct adiv5_dap *swjdp, uint8_t ap, + uint8_t *buffer, int count, uint32_t address) +{ + dap_ap_select(swjdp, ap); + return mem_ap_read_buf_u16(swjdp, buffer, count, address); +} + +int mem_ap_sel_read_buf_u32(struct adiv5_dap *swjdp, uint8_t ap, + uint8_t *buffer, int count, uint32_t address) +{ + dap_ap_select(swjdp, ap); + return mem_ap_read_buf_u32(swjdp, buffer, count, address); +} + +int mem_ap_sel_write_buf_u8(struct adiv5_dap *swjdp, uint8_t ap, + const uint8_t *buffer, int count, uint32_t address) +{ + dap_ap_select(swjdp, ap); + return mem_ap_write_buf_u8(swjdp, buffer, count, address); +} + +int mem_ap_sel_write_buf_u16(struct adiv5_dap *swjdp, uint8_t ap, + const uint8_t *buffer, int count, uint32_t address) +{ + dap_ap_select(swjdp, ap); + return mem_ap_write_buf_u16(swjdp, buffer, count, address); +} + +int mem_ap_sel_write_buf_u32(struct adiv5_dap *swjdp, uint8_t ap, + const uint8_t *buffer, int count, uint32_t address) +{ + dap_ap_select(swjdp, ap); + return mem_ap_write_buf_u32(swjdp, buffer, count, address); +} + +#define MDM_REG_STAT 0x00 +#define MDM_REG_CTRL 0x04 +#define MDM_REG_ID 0xfc + +#define MDM_STAT_FMEACK (1<<0) +#define MDM_STAT_FREADY (1<<1) +#define MDM_STAT_SYSSEC (1<<2) +#define MDM_STAT_SYSRES (1<<3) +#define MDM_STAT_FMEEN (1<<5) +#define MDM_STAT_BACKDOOREN (1<<6) +#define MDM_STAT_LPEN (1<<7) +#define MDM_STAT_VLPEN (1<<8) +#define MDM_STAT_LLSMODEXIT (1<<9) +#define MDM_STAT_VLLSXMODEXIT (1<<10) +#define MDM_STAT_CORE_HALTED (1<<16) +#define MDM_STAT_CORE_SLEEPDEEP (1<<17) +#define MDM_STAT_CORESLEEPING (1<<18) + +#define MEM_CTRL_FMEIP (1<<0) +#define MEM_CTRL_DBG_DIS (1<<1) +#define MEM_CTRL_DBG_REQ (1<<2) +#define MEM_CTRL_SYS_RES_REQ (1<<3) +#define MEM_CTRL_CORE_HOLD_RES (1<<4) +#define MEM_CTRL_VLLSX_DBG_REQ (1<<5) +#define MEM_CTRL_VLLSX_DBG_ACK (1<<6) +#define MEM_CTRL_VLLSX_STAT_ACK (1<<7) + +/** + * + */ +int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap) +{ + uint32_t val; + int retval; + enum reset_types jtag_reset_config = jtag_get_reset_config(); + + dap_ap_select(dap, 1); + + /* first check mdm-ap id register */ + retval = dap_queue_ap_read(dap, MDM_REG_ID, &val); + if (retval != ERROR_OK) + return retval; + dap_run(dap); + + if ( val != 0x001C0000 ) + { + LOG_DEBUG("id doesn't match %08X != 0x001C0000",val); + dap_ap_select(dap, 0); + return ERROR_FAIL; + } + + /* read and parse status register + * it's important that the device is out of + * reset here + */ + retval = dap_queue_ap_read(dap, MDM_REG_STAT, &val); + if (retval != ERROR_OK) + return retval; + dap_run(dap); + + LOG_DEBUG("MDM_REG_STAT %08X",val); + + if ( (val & (MDM_STAT_SYSSEC|MDM_STAT_FREADY)) != (MDM_STAT_FREADY) ) + { + LOG_DEBUG("MDMAP: system is secured, masserase needed"); + + if ( !(val & MDM_STAT_FMEEN) ) + { + LOG_DEBUG("MDMAP: masserase is disabled"); + } + else + { + /* we need to assert reset */ + if ( jtag_reset_config & RESET_HAS_SRST ) + { + /* default to asserting srst */ + if (jtag_reset_config & RESET_SRST_PULLS_TRST) + { + jtag_add_reset(1, 1); + } + else + { + jtag_add_reset(0, 1); + } + } + else + { + LOG_DEBUG("SRST not configured"); + dap_ap_select(dap, 0); + return ERROR_FAIL; + } + + while(1) + { + retval = dap_queue_ap_write(dap, MDM_REG_CTRL, MEM_CTRL_FMEIP); + if (retval != ERROR_OK) + return retval; + dap_run(dap); + /* read status register and wait for ready */ + retval = dap_queue_ap_read(dap, MDM_REG_STAT, &val); + if (retval != ERROR_OK) + return retval; + dap_run(dap); + LOG_DEBUG("MDM_REG_STAT %08X",val); + + if ( (val&1)) + break; + } + + while(1) + { + retval = dap_queue_ap_write(dap, MDM_REG_CTRL, 0); + if (retval != ERROR_OK) + return retval; + dap_run(dap); + /* read status register */ + retval = dap_queue_ap_read(dap, MDM_REG_STAT, &val); + if (retval != ERROR_OK) + return retval; + dap_run(dap); + LOG_DEBUG("MDM_REG_STAT %08X",val); + /* read control register and wait for ready */ + retval = dap_queue_ap_read(dap, MDM_REG_CTRL, &val); + if (retval != ERROR_OK) + return retval; + dap_run(dap); + LOG_DEBUG("MDM_REG_CTRL %08X",val); + + if ( val == 0x00 ) + break; + } + } + } + + dap_ap_select(dap, 0); + + return ERROR_OK; +} + +/** */ +struct dap_syssec_filter { + /** */ + uint32_t idcode; + /** */ + int (*dap_init)(struct adiv5_dap *dap); +}; + +/** */ +static struct dap_syssec_filter dap_syssec_filter_data[] = { + { 0x4BA00477, dap_syssec_kinetis_mdmap } +}; + + +/** + * + */ +int dap_syssec(struct adiv5_dap *dap) +{ + unsigned int i; + struct jtag_tap *tap; + + for(i=0;ijtag_info->tap; + + while (tap != NULL) + { + if ( tap->hasidcode && (dap_syssec_filter_data[i].idcode == tap->idcode) ) + { + LOG_DEBUG("DAP: mdmap_init for idcode: %08x",tap->idcode); + dap_syssec_filter_data[i].dap_init(dap); + } + tap = tap->next_tap; + } + } + + return ERROR_OK; +} + /*--------------------------------------------------------------------------*/ @@ -925,7 +1177,7 @@ int ahbap_debugport_init(struct adiv5_dap *dap) * Should we probe, or take a hint from the caller? * Presumably we can ignore the possibility of multiple APs. */ - dap->apsel = !0; + dap->ap_current = !0; dap_ap_select(dap, 0); /* DP initialization */ @@ -988,6 +1240,8 @@ int ahbap_debugport_init(struct adiv5_dap *dap) if (retval != ERROR_OK) return retval; + dap_syssec(dap); + return ERROR_OK; } @@ -1009,30 +1263,19 @@ is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t cid0) && ((cid1 & 0x0f) == 0) && cid0 == 0x0d; } -struct broken_cpu { - uint32_t dbgbase; - uint32_t apid; - uint32_t idcode; - uint32_t correct_dbgbase; - char *model; -} broken_cpus[] = { - { 0x80000000, 0x04770002, 0x1ba00477, 0x60000000, "imx51" }, -}; - -int dap_get_debugbase(struct adiv5_dap *dap, int apsel, +int dap_get_debugbase(struct adiv5_dap *dap, int ap, uint32_t *out_dbgbase, uint32_t *out_apid) { - uint32_t apselold; + uint32_t ap_old; int retval; - unsigned int i; - uint32_t dbgbase, apid, idcode; + uint32_t dbgbase, apid; /* AP address is in bits 31:24 of DP_SELECT */ - if (apsel >= 256) + if (ap >= 256) return ERROR_INVALID_ARGUMENTS; - apselold = dap->apsel; - dap_ap_select(dap, apsel); + ap_old = dap->ap_current; + dap_ap_select(dap, ap); retval = dap_queue_ap_read(dap, AP_REG_BASE, &dbgbase); if (retval != ERROR_OK) @@ -1047,29 +1290,14 @@ int dap_get_debugbase(struct adiv5_dap *dap, int apsel, /* Excavate the device ID code */ struct jtag_tap *tap = dap->jtag_info->tap; while (tap != NULL) { - if (tap->hasidcode) { - idcode = tap->idcode; + if (tap->hasidcode) break; - } tap = tap->next_tap; } if (tap == NULL || !tap->hasidcode) return ERROR_OK; - /* Some CPUs are messed up, so fixup if needed. */ - for (i = 0; i < sizeof(broken_cpus)/sizeof(struct broken_cpu); i++) - if (broken_cpus[i].dbgbase == dbgbase && - broken_cpus[i].apid == apid && - broken_cpus[i].idcode == idcode) { - LOG_WARNING("Found broken CPU (%s), trying to fixup " - "ROM Table location from 0x%08x to 0x%08x", - broken_cpus[i].model, dbgbase, - broken_cpus[i].correct_dbgbase); - dbgbase = broken_cpus[i].correct_dbgbase; - break; - } - - dap_ap_select(dap, apselold); + dap_ap_select(dap, ap_old); /* The asignment happens only here to prevent modification of these * values before they are certain. */ @@ -1079,18 +1307,18 @@ int dap_get_debugbase(struct adiv5_dap *dap, int apsel, return ERROR_OK; } -int dap_lookup_cs_component(struct adiv5_dap *dap, int apsel, +int dap_lookup_cs_component(struct adiv5_dap *dap, int ap, uint32_t dbgbase, uint8_t type, uint32_t *addr) { - uint32_t apselold; + uint32_t ap_old; uint32_t romentry, entry_offset = 0, component_base, devtype; int retval = ERROR_FAIL; - if (apsel >= 256) + if (ap >= 256) return ERROR_INVALID_ARGUMENTS; - apselold = dap->apsel; - dap_ap_select(dap, apsel); + ap_old = dap->ap_current; + dap_ap_select(dap, ap); do { @@ -1115,26 +1343,26 @@ int dap_lookup_cs_component(struct adiv5_dap *dap, int apsel, entry_offset += 4; } while (romentry > 0); - dap_ap_select(dap, apselold); + dap_ap_select(dap, ap_old); return retval; } static int dap_info_command(struct command_context *cmd_ctx, - struct adiv5_dap *dap, int apsel) + struct adiv5_dap *dap, int ap) { int retval; - uint32_t dbgbase, apid; + uint32_t dbgbase = 0, apid = 0; /* Silence gcc by initializing */ int romtable_present = 0; uint8_t mem_ap; - uint32_t apselold; + uint32_t ap_old; - retval = dap_get_debugbase(dap, apsel, &dbgbase, &apid); + retval = dap_get_debugbase(dap, ap, &dbgbase, &apid); if (retval != ERROR_OK) return retval; - apselold = dap->apsel; - dap_ap_select(dap, apsel); + ap_old = dap->ap_current; + dap_ap_select(dap, ap); /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ mem_ap = ((apid&0x10000) && ((apid&0x0F) != 0)); @@ -1166,7 +1394,7 @@ static int dap_info_command(struct command_context *cmd_ctx, } else { - command_print(cmd_ctx, "No AP found at this apsel 0x%x", apsel); + command_print(cmd_ctx, "No AP found at this ap 0x%x", ap); } romtable_present = ((mem_ap) && (dbgbase != 0xFFFFFFFF)); @@ -1528,7 +1756,7 @@ static int dap_info_command(struct command_context *cmd_ctx, { command_print(cmd_ctx, "\tNo ROM table present"); } - dap_ap_select(dap, apselold); + dap_ap_select(dap, ap_old); return ERROR_OK; } @@ -1560,10 +1788,9 @@ COMMAND_HANDLER(dap_baseaddr_command) struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; - uint32_t apsel, apselsave, baseaddr; + uint32_t apsel, baseaddr; int retval; - apselsave = dap->apsel; switch (CMD_ARGC) { case 0: apsel = dap->apsel; @@ -1578,8 +1805,7 @@ COMMAND_HANDLER(dap_baseaddr_command) return ERROR_COMMAND_SYNTAX_ERROR; } - if (apselsave != apsel) - dap_ap_select(dap, apsel); + dap_ap_select(dap, apsel); /* NOTE: assumes we're talking to a MEM-AP, which * has a base address. There are other kinds of AP, @@ -1595,9 +1821,6 @@ COMMAND_HANDLER(dap_baseaddr_command) command_print(CMD_CTX, "0x%8.8" PRIx32, baseaddr); - if (apselsave != apsel) - dap_ap_select(dap, apselsave); - return retval; } @@ -1650,7 +1873,9 @@ COMMAND_HANDLER(dap_apsel_command) return ERROR_COMMAND_SYNTAX_ERROR; } + dap->apsel = apsel; dap_ap_select(dap, apsel); + retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid); if (retval != ERROR_OK) return retval; @@ -1670,10 +1895,9 @@ COMMAND_HANDLER(dap_apid_command) struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; - uint32_t apsel, apselsave, apid; + uint32_t apsel, apid; int retval; - apselsave = dap->apsel; switch (CMD_ARGC) { case 0: apsel = dap->apsel; @@ -1688,8 +1912,7 @@ COMMAND_HANDLER(dap_apid_command) return ERROR_COMMAND_SYNTAX_ERROR; } - if (apselsave != apsel) - dap_ap_select(dap, apsel); + dap_ap_select(dap, apsel); retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid); if (retval != ERROR_OK) @@ -1699,8 +1922,6 @@ COMMAND_HANDLER(dap_apid_command) return retval; command_print(CMD_CTX, "0x%8.8" PRIx32, apid); - if (apselsave != apsel) - dap_ap_select(dap, apselsave); return retval; }