]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
USB: io_ti: Move download and boot mode code out of download_fw
authorPeter E. Berger <pberger@brimson.com>
Wed, 16 Sep 2015 08:13:00 +0000 (03:13 -0500)
committerJohan Hovold <johan@kernel.org>
Fri, 9 Oct 2015 10:05:22 +0000 (12:05 +0200)
Separate the download and boot mode code from download_fw() into two new
helper functions: do_download_mode() and do_boot_mode().

Signed-off-by: Peter E. Berger <pberger@brimson.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
drivers/usb/serial/io_ti.c

index d41ba747220d8cdcce5759ee3b6e26d1244dd334..b371a0a961bef40216323d625f04c44beb206d19 100644 (file)
@@ -223,6 +223,11 @@ static void edge_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios);
 static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
 
+static int do_download_mode(struct edgeport_serial *serial,
+               const struct firmware *fw);
+static int do_boot_mode(struct edgeport_serial *serial,
+               const struct firmware *fw);
+
 /* sysfs attributes */
 static int edge_create_sysfs_attrs(struct usb_serial_port *port);
 static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
@@ -991,11 +996,7 @@ static int download_fw(struct edgeport_serial *serial,
 {
        struct device *dev = &serial->serial->interface->dev;
        int status = 0;
-       int start_address;
-       struct edge_ti_manuf_descriptor *ti_manuf_desc;
        struct usb_interface_descriptor *interface;
-       int download_cur_ver;
-       int download_new_ver;
        struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
 
        if (check_fw_sanity(serial, fw))
@@ -1029,190 +1030,207 @@ static int download_fw(struct edgeport_serial *serial,
         * if we have more than one endpoint we are definitely in download
         * mode
         */
-       if (interface->bNumEndpoints > 1)
+       if (interface->bNumEndpoints > 1) {
                serial->product_info.TiMode = TI_MODE_DOWNLOAD;
-       else
-               /* Otherwise we will remain in configuring mode */
-               serial->product_info.TiMode = TI_MODE_CONFIGURING;
+               return do_download_mode(serial, fw);
+       }
 
-       /********************************************************************/
-       /* Download Mode */
-       /********************************************************************/
-       if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
-               struct ti_i2c_desc *rom_desc;
+       /* Otherwise we will remain in configuring mode */
+       serial->product_info.TiMode = TI_MODE_CONFIGURING;
+       return do_boot_mode(serial, fw);
 
-               dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
+}
 
-               status = check_i2c_image(serial);
-               if (status) {
-                       dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__);
-                       return status;
-               }
+static int do_download_mode(struct edgeport_serial *serial,
+               const struct firmware *fw)
+{
+       struct device *dev = &serial->serial->interface->dev;
+       int status = 0;
+       int start_address;
+       struct edge_ti_manuf_descriptor *ti_manuf_desc;
+       int download_cur_ver;
+       int download_new_ver;
+       struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+       struct ti_i2c_desc *rom_desc;
 
-               /* Validate Hardware version number
-                * Read Manufacturing Descriptor from TI Based Edgeport
-                */
-               ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
-               if (!ti_manuf_desc)
-                       return -ENOMEM;
+       dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
 
-               status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
-               if (status) {
-                       kfree(ti_manuf_desc);
-                       return status;
-               }
+       status = check_i2c_image(serial);
+       if (status) {
+               dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__);
+               return status;
+       }
 
-               /* Check version number of ION descriptor */
-               if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
-                       dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
-                               __func__, ti_cpu_rev(ti_manuf_desc));
-                       kfree(ti_manuf_desc);
-                       return -EINVAL;
-               }
+       /* Validate Hardware version number
+        * Read Manufacturing Descriptor from TI Based Edgeport
+        */
+       ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
+       if (!ti_manuf_desc)
+               return -ENOMEM;
 
-               rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
-               if (!rom_desc) {
+       status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
+       if (status) {
+               kfree(ti_manuf_desc);
+               return status;
+       }
+
+       /* Check version number of ION descriptor */
+       if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
+               dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
+                       __func__, ti_cpu_rev(ti_manuf_desc));
+               kfree(ti_manuf_desc);
+               return -EINVAL;
+       }
+
+       rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
+       if (!rom_desc) {
+               kfree(ti_manuf_desc);
+               return -ENOMEM;
+       }
+
+       /* Search for type 2 record (firmware record) */
+       start_address = get_descriptor_addr(serial,
+                       I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
+       if (start_address != 0) {
+               struct ti_i2c_firmware_rec *firmware_version;
+               u8 *record;
+
+               dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n",
+                               __func__);
+
+               firmware_version = kmalloc(sizeof(*firmware_version),
+                                                       GFP_KERNEL);
+               if (!firmware_version) {
+                       kfree(rom_desc);
                        kfree(ti_manuf_desc);
                        return -ENOMEM;
                }
 
-               /* Search for type 2 record (firmware record) */
-               start_address = get_descriptor_addr(serial,
-                               I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
-               if (start_address != 0) {
-                       struct ti_i2c_firmware_rec *firmware_version;
-                       u8 *record;
+               /* Validate version number
+                * Read the descriptor data
+                */
+               status = read_rom(serial, start_address +
+                               sizeof(struct ti_i2c_desc),
+                               sizeof(struct ti_i2c_firmware_rec),
+                               (__u8 *)firmware_version);
+               if (status) {
+                       kfree(firmware_version);
+                       kfree(rom_desc);
+                       kfree(ti_manuf_desc);
+                       return status;
+               }
 
-                       dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n", __func__);
+               /* Check version number of download with current
+                * version in I2c */
+               download_cur_ver = (firmware_version->Ver_Major << 8) +
+                                  (firmware_version->Ver_Minor);
+               download_new_ver = (fw_hdr->major_version << 8) +
+                                  (fw_hdr->minor_version);
+
+               dev_dbg(dev, "%s - >> FW Versions Device %d.%d  Driver %d.%d\n",
+                       __func__, firmware_version->Ver_Major,
+                       firmware_version->Ver_Minor,
+                       fw_hdr->major_version, fw_hdr->minor_version);
+
+               /* Check if we have an old version in the I2C and
+                * update if necessary */
+               if (download_cur_ver < download_new_ver) {
+                       dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
+                               __func__,
+                               firmware_version->Ver_Major,
+                               firmware_version->Ver_Minor,
+                               fw_hdr->major_version,
+                               fw_hdr->minor_version);
 
-                       firmware_version = kmalloc(sizeof(*firmware_version),
-                                                               GFP_KERNEL);
-                       if (!firmware_version) {
+                       record = kmalloc(1, GFP_KERNEL);
+                       if (!record) {
+                               kfree(firmware_version);
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
                                return -ENOMEM;
                        }
-
-                       /* Validate version number
-                        * Read the descriptor data
+                       /*
+                        * In order to update the I2C firmware we must
+                        * change the type 2 record to type 0xF2. This
+                        * will force the UMP to come up in Boot Mode.
+                        * Then while in boot mode, the driver will
+                        * download the latest firmware (padded to
+                        * 15.5k) into the UMP ram. Finally when the
+                        * device comes back up in download mode the
+                        * driver will cause the new firmware to be
+                        * copied from the UMP Ram to I2C and the
+                        * firmware will update the record type from
+                        * 0xf2 to 0x02.
                         */
-                       status = read_rom(serial, start_address +
-                                       sizeof(struct ti_i2c_desc),
-                                       sizeof(struct ti_i2c_firmware_rec),
-                                       (__u8 *)firmware_version);
+                       *record = I2C_DESC_TYPE_FIRMWARE_BLANK;
+
+                       /* Change the I2C Firmware record type to
+                        * 0xf2 to trigger an update */
+                       status = write_rom(serial, start_address,
+                                       sizeof(*record), record);
                        if (status) {
+                               kfree(record);
                                kfree(firmware_version);
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
                                return status;
                        }
 
-                       /* Check version number of download with current
-                          version in I2c */
-                       download_cur_ver = (firmware_version->Ver_Major << 8) +
-                                          (firmware_version->Ver_Minor);
-                       download_new_ver = (fw_hdr->major_version << 8) +
-                                          (fw_hdr->minor_version);
-
-                       dev_dbg(dev, "%s - >> FW Versions Device %d.%d  Driver %d.%d\n",
-                               __func__, firmware_version->Ver_Major,
-                               firmware_version->Ver_Minor,
-                               fw_hdr->major_version, fw_hdr->minor_version);
+                       /* verify the write -- must do this in order
+                        * for write to complete before we do the
+                        * hardware reset
+                        */
+                       status = read_rom(serial,
+                                               start_address,
+                                               sizeof(*record),
+                                               record);
+                       if (status) {
+                               kfree(record);
+                               kfree(firmware_version);
+                               kfree(rom_desc);
+                               kfree(ti_manuf_desc);
+                               return status;
+                       }
 
-                       /* Check if we have an old version in the I2C and
-                          update if necessary */
-                       if (download_cur_ver < download_new_ver) {
-                               dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
-                                       __func__,
-                                       firmware_version->Ver_Major,
-                                       firmware_version->Ver_Minor,
-                                       fw_hdr->major_version,
-                                       fw_hdr->minor_version);
-
-                               record = kmalloc(1, GFP_KERNEL);
-                               if (!record) {
-                                       kfree(firmware_version);
-                                       kfree(rom_desc);
-                                       kfree(ti_manuf_desc);
-                                       return -ENOMEM;
-                               }
-                               /* In order to update the I2C firmware we must
-                                * change the type 2 record to type 0xF2. This
-                                * will force the UMP to come up in Boot Mode.
-                                * Then while in boot mode, the driver will
-                                * download the latest firmware (padded to
-                                * 15.5k) into the UMP ram. Finally when the
-                                * device comes back up in download mode the
-                                * driver will cause the new firmware to be
-                                * copied from the UMP Ram to I2C and the
-                                * firmware will update the record type from
-                                * 0xf2 to 0x02.
-                                */
-                               *record = I2C_DESC_TYPE_FIRMWARE_BLANK;
-
-                               /* Change the I2C Firmware record type to
-                                  0xf2 to trigger an update */
-                               status = write_rom(serial, start_address,
-                                               sizeof(*record), record);
-                               if (status) {
-                                       kfree(record);
-                                       kfree(firmware_version);
-                                       kfree(rom_desc);
-                                       kfree(ti_manuf_desc);
-                                       return status;
-                               }
-
-                               /* verify the write -- must do this in order
-                                * for write to complete before we do the
-                                * hardware reset
-                                */
-                               status = read_rom(serial,
-                                                       start_address,
-                                                       sizeof(*record),
-                                                       record);
-                               if (status) {
-                                       kfree(record);
-                                       kfree(firmware_version);
-                                       kfree(rom_desc);
-                                       kfree(ti_manuf_desc);
-                                       return status;
-                               }
-
-                               if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
-                                       dev_err(dev, "%s - error resetting device\n", __func__);
-                                       kfree(record);
-                                       kfree(firmware_version);
-                                       kfree(rom_desc);
-                                       kfree(ti_manuf_desc);
-                                       return -ENODEV;
-                               }
-
-                               dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
-
-                               /* Reset UMP -- Back to BOOT MODE */
-                               status = ti_vsend_sync(serial->serial->dev,
-                                               UMPC_HARDWARE_RESET,
-                                               0, 0, NULL, 0,
-                                               TI_VSEND_TIMEOUT_DEFAULT);
-
-                               dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status);
-
-                               /* return an error on purpose. */
+                       if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
+                               dev_err(dev, "%s - error resetting device\n",
+                                               __func__);
                                kfree(record);
                                kfree(firmware_version);
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
                                return -ENODEV;
-                       } else {
-                               /* Same or newer fw version is already loaded */
-                               serial->fw_version = download_cur_ver;
                        }
+
+                       dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
+
+                       /* Reset UMP -- Back to BOOT MODE */
+                       status = ti_vsend_sync(serial->serial->dev,
+                                       UMPC_HARDWARE_RESET,
+                                       0, 0, NULL, 0,
+                                       TI_VSEND_TIMEOUT_DEFAULT);
+
+                       dev_dbg(dev, "%s - HARDWARE RESET return %d\n",
+                                       __func__, status);
+
+                       /* return an error on purpose. */
+                       kfree(record);
                        kfree(firmware_version);
+                       kfree(rom_desc);
+                       kfree(ti_manuf_desc);
+                       return -ENODEV;
                }
