-
Notifications
You must be signed in to change notification settings - Fork 10
/
ftdi-sio-bankA-only.patch
171 lines (162 loc) · 4.93 KB
/
ftdi-sio-bankA-only.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
--- ../ftdi_sio.c 2022-01-04 14:05:18.843273600 -0500
+++ drivers/usb/serial/ftdi_sio.c 2022-01-09 13:38:32.240012675 -0500
@@ -69,7 +69,7 @@
this value */
int force_rtscts; /* if non-zero, force RTS-CTS to always
be enabled */
-
+ int syncmode;
unsigned int latency; /* latency setting in use */
unsigned short max_packet_size;
struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() and change_speed() */
@@ -92,6 +92,7 @@
};
static int ftdi_jtag_probe(struct usb_serial *serial);
+static int ft4232_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);
@@ -102,6 +103,10 @@
.probe = ftdi_jtag_probe,
};
+static const struct ftdi_sio_quirk ft4232_jtag_quirk = {
+ .probe = ft4232_jtag_probe,
+};
+
static const struct ftdi_sio_quirk ftdi_NDI_device_quirk = {
.probe = ftdi_NDI_device_setup,
};
@@ -177,7 +182,8 @@
{ USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) ,
.driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
- { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) ,
+ .driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_FTX_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
@@ -1047,6 +1053,9 @@
.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 },
+ /* 16ton i2c spi */
+ { USB_DEVICE(FTDI_VID, FTDI_4232H_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
{ } /* Terminating entry */
};
@@ -1407,6 +1416,36 @@
return rv;
}
+static int set_syncmode(struct usb_serial_port *port, int enable)
+{
+struct ftdi_private *priv = usb_get_serial_port_data(port);
+
+__u16 urb_value = 0;
+int rv = 0;
+
+enable = enable ? 1 : 0;
+if (enable == priv->syncmode)
+return 0;
+
+priv->syncmode = enable;
+
+/* FTDI seems to say that the urb_value should be or'ed with 0xff. But
+* when done this way the port gets quite slow. 0x00 seems to work much
+* better.
+*/
+if (enable)
+urb_value = FTDI_BITMODE_SYNCFIFO << 8 | 0x00;
+
+rv = usb_control_msg(port->serial->dev,
+usb_sndctrlpipe(port->serial->dev, 0),
+FTDI_SIO_SET_BITBANG_REQUEST,
+FTDI_SIO_SET_BITBANG_REQUEST_TYPE,
+urb_value, priv->interface,
+NULL, 0, WDR_SHORT_TIMEOUT);
+
+return rv;
+}
+
static int write_latency_timer(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1704,6 +1743,32 @@
}
static DEVICE_ATTR_RW(latency_timer);
+static ssize_t syncmode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ return sprintf(buf, "%i\n", priv->syncmode);
+}
+
+static ssize_t syncmode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *valbuf, size_t count)
+{
+ unsigned long value;
+ int rv;
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+ int ret = kstrtoul(valbuf, 0, &value);
+ if (ret)
+ return -EINVAL;
+
+ rv = set_syncmode(port, value);
+ if (rv < 0)
+ return -EIO;
+ return count;
+}
+static DEVICE_ATTR_RW(syncmode);
+
/* Write an event character directly to the FTDI register. The ASCII
value is in the low 8 bits, with the enable bit in the 9th bit. */
static ssize_t event_char_store(struct device *dev,
@@ -1757,6 +1822,10 @@
&dev_attr_latency_timer);
}
}
+ if ((!retval) && (priv->chip_type == FT232H || priv->chip_type == FT2232H || priv->chip_type == FT4232H)) {
+ retval = device_create_file(&port->dev,
+ &dev_attr_syncmode);
+ }
return retval;
}
@@ -1777,7 +1846,8 @@
device_remove_file(&port->dev, &dev_attr_latency_timer);
}
}
-
+ if (priv->chip_type == FT232H || priv->chip_type == FT2232H || priv->chip_type == FT4232H)
+ device_remove_file(&port->dev, &dev_attr_syncmode);
}
#ifdef CONFIG_GPIOLIB
@@ -2352,6 +2422,19 @@
return 0;
}
+static int ft4232_jtag_probe(struct usb_serial *serial)
+{
+ struct usb_interface *intf = serial->interface;
+ int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+ if (ifnum < 2) {
+ dev_info(&intf->dev, "Ignoring interface reserved for JTAG\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static int ftdi_8u2232c_probe(struct usb_serial *serial)
{
struct usb_device *udev = serial->dev;
@@ -2359,6 +2442,9 @@
if (udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems"))
return ftdi_jtag_probe(serial);
+ if (udev->product && (!strcmp(udev->product, "ft4232H-16ton") || !strcmp(udev->product, "ft2232H-16ton")))
+ return ft4232_jtag_probe(serial);
+
if (udev->product &&
(!strcmp(udev->product, "Arrow USB Blaster") ||
!strcmp(udev->product, "BeagleBone/XDS100V2") ||