edgeport: use request_firmware()

Version number provided in first HEX record.

Signed-off-by: Jaswinder Singh <jaswinder@infradead.org>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 06b52f4..2fd449b 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -42,6 +42,8 @@
 #include <linux/serial.h>
 #include <linux/ioctl.h>
 #include <linux/wait.h>
+#include <linux/firmware.h>
+#include <linux/ihex.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
@@ -56,26 +58,6 @@
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
-/* First, the latest boot code - for first generation edgeports */
-#define IMAGE_ARRAY_NAME	BootCodeImage_GEN1
-#define IMAGE_VERSION_NAME	BootCodeImageVersion_GEN1
-#include "io_fw_boot.h"		/* the bootloader firmware to download to a device, if it needs it */
-
-/* for second generation edgeports */
-#define IMAGE_ARRAY_NAME	BootCodeImage_GEN2
-#define IMAGE_VERSION_NAME	BootCodeImageVersion_GEN2
-#include "io_fw_boot2.h"	/* the bootloader firmware to download to a device, if it needs it */
-
-/* Then finally the main run-time operational code - for first generation edgeports */
-#define IMAGE_ARRAY_NAME	OperationalCodeImage_GEN1
-#define IMAGE_VERSION_NAME	OperationalCodeImageVersion_GEN1
-#include "io_fw_down.h"		/* Define array OperationalCodeImage[] */
-
-/* for second generation edgeports */
-#define IMAGE_ARRAY_NAME	OperationalCodeImage_GEN2
-#define IMAGE_VERSION_NAME	OperationalCodeImageVersion_GEN2
-#include "io_fw_down2.h"	/* Define array OperationalCodeImage[] */
-
 #define MAX_NAME_LEN		64
 
 #define CHASE_TIMEOUT		(5*HZ)		/* 5 seconds */
@@ -256,9 +238,9 @@
 static int  write_cmd_usb		(struct edgeport_port *edge_port, unsigned char *buffer, int writeLength);
 static void send_more_port_data		(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port);
 
-static int  sram_write			(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);
+static int  sram_write			(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data);
 static int  rom_read			(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);
-static int  rom_write			(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);
+static int  rom_write			(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data);
 static void get_manufacturing_desc	(struct edgeport_serial *edge_serial);
 static void get_boot_desc		(struct edgeport_serial *edge_serial);
 static void load_application_firmware	(struct edgeport_serial *edge_serial);
@@ -283,37 +265,41 @@
 {
 	__u32 BootCurVer;
 	__u32 BootNewVer;
-	__u8 BootMajorVersion;                  
-	__u8 BootMinorVersion;                  
-	__le16 BootBuildNumber;
-	__u8 *BootImage;      
-	__u32 BootSize;
-	struct edge_firmware_image_record *record;
-	unsigned char *firmware;
+	__u8 BootMajorVersion;
+	__u8 BootMinorVersion;
+	__u16 BootBuildNumber;
+	__u32 Bootaddr;
+	const struct ihex_binrec *rec;
+	const struct firmware *fw;
+	const char *fw_name;
 	int response;
 
-
 	switch (edge_serial->product_info.iDownloadFile) {
 		case EDGE_DOWNLOAD_FILE_I930:
-			BootMajorVersion	= BootCodeImageVersion_GEN1.MajorVersion;
-			BootMinorVersion	= BootCodeImageVersion_GEN1.MinorVersion;
-			BootBuildNumber		= cpu_to_le16(BootCodeImageVersion_GEN1.BuildNumber);
-			BootImage		= &BootCodeImage_GEN1[0];
-			BootSize		= sizeof( BootCodeImage_GEN1 );
+			fw_name	= "edgeport/boot.fw";
 			break;
 
 		case EDGE_DOWNLOAD_FILE_80251:
-			BootMajorVersion	= BootCodeImageVersion_GEN2.MajorVersion;
-			BootMinorVersion	= BootCodeImageVersion_GEN2.MinorVersion;
-			BootBuildNumber		= cpu_to_le16(BootCodeImageVersion_GEN2.BuildNumber);
-			BootImage		= &BootCodeImage_GEN2[0];
-			BootSize		= sizeof( BootCodeImage_GEN2 );
+			fw_name	= "edgeport/boot2.fw";
 			break;
 
 		default:
 			return;
 	}
 
+	response = request_ihex_firmware(&fw, fw_name,
+					 &edge_serial->serial->dev->dev);
+	if (response) {
+		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+		       fw_name, response);
+		return;
+	}
+
+	rec = (const struct ihex_binrec *)fw->data;
+	BootMajorVersion = rec->data[0];
+	BootMinorVersion = rec->data[1];
+	BootBuildNumber = (rec->data[2] << 8) | rec->data[3];
+
 	// Check Boot Image Version
 	BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) +
 		     (edge_serial->boot_descriptor.MinorVersion << 16) +
@@ -321,7 +307,7 @@
 
 	BootNewVer = (BootMajorVersion << 24) +
 		     (BootMinorVersion << 16) +
-		      le16_to_cpu(BootBuildNumber);
+		      BootBuildNumber;
 
 	dbg("Current Boot Image version %d.%d.%d",
 	    edge_serial->boot_descriptor.MajorVersion,
@@ -334,30 +320,30 @@
 		    edge_serial->boot_descriptor.MajorVersion,
 		    edge_serial->boot_descriptor.MinorVersion,
 		    le16_to_cpu(edge_serial->boot_descriptor.BuildNumber),
-		    BootMajorVersion,
-		    BootMinorVersion,
-		    le16_to_cpu(BootBuildNumber));
-
+		    BootMajorVersion, BootMinorVersion, BootBuildNumber);
 
 		dbg("Downloading new Boot Image");
 
-		firmware = BootImage;
-
-		for (;;) {
-			record = (struct edge_firmware_image_record *)firmware;
-			response = rom_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]);
+		for (rec = ihex_next_binrec(rec); rec;
+		     rec = ihex_next_binrec(rec)) {
+			Bootaddr = be32_to_cpu(rec->addr);
+			response = rom_write(edge_serial->serial,
+					     Bootaddr >> 16,
+					     Bootaddr & 0xFFFF,
+					     be16_to_cpu(rec->len),
+					     &rec->data[0]);
 			if (response < 0) {
-				dev_err(&edge_serial->serial->dev->dev, "rom_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len));
-				break;
-			}
-			firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len);
-			if (firmware >= &BootImage[BootSize]) {
+				dev_err(&edge_serial->serial->dev->dev,
+					"rom_write failed (%x, %x, %d)\n",
+					Bootaddr >> 16, Bootaddr & 0xFFFF,
+					be16_to_cpu(rec->len));
 				break;
 			}
 		}
 	} else {
 		dbg("Boot Image -- already up to date");
 	}
+	release_firmware(fw);
 }
 
 
@@ -447,9 +433,6 @@
 	dbg("  BootMajorVersion      %d.%d.%d", product_info->BootMajorVersion,
 	    product_info->BootMinorVersion,
 	    le16_to_cpu(product_info->BootBuildNumber));
-	dbg("  FirmwareMajorVersion  %d.%d.%d", product_info->FirmwareMajorVersion,
-	    product_info->FirmwareMinorVersion,
-	    le16_to_cpu(product_info->FirmwareBuildNumber));
 	dbg("  ManufactureDescDate   %d/%d/%d", product_info->ManufactureDescDate[0],
 	    product_info->ManufactureDescDate[1],
 	    product_info->ManufactureDescDate[2]+1900);
@@ -480,14 +463,8 @@
 
 	// check if this is 2nd generation hardware
 	if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ION_DEVICE_ID_80251_NETCHIP) {
-		product_info->FirmwareMajorVersion	= OperationalCodeImageVersion_GEN2.MajorVersion;
-		product_info->FirmwareMinorVersion	= OperationalCodeImageVersion_GEN2.MinorVersion;
-		product_info->FirmwareBuildNumber	= cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber);
 		product_info->iDownloadFile		= EDGE_DOWNLOAD_FILE_80251;
 	} else {
-		product_info->FirmwareMajorVersion	= OperationalCodeImageVersion_GEN1.MajorVersion;
-		product_info->FirmwareMinorVersion	= OperationalCodeImageVersion_GEN1.MinorVersion;
-		product_info->FirmwareBuildNumber	= cpu_to_le16(OperationalCodeImageVersion_GEN1.BuildNumber);
 		product_info->iDownloadFile		= EDGE_DOWNLOAD_FILE_I930;
 	}
 
@@ -2130,7 +2107,7 @@
  *	If successful returns the number of bytes written, otherwise it returns
  *	a negative error number of the problem.
  ****************************************************************************/
-static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data)
+static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data)
 {
 	int result;
 	__u16 current_length;
@@ -2175,7 +2152,7 @@
  *	If successful returns the number of bytes written, otherwise it returns
  *	a negative error number of the problem.
  ****************************************************************************/
-static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data)
+static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data)
 {
 	int result;
 	__u16 current_length;
@@ -2761,32 +2738,23 @@
  ****************************************************************************/
 static void load_application_firmware (struct edgeport_serial *edge_serial)
 {
-	struct edge_firmware_image_record *record;
-	unsigned char *firmware;
-	unsigned char *FirmwareImage;
-	int ImageSize;
+	const struct ihex_binrec *rec;
+	const struct firmware *fw;
+	const char *fw_name;
+	const char *fw_info;
 	int response;
-
+	__u32 Operaddr;
+	__u16 build;
 
 	switch (edge_serial->product_info.iDownloadFile) {
 		case EDGE_DOWNLOAD_FILE_I930:
-			dbg("downloading firmware version (930) %d.%d.%d", 
-			    OperationalCodeImageVersion_GEN1.MajorVersion, 
-			    OperationalCodeImageVersion_GEN1.MinorVersion, 
-			    OperationalCodeImageVersion_GEN1.BuildNumber);
-			firmware = &OperationalCodeImage_GEN1[0];
-			FirmwareImage = &OperationalCodeImage_GEN1[0];
-			ImageSize = sizeof(OperationalCodeImage_GEN1);
+			fw_info = "downloading firmware version (930)";
+			fw_name	= "edgeport/down.fw";
 			break;
 
 		case EDGE_DOWNLOAD_FILE_80251:
-			dbg("downloading firmware version (80251) %d.%d.%d", 
-			    OperationalCodeImageVersion_GEN2.MajorVersion, 
-			    OperationalCodeImageVersion_GEN2.MinorVersion, 
-			    OperationalCodeImageVersion_GEN2.BuildNumber);
-			firmware = &OperationalCodeImage_GEN2[0];
-			FirmwareImage = &OperationalCodeImage_GEN2[0];
-			ImageSize = sizeof(OperationalCodeImage_GEN2);
+			fw_info = "downloading firmware version (80251)";
+			fw_name	= "edgeport/down2.fw";
 			break;
 
 		case EDGE_DOWNLOAD_FILE_NONE:
@@ -2797,16 +2765,36 @@
 			return;
 	}
 
+	response = request_ihex_firmware(&fw, fw_name,
+				    &edge_serial->serial->dev->dev);
+	if (response) {
+		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+		       fw_name, response);
+		return;
+	}
 
-	for (;;) {
-		record = (struct edge_firmware_image_record *)firmware;
-		response = sram_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]);
+	rec = (const struct ihex_binrec *)fw->data;
+	build = (rec->data[2] << 8) | rec->data[3];
+
+	dbg("%s %d.%d.%d", fw_info, rec->data[0], rec->data[1], build);
+
+	edge_serial->product_info.FirmwareMajorVersion = fw->data[0];
+	edge_serial->product_info.FirmwareMinorVersion = fw->data[1];
+	edge_serial->product_info.FirmwareBuildNumber = cpu_to_le16(build);
+
+	for (rec = ihex_next_binrec(rec); rec;
+	     rec = ihex_next_binrec(rec)) {
+		Operaddr = be32_to_cpu(rec->addr);
+		response = sram_write(edge_serial->serial,
+				     Operaddr >> 16,
+				     Operaddr & 0xFFFF,
+				     be16_to_cpu(rec->len),
+				     &rec->data[0]);
 		if (response < 0) {
-			dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len));
-			break;
-		}
-		firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len);
-		if (firmware >= &FirmwareImage[ImageSize]) {
+			dev_err(&edge_serial->serial->dev->dev,
+				"sram_write failed (%x, %x, %d)\n",
+				Operaddr >> 16, Operaddr & 0xFFFF,
+				be16_to_cpu(rec->len));
 			break;
 		}
 	}
@@ -2817,6 +2805,7 @@
 				    USB_REQUEST_ION_EXEC_DL_CODE, 
 				    0x40, 0x4000, 0x0001, NULL, 0, 3000);
 
+	release_firmware(fw);
 	return;
 }
 
@@ -2903,6 +2892,10 @@
 //		dbg("set_configuration 1");
 //		usb_set_configuration (dev, 1);
 	}
+	dbg("  FirmwareMajorVersion  %d.%d.%d",
+	    edge_serial->product_info.FirmwareMajorVersion,
+	    edge_serial->product_info.FirmwareMinorVersion,
+	    le16_to_cpu(edge_serial->product_info.FirmwareBuildNumber));
 
 	/* we set up the pointers to the endpoints in the edge_open function, 
 	 * as the structures aren't created yet. */
@@ -3115,6 +3108,10 @@
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("edgeport/boot.fw");
+MODULE_FIRMWARE("edgeport/boot2.fw");
+MODULE_FIRMWARE("edgeport/down.fw");
+MODULE_FIRMWARE("edgeport/down2.fw");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");