ch347_spi: Add 'spimode' parameter

This allows the SPI mode (clock polarity and phase) of the CH347 to be
selected. By default mode 0 is used, as most flash chips are compatible
with this mode. I have noticed that the CH347 is able to work at higher
clock speeds with some chips when set to mode 1, despite the chip not
officially having support for this configuration.

Change-Id: I7938519e23e9e014c016f9d7f130d1ac191a09fa
Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/244
Reviewed-by: Nico Huber <nico.h@gmx.de>
Tested-by: Nico Huber <nico.h@gmx.de>
diff --git a/ch347_spi.c b/ch347_spi.c
index 2b42077..7772fe0 100644
--- a/ch347_spi.c
+++ b/ch347_spi.c
@@ -202,7 +202,7 @@
 	return 0;
 }
 
-static int32_t ch347_spi_config(struct ch347_spi_data *ch347_data, uint8_t divisor)
+static int32_t ch347_spi_config(struct ch347_spi_data *ch347_data, uint8_t divisor, uint8_t mode)
 {
 	int32_t ret;
 	uint8_t buff[29] = {
@@ -215,9 +215,9 @@
 		[5] = 4,
 		[6] = 1,
 		/* Clock polarity: bit 1 */
-		[9] = 0,
+		[9] = mode & 2,
 		/* Clock phase: bit 0 */
-		[11] = 0,
+		[11] = mode & 1,
 		/* Another mystery byte */
 		[14] = 2,
 		/* Clock divisor: bits 5:3 */
@@ -295,6 +295,23 @@
 	} else {
 		msg_pdbg("Using default spispeed of %ukHz.\n", ch347_div_to_khz(div));
 	}
+	char *const spimode = extract_programmer_param("spimode");
+	uint8_t mode = 0;
+	if (spimode) {
+		char *endptr;
+		mode = strtoul(spimode, &endptr, 10);
+		if (*endptr != '\0' || endptr == spimode || mode > 3) {
+			msg_perr("Invalid `spimode` argument.\n");
+			free(spimode);
+			free(ch347_data);
+			return 1;
+		}
+		free(spimode);
+
+		msg_pinfo("Using spimode of %u.\n", mode);
+	} else {
+		msg_pdbg("Using default spimode of 0.\n");
+	}
 
 	int32_t ret = libusb_init(NULL);
 	if (ret < 0) {
@@ -373,7 +390,7 @@
 		(desc.bcdDevice >> 0) & 0x000F);
 
 	/* TODO: add programmer cfg for things like CS pin */
-	if (ch347_spi_config(ch347_data, div) < 0)
+	if (ch347_spi_config(ch347_data, div, mode) < 0)
 		goto error_exit;
 
 	return register_spi_master(&spi_master_ch347_spi, 0, ch347_data);
diff --git a/flashprog.8.tmpl b/flashprog.8.tmpl
index c8f35d7..0598b84 100644
--- a/flashprog.8.tmpl
+++ b/flashprog.8.tmpl
@@ -1335,6 +1335,13 @@
 and can be in the range 468 .. 60000. The frequency will be rounded down to
 a supported value (60 MHz divided by a power of 2). The default is a frequency
 of 7.5 MHz.
+The SPI mode can also be set using the spimode parameter:
+.sp
+.B "  flashprog \-p ch347_spi:spimode=mode"
+.sp
+where
+.B mode
+is in the range 0 to 3. The default is mode 0.
 .SS
 .BR "ni845x_spi " programmer
 .IP