Пример #1
0
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
static void i2c_event_handler(int port)
{
	/* save and clear status */
	i2c_sr1[port] = STM32_I2C_SR1(port);
	STM32_I2C_SR1(port) = 0;

	/* Confirm that you are not in master mode */
	if (STM32_I2C_SR2(port) & (1 << 0)) {
		CPRINTS("slave ISR triggered in master mode, ignoring");
		return;
	}

	/* transfer matched our slave address */
	if (i2c_sr1[port] & (1 << 1)) {
		/* If it's a receiver slave */
		if (!(STM32_I2C_SR2(port) & (1 << 2))) {
			dma_start_rx(dma_rx_option + port, sizeof(host_buffer),
				     host_buffer);

			STM32_I2C_CR2(port) |= (1 << 11);
			rx_pending = 1;
		}

		/* cleared by reading SR1 followed by reading SR2 */
		STM32_I2C_SR1(port);
		STM32_I2C_SR2(port);
	} else if (i2c_sr1[port] & (1 << 4)) {
		/* If it's a receiver slave */
		if (!(STM32_I2C_SR2(port) & (1 << 2))) {
			/* Disable, and clear the DMA transfer complete flag */
			dma_disable(DMAC_SLAVE_RX);
			dma_clear_isr(DMAC_SLAVE_RX);

			/* Turn off i2c's DMA flag */
			STM32_I2C_CR2(port) &= ~(1 << 11);
		}
		/* clear STOPF bit by reading SR1 and then writing CR1 */
		STM32_I2C_SR1(port);
		STM32_I2C_CR1(port) = STM32_I2C_CR1(port);
	}

	/* TxE event */
	if (i2c_sr1[port] & (1 << 7)) {
		if (port == I2C2) { /* AP is waiting for EC response */
			if (rx_pending) {
				i2c_process_command();
				/* reset host buffer after end of transfer */
				rx_pending = 0;
			} else {
				/* spurious read : return dummy value */
				STM32_I2C_DR(port) = 0xec;
			}
		}
	}
}
Пример #3
0
int adc_read_all_channels(int *data)
{
	int i;
	uint32_t channels = 0;
	uint32_t raw_data[ADC_CH_COUNT];
	const struct adc_t *adc;
	int restore_watchdog = 0;
	int ret = EC_SUCCESS;

	mutex_lock(&adc_lock);

	if (adc_watchdog_enabled()) {
		restore_watchdog = 1;
		adc_disable_watchdog_no_lock();
	}

	/* Select all used channels */
	for (i = 0; i < ADC_CH_COUNT; ++i)
		channels |= 1 << adc_channels[i].channel;
	STM32_ADC_CHSELR = channels;

	/* Enable DMA */
	STM32_ADC_CFGR1 |= 0x1;

	dma_clear_isr(STM32_DMAC_ADC);
	dma_start_rx(&dma_adc_option, ADC_CH_COUNT, raw_data);

	/* Clear flags */
	STM32_ADC_ISR = 0xe;

	STM32_ADC_CR |= 1 << 2; /* ADSTART */

	if (dma_wait(STM32_DMAC_ADC)) {
		ret = EC_ERROR_UNKNOWN;
		goto fail; /* goto fail; goto fail; */
	}

	for (i = 0; i < ADC_CH_COUNT; ++i) {
		adc = adc_channels + i;
		data[i] = (raw_data[i] & 0xffff) *
			   adc->factor_mul / adc->factor_div + adc->shift;
	}

fail:
	if (restore_watchdog)
		adc_enable_watchdog_no_lock();
	mutex_unlock(&adc_lock);
	return ret;
}
Пример #4
0
static int spi_master_read_write_byte(uint8_t *in_buf, uint8_t *out_buf, int sz)
{
	int ret;

	dma_start_rx(&dma_rx_option, sz, in_buf);
	dma_prepare_tx(&dma_tx_option, sz, out_buf);
	dma_go(dma_get_channel(STM32_DMAC_SPI1_TX));
	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);

	return ret;
}
Пример #5
0
int adc_read_all_channels(int *data)
{
	int i;
	int16_t raw_data[ADC_CH_COUNT];
	const struct adc_t *adc;
	int restore_watchdog = 0;
	int ret = EC_SUCCESS;

	if (!adc_powered())
		return EC_ERROR_UNKNOWN;

	mutex_lock(&adc_lock);

	if (adc_watchdog_enabled()) {
		restore_watchdog = 1;
		adc_disable_watchdog_no_lock();
	}

	adc_configure_all();

	dma_clear_isr(STM32_DMAC_ADC);
	dma_start_rx(&dma_adc_option, ADC_CH_COUNT, raw_data);

	/* Start conversion */
	STM32_ADC_CR2 |= (1 << 0); /* ADON */

	if (dma_wait(STM32_DMAC_ADC)) {
		ret = EC_ERROR_UNKNOWN;
		goto exit_all_channels;
	}

	for (i = 0; i < ADC_CH_COUNT; ++i) {
		adc = adc_channels + i;
		data[i] = raw_data[i] * adc->factor_mul / adc->factor_div +
			  adc->shift;
	}

exit_all_channels:
	dma_disable(STM32_DMAC_ADC);

	if (restore_watchdog)
		adc_enable_watchdog_no_lock();

	mutex_unlock(&adc_lock);
	return ret;
}
Пример #6
0
static void spi_nss_interrupt(void)
{
	const struct spi_comm_packet *cmd =
		(const struct spi_comm_packet *)in_msg;
	stm32_spi_regs_t *spi = STM32_SPI1_REGS;

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

	master_slave_sync(5);

	/* Read in the packet size */
	while (!(spi->sr & STM32_SPI_SR_RXNE))
		;
	in_msg[0] = spi->dr;

	/* Read in the rest of the packet */
	dma_clear_isr(STM32_DMAC_SPI1_RX);
	dma_start_rx(&dma_rx_option, in_msg[0] + SPI_PACKET_HEADER_SIZE - 1,
		     in_msg + 1);
	dma_prepare_tx(&dma_tx_option, in_msg[0] + SPI_PACKET_HEADER_SIZE - 1,
		       out_msg);
	dma_go(dma_get_channel(STM32_DMAC_SPI1_TX));

	master_slave_sync(5);

	if (dma_wait(STM32_DMAC_SPI1_RX) != EC_SUCCESS) {
		debug_printf("SPI: Incomplete packet\n");
		spi_slave_nack();
		return;
	}
	if (spi->sr & STM32_SPI_SR_CRCERR) {
		debug_printf("SPI: CRC mismatch\n");
		spi_slave_nack();
		return;
	}

	if (cmd->cmd_sts == TS_CMD_HELLO)
		spi_slave_hello_back(cmd);
	else if (cmd->cmd_sts == TS_CMD_FULL_SCAN)
		touch_scan_slave_start();
	else
		spi_slave_nack();
}
Пример #7
0
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;
}
Пример #8
0
Файл: spi.c Проект: longsleep/ec
/**
 * Get ready to receive a message from the master.
 *
 * Set up our RX DMA and disable our TX DMA. Set up the data output so that
 * we will send preamble bytes.
 */
static void setup_for_transaction(void)
{
	stm32_spi_regs_t *spi = STM32_SPI1_REGS;
	volatile uint8_t dummy __attribute__((unused));

	/* clear this as soon as possible */
	setup_transaction_later = 0;

	/* Not ready to receive yet */
	tx_status(EC_SPI_NOT_READY);

	/* We are no longer actively processing a transaction */
	state = SPI_STATE_PREPARE_RX;

	/* Stop sending response, if any */
	dma_disable(STM32_DMAC_SPI1_TX);

	/*
	 * Read dummy bytes in case there are some pending; this prevents the
	 * receive DMA from getting that byte right when we start it.
	 */
	dummy = spi->dr;
#ifdef CHIP_FAMILY_STM32F0
	/* 4 Bytes makes sure the RX FIFO on the F0 is empty as well. */
	dummy = spi->dr;
	dummy = spi->dr;
	dummy = spi->dr;
#endif

	/* Start DMA */
	dma_start_rx(&dma_rx_option, sizeof(in_msg), in_msg);

	/* Ready to receive */
	state = SPI_STATE_READY_TO_RX;
	tx_status(EC_SPI_OLD_READY);
}