Exemplo n.º 1
0
void cts_task(void)
{
	enum cts_rc rc;
	int i;

	gpio_enable_interrupt(GPIO_CTS_IRQ1);
	gpio_enable_interrupt(GPIO_CTS_IRQ2);
	interrupt_enable();
	for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
		clear_state();
		sync();
		rc = tests[i].run();
		interrupt_enable();
		CPRINTF("\n%s %d\n", tests[i].name, rc);
		cflush();
	}

	CPRINTS("Interrupt test suite finished");
	cflush();

	while (1) {
		watchdog_reload();
		sleep(1);
	}
}
Exemplo n.º 2
0
static int command_mem_dump(int argc, char **argv)
{
	volatile uint32_t *address;
	uint32_t value, num = 1, i;
	char *e;

	if (argc < 2)
		return EC_ERROR_PARAM_COUNT;

	address = (uint32_t *)(uintptr_t)strtoi(argv[1], &e, 0);
	if (*e)
		return EC_ERROR_PARAM1;

	if (argc >= 3)
		num = strtoi(argv[2], &e, 0);

	for (i = 0; i < num; i++) {
		value = address[i];
		if (0 == (i%4))
			ccprintf("\n%08X: %08x", address+i, value);
		else
			ccprintf(" %08x", value);
		cflush();

		/* Lots of output could take a while.
		 * Let other things happen, too */
		if (!(i % 0x100)) {
			watchdog_reload();
			usleep(10 * MSEC);
		}
	}
	ccprintf("\n");
	cflush();
	return EC_SUCCESS;
}
Exemplo n.º 3
0
int flash_physical_write(int offset, int size, const char *data)
{
	uint16_t *address = (uint16_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset);
	int res = EC_SUCCESS;
	int i;

	if (unlock(PRG_LOCK) != EC_SUCCESS) {
		res = EC_ERROR_UNKNOWN;
		goto exit_wr;
	}

	/* Clear previous error status */
	STM32_FLASH_SR = 0x34;

	/* set PG bit */
	STM32_FLASH_CR |= PG;

	for (; size > 0; size -= sizeof(uint16_t)) {
		/*
		 * Reload the watchdog timer to avoid watchdog reset when doing
		 * long writing with interrupt disabled.
		 */
		watchdog_reload();

		/* wait to be ready  */
		for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP);
		     i++)
			;

		/* write the half word */
		*address++ = data[0] + (data[1] << 8);
		data += 2;

		/* Wait for writes to complete */
		for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP);
		     i++)
			;

		if (STM32_FLASH_SR & 1) {
			res = EC_ERROR_TIMEOUT;
			goto exit_wr;
		}

		/* Check for error conditions - erase failed, voltage error,
		 * protection error */
		if (STM32_FLASH_SR & 0x14) {
			res = EC_ERROR_UNKNOWN;
			goto exit_wr;
		}
	}

exit_wr:
	/* Disable PG bit */
	STM32_FLASH_CR &= ~PG;

	lock();

	return res;
}
Exemplo n.º 4
0
int flash_physical_erase(int offset, int size)
{
	int rv = EC_SUCCESS;
	/* check protection */
	if (all_protected)
		return EC_ERROR_ACCESS_DENIED;

	/* Lock physical flash operations */
	flash_lock_mapped_storage(1);

	/* Disable tri-state */
	TRISTATE_FLASH(0);

	/* Alignment has been checked in upper layer */
	for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
		offset += CONFIG_FLASH_ERASE_SIZE) {
		/* check protection */
		if (flash_check_prot_range(offset, CONFIG_FLASH_ERASE_SIZE)) {
			rv = EC_ERROR_ACCESS_DENIED;
			break;
		}

		/*
		 * Reload the watchdog timer, so that erasing many flash pages
		 * doesn't cause a watchdog reset.  May not need this now that
		 * we're using msleep() below.
		 */
		watchdog_reload();

		/* Enable write */
		rv = flash_write_enable();
		if (rv)
			break;

		/* Set erase address */
		flash_set_address(offset);
		/* Start erase */
		flash_execute_cmd(CMD_SECTOR_ERASE, MASK_CMD_ADR);

		/* Wait erase completed */
		rv = flash_wait_ready(FLASH_ABORT_TIMEOUT);
		if (rv)
			break;
	}

	/* Enable tri-state */
	TRISTATE_FLASH(1);

	/* Unlock physical flash operations */
	flash_lock_mapped_storage(0);

	return rv;
}
Exemplo n.º 5
0
static int command_mem_dump(int argc, char **argv)
{
	uint32_t address, i, num = 1;
	char *e;
	enum format fmt = FMT_WORD;

	if (argc > 1) {
		if ((argv[1][0] == '.') && (strlen(argv[1]) == 2)) {
			switch (argv[1][1]) {
			case 'b':
				fmt = FMT_BYTE;
				break;
			case 'h':
				fmt = FMT_HALF;
				break;
			case 's':
				fmt = FMT_STRING;
				break;
			default:
				return EC_ERROR_PARAM1;
			}
			argc--;
			argv++;
		}
	}

	if (argc < 2)
		return EC_ERROR_PARAM_COUNT;

	address = strtoi(argv[1], &e, 0);
	if (*e)
		return EC_ERROR_PARAM1;

	if (argc >= 3)
		num = strtoi(argv[2], &e, 0);

	for (i = 0; i < num; i++) {
		show_val(address, i, fmt);
		/* Lots of output could take a while.
		 * Let other things happen, too */
		if (!(i % 0x100)) {
			watchdog_reload();
			usleep(10 * MSEC);
		}
	}
	ccprintf("\n");
	cflush();
	return EC_SUCCESS;
}
Exemplo n.º 6
0
/*
 * Raw busy loop. Returns 1 if loop finishes before interrupt is triggered.
 * Loop length is controlled by busy_loop_timeout. It has to be set to the
 * value which makes the loop last longer than CTS_INTERRUPT_TRIGGER_DELAY_US.
 */
