Skip to content

Commit 094c2e6

Browse files
Mark Adamsongregkh
authored andcommitted
USB: serial: FTDI: add high speed device support
Added support for FTDI's USB 2.0 hi-speed devices - FT2232H (2 interfaces) and FT4232H (4 interfaces), including a new baud rate calculation for these devices which can now achieve up to 12Mbaud by turning off a divide by 2.5 in the baud rate generator of the chips. In order to achieve baud rates of <1200 baud, the divide by 2.5 must be active. The default product ID of the FT2232H is 0x6010 (same as the FT2232C IC). The default PID of the FT4232H is 0x6011. Signed-off-by: Mark J. Adamson <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a483d70 commit 094c2e6

File tree

2 files changed

+89
-11
lines changed

2 files changed

+89
-11
lines changed

drivers/usb/serial/ftdi_sio.c

Lines changed: 80 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
/*
4848
* Version Information
4949
*/
50-
#define DRIVER_VERSION "v1.4.3"
50+
#define DRIVER_VERSION "v1.5.0"
5151
#define DRIVER_AUTHOR "Greg Kroah-Hartman <[email protected]>, Bill Ryder <[email protected]>, Kuba Ober <[email protected]>"
5252
#define DRIVER_DESC "USB FTDI Serial Converters Driver"
5353

@@ -82,7 +82,8 @@ struct ftdi_private {
8282
int rx_processed;
8383
unsigned long rx_bytes;
8484

85-
__u16 interface; /* FT2232C port interface (0 for FT232/245) */
85+
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
86+
(0 for FT232/245) */
8687

8788
speed_t force_baud; /* if non-zero, force the baud rate to
8889
this value */
@@ -164,6 +165,7 @@ static struct usb_device_id id_table_combined [] = {
164165
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
165166
{ USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
166167
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
168+
{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
167169
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
168170
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
169171
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
@@ -694,6 +696,8 @@ static const char *ftdi_chip_name[] = {
694696
[FT232BM] = "FT232BM",
695697
[FT2232C] = "FT2232C",
696698
[FT232RL] = "FT232RL",
699+
[FT2232H] = "FT2232H",
700+
[FT4232H] = "FT4232H"
697701
};
698702

699703

@@ -745,6 +749,8 @@ static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
745749
static unsigned short int ftdi_232am_baud_to_divisor(int baud);
746750
static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base);
747751
static __u32 ftdi_232bm_baud_to_divisor(int baud);
752+
static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base);
753+
static __u32 ftdi_2232h_baud_to_divisor(int baud);
748754

749755
static struct usb_serial_driver ftdi_sio_device = {
750756
.driver = {
@@ -839,6 +845,36 @@ static __u32 ftdi_232bm_baud_to_divisor(int baud)
839845
return ftdi_232bm_baud_base_to_divisor(baud, 48000000);
840846
}
841847

848+
static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base)
849+
{
850+
static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
851+
__u32 divisor;
852+
int divisor3;
853+
854+
/* hi-speed baud rate is 10-bit sampling instead of 16-bit */
855+
divisor3 = (base / 10 / baud) * 8;
856+
857+
divisor = divisor3 >> 3;
858+
divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
859+
/* Deal with special cases for highest baud rates. */
860+
if (divisor == 1)
861+
divisor = 0;
862+
else if (divisor == 0x4001)
863+
divisor = 1;
864+
/*
865+
* Set this bit to turn off a divide by 2.5 on baud rate generator
866+
* This enables baud rates up to 12Mbaud but cannot reach below 1200
867+
* baud with this bit set
868+
*/
869+
divisor |= 0x00020000;
870+
return divisor;
871+
}
872+
873+
static __u32 ftdi_2232h_baud_to_divisor(int baud)
874+
{
875+
return ftdi_2232h_baud_base_to_divisor(baud, 120000000);
876+
}
877+
842878
#define set_mctrl(port, set) update_mctrl((port), (set), 0)
843879
#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear))
844880

@@ -997,6 +1033,19 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
9971033
baud = 9600;
9981034
}
9991035
break;
1036+
case FT2232H: /* FT2232H chip */
1037+
case FT4232H: /* FT4232H chip */
1038+
if ((baud <= 12000000) & (baud >= 1200)) {
1039+
div_value = ftdi_2232h_baud_to_divisor(baud);
1040+
} else if (baud < 1200) {
1041+
div_value = ftdi_232bm_baud_to_divisor(baud);
1042+
} else {
1043+
dbg("%s - Baud rate too high!", __func__);
1044+
div_value = ftdi_232bm_baud_to_divisor(9600);
1045+
div_okay = 0;
1046+
baud = 9600;
1047+
}
1048+
break;
10001049
} /* priv->chip_type */
10011050

