diff options
Diffstat (limited to 'drivers/usb/serial/keyspan.c')
-rw-r--r-- | drivers/usb/serial/keyspan.c | 78 |
1 files changed, 42 insertions, 36 deletions
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 3df8a66c5c3c..11e439b90eac 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
@@ -105,6 +105,8 @@ | |||
105 | #include <linux/tty_flip.h> | 105 | #include <linux/tty_flip.h> |
106 | #include <linux/module.h> | 106 | #include <linux/module.h> |
107 | #include <linux/spinlock.h> | 107 | #include <linux/spinlock.h> |
108 | #include <linux/firmware.h> | ||
109 | #include <linux/ihex.h> | ||
108 | #include <asm/uaccess.h> | 110 | #include <asm/uaccess.h> |
109 | #include <linux/usb.h> | 111 | #include <linux/usb.h> |
110 | #include <linux/usb/serial.h> | 112 | #include <linux/usb/serial.h> |
@@ -1339,13 +1341,13 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp) | |||
1339 | port->tty = NULL; | 1341 | port->tty = NULL; |
1340 | } | 1342 | } |
1341 | 1343 | ||
1342 | |||
1343 | /* download the firmware to a pre-renumeration device */ | 1344 | /* download the firmware to a pre-renumeration device */ |
1344 | static int keyspan_fake_startup (struct usb_serial *serial) | 1345 | static int keyspan_fake_startup (struct usb_serial *serial) |
1345 | { | 1346 | { |
1346 | int response; | 1347 | int response; |
1347 | const struct ezusb_hex_record *record; | 1348 | const struct ihex_binrec *record; |
1348 | char *fw_name; | 1349 | char *fw_name; |
1350 | const struct firmware *fw; | ||
1349 | 1351 | ||
1350 | dbg("Keyspan startup version %04x product %04x", | 1352 | dbg("Keyspan startup version %04x product %04x", |
1351 | le16_to_cpu(serial->dev->descriptor.bcdDevice), | 1353 | le16_to_cpu(serial->dev->descriptor.bcdDevice), |
@@ -1359,72 +1361,60 @@ static int keyspan_fake_startup (struct usb_serial *serial) | |||
1359 | /* Select firmware image on the basis of idProduct */ | 1361 | /* Select firmware image on the basis of idProduct */ |
1360 | switch (le16_to_cpu(serial->dev->descriptor.idProduct)) { | 1362 | switch (le16_to_cpu(serial->dev->descriptor.idProduct)) { |
1361 | case keyspan_usa28_pre_product_id: | 1363 | case keyspan_usa28_pre_product_id: |
1362 | record = &keyspan_usa28_firmware[0]; | 1364 | fw_name = "keyspan/usa28.fw"; |
1363 | fw_name = "USA28"; | ||
1364 | break; | 1365 | break; |
1365 | 1366 | ||
1366 | case keyspan_usa28x_pre_product_id: | 1367 | case keyspan_usa28x_pre_product_id: |
1367 | record = &keyspan_usa28x_firmware[0]; | 1368 | fw_name = "keyspan/usa28x.fw"; |
1368 | fw_name = "USA28X"; | ||
1369 | break; | 1369 | break; |
1370 | 1370 | ||
1371 | case keyspan_usa28xa_pre_product_id: | 1371 | case keyspan_usa28xa_pre_product_id: |
1372 | record = &keyspan_usa28xa_firmware[0]; | 1372 | fw_name = "keyspan/usa28xa.fw"; |
1373 | fw_name = "USA28XA"; | ||
1374 | break; | 1373 | break; |
1375 | 1374 | ||
1376 | case keyspan_usa28xb_pre_product_id: | 1375 | case keyspan_usa28xb_pre_product_id: |
1377 | record = &keyspan_usa28xb_firmware[0]; | 1376 | fw_name = "keyspan/usa28xb.fw"; |
1378 | fw_name = "USA28XB"; | ||
1379 | break; | 1377 | break; |
1380 | 1378 | ||
1381 | case keyspan_usa19_pre_product_id: | 1379 | case keyspan_usa19_pre_product_id: |
1382 | record = &keyspan_usa19_firmware[0]; | 1380 | fw_name = "keyspan/usa19.fw"; |
1383 | fw_name = "USA19"; | ||
1384 | break; | 1381 | break; |
1385 | 1382 | ||
1386 | case keyspan_usa19qi_pre_product_id: | 1383 | case keyspan_usa19qi_pre_product_id: |
1387 | record = &keyspan_usa19qi_firmware[0]; | 1384 | fw_name = "keyspan/usa19qi.fw"; |
1388 | fw_name = "USA19QI"; | ||
1389 | break; | 1385 | break; |
1390 | 1386 | ||
1391 | case keyspan_mpr_pre_product_id: | 1387 | case keyspan_mpr_pre_product_id: |
1392 | record = &keyspan_mpr_firmware[0]; | 1388 | fw_name = "keyspan/mpr.fw"; |
1393 | fw_name = "MPR"; | ||
1394 | break; | 1389 | break; |
1395 | 1390 | ||
1396 | case keyspan_usa19qw_pre_product_id: | 1391 | case keyspan_usa19qw_pre_product_id: |
1397 | record = &keyspan_usa19qw_firmware[0]; | 1392 | fw_name = "keyspan/usa19qw.fw"; |
1398 | fw_name = "USA19QI"; | ||
1399 | break; | 1393 | break; |
1400 | 1394 | ||
1401 | case keyspan_usa18x_pre_product_id: | 1395 | case keyspan_usa18x_pre_product_id: |
1402 | record = &keyspan_usa18x_firmware[0]; | 1396 | fw_name = "keyspan/usa18x.fw"; |
1403 | fw_name = "USA18X"; | ||
1404 | break; | 1397 | break; |
1405 | 1398 | ||
1406 | case keyspan_usa19w_pre_product_id: | 1399 | case keyspan_usa19w_pre_product_id: |
1407 | record = &keyspan_usa19w_firmware[0]; | 1400 | fw_name = "keyspan/usa19w.fw"; |
1408 | fw_name = "USA19W"; | ||
1409 | break; | 1401 | break; |
1410 | 1402 | ||
1411 | case keyspan_usa49w_pre_product_id: | 1403 | case keyspan_usa49w_pre_product_id: |
1412 | record = &keyspan_usa49w_firmware[0]; | 1404 | fw_name = "keyspan/usa49w.fw"; |
1413 | fw_name = "USA49W"; | ||
1414 | break; | 1405 | break; |
1415 | 1406 | ||
1416 | case keyspan_usa49wlc_pre_product_id: | 1407 | case keyspan_usa49wlc_pre_product_id: |
1417 | record = &keyspan_usa49wlc_firmware[0]; | 1408 | fw_name = "keyspan/usa49wlc.fw"; |
1418 | fw_name = "USA49WLC"; | ||
1419 | break; | 1409 | break; |
1420 | 1410 | ||
1421 | default: | 1411 | default: |
1422 | record = NULL; | 1412 | dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n", |
1423 | fw_name = "Unknown"; | 1413 | le16_to_cpu(serial->dev->descriptor.idProduct)); |
1424 | break; | 1414 | return 1; |
1425 | } | 1415 | } |
1426 | 1416 | ||
1427 | if (record == NULL) { | 1417 | if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) { |
1428 | dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name); | 1418 | dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name); |
1429 | return(1); | 1419 | return(1); |
1430 | } | 1420 | } |
@@ -1434,19 +1424,22 @@ static int keyspan_fake_startup (struct usb_serial *serial) | |||
1434 | /* download the firmware image */ | 1424 | /* download the firmware image */ |
1435 | response = ezusb_set_reset(serial, 1); | 1425 | response = ezusb_set_reset(serial, 1); |
1436 | 1426 | ||
1437 | while(record->address != 0xffff) { | 1427 | record = (const struct ihex_binrec *)fw->data; |
1438 | response = ezusb_writememory(serial, record->address, | 1428 | |
1429 | while (record) { | ||
1430 | response = ezusb_writememory(serial, be32_to_cpu(record->addr), | ||
1439 | (unsigned char *)record->data, | 1431 | (unsigned char *)record->data, |
1440 | record->data_size, 0xa0); | 1432 | be16_to_cpu(record->len), 0xa0); |
1441 | if (response < 0) { | 1433 | if (response < 0) { |
1442 | dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan" | 1434 | dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan" |
1443 | "firmware (%d %04X %p %d)\n", | 1435 | "firmware (%d %04X %p %d)\n", |
1444 | response, | 1436 | response, be32_to_cpu(record->addr), |
1445 | record->address, record->data, record->data_size); | 1437 | record->data, be16_to_cpu(record->len)); |
1446 | break; | 1438 | break; |
1447 | } | 1439 | } |
1448 | record++; | 1440 | record = ihex_next_binrec(record); |
1449 | } | 1441 | } |
1442 | release_firmware(fw); | ||
1450 | /* bring device out of reset. Renumeration will occur in a | 1443 | /* bring device out of reset. Renumeration will occur in a |
1451 | moment and the new device will bind to the real driver */ | 1444 | moment and the new device will bind to the real driver */ |
1452 | response = ezusb_set_reset(serial, 0); | 1445 | response = ezusb_set_reset(serial, 0); |
@@ -2756,6 +2749,19 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); | |||
2756 | MODULE_DESCRIPTION( DRIVER_DESC ); | 2749 | MODULE_DESCRIPTION( DRIVER_DESC ); |
2757 | MODULE_LICENSE("GPL"); | 2750 | MODULE_LICENSE("GPL"); |
2758 | 2751 | ||
2752 | MODULE_FIRMWARE("keyspan/usa28.fw"); | ||
2753 | MODULE_FIRMWARE("keyspan/usa28x.fw"); | ||
2754 | MODULE_FIRMWARE("keyspan/usa28xa.fw"); | ||
2755 | MODULE_FIRMWARE("keyspan/usa28xb.fw"); | ||
2756 | MODULE_FIRMWARE("keyspan/usa19.fw"); | ||
2757 | MODULE_FIRMWARE("keyspan/usa19qi.fw"); | ||
2758 | MODULE_FIRMWARE("keyspan/mpr.fw"); | ||
2759 | MODULE_FIRMWARE("keyspan/usa19qw.fw"); | ||
2760 | MODULE_FIRMWARE("keyspan/usa18x.fw"); | ||
2761 | MODULE_FIRMWARE("keyspan/usa19w.fw"); | ||
2762 | MODULE_FIRMWARE("keyspan/usa49w.fw"); | ||
2763 | MODULE_FIRMWARE("keyspan/usa49wlc.fw"); | ||
2764 | |||
2759 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 2765 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
2760 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 2766 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
2761 | 2767 | ||