예제 #1
0
파일: spi_comm.c 프로젝트: gelraen/cros-ec
int spi_slave_send_response_async(struct spi_comm_packet *resp)
{
	int size = resp->size + SPI_PACKET_HEADER_SIZE;
	stm32_spi_regs_t *spi = STM32_SPI1_REGS;

	if (size > SPI_PACKET_MAX_SIZE)
		return EC_ERROR_OVERFLOW;

	if (out_msg != (uint8_t *)resp)
		memcpy(out_msg, resp, size);

	master_slave_sync(100);

	if (spi->sr & STM32_SPI_SR_RXNE)
		in_msg[0] = spi->dr;
	spi->dr = out_msg[0];

	/* Set N_CHG (master SPI_NSS) to high */
	STM32_GPIO_BSRR(GPIO_A) = 1 << 1;

	while (!(spi->sr & STM32_SPI_SR_RXNE))
		;
	in_msg[0] = spi->dr;

	dma_clear_isr(STM32_DMAC_SPI1_TX);
	dma_clear_isr(STM32_DMAC_SPI1_RX);
	dma_start_rx(&dma_rx_option, size - 1, in_msg);
	dma_prepare_tx(&dma_tx_option, size - 1, out_msg + 1);
	dma_go(dma_get_channel(STM32_DMAC_SPI1_TX));

	master_slave_sync(5);

	return EC_SUCCESS;
}
예제 #2
0
파일: spi_comm.c 프로젝트: gelraen/cros-ec
const struct spi_comm_packet *spi_master_wait_response_done(void)
{
	const struct spi_comm_packet *resp =
		(const struct spi_comm_packet *)in_msg;
	stm32_spi_regs_t *spi = STM32_SPI1_REGS;

	if (dma_wait(STM32_DMAC_SPI1_TX) || dma_wait(STM32_DMAC_SPI1_RX)) {
		debug_printf("SPI: Incomplete response\n");
		goto err_wait_response_done;
	}
	if (spi->sr & STM32_SPI_SR_CRCERR) {
		debug_printf("SPI: CRC mismatch\n");
		goto err_wait_response_done;
	}
	if (resp->cmd_sts != EC_SUCCESS) {
		debug_printf("SPI: Slave error\n");
		goto err_wait_response_done;
	}

exit_wait_response_done:
	dma_disable(STM32_DMAC_SPI1_TX);
	dma_disable(STM32_DMAC_SPI1_RX);
	dma_clear_isr(STM32_DMAC_SPI1_TX);
	dma_clear_isr(STM32_DMAC_SPI1_RX);

	/* Set CS1 (slave SPI_NSS) to high */
	STM32_GPIO_BSRR(GPIO_A) = 1 << 6;

	return resp;
err_wait_response_done:
	resp = NULL;
	goto exit_wait_response_done;
}
예제 #3
0
파일: spi_comm.c 프로젝트: gelraen/cros-ec
int spi_master_send_command(struct spi_comm_packet *cmd)
{
	stm32_spi_regs_t *spi = STM32_SPI1_REGS;
	int ret;

	if (cmd->size + 3 > SPI_PACKET_MAX_SIZE)
		return EC_ERROR_OVERFLOW;

	/* Wait for SPI_NSS to go low */
	if (wait_for_signal(GPIO_A, 1 << 0, 0, 10 * MSEC))
		return EC_ERROR_TIMEOUT;

	/* Set CS1 (slave SPI_NSS) to low */
	STM32_GPIO_BSRR(GPIO_A) = 1 << (6 + 16);

	/* Wait for the slave to acknowledge */
	master_slave_sync(5);

	/* Clock out the packet size. */
	spi->dr = cmd->size;
	while (!(spi->sr & STM32_SPI_SR_RXNE))
		;
	ret = spi->dr;

	/* Wait for the slave to acknowledge */
	master_slave_sync(5);

	/* Clock out command. Don't care about input. */
	ret = spi_master_read_write_byte(in_msg, ((uint8_t *)cmd) + 1,
			cmd->size + SPI_PACKET_HEADER_SIZE - 1);

	return ret;
}
예제 #4
0
파일: spi_comm.c 프로젝트: gelraen/cros-ec
int spi_slave_send_response_flush(void)
{
	int ret;

	ret = dma_wait(STM32_DMAC_SPI1_TX);
	ret |= dma_wait(STM32_DMAC_SPI1_RX);
	dma_disable(STM32_DMAC_SPI1_TX);
	dma_disable(STM32_DMAC_SPI1_RX);
	dma_clear_isr(STM32_DMAC_SPI1_TX);
	dma_clear_isr(STM32_DMAC_SPI1_RX);

	/* Set N_CHG (master SPI_NSS) to low */
	STM32_GPIO_BSRR(GPIO_A) = 1 << (1 + 16);

	return ret;
}
예제 #5
0
파일: spi_comm.c 프로젝트: gelraen/cros-ec
int spi_master_wait_response_async(void)
{
	stm32_spi_regs_t *spi = STM32_SPI1_REGS;
	int size;

	master_slave_sync(40);
	if (wait_for_signal(GPIO_A, 1 << 0, 1, 40 * MSEC))
		goto err_wait_resp_async;

	/* Discard potential garbage in SPI DR */
	if (spi->sr & STM32_SPI_SR_RXNE)
		in_msg[0] = spi->dr;

	/* Get the packet size */
	spi->dr = DUMMY_DATA;
	while (!(spi->sr & STM32_SPI_SR_RXNE))
		;
	in_msg[0] = spi->dr;
	size = in_msg[0] + SPI_PACKET_HEADER_SIZE;

	master_slave_sync(5);

	dma_clear_isr(STM32_DMAC_SPI1_TX);
	dma_clear_isr(STM32_DMAC_SPI1_RX);

	/* Get the rest of the packet*/
	dma_start_rx(&dma_rx_option, size - 1, in_msg + 1);
	dma_prepare_tx(&dma_tx_option, size - 1, out_msg);
	dma_go(dma_get_channel(STM32_DMAC_SPI1_TX));

	return EC_SUCCESS;
err_wait_resp_async:
	/* Set CS1 (slave SPI_NSS) to high */
	STM32_GPIO_BSRR(GPIO_A) = 1 << 6;
	return EC_ERROR_TIMEOUT;
}
예제 #6
0
void gpio_set_level(enum gpio_signal signal, int value)
{
	STM32_GPIO_BSRR(gpio_list[signal].port) =
			gpio_list[signal].mask << (value ? 0 : 16);
}
예제 #7
0
static inline void output_disable(void)
{
	/* GPF0 (disable OR'ing FETs) = 0 */
	STM32_GPIO_BSRR(GPIO_F) = GPIO_RESET(0);
}
예제 #8
0
static inline void output_enable(void)
{
	/* GPF0 (enable OR'ing FETs) = 1 */
	STM32_GPIO_BSRR(GPIO_F) = GPIO_SET(0);
}
예제 #9
0
static inline void set_output_voltage(enum volt v)
{
	/* set voltage_select on PA13/PA14 */
	STM32_GPIO_BSRR(GPIO_A) = v;
}
예제 #10
0
static inline void discharge_disable(void)
{
	STM32_GPIO_BSRR(GPIO_F) = GPIO_RESET(1);
	adc_disable_watchdog();
}
예제 #11
0
static inline void discharge_enable(void)
{
	STM32_GPIO_BSRR(GPIO_F) = GPIO_SET(1);
}
예제 #12
0
파일: gpio-stm32f.c 프로젝트: longsleep/ec
void gpio_set_flags_by_mask(uint32_t port, uint32_t pmask, uint32_t flags)
{
	uint32_t addr, cnf, mode, mask;

	gpio_config_info(port, pmask, &addr, &mode, &cnf);
	mask = REG32(addr) & ~(cnf | mode);

	/*
	 * For STM32, the port configuration field changes meaning
	 * depending on whether the port is an input, analog input,
	 * output, or alternate function.
	 */
	if (flags & GPIO_OUTPUT) {
		/*
		 * This sets output max speed to 10MHz.  That should be
		 * sufficient for most GPIO needs; the only thing that needs to
		 * go faster is SPI, which overrides the port speed on its own.
		 */
		mask |= 0x11111111 & mode;
		if (flags & GPIO_OPEN_DRAIN)
			mask |= 0x44444444 & cnf;

	} else {
		/*
		 * GPIOx_ODR determines which resistor to activate in
		 * input mode, see Table 16 (datasheet rm0041)
		 */
		if (flags & GPIO_ANALOG) {
			/* Analog input, MODE=00 CNF=00 */
			/* the 4 bits in mask are already reset above */
		} else if (flags & GPIO_PULL_UP) {
			mask |= 0x88888888 & cnf;
			STM32_GPIO_BSRR(port) = pmask;
		} else if (flags & GPIO_PULL_DOWN) {
			mask |= 0x88888888 & cnf;
			STM32_GPIO_BSRR(port) = pmask << 16;
		} else {
			mask |= 0x44444444 & cnf;
		}
	}

	REG32(addr) = mask;

	if (flags & GPIO_OUTPUT) {
		/*
		 * Set pin level after port has been set up as to avoid
		 * potential damage, e.g. driving an open-drain output high
		 * before it has been configured as such.
		 */
		if (flags & GPIO_HIGH)
			STM32_GPIO_BSRR(port) = pmask;
		else if (flags & GPIO_LOW)
			STM32_GPIO_BSRR(port) = pmask << 16;
	}

	/* Set up interrupts if necessary */
	ASSERT(!(flags & (GPIO_INT_F_LOW | GPIO_INT_F_HIGH)));
	if (flags & GPIO_INT_F_RISING)
		STM32_EXTI_RTSR |= pmask;
	if (flags & GPIO_INT_F_FALLING)
		STM32_EXTI_FTSR |= pmask;
	/* Interrupt is enabled by gpio_enable_interrupt() */
}