10021051
if (div_okay) {
@@ -1197,14 +1246,29 @@ static void ftdi_determine_type(struct usb_serial_port *port)
11971246
if (interfaces > 1) {
11981247
int inter;
11991248

1200-
/* Multiple interfaces. Assume FT2232C. */
1201-
priv->chip_type = FT2232C;
1249+
/* Multiple interfaces.*/
1250+
if (version == 0x0800) {
1251+
priv->chip_type = FT4232H;
1252+
/* Hi-speed - baud clock runs at 120MHz */
1253+
priv->baud_base = 120000000 / 2;
1254+
} else if (version == 0x0700) {
1255+
priv->chip_type = FT2232H;
1256+
/* Hi-speed - baud clock runs at 120MHz */
1257+
priv->baud_base = 120000000 / 2;
1258+
} else
1259+
priv->chip_type = FT2232C;
1260+
12021261
/* Determine interface code. */
12031262
inter = serial->interface->altsetting->desc.bInterfaceNumber;
1204-
if (inter == 0)
1205-
priv->interface = PIT_SIOA;
1206-
else
1207-
priv->interface = PIT_SIOB;
1263+
if (inter == 0) {
1264+
priv->interface = INTERFACE_A;
1265+
} else if (inter == 1) {
1266+
priv->interface = INTERFACE_B;
1267+
} else if (inter == 2) {
1268+
priv->interface = INTERFACE_C;
1269+
} else if (inter == 3) {
1270+
priv->interface = INTERFACE_D;
1271+
}
12081272
/* BM-type devices have a bug where bcdDevice gets set
12091273
* to 0x200 when iSerialNumber is 0. */
12101274
if (version < 0x500) {
@@ -1315,7 +1379,9 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
13151379
if ((!retval) &&
13161380
(priv->chip_type == FT232BM ||
13171381
priv->chip_type == FT2232C ||
1318-
priv->chip_type == FT232RL)) {
1382+
priv->chip_type == FT232RL ||
1383+
priv->chip_type == FT2232H ||
1384+
priv->chip_type == FT4232H)) {
13191385
retval = device_create_file(&port->dev,
13201386
&dev_attr_latency_timer);
13211387
}
@@ -1334,7 +1400,9 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
13341400
device_remove_file(&port->dev, &dev_attr_event_char);
13351401
if (priv->chip_type == FT232BM ||
13361402
priv->chip_type == FT2232C ||
1337-
priv->chip_type == FT232RL) {
1403+
priv->chip_type == FT232RL ||
1404+
priv->chip_type == FT2232H ||
1405+
priv->chip_type == FT4232H) {
13381406
device_remove_file(&port->dev, &dev_attr_latency_timer);
13391407
}
13401408
}
@@ -2333,6 +2401,8 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
23332401
case FT232BM:
23342402
case FT2232C:
23352403
case FT232RL:
2404+
case FT2232H:
2405+
case FT4232H:
23362406
/* the 8U232AM returns a two byte value (the sio is a 1 byte
23372407
value) - in the same format as the data returned from the in
23382408
point */

drivers/usb/serial/ftdi_sio.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side,
1111
* USB on the other.
1212
*
13-
* Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details
13+
* Thanx to FTDI (http://www.ftdichip.com) for so kindly providing details
1414
* of the protocol required to talk to the device and ongoing assistence
1515
* during development.
1616
*
@@ -28,6 +28,7 @@
2828
#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
2929
#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
3030
#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */
31+
#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
3132
#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */
3233
#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */
3334
#define FTDI_NF_RIC_PID 0x0001 /* Product Id */
@@ -876,6 +877,11 @@
876877
#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */
877878
#define FTDI_SIO_GET_LATENCY_TIMER 10 /* Get the latency timer */
878879

880+
/* Interface indicies for FT2232, FT2232H and FT4232H devices*/
881+
#define INTERFACE_A 1
882+
#define INTERFACE_B 2
883+
#define INTERFACE_C 3
884+
#define INTERFACE_D 4
879885

880886
/*
881887
* FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3
@@ -1039,6 +1045,8 @@ typedef enum {
10391045
FT232BM = 3,
10401046
FT2232C = 4,
10411047
FT232RL = 5,
1048+
FT2232H = 6,
1049+
FT4232H = 7
10421050
} ftdi_chip_type_t;
10431051

10441052
typedef enum {

0 commit comments

Comments
 (0)