static int busy_loop(void)
{
	/* TODO: Derive a proper value from clock speed */
	const uint32_t busy_loop_timeout = 0xfffff;
	uint32_t counter = 0;

	while (counter++ < busy_loop_timeout) {
		if (got_interrupt)
			break;
		watchdog_reload();
	}
	if (counter > busy_loop_timeout)
		return 1;

	return 0;
}
Exemplo n.º 7
0
void system_reset(int flags)
{
	/* Disable interrupts to avoid task swaps during reboot. */
	interrupt_disable();

	/* TODO: Implement flags and stuff. */

	/*
	 * Try to trigger a watchdog reset, by setting the smallest timeout
	 * period we can.
	 */
	ROTOR_MCU_WDT_TORR = 0;
	watchdog_reload();

	/* Wait for system reset. */
	while (1)
		asm("wfi");
}
Exemplo n.º 8
0
int flash_physical_erase(int offset, int size)
{
	/* check protection */
	if (all_protected)
		return EC_ERROR_ACCESS_DENIED;

	/* Disable tri-state */
	TRISTATE_FLASH(0);

	/* Alignment has been checked in upper layer */
	for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
		offset += CONFIG_FLASH_ERASE_SIZE) {

		/* Do nothing if already erased */
		if (flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE))
			continue;

		/* check protection */
		if (flash_check_prot_range(offset, CONFIG_FLASH_ERASE_SIZE))
			return EC_ERROR_ACCESS_DENIED;

		/*
		 * Reload the watchdog timer, so that erasing many flash pages
		 * doesn't cause a watchdog reset.  May not need this now that
		 * we're using msleep() below.
		 */
		watchdog_reload();

		/* Enable write */
		flash_write_enable();
		/* Set erase address */
		flash_set_address(offset);
		/* Start erase */
		flash_execute_cmd(CMD_SECTOR_ERASE, MASK_CMD_ADR);

		/* Wait erase completed */
		flash_wait_ready();
	}

	/* Enable tri-state */
	TRISTATE_FLASH(1);
	return EC_SUCCESS;
}
Exemplo n.º 9
0
void cts_task(void)
{
	enum cts_rc rc;
	int i;

	for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
		sync();
		rc = tests[i].run();
		CPRINTF("\n%s %d\n", tests[i].name, rc);
		cflush();
	}

	CPRINTS("Timer test suite finished");
	cflush();

	while (1) {
		watchdog_reload();
		sleep(1);
	}
}
Exemplo n.º 10
0
void cts_task(void)
{
	enum cts_rc result;
	int i;

	uart_flush_output();
	for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
		sync();
		result = tests[i].run();
		CPRINTF("\n%s %d\n", tests[i].name, result);
		uart_flush_output();
	}

	CPRINTS("GPIO test suite finished");
	uart_flush_output();
	while (1) {
		watchdog_reload();
		sleep(1);
	}
}
Exemplo n.º 11
0
void cts_task(void)
{
	enum cts_rc rc;
	int i;

	gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_HIGH);

	for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
		gpio_set_level(GPIO_OUTPUT_TEST, 1);
		gpio_set_level(GPIO_CTS_IRQ2, 1);
		sync();
		rc = tests[i].run();
		CPRINTF("\n%s %d\n", tests[i].name, rc);
		cflush();
	}

	CPRINTS("Interrupt test suite finished");
	cflush();

	while (1) {
		watchdog_reload();
		sleep(1);
	}
}
Exemplo n.º 12
0
int flash_physical_erase(int offset, int size)
{
	int res = EC_SUCCESS;

	if (unlock(PRG_LOCK) != EC_SUCCESS)
		return EC_ERROR_UNKNOWN;

	/* Clear previous error status */
	STM32_FLASH_SR = 0x34;

	/* set PER bit */
	STM32_FLASH_CR |= PER;

	for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
	     offset += CONFIG_FLASH_ERASE_SIZE) {
		timestamp_t deadline;

		/* Do nothing if already erased */
		if (flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE))
			continue;

		/* select page to erase */
		STM32_FLASH_AR = CONFIG_PROGRAM_MEMORY_BASE + offset;

		/* set STRT bit : start erase */
		STM32_FLASH_CR |= STRT;

		/*
		 * Reload the watchdog timer to avoid watchdog reset during a
		 * long erase operation.
		 */
		watchdog_reload();

		deadline.val = get_time().val + FLASH_TIMEOUT_US;
		/* Wait for erase to complete */
		while ((STM32_FLASH_SR & 1) &&
		       (get_time().val < deadline.val)) {
			usleep(300);
		}
		if (STM32_FLASH_SR & 1) {
			res = EC_ERROR_TIMEOUT;
			goto exit_er;
		}

		/*
		 * Check for error conditions - erase failed, voltage error,
		 * protection error
		 */
		if (STM32_FLASH_SR & 0x14) {
			res = EC_ERROR_UNKNOWN;
			goto exit_er;
		}
	}

