Esempio n. 1
0
static int str9xpec_blank_check(struct flash_bank *bank, int first, int last)
{
	struct scan_field field;
	uint8_t status;
	struct jtag_tap *tap;
	int i;
	uint8_t *buffer = NULL;

	struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;

	tap = str9xpec_info->tap;

	if (!str9xpec_info->isc_enable)
		str9xpec_isc_enable(bank);

	if (!str9xpec_info->isc_enable)
		return ERROR_FLASH_OPERATION_FAILED;

	buffer = calloc(DIV_ROUND_UP(64, 8), 1);

	LOG_DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);

	for (i = first; i <= last; i++)
		buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);

	/* execute ISC_BLANK_CHECK command */
	str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE);

	field.num_bits = 64;
	field.out_value = buffer;
	field.in_value = NULL;

	jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
	jtag_add_sleep(40000);

	/* read blank check result */
	field.num_bits = 64;
	field.out_value = NULL;
	field.in_value = buffer;

	jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
	jtag_execute_queue();

	status = str9xpec_isc_status(tap);

	for (i = first; i <= last; i++) {
		if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
			bank->sectors[i].is_erased = 0;
		else
			bank->sectors[i].is_erased = 1;
	}

	free(buffer);

	str9xpec_isc_disable(bank);

	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
		return ERROR_FLASH_OPERATION_FAILED;
	return ERROR_OK;
}
Esempio n. 2
0
static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)
{
	struct scan_field field;
	uint8_t status;
	struct jtag_tap *tap;
	int i;
	uint8_t *buffer = NULL;

	struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;

	tap = str9xpec_info->tap;

	if (!str9xpec_info->isc_enable)
		str9xpec_isc_enable(bank);

	if (!str9xpec_info->isc_enable)
		return ISC_STATUS_ERROR;

	buffer = calloc(DIV_ROUND_UP(64, 8), 1);

	LOG_DEBUG("erase: first_bank: %i, last_bank: %i", first, last);

	/* last bank: 0xFF signals a full erase (unlock complete device) */
	/* last bank: 0xFE signals a option byte erase */
	if (last == 0xFF) {
		for (i = 0; i < 64; i++)
			buf_set_u32(buffer, i, 1, 1);
	} else if (last == 0xFE)
		buf_set_u32(buffer, 49, 1, 1);
	else {
		for (i = first; i <= last; i++)
			buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
	}

	LOG_DEBUG("ISC_ERASE");

	/* execute ISC_ERASE command */
	str9xpec_set_instr(tap, ISC_ERASE, TAP_IRPAUSE);

	field.num_bits = 64;
	field.out_value = buffer;
	field.in_value = NULL;

	jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
	jtag_execute_queue();

	jtag_add_sleep(10);

	/* wait for erase completion */
	while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY))
		alive_sleep(1);

	free(buffer);

	str9xpec_isc_disable(bank);

	return status;
}
Esempio n. 3
0
static int str9xpec_write_options(struct flash_bank *bank)
{
	struct scan_field field;
	uint8_t status;
	struct jtag_tap *tap;
	struct str9xpec_flash_controller *str9xpec_info = NULL;

	str9xpec_info = bank->driver_priv;
	tap = str9xpec_info->tap;

	/* erase config options first */
	status = str9xpec_erase_area(bank, 0xFE, 0xFE);

	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
		return status;

	if (!str9xpec_info->isc_enable)
		str9xpec_isc_enable(bank);

	if (!str9xpec_info->isc_enable)
		return ISC_STATUS_ERROR;

	/* according to data 64th bit has to be set */
	buf_set_u32(str9xpec_info->options, 63, 1, 1);

	/* set option byte address */
	str9xpec_set_address(bank, 0x50);

	/* execute ISC_PROGRAM command */
	str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);

	field.num_bits = 64;
	field.out_value = str9xpec_info->options;
	field.in_value = NULL;

	jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);

	/* small delay before polling */
	jtag_add_sleep(50);

	str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);

	do {
		field.num_bits = 8;
		field.out_value = NULL;
		field.in_value = &status;

		jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
		jtag_execute_queue();

	} while (!(status & ISC_STATUS_BUSY));

	str9xpec_isc_disable(bank);

	return status;
}
Esempio n. 4
0
int str9xpec_lock_device(struct flash_bank_s *bank)
{
	scan_field_t field;
	u8 status;
	jtag_tap_t *tap;
	str9xpec_flash_controller_t *str9xpec_info = NULL;

	str9xpec_info = bank->driver_priv;
	tap = str9xpec_info->tap;

	if (!str9xpec_info->isc_enable) {
		str9xpec_isc_enable( bank );
	}

	if (!str9xpec_info->isc_enable) {
		return ISC_STATUS_ERROR;
	}

	/* set security address */
	str9xpec_set_address(bank, 0x80);

	/* execute ISC_PROGRAM command */
	str9xpec_set_instr(tap, ISC_PROGRAM_SECURITY, TAP_IDLE);

	str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);

	do {
		field.tap = tap;
		field.num_bits = 8;
		field.out_value = NULL;
		field.out_mask = NULL;
		field.in_value = &status;
		field.in_check_value = NULL;
		field.in_check_mask = NULL;
		field.in_handler = NULL;
		field.in_handler_priv = NULL;

		jtag_add_dr_scan(1, &field, -1);
		jtag_execute_queue();

	} while(!(status & ISC_STATUS_BUSY));

	str9xpec_isc_disable(bank);

	return status;
}
Esempio n. 5
0
static int str9xpec_lock_device(struct flash_bank *bank)
{
	struct scan_field field;
	uint8_t status;
	struct jtag_tap *tap;
	struct str9xpec_flash_controller *str9xpec_info = NULL;

	str9xpec_info = bank->driver_priv;
	tap = str9xpec_info->tap;

	if (!str9xpec_info->isc_enable)
		str9xpec_isc_enable(bank);

	if (!str9xpec_info->isc_enable)
		return ISC_STATUS_ERROR;

	/* set security address */
	str9xpec_set_address(bank, 0x80);

	/* execute ISC_PROGRAM command */
	str9xpec_set_instr(tap, ISC_PROGRAM_SECURITY, TAP_IDLE);

	str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);

	do {
		field.num_bits = 8;
		field.out_value = NULL;
		field.in_value = &status;

		jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
		jtag_execute_queue();

	} while (!(status & ISC_STATUS_BUSY));

	str9xpec_isc_disable(bank);

	return status;
}
Esempio n. 6
0
static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer,
		uint32_t offset, uint32_t count)
{
	struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
	uint32_t dwords_remaining = (count / 8);
	uint32_t bytes_remaining = (count & 0x00000007);
	uint32_t bytes_written = 0;
	uint8_t status;
	uint32_t check_address = offset;
	struct jtag_tap *tap;
	struct scan_field field;
	uint8_t *scanbuf;
	int i;
	int first_sector = 0;
	int last_sector = 0;

	tap = str9xpec_info->tap;

	if (!str9xpec_info->isc_enable)
		str9xpec_isc_enable(bank);

	if (!str9xpec_info->isc_enable)
		return ERROR_FLASH_OPERATION_FAILED;

	if (offset & 0x7) {
		LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
	}

	for (i = 0; i < bank->num_sectors; i++) {
		uint32_t sec_start = bank->sectors[i].offset;
		uint32_t sec_end = sec_start + bank->sectors[i].size;

		/* check if destination falls within the current sector */
		if ((check_address >= sec_start) && (check_address < sec_end)) {
			/* check if destination ends in the current sector */
			if (offset + count < sec_end)
				check_address = offset + count;
			else
				check_address = sec_end;
		}

		if ((offset >= sec_start) && (offset < sec_end))
			first_sector = i;

		if ((offset + count >= sec_start) && (offset + count < sec_end))
			last_sector = i;
	}

	if (check_address != offset + count)
		return ERROR_FLASH_DST_OUT_OF_BANK;

	LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);

	scanbuf = calloc(DIV_ROUND_UP(64, 8), 1);

	LOG_DEBUG("ISC_PROGRAM");

	for (i = first_sector; i <= last_sector; i++) {
		str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);

		dwords_remaining = dwords_remaining < (bank->sectors[i].size/8)
				? dwords_remaining : (bank->sectors[i].size/8);

		while (dwords_remaining > 0) {
			str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);

			field.num_bits = 64;
			field.out_value = (buffer + bytes_written);
			field.in_value = NULL;

			jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);

			/* small delay before polling */
			jtag_add_sleep(50);

			str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);

			do {
				field.num_bits = 8;
				field.out_value = NULL;
				field.in_value = scanbuf;

				jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
				jtag_execute_queue();

				status = buf_get_u32(scanbuf, 0, 8);

			} while (!(status & ISC_STATUS_BUSY));

			if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
				return ERROR_FLASH_OPERATION_FAILED;

			/* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
				return ERROR_FLASH_OPERATION_FAILED; */

			dwords_remaining--;
			bytes_written += 8;
		}
	}

	if (bytes_remaining) {
		uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

		/* copy the last remaining bytes into the write buffer */
		memcpy(last_dword, buffer+bytes_written, bytes_remaining);

		str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);

		field.num_bits = 64;
		field.out_value = last_dword;
		field.in_value = NULL;

		jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);

		/* small delay before polling */
		jtag_add_sleep(50);

		str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);

		do {
			field.num_bits = 8;
			field.out_value = NULL;
			field.in_value = scanbuf;

			jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
			jtag_execute_queue();

			status = buf_get_u32(scanbuf, 0, 8);

		} while (!(status & ISC_STATUS_BUSY));

		if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
			return ERROR_FLASH_OPERATION_FAILED;

		/* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
			return ERROR_FLASH_OPERATION_FAILED; */
	}

	free(scanbuf);

	str9xpec_isc_disable(bank);

	return ERROR_OK;
}