From: Jagan Teki <jagan@amarulasolutions.com>
To: u-boot@lists.denx.de
Subject: [PATCH 1/3] spi: spi-mem: Xfer opcode alone for non spi-mem
Date: Mon, 20 Apr 2020 17:39:19 +0530 [thread overview]
Message-ID: <20200420120921.12840-2-jagan@amarulasolutions.com> (raw)
In-Reply-To: <20200420120921.12840-1-jagan@amarulasolutions.com>
Some of the SPI controllers have a special set of format
registers that defines how the transfer initiated to the
FIFO by means of I/O protocol lines.
Each mode of transfer from slave would be required to configure
the I/O protocol lines so-that the master would identify how
many number I/O protocol lines were used and alter the protocol
bits on the controller.
If a particular transfer combined opcode and address together,
then it would be difficult for the master to identify how many
I/O protocol lines are being used for opcode and address separately.
For example a transfer of SNOR_1_4_4 is not possible to identify
the master that how many I/O protocol lines by spi-nor if that
particular transfer initites the single xfer for both opcode and
address.
To address this issue (on these kind of SPI controllers) this
patch is trying to send the opcode alone as both opcode and
address send together in current code.
On the performance note there is no significant issue on the
transfer rate for adding this opcode xfer separately.
Sample test on 32MiB flash used in SiFive platform with
PP and RF opcodes.
With existing code:
=> sf update 0x90000000 0x0 0x2000000
device 0 whole chip
33554432 bytes written, 0 bytes skipped in 543.795s, speed 63191 B/s
With opcode alone xfer:
=> sf update 0x90000000 0x0 0x2000000
device 0 whole chip
33554432 bytes written, 0 bytes skipped in 541.739s, speed 63429 B/s
Signed-off-by: Suneel Garapati <suneelglinux@gmail.com>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
drivers/spi/spi-mem.c | 63 ++++++++++++++++++++++++++-----------------
1 file changed, 38 insertions(+), 25 deletions(-)
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index e900c997bd..7f4039e856 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -336,15 +336,18 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
if (msg.actual_length != totalxferlen)
return -EIO;
#else
+ u8 opcode = op->cmd.opcode;
- if (op->data.nbytes) {
- if (op->data.dir == SPI_MEM_DATA_IN)
- rx_buf = op->data.buf.in;
- else
- tx_buf = op->data.buf.out;
- }
+ flag = SPI_XFER_BEGIN;
+ if (!op->addr.nbytes && !op->dummy.nbytes && !op->data.nbytes)
+ flag |= SPI_XFER_END;
- op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
+ /* send the opcode */
+ ret = spi_xfer(slave, 8, (void *)&opcode, NULL, flag);
+ if (ret < 0) {
+ dev_err(slave->dev, "failed to xfer opcode\n");
+ return ret;
+ }
/*
* Avoid using malloc() here so that we can use this code in SPL where
@@ -355,41 +358,51 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
* data being sent, only the op-code and address. In fact, it should be
* possible to just use a small fixed value here instead of op_len.
*/
+ op_len = op->addr.nbytes + op->dummy.nbytes;
u8 op_buf[op_len];
- op_buf[pos++] = op->cmd.opcode;
-
+ /* send the addr + dummy */
if (op->addr.nbytes) {
+ /* fill address */
for (i = 0; i < op->addr.nbytes; i++)
op_buf[pos + i] = op->addr.val >>
(8 * (op->addr.nbytes - i - 1));
pos += op->addr.nbytes;
- }
- if (op->dummy.nbytes)
- memset(op_buf + pos, 0xff, op->dummy.nbytes);
+ /* fill dummy */
+ if (op->dummy.nbytes)
+ memset(op_buf + pos, 0xff, op->dummy.nbytes);
- /* 1st transfer: opcode + address + dummy cycles */
- flag = SPI_XFER_BEGIN;
- /* Make sure to set END bit if no tx or rx data messages follow */
- if (!tx_buf && !rx_buf)
- flag |= SPI_XFER_END;
+ /* make sure to set end flag, if no data bytes */
+ if (!op->data.nbytes)
+ flag |= SPI_XFER_END;
- ret = spi_xfer(slave, op_len * 8, op_buf, NULL, flag);
- if (ret)
- return ret;
+ ret = spi_xfer(slave, op_len * 8, op_buf, NULL, flag);
+ if (ret < 0) {
+ dev_err(slave->dev, "failed to xfer addr + dummy\n");
+ return ret;
+ }
+ }
- /* 2nd transfer: rx or tx data path */
- if (tx_buf || rx_buf) {
- ret = spi_xfer(slave, op->data.nbytes * 8, tx_buf,
- rx_buf, SPI_XFER_END);
- if (ret)
+ /* send/received the data */
+ if (op->data.nbytes) {
+ if (op->data.dir == SPI_MEM_DATA_IN)
+ rx_buf = op->data.buf.in;
+ else
+ tx_buf = op->data.buf.out;
+
+ ret = spi_xfer(slave, op->data.nbytes * 8, tx_buf, rx_buf,
+ SPI_XFER_END);
+ if (ret) {
+ dev_err(slave->dev, "failed to xfer data\n");
return ret;
+ }
}
spi_release_bus(slave);
+ debug("%02x ", op->cmd.opcode);
for (i = 0; i < pos; i++)
debug("%02x ", op_buf[i]);
debug("| [%dB %s] ",
--
2.17.1
next prev parent reply other threads:[~2020-04-20 12:09 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-20 12:09 [PATCH 0/3] spi: Support SPI I/O protocol lines Jagan Teki
2020-04-20 12:09 ` Jagan Teki [this message]
2020-04-20 12:09 ` [PATCH 2/3] " Jagan Teki
2020-04-20 12:09 ` [PATCH 3/3] spi: sifive: Fix format register proto field Jagan Teki
2020-04-20 23:14 ` Bin Meng
2020-04-21 15:47 ` Sagar Kadam
2020-04-23 17:05 ` Jagan Teki
2020-04-21 7:19 ` [PATCH 0/3] spi: Support SPI I/O protocol lines Vignesh Raghavendra
2020-04-21 8:08 ` Jagan Teki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200420120921.12840-2-jagan@amarulasolutions.com \
--to=jagan@amarulasolutions.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox