Newer
Older
/*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* Memory Functions
*
* Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
*/
#include <common.h>
#ifdef CONFIG_HAS_DATAFLASH
#include <dataflash.h>
#endif
#include <mapmem.h>
#include <watchdog.h>
#include <linux/compiler.h>
DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_SYS_MEMTEST_SCRATCH
#define CONFIG_SYS_MEMTEST_SCRATCH 0
#endif
static int mod_mem(cmd_tbl_t *, int, int, int, char * const []);
/* Display values from last command.
* Memory modify remembered values are different from display memory.
*/
static ulong dp_last_addr, dp_last_size;
static ulong dp_last_length = 0x40;
static ulong mm_last_addr, mm_last_size;
static ulong base_address = 0;
/* Memory Display
*
* Syntax:
static int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
ulong addr, length;
#if defined(CONFIG_HAS_DATAFLASH)
ulong nbytes, linebytes;
#endif
int size;
int rc = 0;
/* We use the last specified parameters, unless new ones are
* entered.
*/
addr = dp_last_addr;
size = dp_last_size;
length = dp_last_length;
return CMD_RET_USAGE;
if ((flag & CMD_FLAG_REPEAT) == 0) {
/* New command specified. Check for a size specification.
* Defaults to long if no or incorrect specification.
*/
if ((size = cmd_get_data_size(argv[0], 4)) < 0)
return 1;
/* Address is specified since argc > 1
*/
addr = simple_strtoul(argv[1], NULL, 16);
addr += base_address;
/* If another parameter, it is the length to display.
* Length is the number of objects, not number of bytes.
*/
if (argc > 2)
length = simple_strtoul(argv[2], NULL, 16);
}
#if defined(CONFIG_HAS_DATAFLASH)
/* Print the lines.
*
* We buffer all read data, so we can make sure data is read only
* once, and all accesses are with the specified bus width.
*/
nbytes = length * size;
do {
char linebuf[DISP_LINE_LEN];
void* p;
linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
rc = read_dataflash(addr, (linebytes/size)*size, linebuf);
p = (rc == DATAFLASH_OK) ? linebuf : (void*)addr;
print_buffer(addr, p, size, linebytes/size, DISP_LINE_LEN/size);
addr += linebytes;
if (ctrlc()) {
rc = 1;
break;
}
} while (nbytes > 0);
#else
# if defined(CONFIG_BLACKFIN)
/* See if we're trying to display L1 inst */
if (addr_bfin_on_chip_mem(addr)) {
char linebuf[DISP_LINE_LEN];
ulong linebytes, nbytes = length * size;
do {
linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
memcpy(linebuf, (void *)addr, linebytes);
print_buffer(addr, linebuf, size, linebytes/size, DISP_LINE_LEN/size);
nbytes -= linebytes;
addr += linebytes;
if (ctrlc()) {
rc = 1;
break;
}
} while (nbytes > 0);
} else
# endif
{
ulong bytes = size * length;
const void *buf = map_sysmem(addr, bytes);
/* Print the lines. */
print_buffer(addr, buf, size, length, DISP_LINE_LEN / size);
addr += bytes;
unmap_sysmem(buf);
#endif
dp_last_addr = addr;
dp_last_length = length;
dp_last_size = size;
return (rc);
}
static int do_mem_mm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
return mod_mem (cmdtp, 1, flag, argc, argv);
}
static int do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
return mod_mem (cmdtp, 0, flag, argc, argv);
}
static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
u64 writeval;
#else
ulong writeval;
#endif
ulong addr, count;
int size;
if ((argc < 3) || (argc > 4))
return CMD_RET_USAGE;
if ((size = cmd_get_data_size(argv[0], 4)) < 1)
return 1;
/* Address is specified since argc > 1
*/
addr = simple_strtoul(argv[1], NULL, 16);
addr += base_address;
/* Get the value to write.
*/
#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
writeval = simple_strtoull(argv[2], NULL, 16);
#else
/* Count ? */
if (argc == 4) {
count = simple_strtoul(argv[3], NULL, 16);
} else {
count = 1;
}
start = map_sysmem(addr, bytes);
buf = start;
#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
else if (size == 8)
*((u64 *)buf) = (u64)writeval;
#endif
#ifdef CONFIG_MX_CYCLIC
static int do_mem_mdc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i;
ulong count;
return CMD_RET_USAGE;
count = simple_strtoul(argv[3], NULL, 10);
for (;;) {
do_mem_md (NULL, 0, 3, argv);
/* delay for <count> ms... */
for (i=0; i<count; i++)
udelay (1000);
/* check for ctrl-c to abort... */
if (ctrlc()) {
puts("Abort\n");
return 0;
}
}
return 0;
}
static int do_mem_mwc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i;
ulong count;
return CMD_RET_USAGE;
count = simple_strtoul(argv[3], NULL, 10);
for (;;) {
do_mem_mw (NULL, 0, 3, argv);
/* delay for <count> ms... */
for (i=0; i<count; i++)
udelay (1000);
/* check for ctrl-c to abort... */
if (ctrlc()) {
puts("Abort\n");
return 0;
}
}
return 0;
}
#endif /* CONFIG_MX_CYCLIC */
static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
ulong addr1, addr2, count, ngood, bytes;
int size;
const void *buf1, *buf2, *base;
#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
u64 word1, word2;
#else
ulong word1, word2;
#endif
return CMD_RET_USAGE;
if ((size = cmd_get_data_size(argv[0], 4)) < 0)
return 1;
type = size == 8 ? "double word" :
size == 4 ? "word" :
size == 2 ? "halfword" : "byte";
addr1 = simple_strtoul(argv[1], NULL, 16);
addr1 += base_address;
addr2 = simple_strtoul(argv[2], NULL, 16);
addr2 += base_address;
count = simple_strtoul(argv[3], NULL, 16);
#ifdef CONFIG_HAS_DATAFLASH
if (addr_dataflash(addr1) | addr_dataflash(addr2)){
puts ("Comparison with DataFlash space not supported.\n\r");
return 0;
}
#endif
#ifdef CONFIG_BLACKFIN
if (addr_bfin_on_chip_mem(addr1) || addr_bfin_on_chip_mem(addr2)) {
puts ("Comparison with L1 instruction memory not supported.\n\r");
return 0;
}
#endif
bytes = size * count;
base = buf1 = map_sysmem(addr1, bytes);
buf2 = map_sysmem(addr2, bytes);
for (ngood = 0; ngood < count; ++ngood) {
word1 = *(u32 *)buf1;
word2 = *(u32 *)buf2;
#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
} else if (size == 8) {
word1 = *(u64 *)buf1;
word2 = *(u64 *)buf2;
#endif
word1 = *(u16 *)buf1;
word2 = *(u16 *)buf2;
word1 = *(u8 *)buf1;
word2 = *(u8 *)buf2;
ulong offset = buf1 - base;
#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
printf("%s at 0x%p (%#0*"PRIx64") != %s at 0x%p (%#0*"
PRIx64 ")\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);
buf1 += size;
buf2 += size;
/* reset watchdog from time to time */
if ((ngood % (64 << 10)) == 0)
unmap_sysmem(buf1);
unmap_sysmem(buf2);
printf("Total of %ld %s(s) were the same\n", ngood, type);
static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
ulong addr, dest, count, bytes;
int size;
const void *src;
void *buf;
return CMD_RET_USAGE;
if ((size = cmd_get_data_size(argv[0], 4)) < 0)
return 1;
addr = simple_strtoul(argv[1], NULL, 16);
addr += base_address;
dest = simple_strtoul(argv[2], NULL, 16);
dest += base_address;
count = simple_strtoul(argv[3], NULL, 16);
if (count == 0) {
puts ("Zero length ???\n");
return 1;
}
#ifndef CONFIG_SYS_NO_FLASH
if ( (addr2info(dest) != NULL)
#ifdef CONFIG_HAS_DATAFLASH
if (rc != 0) {
flash_perror (rc);
return (1);
}
puts ("done\n");
return 0;
}
#endif
#ifdef CONFIG_HAS_DATAFLASH
/* Check if we are copying from RAM or Flash to DataFlash */
if (addr_dataflash(dest) && !addr_dataflash(addr)){
int rc;
puts ("Copy to DataFlash... ");
rc = write_dataflash (dest, addr, count*size);
if (rc != 1) {
dataflash_perror (rc);
return (1);
}
puts ("done\n");
return 0;
}
/* Check if we are copying from DataFlash to RAM */
if (addr_dataflash(addr) && !addr_dataflash(dest)
#ifndef CONFIG_SYS_NO_FLASH
&& (addr2info(dest) == NULL)
#endif
){
int rc;
rc = read_dataflash(addr, count * size, (char *) dest);
if (rc != 1) {
Loading
Loading full blame…