spi: Prepare for multi i/o and dummy bytes
Multi-i/o commands split SPI transactions into multiple phases that
can be transferred over 1, 2 or 4 wires. For this, we adapt `struct
spi_command` with a new enum, specifying the transfer mode, and ad-
ditional size fields. While we are at it, move everything related
into a new header file `spi_command.h` so we won't further clutter
`flash.h`.
On the master side, we add respective feature flags for the multi-
i/o modes.
See also the comment in `spi_command.h` about multi-i/o commands.
Change-Id: I79debb845f1c8fec77e0556853ffb01735e73ab8
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/44
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/ft2232_spi.c b/ft2232_spi.c
index 889db98..a82153d 100644
--- a/ft2232_spi.c
+++ b/ft2232_spi.c
@@ -22,6 +22,7 @@
#include <ctype.h>
#include "flash.h"
#include "programmer.h"
+#include "spi_command.h"
#include "spi.h"
#include <ftdi.h>
@@ -206,9 +207,9 @@
/* commands for CS# assertion and de-assertion: */
cmd_len + cmd_len
/* commands for either a write, a read or both: */
- + (cmd->writecnt && cmd->readcnt ? cmd_len + cmd_len : cmd_len)
+ + (spi_write_len(cmd) && spi_read_len(cmd) ? cmd_len + cmd_len : cmd_len)
/* payload (only writecnt; readcnt concerns another buffer): */
- + cmd->writecnt
+ + spi_write_len(cmd)
<= buffer_size;
}
@@ -224,9 +225,11 @@
/*
* Minimize FTDI-calls by packing as many commands as possible together.
*/
- for (; cmds->writecnt || cmds->readcnt; cmds++) {
+ for (; !spi_is_empty(cmds); cmds++) {
+ const size_t writecnt = spi_write_len(cmds);
+ const size_t readcnt = spi_read_len(cmds);
- if (cmds->writecnt > 65536 || cmds->readcnt > 65536)
+ if (writecnt > 65536 || readcnt > 65536)
return SPI_INVALID_LENGTH;
if (!ft2232_spi_command_fits(cmds, FTDI_HW_BUFFER_SIZE - i)) {
@@ -241,19 +244,19 @@
buf[i++] = spi_data->pindir;
/* WREN, OP(PROGRAM, ERASE), ADDR, DATA */
- if (cmds->writecnt) {
+ if (writecnt) {
buf[i++] = MPSSE_DO_WRITE | MPSSE_WRITE_NEG;
- buf[i++] = (cmds->writecnt - 1) & 0xff;
- buf[i++] = ((cmds->writecnt - 1) >> 8) & 0xff;
- memcpy(buf + i, cmds->writearr, cmds->writecnt);
- i += cmds->writecnt;
+ buf[i++] = (writecnt - 1) & 0xff;
+ buf[i++] = ((writecnt - 1) >> 8) & 0xff;
+ memcpy(buf + i, cmds->writearr, writecnt);
+ i += writecnt;
}
/* An optional read command */
- if (cmds->readcnt) {
+ if (readcnt) {
buf[i++] = MPSSE_DO_READ;
- buf[i++] = (cmds->readcnt - 1) & 0xff;
- buf[i++] = ((cmds->readcnt - 1) >> 8) & 0xff;
+ buf[i++] = (readcnt - 1) & 0xff;
+ buf[i++] = ((readcnt - 1) >> 8) & 0xff;
}
/* Add final de-assert CS# */
@@ -263,8 +266,7 @@
buf[i++] = spi_data->pindir;
/* continue if there is no read-cmd and further cmds exist */
- if (!cmds->readcnt &&
- ((cmds + 1)->writecnt || (cmds + 1)->readcnt) &&
+ if (!readcnt && !spi_is_empty(cmds + 1) &&
ft2232_spi_command_fits((cmds + 1), FTDI_HW_BUFFER_SIZE - i)) {
continue;
}
@@ -276,8 +278,8 @@
break;
}
- if (cmds->readcnt) {
- ret = get_buf(ftdic, cmds->readarr, cmds->readcnt);
+ if (readcnt) {
+ ret = get_buf(ftdic, cmds->readarr, readcnt);
if (ret) {
msg_perr("get_buf failed: %i\n", ret);
break;