diff options
Diffstat (limited to 'drivers/usb/serial/mos7840.c')
-rw-r--r-- | drivers/usb/serial/mos7840.c | 298 |
1 files changed, 193 insertions, 105 deletions
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index c526550694a..29160f8b510 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -114,10 +114,10 @@ | |||
114 | #define USB_VENDOR_ID_MOSCHIP 0x9710 | 114 | #define USB_VENDOR_ID_MOSCHIP 0x9710 |
115 | #define MOSCHIP_DEVICE_ID_7840 0x7840 | 115 | #define MOSCHIP_DEVICE_ID_7840 0x7840 |
116 | #define MOSCHIP_DEVICE_ID_7820 0x7820 | 116 | #define MOSCHIP_DEVICE_ID_7820 0x7820 |
117 | #define MOSCHIP_DEVICE_ID_7810 0x7810 | ||
117 | /* The native component can have its vendor/device id's overridden | 118 | /* The native component can have its vendor/device id's overridden |
118 | * in vendor-specific implementations. Such devices can be handled | 119 | * in vendor-specific implementations. Such devices can be handled |
119 | * by making a change here, in moschip_port_id_table, and in | 120 | * by making a change here, in id_table. |
120 | * moschip_id_table_combined | ||
121 | */ | 121 | */ |
122 | #define USB_VENDOR_ID_BANDB 0x0856 | 122 | #define USB_VENDOR_ID_BANDB 0x0856 |
123 | #define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 | 123 | #define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 |
@@ -184,31 +184,16 @@ | |||
184 | #define NUM_URBS 16 /* URB Count */ | 184 | #define NUM_URBS 16 /* URB Count */ |
185 | #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ | 185 | #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ |
186 | 186 | ||
187 | /* LED on/off milliseconds*/ | ||
188 | #define LED_ON_MS 500 | ||
189 | #define LED_OFF_MS 500 | ||
187 | 190 | ||
188 | static const struct usb_device_id moschip_port_id_table[] = { | 191 | static int device_type; |
189 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, | ||
190 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, | ||
191 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, | ||
192 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, | ||
193 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, | ||
194 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)}, | ||
195 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, | ||
196 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, | ||
197 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, | ||
198 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, | ||
199 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, | ||
200 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)}, | ||
201 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, | ||
202 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)}, | ||
203 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, | ||
204 | {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, | ||
205 | {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, | ||
206 | {} /* terminating entry */ | ||
207 | }; | ||
208 | 192 | ||
209 | static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { | 193 | static const struct usb_device_id id_table[] __devinitconst = { |
210 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, | 194 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, |
211 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, | 195 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, |
196 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)}, | ||
212 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, | 197 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, |
213 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, | 198 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, |
214 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, | 199 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, |
@@ -226,8 +211,7 @@ static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { | |||
226 | {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, | 211 | {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, |
227 | {} /* terminating entry */ | 212 | {} /* terminating entry */ |
228 | }; | 213 | }; |
229 | 214 | MODULE_DEVICE_TABLE(usb, id_table); | |
230 | MODULE_DEVICE_TABLE(usb, moschip_id_table_combined); | ||
231 | 215 | ||
232 | /* This structure holds all of the local port information */ | 216 | /* This structure holds all of the local port information */ |
233 | 217 | ||
@@ -261,8 +245,13 @@ struct moschip_port { | |||
261 | struct urb *write_urb_pool[NUM_URBS]; | 245 | struct urb *write_urb_pool[NUM_URBS]; |
262 | char busy[NUM_URBS]; | 246 | char busy[NUM_URBS]; |
263 | bool read_urb_busy; | 247 | bool read_urb_busy; |
264 | }; | ||
265 | 248 | ||
249 | /* For device(s) with LED indicator */ | ||
250 | bool has_led; | ||
251 | bool led_flag; | ||
252 | struct timer_list led_timer1; /* Timer for LED on */ | ||
253 | struct timer_list led_timer2; /* Timer for LED off */ | ||
254 | }; | ||
266 | 255 | ||
267 | static bool debug; | 256 | static bool debug; |
268 | 257 | ||
@@ -572,6 +561,69 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, | |||
572 | return ret; | 561 | return ret; |
573 | } | 562 | } |
574 | 563 | ||
564 | static void mos7840_set_led_callback(struct urb *urb) | ||
565 | { | ||
566 | switch (urb->status) { | ||
567 | case 0: | ||
568 | /* Success */ | ||
569 | break; | ||
570 | case -ECONNRESET: | ||
571 | case -ENOENT: | ||
572 | case -ESHUTDOWN: | ||
573 | /* This urb is terminated, clean up */ | ||
574 | dbg("%s - urb shutting down with status: %d", __func__, | ||
575 | urb->status); | ||
576 | break; | ||
577 | default: | ||
578 | dbg("%s - nonzero urb status received: %d", __func__, | ||
579 | urb->status); | ||
580 | } | ||
581 | } | ||
582 | |||
583 | static void mos7840_set_led_async(struct moschip_port *mcs, __u16 wval, | ||
584 | __u16 reg) | ||
585 | { | ||
586 | struct usb_device *dev = mcs->port->serial->dev; | ||
587 | struct usb_ctrlrequest *dr = mcs->dr; | ||
588 | |||
589 | dr->bRequestType = MCS_WR_RTYPE; | ||
590 | dr->bRequest = MCS_WRREQ; | ||
591 | dr->wValue = cpu_to_le16(wval); | ||
592 | dr->wIndex = cpu_to_le16(reg); | ||
593 | dr->wLength = cpu_to_le16(0); | ||
594 | |||
595 | usb_fill_control_urb(mcs->control_urb, dev, usb_sndctrlpipe(dev, 0), | ||
596 | (unsigned char *)dr, NULL, 0, mos7840_set_led_callback, NULL); | ||
597 | |||
598 | usb_submit_urb(mcs->control_urb, GFP_ATOMIC); | ||
599 | } | ||
600 | |||
601 | static void mos7840_set_led_sync(struct usb_serial_port *port, __u16 reg, | ||
602 | __u16 val) | ||
603 | { | ||
604 | struct usb_device *dev = port->serial->dev; | ||
605 | |||
606 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, MCS_WR_RTYPE, | ||
607 | val, reg, NULL, 0, MOS_WDR_TIMEOUT); | ||
608 | } | ||
609 | |||
610 | static void mos7840_led_off(unsigned long arg) | ||
611 | { | ||
612 | struct moschip_port *mcs = (struct moschip_port *) arg; | ||
613 | |||
614 | /* Turn off LED */ | ||
615 | mos7840_set_led_async(mcs, 0x0300, MODEM_CONTROL_REGISTER); | ||
616 | mod_timer(&mcs->led_timer2, | ||
617 | jiffies + msecs_to_jiffies(LED_OFF_MS)); | ||
618 | } | ||
619 | |||
620 | static void mos7840_led_flag_off(unsigned long arg) | ||
621 | { | ||
622 | struct moschip_port *mcs = (struct moschip_port *) arg; | ||
623 | |||
624 | mcs->led_flag = false; | ||
625 | } | ||
626 | |||
575 | /***************************************************************************** | 627 | /***************************************************************************** |
576 | * mos7840_interrupt_callback | 628 | * mos7840_interrupt_callback |
577 | * this is the callback function for when we have received data on the | 629 | * this is the callback function for when we have received data on the |
@@ -591,8 +643,6 @@ static void mos7840_interrupt_callback(struct urb *urb) | |||
591 | __u16 wval, wreg = 0; | 643 | __u16 wval, wreg = 0; |
592 | int status = urb->status; | 644 | int status = urb->status; |
593 | 645 | ||
594 | dbg("%s", " : Entering"); | ||
595 | |||
596 | switch (status) { | 646 | switch (status) { |
597 | case 0: | 647 | case 0: |
598 | /* success */ | 648 | /* success */ |
@@ -766,12 +816,8 @@ static void mos7840_bulk_in_callback(struct urb *urb) | |||
766 | return; | 816 | return; |
767 | } | 817 | } |
768 | 818 | ||
769 | dbg("%s", "Entering... "); | ||
770 | |||
771 | data = urb->transfer_buffer; | 819 | data = urb->transfer_buffer; |
772 | 820 | ||
773 | dbg("%s", "Entering ..........."); | ||
774 | |||
775 | if (urb->actual_length) { | 821 | if (urb->actual_length) { |
776 | tty = tty_port_tty_get(&mos7840_port->port->port); | 822 | tty = tty_port_tty_get(&mos7840_port->port->port); |
777 | if (tty) { | 823 | if (tty) { |
@@ -792,6 +838,14 @@ static void mos7840_bulk_in_callback(struct urb *urb) | |||
792 | return; | 838 | return; |
793 | } | 839 | } |
794 | 840 | ||
841 | /* Turn on LED */ | ||
842 | if (mos7840_port->has_led && !mos7840_port->led_flag) { | ||
843 | mos7840_port->led_flag = true; | ||
844 | mos7840_set_led_async(mos7840_port, 0x0301, | ||
845 | MODEM_CONTROL_REGISTER); | ||
846 | mod_timer(&mos7840_port->led_timer1, | ||
847 | jiffies + msecs_to_jiffies(LED_ON_MS)); | ||
848 | } | ||
795 | 849 | ||
796 | mos7840_port->read_urb_busy = true; | 850 | mos7840_port->read_urb_busy = true; |
797 | retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | 851 | retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); |
@@ -835,8 +889,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) | |||
835 | return; | 889 | return; |
836 | } | 890 | } |
837 | 891 | ||
838 | dbg("%s", "Entering ........."); | ||
839 | |||
840 | tty = tty_port_tty_get(&mos7840_port->port->port); | 892 | tty = tty_port_tty_get(&mos7840_port->port->port); |
841 | if (tty && mos7840_port->open) | 893 | if (tty && mos7840_port->open) |
842 | tty_wakeup(tty); | 894 | tty_wakeup(tty); |
@@ -878,8 +930,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
878 | struct moschip_port *mos7840_port; | 930 | struct moschip_port *mos7840_port; |
879 | struct moschip_port *port0; | 931 | struct moschip_port *port0; |
880 | 932 | ||
881 | dbg ("%s enter", __func__); | ||
882 | |||
883 | if (mos7840_port_paranoia_check(port, __func__)) { | 933 | if (mos7840_port_paranoia_check(port, __func__)) { |
884 | dbg("%s", "Port Paranoia failed"); | 934 | dbg("%s", "Port Paranoia failed"); |
885 | return -ENODEV; | 935 | return -ENODEV; |
@@ -1151,10 +1201,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1151 | dbg("usb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p", | 1201 | dbg("usb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p", |
1152 | serial, mos7840_port, port); | 1202 | serial, mos7840_port, port); |
1153 | 1203 | ||
1154 | dbg ("%s leave", __func__); | ||
1155 | |||
1156 | return 0; | 1204 | return 0; |
1157 | |||
1158 | } | 1205 | } |
1159 | 1206 | ||
1160 | /***************************************************************************** | 1207 | /***************************************************************************** |
@@ -1175,18 +1222,14 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) | |||
1175 | unsigned long flags; | 1222 | unsigned long flags; |
1176 | struct moschip_port *mos7840_port; | 1223 | struct moschip_port *mos7840_port; |
1177 | 1224 | ||
1178 | dbg("%s", " mos7840_chars_in_buffer:entering ..........."); | ||
1179 | |||
1180 | if (mos7840_port_paranoia_check(port, __func__)) { | 1225 | if (mos7840_port_paranoia_check(port, __func__)) { |
1181 | dbg("%s", "Invalid port"); | 1226 | dbg("%s", "Invalid port"); |
1182 | return 0; | 1227 | return 0; |
1183 | } | 1228 | } |
1184 | 1229 | ||
1185 | mos7840_port = mos7840_get_port_private(port); | 1230 | mos7840_port = mos7840_get_port_private(port); |
1186 | if (mos7840_port == NULL) { | 1231 | if (mos7840_port == NULL) |
1187 | dbg("%s", "mos7840_break:leaving ..........."); | ||
1188 | return 0; | 1232 | return 0; |
1189 | } | ||
1190 | 1233 | ||
1191 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); | 1234 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); |
1192 | for (i = 0; i < NUM_URBS; ++i) | 1235 | for (i = 0; i < NUM_URBS; ++i) |
@@ -1211,8 +1254,6 @@ static void mos7840_close(struct usb_serial_port *port) | |||
1211 | int j; | 1254 | int j; |
1212 | __u16 Data; | 1255 | __u16 Data; |
1213 | 1256 | ||
1214 | dbg("%s", "mos7840_close:entering..."); | ||
1215 | |||
1216 | if (mos7840_port_paranoia_check(port, __func__)) { | 1257 | if (mos7840_port_paranoia_check(port, __func__)) { |
1217 | dbg("%s", "Port Paranoia failed"); | 1258 | dbg("%s", "Port Paranoia failed"); |
1218 | return; | 1259 | return; |
@@ -1287,8 +1328,6 @@ static void mos7840_close(struct usb_serial_port *port) | |||
1287 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | 1328 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); |
1288 | 1329 | ||
1289 | mos7840_port->open = 0; | 1330 | mos7840_port->open = 0; |
1290 | |||
1291 | dbg("%s", "Leaving ............"); | ||
1292 | } | 1331 | } |
1293 | 1332 | ||
1294 | /************************************************************************ | 1333 | /************************************************************************ |
@@ -1343,9 +1382,6 @@ static void mos7840_break(struct tty_struct *tty, int break_state) | |||
1343 | struct usb_serial *serial; | 1382 | struct usb_serial *serial; |
1344 | struct moschip_port *mos7840_port; | 1383 | struct moschip_port *mos7840_port; |
1345 | 1384 | ||
1346 | dbg("%s", "Entering ..........."); | ||
1347 | dbg("mos7840_break: Start"); | ||
1348 | |||
1349 | if (mos7840_port_paranoia_check(port, __func__)) { | 1385 | if (mos7840_port_paranoia_check(port, __func__)) { |
1350 | dbg("%s", "Port Paranoia failed"); | 1386 | dbg("%s", "Port Paranoia failed"); |
1351 | return; | 1387 | return; |
@@ -1395,8 +1431,6 @@ static int mos7840_write_room(struct tty_struct *tty) | |||
1395 | unsigned long flags; | 1431 | unsigned long flags; |
1396 | struct moschip_port *mos7840_port; | 1432 | struct moschip_port *mos7840_port; |
1397 | 1433 | ||
1398 | dbg("%s", " mos7840_write_room:entering ..........."); | ||
1399 | |||
1400 | if (mos7840_port_paranoia_check(port, __func__)) { | 1434 | if (mos7840_port_paranoia_check(port, __func__)) { |
1401 | dbg("%s", "Invalid port"); | 1435 | dbg("%s", "Invalid port"); |
1402 | dbg("%s", " mos7840_write_room:leaving ..........."); | 1436 | dbg("%s", " mos7840_write_room:leaving ..........."); |
@@ -1445,9 +1479,6 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1445 | /* __u16 Data; */ | 1479 | /* __u16 Data; */ |
1446 | const unsigned char *current_position = data; | 1480 | const unsigned char *current_position = data; |
1447 | unsigned char *data1; | 1481 | unsigned char *data1; |
1448 | dbg("%s", "entering ..........."); | ||
1449 | /* dbg("mos7840_write: mos7840_port->shadowLCR is %x", | ||
1450 | mos7840_port->shadowLCR); */ | ||
1451 | 1482 | ||
1452 | #ifdef NOTMOS7840 | 1483 | #ifdef NOTMOS7840 |
1453 | Data = 0x00; | 1484 | Data = 0x00; |
@@ -1554,6 +1585,14 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1554 | data1 = urb->transfer_buffer; | 1585 | data1 = urb->transfer_buffer; |
1555 | dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress); | 1586 | dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress); |
1556 | 1587 | ||
1588 | /* Turn on LED */ | ||
1589 | if (mos7840_port->has_led && !mos7840_port->led_flag) { | ||
1590 | mos7840_port->led_flag = true; | ||
1591 | mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0301); | ||
1592 | mod_timer(&mos7840_port->led_timer1, | ||
1593 | jiffies + msecs_to_jiffies(LED_ON_MS)); | ||
1594 | } | ||
1595 | |||
1557 | /* send it down the pipe */ | 1596 | /* send it down the pipe */ |
1558 | status = usb_submit_urb(urb, GFP_ATOMIC); | 1597 | status = usb_submit_urb(urb, GFP_ATOMIC); |
1559 | 1598 | ||
@@ -1602,8 +1641,6 @@ static void mos7840_throttle(struct tty_struct *tty) | |||
1602 | return; | 1641 | return; |
1603 | } | 1642 | } |
1604 | 1643 | ||
1605 | dbg("%s", "Entering .........."); | ||
1606 | |||
1607 | /* if we are implementing XON/XOFF, send the stop character */ | 1644 | /* if we are implementing XON/XOFF, send the stop character */ |
1608 | if (I_IXOFF(tty)) { | 1645 | if (I_IXOFF(tty)) { |
1609 | unsigned char stop_char = STOP_CHAR(tty); | 1646 | unsigned char stop_char = STOP_CHAR(tty); |
@@ -1646,8 +1683,6 @@ static void mos7840_unthrottle(struct tty_struct *tty) | |||
1646 | return; | 1683 | return; |
1647 | } | 1684 | } |
1648 | 1685 | ||
1649 | dbg("%s", "Entering .........."); | ||
1650 | |||
1651 | /* if we are implementing XON/XOFF, send the start character */ | 1686 | /* if we are implementing XON/XOFF, send the start character */ |
1652 | if (I_IXOFF(tty)) { | 1687 | if (I_IXOFF(tty)) { |
1653 | unsigned char start_char = START_CHAR(tty); | 1688 | unsigned char start_char = START_CHAR(tty); |
@@ -1676,8 +1711,6 @@ static int mos7840_tiocmget(struct tty_struct *tty) | |||
1676 | int status; | 1711 | int status; |
1677 | mos7840_port = mos7840_get_port_private(port); | 1712 | mos7840_port = mos7840_get_port_private(port); |
1678 | 1713 | ||
1679 | dbg("%s - port %d", __func__, port->number); | ||
1680 | |||
1681 | if (mos7840_port == NULL) | 1714 | if (mos7840_port == NULL) |
1682 | return -ENODEV; | 1715 | return -ENODEV; |
1683 | 1716 | ||
@@ -1704,8 +1737,6 @@ static int mos7840_tiocmset(struct tty_struct *tty, | |||
1704 | unsigned int mcr; | 1737 | unsigned int mcr; |
1705 | int status; | 1738 | int status; |
1706 | 1739 | ||
1707 | dbg("%s - port %d", __func__, port->number); | ||
1708 | |||
1709 | mos7840_port = mos7840_get_port_private(port); | 1740 | mos7840_port = mos7840_get_port_private(port); |
1710 | 1741 | ||
1711 | if (mos7840_port == NULL) | 1742 | if (mos7840_port == NULL) |
@@ -1746,7 +1777,6 @@ static int mos7840_tiocmset(struct tty_struct *tty, | |||
1746 | static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, | 1777 | static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, |
1747 | __u16 *clk_sel_val) | 1778 | __u16 *clk_sel_val) |
1748 | { | 1779 | { |
1749 | |||
1750 | dbg("%s - %d", __func__, baudRate); | 1780 | dbg("%s - %d", __func__, baudRate); |
1751 | 1781 | ||
1752 | if (baudRate <= 115200) { | 1782 | if (baudRate <= 115200) { |
@@ -1839,8 +1869,6 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, | |||
1839 | return -1; | 1869 | return -1; |
1840 | } | 1870 | } |
1841 | 1871 | ||
1842 | dbg("%s", "Entering .........."); | ||
1843 | |||
1844 | number = mos7840_port->port->number - mos7840_port->port->serial->minor; | 1872 | number = mos7840_port->port->number - mos7840_port->port->serial->minor; |
1845 | 1873 | ||
1846 | dbg("%s - port = %d, baud = %d", __func__, | 1874 | dbg("%s - port = %d, baud = %d", __func__, |
@@ -1966,8 +1994,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty, | |||
1966 | return; | 1994 | return; |
1967 | } | 1995 | } |
1968 | 1996 | ||
1969 | dbg("%s", "Entering .........."); | ||
1970 | |||
1971 | lData = LCR_BITS_8; | 1997 | lData = LCR_BITS_8; |
1972 | lStop = LCR_STOP_1; | 1998 | lStop = LCR_STOP_1; |
1973 | lParity = LCR_PAR_NONE; | 1999 | lParity = LCR_PAR_NONE; |
@@ -2108,7 +2134,7 @@ static void mos7840_set_termios(struct tty_struct *tty, | |||
2108 | unsigned int cflag; | 2134 | unsigned int cflag; |
2109 | struct usb_serial *serial; | 2135 | struct usb_serial *serial; |
2110 | struct moschip_port *mos7840_port; | 2136 | struct moschip_port *mos7840_port; |
2111 | dbg("mos7840_set_termios: START"); | 2137 | |
2112 | if (mos7840_port_paranoia_check(port, __func__)) { | 2138 | if (mos7840_port_paranoia_check(port, __func__)) { |
2113 | dbg("%s", "Invalid port"); | 2139 | dbg("%s", "Invalid port"); |
2114 | return; | 2140 | return; |
@@ -2327,28 +2353,74 @@ static int mos7840_ioctl(struct tty_struct *tty, | |||
2327 | return -ENOIOCTLCMD; | 2353 | return -ENOIOCTLCMD; |
2328 | } | 2354 | } |
2329 | 2355 | ||
2356 | static int mos7810_check(struct usb_serial *serial) | ||
2357 | { | ||
2358 | int i, pass_count = 0; | ||
2359 | __u16 data = 0, mcr_data = 0; | ||
2360 | __u16 test_pattern = 0x55AA; | ||
2361 | |||
2362 | /* Store MCR setting */ | ||
2363 | usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
2364 | MCS_RDREQ, MCS_RD_RTYPE, 0x0300, MODEM_CONTROL_REGISTER, | ||
2365 | &mcr_data, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); | ||
2366 | |||
2367 | for (i = 0; i < 16; i++) { | ||
2368 | /* Send the 1-bit test pattern out to MCS7810 test pin */ | ||
2369 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
2370 | MCS_WRREQ, MCS_WR_RTYPE, | ||
2371 | (0x0300 | (((test_pattern >> i) & 0x0001) << 1)), | ||
2372 | MODEM_CONTROL_REGISTER, NULL, 0, MOS_WDR_TIMEOUT); | ||
2373 | |||
2374 | /* Read the test pattern back */ | ||
2375 | usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
2376 | MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data, | ||
2377 | VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); | ||
2378 | |||
2379 | /* If this is a MCS7810 device, both test patterns must match */ | ||
2380 | if (((test_pattern >> i) ^ (~data >> 1)) & 0x0001) | ||
2381 | break; | ||
2382 | |||
2383 | pass_count++; | ||
2384 | } | ||
2385 | |||
2386 | /* Restore MCR setting */ | ||
2387 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCS_WRREQ, | ||
2388 | MCS_WR_RTYPE, 0x0300 | mcr_data, MODEM_CONTROL_REGISTER, NULL, | ||
2389 | 0, MOS_WDR_TIMEOUT); | ||
2390 | |||
2391 | if (pass_count == 16) | ||
2392 | return 1; | ||
2393 | |||
2394 | return 0; | ||
2395 | } | ||
2396 | |||
2330 | static int mos7840_calc_num_ports(struct usb_serial *serial) | 2397 | static int mos7840_calc_num_ports(struct usb_serial *serial) |
2331 | { | 2398 | { |
2332 | __u16 Data = 0x00; | 2399 | __u16 data = 0x00; |
2333 | int ret = 0; | ||
2334 | int mos7840_num_ports; | 2400 | int mos7840_num_ports; |
2335 | 2401 | ||
2336 | ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 2402 | usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
2337 | MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data, | 2403 | MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data, |
2338 | VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); | 2404 | VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); |
2339 | 2405 | ||
2340 | if ((Data & 0x01) == 0) { | 2406 | if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 || |
2341 | mos7840_num_ports = 2; | 2407 | serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) { |
2342 | serial->num_bulk_in = 2; | 2408 | device_type = serial->dev->descriptor.idProduct; |
2343 | serial->num_bulk_out = 2; | ||
2344 | serial->num_ports = 2; | ||
2345 | } else { | 2409 | } else { |
2346 | mos7840_num_ports = 4; | 2410 | /* For a MCS7840 device GPIO0 must be set to 1 */ |
2347 | serial->num_bulk_in = 4; | 2411 | if ((data & 0x01) == 1) |
2348 | serial->num_bulk_out = 4; | 2412 | device_type = MOSCHIP_DEVICE_ID_7840; |
2349 | serial->num_ports = 4; | 2413 | else if (mos7810_check(serial)) |
2414 | device_type = MOSCHIP_DEVICE_ID_7810; | ||
2415 | else | ||
2416 | device_type = MOSCHIP_DEVICE_ID_7820; | ||
2350 | } | 2417 | } |
2351 | 2418 | ||
2419 | mos7840_num_ports = (device_type >> 4) & 0x000F; | ||
2420 | serial->num_bulk_in = mos7840_num_ports; | ||
2421 | serial->num_bulk_out = mos7840_num_ports; | ||
2422 | serial->num_ports = mos7840_num_ports; | ||
2423 | |||
2352 | return mos7840_num_ports; | 2424 | return mos7840_num_ports; |
2353 | } | 2425 | } |
2354 | 2426 | ||
@@ -2361,9 +2433,7 @@ static int mos7840_startup(struct usb_serial *serial) | |||
2361 | struct moschip_port *mos7840_port; | 2433 | struct moschip_port *mos7840_port; |
2362 | struct usb_device *dev; | 2434 | struct usb_device *dev; |
2363 | int i, status; | 2435 | int i, status; |
2364 | |||
2365 | __u16 Data; | 2436 | __u16 Data; |
2366 | dbg("%s", "mos7840_startup :Entering.........."); | ||
2367 | 2437 | ||
2368 | if (!serial) { | 2438 | if (!serial) { |
2369 | dbg("%s", "Invalid Handler"); | 2439 | dbg("%s", "Invalid Handler"); |
@@ -2372,9 +2442,6 @@ static int mos7840_startup(struct usb_serial *serial) | |||
2372 | 2442 | ||
2373 | dev = serial->dev; | 2443 | dev = serial->dev; |
2374 | 2444 | ||
2375 | dbg("%s", "Entering..."); | ||
2376 | dbg ("mos7840_startup: serial = %p", serial); | ||
2377 | |||
2378 | /* we set up the pointers to the endpoints in the mos7840_open * | 2445 | /* we set up the pointers to the endpoints in the mos7840_open * |
2379 | * function, as the structures aren't created yet. */ | 2446 | * function, as the structures aren't created yet. */ |
2380 | 2447 | ||
@@ -2563,6 +2630,34 @@ static int mos7840_startup(struct usb_serial *serial) | |||
2563 | status = -ENOMEM; | 2630 | status = -ENOMEM; |
2564 | goto error; | 2631 | goto error; |
2565 | } | 2632 | } |
2633 | |||
2634 | mos7840_port->has_led = false; | ||
2635 | |||
2636 | /* Initialize LED timers */ | ||
2637 | if (device_type == MOSCHIP_DEVICE_ID_7810) { | ||
2638 | mos7840_port->has_led = true; | ||
2639 | |||
2640 | init_timer(&mos7840_port->led_timer1); | ||
2641 | mos7840_port->led_timer1.function = mos7840_led_off; | ||
2642 | mos7840_port->led_timer1.expires = | ||
2643 | jiffies + msecs_to_jiffies(LED_ON_MS); | ||
2644 | mos7840_port->led_timer1.data = | ||
2645 | (unsigned long)mos7840_port; | ||
2646 | |||
2647 | init_timer(&mos7840_port->led_timer2); | ||
2648 | mos7840_port->led_timer2.function = | ||
2649 | mos7840_led_flag_off; | ||
2650 | mos7840_port->led_timer2.expires = | ||
2651 | jiffies + msecs_to_jiffies(LED_OFF_MS); | ||
2652 | mos7840_port->led_timer2.data = | ||
2653 | (unsigned long)mos7840_port; | ||
2654 | |||
2655 | mos7840_port->led_flag = false; | ||
2656 | |||
2657 | /* Turn off LED */ | ||
2658 | mos7840_set_led_sync(serial->port[i], | ||
2659 | MODEM_CONTROL_REGISTER, 0x0300); | ||
2660 | } | ||
2566 | } | 2661 | } |
2567 | dbg ("mos7840_startup: all ports configured..........."); | 2662 | dbg ("mos7840_startup: all ports configured..........."); |
2568 | 2663 | ||
@@ -2602,7 +2697,6 @@ static void mos7840_disconnect(struct usb_serial *serial) | |||
2602 | int i; | 2697 | int i; |
2603 | unsigned long flags; | 2698 | unsigned long flags; |
2604 | struct moschip_port *mos7840_port; | 2699 | struct moschip_port *mos7840_port; |
2605 | dbg("%s", " disconnect :entering.........."); | ||
2606 | 2700 | ||
2607 | if (!serial) { | 2701 | if (!serial) { |
2608 | dbg("%s", "Invalid Handler"); | 2702 | dbg("%s", "Invalid Handler"); |
@@ -2624,9 +2718,6 @@ static void mos7840_disconnect(struct usb_serial *serial) | |||
2624 | usb_kill_urb(mos7840_port->control_urb); | 2718 | usb_kill_urb(mos7840_port->control_urb); |
2625 | } | 2719 | } |
2626 | } | 2720 | } |
2627 | |||
2628 | dbg("%s", "Thank u :: "); | ||
2629 | |||
2630 | } | 2721 | } |
2631 | 2722 | ||
2632 | /**************************************************************************** | 2723 | /**************************************************************************** |
@@ -2638,7 +2729,6 @@ static void mos7840_release(struct usb_serial *serial) | |||
2638 | { | 2729 | { |
2639 | int i; | 2730 | int i; |
2640 | struct moschip_port *mos7840_port; | 2731 | struct moschip_port *mos7840_port; |
2641 | dbg("%s", " release :entering.........."); | ||
2642 | 2732 | ||
2643 | if (!serial) { | 2733 | if (!serial) { |
2644 | dbg("%s", "Invalid Handler"); | 2734 | dbg("%s", "Invalid Handler"); |
@@ -2654,30 +2744,28 @@ static void mos7840_release(struct usb_serial *serial) | |||
2654 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 2744 | mos7840_port = mos7840_get_port_private(serial->port[i]); |
2655 | dbg("mos7840_port %d = %p", i, mos7840_port); | 2745 | dbg("mos7840_port %d = %p", i, mos7840_port); |
2656 | if (mos7840_port) { | 2746 | if (mos7840_port) { |
2747 | if (mos7840_port->has_led) { | ||
2748 | /* Turn off LED */ | ||
2749 | mos7840_set_led_sync(mos7840_port->port, | ||
2750 | MODEM_CONTROL_REGISTER, 0x0300); | ||
2751 | |||
2752 | del_timer_sync(&mos7840_port->led_timer1); | ||
2753 | del_timer_sync(&mos7840_port->led_timer2); | ||
2754 | } | ||
2657 | kfree(mos7840_port->ctrl_buf); | 2755 | kfree(mos7840_port->ctrl_buf); |
2658 | kfree(mos7840_port->dr); | 2756 | kfree(mos7840_port->dr); |
2659 | kfree(mos7840_port); | 2757 | kfree(mos7840_port); |
2660 | } | 2758 | } |
2661 | } | 2759 | } |
2662 | |||
2663 | dbg("%s", "Thank u :: "); | ||
2664 | |||
2665 | } | 2760 | } |
2666 | 2761 | ||
2667 | static struct usb_driver io_driver = { | ||
2668 | .name = "mos7840", | ||
2669 | .probe = usb_serial_probe, | ||
2670 | .disconnect = usb_serial_disconnect, | ||
2671 | .id_table = moschip_id_table_combined, | ||
2672 | }; | ||
2673 | |||
2674 | static struct usb_serial_driver moschip7840_4port_device = { | 2762 | static struct usb_serial_driver moschip7840_4port_device = { |
2675 | .driver = { | 2763 | .driver = { |
2676 | .owner = THIS_MODULE, | 2764 | .owner = THIS_MODULE, |
2677 | .name = "mos7840", | 2765 | .name = "mos7840", |
2678 | }, | 2766 | }, |
2679 | .description = DRIVER_DESC, | 2767 | .description = DRIVER_DESC, |
2680 | .id_table = moschip_port_id_table, | 2768 | .id_table = id_table, |
2681 | .num_ports = 4, | 2769 | .num_ports = 4, |
2682 | .open = mos7840_open, | 2770 | .open = mos7840_open, |
2683 | .close = mos7840_close, | 2771 | .close = mos7840_close, |
@@ -2707,7 +2795,7 @@ static struct usb_serial_driver * const serial_drivers[] = { | |||
2707 | &moschip7840_4port_device, NULL | 2795 | &moschip7840_4port_device, NULL |
2708 | }; | 2796 | }; |
2709 | 2797 | ||
2710 | module_usb_serial_driver(io_driver, serial_drivers); | 2798 | module_usb_serial_driver(serial_drivers, id_table); |
2711 | 2799 | ||
2712 | MODULE_DESCRIPTION(DRIVER_DESC); | 2800 | MODULE_DESCRIPTION(DRIVER_DESC); |
2713 | MODULE_LICENSE("GPL"); | 2801 | MODULE_LICENSE("GPL"); |