Example #1
0
/* 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;
}
Example #2
0
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;
}
Example #3
0
int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
{
	uint32_t pracc_list[] = {MIPS32_DRET, 0};
	struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = pracc_list, .code_count = 1, .store_count = 0};

	/* execute our dret instruction */
	ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);

	/* pic32mx/mz workaround, false pending at low core clock */
	jtag_add_sleep(1000);
	return ctx.retval;
}

/* mips_ejtag_init_mmr - asign Memory-Mapped Registers depending
 *			on EJTAG version.
 */
static void mips_ejtag_init_mmr(struct mips_ejtag *ejtag_info)
{
	if (ejtag_info->ejtag_version == EJTAG_VERSION_20) {
		ejtag_info->ejtag_ibs_addr	= EJTAG_V20_IBS;
		ejtag_info->ejtag_iba0_addr	= EJTAG_V20_IBA0;
		ejtag_info->ejtag_ibc_offs	= EJTAG_V20_IBC_OFFS;
		ejtag_info->ejtag_ibm_offs	= EJTAG_V20_IBM_OFFS;

		ejtag_info->ejtag_dbs_addr	= EJTAG_V20_DBS;
		ejtag_info->ejtag_dba0_addr	= EJTAG_V20_DBA0;
		ejtag_info->ejtag_dbc_offs	= EJTAG_V20_DBC_OFFS;
		ejtag_info->ejtag_dbm_offs	= EJTAG_V20_DBM_OFFS;
		ejtag_info->ejtag_dbv_offs	= EJTAG_V20_DBV_OFFS;

		ejtag_info->ejtag_iba_step_size	= EJTAG_V20_IBAn_STEP;
		ejtag_info->ejtag_dba_step_size	= EJTAG_V20_DBAn_STEP;
	} else {
		ejtag_info->ejtag_ibs_addr	= EJTAG_V25_IBS;
		ejtag_info->ejtag_iba0_addr	= EJTAG_V25_IBA0;
		ejtag_info->ejtag_ibm_offs	= EJTAG_V25_IBM_OFFS;
		ejtag_info->ejtag_ibasid_offs	= EJTAG_V25_IBASID_OFFS;
		ejtag_info->ejtag_ibc_offs	= EJTAG_V25_IBC_OFFS;

		ejtag_info->ejtag_dbs_addr	= EJTAG_V25_DBS;
		ejtag_info->ejtag_dba0_addr	= EJTAG_V25_DBA0;
		ejtag_info->ejtag_dbm_offs	= EJTAG_V25_DBM_OFFS;
		ejtag_info->ejtag_dbasid_offs	= EJTAG_V25_DBASID_OFFS;
		ejtag_info->ejtag_dbc_offs	= EJTAG_V25_DBC_OFFS;
		ejtag_info->ejtag_dbv_offs	= EJTAG_V25_DBV_OFFS;

		ejtag_info->ejtag_iba_step_size	= EJTAG_V25_IBAn_STEP;
		ejtag_info->ejtag_dba_step_size	= EJTAG_V25_DBAn_STEP;
	}
}

static void ejtag_v20_print_imp(struct mips_ejtag *ejtag_info)
{
	LOG_DEBUG("EJTAG v2.0: features:%s%s%s%s%s%s%s%s",
		EJTAG_IMP_HAS(EJTAG_V20_IMP_SDBBP) ? " SDBBP_SPECIAL2" : " SDBBP",
		EJTAG_IMP_HAS(EJTAG_V20_IMP_EADDR_NO32BIT) ? " EADDR>32bit" : " EADDR=32bit",
		EJTAG_IMP_HAS(EJTAG_V20_IMP_COMPLEX_BREAK) ? " COMPLEX_BREAK" : "",
		EJTAG_IMP_HAS(EJTAG_V20_IMP_DCACHE_COH) ? " DCACHE_COH" : " DCACHE_NOT_COH",
		EJTAG_IMP_HAS(EJTAG_V20_IMP_ICACHE_COH) ? " ICACHE_COH" : " ICACHE_NOT_COH",
		EJTAG_IMP_HAS(EJTAG_V20_IMP_NOPB) ? " noPB" : " PB",
		EJTAG_IMP_HAS(EJTAG_V20_IMP_NODB) ? " noDB" : " DB",
		EJTAG_IMP_HAS(EJTAG_V20_IMP_NOIB) ? " noIB" : " IB");
	LOG_DEBUG("EJTAG v2.0: Break Channels: %i",
		(ejtag_info->impcode >> EJTAG_V20_IMP_BCHANNELS_SHIFT) &
		EJTAG_V20_IMP_BCHANNELS_MASK);
}