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/spi.c b/spi.c
index ac51d87..48e86ec 100644
--- a/spi.c
+++ b/spi.c
@@ -24,6 +24,7 @@
 #include "flashchips.h"
 #include "chipdrivers.h"
 #include "programmer.h"
+#include "spi_command.h"
 #include "spi.h"
 
 int spi_send_command(const struct flashctx *flash, unsigned int writecnt,
@@ -46,16 +47,15 @@
 {
 	struct spi_command cmd[] = {
 	{
-		.writecnt = writecnt,
-		.readcnt = readcnt,
+		.io_mode = SINGLE_IO_1_1_1,
+		.opcode_len = 1,
+		.address_len = writecnt - 1,
+		.read_len = readcnt,
 		.writearr = writearr,
 		.readarr = readarr,
-	}, {
-		.writecnt = 0,
-		.writearr = NULL,
-		.readcnt = 0,
-		.readarr = NULL,
-	}};
+	},
+		NULL_SPI_CMD
+	};
 
 	return spi_send_multicommand(flash, cmd);
 }
@@ -64,9 +64,12 @@
 				  struct spi_command *cmds)
 {
 	int result = 0;
-	for (; (cmds->writecnt || cmds->readcnt) && !result; cmds++) {
-		result = spi_send_command(flash, cmds->writecnt, cmds->readcnt,
-					  cmds->writearr, cmds->readarr);
+	for (; !spi_is_empty(cmds) && !result; cmds++) {
+		if (cmds->io_mode != SINGLE_IO_1_1_1)
+			return SPI_FLASHPROG_BUG;
+		result = spi_send_command(flash,
+				spi_write_len(cmds), spi_read_len(cmds),
+				cmds->writearr, cmds->readarr);
 	}
 	return result;
 }