-               /* Search for type 0xF2 record (firmware blank record) */
-               else if ((start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
+               /* Same or newer fw version is already loaded */
+               serial->fw_version = download_cur_ver;
+               kfree(firmware_version);
+       }
+       /* Search for type 0xF2 record (firmware blank record) */
+       else {
+               start_address = get_descriptor_addr(serial,
+                               I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc);
+               if (start_address != 0) {
 #define HEADER_SIZE    (sizeof(struct ti_i2c_desc) + \
-                                       sizeof(struct ti_i2c_firmware_rec))
+                               sizeof(struct ti_i2c_firmware_rec))
                        __u8 *header;
                        __u8 *vheader;
 
@@ -1231,7 +1249,8 @@ static int download_fw(struct edgeport_serial *serial,
                                return -ENOMEM;
                        }
 
-                       dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n", __func__);
+                       dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n",
+                                       __func__);
 
                        /*
                         * In order to update the I2C firmware we must change
@@ -1254,7 +1273,7 @@ static int download_fw(struct edgeport_serial *serial,
                        }
 
                        /* Update I2C with type 0xf2 record with correct
-                          size and checksum */
+                        * size and checksum */
                        status = write_rom(serial,
                                                start_address,
                                                HEADER_SIZE,
@@ -1268,12 +1287,13 @@ static int download_fw(struct edgeport_serial *serial,
                        }
 
                        /* verify the write -- must do this in order for
-                          write to complete before we do the hardware reset */
+                        * write to complete before we do the hardware reset */
                        status = read_rom(serial, start_address,
                                                        HEADER_SIZE, vheader);
 
                        if (status) {
-                               dev_dbg(dev, "%s - can't read header back\n", __func__);
+                               dev_dbg(dev, "%s - can't read header back\n",
+                                               __func__);
                                kfree(vheader);
                                kfree(header);
                                kfree(rom_desc);
@@ -1281,7 +1301,8 @@ static int download_fw(struct edgeport_serial *serial,
                                return status;
                        }
                        if (memcmp(vheader, header, HEADER_SIZE)) {
-                               dev_dbg(dev, "%s - write download record failed\n", __func__);
+                               dev_dbg(dev, "%s - write download record failed\n",
+                                               __func__);
                                kfree(vheader);
                                kfree(header);
                                kfree(rom_desc);
@@ -1300,26 +1321,33 @@ static int download_fw(struct edgeport_serial *serial,
                                        0, 0, NULL, 0,
                                        TI_VSEND_TIMEOUT_FW_DOWNLOAD);
 
-                       dev_dbg(dev, "%s - Update complete 0x%x\n", __func__, status);
+                       dev_dbg(dev, "%s - Update complete 0x%x\n", __func__,
+                                       status);
                        if (status) {
                                dev_err(dev,
                                        "%s - UMPC_COPY_DNLD_TO_I2C failed\n",
-                                                               __func__);
+                                       __func__);
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
                                return status;
                        }
                }
-
-               // The device is running the download code
-               kfree(rom_desc);
-               kfree(ti_manuf_desc);
-               return 0;
        }
 
-       /********************************************************************/
-       /* Boot Mode */
-       /********************************************************************/
+       /* The device is running the download code */
+       kfree(rom_desc);
+       kfree(ti_manuf_desc);
+       return 0;
+}
+
+static int do_boot_mode(struct edgeport_serial *serial,
+               const struct firmware *fw)
+{
+       struct device *dev = &serial->serial->interface->dev;
+       int status = 0;
+       struct edge_ti_manuf_descriptor *ti_manuf_desc;
+       struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
        dev_dbg(dev, "%s - RUNNING IN BOOT MODE\n", __func__);
 
        /* Configure the TI device so we can use the BULK pipes for download */