diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 90 |
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); | |||
745 | static unsigned short int ftdi_232am_baud_to_divisor(int baud); | 749 | static unsigned short int ftdi_232am_baud_to_divisor(int baud); |
746 | static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base); | 750 | static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base); |
747 | static __u32 ftdi_232bm_baud_to_divisor(int baud); | 751 | 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); | ||
748 | 754 | ||
749 | static struct usb_serial_driver ftdi_sio_device = { | 755 | static 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 | ||
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 | |||
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 */ |