diff mbox

[U-Boot] Add 64-bit data support for memory commands

Message ID 1393462999-24561-1-git-send-email-yorksun@freescale.com
State Accepted
Delegated to: Tom Rini
Headers show

Commit Message

York Sun Feb. 27, 2014, 1:03 a.m. UTC
Add 64-bit data for memory commands, such as md, mw, mm, cmp. The new
size ".q " is introduced.

For 64-bit architecture, 64-bit data is enabled by default, by detecting
compiler __LP64__. It is optional for other architectures.

Signed-off-by: York Sun <yorksun@freescale.com>
---
Please comment if using __LP64__ is the right way to detect 64-bit systems.

 README                |    3 +
 common/cmd_mem.c      |  157 +++++++++++++++++++++++++++++++++++++++++++++----
 common/command.c      |    4 ++
 include/common.h      |    4 ++
 lib/display_options.c |   17 +++++-
 5 files changed, 174 insertions(+), 11 deletions(-)

Comments

Tom Rini March 4, 2014, 7:13 p.m. UTC | #1
On Wed, Feb 26, 2014 at 05:03:19PM -0800, York Sun wrote:

> Add 64-bit data for memory commands, such as md, mw, mm, cmp. The new
> size ".q " is introduced.
> 
> For 64-bit architecture, 64-bit data is enabled by default, by detecting
> compiler __LP64__. It is optional for other architectures.
> 
> Signed-off-by: York Sun <yorksun@freescale.com>

Applied to u-boot/master, thanks!  Please note this introduces warnings
on mips64 boards because we can now better support 64bitness.  Or we
need to discuss things more but, lets get that started.  Thanks!
diff mbox

Patch

diff --git a/README b/README
index f51f17e..9cc265b 100644
--- a/README
+++ b/README
@@ -3470,6 +3470,9 @@  typically in board_init_f() and board_init_r().
 Configuration Settings:
 -----------------------
 
+- CONFIG_SYS_SUPPORT_64BIT_DATA: Defined automatically if compiled as 64-bit.
+		Optionally it can be defined to support 64-bit memory commands.
+
 - CONFIG_SYS_LONGHELP: Defined when you want long help messages included;
 		undefine this when you're short of memory.
 
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index 6d75d02..5b03c2d 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -41,7 +41,7 @@  static	ulong	base_address = 0;
 /* Memory Display
  *
  * Syntax:
- *	md{.b, .w, .l} {addr} {len}
+ *	md{.b, .w, .l, .q} {addr} {len}
  */
 #define DISP_LINE_LEN	16
 static int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -155,7 +155,12 @@  static int do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	ulong	addr, writeval, count;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	u64 writeval;
+#else
+	ulong writeval;
+#endif
+	ulong	addr, count;
 	int	size;
 	void *buf;
 	ulong bytes;
@@ -175,7 +180,11 @@  static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	/* Get the value to write.
 	*/
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	writeval = simple_strtoull(argv[2], NULL, 16);
+#else
 	writeval = simple_strtoul(argv[2], NULL, 16);
