static void completed(struct device *dev, int error) { const struct spi_dw_config *info = dev->config->config_info; struct spi_dw_data *spi = dev->driver_data; if (error) { goto out; } if (spi_context_tx_on(&spi->ctx) || spi_context_rx_on(&spi->ctx)) { return; } out: /* need to give time for FIFOs to drain before issuing more commands */ while (test_bit_sr_busy(info->regs)) { } /* Disabling interrupts */ write_imr(DW_SPI_IMR_MASK, info->regs); /* Disabling the controller */ clear_bit_ssienr(info->regs); spi_context_cs_control(&spi->ctx, false); LOG_DBG("SPI transaction completed %s error", error ? "with" : "without"); spi_context_complete(&spi->ctx, error); }
static void spi_stm32_complete(struct spi_stm32_data *data, SPI_TypeDef *spi, int status) { #ifdef CONFIG_SPI_STM32_INTERRUPT LL_SPI_DisableIT_TXE(spi); LL_SPI_DisableIT_RXNE(spi); LL_SPI_DisableIT_ERR(spi); #endif spi_context_cs_control(&data->ctx, false); #if defined(CONFIG_SOC_SERIES_STM32L4X) || defined(CONFIG_SOC_SERIES_STM32F3X) /* Flush RX buffer */ while (LL_SPI_IsActiveFlag_RXNE(spi)) { (void) LL_SPI_ReceiveData8(spi); } #endif if (LL_SPI_GetMode(spi) == LL_SPI_MODE_MASTER) { while (LL_SPI_IsActiveFlag_BSY(spi)) { /* NOP */ } } LL_SPI_Disable(spi); #ifdef CONFIG_SPI_STM32_INTERRUPT spi_context_complete(&data->ctx, status); #endif }
static int transceive(struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs, bool asynchronous, struct k_poll_signal *signal) { const struct spi_dw_config *info = dev->config->config_info; struct spi_dw_data *spi = dev->driver_data; u32_t tmod = DW_SPI_CTRLR0_TMOD_TX_RX; u32_t reg_data; int ret; spi_context_lock(&spi->ctx, asynchronous, signal); /* Configure */ ret = spi_dw_configure(info, spi, config); if (ret) { goto out; } if (!rx_bufs || !rx_bufs->buffers) { tmod = DW_SPI_CTRLR0_TMOD_TX; } else if (!tx_bufs || !tx_bufs->buffers) { tmod = DW_SPI_CTRLR0_TMOD_RX; } /* ToDo: add a way to determine EEPROM mode */ if (tmod >= DW_SPI_CTRLR0_TMOD_RX && !spi_dw_is_slave(spi)) { reg_data = spi_dw_compute_ndf(rx_bufs->buffers, rx_bufs->count, spi->dfs); if (reg_data == UINT32_MAX) { ret = -EINVAL; goto out; } write_ctrlr1(reg_data, info->regs); } else { write_ctrlr1(0, info->regs); } if (spi_dw_is_slave(spi)) { /* Enabling MISO line relevantly */ if (tmod == DW_SPI_CTRLR0_TMOD_RX) { tmod |= DW_SPI_CTRLR0_SLV_OE; } else { tmod &= ~DW_SPI_CTRLR0_SLV_OE; } } /* Updating TMOD in CTRLR0 register */ reg_data = read_ctrlr0(info->regs); reg_data &= ~DW_SPI_CTRLR0_TMOD_RESET; reg_data |= tmod; write_ctrlr0(reg_data, info->regs); /* Set buffers info */ spi_context_buffers_setup(&spi->ctx, tx_bufs, rx_bufs, spi->dfs); spi->fifo_diff = 0U; /* Tx Threshold */ spi_dw_update_txftlr(info, spi); /* Does Rx thresholds needs to be lower? */ reg_data = DW_SPI_RXFTLR_DFLT; if (spi_dw_is_slave(spi)) { if (spi->ctx.rx_len && spi->ctx.rx_len < DW_SPI_RXFTLR_DFLT) { reg_data = spi->ctx.rx_len - 1; } } else { if (spi->ctx.rx_len && spi->ctx.rx_len < DW_SPI_FIFO_DEPTH) { reg_data = spi->ctx.rx_len - 1; } } /* Rx Threshold */ write_rxftlr(reg_data, info->regs); /* Enable interrupts */ reg_data = !rx_bufs ? DW_SPI_IMR_UNMASK & DW_SPI_IMR_MASK_RX : DW_SPI_IMR_UNMASK; write_imr(reg_data, info->regs); spi_context_cs_control(&spi->ctx, true); LOG_DBG("Enabling controller"); set_bit_ssienr(info->regs); ret = spi_context_wait_for_completion(&spi->ctx); out: spi_context_release(&spi->ctx, ret); return ret; }