aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorChris Adams <cmadams@hiwaay.net>2009-01-11 14:48:53 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-12 19:37:01 -0500
commit05a3d9050ad7bb791b9ba306165ea98e6d9e9da2 (patch)
treee07816d365aa05914a92cb7eed05cb20462779e7 /drivers/usb
parentbf0672db79c18ce38d1783be982051a718a0bc22 (diff)
ti_usb_3410_5052: support alternate firmware
The TI USB serial driver supports specifying alternate vendor and product IDs (since the chips can and are used in devices under other vendor/product IDs). However, the alternate IDs were not loaded in the combined product table. This patch also adds support for loading alternate firmware for alternate vendor/product IDs. Signed-off-by: Chris Adams <cmadams@hiwaay.net> Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 01d0c70d60e9..1cdb1515253d 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -145,7 +145,7 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
145static int ti_write_byte(struct ti_device *tdev, unsigned long addr, 145static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
146 __u8 mask, __u8 byte); 146 __u8 mask, __u8 byte);
147 147
148static int ti_download_firmware(struct ti_device *tdev, int type); 148static int ti_download_firmware(struct ti_device *tdev);
149 149
150/* circular buffer */ 150/* circular buffer */
151static struct circ_buf *ti_buf_alloc(void); 151static struct circ_buf *ti_buf_alloc(void);
@@ -176,7 +176,7 @@ static unsigned int product_5052_count;
176/* the array dimension is the number of default entries plus */ 176/* the array dimension is the number of default entries plus */
177/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */ 177/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
178/* null entry */ 178/* null entry */
179static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = { 179static struct usb_device_id ti_id_table_3410[2+TI_EXTRA_VID_PID_COUNT+1] = {
180 { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, 180 { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
181 { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, 181 { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
182}; 182};
@@ -188,7 +188,7 @@ static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
188 { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, 188 { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
189}; 189};
190 190
191static struct usb_device_id ti_id_table_combined[] = { 191static struct usb_device_id ti_id_table_combined[6+2*TI_EXTRA_VID_PID_COUNT+1] = {
192 { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, 192 { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
193 { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, 193 { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
194 { USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) }, 194 { USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
@@ -304,21 +304,28 @@ MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
304 304
305static int __init ti_init(void) 305static int __init ti_init(void)
306{ 306{
307 int i, j; 307 int i, j, c;
308 int ret; 308 int ret;
309 309
310 /* insert extra vendor and product ids */ 310 /* insert extra vendor and product ids */
311 c = ARRAY_SIZE(ti_id_table_combined) - 2 * TI_EXTRA_VID_PID_COUNT - 1;
311 j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1; 312 j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
312 for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++) { 313 for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++, c++) {
313 ti_id_table_3410[j].idVendor = vendor_3410[i]; 314 ti_id_table_3410[j].idVendor = vendor_3410[i];
314 ti_id_table_3410[j].idProduct = product_3410[i]; 315 ti_id_table_3410[j].idProduct = product_3410[i];
315 ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE; 316 ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
317 ti_id_table_combined[c].idVendor = vendor_3410[i];
318 ti_id_table_combined[c].idProduct = product_3410[i];
319 ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
316 } 320 }
317 j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1; 321 j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
318 for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++) { 322 for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++, c++) {
319 ti_id_table_5052[j].idVendor = vendor_5052[i]; 323 ti_id_table_5052[j].idVendor = vendor_5052[i];
320 ti_id_table_5052[j].idProduct = product_5052[i]; 324 ti_id_table_5052[j].idProduct = product_5052[i];
321 ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE; 325 ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
326 ti_id_table_combined[c].idVendor = vendor_5052[i];
327 ti_id_table_combined[c].idProduct = product_5052[i];
328 ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
322 } 329 }
323 330
324 ret = usb_serial_register(&ti_1port_device); 331 ret = usb_serial_register(&ti_1port_device);
@@ -390,11 +397,7 @@ static int ti_startup(struct usb_serial *serial)
390 397
391 /* if we have only 1 configuration, download firmware */ 398 /* if we have only 1 configuration, download firmware */
392 if (dev->descriptor.bNumConfigurations == 1) { 399 if (dev->descriptor.bNumConfigurations == 1) {
393 if (tdev->td_is_3410) 400 if ((status = ti_download_firmware(tdev)) != 0)
394 status = ti_download_firmware(tdev, 3410);
395 else
396 status = ti_download_firmware(tdev, 5052);
397 if (status)
398 goto free_tdev; 401 goto free_tdev;
399 402
400 /* 3410 must be reset, 5052 resets itself */ 403 /* 3410 must be reset, 5052 resets itself */
@@ -1671,9 +1674,9 @@ static int ti_do_download(struct usb_device *dev, int pipe,
1671 return status; 1674 return status;
1672} 1675}
1673 1676
1674static int ti_download_firmware(struct ti_device *tdev, int type) 1677static int ti_download_firmware(struct ti_device *tdev)
1675{ 1678{
1676 int status = -ENOMEM; 1679 int status;
1677 int buffer_size; 1680 int buffer_size;
1678 __u8 *buffer; 1681 __u8 *buffer;
1679 struct usb_device *dev = tdev->td_serial->dev; 1682 struct usb_device *dev = tdev->td_serial->dev;
@@ -1681,9 +1684,18 @@ static int ti_download_firmware(struct ti_device *tdev, int type)
1681 tdev->td_serial->port[0]->bulk_out_endpointAddress); 1684 tdev->td_serial->port[0]->bulk_out_endpointAddress);
1682 const struct firmware *fw_p; 1685 const struct firmware *fw_p;
1683 char buf[32]; 1686 char buf[32];
1684 sprintf(buf, "ti_usb-%d.bin", type);
1685 1687
1686 if (request_firmware(&fw_p, buf, &dev->dev)) { 1688 /* try ID specific firmware first, then try generic firmware */
1689 sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor,
1690 dev->descriptor.idProduct);
1691 if ((status = request_firmware(&fw_p, buf, &dev->dev)) != 0) {
1692 if (tdev->td_is_3410)
1693 strcpy(buf, "ti_3410.fw");
1694 else
1695 strcpy(buf, "ti_5052.fw");
1696 status = request_firmware(&fw_p, buf, &dev->dev);
1697 }
1698 if (status) {
1687 dev_err(&dev->dev, "%s - firmware not found\n", __func__); 1699 dev_err(&dev->dev, "%s - firmware not found\n", __func__);
1688 return -ENOENT; 1700 return -ENOENT;
1689 } 1701 }
@@ -1699,6 +1711,8 @@ static int ti_download_firmware(struct ti_device *tdev, int type)
1699 memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size); 1711 memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
1700 status = ti_do_download(dev, pipe, buffer, fw_p->size); 1712 status = ti_do_download(dev, pipe, buffer, fw_p->size);
1701 kfree(buffer); 1713 kfree(buffer);
1714 } else {
1715 status = -ENOMEM;
1702 } 1716 }
1703 release_firmware(fw_p); 1717 release_firmware(fw_p);
1704 if (status) { 1718 if (status) {