Skip to content

Commit

Permalink
ti_usb_3410_5052: support alternate firmware
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Chris Adams authored and Linus Torvalds committed Jan 13, 2009
1 parent bf0672d commit 05a3d90
Showing 1 changed file with 29 additions and 15 deletions.
44 changes: 29 additions & 15 deletions drivers/usb/serial/ti_usb_3410_5052.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
__u8 mask, __u8 byte);

static int ti_download_firmware(struct ti_device *tdev, int type);
static int ti_download_firmware(struct ti_device *tdev);

/* circular buffer */
static struct circ_buf *ti_buf_alloc(void);
Expand Down Expand Up @@ -176,7 +176,7 @@ static unsigned int product_5052_count;
/* the array dimension is the number of default entries plus */
/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
/* null entry */
static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = {
static struct usb_device_id ti_id_table_3410[2+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
};
Expand All @@ -188,7 +188,7 @@ static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
};

static struct usb_device_id ti_id_table_combined[] = {
static struct usb_device_id ti_id_table_combined[6+2*TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
Expand Down Expand Up @@ -304,21 +304,28 @@ MODULE_DEVICE_TABLE(usb, ti_id_table_combined);

static int __init ti_init(void)
{
int i, j;
int i, j, c;
int ret;

/* insert extra vendor and product ids */
c = ARRAY_SIZE(ti_id_table_combined) - 2 * TI_EXTRA_VID_PID_COUNT - 1;
j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++) {
for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++, c++) {
ti_id_table_3410[j].idVendor = vendor_3410[i];
ti_id_table_3410[j].idProduct = product_3410[i];
ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
ti_id_table_combined[c].idVendor = vendor_3410[i];
ti_id_table_combined[c].idProduct = product_3410[i];
ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
}
j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++) {
for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++, c++) {
ti_id_table_5052[j].idVendor = vendor_5052[i];
ti_id_table_5052[j].idProduct = product_5052[i];
ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
ti_id_table_combined[c].idVendor = vendor_5052[i];
ti_id_table_combined[c].idProduct = product_5052[i];
ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
}

ret = usb_serial_register(&ti_1port_device);
Expand Down Expand Up @@ -390,11 +397,7 @@ static int ti_startup(struct usb_serial *serial)

/* if we have only 1 configuration, download firmware */
if (dev->descriptor.bNumConfigurations == 1) {
if (tdev->td_is_3410)
status = ti_download_firmware(tdev, 3410);
else
status = ti_download_firmware(tdev, 5052);
if (status)
if ((status = ti_download_firmware(tdev)) != 0)
goto free_tdev;

/* 3410 must be reset, 5052 resets itself */
Expand Down Expand Up @@ -1671,19 +1674,28 @@ static int ti_do_download(struct usb_device *dev, int pipe,
return status;
}

static int ti_download_firmware(struct ti_device *tdev, int type)
static int ti_download_firmware(struct ti_device *tdev)
{
int status = -ENOMEM;
int status;
int buffer_size;
__u8 *buffer;
struct usb_device *dev = tdev->td_serial->dev;
unsigned int pipe = usb_sndbulkpipe(dev,
tdev->td_serial->port[0]->bulk_out_endpointAddress);
const struct firmware *fw_p;
char buf[32];
sprintf(buf, "ti_usb-%d.bin", type);

if (request_firmware(&fw_p, buf, &dev->dev)) {
/* try ID specific firmware first, then try generic firmware */
sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor,
dev->descriptor.idProduct);
if ((status = request_firmware(&fw_p, buf, &dev->dev)) != 0) {
if (tdev->td_is_3410)
strcpy(buf, "ti_3410.fw");
else
strcpy(buf, "ti_5052.fw");
status = request_firmware(&fw_p, buf, &dev->dev);
}
if (status) {
dev_err(&dev->dev, "%s - firmware not found\n", __func__);
return -ENOENT;
}
Expand All @@ -1699,6 +1711,8 @@ static int ti_download_firmware(struct ti_device *tdev, int type)
memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
status = ti_do_download(dev, pipe, buffer, fw_p->size);
kfree(buffer);
} else {
status = -ENOMEM;
}
release_firmware(fw_p);
if (status) {
Expand Down

0 comments on commit 05a3d90

Please sign in to comment.