exit_er:
	/* reset PER bit */
	STM32_FLASH_CR &= ~PER;

	lock();

	return res;
}
int flash_physical_erase(int offset, int size)
{
	uint32_t *address;
	int res = EC_SUCCESS;

	res = unlock(STM32_FLASH_PECR_PRG_LOCK);
	if (res)
		return res;

	/* Clear previous error status */
	STM32_FLASH_SR = 0xf00;

	/* Set PROG and ERASE bits */
	STM32_FLASH_PECR |= STM32_FLASH_PECR_PROG | STM32_FLASH_PECR_ERASE;

	for (address = (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset);
	     size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
	     address += CONFIG_FLASH_ERASE_SIZE / sizeof(uint32_t)) {
		timestamp_t deadline;

		/* Do nothing if already erased */
		if (flash_is_erased((uint32_t)address -
				    CONFIG_PROGRAM_MEMORY_BASE,
				    CONFIG_FLASH_ERASE_SIZE))
			continue;

		/* Start erase */
		*address = 0x00000000;

		/*
		 * Reload the watchdog timer to avoid watchdog reset during
		 * multi-page erase operations.
		 */
		watchdog_reload();

		deadline.val = get_time().val + FLASH_TIMEOUT_MS * MSEC;
		/* Wait for erase to complete */
		while ((STM32_FLASH_SR & 1) &&
		       (get_time().val < deadline.val)) {
			usleep(300);
		}
		if (STM32_FLASH_SR & 1) {
			res = EC_ERROR_TIMEOUT;
			goto exit_er;
		}

		/*
		 * Check for error conditions: erase failed, voltage error,
		 * protection error
		 */
		if (STM32_FLASH_SR & 0xF00) {
			res = EC_ERROR_UNKNOWN;
			goto exit_er;
		}
	}

exit_er:
	/* Disable program and erase, and relock PECR */
	STM32_FLASH_PECR &= ~(STM32_FLASH_PECR_PROG | STM32_FLASH_PECR_ERASE);
	lock();

	return res;
}
int flash_physical_write(int offset, int size, const char *data)
{
	uint32_t *data32 = (uint32_t *)data;
	uint32_t *address = (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset);
	int res = EC_SUCCESS;
	int word_mode = 0;
	int i;

	/* Fail if offset, size, and data aren't at least word-aligned */
	if ((offset | size | (uint32_t)(uintptr_t)data) & 3)
		return EC_ERROR_INVAL;

	/* Unlock program area */
	res = unlock(STM32_FLASH_PECR_PRG_LOCK);
	if (res)
		goto exit_wr;

	/* Clear previous error status */
	STM32_FLASH_SR = 0xf00;

	/*
	 * If offset and size aren't on word boundaries, do word writes.  This
	 * is slower, but since we claim to the outside world that writes must
	 * be half-page size, the only code which hits this path is writing
	 * pstate (which is just writing one word).
	 */
	if ((offset | size) & (CONFIG_FLASH_WRITE_SIZE - 1))
		word_mode = 1;

	/* Update flash timeout based on current clock speed */
	flash_timeout_loop = FLASH_TIMEOUT_MS * (clock_get_freq() / MSEC) /
		CYCLE_PER_FLASH_LOOP;

	while (size > 0) {
		/*
		 * Reload the watchdog timer to avoid watchdog reset when doing
		 * long writing with interrupt disabled.
		 */
		watchdog_reload();

		if (word_mode) {
			/* Word write */
			*address++ = *data32++;

			/* Wait for writes to complete */
			for (i = 0; ((STM32_FLASH_SR & 9) != 8) &&
				     (i < flash_timeout_loop); i++)
				;

			size -= sizeof(uint32_t);
		} else {
			/* Half page write */
			interrupt_disable();
			iram_flash_write(address, data32);
			interrupt_enable();
			address += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t);
			data32 += CONFIG_FLASH_WRITE_SIZE / sizeof(uint32_t);
			size -= CONFIG_FLASH_WRITE_SIZE;
		}

		if (STM32_FLASH_SR & 1) {
			res = EC_ERROR_TIMEOUT;
			goto exit_wr;
		}

		/*
		 * Check for error conditions: erase failed, voltage error,
		 * protection error
		 */
		if (STM32_FLASH_SR & 0xf00) {
			res = EC_ERROR_UNKNOWN;
			goto exit_wr;
		}
	}

