# HG changeset patch # User Mychaela Falconia # Date 1702274117 0 # Node ID 713fe1e8df4183694bc51c507e0e5933f2421c36 initial import of formal patches from freecalypso-hwlab repo diff -r 000000000000 -r 713fe1e8df41 4.4.14/0001-USB-serial-ftdi_sio-add-support-for-FreeCalypso-JTAG.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4.4.14/0001-USB-serial-ftdi_sio-add-support-for-FreeCalypso-JTAG.patch Mon Dec 11 05:55:17 2023 +0000 @@ -0,0 +1,78 @@ +From 5af8e2ad7d0295d90cb2bc566f3d935668fb0535 Mon Sep 17 00:00:00 2001 +From: "Mychaela N. Falconia" +Date: Wed, 16 Sep 2020 01:56:29 +0000 +Subject: [PATCH 1/3] USB: serial: ftdi_sio: add support for FreeCalypso + JTAG+UART adapters + +commit 6cf87e5edd9944e1d3b6efd966ea401effc304ee upstream. + +There exist many FT2232-based JTAG+UART adapter designs in which +FT2232 Channel A is used for JTAG and Channel B is used for UART. +The best way to handle them in Linux is to have the ftdi_sio driver +create a ttyUSB device only for Channel B and not for Channel A: +a ttyUSB device for Channel A would be bogus and will disappear as +soon as the user runs OpenOCD or other applications that access +Channel A for JTAG from userspace, causing undesirable noise for +users. The ftdi_sio driver already has a dedicated quirk for such +JTAG+UART FT2232 adapters, and it requires assigning custom USB IDs +to such adapters and adding these IDs to the driver with the +ftdi_jtag_quirk applied. + +Boutique hardware manufacturer Falconia Partners LLC has created a +couple of JTAG+UART adapter designs (one buffered, one unbuffered) +as part of FreeCalypso project, and this hardware is specifically made +to be used with Linux hosts, with the intent that Channel A will be +accessed only from userspace via appropriate applications, and that +Channel B will be supported by the ftdi_sio kernel driver, presenting +a standard ttyUSB device to userspace. Toward this end the hardware +manufacturer will be programming FT2232 EEPROMs with custom USB IDs, +specifically with the intent that these IDs will be recognized by +the ftdi_sio driver with the ftdi_jtag_quirk applied. + +Signed-off-by: Mychaela N. Falconia +[johan: insert in PID order and drop unused define] +Cc: stable@vger.kernel.org +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/ftdi_sio.c | 5 +++++ + drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++ + 2 files changed, 12 insertions(+) + +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index b61f12160d37..984a93c38365 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -1008,6 +1008,11 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) }, + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) }, + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) }, ++ /* FreeCalypso USB adapters */ ++ { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_BUF_PID), ++ .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 }, + { } /* Terminating entry */ + }; + +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index c5d6c1e73e8e..6218f9c45016 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -38,6 +38,13 @@ + + #define FTDI_LUMEL_PD12_PID 0x6002 + ++/* ++ * Custom USB adapters made by Falconia Partners LLC ++ * for FreeCalypso project, ID codes allocated to Falconia by FTDI. ++ */ ++#define FTDI_FALCONIA_JTAG_BUF_PID 0x7150 ++#define FTDI_FALCONIA_JTAG_UNBUF_PID 0x7151 ++ + /* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */ + #define CYBER_CORTEX_AV_PID 0x8698 + +-- +2.9.0 + diff -r 000000000000 -r 713fe1e8df41 4.4.14/0002-USB-serial-ftdi_sio-pass-port-to-quirk-port_probe-fu.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4.4.14/0002-USB-serial-ftdi_sio-pass-port-to-quirk-port_probe-fu.patch Mon Dec 11 05:55:17 2023 +0000 @@ -0,0 +1,85 @@ +From 13701049a8f24450d69b6eeac6cfab5951abc604 Mon Sep 17 00:00:00 2001 +From: "Mychaela N. Falconia" +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 +--- + 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 984a93c38365..60d1831ee8c3 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 struct ftdi_sio_quirk ftdi_jtag_quirk = { + .probe = ftdi_jtag_probe, +@@ -1808,11 +1808,11 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) + + priv->flags = ASYNC_LOW_LATENCY; + +- 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) +@@ -1825,8 +1825,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; +@@ -1835,8 +1837,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 + diff -r 000000000000 -r 713fe1e8df41 4.4.14/0003-USB-serial-ftdi_sio-add-support-for-FreeCalypso-DUAR.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4.4.14/0003-USB-serial-ftdi_sio-add-support-for-FreeCalypso-DUAR.patch Mon Dec 11 05:55:17 2023 +0000 @@ -0,0 +1,163 @@ +From 32c23625ab6e7cdc7da7849e866ccee66cbe2ee9 Mon Sep 17 00:00:00 2001 +From: "Mychaela N. Falconia" +Date: Sat, 5 Dec 2020 20:53:18 +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 +--- + 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 60d1831ee8c3..b9abe8571aa1 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 struct ftdi_sio_quirk ftdi_jtag_quirk = { + .probe = ftdi_jtag_probe, +@@ -117,6 +120,10 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { + .probe = ftdi_8u2232c_probe, + }; + ++static 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: +@@ -1013,6 +1020,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 */ + }; + +@@ -1935,6 +1944,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); +@@ -1984,10 +2026,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); + } + +@@ -2325,7 +2375,8 @@ no_data_parity_stop_changes: + 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 6218f9c45016..5720768859fe 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -44,6 +44,7 @@ + */ + #define FTDI_FALCONIA_JTAG_BUF_PID 0x7150 + #define FTDI_FALCONIA_JTAG_UNBUF_PID 0x7151 ++#define FTDI_FALCONIA_DUART28C_PID 0x7152 + + /* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */ + #define CYBER_CORTEX_AV_PID 0x8698 +-- +2.9.0 + diff -r 000000000000 -r 713fe1e8df41 4.4.240/0002-USB-serial-ftdi_sio-pass-port-to-quirk-port_probe-fu.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4.4.240/0002-USB-serial-ftdi_sio-pass-port-to-quirk-port_probe-fu.patch Mon Dec 11 05:55:17 2023 +0000 @@ -0,0 +1,85 @@ +From 269f94070f6ae14abbc47a36ec2556e977ea9bec Mon Sep 17 00:00:00 2001 +From: "Mychaela N. Falconia" +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 +--- + 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 5b42b8d760cb..2d23fd7b93cb 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 struct ftdi_sio_quirk ftdi_jtag_quirk = { + .probe = ftdi_jtag_probe, +@@ -1833,11 +1833,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) +@@ -1850,8 +1850,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; +@@ -1860,8 +1862,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 + diff -r 000000000000 -r 713fe1e8df41 4.4.240/0003-USB-serial-ftdi_sio-add-support-for-FreeCalypso-DUAR.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4.4.240/0003-USB-serial-ftdi_sio-add-support-for-FreeCalypso-DUAR.patch Mon Dec 11 05:55:17 2023 +0000 @@ -0,0 +1,163 @@ +From 6bfda041e99ef9f1175c0583f2f3c87b491e19b4 Mon Sep 17 00:00:00 2001 +From: "Mychaela N. Falconia" +Date: Sat, 5 Dec 2020 20:53:18 +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 +--- + 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 2d23fd7b93cb..41f73b519023 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 struct ftdi_sio_quirk ftdi_jtag_quirk = { + .probe = ftdi_jtag_probe, +@@ -117,6 +120,10 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { + .probe = ftdi_8u2232c_probe, + }; + ++static 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 */ + }; + +@@ -1961,6 +1970,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); +@@ -2010,10 +2052,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); + } + +@@ -2355,7 +2405,8 @@ no_data_parity_stop_changes: + 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 f3302516a1e4..f756b80cb361 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -44,6 +44,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 + diff -r 000000000000 -r 713fe1e8df41 4.9.240/0002-USB-serial-ftdi_sio-pass-port-to-quirk-port_probe-fu.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4.9.240/0002-USB-serial-ftdi_sio-pass-port-to-quirk-port_probe-fu.patch Mon Dec 11 05:55:17 2023 +0000 @@ -0,0 +1,85 @@ +From 214b1d2da22e380b05ecf6e546962ca867e3a60e Mon Sep 17 00:00:00 2001 +From: "Mychaela N. Falconia" +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 +--- + 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 c9f979063af1..878ab4e5625c 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, +@@ -1833,11 +1833,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) +@@ -1850,8 +1850,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; +@@ -1860,8 +1862,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 + diff -r 000000000000 -r 713fe1e8df41 4.9.240/0003-USB-serial-ftdi_sio-add-support-for-FreeCalypso-DUAR.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4.9.240/0003-USB-serial-ftdi_sio-add-support-for-FreeCalypso-DUAR.patch Mon Dec 11 05:55:17 2023 +0000 @@ -0,0 +1,163 @@ +From 8edb5017764d4ad9d90a631c420caca41827cd6e Mon Sep 17 00:00:00 2001 +From: "Mychaela N. Falconia" +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 +--- + 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 878ab4e5625c..443aee847556 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 */ + }; + +@@ -1961,6 +1970,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); +@@ -2010,10 +2052,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); + } + +@@ -2355,7 +2405,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 f3302516a1e4..f756b80cb361 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -44,6 +44,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 +