aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Adamson <mark.adamson@ftdichip.com>2009-04-09 10:03:09 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:41 -0400
commit094c2e6db4be381f708ad8a2e0532d7782f05ea4 (patch)
tree2bb8fc0b4ace555ad341dd19fcc65174685f9cbc
parenta483d7068f661213e9586d4d132fc0e0287118b4 (diff)
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 <mark.adamson@ftdichip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/serial/ftdi_sio.c90
-rw-r--r--drivers/usb/serial/ftdi_sio.h10
2 files changed, 89 insertions, 11 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 59c7501840cb..80ccfa13e0b3 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -47,7 +47,7 @@
47/* 47/*
48 * Version Information 48 * Version Information
49 */ 49 */
50#define DRIVER_VERSION "v1.4.3" 50#define DRIVER_VERSION "v1.5.0"
51#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>" 51#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
52#define DRIVER_DESC "USB FTDI Serial Converters Driver" 52#define DRIVER_DESC "USB FTDI Serial Converters Driver"
53 53
@@ -82,7 +82,8 @@ struct ftdi_private {
82 int rx_processed; 82 int rx_processed;
83 unsigned long rx_bytes; 83 unsigned long rx_bytes;
84 84
85 __u16 interface; /* FT2232C port interface (0 for FT232/245) */ 85 __u16 interface; /* FT2232C, FT2232H or FT4232H port interface
86 (0 for FT232/245) */
86 87
87 speed_t force_baud; /* if non-zero, force the baud rate to 88 speed_t force_baud; /* if non-zero, force the baud rate to
88 this value */ 89 this value */
@@ -164,6 +165,7 @@ static struct usb_device_id id_table_combined [] = {
164 { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, 165 { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
165 { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, 166 { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
166 { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, 167 { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
168 { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
167 { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, 169 { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
168 { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, 170 { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
169 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, 171 { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
@@ -694,6 +696,8 @@ static const char *ftdi_chip_name[] = {
694 [FT232BM] = "FT232BM", 696 [FT232BM] = "FT232BM",
695 [FT2232C] = "FT2232C", 697 [FT2232C] = "FT2232C",
696 [FT232RL] = "FT232RL", 698 [FT232RL] = "FT232RL",
699 [FT2232H] = "FT2232H",
700 [FT4232H] = "FT4232H"
697}; 701};
698 702
699 703
@@ -745,6 +749,8 @@ static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
745static unsigned short int ftdi_232am_baud_to_divisor(int baud); 749static unsigned short int ftdi_232am_baud_to_divisor(int baud);
746static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base); 750static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base);
747static __u32 ftdi_232bm_baud_to_divisor(int baud); 751static __u32 ftdi_232bm_baud_to_divisor(int baud);
752static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base);
753static __u32 ftdi_2232h_baud_to_divisor(int baud);
748 754
749static struct usb_serial_driver ftdi_sio_device = { 755static struct usb_serial_driver ftdi_sio_device = {
750 .driver = { 756 .driver = {
@@ -839,6 +845,36 @@ static __u32 ftdi_232bm_baud_to_divisor(int baud)
839 return ftdi_232bm_baud_base_to_divisor(baud, 48000000); 845 return ftdi_232bm_baud_base_to_divisor(baud, 48000000);
840} 846}
841 847
848static __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
873static __u32 ftdi_2232h_baud_to_divisor(int baud)
874{
875 return ftdi_2232h_baud_base_to_divisor(baud, 120000000);
876}
877
842#define set_mctrl(port, set) update_mctrl((port), (set), 0) 878#define set_mctrl(port, set) update_mctrl((port), (set), 0)
843#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) 879#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear))
844 880
@@ -997,6 +1033,19 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
997 baud = 9600; 1033 baud = 9600;
998 } 1034 }
999 break; 1035 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;
1000 } /* priv->chip_type */ 1049 } /* priv->chip_type */
1001 1050
1002 if (div_okay) { 1051 if (div_okay) {
@@ -1197,14 +1246,29 @@ static void ftdi_determine_type(struct usb_serial_port *port)
1197 if (interfaces > 1) { 1246 if (interfaces > 1) {
1198 int inter; 1247 int inter;
1199 1248
1200 /* Multiple interfaces. Assume FT2232C. */ 1249 /* Multiple interfaces.*/
1201 priv->chip_type = FT2232C; 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
1202 /* Determine interface code. */ 1261 /* Determine interface code. */
1203 inter = serial->interface->altsetting->desc.bInterfaceNumber; 1262 inter = serial->interface->altsetting->desc.bInterfaceNumber;
1204 if (inter == 0) 1263 if (inter == 0) {
1205 priv->interface = PIT_SIOA; 1264 priv->interface = INTERFACE_A;
1206 else 1265 } else if (inter == 1) {
1207 priv->interface = PIT_SIOB; 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 }
1208 /* BM-type devices have a bug where bcdDevice gets set 1272 /* BM-type devices have a bug where bcdDevice gets set
1209 * to 0x200 when iSerialNumber is 0. */ 1273 * to 0x200 when iSerialNumber is 0. */
1210 if (version < 0x500) { 1274 if (version < 0x500) {
@@ -1315,7 +1379,9 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
1315 if ((!retval) && 1379 if ((!retval) &&
1316 (priv->chip_type == FT232BM || 1380 (priv->chip_type == FT232BM ||
1317 priv->chip_type == FT2232C || 1381 priv->chip_type == FT2232C ||
1318 priv->chip_type == FT232RL)) { 1382 priv->chip_type == FT232RL ||
1383 priv->chip_type == FT2232H ||
1384 priv->chip_type == FT4232H)) {
1319 retval = device_create_file(&port->dev, 1385 retval = device_create_file(&port->dev,
1320 &dev_attr_latency_timer); 1386 &dev_attr_latency_timer);
1321 } 1387 }
@@ -1334,7 +1400,9 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
1334 device_remove_file(&port->dev, &dev_attr_event_char); 1400 device_remove_file(&port->dev, &dev_attr_event_char);
1335 if (priv->chip_type == FT232BM || 1401 if (priv->chip_type == FT232BM ||
1336 priv->chip_type == FT2232C || 1402 priv->chip_type == FT2232C ||
1337 priv->chip_type == FT232RL) { 1403 priv->chip_type == FT232RL ||
1404 priv->chip_type == FT2232H ||
1405 priv->chip_type == FT4232H) {
1338 device_remove_file(&port->dev, &dev_attr_latency_timer); 1406 device_remove_file(&port->dev, &dev_attr_latency_timer);
1339 } 1407 }
1340 } 1408 }
@@ -2333,6 +2401,8 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
2333 case FT232BM: 2401 case FT232BM:
2334 case FT2232C: 2402 case FT2232C:
2335 case FT232RL: 2403 case FT232RL:
2404 case FT2232H:
2405 case FT4232H:
2336 /* the 8U232AM returns a two byte value (the sio is a 1 byte 2406 /* the 8U232AM returns a two byte value (the sio is a 1 byte
2337 value) - in the same format as the data returned from the in 2407 value) - in the same format as the data returned from the in
2338 point */ 2408 point */
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 0a09118f315e..f1d440a728a3 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -10,7 +10,7 @@
10 * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, 10 * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side,
11 * USB on the other. 11 * USB on the other.
12 * 12 *
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
14 * of the protocol required to talk to the device and ongoing assistence 14 * of the protocol required to talk to the device and ongoing assistence
15 * during development. 15 * during development.
16 * 16 *
@@ -28,6 +28,7 @@
28#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ 28#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
29#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ 29#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
30#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ 30#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */
31#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
31#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ 32#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */
32#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ 33#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */
33#define FTDI_NF_RIC_PID 0x0001 /* Product Id */ 34#define FTDI_NF_RIC_PID 0x0001 /* Product Id */
@@ -876,6 +877,11 @@
876#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */ 877#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */
877#define FTDI_SIO_GET_LATENCY_TIMER 10 /* Get the latency timer */ 878#define FTDI_SIO_GET_LATENCY_TIMER 10 /* Get the latency timer */
878 879
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
879 885
880/* 886/*
881 * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3 887 * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3
@@ -1039,6 +1045,8 @@ typedef enum {
1039 FT232BM = 3, 1045 FT232BM = 3,
1040 FT2232C = 4, 1046 FT2232C = 4,
1041 FT232RL = 5, 1047 FT232RL = 5,
1048 FT2232H = 6,
1049 FT4232H = 7
1042} ftdi_chip_type_t; 1050} ftdi_chip_type_t;
1043 1051
1044typedef enum { 1052typedef enum {