From ddde6b7cf8341a15ad46551dc611488e9a3f36e6 Mon Sep 17 00:00:00 2001
From: Bartlomiej Sieka <tur@semihalf.com>
Date: Tue, 22 Aug 2006 10:38:18 +0200
Subject: [PATCH] Add a fix for a buggy USB device on the FO300 board.

---
 CHANGELOG                 |  2 ++
 common/usb_storage.c      | 25 +++++++++++++++++++++++++
 include/configs/TQM5200.h |  2 +-
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG b/CHANGELOG
index 82be4e3d77..3c752d1599 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,8 @@
 Changes since U-Boot 1.1.4:
 ======================================================================
 
+* Add a fix for a buggy USB device on the FO300 board.
+
 * Add support for WTK FO300 board (TQM5200 based).
 
 * Fix TQM834x hang.
diff --git a/common/usb_storage.c b/common/usb_storage.c
index e64470cb91..69ecf18784 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -916,6 +916,28 @@ static int usb_read_10(ccb *srb,struct us_data *ss, unsigned long start, unsigne
 }
 
 
+#ifdef CONFIG_USB_BIN_FIXUP
+/*
+ * Some USB storage devices queried for SCSI identification data respond with
+ * binary strings, which if output to the console freeze the terminal. The
+ * workaround is to modify the vendor and product strings read from such
+ * device with proper values (as reported by 'usb info').
+ *
+ * Vendor and product length limits are taken from the definition of
+ * block_dev_desc_t in include/part.h.
+ */
+static void usb_bin_fixup(struct usb_device_descriptor descriptor,
+				unsigned char vendor[],
+				unsigned char product[]) {
+	const unsigned char max_vendor_len = 40;
+	const unsigned char max_product_len = 20;
+	if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
+		strncpy(vendor, "SMSC", max_vendor_len);
+		strncpy(product, "Flash Media Cntrller", max_product_len);
+	}
+}
+#endif /* CONFIG_USB_BIN_FIXUP */
+
 #define USB_MAX_READ_BLK 20
 
 unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, unsigned long *buffer)
@@ -1171,6 +1193,9 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
 	dev_desc->vendor[8] = 0;
 	dev_desc->product[16] = 0;
 	dev_desc->revision[4] = 0;
+#ifdef CONFIG_USB_BIN_FIXUP
+	usb_bin_fixup(dev->descriptor, dev_desc->vendor, dev_desc->product);
+#endif /* CONFIG_USB_BIN_FIXUP */
 	USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n",usb_stor_buf[2],usb_stor_buf[3]);
 	if(usb_test_unit_ready(pccb,ss)) {
 		printf("Device NOT ready\n   Request Sense returned %02X %02X %02X\n",pccb->sense_buf[2],pccb->sense_buf[12],pccb->sense_buf[13]);
diff --git a/include/configs/TQM5200.h b/include/configs/TQM5200.h
index f157d42fce..89ec1bf7a9 100644
--- a/include/configs/TQM5200.h
+++ b/include/configs/TQM5200.h
@@ -63,7 +63,7 @@
 #define CFG_DEVICE_NULLDEV		1	/* enable null device */
 #define CONFIG_SILENT_CONSOLE		1	/* enable silent startup */
 #define CONFIG_BOARD_EARLY_INIT_F	1	/* used to detect S1 switch position */
-
+#define CONFIG_USB_BIN_FIXUP		1	/* for a buggy USB device */
 #if 0
 #define FO300_SILENT_CONSOLE_WHEN_S1_CLOSED	1	/* silent console on PSC1 when S1 */
 							/* switch is closed */
-- 
2.39.5