diff options
-rw-r--r-- | drivers/spi/atmel-quadspi.c | 6 | ||||
-rw-r--r-- | drivers/spi/spi-mem.c | 16 | ||||
-rw-r--r-- | drivers/spi/spi-mtk-nor.c | 10 | ||||
-rw-r--r-- | drivers/spi/spi-mxic.c | 3 | ||||
-rw-r--r-- | drivers/spi/spi-zynq-qspi.c | 11 | ||||
-rw-r--r-- | include/linux/spi/spi-mem.h | 14 |
6 files changed, 45 insertions, 15 deletions
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index cb44d1e169aa..a898755fb41e 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -285,6 +285,12 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem, op->dummy.nbytes == 0) return false; + /* DTR ops not supported. */ + if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) + return false; + if (op->cmd.nbytes != 1) + return false; + return true; } diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 9a86cc27fcc0..ef53290b7d24 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -156,6 +156,12 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, op->data.dir == SPI_MEM_DATA_OUT)) return false; + if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) + return false; + + if (op->cmd.nbytes != 1) + return false; + return true; } EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); @@ -170,7 +176,7 @@ static bool spi_mem_buswidth_is_valid(u8 buswidth) static int spi_mem_check_op(const struct spi_mem_op *op) { - if (!op->cmd.buswidth) + if (!op->cmd.buswidth || !op->cmd.nbytes) return -EINVAL; if ((op->addr.nbytes && !op->addr.buswidth) || @@ -306,8 +312,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) return ret; } - tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes + - op->dummy.nbytes; + tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; /* * Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so @@ -322,7 +327,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) tmpbuf[0] = op->cmd.opcode; xfers[xferpos].tx_buf = tmpbuf; - xfers[xferpos].len = sizeof(op->cmd.opcode); + xfers[xferpos].len = op->cmd.nbytes; xfers[xferpos].tx_nbits = op->cmd.buswidth; spi_message_add_tail(&xfers[xferpos], &msg); xferpos++; @@ -424,8 +429,7 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) return ctlr->mem_ops->adjust_op_size(mem, op); if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) { - len = sizeof(op->cmd.opcode) + op->addr.nbytes + - op->dummy.nbytes; + len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; if (len > spi_max_transfer_size(mem->spi)) return -EINVAL; diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index 7bc302b50396..b08d8e9a8ee9 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -195,7 +195,7 @@ static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) } } - len = MTK_NOR_PRG_MAX_SIZE - sizeof(op->cmd.opcode) - op->addr.nbytes - + len = MTK_NOR_PRG_MAX_SIZE - op->cmd.nbytes - op->addr.nbytes - op->dummy.nbytes; if (op->data.nbytes > len) op->data.nbytes = len; @@ -211,6 +211,12 @@ static bool mtk_nor_supports_op(struct spi_mem *mem, if (op->cmd.buswidth != 1) return false; + /* DTR ops not supported. */ + if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) + return false; + if (op->cmd.nbytes != 1) + return false; + if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) { if ((op->data.dir == SPI_MEM_DATA_IN) && mtk_nor_match_read(op)) return true; @@ -219,7 +225,7 @@ static bool mtk_nor_supports_op(struct spi_mem *mem, (op->dummy.buswidth == 0) && (op->data.buswidth == 1); } - len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; + len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; if ((len > MTK_NOR_PRG_MAX_SIZE) || ((op->data.nbytes) && (len == MTK_NOR_PRG_MAX_SIZE))) return false; diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c index 69491f3a515d..8c630acb0110 100644 --- a/drivers/spi/spi-mxic.c +++ b/drivers/spi/spi-mxic.c @@ -356,6 +356,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, int nio = 1, i, ret; u32 ss_ctrl; u8 addr[8]; + u8 opcode = op->cmd.opcode; ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz); if (ret) @@ -393,7 +394,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT, mxic->regs + HC_CFG); - ret = mxic_spi_data_xfer(mxic, &op->cmd.opcode, NULL, 1); + ret = mxic_spi_data_xfer(mxic, &opcode, NULL, 1); if (ret) goto out; diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index 17641157354d..bbf3d90561f5 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -527,20 +527,21 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem, struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->master); int err = 0, i; u8 *tmpbuf; + u8 opcode = op->cmd.opcode; dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n", - op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, + opcode, op->cmd.buswidth, op->addr.buswidth, op->dummy.buswidth, op->data.buswidth); zynq_qspi_chipselect(mem->spi, true); zynq_qspi_config_op(xqspi, mem->spi); - if (op->cmd.opcode) { + if (op->cmd.nbytes) { reinit_completion(&xqspi->data_completion); - xqspi->txbuf = (u8 *)&op->cmd.opcode; + xqspi->txbuf = &opcode; xqspi->rxbuf = NULL; - xqspi->tx_bytes = sizeof(op->cmd.opcode); - xqspi->rx_bytes = sizeof(op->cmd.opcode); + xqspi->tx_bytes = op->cmd.nbytes; + xqspi->rx_bytes = op->cmd.nbytes; zynq_qspi_write_op(xqspi, ZYNQ_QSPI_FIFO_DEPTH, true); zynq_qspi_write(xqspi, ZYNQ_QSPI_IEN_OFFSET, ZYNQ_QSPI_IXR_RXTX_MASK); diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index af9ff2f0f1b2..159463cc659c 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -17,6 +17,7 @@ { \ .buswidth = __buswidth, \ .opcode = __opcode, \ + .nbytes = 1, \ } #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth) \ @@ -69,11 +70,15 @@ enum spi_mem_data_dir { /** * struct spi_mem_op - describes a SPI memory operation + * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is + * sent MSB-first. * @cmd.buswidth: number of IO lines used to transmit the command * @cmd.opcode: operation opcode + * @cmd.dtr: whether the command opcode should be sent in DTR mode or not * @addr.nbytes: number of address bytes to send. Can be zero if the operation * does not need to send an address * @addr.buswidth: number of IO lines used to transmit the address cycles + * @addr.dtr: whether the address should be sent in DTR mode or not * @addr.val: address value. This value is always sent MSB first on the bus. * Note that only @addr.nbytes are taken into account in this * address value, so users should make sure the value fits in the @@ -81,7 +86,9 @@ enum spi_mem_data_dir { * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can * be zero if the operation does not require dummy bytes * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes + * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not * @data.buswidth: number of IO lanes used to send/receive the data + * @data.dtr: whether the data should be sent in DTR mode or not * @data.dir: direction of the transfer * @data.nbytes: number of data bytes to send/receive. Can be zero if the * operation does not involve transferring data @@ -90,23 +97,28 @@ enum spi_mem_data_dir { */ struct spi_mem_op { struct { + u8 nbytes; u8 buswidth; - u8 opcode; + u8 dtr : 1; + u16 opcode; } cmd; struct { u8 nbytes; u8 buswidth; + u8 dtr : 1; u64 val; } addr; struct { u8 nbytes; u8 buswidth; + u8 dtr : 1; } dummy; struct { u8 buswidth; + u8 dtr : 1; enum spi_mem_data_dir dir; unsigned int nbytes; union { |