/* Set (to enable) or clear (to disable stepping) the SSt bit (bit 8) in Cp0 Debug reg (reg 23, sel 0) */ int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step) { struct pracc_queue_info ctx = {.max_code = 7}; pracc_queue_init(&ctx); if (ctx.retval != ERROR_OK) goto exit; pracc_add(&ctx, 0, MIPS32_MFC0(8, 23, 0)); /* move COP0 Debug to $8 */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, 0x0100)); /* set SSt bit in debug reg */ if (!enable_step) pracc_add(&ctx, 0, MIPS32_XORI(8, 8, 0x0100)); /* clear SSt bit in debug reg */ pracc_add(&ctx, 0, MIPS32_MTC0(8, 23, 0)); /* move $8 to COP0 Debug */ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ pracc_add(&ctx, 0, MIPS32_B(NEG16((ctx.code_count + 1)))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); exit: pracc_queue_free(&ctx); return ctx.retval; } /* * Disable memory protection for 0xFF20.0000–0xFF3F.FFFF * It is needed by EJTAG 1.5-2.0, especially for BMIPS CPUs * For example bcm7401 and others. At leas on some * CPUs, DebugMode wont start if this bit is not removed. */ static int disable_dcr_mp(struct mips_ejtag *ejtag_info) { uint32_t dcr; int retval; retval = mips32_dmaacc_read_mem(ejtag_info, EJTAG_DCR, 4, 1, &dcr); if (retval != ERROR_OK) goto error; dcr &= ~EJTAG_DCR_MP; retval = mips32_dmaacc_write_mem(ejtag_info, EJTAG_DCR, 4, 1, &dcr); if (retval != ERROR_OK) goto error; return ERROR_OK; error: LOG_ERROR("Failed to remove DCR MPbit!"); return retval; }
static int ath79_spi_bitbang_chunk(struct flash_bank *bank, uint8_t *data, int len, int *transferred) { struct target *target = bank->target; struct ath79_flash_bank *ath79_info = bank->driver_priv; struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; int pracc_words; /* * These constants must match the worst case in the above code * generator function ath79_spi_bitbang_codegen. */ const int pracc_pre_post = 26; const int pracc_loop_byte = 8 * 2 + 2; struct pracc_queue_info ctx = { .ejtag_info = ejtag_info }; int max_len = (PRACC_MAX_INSTRUCTIONS - pracc_pre_post) / pracc_loop_byte; int to_xfer = len > max_len ? max_len : len; int partial_xfer = len != to_xfer; int padded_len = (to_xfer + 3) & ~3; uint32_t *out = malloc(padded_len); if (!out) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } *transferred = 0; pracc_queue_init(&ctx); LOG_DEBUG("ath79_spi_bitbang_bytes(%p, %08x, %p, %d)", target, ath79_info->io_base, data, len); LOG_DEBUG("max code %d => max len %d. to_xfer %d", PRACC_MAX_INSTRUCTIONS, max_len, to_xfer); pracc_words = ath79_spi_bitbang_codegen( ath79_info, &ctx, data, to_xfer, partial_xfer); LOG_DEBUG("Assembled %d instructions, %d stores", ctx.code_count, ctx.store_count); ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, out, 1); if (ctx.retval != ERROR_OK) goto exit; if (to_xfer & 3) { /* Not a multiple of 4 bytes. */ /* * Need to realign last word since we didn't shift the * full 32 bits. */ int missed_bytes = 4 - (to_xfer & 3); out[pracc_words - 1] <<= BITS_PER_BYTE * missed_bytes; } /* * pracc reads return uint32_t in host endianness, convert to * target endianness. * Since we know the ATH79 target is big endian and the SPI * shift register has the bytes in highest to lowest bit order, * this will ensure correct memory byte order regardless of host * endianness. */ target_buffer_set_u32_array(target, (uint8_t *)out, pracc_words, out); if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) { for (int i = 0; i < to_xfer; i++) { LOG_DEBUG("bitbang %02x => %02x", data[i], ((uint8_t *)out)[i]); } } memcpy(data, out, to_xfer); *transferred = to_xfer; exit: pracc_queue_free(&ctx); free(out); return ctx.retval; }