[U-Boot] [PATCH] usb: Add new command to regress USB devices

Rajat Srivastava rajat.srivastava at nxp.com
Wed Mar 9 12:22:26 CET 2016


This patch adds a new 'usb regress' command, that can be used to
regress test a USB device. It performs the following operations:

1. starts the USB device
2. performs read/write operations
3. stops the USB device
4. verifies the contents of read/write operations

Sample Output:
=> usb regress 81000000 82000000 32m
regressing USB..
starting USB...
USB0:   Register 200017f NbrPorts 2
Starting the controller
USB XHCI 1.00
scanning bus 0 for devices... 2 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
USB write: device 0 block # 0, count 65536 ... 65536 blocks write: OK
USB read: device 0 block # 0, count 65536 ... 65536 blocks read: OK
stopping USB..
verifying data on addresses 0x81000000 and 0x82000000
Total of 65536 word(s) were the same

Signed-off-by: Rajat Srivastava <rajat.srivastava at nxp.com>
Signed-off-by: Rajesh Bhagat <rajesh.bhagat at nxp.com>
---
 common/cmd_usb.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 173 insertions(+), 1 deletion(-)

diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index a540b42..25fdeab 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -20,6 +20,7 @@
 #include <asm/unaligned.h>
 #include <part.h>
 #include <usb.h>
+#include <mapmem.h>
 
 #ifdef CONFIG_USB_STORAGE
 static int usb_stor_curr_dev = -1; /* current device */
@@ -616,6 +617,167 @@ static int usb_device_info(void)
 }
 #endif
 