+#endif
 
 	/* Count ? */
 	if (argc == 4) {
@@ -189,6 +198,10 @@  static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	while (count-- > 0) {
 		if (size == 4)
 			*((u32 *)buf) = (u32)writeval;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+		else if (size == 8)
+			*((u64 *)buf) = (u64)writeval;
+#endif
 		else if (size == 2)
 			*((u16 *)buf) = (u16)writeval;
 		else
@@ -262,6 +275,11 @@  static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	int     rcode = 0;
 	const char *type;
 	const void *buf1, *buf2, *base;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	u64 word1, word2;
+#else
+	ulong word1, word2;
+#endif
 
 	if (argc != 4)
 		return CMD_RET_USAGE;
@@ -270,7 +288,9 @@  static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	*/
 	if ((size = cmd_get_data_size(argv[0], 4)) < 0)
 		return 1;
-	type = size == 4 ? "word" : size == 2 ? "halfword" : "byte";
+	type = size == 8 ? "double word" :
+	       size == 4 ? "word" :
+	       size == 2 ? "halfword" : "byte";
 
 	addr1 = simple_strtoul(argv[1], NULL, 16);
 	addr1 += base_address;
@@ -298,10 +318,14 @@  static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	base = buf1 = map_sysmem(addr1, bytes);
 	buf2 = map_sysmem(addr2, bytes);
 	for (ngood = 0; ngood < count; ++ngood) {
-		ulong word1, word2;
 		if (size == 4) {
 			word1 = *(u32 *)buf1;
 			word2 = *(u32 *)buf2;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+		} else if (size == 8) {
+			word1 = *(u64 *)buf1;
+			word2 = *(u64 *)buf2;
+#endif
 		} else if (size == 2) {
 			word1 = *(u16 *)buf1;
 			word2 = *(u16 *)buf2;
@@ -311,10 +335,15 @@  static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		}
 		if (word1 != word2) {
 			ulong offset = buf1 - base;
-
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+			printf("%s at 0x%p (%#0*llx) != %s at 0x%p (%#0*llx)\n",
+			       type, (void *)(addr1 + offset), size, word1,
+			       type, (void *)(addr2 + offset), size, word2);
+#else
 			printf("%s at 0x%08lx (%#0*lx) != %s at 0x%08lx (%#0*lx)\n",
 				type, (ulong)(addr1 + offset), size, word1,
 				type, (ulong)(addr2 + offset), size, word2);
+#endif
 			rcode = 1;
 			break;
 		}
@@ -434,6 +463,10 @@  static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	while (count-- > 0) {
 		if (size == 4)
 			*((u32 *)buf) = *((u32  *)src);
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+		else if (size == 8)
+			*((u64 *)buf) = *((u64 *)src);
+#endif
 		else if (size == 2)
 			*((u16 *)buf) = *((u16 *)src);
 		else
@@ -467,6 +500,9 @@  static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
 {
 	ulong	addr, length, i, bytes;
 	int	size;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	volatile u64 *llp;
+#endif
 	volatile u32 *longp;
 	volatile u16 *shortp;
 	volatile u8 *cp;
@@ -497,6 +533,13 @@  static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
 	 * If we have only one object, just run infinite loops.
 	 */
 	if (length == 1) {
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+		if (size == 8) {
+			llp = (u64 *)buf;
+			for (;;)
+				i = *llp;
+		}
+#endif
 		if (size == 4) {
 			longp = (u32 *)buf;
 			for (;;)
@@ -512,6 +555,16 @@  static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
 			i = *cp;
 	}
 
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	if (size == 8) {
+		for (;;) {
+			llp = (u64 *)buf;
+			i = length;
+			while (i-- > 0)
+				*llp++;
+		}
+	}
+#endif
 	if (size == 4) {
 		for (;;) {
 			longp = (u32 *)buf;
@@ -542,8 +595,14 @@  static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
 #ifdef CONFIG_LOOPW
 int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	ulong	addr, length, i, data, bytes;
+	ulong	addr, length, i, bytes;
 	int	size;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	volatile u64 *llp;
+	u64 data;
+#else
+	ulong	data;
+#endif
 	volatile u32 *longp;
 	volatile u16 *shortp;
 	volatile u8 *cp;
@@ -568,7 +627,11 @@  int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	length = simple_strtoul(argv[2], NULL, 16);
 
 	/* data to write */
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	data = simple_strtoull(argv[3], NULL, 16);
+#else
 	data = simple_strtoul(argv[3], NULL, 16);
+#endif
 
 	bytes = size * length;
 	buf = map_sysmem(addr, bytes);
@@ -577,11 +640,18 @@  int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	 * If we have only one object, just run infinite loops.
 	 */
 	if (length == 1) {
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+		if (size == 8) {
+			llp = (u64 *)buf;
+			for (;;)
+				*llp = data;
+		}
+#endif
 		if (size == 4) {
 			longp = (u32 *)buf;
 			for (;;)
 				*longp = data;
-					}
+		}
 		if (size == 2) {
 			shortp = (u16 *)buf;
 			for (;;)
@@ -592,6 +662,16 @@  int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 			*cp = data;
 	}
 
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	if (size == 8) {
+		for (;;) {
+			llp = (u64 *)buf;
+			i = length;
+			while (i-- > 0)
+				*llp++ = data;
+		}
+	}
+#endif
 	if (size == 4) {
 		for (;;) {
 			longp = (u32 *)buf;
@@ -998,13 +1078,18 @@  static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
 /* Modify memory.
  *
  * Syntax:
- *	mm{.b, .w, .l} {addr}
- *	nm{.b, .w, .l} {addr}
+ *	mm{.b, .w, .l, .q} {addr}
+ *	nm{.b, .w, .l, .q} {addr}
  */
 static int
 mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 {
-	ulong	addr, i;
+	ulong	addr;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	u64 i;
+#else
+	ulong i;
+#endif
 	int	nbytes, size;
 	void *ptr = NULL;
 
@@ -1055,6 +1140,10 @@  mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 		printf("%08lx:", addr);
 		if (size == 4)
 			printf(" %08x", *((u32 *)ptr));
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+		else if (size == 8)
+			printf(" %016llx", *((u64 *)ptr));
+#endif
 		else if (size == 2)
 			printf(" %04x", *((u16 *)ptr));
 		else
@@ -1079,7 +1168,11 @@  mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 #endif
 		else {
 			char *endp;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+			i = simple_strtoull(console_buffer, &endp, 16);
+#else
 			i = simple_strtoul(console_buffer, &endp, 16);
+#endif
 			nbytes = endp - console_buffer;
 			if (nbytes) {
 #ifdef CONFIG_BOOT_RETRY_TIME
@@ -1089,6 +1182,10 @@  mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 #endif
 				if (size == 4)
 					*((u32 *)ptr) = i;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+				else if (size == 8)
+					*((u64 *)ptr) = i;
+#endif
 				else if (size == 2)
 					*((u16 *)ptr) = i;
 				else
@@ -1136,39 +1233,63 @@  static int do_mem_crc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 U_BOOT_CMD(
 	md,	3,	1,	do_mem_md,
 	"memory display",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] address [# of objects]"
+#else
 	"[.b, .w, .l] address [# of objects]"
+#endif
 );
 
 
 U_BOOT_CMD(
 	mm,	2,	1,	do_mem_mm,
 	"memory modify (auto-incrementing address)",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] address"
+#else
 	"[.b, .w, .l] address"
+#endif
 );
 
 
 U_BOOT_CMD(
 	nm,	2,	1,	do_mem_nm,
 	"memory modify (constant address)",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] address"
+#else
 	"[.b, .w, .l] address"
+#endif
 );
 
 U_BOOT_CMD(
 	mw,	4,	1,	do_mem_mw,
 	"memory write (fill)",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] address value [count]"
+#else
 	"[.b, .w, .l] address value [count]"
+#endif
 );
 
 U_BOOT_CMD(
 	cp,	4,	1,	do_mem_cp,
 	"memory copy",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] source target count"
+#else
 	"[.b, .w, .l] source target count"
+#endif
 );
 
 U_BOOT_CMD(
 	cmp,	4,	1,	do_mem_cmp,
 	"memory compare",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] addr1 addr2 count"
+#else
 	"[.b, .w, .l] addr1 addr2 count"
+#endif
 );
 
 #ifdef CONFIG_CMD_CRC32
@@ -1220,14 +1341,22 @@  U_BOOT_CMD(
 U_BOOT_CMD(
 	loop,	3,	1,	do_mem_loop,
 	"infinite loop on address range",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] address number_of_objects"
+#else
 	"[.b, .w, .l] address number_of_objects"
+#endif
 );
 
 #ifdef CONFIG_LOOPW
 U_BOOT_CMD(
 	loopw,	4,	1,	do_mem_loopw,
 	"infinite write loop on address range",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] address number_of_objects data_to_write"
+#else
 	"[.b, .w, .l] address number_of_objects data_to_write"
+#endif
 );
 #endif /* CONFIG_LOOPW */
 
@@ -1243,13 +1372,21 @@  U_BOOT_CMD(
 U_BOOT_CMD(
 	mdc,	4,	1,	do_mem_mdc,
 	"memory display cyclic",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] address count delay(ms)"
+#else
 	"[.b, .w, .l] address count delay(ms)"
+#endif
 );
 
 U_BOOT_CMD(
 	mwc,	4,	1,	do_mem_mwc,
 	"memory write cyclic",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	"[.b, .w, .l, .q] address value delay(ms)"
+#else
 	"[.b, .w, .l] address value delay(ms)"
+#endif
 );
 #endif /* CONFIG_MX_CYCLIC */
 
diff --git a/common/command.c b/common/command.c
index 597ab4c..1e7a477 100644
--- a/common/command.c
+++ b/common/command.c
@@ -421,6 +421,10 @@  int cmd_get_data_size(char* arg, int default_size)
 			return 2;
 		case 'l':
 			return 4;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+		case 'q':
+			return 8;
+#endif
 		case 's':
 			return -2;
 		default:
diff --git a/include/common.h b/include/common.h
index 96a45a6..15f5834 100644
--- a/include/common.h
+++ b/include/common.h
@@ -96,6 +96,10 @@  typedef volatile unsigned char	vu_char;
 #include <flash.h>
 #include <image.h>
 
+#ifdef __LP64__
+#define CONFIG_SYS_SUPPORT_64BIT_DATA
+#endif
+
 #ifdef DEBUG
 #define _DEBUG	1
 #else
diff --git a/lib/display_options.c b/lib/display_options.c
index 4a972b0..4c0c886 100644
--- a/lib/display_options.c
+++ b/lib/display_options.c
@@ -87,11 +87,19 @@  int print_buffer(ulong addr, const void *data, uint width, uint count,
 {
 	/* linebuf as a union causes proper alignment */
 	union linebuf {
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+		uint64_t uq[MAX_LINE_LENGTH_BYTES/sizeof(uint64_t) + 1];
+#endif
 		uint32_t ui[MAX_LINE_LENGTH_BYTES/sizeof(uint32_t) + 1];
 		uint16_t us[MAX_LINE_LENGTH_BYTES/sizeof(uint16_t) + 1];
 		uint8_t  uc[MAX_LINE_LENGTH_BYTES/sizeof(uint8_t) + 1];
 	} lb;
 	int i;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+	uint64_t x;
+#else
+	uint32_t x;
+#endif
 
 	if (linelen*width > MAX_LINE_LENGTH_BYTES)
 		linelen = MAX_LINE_LENGTH_BYTES / width;
@@ -108,14 +116,21 @@  int print_buffer(ulong addr, const void *data, uint width, uint count,
 
 		/* Copy from memory into linebuf and print hex values */
 		for (i = 0; i < thislinelen; i++) {
-			uint32_t x;
 			if (width == 4)
 				x = lb.ui[i] = *(volatile uint32_t *)data;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+			else if (width == 8)
+				x = lb.uq[i] = *(volatile uint64_t *)data;
+#endif
 			else if (width == 2)
 				x = lb.us[i] = *(volatile uint16_t *)data;
 			else
 				x = lb.uc[i] = *(volatile uint8_t *)data;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+			printf(" %0*llx", width * 2, x);
+#else
 			printf(" %0*x", width * 2, x);
+#endif
 			data += width;
 		}