/* 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;
}
Exemple #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;
}