aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ftdi_sio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r--drivers/usb/serial/ftdi_sio.c90
1 files changed, 80 insertions, 10 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 */