exit_wr:
	/* Relock program lock */
	lock();

	return res;
}
Exemplo n.º 15
0
static int do_flash_op(enum flash_op op, int is_info_bank,
		       int byte_offset, int words)
{
	volatile uint32_t *fsh_pe_control;
	uint32_t opcode, tmp, errors;
	int retry_count, max_attempts, extra_prog_pulse, i;
	int timedelay_us = 100;
	uint32_t prev_error = 0;

	/* Make sure the smart program/erase algorithms are enabled. */
	if (!GREAD(FLASH, FSH_TIMING_PROG_SMART_ALGO_ON) ||
	    !GREAD(FLASH, FSH_TIMING_ERASE_SMART_ALGO_ON)) {
		CPRINTF("%s:%d\n", __func__, __LINE__);
		return EC_ERROR_UNIMPLEMENTED;
	}

	/* Error status is self-clearing. Read it until it does (we hope). */
	for (i = 0; i < 50; i++) {
		tmp = GREAD(FLASH, FSH_ERROR);
		if (!tmp)
			break;
		usleep(timedelay_us);
	}
	/* If we can't clear the error status register then something is wrong.
	 */
	if (tmp) {
		CPRINTF("%s:%d\n", __func__, __LINE__);
		return EC_ERROR_UNKNOWN;
	}

	/* We have two flash banks. Adjust offset and registers accordingly. */
	if (is_info_bank) {
		/* Only INFO bank operations are supported. */
		fsh_pe_control = GREG32_ADDR(FLASH, FSH_PE_CONTROL1);
	} else if (byte_offset >= CFG_FLASH_HALF) {
		byte_offset -= CFG_FLASH_HALF;
		fsh_pe_control = GREG32_ADDR(FLASH, FSH_PE_CONTROL1);
	} else {
		fsh_pe_control = GREG32_ADDR(FLASH, FSH_PE_CONTROL0);
	}

	/* What are we doing? */
	switch (op) {
	case OP_ERASE_BLOCK:
		if (is_info_bank)
			/* Erasing the INFO bank from the RW section is
			 * unsupported. */
			return EC_ERROR_INVAL;
		opcode = 0x31415927;
		words = 0;			/* don't care, really */
		/* This number is based on the TSMC spec Nme=Terase/Tsme */
		max_attempts = 45;
		break;
	case OP_WRITE_BLOCK:
		opcode = 0x27182818;
		words--;		     /* count register is zero-based */
		/* This number is based on the TSMC spec Nmp=Tprog/Tsmp */
		max_attempts = 9;
		break;
	case OP_READ_BLOCK:
		if (!is_info_bank)
			/* This code path only supports reading from
			 * the INFO bank.
			 */
			return EC_ERROR_INVAL;
		opcode = 0x16021765;
		words = 1;
		max_attempts = 9;
		break;
	default:
		return EC_ERROR_INVAL;
	}

	/*
	 * Set the parameters. For writes, we assume the write buffer is
	 * already filled before we call this function.
	 */
	GWRITE_FIELD(FLASH, FSH_TRANS, OFFSET,
		     byte_offset / 4);		  /* word offset */
	GWRITE_FIELD(FLASH, FSH_TRANS, MAINB, is_info_bank ? 1 : 0);
	GWRITE_FIELD(FLASH, FSH_TRANS, SIZE, words);

	/* TODO: Make sure this function isn't getting called "too often" in
	 * between erases.
	 */
	extra_prog_pulse = 0;
	for (retry_count = 0; retry_count < max_attempts; retry_count++) {
		/* Kick it off */
		GWRITE(FLASH, FSH_PE_EN, 0xb11924e1);
		*fsh_pe_control = opcode;

		/* Wait for completion. 150ms should be enough
		 * (crosbug.com/p/45366).
		 */
		for (i = 0; i < 1500; i++) {
			tmp = *fsh_pe_control;
			if (!tmp)
				break;
			usleep(timedelay_us);
		}

		/* Timed out waiting for control register to clear */
		if (tmp) {
			CPRINTF("%s:%d\n", __func__, __LINE__);
			return EC_ERROR_UNKNOWN;
		}
		/* Check error status */
		errors = GREAD(FLASH, FSH_ERROR);

		if (errors && (errors != prev_error)) {
			prev_error = errors;
			CPRINTF("%s:%d errors %x fsh_pe_control %p\n",
				__func__, __LINE__, errors, fsh_pe_control);
		}
		/* Error status is self-clearing. Read it until it does
		 * (we hope).
		 */
		for (i = 0; i < 50; i++) {
			tmp = GREAD(FLASH, FSH_ERROR);
			if (!tmp)
				break;
			usleep(timedelay_us);
		}
		/* If we can't clear the error status register then something
		 * is wrong.
		 */
		if (tmp) {
			CPRINTF("%s:%d\n", __func__, __LINE__);
			return EC_ERROR_UNKNOWN;
		}
		/* The operation was successful. */
		if (!errors) {
			/* From the spec:
			 * "In addition, one more program pulse is needed after
			 * program verification is passed."
			 */
			if (op == OP_WRITE_BLOCK && !extra_prog_pulse) {
				extra_prog_pulse = 1;
				max_attempts++;
				continue;
			}
			return EC_SUCCESS;
		}
		/* If there were errors after completion retry. */
		watchdog_reload();
	}
	CPRINTF("%s:%d, retry count %d\n", __func__, __LINE__, retry_count);
	return EC_ERROR_UNKNOWN;
}
Exemplo n.º 16
0
static int command_sps(int argc, char **argv)
{
	int count = 0;
	int target = 10; /* Expect 10 frames by default.*/
	char *e;

	sps_tx_status(GC_SPS_DUMMY_WORD_DEFAULT);

	rx_state = spstrx_not_started;
	sps_register_rx_handler(SPS_GENERIC_MODE, sps_receive_callback);

	if (argc > 1) {
		target = strtoi(argv[1], &e, 10);
		if (*e)
			return EC_ERROR_PARAM1;
	}

	while (count++ < target) {
		size_t transmitted;
		size_t to_go;
		size_t index;

		/* Wait for a frame to be received.*/
		while (rx_state != spstrx_finished) {
			watchdog_reload();
			usleep(10);
		}

		/* Transmit the frame back to the host.*/
		index = frame_base;
		to_go = frame_index - frame_base;
		do {
			if ((index == frame_base) && (to_go > 8)) {
				/*
				 * This is the first transmit attempt for this
				 * frame. Send a little just to prime the
				 * transmit FIFO.
				 */
				transmitted = sps_transmit
					(test_frame + index, 8);
			} else {
				transmitted = sps_transmit
					(test_frame + index, to_go);
			}
			index += transmitted;
			to_go -= transmitted;
		} while (to_go);

		/*
		 * Wait for receive state machine to transition out of 'frame
		 * finised' state.
		 */
		while (rx_state == spstrx_finished) {
			watchdog_reload();
			usleep(10);
		}
	}

	sps_unregister_rx_handler();

	ccprintf("Processed %d frames\n", count - 1);
	ccprintf("rx count %d, tx count %d, tx_empty %d, max rx batch %d\n",
		 sps_rx_count, sps_tx_count,
		 tx_empty_count, max_rx_batch);

	sps_rx_count =
		sps_tx_count =
		tx_empty_count =
		max_rx_batch = 0;

	return EC_SUCCESS;
}