in spi-zynqmp-gqspi.c [935:1075]
static int zynqmp_qspi_exec_op(struct spi_mem *mem,
const struct spi_mem_op *op)
{
struct zynqmp_qspi *xqspi = spi_controller_get_devdata
(mem->spi->master);
int err = 0, i;
u32 genfifoentry = 0;
u16 opcode = op->cmd.opcode;
u64 opaddr;
dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
op->dummy.buswidth, op->data.buswidth);
mutex_lock(&xqspi->op_lock);
zynqmp_qspi_config_op(xqspi, mem->spi);
zynqmp_qspi_chipselect(mem->spi, false);
genfifoentry |= xqspi->genfifocs;
genfifoentry |= xqspi->genfifobus;
if (op->cmd.opcode) {
reinit_completion(&xqspi->data_completion);
xqspi->txbuf = &opcode;
xqspi->rxbuf = NULL;
xqspi->bytes_to_transfer = op->cmd.nbytes;
xqspi->bytes_to_receive = 0;
zynqmp_qspi_write_op(xqspi, op->cmd.buswidth, genfifoentry);
zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
GQSPI_CFG_START_GEN_FIFO_MASK);
zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
GQSPI_IER_GENFIFOEMPTY_MASK |
GQSPI_IER_TXNOT_FULL_MASK);
if (!wait_for_completion_timeout
(&xqspi->data_completion, msecs_to_jiffies(1000))) {
err = -ETIMEDOUT;
goto return_err;
}
}
if (op->addr.nbytes) {
xqspi->txbuf = &opaddr;
for (i = 0; i < op->addr.nbytes; i++) {
*(((u8 *)xqspi->txbuf) + i) = op->addr.val >>
(8 * (op->addr.nbytes - i - 1));
}
reinit_completion(&xqspi->data_completion);
xqspi->rxbuf = NULL;
xqspi->bytes_to_transfer = op->addr.nbytes;
xqspi->bytes_to_receive = 0;
zynqmp_qspi_write_op(xqspi, op->addr.buswidth, genfifoentry);
zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
zynqmp_gqspi_read(xqspi,
GQSPI_CONFIG_OFST) |
GQSPI_CFG_START_GEN_FIFO_MASK);
zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
GQSPI_IER_TXEMPTY_MASK |
GQSPI_IER_GENFIFOEMPTY_MASK |
GQSPI_IER_TXNOT_FULL_MASK);
if (!wait_for_completion_timeout
(&xqspi->data_completion, msecs_to_jiffies(1000))) {
err = -ETIMEDOUT;
goto return_err;
}
}
if (op->dummy.nbytes) {
xqspi->txbuf = NULL;
xqspi->rxbuf = NULL;
/*
* xqspi->bytes_to_transfer here represents the dummy circles
* which need to be sent.
*/
xqspi->bytes_to_transfer = op->dummy.nbytes * 8 / op->dummy.buswidth;
xqspi->bytes_to_receive = 0;
/*
* Using op->data.buswidth instead of op->dummy.buswidth here because
* we need to use it to configure the correct SPI mode.
*/
zynqmp_qspi_write_op(xqspi, op->data.buswidth,
genfifoentry);
zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
GQSPI_CFG_START_GEN_FIFO_MASK);
}
if (op->data.nbytes) {
reinit_completion(&xqspi->data_completion);
if (op->data.dir == SPI_MEM_DATA_OUT) {
xqspi->txbuf = (u8 *)op->data.buf.out;
xqspi->rxbuf = NULL;
xqspi->bytes_to_transfer = op->data.nbytes;
xqspi->bytes_to_receive = 0;
zynqmp_qspi_write_op(xqspi, op->data.buswidth,
genfifoentry);
zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
zynqmp_gqspi_read
(xqspi, GQSPI_CONFIG_OFST) |
GQSPI_CFG_START_GEN_FIFO_MASK);
zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
GQSPI_IER_TXEMPTY_MASK |
GQSPI_IER_GENFIFOEMPTY_MASK |
GQSPI_IER_TXNOT_FULL_MASK);
} else {
xqspi->txbuf = NULL;
xqspi->rxbuf = (u8 *)op->data.buf.in;
xqspi->bytes_to_receive = op->data.nbytes;
xqspi->bytes_to_transfer = 0;
err = zynqmp_qspi_read_op(xqspi, op->data.buswidth,
genfifoentry);
if (err)
goto return_err;
zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
zynqmp_gqspi_read
(xqspi, GQSPI_CONFIG_OFST) |
GQSPI_CFG_START_GEN_FIFO_MASK);
if (xqspi->mode == GQSPI_MODE_DMA) {
zynqmp_gqspi_write
(xqspi, GQSPI_QSPIDMA_DST_I_EN_OFST,
GQSPI_QSPIDMA_DST_I_EN_DONE_MASK);
} else {
zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
GQSPI_IER_GENFIFOEMPTY_MASK |
GQSPI_IER_RXNEMPTY_MASK |
GQSPI_IER_RXEMPTY_MASK);
}
}
if (!wait_for_completion_timeout
(&xqspi->data_completion, msecs_to_jiffies(1000)))
err = -ETIMEDOUT;
}
return_err:
zynqmp_qspi_chipselect(mem->spi, true);
mutex_unlock(&xqspi->op_lock);
return err;
}