Example #1
0
static void completed(struct device *dev, int error)
{
	struct spi_dw_config *info = dev->config->config_info;
	struct spi_dw_data *spi = dev->driver_data;

	if (error) {
		goto out;
	}

	if (spi->fifo_diff ||
	    !((spi->tx_buf && !spi->tx_buf_len && !spi->rx_buf) ||
	      (spi->rx_buf && !spi->rx_buf_len && !spi->tx_buf) ||
	      (spi->tx_buf && !spi->tx_buf_len &&
				spi->rx_buf && !spi->rx_buf_len))) {
		return;
	}

out:
	spi->error = error;

	/* Disabling interrupts */
	write_imr(DW_SPI_IMR_MASK, info->regs);
	/* Disabling the controller */
	clear_bit_ssienr(info->regs);

	_spi_control_cs(dev, 0);

	DBG("SPI transaction completed %s error\n",
	    error ? "with" : "without");

	device_sync_call_complete(&spi->sync);
}
Example #2
0
int spi_dw_init(struct device *dev)
{
	struct spi_dw_config *info = dev->config->config_info;
	struct spi_dw_data *spi = dev->driver_data;

	_clock_config(dev);
	_clock_on(dev);

#ifndef CONFIG_SOC_QUARK_SE_SS
	if (read_ssi_comp_version(info->regs) != DW_SSI_COMP_VERSION) {
		_clock_off(dev);
		return DEV_NOT_CONFIG;
	}
#endif

	dev->driver_api = &dw_spi_api;

	info->config_func();

	device_sync_call_init(&spi->sync);

	_spi_config_cs(dev);

	/* Masking interrupt and making sure controller is disabled */
	write_imr(DW_SPI_IMR_MASK, info->regs);
	clear_bit_ssienr(info->regs);

	DBG("Designware SPI driver initialized on device: %p\n", dev);

	return DEV_OK;
}
Example #3
0
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);
}
Example #4
0
static int spi_dw_transceive(struct device *dev,
			     const void *tx_buf, uint32_t tx_buf_len,
			     void *rx_buf, uint32_t rx_buf_len)
{
	struct spi_dw_config *info = dev->config->config_info;
	struct spi_dw_data *spi = dev->driver_data;
	uint32_t rx_thsld = DW_SPI_RXFTLR_DFLT;

	DBG("%s: %p, %p, %u, %p, %u\n",
	    __func__, dev, tx_buf, tx_buf_len, rx_buf, rx_buf_len);

	/* Check status */
	if (!_spi_dw_is_controller_ready(dev)) {
		DBG("%s: Controller is busy\n", __func__);
		return DEV_USED;
	}

	/* Set buffers info */
	spi->tx_buf = tx_buf;
	spi->tx_buf_len = tx_buf_len/spi->dfs;
	spi->rx_buf = rx_buf;
	spi->rx_buf_len = rx_buf_len/spi->dfs;
	spi->fifo_diff = 0;

	/* Tx Threshold, always at default */
	write_txftlr(DW_SPI_TXFTLR_DFLT, info->regs);

	/* Does Rx thresholds needs to be lower? */
	if (rx_buf_len && spi->rx_buf_len < DW_SPI_FIFO_DEPTH) {
		rx_thsld = spi->rx_buf_len - 1;
	} else if (!rx_buf_len && spi->tx_buf_len < DW_SPI_FIFO_DEPTH) {
		rx_thsld = spi->tx_buf_len - 1;
	}

	write_rxftlr(rx_thsld, info->regs);

	/* Slave select */
	write_ser(spi->slave, info->regs);

	_spi_control_cs(dev, 1);

	/* Enable interrupts */
	write_imr(DW_SPI_IMR_UNMASK, info->regs);

	/* Enable the controller */
	set_bit_ssienr(info->regs);

	device_sync_call_wait(&spi->sync);

	if (spi->error) {
		spi->error = 0;
		return DEV_FAIL;
	}

	return DEV_OK;
}
Example #5
0
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;
	}

	/*
	* There are several situations here.
	* 1. spi_write w rx_buf - need last_tx && rx_buf_len zero to be done.
	* 2. spi_write w/o rx_buf - only need to determine when write is done.
	* 3. spi_read - need rx_buf_len zero.
	*/
	if (spi->tx_buf && spi->rx_buf) {
		if (!spi->last_tx || spi->rx_buf_len) {
			return;
		}
	} else if (spi->tx_buf) {
		if (!spi->last_tx) {
			return;
		}
	} else { /* or, spi->rx_buf!=0 */
		if (spi->rx_buf_len) {
			return;
		}
	}

