FreeCalypso > hg > freecalypso-hwlab
comparison linux-patch/ftdi_sio.c.patch @ 73:749e1a14aa24
linux-patch: publishing currently used ftdi_sio driver patch
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Thu, 30 Jul 2020 05:12:44 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 72:5197272cd624 | 73:749e1a14aa24 |
|---|---|
| 1 --- ftdi_sio.c.orig 2016-06-24 09:18:38.000000000 -0800 | |
| 2 +++ ftdi_sio.c 2020-07-28 15:33:04.022945400 -0800 | |
| 3 @@ -73,6 +73,8 @@ | |
| 4 this value */ | |
| 5 int force_rtscts; /* if non-zero, force RTS-CTS to always | |
| 6 be enabled */ | |
| 7 + int no_auto_dtr_rts; /* if non-zero, suppress automatic assertion | |
| 8 + of DTR & RTS on device open */ | |
| 9 | |
| 10 unsigned int latency; /* latency setting in use */ | |
| 11 unsigned short max_packet_size; | |
| 12 @@ -83,15 +85,19 @@ | |
| 13 struct ftdi_sio_quirk { | |
| 14 int (*probe)(struct usb_serial *); | |
| 15 /* Special settings for probed ports. */ | |
| 16 - void (*port_probe)(struct ftdi_private *); | |
| 17 + void (*port_probe)(struct usb_serial_port *, struct ftdi_private *); | |
| 18 }; | |
| 19 | |
| 20 static int ftdi_jtag_probe(struct usb_serial *serial); | |
| 21 static int ftdi_NDI_device_setup(struct usb_serial *serial); | |
| 22 static int ftdi_stmclite_probe(struct usb_serial *serial); | |
| 23 static int ftdi_8u2232c_probe(struct usb_serial *serial); | |
| 24 -static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); | |
| 25 -static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); | |
| 26 +static void ftdi_USB_UIRT_setup(struct usb_serial_port *port, | |
| 27 + struct ftdi_private *priv); | |
| 28 +static void ftdi_HE_TIRA1_setup(struct usb_serial_port *port, | |
| 29 + struct ftdi_private *priv); | |
| 30 +static void ftdi_duart28c_setup(struct usb_serial_port *port, | |
| 31 + struct ftdi_private *priv); | |
| 32 | |
| 33 static struct ftdi_sio_quirk ftdi_jtag_quirk = { | |
| 34 .probe = ftdi_jtag_probe, | |
| 35 @@ -117,6 +123,10 @@ | |
| 36 .probe = ftdi_8u2232c_probe, | |
| 37 }; | |
| 38 | |
| 39 +static struct ftdi_sio_quirk ftdi_duart28c_quirk = { | |
| 40 + .port_probe = ftdi_duart28c_setup, | |
| 41 +}; | |
| 42 + | |
| 43 /* | |
| 44 * The 8U232AM has the same API as the sio except for: | |
| 45 * - it can support MUCH higher baudrates; up to: | |
| 46 @@ -1008,6 +1018,13 @@ | |
| 47 { USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) }, | |
| 48 { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) }, | |
| 49 { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) }, | |
| 50 + /* FreeCalypso USB adapters */ | |
| 51 + { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_BUF_PID), | |
| 52 + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | |
| 53 + { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_UNBUF_PID), | |
| 54 + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | |
| 55 + { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_DUART28C_PID), | |
| 56 + .driver_info = (kernel_ulong_t)&ftdi_duart28c_quirk }, | |
| 57 { } /* Terminating entry */ | |
| 58 }; | |
| 59 | |
| 60 @@ -1804,7 +1821,7 @@ | |
| 61 priv->flags = ASYNC_LOW_LATENCY; | |
| 62 | |
| 63 if (quirk && quirk->port_probe) | |
| 64 - quirk->port_probe(priv); | |
| 65 + quirk->port_probe(port, priv); | |
| 66 | |
| 67 usb_set_serial_port_data(port, priv); | |
| 68 | |
| 69 @@ -1820,7 +1837,8 @@ | |
| 70 /* Setup for the USB-UIRT device, which requires hardwired | |
| 71 * baudrate (38400 gets mapped to 312500) */ | |
| 72 /* Called from usbserial:serial_probe */ | |
| 73 -static void ftdi_USB_UIRT_setup(struct ftdi_private *priv) | |
| 74 +static void ftdi_USB_UIRT_setup(struct usb_serial_port *port, | |
| 75 + struct ftdi_private *priv) | |
| 76 { | |
| 77 priv->flags |= ASYNC_SPD_CUST; | |
| 78 priv->custom_divisor = 77; | |
| 79 @@ -1830,7 +1848,8 @@ | |
| 80 /* Setup for the HE-TIRA1 device, which requires hardwired | |
| 81 * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ | |
| 82 | |
| 83 -static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv) | |
| 84 +static void ftdi_HE_TIRA1_setup(struct usb_serial_port *port, | |
| 85 + struct ftdi_private *priv) | |
| 86 { | |
| 87 priv->flags |= ASYNC_SPD_CUST; | |
| 88 priv->custom_divisor = 240; | |
| 89 @@ -1926,6 +1945,37 @@ | |
| 90 return 0; | |
| 91 } | |
| 92 | |
| 93 +/* | |
| 94 + * FreeCalypso DUART28C is an FT2232D-based USB to dual UART adapter | |
| 95 + * with a special quirk: Channel B RTS and DTR outputs (BDBUS2 and BDBUS4 | |
| 96 + * on the chip) have been repurposed to drive power and reset controls | |
| 97 + * on Calypso targets. The circuit is wired such that BDBUS[24] high | |
| 98 + * (RTS/DTR inactive) is the normal state with power/reset control | |
| 99 + * NOT activated, whereas BDBUS[24] low (RTS or DTR active) turn ON | |
| 100 + * the corresponding power/reset control drivers. | |
| 101 + * | |
| 102 + * A special ftdi_sio driver quirk is needed in order to suppress | |
| 103 + * automatic assertion of DTR & RTS on device open: this device's | |
| 104 + * special power and reset control drivers MUST NOT be activated | |
| 105 + * when the port is ordinarily opened for plain serial communication, | |
| 106 + * instead they must only be activated when a special userspace | |
| 107 + * application explicitly requests such activation with a TIOCMBIS ioctl. | |
| 108 + * | |
| 109 + * The special quirk must be applied only to FT2232D Channel B: | |
| 110 + * Channel A is wired normally, with the chip's ADBUS2 and ADBUS4 outputs | |
| 111 + * actually being RTS and DTR rather than something else. | |
| 112 + */ | |
| 113 +static void ftdi_duart28c_setup(struct usb_serial_port *port, | |
| 114 + struct ftdi_private *priv) | |
| 115 +{ | |
| 116 + struct usb_serial *serial = port->serial; | |
| 117 + struct usb_device *udev = serial->dev; | |
| 118 + struct usb_interface *interface = serial->interface; | |
| 119 + | |
| 120 + if (interface == udev->actconfig->interface[1]) | |
| 121 + priv->no_auto_dtr_rts = 1; | |
| 122 +} | |
| 123 + | |
| 124 static int ftdi_sio_port_remove(struct usb_serial_port *port) | |
| 125 { | |
| 126 struct ftdi_private *priv = usb_get_serial_port_data(port); | |
| 127 @@ -1976,9 +2026,10 @@ | |
| 128 } | |
| 129 } | |
| 130 /* drop RTS and DTR */ | |
| 131 - if (on) | |
| 132 - set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | |
| 133 - else | |
| 134 + if (on) { | |
| 135 + if (!priv->no_auto_dtr_rts) | |
| 136 + set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | |
| 137 + } else | |
| 138 clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | |
| 139 } | |
| 140 | |
| 141 @@ -2316,7 +2367,8 @@ | |
| 142 dev_err(ddev, "%s urb failed to set baudrate\n", __func__); | |
| 143 mutex_unlock(&priv->cfg_lock); | |
| 144 /* Ensure RTS and DTR are raised when baudrate changed from 0 */ | |
| 145 - if (old_termios && (old_termios->c_cflag & CBAUD) == B0) | |
| 146 + if (old_termios && (old_termios->c_cflag & CBAUD) == B0 | |
| 147 + && !priv->no_auto_dtr_rts) | |
| 148 set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | |
| 149 } | |
| 150 |
