From 25a5bceb930b6db3f29b1af58133ebbd8ea5f85c Mon Sep 17 00:00:00 2001
From: Alan Green <avg@google.com>
Date: Fri, 8 Jan 2021 09:36:45 +1100
Subject: ft2232_spi.c: release I/Os on shutdown

Reset FTDI I/O pins to high-Z (input) when shutting down. This allows
other devices to use the SPI bus without having to disconnect the
programmer.

This change will introduce a backward incompatibility in the case where
a user is relying on the state of FTDI outputs post-programming (eg. to
disallow another device from driving CS low).

However, there are likely more cases where releasing the SPI bus is the
correct thing to do.

Signed-off-by: Alan Green <avg@google.com>
Change-Id: I9fae55e532595752983f55fac2298f81699dbe5b
Reviewed-on: https://review.coreboot.org/c/flashrom/+/49632
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
---
 ft2232_spi.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/ft2232_spi.c b/ft2232_spi.c
index 65ff4490..c963a45b 100644
--- a/ft2232_spi.c
+++ b/ft2232_spi.c
@@ -159,6 +159,30 @@ static int get_buf(struct ftdi_context *ftdic, const unsigned char *buf,
 	return 0;
 }
 
+static int ft2232_shutdown(void *data)
+{
+	int f;
+	struct ftdi_context *ftdic = (struct ftdi_context *) data;
+	unsigned char buf[3];
+
+	msg_pdbg("Releasing I/Os\n");
+	buf[0] = SET_BITS_LOW;
+	buf[1] = 0; /* Output byte ignored */
+	buf[2] = 0; /* Pin direction: all inputs */
+	if (send_buf(ftdic, buf, 3)) {
+		msg_perr("Unable to set pins back inputs: (%s)\n",
+		         ftdi_get_error_string(ftdic));
+	}
+
+	if ((f = ftdi_usb_close(ftdic)) < 0) {
+		msg_perr("Unable to close FTDI device: %d (%s)\n", f,
+		         ftdi_get_error_string(ftdic));
+		return f;
+	}
+
+	return 0;
+}
+
 static int ft2232_spi_send_command(const struct flashctx *flash,
 				   unsigned int writecnt, unsigned int readcnt,
 				   const unsigned char *writearr,
@@ -453,6 +477,7 @@ int ft2232_spi_init(void)
 		goto ftdi_err;
 	}
 
+	register_shutdown(ft2232_shutdown, ftdic);
 	register_spi_master(&spi_master_ft2232);
 
 	return 0;
-- 
cgit v1.2.3