out:
	/* need to give time for FIFOs to drain before issuing more commands */
	while (test_bit_sr_busy(info->regs)) {
	}

	spi->error = error;

	/* Disabling interrupts */
	write_imr(DW_SPI_IMR_MASK, info->regs);
	/* Disabling the controller */
	clear_bit_ssienr(info->regs);

	_spi_control_cs(dev, 0);

	SYS_LOG_DBG("SPI transaction completed %s error",
		    error ? "with" : "without");

	k_sem_give(&spi->device_sync_sem);
}
Example #6
0
int spi_dw_init(struct device *dev)
{
	const struct spi_dw_config *info = dev->config->config_info;
	struct spi_dw_data *spi = dev->driver_data;

	_clock_config(dev);
	_clock_on(dev);

	info->config_func();

	/* Masking interrupt and making sure controller is disabled */
	write_imr(DW_SPI_IMR_MASK, info->regs);
	clear_bit_ssienr(info->regs);

	LOG_DBG("Designware SPI driver initialized on device: %p", dev);

	spi_context_unlock_unconditionally(&spi->ctx);

	return 0;
}
Example #7
0
int spi_dw_init(struct device *dev)
{
	const struct spi_dw_config *info = dev->config->config_info;
	struct spi_dw_data *spi = dev->driver_data;

	_clock_config(dev);
	_clock_on(dev);

	info->config_func();

	k_sem_init(&spi->device_sync_sem, 0, UINT_MAX);

	_spi_config_cs(dev);

	/* Masking interrupt and making sure controller is disabled */
	write_imr(DW_SPI_IMR_MASK, info->regs);
	clear_bit_ssienr(info->regs);

	SYS_LOG_DBG("Designware SPI driver initialized on device: %p", dev);

	return 0;
}
Example #8
0
static int spi_dw_transceive(struct device *dev,
			     const void *tx_buf, u32_t tx_buf_len,
			     void *rx_buf, u32_t rx_buf_len)
{
	const struct spi_dw_config *info = dev->config->config_info;
	struct spi_dw_data *spi = dev->driver_data;
	u32_t rx_thsld = DW_SPI_RXFTLR_DFLT;
	u32_t imask;

	SYS_LOG_DBG("%p, %p, %u, %p, %u",
		    dev, tx_buf, tx_buf_len, rx_buf, rx_buf_len);

	/* Check status */
	if (!_spi_dw_is_controller_ready(dev)) {
		SYS_LOG_DBG("Controller is busy");
		return -EBUSY;
	}

	/* Set buffers info */
	spi->tx_buf = tx_buf;
	spi->tx_buf_len = tx_buf_len/spi->dfs;
	spi->rx_buf = rx_buf;
	if (rx_buf) {
		spi->rx_buf_len = rx_buf_len/spi->dfs;
	} else {
		spi->rx_buf_len = 0; /* must be zero if no buffer */
	}
	spi->fifo_diff = 0;
	spi->last_tx = 0;

	/* Tx Threshold */
	write_txftlr(DW_SPI_TXFTLR_DFLT, info->regs);

	/* Does Rx thresholds needs to be lower? */
	if (spi->rx_buf_len && spi->rx_buf_len < DW_SPI_FIFO_DEPTH) {
		rx_thsld = spi->rx_buf_len - 1;
	} else if (!spi->rx_buf_len && spi->tx_buf_len < DW_SPI_FIFO_DEPTH) {
		rx_thsld = spi->tx_buf_len - 1;
		/* TODO: why? */
	}

	write_rxftlr(rx_thsld, info->regs);

	/* Slave select */
	write_ser(spi->slave, info->regs);

	_spi_control_cs(dev, 1);

	/* Enable interrupts */
	imask = DW_SPI_IMR_UNMASK;
	if (!rx_buf) {
		/* if there is no rx buffer, keep all rx interrupts masked */
		imask &= DW_SPI_IMR_MASK_RX;
	}

	write_imr(imask, info->regs);

	/* Enable the controller */
	set_bit_ssienr(info->regs);

	k_sem_take(&spi->device_sync_sem, K_FOREVER);

	if (spi->error) {
		spi->error = 0;
		return -EIO;
	}

	return 0;
}
Example #9
0
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;
}