aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/cypress_m8.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/cypress_m8.c')
-rw-r--r--drivers/usb/serial/cypress_m8.c111
1 files changed, 66 insertions, 45 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 155b82a25d18..c42d3bdbe98c 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -122,6 +122,11 @@ static struct usb_driver cypress_driver = {
122 .no_dynamic_id = 1, 122 .no_dynamic_id = 1,
123}; 123};
124 124
125enum packet_format {
126 packet_format_1, /* b0:status, b1:payload count */
127 packet_format_2 /* b0[7:3]:status, b0[2:0]:payload count */
128};
129
125struct cypress_private { 130struct cypress_private {
126 spinlock_t lock; /* private lock */ 131 spinlock_t lock; /* private lock */
127 int chiptype; /* identifier of device, for quirks/etc */ 132 int chiptype; /* identifier of device, for quirks/etc */
@@ -139,6 +144,7 @@ struct cypress_private {
139 __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */ 144 __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */
140 __u8 current_config; /* stores the current configuration byte */ 145 __u8 current_config; /* stores the current configuration byte */
141 __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */ 146 __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */
147 enum packet_format pkt_fmt; /* format to use for packet send / receive */
142 int baud_rate; /* stores current baud rate in integer form */ 148 int baud_rate; /* stores current baud rate in integer form */
143 int cbr_mask; /* stores current baud rate in masked form */ 149 int cbr_mask; /* stores current baud rate in masked form */
144 int isthrottled; /* if throttled, discard reads */ 150 int isthrottled; /* if throttled, discard reads */
@@ -532,6 +538,17 @@ static int generic_startup (struct usb_serial *serial)
532 priv->termios_initialized = 0; 538 priv->termios_initialized = 0;
533 priv->rx_flags = 0; 539 priv->rx_flags = 0;
534 priv->cbr_mask = B300; 540 priv->cbr_mask = B300;
541 /* Default packet format setting is determined by packet size.
542 Anything with a size larger then 9 must have a separate
543 count field since the 3 bit count field is otherwise too
544 small. Otherwise we can use the slightly more compact
545 format. This is in accordance with the cypress_m8 serial
546 converter app note. */
547 if (port->interrupt_out_size > 9) {
548 priv->pkt_fmt = packet_format_1;
549 } else {
550 priv->pkt_fmt = packet_format_2;
551 }
535 if (interval > 0) { 552 if (interval > 0) {
536 priv->write_urb_interval = interval; 553 priv->write_urb_interval = interval;
537 priv->read_urb_interval = interval; 554 priv->read_urb_interval = interval;
@@ -564,6 +581,9 @@ static int cypress_earthmate_startup (struct usb_serial *serial)
564 581
565 priv = usb_get_serial_port_data(serial->port[0]); 582 priv = usb_get_serial_port_data(serial->port[0]);
566 priv->chiptype = CT_EARTHMATE; 583 priv->chiptype = CT_EARTHMATE;
584 /* All Earthmate devices use the separated-count packet
585 format! Idiotic. */
586 priv->pkt_fmt = packet_format_1;
567 587
568 return 0; 588 return 0;
569} /* cypress_earthmate_startup */ 589} /* cypress_earthmate_startup */
@@ -811,21 +831,18 @@ static void cypress_send(struct usb_serial_port *port)
811 memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size); 831 memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size);
812 832
813 spin_lock_irqsave(&priv->lock, flags); 833 spin_lock_irqsave(&priv->lock, flags);
814 switch (port->interrupt_out_size) { 834 switch (priv->pkt_fmt) {
815 case 32: 835 default:
816 /* this is for the CY7C64013... */ 836 case packet_format_1:
817 offset = 2; 837 /* this is for the CY7C64013... */
818 port->interrupt_out_buffer[0] = priv->line_control; 838 offset = 2;
819 break; 839 port->interrupt_out_buffer[0] = priv->line_control;
820 case 8: 840 break;
821 /* this is for the CY7C63743... */ 841 case packet_format_2:
822 offset = 1; 842 /* this is for the CY7C63743... */
823 port->interrupt_out_buffer[0] = priv->line_control; 843 offset = 1;
824 break; 844 port->interrupt_out_buffer[0] = priv->line_control;
825 default: 845 break;
826 dbg("%s - wrong packet size", __FUNCTION__);
827 spin_unlock_irqrestore(&priv->lock, flags);
828 return;
829 } 846 }
830 847
831 if (priv->line_control & CONTROL_RESET) 848 if (priv->line_control & CONTROL_RESET)
@@ -846,12 +863,13 @@ static void cypress_send(struct usb_serial_port *port)
846 return; 863 return;
847 } 864 }
848 865
849 switch (port->interrupt_out_size) { 866 switch (priv->pkt_fmt) {
850 case 32: 867 default:
851 port->interrupt_out_buffer[1] = count; 868 case packet_format_1:
852 break; 869 port->interrupt_out_buffer[1] = count;
853 case 8: 870 break;
854 port->interrupt_out_buffer[0] |= count; 871 case packet_format_2:
872 port->interrupt_out_buffer[0] |= count;
855 } 873 }
856 874
857 dbg("%s - count is %d", __FUNCTION__, count); 875 dbg("%s - count is %d", __FUNCTION__, count);
@@ -864,8 +882,9 @@ send:
864 if (priv->cmd_ctrl) 882 if (priv->cmd_ctrl)
865 actual_size = 1; 883 actual_size = 1;
866 else 884 else
867 actual_size = count + (port->interrupt_out_size == 32 ? 2 : 1); 885 actual_size = count +
868 886 (priv->pkt_fmt == packet_format_1 ? 2 : 1);
887
869 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size, 888 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size,
870 port->interrupt_out_urb->transfer_buffer); 889 port->interrupt_out_urb->transfer_buffer);
871 890
@@ -1331,30 +1350,32 @@ static void cypress_read_int_callback(struct urb *urb)
1331 } 1350 }
1332 1351
1333 spin_lock_irqsave(&priv->lock, flags); 1352 spin_lock_irqsave(&priv->lock, flags);
1334 switch(urb->actual_length) { 1353 result = urb->actual_length;
1335 case 32: 1354 switch (priv->pkt_fmt) {
1336 /* This is for the CY7C64013... */ 1355 default:
1337 priv->current_status = data[0] & 0xF8; 1356 case packet_format_1:
1338 bytes = data[1] + 2; 1357 /* This is for the CY7C64013... */
1339 i = 2; 1358 priv->current_status = data[0] & 0xF8;
1340 if (bytes > 2) 1359 bytes = data[1] + 2;
1341 havedata = 1; 1360 i = 2;
1342 break; 1361 if (bytes > 2)
1343 case 8: 1362 havedata = 1;
1344 /* This is for the CY7C63743... */ 1363 break;
1345 priv->current_status = data[0] & 0xF8; 1364 case packet_format_2:
1346 bytes = (data[0] & 0x07) + 1; 1365 /* This is for the CY7C63743... */
1347 i = 1; 1366 priv->current_status = data[0] & 0xF8;
1348 if (bytes > 1) 1367 bytes = (data[0] & 0x07) + 1;
1349 havedata = 1; 1368 i = 1;
1350 break; 1369 if (bytes > 1)
1351 default: 1370 havedata = 1;
1352 dbg("%s - wrong packet size - received %d bytes", 1371 break;
1353 __FUNCTION__, urb->actual_length);
1354 spin_unlock_irqrestore(&priv->lock, flags);
1355 goto continue_read;
1356 } 1372 }
1357 spin_unlock_irqrestore(&priv->lock, flags); 1373 spin_unlock_irqrestore(&priv->lock, flags);
1374 if (result < bytes) {
1375 dbg("%s - wrong packet size - received %d bytes but packet "
1376 "said %d bytes", __func__, result, bytes);
1377 goto continue_read;
1378 }
1358 1379
1359 usb_serial_debug_data (debug, &port->dev, __FUNCTION__, 1380 usb_serial_debug_data (debug, &port->dev, __FUNCTION__,
1360 urb->actual_length, data); 1381 urb->actual_length, data);