Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Chris Adams and committed by
Linus Torvalds
05a3d905 bf0672db

+29 -15
+29 -15
drivers/usb/serial/ti_usb_3410_5052.c
··· 145 145 static int ti_write_byte(struct ti_device *tdev, unsigned long addr, 146 146 __u8 mask, __u8 byte); 147 147 148 - static int ti_download_firmware(struct ti_device *tdev, int type); 148 + static int ti_download_firmware(struct ti_device *tdev); 149 149 150 150 /* circular buffer */ 151 151 static struct circ_buf *ti_buf_alloc(void); ··· 176 176 /* the array dimension is the number of default entries plus */ 177 177 /* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */ 178 178 /* null entry */ 179 - static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = { 179 + static struct usb_device_id ti_id_table_3410[2+TI_EXTRA_VID_PID_COUNT+1] = { 180 180 { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, 181 181 { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, 182 182 }; ··· 188 188 { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, 189 189 }; 190 190 191 - static struct usb_device_id ti_id_table_combined[] = { 191 + static struct usb_device_id ti_id_table_combined[6+2*TI_EXTRA_VID_PID_COUNT+1] = { 192 192 { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, 193 193 { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, 194 194 { USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) }, ··· 304 304 305 305 static int __init ti_init(void) 306 306 { 307 - int i, j; 307 + int i, j, c; 308 308 int ret; 309 309 310 310 /* insert extra vendor and product ids */ 311 + c = ARRAY_SIZE(ti_id_table_combined) - 2 * TI_EXTRA_VID_PID_COUNT - 1; 311 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 314 ti_id_table_3410[j].idVendor = vendor_3410[i]; 314 315 ti_id_table_3410[j].idProduct = product_3410[i]; 315 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 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 323 ti_id_table_5052[j].idVendor = vendor_5052[i]; 320 324 ti_id_table_5052[j].idProduct = product_5052[i]; 321 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 331 ret = usb_serial_register(&ti_1port_device); ··· 397 390 398 391 /* if we have only 1 configuration, download firmware */ 399 392 if (dev->descriptor.bNumConfigurations == 1) { 400 - if (tdev->td_is_3410) 401 - status = ti_download_firmware(tdev, 3410); 402 - else 403 - status = ti_download_firmware(tdev, 5052); 404 - if (status) 393 + if ((status = ti_download_firmware(tdev)) != 0) 405 394 goto free_tdev; 406 395 407 396 /* 3410 must be reset, 5052 resets itself */ ··· 1674 1671 return status; 1675 1672 } 1676 1673 1677 - static int ti_download_firmware(struct ti_device *tdev, int type) 1674 + static int ti_download_firmware(struct ti_device *tdev) 1678 1675 { 1679 - int status = -ENOMEM; 1676 + int status; 1680 1677 int buffer_size; 1681 1678 __u8 *buffer; 1682 1679 struct usb_device *dev = tdev->td_serial->dev; ··· 1684 1681 tdev->td_serial->port[0]->bulk_out_endpointAddress); 1685 1682 const struct firmware *fw_p; 1686 1683 char buf[32]; 1687 - sprintf(buf, "ti_usb-%d.bin", type); 1688 1684 1689 - if (request_firmware(&fw_p, buf, &dev->dev)) { 1685 + /* try ID specific firmware first, then try generic firmware */ 1686 + sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor, 1687 + dev->descriptor.idProduct); 1688 + if ((status = request_firmware(&fw_p, buf, &dev->dev)) != 0) { 1689 + if (tdev->td_is_3410) 1690 + strcpy(buf, "ti_3410.fw"); 1691 + else 1692 + strcpy(buf, "ti_5052.fw"); 1693 + status = request_firmware(&fw_p, buf, &dev->dev); 1694 + } 1695 + if (status) { 1690 1696 dev_err(&dev->dev, "%s - firmware not found\n", __func__); 1691 1697 return -ENOENT; 1692 1698 } ··· 1711 1699 memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size); 1712 1700 status = ti_do_download(dev, pipe, buffer, fw_p->size); 1713 1701 kfree(buffer); 1702 + } else { 1703 + status = -ENOMEM; 1714 1704 } 1715 1705 release_firmware(fw_p); 1716 1706 if (status) {