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; }
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; } } } }
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; }
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; }
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; }
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(); }
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; }
/** * 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); }