+static unsigned long calc_blockcount(char * const size)
+{
+	unsigned long value, multiplier;
+	int size_len = strlen(size);
+	char unit;
+
+	/* extract the unit of size passed */
+	unit = size[size_len - 1];
+	/* updating the source string to remove unit */
+	size[size_len - 1] = '\0';
+
+	value = simple_strtoul(size, NULL, 10);
+	if (value <= 0) {
+		printf("invalid size\n");
+		return 0;
+	}
+
+	if (unit == 'G' || unit == 'g') {
+		multiplier = 2 * 1024 * 1024;
+	} else if (unit == 'M' || unit == 'm') {
+		multiplier = 2 * 1024;
+	} else if (unit == 'K' || unit == 'k') {
+		multiplier = 2;
+	} else if (unit == 'B' || unit == 'b') {
+		if (value % 512 != 0) {
+			printf("size can only be multiples of 512 bytes\n");
+			return 0;
+		}
+		multiplier = 1;
+		value /= 512;
+	} else {
+		printf("syntax mismatch\n");
+		return 0;
+	}
+
+	return value * multiplier;
+}
+
+static int usb_read_write_verify(unsigned long w_addr, unsigned long r_addr,
+							unsigned long cnt)
+{
+	cmd_tbl_t *c;
+	char str[3][16];
+	char *ptr[4] = { "cmp", str[0], str[1], str[2] };
+
+	c = find_cmd("cmp");
+	if (!c) {
+		printf("compare command not found\n");
+		return -1;
+	}
+	printf("verifying data on addresses 0x%lx and 0x%lx\n", w_addr, r_addr);
+	sprintf(str[0], "%lx", w_addr);
+	sprintf(str[1], "%lx", r_addr);
+	sprintf(str[2], "%lx", cnt);
+	(c->cmd)(c, 0, 4, ptr);
+	return 0;
+}
+
+
+static int do_usb_regress(int argc, char * const argv[])
+{
+	unsigned long loopcount, iteration;
+	unsigned long w_addr, r_addr, cnt, n;
+	unsigned long blk = 0;
+	extern char usb_started;
+
+#ifdef CONFIG_USB_STORAGE
+	block_dev_desc_t *stor_dev;
+#endif
+
+	if (argc < 5 || argc > 6) {
+		printf("syntax mismatch\n");
+		return -1;
+	}
+
+	if (argc == 5)
+		loopcount = 1;
+	else
+		loopcount = simple_strtoul(argv[5], NULL, 10);
+
+	if (loopcount <= 0) {
+		printf("syntax mismatch\n");
+		return -1;
+	}
+
+	cnt = calc_blockcount(argv[4]);
+	if (cnt == 0)
+		return -1;
+
+	iteration = loopcount;
+	while (loopcount--) {
+		if (argc > 5)
+			printf("\niteration #%lu\n\n", iteration - loopcount);
+
+		/* start USB */
+		if (usb_started) {
+			printf("USB already started\n");
+		} else {
+			printf("starting USB...\n");
+			do_usb_start();
+		}
+		if (!usb_started) {
+			printf("USB did not start\n");
+			return -1;
+		}
+		if (usb_stor_curr_dev < 0) {
+			printf("no current device selected\nstopping USB...\n");
+			usb_stop();
+			return -1;
+		}
+
+#ifdef CONFIG_USB_STORAGE
+		/* write on USB from address (w_addr) of RAM */
+		w_addr = simple_strtoul(argv[2], NULL, 16);
+		printf("USB write: device %d block # %ld, count %ld ... ",
+		       usb_stor_curr_dev, blk, cnt);
+		stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
+		n = stor_dev->block_write(usb_stor_curr_dev, blk, cnt,
+							(ulong *)w_addr);
+		printf("%ld blocks write: %s\n", n, (n == cnt) ?
+		"OK" : "ERROR");
+		if (n != cnt) {
+			printf("aborting.. USB write failed\n");
+			usb_stop();
+			return -1;
+		}
+
+		/* read from USB and write on to address (r_addr) on RAM */
+		r_addr = simple_strtoul(argv[3], NULL, 16);
+		printf("USB read: device %d block # %ld, count %ld ... ",
+		       usb_stor_curr_dev, blk, cnt);
+		stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
+		n = stor_dev->block_read(usb_stor_curr_dev, blk, cnt,
+							(ulong *)r_addr);
+		printf("%ld blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+		if (n != cnt) {
+			printf("aborting.. USB read failed\n");
+			usb_stop();
+			return -1;
+		}
+#endif
+
+		/* stop USB */
+		printf("stopping USB..\n");
+		usb_stop();
+
+#ifdef CONFIG_USB_STORAGE
+		/*
+		 * verify the content written on USB and
+		 * content read from USB.
+		 */
+		if (usb_read_write_verify(w_addr, r_addr, cnt) == -1)
+			return -1;
+#endif
+		if (ctrlc())
+			return -1;
+	}
+
+	return 0;
+}
+
 /******************************************************************************
  * usb command intepreter
  */
@@ -656,6 +818,13 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		usb_stop();
 		return 0;
 	}
+	if (strncmp(argv[1], "regress", 6) == 0) {
+		if (do_usb_stop_keyboard(0) != 0)
+			return 1;
+		printf("regressing USB..\n");
+		do_usb_regress(argc, argv);
+		return 0;
+	}
 	if (!usb_started) {
 		printf("USB is stopped. Please issue 'usb start' first.\n");
 		return 1;
@@ -821,7 +990,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 }
 
 U_BOOT_CMD(
-	usb,	5,	1,	do_usb,
+	usb,	6,	1,	do_usb,
 	"USB sub-system",
 	"start - start (scan) USB controller\n"
 	"usb reset - reset (rescan) USB controller\n"
@@ -831,6 +1000,9 @@ U_BOOT_CMD(
 	"usb test [dev] [port] [mode] - set USB 2.0 test mode\n"
 	"    (specify port 0 to indicate the device's upstream port)\n"
 	"    Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n"
+	"usb regress waddr raddr size [iterations] - regress a USB device\n"
+	"    (starts, writes to waddr, reads from raddr, stops and verifies.\n"
+	"    `size' format 1B/1K/1M/1G)\n "
 #ifdef CONFIG_USB_STORAGE
 	"usb storage - show details of USB storage devices\n"
 	"usb dev [dev] - show or set current USB storage device\n"
-- 
1.9.1



More information about the U-Boot mailing list