changeset 12:6c347929a458

4.14.202: add for completeness
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 20 Jan 2024 02:19:26 +0000
parents 298c838f12c0
children db3d2cc644a5
files 4.14.202/0002-USB-serial-ftdi_sio-pass-port-to-quirk-port_probe-fu.patch 4.14.202/0003-USB-serial-ftdi_sio-add-support-for-FreeCalypso-DUAR.patch
diffstat 2 files changed, 248 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4.14.202/0002-USB-serial-ftdi_sio-pass-port-to-quirk-port_probe-fu.patch	Sat Jan 20 02:19:26 2024 +0000
@@ -0,0 +1,85 @@
+From 2a8c3dabcf6440a9ed17e8ef26bc7ed325a1ff7b Mon Sep 17 00:00:00 2001
+From: "Mychaela N. Falconia" <falcon@freecalypso.org>
+Date: Fri, 2 Oct 2020 17:38:56 +0000
+Subject: [PATCH 2/3] USB: serial: ftdi_sio: pass port to quirk port_probe
+ functions
+
+The original code passed only the pointer to the ftdi_private struct
+to quirk port_probe functions.  However, some quirks may need to be
+applied conditionally only to some channels of a multichannel FT2232x
+or FT4232H device, and if a given quirk's port_probe function needs
+to figure out which channel of a multichannel device is currently
+being considered, it needs access to the port pointer passed to the
+ftdi_sio_port_probe() function, so it can traverse USB data structures
+from there.
+
+Signed-off-by: Mychaela N. Falconia <falcon@freecalypso.org>
+---
+ drivers/usb/serial/ftdi_sio.c | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index 8ed84338a626..137688e9a86a 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -83,15 +83,15 @@ struct ftdi_private {
+ struct ftdi_sio_quirk {
+ 	int (*probe)(struct usb_serial *);
+ 	/* Special settings for probed ports. */
+-	void (*port_probe)(struct ftdi_private *);
++	void (*port_probe)(struct usb_serial_port *);
+ };
+ 
+ static int   ftdi_jtag_probe(struct usb_serial *serial);
+ static int   ftdi_NDI_device_setup(struct usb_serial *serial);
+ static int   ftdi_stmclite_probe(struct usb_serial *serial);
+ static int   ftdi_8u2232c_probe(struct usb_serial *serial);
+-static void  ftdi_USB_UIRT_setup(struct ftdi_private *priv);
+-static void  ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
++static void  ftdi_USB_UIRT_setup(struct usb_serial_port *port);
++static void  ftdi_HE_TIRA1_setup(struct usb_serial_port *port);
+ 
+ static const struct ftdi_sio_quirk ftdi_jtag_quirk = {
+ 	.probe	= ftdi_jtag_probe,
+@@ -1824,11 +1824,11 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
+ 
+ 	mutex_init(&priv->cfg_lock);
+ 
+-	if (quirk && quirk->port_probe)
+-		quirk->port_probe(priv);
+-
+ 	usb_set_serial_port_data(port, priv);
+ 
++	if (quirk && quirk->port_probe)
++		quirk->port_probe(port);
++
+ 	ftdi_determine_type(port);
+ 	ftdi_set_max_packet_size(port);
+ 	if (read_latency_timer(port) < 0)
+@@ -1841,8 +1841,10 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
+ /* Setup for the USB-UIRT device, which requires hardwired
+  * baudrate (38400 gets mapped to 312500) */
+ /* Called from usbserial:serial_probe */
+-static void ftdi_USB_UIRT_setup(struct ftdi_private *priv)
++static void ftdi_USB_UIRT_setup(struct usb_serial_port *port)
+ {
++	struct ftdi_private *priv = usb_get_serial_port_data(port);
++
+ 	priv->flags |= ASYNC_SPD_CUST;
+ 	priv->custom_divisor = 77;
+ 	priv->force_baud = 38400;
+@@ -1851,8 +1853,10 @@ static void ftdi_USB_UIRT_setup(struct ftdi_private *priv)
+ /* Setup for the HE-TIRA1 device, which requires hardwired
+  * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled.  */
+ 
+-static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
++static void ftdi_HE_TIRA1_setup(struct usb_serial_port *port)
+ {
++	struct ftdi_private *priv = usb_get_serial_port_data(port);
++
+ 	priv->flags |= ASYNC_SPD_CUST;
+ 	priv->custom_divisor = 240;
+ 	priv->force_baud = 38400;
+-- 
+2.9.0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4.14.202/0003-USB-serial-ftdi_sio-add-support-for-FreeCalypso-DUAR.patch	Sat Jan 20 02:19:26 2024 +0000
@@ -0,0 +1,163 @@
+From a3aab542c53b3236a1a7315d201496c837793fa9 Mon Sep 17 00:00:00 2001
+From: "Mychaela N. Falconia" <falcon@freecalypso.org>
+Date: Fri, 2 Oct 2020 18:01:12 +0000
+Subject: [PATCH 3/3] USB: serial: ftdi_sio: add support for FreeCalypso
+ DUART28C adapter
+
+FreeCalypso DUART28C is an FT2232D-based USB to dual UART adapter
+with a special quirk: Channel B RTS and DTR outputs (BDBUS2 and BDBUS4
+on the chip) have been repurposed to drive PWON and RESET controls
+on Calypso targets.  The circuit is wired such that BDBUS[24] high
+(RTS/DTR inactive) is the normal state with Iota VRPC controls
+NOT activated, whereas BDBUS[24] low (RTS or DTR active) turn ON
+the corresponding open drain control signal drivers.
+
+A special ftdi_sio driver quirk is needed in order to suppress
+automatic assertion of DTR & RTS on device open: this device's
+special PWON and RESET control drivers MUST NOT be activated
+when the port is ordinarily opened for plain serial communication,
+instead they must only be activated when a special userspace
+application explicitly requests such activation with a TIOCMBIS ioctl.
+These special userspace applications are responsible for making the
+needed pulse with a TIOCMBIS, delay, TIOCMBIC sequence.
+
+The special quirk is conditionalized on the DUART28C adapter's custom
+USB ID, and is further limited to FT2232D Channel B only: Channel A
+is wired normally, with the chip's ADBUS2 and ADBUS4 outputs
+actually being RTS and DTR rather than something else.
+
+Signed-off-by: Mychaela N. Falconia <falcon@freecalypso.org>
+---
+ drivers/usb/serial/ftdi_sio.c     | 61 +++++++++++++++++++++++++++++++++++----
+ drivers/usb/serial/ftdi_sio_ids.h |  1 +
+ 2 files changed, 57 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index 137688e9a86a..88ef223b72c9 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -73,6 +73,8 @@ struct ftdi_private {
+ 				   this value */
+ 	int force_rtscts;	/* if non-zero, force RTS-CTS to always
+ 				   be enabled */
++	int no_auto_dtr_rts;	/* if non-zero, suppress automatic assertion
++				   of DTR & RTS on device open */
+ 
+ 	unsigned int latency;		/* latency setting in use */
+ 	unsigned short max_packet_size;
+@@ -92,6 +94,7 @@ static int   ftdi_stmclite_probe(struct usb_serial *serial);
+ static int   ftdi_8u2232c_probe(struct usb_serial *serial);
+ static void  ftdi_USB_UIRT_setup(struct usb_serial_port *port);
+ static void  ftdi_HE_TIRA1_setup(struct usb_serial_port *port);
++static void  ftdi_duart28c_setup(struct usb_serial_port *port);
+ 
+ static const struct ftdi_sio_quirk ftdi_jtag_quirk = {
+ 	.probe	= ftdi_jtag_probe,
+@@ -117,6 +120,10 @@ static const struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
+ 	.probe	= ftdi_8u2232c_probe,
+ };
+ 
++static const struct ftdi_sio_quirk ftdi_duart28c_quirk = {
++	.port_probe = ftdi_duart28c_setup,
++};
++
+ /*
+  * The 8U232AM has the same API as the sio except for:
+  * - it can support MUCH higher baudrates; up to:
+@@ -1037,6 +1044,8 @@ static const struct usb_device_id id_table_combined[] = {
+ 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ 	{ USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_UNBUF_PID),
+ 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
++	{ USB_DEVICE(FTDI_VID, FTDI_FALCONIA_DUART28C_PID),
++		.driver_info = (kernel_ulong_t)&ftdi_duart28c_quirk },
+ 	{ }					/* Terminating entry */
+ };
+ 
+@@ -1952,6 +1961,39 @@ static int ftdi_stmclite_probe(struct usb_serial *serial)
+ 	return 0;
+ }
+ 
++/*
++ * FreeCalypso DUART28C is an FT2232D-based USB to dual UART adapter
++ * with a special quirk: Channel B RTS and DTR outputs (BDBUS2 and BDBUS4
++ * on the chip) have been repurposed to drive PWON and RESET controls
++ * on Calypso targets.  The circuit is wired such that BDBUS[24] high
++ * (RTS/DTR inactive) is the normal state with Iota VRPC controls
++ * NOT activated, whereas BDBUS[24] low (RTS or DTR active) turn ON
++ * the corresponding open drain control signal drivers.
++ *
++ * A special ftdi_sio driver quirk is needed in order to suppress
++ * automatic assertion of DTR & RTS on device open: this device's
++ * special PWON and RESET control drivers MUST NOT be activated
++ * when the port is ordinarily opened for plain serial communication,
++ * instead they must only be activated when a special userspace
++ * application explicitly requests such activation with a TIOCMBIS ioctl.
++ * These special userspace applications are responsible for making the
++ * needed pulse with a TIOCMBIS, delay, TIOCMBIC sequence.
++ *
++ * The special quirk must be applied only to FT2232D Channel B:
++ * Channel A is wired normally, with the chip's ADBUS2 and ADBUS4 outputs
++ * actually being RTS and DTR rather than something else.
++ */
++static void ftdi_duart28c_setup(struct usb_serial_port *port)
++{
++	struct ftdi_private *priv = usb_get_serial_port_data(port);
++	struct usb_serial *serial = port->serial;
++	struct usb_interface *intf = serial->interface;
++	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
++
++	if (ifnum == 1)
++		priv->no_auto_dtr_rts = 1;
++}
++
+ static int ftdi_sio_port_remove(struct usb_serial_port *port)
+ {
+ 	struct ftdi_private *priv = usb_get_serial_port_data(port);
+@@ -2001,10 +2043,18 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
+ 			dev_err(&port->dev, "error from flowcontrol urb\n");
+ 		}
+ 	}
+-	/* drop RTS and DTR */
+-	if (on)
+-		set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+-	else
++	/*
++	 * Assert or negate RTS and DTR as requested.  When DUART28C
++	 * quirk is applied, we suppress automatic assertion, but
++	 * automatic negation on device close is retained - these
++	 * special control signals are meant to be pulsed, and leaving
++	 * either of them stuck on when the responsible userspace
++	 * program has terminated unexpectedly is undesirable.
++	 */
++	if (on) {
++		if (!priv->no_auto_dtr_rts)
++			set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
++	} else
+ 		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ }
+ 
+@@ -2346,7 +2396,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
+ 			dev_err(ddev, "%s urb failed to set baudrate\n", __func__);
+ 		mutex_unlock(&priv->cfg_lock);
+ 		/* Ensure RTS and DTR are raised when baudrate changed from 0 */
+-		if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
++		if (old_termios && (old_termios->c_cflag & CBAUD) == B0
++		    && !priv->no_auto_dtr_rts)
+ 			set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ 	}
+ 
+diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
+index 3d47c6d72256..3081b8916a0a 100644
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -45,6 +45,7 @@
+  */
+ #define FTDI_FALCONIA_JTAG_BUF_PID	0x7150
+ #define FTDI_FALCONIA_JTAG_UNBUF_PID	0x7151
++#define FTDI_FALCONIA_DUART28C_PID	0x7152
+ 
+ /* Sienna Serial Interface by Secyourit GmbH */
+ #define FTDI_SIENNA_PID		0x8348
+-- 
+2.9.0
+