dediprog: Enable 4BA support for SF600, protocol V2

The only combination we could successfully test so far is the SF600 with
protocol version V2 (firmware 7.2.21) and native 4BA commands. Let's
enable that at least.

Change-Id: I665d0806aec469a3509620a760815861fbe22841
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/28804
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: David Hendricks <david.hendricks@gmail.com>
diff --git a/dediprog.c b/dediprog.c
index c99c922..03675e5 100644
--- a/dediprog.c
+++ b/dediprog.c
@@ -360,8 +360,9 @@
 	return 0;
 }
 
-static void fill_rw_cmd_payload(uint8_t *data_packet, unsigned int count, uint8_t dedi_spi_cmd,
-		unsigned int *value, unsigned int *idx, unsigned int start, int is_read) {
+static void prepare_rw_cmd(
+		struct flashctx *const flash, uint8_t *data_packet, unsigned int count,
+		uint8_t dedi_spi_cmd, unsigned int *value, unsigned int *idx, unsigned int start, int is_read) {
 	/* First 5 bytes are common in both generations. */
 	data_packet[0] = count & 0xff;
 	data_packet[1] = (count >> 8) & 0xff;
@@ -370,6 +371,15 @@
 	data_packet[4] = 0; /* "Opcode". Specs imply necessity only for READ_MODE_4B_ADDR_FAST and WRITE_MODE_4B_ADDR_256B_PAGE_PGM */
 
 	if (protocol() >= PROTOCOL_V2) {
+		if (is_read && flash->chip->feature_bits & FEATURE_4BA_FAST_READ) {
+			data_packet[3] = READ_MODE_4B_ADDR_FAST_0x0C;
+			data_packet[4] = JEDEC_READ_4BA_FAST;
+		} else if (dedi_spi_cmd == WRITE_MODE_PAGE_PGM
+			   && (flash->chip->feature_bits & FEATURE_4BA_WRITE)) {
+			data_packet[3] = WRITE_MODE_4B_ADDR_256B_PAGE_PGM_0x12;
+			data_packet[4] = JEDEC_BYTE_PROGRAM_4BA;
+		}
+
 		*value = *idx = 0;
 		data_packet[5] = 0; /* RFU */
 		data_packet[6] = (start >>  0) & 0xff;
@@ -438,7 +448,7 @@
 
 	uint8_t data_packet[command_packet_size];
 	unsigned int value, idx;
-	fill_rw_cmd_payload(data_packet, count, READ_MODE_STD, &value, &idx, start, 1);
+	prepare_rw_cmd(flash, data_packet, count, READ_MODE_STD, &value, &idx, start, 1);
 
 	int ret = dediprog_write(CMD_READ, value, idx, data_packet, sizeof(data_packet));
 	if (ret != sizeof(data_packet)) {
@@ -594,7 +604,7 @@
 
 	uint8_t data_packet[command_packet_size];
 	unsigned int value, idx;
-	fill_rw_cmd_payload(data_packet, count, dedi_spi_cmd, &value, &idx, start, 0);
+	prepare_rw_cmd(flash, data_packet, count, dedi_spi_cmd, &value, &idx, start, 0);
 	int ret = dediprog_write(CMD_WRITE, value, idx, data_packet, sizeof(data_packet));
 	if (ret != sizeof(data_packet)) {
 		msg_perr("Command Write SPI Bulk failed, %s!\n", libusb_error_name(ret));
@@ -638,8 +648,8 @@
 	if (residue) {
 		msg_pdbg("Slow write for partial block from 0x%x, length 0x%x\n",
 			 start, residue);
-		/* No idea about the real limit. Maybe 12, maybe more. */
-		ret = spi_write_chunked(flash, buf, start, residue, 12);
+		/* No idea about the real limit. Maybe 16 including command and address, maybe more. */
+		ret = spi_write_chunked(flash, buf, start, residue, 11);
 		if (ret) {
 			dediprog_set_leds(LED_ERROR);
 			return ret;
@@ -659,7 +669,7 @@
 		msg_pdbg("Slow write for partial block from 0x%x, length 0x%x\n",
 			 start, len);
 		ret = spi_write_chunked(flash, buf + residue + bulklen,
-				        start + residue + bulklen, len, 12);
+				        start + residue + bulklen, len, 11);
 		if (ret) {
 			dediprog_set_leds(LED_ERROR);
 			return ret;
@@ -931,7 +941,7 @@
 	return millivolt;
 }
 
-static const struct spi_master spi_master_dediprog = {
+static struct spi_master spi_master_dediprog = {
 	.type		= SPI_CONTROLLER_DEDIPROG,
 	.features	= SPI_MASTER_NO_4BA_MODES,
 	.max_data_read	= 16, /* 18 seems to work fine as well, but 19 times out sometimes with FW 5.15. */
@@ -1124,6 +1134,9 @@
 	if (dediprog_standalone_mode())
 		return 1;
 
+	if (dediprog_devicetype == DEV_SF600 && protocol() == PROTOCOL_V2)
+		spi_master_dediprog.features |= SPI_MASTER_4BA;
+
 	if (register_spi_master(&spi_master_dediprog) || dediprog_set_leds(LED_NONE))
 		return 1;